Exemple #1
0
// StructToXML writes an XMLNode to a xml.Encoder as tokens.
func StructToXML(e *xml.Encoder, node *XMLNode, sorted bool) error {
	e.EncodeToken(xml.StartElement{Name: node.Name, Attr: node.Attr})

	if node.Text != "" {
		e.EncodeToken(xml.CharData([]byte(node.Text)))
	} else if sorted {
		sortedNames := []string{}
		for k := range node.Children {
			sortedNames = append(sortedNames, k)
		}
		sort.Strings(sortedNames)

		for _, k := range sortedNames {
			for _, v := range node.Children[k] {
				StructToXML(e, v, sorted)
			}
		}
	} else {
		for _, c := range node.Children {
			for _, v := range c {
				StructToXML(e, v, sorted)
			}
		}
	}

	e.EncodeToken(xml.EndElement{Name: node.Name})
	return e.Flush()
}
Exemple #2
0
// TransformXML parses the XML tree, traverses it and calls TransformFunc
// on each XML token, writing the output to the writer, resulting in a
// transformed XML tree
func TransformXML(decoder *xml.Decoder, encoder *xml.Encoder, fn TransformFunc) error {
	parentNodes := &NodeList{}
	for {
		token, err := decoder.Token()
		if err != nil {
			if err != io.EOF {
				return trace.Wrap(err)
			}
			break
		}
		for _, t := range fn(parentNodes, token) {
			if err := encoder.EncodeToken(t); err != nil {
				return err
			}
		}
		switch e := token.(type) {
		case xml.StartElement:
			parentNodes.Push(e)
		case xml.EndElement:
			parentNodes.Pop()
		}
	}
	encoder.Flush()
	return nil
}
// writeNewline is used to force conventional XML plist formatting when
// writing the file header.
func writeNewline(w io.Writer, e *xml.Encoder) error {
	// Flush before writing to the Writer ourselves.
	if err := e.Flush(); err != nil {
		return err
	}
	if _, err := fmt.Fprintln(w); err != nil {
		return err
	}
	return nil
}
Exemple #4
0
func (fc *FeatureContainer) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
	start = xml.StartElement{Name: xml.Name{Local: "stream:features"}}
	if err := e.EncodeToken(start); err != nil {
		return err
	}

	fs := make([]Feature, 0, len(fc.features))
	for _, v := range fc.features {
		fs = append(fs, v)
	}

	if err := e.Encode(fs); err != nil {
		return err
	}

	if err := e.EncodeToken(start.End()); err != nil {
		return err
	}

	return e.Flush()
}
Exemple #5
0
// MarshalXML is a custom XML marshaler for InstanceMetadata.
func (i InstanceMetadata) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
	tokens := []xml.Token{start}

	if i.parsed != nil {
		for key, value := range i.parsed {
			t := xml.StartElement{Name: xml.Name{"", key}}
			tokens = append(tokens, t, xml.CharData(value.(string)), xml.EndElement{t.Name})
		}
	}
	tokens = append(tokens, xml.EndElement{start.Name})

	for _, t := range tokens {
		err := e.EncodeToken(t)
		if err != nil {
			return err
		}
	}

	// flush to ensure tokens are written
	return e.Flush()
}
func (s *MetaData) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
	var attributes []xml.Attr = make([]xml.Attr, 0)
	if s.Class != "" {
		attributes = append(attributes, xml.Attr{
			Name: xml.Name{
				Local: "class",
			},
			Value: s.Class,
		})
	}
	start.Attr = attributes
	tokens := []xml.Token{start}

	for key, value := range s.Map {
		t := xml.StartElement{Name: xml.Name{"", key}}
		tokens = append(tokens, t, xml.CharData(value), xml.EndElement{t.Name})
	}

	tokens = append(tokens, xml.EndElement{
		Name: start.Name,
	})

	for _, t := range tokens {
		err := e.EncodeToken(t)
		if err != nil {
			return err
		}
	}

	// flush to ensure tokens are written
	err := e.Flush()
	if err != nil {
		return err
	}

	return nil
}
func xmppHandshake(xmlEncoder *xml.Encoder, xmlDecoder *xml.Decoder, domain, proxyName string) (string, error) {
	handshake := xml.StartElement{
		Name: xml.Name{"jabber:client", "stream:stream"},
		Attr: []xml.Attr{
			xml.Attr{xml.Name{Local: "to"}, domain},
			xml.Attr{xml.Name{Local: "xml:lang"}, "en"},
			xml.Attr{xml.Name{Local: "version"}, "1.0"},
			xml.Attr{xml.Name{Local: "xmlns:stream"}, "http://etherx.jabber.org/streams"},
		},
	}
	if err := xmlEncoder.EncodeToken(handshake); err != nil {
		return "", fmt.Errorf("Failed to write SASL handshake: %s", err)
	}
	if err := xmlEncoder.Flush(); err != nil {
		return "", fmt.Errorf("Failed to flush encoding stream: %s", err)
	}

	if startElement, err := readStartElement(xmlDecoder); err != nil {
		return "", err
	} else if startElement.Name.Space != "http://etherx.jabber.org/streams" ||
		startElement.Name.Local != "stream" {
		return "", fmt.Errorf("Read unexpected XMPP XML stanza: %s", startElement.Name.Local)
	}

	var features struct {
		XMLName xml.Name `xml:"http://etherx.jabber.org/streams features"`
		Bind    *struct {
			XMLName xml.Name `xml:"urn:ietf:params:xml:ns:xmpp-bind bind"`
		}
		Session *struct {
			XMLName xml.Name `xml:"urn:ietf:params:xml:ns:xmpp-session session"`
		}
	}
	if err := xmlDecoder.Decode(&features); err != nil {
		return "", fmt.Errorf("Read unexpected XMPP XML element: %s", err)
	} else if features.Bind == nil || features.Session == nil {
		return "", errors.New("XMPP bind or session missing from handshake")
	}

	var resource struct {
		XMLName xml.Name `xml:"jabber:client iq"`
		Type    string   `xml:"type,attr"`
		ID      string   `xml:"id,attr"`
		Bind    struct {
			XMLName  xml.Name `xml:"urn:ietf:params:xml:ns:xmpp-bind bind"`
			Resource struct {
				XMLName      xml.Name `xml:"resource"`
				ResourceName string   `xml:",chardata"`
			}
		}
	}
	resource.Type = "set"
	resource.ID = "0"
	resource.Bind.Resource.ResourceName = proxyName
	if err := xmlEncoder.Encode(&resource); err != nil {
		return "", fmt.Errorf("Failed to set resource during XMPP handshake: %s", err)
	}

	var jid struct {
		XMLName xml.Name `xml:"jabber:client iq"`
		Bind    *struct {
			XMLName xml.Name `xml:"urn:ietf:params:xml:ns:xmpp-bind bind"`
			JID     string   `xml:"jid"`
		}
	}
	if err := xmlDecoder.Decode(&jid); err != nil {
		return "", err
	} else if jid.Bind == nil || jid.Bind.JID == "" {
		return "", errors.New("Received unexpected XML element during XMPP handshake")
	}

	fullJID := jid.Bind.JID

	var session struct {
		XMLName xml.Name `xml:"jabber:client iq"`
		Type    string   `xml:"type,attr"`
		ID      string   `xml:"id,attr"`
		Session struct {
			XMLName xml.Name `xml:"urn:ietf:params:xml:ns:xmpp-session session"`
		}
	}
	session.Type = "set"
	session.ID = "1"
	if err := xmlEncoder.Encode(&session); err != nil {
		return "", fmt.Errorf("Failed to complete XMPP handshake: %s", err)
	}

	var done struct {
		XMLName xml.Name `xml:"jabber:client iq"`
		ID      string   `xml:"id,attr"`
	}
	if err := xmlDecoder.Decode(&done); err != nil {
		return "", err
	} else if done.ID != "1" {
		return "", errors.New("Received unexpected result at end of XMPP handshake")
	}

	return fullJID, nil
}
func saslHandshake(xmlEncoder *xml.Encoder, xmlDecoder *xml.Decoder, domain, user, accessToken string) error {
	handshake := xml.StartElement{
		Name: xml.Name{"jabber:client", "stream:stream"},
		Attr: []xml.Attr{
			xml.Attr{xml.Name{Local: "to"}, domain},
			xml.Attr{xml.Name{Local: "xml:lang"}, "en"},
			xml.Attr{xml.Name{Local: "version"}, "1.0"},
			xml.Attr{xml.Name{Local: "xmlns:stream"}, "http://etherx.jabber.org/streams"},
		},
	}
	if err := xmlEncoder.EncodeToken(handshake); err != nil {
		return fmt.Errorf("Failed to write SASL handshake: %s", err)
	}
	if err := xmlEncoder.Flush(); err != nil {
		return fmt.Errorf("Failed to flush encoding stream: %s", err)
	}

	if startElement, err := readStartElement(xmlDecoder); err != nil {
		return err
	} else if startElement.Name.Space != "http://etherx.jabber.org/streams" ||
		startElement.Name.Local != "stream" {
		return fmt.Errorf("Read unexpected SASL XML stanza: %s", startElement.Name.Local)
	}

	var features struct {
		XMLName    xml.Name `xml:"http://etherx.jabber.org/streams features"`
		Mechanisms *struct {
			XMLName xml.Name `xml:"urn:ietf:params:xml:ns:xmpp-sasl mechanisms"`
		}
	}
	if err := xmlDecoder.Decode(&features); err != nil {
		return fmt.Errorf("Read unexpected SASL XML element: %s", err)
	} else if features.Mechanisms == nil {
		return errors.New("SASL mechanisms missing from handshake")
	}

	credential := base64.StdEncoding.EncodeToString([]byte("\x00" + user + "\x00" + accessToken))

	var auth struct {
		XMLName    xml.Name `xml:"urn:ietf:params:xml:ns:xmpp-sasl auth"`
		Mechanism  string   `xml:"mechanism,attr"`
		Service    string   `xml:"auth:service,attr"`
		Allow      string   `xml:"auth:allow-generated-jid,attr"`
		FullBind   string   `xml:"auth:client-uses-full-bind-result,attr"`
		XMLNS      string   `xml:"xmlns:auth,attr"`
		Credential string   `xml:",chardata"`
	}
	auth.Mechanism = "X-OAUTH2"
	auth.Service = "chromiumsync"
	auth.Allow = "true"
	auth.FullBind = "true"
	auth.XMLNS = "http://www.google.com/talk/protocol/auth"
	auth.Credential = credential
	if err := xmlEncoder.Encode(auth); err != nil {
		return fmt.Errorf("Failed to write SASL credentials: %s", err)
	}

	var success struct {
		XMLName xml.Name `xml:"urn:ietf:params:xml:ns:xmpp-sasl success"`
	}
	if err := xmlDecoder.Decode(&success); err != nil {
		return fmt.Errorf("Failed to complete SASL handshake: %s", err)
	}

	return nil
}
Exemple #9
0
func spl1t(bunch net.Conn, errHandler func(error)) (ret chan []byte) {
	ret = make(chan []byte)
	go func() {
		d := xml.NewDecoder(bunch)
		d.Strict = false
		var (
			_t  xml.Token
			err error
			buf *bytes.Buffer
			e   *xml.Encoder
		)
		init := func() {
			buf = bytes.NewBuffer(nil)
			e = xml.NewEncoder(buf)
		}
		flush := func() {
			e.Flush()
			if buf.Len() > 0 {
				ret <- buf.Bytes()
			}
			init()
		}
		join := func(n xml.Name) (ret string) {
			if n.Space != "" {
				ret = n.Space + ":"
			}
			ret = ret + n.Local
			return
		}
		depth := 0
		init()
		for stop := false; !stop && err == nil; {
			bunch.SetDeadline(time.Now().Add(10 * time.Second))
			if _t, err = d.RawToken(); err == nil {
				switch t := _t.(type) {
				case xml.ProcInst:
					e.EncodeToken(t.Copy())
				case xml.StartElement:
					tt := t.Copy()
					tt.Name = xml.Name{Local: join(t.Name)}
					var tmp []xml.Attr
					for _, a := range tt.Attr {
						a.Name = xml.Name{Local: join(a.Name)}
						tmp = append(tmp, a)
					}
					tt.Attr = tmp
					e.EncodeToken(tt)
					if tt.Name.Local == "stream:stream" {
						depth--
						flush()
					}
					depth++
				case xml.EndElement:
					tt := t
					tt.Name = xml.Name{Local: join(t.Name)}
					e.EncodeToken(tt)
					depth--
					if depth == 0 {
						flush()
					}
				case xml.CharData:
					e.EncodeToken(t)
				default:
					halt.As(100, reflect.TypeOf(t))
				}
			} else {
				flush()
				errHandler(err)
			}
			//log.Println("raw token read", err)
		}
		close(ret)
	}()
	return
}