xmpp.go
changeset 0 6dbd969c8f3a
equal deleted inserted replaced
-1:000000000000 0:6dbd969c8f3a
       
     1 // Copyright 2011 The Go Authors.  All rights reserved.
       
     2 // Use of this source code is governed by a BSD-style
       
     3 // license that can be found in the LICENSE file.
       
     4 
       
     5 // This package implements a simple XMPP client according to RFCs 3920
       
     6 // and 3921, plus the various XEPs at http://xmpp.org/protocols/.
       
     7 package xmpp
       
     8 
       
     9 import (
       
    10 	"bytes"
       
    11 	"fmt"
       
    12 	"io"
       
    13 	"os"
       
    14 	"xml"
       
    15 )
       
    16 
       
    17 const (
       
    18 	// Version of RFC 3920 that we implement.
       
    19 	Version = "1.0"
       
    20 	nsStreams = "urn:ietf:params:xml:ns:xmpp-streams"
       
    21 )
       
    22 
       
    23 // JID represents an entity that can communicate with other
       
    24 // entities. It looks like node@domain/resource. Node and resource are
       
    25 // sometimes optional.
       
    26 type JID struct {
       
    27 	Node *string
       
    28 	Domain string
       
    29 	Resource *string
       
    30 }
       
    31 var _ fmt.Stringer = &JID{}
       
    32 
       
    33 // XMPP's <stream:stream> XML element
       
    34 type Stream struct {
       
    35 	to string `xml:"attr"`
       
    36 	from string `xml:"attr"`
       
    37 	id string `xml:"attr"`
       
    38 	lang string `xml:"attr"`
       
    39 	version string `xml:"attr"`
       
    40 }
       
    41 var _ xml.Marshaler = &Stream{}
       
    42 
       
    43 type StreamError struct {
       
    44 	cond definedCondition
       
    45 	text errText
       
    46 }
       
    47 var _ xml.Marshaler = &StreamError{}
       
    48 
       
    49 type definedCondition struct {
       
    50 	// Must always be in namespace nsStreams
       
    51 	XMLName xml.Name
       
    52 }
       
    53 
       
    54 type errText struct {
       
    55 	XMLName xml.Name
       
    56 	Lang string
       
    57 	text string `xml:"chardata"`
       
    58 }
       
    59 var _ xml.Marshaler = &errText{}
       
    60 
       
    61 func (jid *JID) String() string {
       
    62 	result := jid.Domain
       
    63 	if jid.Node != nil {
       
    64 		result = *jid.Node + "@" + result
       
    65 	}
       
    66 	if jid.Resource != nil {
       
    67 		result = result + "/" + *jid.Resource
       
    68 	}
       
    69 	return result
       
    70 }
       
    71 
       
    72 func (s *Stream) MarshalXML() ([]byte, os.Error) {
       
    73 	buf := bytes.NewBuffer(nil)
       
    74 	buf.WriteString("<stream:stream")
       
    75 	writeField(buf, "to", s.to)
       
    76 	writeField(buf, "from", s.from)
       
    77 	writeField(buf, "id", s.id)
       
    78 	writeField(buf, "xml:lang", s.lang)
       
    79 	writeField(buf, "version", s.version)
       
    80 	buf.WriteString(">")
       
    81 	// We never write </stream:stream>
       
    82 	return buf.Bytes(), nil
       
    83 }
       
    84 
       
    85 func (s *StreamError) MarshalXML() ([]byte, os.Error) {
       
    86 	buf := bytes.NewBuffer(nil)
       
    87 	buf.WriteString("<stream:error>")
       
    88 	xml.Marshal(buf, s.cond)
       
    89 	xml.Marshal(buf, s.text)
       
    90 	buf.WriteString("</stream:error>")
       
    91 	return buf.Bytes(), nil
       
    92 }
       
    93 
       
    94 func (e *errText) MarshalXML() ([]byte, os.Error) {
       
    95 	buf := bytes.NewBuffer(nil)
       
    96 	buf.WriteString("<text")
       
    97 	writeField(buf, "xmlns", nsStreams)
       
    98 	writeField(buf, "xml:lang", e.Lang)
       
    99 	buf.WriteString(">")
       
   100 	xml.Escape(buf, []byte(e.text))
       
   101 	buf.WriteString("</text>")
       
   102 	return buf.Bytes(), nil
       
   103 }
       
   104 
       
   105 func writeField(w io.Writer, field, value string) {
       
   106 	if value != "" {
       
   107 		io.WriteString(w, " ")
       
   108 		io.WriteString(w, field)
       
   109 		io.WriteString(w, `="`)
       
   110 		xml.Escape(w, []byte(value))
       
   111 		io.WriteString(w, `"`)
       
   112 	}
       
   113 }