Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Non-OTR MUC support #112

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions input.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ var uiCommands = []uiCommand{
{"help", helpCommand{}, "List known commands"},
{"ignore", ignoreCommand{}, "Ignore messages from another user"},
{"ignore-list", ignoreListCommand{}, "List currently ignored users"},
{"join", joinCommand{}, "Join a Multi-User-Chat"},
{"leave", leaveCommand{}, "Leave a Multi-User-Chat"},
{"nopaste", noPasteCommand{}, "Stop interpreting text verbatim"},
{"online", onlineCommand{}, "Set your status to Available / Online"},
{"otr-auth", authCommand{}, "Authenticate a secure peer with a mutual, shared secret"},
Expand Down Expand Up @@ -92,6 +94,14 @@ type ignoreCommand struct {

type ignoreListCommand struct{}

type joinCommand struct {
User string "uid"
}

type leaveCommand struct {
User string "uid"
}

type msgCommand struct {
to string
msg string
Expand Down
13 changes: 13 additions & 0 deletions ui.go
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,12 @@ MainLoop:
s.handleConfirmOrDeny(cmd.User, false /* deny */)
case addCommand:
s.conn.SendPresence(cmd.User, "subscribe", "" /* generate id */)
case joinCommand:
info(s.term, fmt.Sprintf("Warning: OTR is ***NOT SUPPORTED*** for Multi-User-Chats"))
s.conn.JoinMUC(cmd.User, "", "")
case leaveCommand:
s.conn.LeaveMUC(cmd.User)

case msgCommand:
conversation, ok := s.conversations[cmd.to]
isEncrypted := ok && conversation.IsEncrypted()
Expand Down Expand Up @@ -588,6 +594,7 @@ MainLoop:
} else {
msgs = [][]byte{[]byte(message)}
}

for _, message := range msgs {
s.conn.Send(cmd.to, string(message))
}
Expand Down Expand Up @@ -932,6 +939,12 @@ func (s *Session) processClientMessage(stanza *xmpp.ClientMessage) {
}
}

// MultiParty OTR does not exist yet unfortunately
// Thus do not note we are going to try it
if stanza.Type == "groupchat" {
detectedOTRVersion = 0
}

if s.config.OTRAutoStartSession && detectedOTRVersion >= 2 {
info(s.term, fmt.Sprintf("%s appears to support OTRv%d. We are attempting to start an OTR session with them.", from, detectedOTRVersion))
s.conn.Send(from, otr.QueryMessage)
Expand Down
47 changes: 45 additions & 2 deletions xmpp/xmpp.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ type Conn struct {
lock sync.Mutex
inflights map[Cookie]inflight
customStorage map[xml.Name]reflect.Type

// chatTypes maps from a JID (without the resource) to the
// type of conversation if it is not 'chat' (and thus 'groupchat')
chatTypes map[string]string
}

// inflight contains the details of a pending request to which we are awaiting
Expand Down Expand Up @@ -266,7 +270,14 @@ func (c *Conn) Send(to, msg string) error {
// http://xmpp.org/extensions/xep-0136.html#otr-nego
archive = "<nos:x xmlns:nos='google:nosave' value='enabled'/><arc:record xmlns:arc='http://jabber.org/protocol/archive' otr='require'/>"
}
_, err := fmt.Fprintf(c.out, "<message to='%s' from='%s' type='chat'><body>%s</body>%s</message>", xmlEscape(to), xmlEscape(c.jid), xmlEscape(msg), archive)

// Only non-'chat' types are listed
chattype, cok := c.chatTypes[to]
if !cok {
chattype = "chat"
}

_, err := fmt.Fprintf(c.out, "<message to='%s' from='%s' type='%s'><body>%s</body>%s</message>", xmlEscape(to), xmlEscape(c.jid), chattype, xmlEscape(msg), archive)
return err
}

Expand All @@ -285,6 +296,37 @@ func (c *Conn) SignalPresence(state string) error {
return err
}

/* XEP-0045 7.2 */
const nsMUC = "http://jabber.org/protocol/muc"

/* XEP-0045 7.2 & 7.2.6 */
func (c *Conn) JoinMUC(to, nick, password string) error {
if nick == "" {
nick = c.jid
}

pw := ""
if password != "" {
pw = "<password>" + xmlEscape(password) + "</password>\n"
}

_, err := fmt.Fprintf(c.out, "<presence to='%s/%s'>\n<x xmlns='http://jabber.org/protocol/muc'>\n%s</x>\n</presence>", xmlEscape(to), xmlEscape(nick), pw)

/* Register this as a groupchat */
c.chatTypes[to] = "groupchat"
return err
}

/* XEP-0045 7.14 */
func (c *Conn) LeaveMUC(to string) error {
_, err := fmt.Fprintf(c.out, "<presence from='%s' to='%s' type='unavailable' />", c.jid, xmlEscape(to))

/* Unregister as group chat */
delete(c.chatTypes, to)

return err
}

func (c *Conn) SendStanza(s interface{}) error {
return xml.NewEncoder(c.out).Encode(s)
}
Expand Down Expand Up @@ -383,7 +425,7 @@ func certName(cert *x509.Certificate) string {
func Resolve(domain string) (host string, port uint16, err error) {
_, addrs, err := net.LookupSRV("xmpp-client", "tcp", domain)
if err != nil {
return "", 0, err
return domain, 5222, nil
}
if len(addrs) == 0 {
return "", 0, errors.New("xmpp: no SRV records found for " + domain)
Expand Down Expand Up @@ -471,6 +513,7 @@ func printTLSDetails(w io.Writer, tlsState tls.ConnectionState) {
func Dial(address, user, domain, password string, config *Config) (c *Conn, err error) {
c = new(Conn)
c.inflights = make(map[Cookie]inflight)
c.chatTypes = make(map[string]string)
c.archive = config.Archive

log := ioutil.Discard
Expand Down