diff --git a/example/example.go b/example/example.go index af2a17f..c5887c0 100644 --- a/example/example.go +++ b/example/example.go @@ -1,9 +1,9 @@ package main import ( + "bufio" "fmt" "flag" - "github.com/kless/go-readin/readin" "github.com/mattn/go-xmpp" "github.com/mattn/go-iconv" "log" @@ -61,11 +61,12 @@ func main() { } }() for { - line, err := readin.RepeatPrompt("") + in := bufio.NewReader(os.Stdin) + line, err := in.ReadString('\n') if err != nil { - fmt.Fprintln(os.Stderr, err.String()) continue } + line = strings.TrimRight(line, "\n") tokens := strings.SplitN(line, " ", 2) if len(tokens) == 2 { diff --git a/xmpp.go b/xmpp.go index 1127b2c..3a8db66 100644 --- a/xmpp.go +++ b/xmpp.go @@ -17,6 +17,7 @@ import ( "bytes" "crypto/tls" "encoding/base64" + "errors" "fmt" "http" "io" @@ -24,8 +25,8 @@ import ( "net" "os" "strings" - "xml" "url" + "xml" ) const ( @@ -47,7 +48,7 @@ type Client struct { // NewClient creates a new connection to a host given as "hostname" or "hostname:port". // If host is not specified, the DNS SRV should be used to find the host from the domainpart of the JID. // Default the port to 5222. -func NewClient(host, user, passwd string) (*Client, os.Error) { +func NewClient(host, user, passwd string) (*Client, error) { addr := host if strings.TrimSpace(host) == "" { @@ -87,7 +88,7 @@ func NewClient(host, user, passwd string) (*Client, os.Error) { } if resp.StatusCode != 200 { f := strings.SplitN(resp.Status, " ", 2) - return nil, os.NewError(f[1]) + return nil, errors.New(f[1]) } } @@ -112,18 +113,18 @@ func NewClient(host, user, passwd string) (*Client, os.Error) { return client, nil } -func (c *Client) Close() os.Error { +func (c *Client) Close() error { return c.tls.Close() } -func (c *Client) init(user, passwd string) os.Error { +func (c *Client) init(user, passwd string) error { // For debugging: the following causes the plaintext of the connection to be duplicated to stdout. // c.p = xml.NewParser(tee{c.tls, os.Stdout}); c.p = xml.NewParser(c.tls) a := strings.SplitN(user, "@", 2) if len(a) != 2 { - return os.NewError("xmpp: invalid username (want user@domain): " + user) + return errors.New("xmpp: invalid username (want user@domain): " + user) } user = a[0] domain := a[1] @@ -140,7 +141,7 @@ func (c *Client) init(user, passwd string) os.Error { return err } if se.Name.Space != nsStream || se.Name.Local != "stream" { - return os.NewError("xmpp: expected but got <" + se.Name.Local + "> in " + se.Name.Space) + return errors.New("xmpp: expected but got <" + se.Name.Local + "> in " + se.Name.Space) } // Now we're in the stream and can use Unmarshal. @@ -148,7 +149,7 @@ func (c *Client) init(user, passwd string) os.Error { // See section 4.6 in RFC 3920. var f streamFeatures if err = c.p.Unmarshal(&f, nil); err != nil { - return os.NewError("unmarshal : " + err.String()) + return errors.New("unmarshal : " + err.Error()) } havePlain := false for _, m := range f.Mechanisms.Mechanism { @@ -158,7 +159,7 @@ func (c *Client) init(user, passwd string) os.Error { } } if !havePlain { - return os.NewError(fmt.Sprintf("PLAIN authentication is not an option: %v", f.Mechanisms.Mechanism)) + return errors.New(fmt.Sprintf("PLAIN authentication is not an option: %v", f.Mechanisms.Mechanism)) } // Plain authentication: send base64-encoded \x00 user \x00 password. @@ -175,9 +176,9 @@ func (c *Client) init(user, passwd string) os.Error { case *saslFailure: // v.Any is type of sub-element in failure, // which gives a description of what failed. - return os.NewError("auth failure: " + v.Any.Local) + return errors.New("auth failure: " + v.Any.Local) default: - return os.NewError("expected or , got <" + name.Local + "> in " + name.Space) + return errors.New("expected or , got <" + name.Local + "> in " + name.Space) } // Now that we're authenticated, we're supposed to start the stream over again. @@ -192,7 +193,7 @@ func (c *Client) init(user, passwd string) os.Error { return err } if se.Name.Space != nsStream || se.Name.Local != "stream" { - return os.NewError("expected , got <" + se.Name.Local + "> in " + se.Name.Space) + return errors.New("expected , got <" + se.Name.Local + "> in " + se.Name.Space) } if err = c.p.Unmarshal(&f, nil); err != nil { // TODO: often stream stop. @@ -203,10 +204,10 @@ func (c *Client) init(user, passwd string) os.Error { fmt.Fprintf(c.tls, "\n", nsBind) var iq clientIQ if err = c.p.Unmarshal(&iq, nil); err != nil { - return os.NewError("unmarshal : " + err.String()) + return errors.New("unmarshal : " + err.Error()) } if &iq.Bind == nil { - return os.NewError(" result missing ") + return errors.New(" result missing ") } c.jid = iq.Bind.Jid // our local id @@ -222,7 +223,7 @@ type Chat struct { } // Recv wait next token of chat. -func (c *Client) Recv() (chat Chat, err os.Error) { +func (c *Client) Recv() (chat Chat, err error) { for { _, val, err := next(c.p) if err != nil { @@ -243,7 +244,6 @@ func (c *Client) Send(chat Chat) { xmlEscape(chat.Text)) } - // RFC 3920 C.1 Streams name space type streamFeatures struct { @@ -366,7 +366,7 @@ type clientError struct { } // Scan XML token stream to find next StartElement. -func nextStart(p *xml.Parser) (xml.StartElement, os.Error) { +func nextStart(p *xml.Parser) (xml.StartElement, error) { for { t, err := p.Token() if err != nil { @@ -383,7 +383,7 @@ func nextStart(p *xml.Parser) (xml.StartElement, os.Error) { // Scan XML token stream for next element and save into val. // If val == nil, allocate new element based on proto map. // Either way, return val. -func next(p *xml.Parser) (xml.Name, interface{}, os.Error) { +func next(p *xml.Parser) (xml.Name, interface{}, error) { // Read start element to find out what type we want. se, err := nextStart(p) if err != nil { @@ -392,25 +392,41 @@ func next(p *xml.Parser) (xml.Name, interface{}, os.Error) { // Put it in an interface and allocate one. var nv interface{} - switch (se.Name.Space+" "+se.Name.Local) { - case nsStream + " features": nv = &streamFeatures{} - case nsStream + " error": nv = &streamError{} - case nsTLS + " starttls": nv = &tlsStartTLS{} - case nsTLS + " proceed": nv = &tlsProceed{} - case nsTLS + " failure": nv = &tlsFailure{} - case nsSASL + " mechanisms": nv = &saslMechanisms{} - case nsSASL + " challenge": nv = "" - case nsSASL + " response": nv = "" - case nsSASL + " abort": nv = &saslAbort{} - case nsSASL + " success": nv = &saslSuccess{} - case nsSASL + " failure": nv = &saslFailure{} - case nsBind + " bind": nv = &bindBind{} - case nsClient + " message": nv = &clientMessage{} - case nsClient + " presence": nv = &clientPresence{} - case nsClient + " iq": nv = &clientIQ{} - case nsClient + " error": nv = &clientError{} + switch se.Name.Space + " " + se.Name.Local { + case nsStream + " features": + nv = &streamFeatures{} + case nsStream + " error": + nv = &streamError{} + case nsTLS + " starttls": + nv = &tlsStartTLS{} + case nsTLS + " proceed": + nv = &tlsProceed{} + case nsTLS + " failure": + nv = &tlsFailure{} + case nsSASL + " mechanisms": + nv = &saslMechanisms{} + case nsSASL + " challenge": + nv = "" + case nsSASL + " response": + nv = "" + case nsSASL + " abort": + nv = &saslAbort{} + case nsSASL + " success": + nv = &saslSuccess{} + case nsSASL + " failure": + nv = &saslFailure{} + case nsBind + " bind": + nv = &bindBind{} + case nsClient + " message": + nv = &clientMessage{} + case nsClient + " presence": + nv = &clientPresence{} + case nsClient + " iq": + nv = &clientIQ{} + case nsClient + " error": + nv = &clientError{} default: - return xml.Name{}, nil, os.NewError("unexpected XMPP message " + + return xml.Name{}, nil, errors.New("unexpected XMPP message " + se.Name.Space + " <" + se.Name.Local + "/>") } @@ -447,7 +463,7 @@ type tee struct { w io.Writer } -func (t tee) Read(p []byte) (n int, err os.Error) { +func (t tee) Read(p []byte) (n int, err error) { n, err = t.r.Read(p) if n > 0 { t.w.Write(p[0:n])