aboutsummaryrefslogtreecommitdiff
path: root/xmpp/gateway/gateway.go
diff options
context:
space:
mode:
Diffstat (limited to 'xmpp/gateway/gateway.go')
-rw-r--r--xmpp/gateway/gateway.go116
1 files changed, 116 insertions, 0 deletions
diff --git a/xmpp/gateway/gateway.go b/xmpp/gateway/gateway.go
index 534ee7e..9cd2102 100644
--- a/xmpp/gateway/gateway.go
+++ b/xmpp/gateway/gateway.go
@@ -1,8 +1,13 @@
package gateway
import (
+ "bytes"
+ "encoding/base64"
"encoding/xml"
"github.com/pkg/errors"
+ "fmt"
+ "io"
+ "sort"
"strings"
"sync"
@@ -37,6 +42,19 @@ var DirtySessions = false
// MessageOutgoingPermission allows to fake outgoing messages by foreign JIDs
var MessageOutgoingPermission = false
+// CapsType is a capability category
+type CapsType int
+const (
+ CapsAudio CapsType = iota
+)
+
+// ContactType is a disco JID category
+type ContactType int
+const (
+ ContactTransport CapsType = iota
+ ContactPM
+)
+
// SendMessage creates and sends a message stanza
func SendMessage(to string, from string, body string, id string, component *xmpp.Component, reply *Reply, isOutgoing bool) {
sendMessageWrapper(to, from, body, id, component, reply, "", isOutgoing)
@@ -225,6 +243,9 @@ var SPResource = args.NewString()
// SPImmed skips queueing
var SPImmed = args.NewBool(args.Default(true))
+// SPCaps is a XEP-0115 verification string
+var SPCaps = args.NewString()
+
func newPresence(bareJid string, to string, args ...args.V) stanza.Presence {
var presenceFrom string
if SPFrom.IsSet(args) {
@@ -280,6 +301,16 @@ func newPresence(bareJid string, to string, args ...args.V) stanza.Presence {
})
}
}
+ if SPCaps.IsSet(args) {
+ ver := SPCaps.Get(args)
+ if ver != "" {
+ presence.Extensions = append(presence.Extensions, extensions.CapsExtension{
+ Hash: "sha-1",
+ Node: "https://dev.narayana.im/narayana/telegabber/",
+ Ver: ver,
+ })
+ }
+ }
return presence
}
@@ -356,3 +387,88 @@ func SplitJID(from string) (string, string, bool) {
}
return fromJid.Bare(), fromJid.Resource, true
}
+
+func getDiscoFeatures(caps []CapsType) []string {
+ features := []string{
+ "http://jabber.org/protocol/caps",
+ "http://jabber.org/protocol/disco#info",
+ }
+ for typ := range features {
+ switch typ {
+ case CapsAudio:
+ features = append(
+ features,
+ "urn:xmpp:jingle-message:0",
+ "urn:xmpp:jingle:1",
+ "urn:xmpp:jingle:apps:dtls:0",
+ "urn:xmpp:jingle:apps:rtp:1",
+ "urn:xmpp:jingle:apps:rtp:audio",
+ "urn:xmpp:jingle:transports:ice-udp:1",
+ )
+ }
+ }
+ return features
+}
+
+// GetDiscoInfo generates a disco info IQ query response
+func GetDiscoInfo(typ ContactType, features []string) *stanza.DiscoInfo {
+ disco := stanza.DiscoInfo{}
+ if typ == ContactPM {
+ disco.AddIdentity("", "account", "registered")
+ } else {
+ disco.AddIdentity("Telegram Gateway", "gateway", "telegram")
+ }
+ disco.AddFeatures(features...)
+ return &disco
+}
+
+
+// GetCapsVer hashes a capabilities set into a verification string
+func GetCapsVer(caps []CapsType) (string, error) {
+ features := getDiscoFeatures(caps)
+ disco := GetDiscoInfo(features)
+ discoToCapsHash(disco)
+ buf := new(bytes.Buffer)
+ binval := base64.NewEncoder(base64.StdEncoding, buf)
+ _, err = io.Copy(binval, file)
+ binval.Close()
+ if err != nil {
+ return "", errors.Wrap(err, "Error calculating caps base64")
+ }
+ return buf.String(), nil
+}
+
+func iOctetComparator(a, b string) bool {
+ return a < b
+}
+
+func discoToCaps(disco *stanza.DiscoInfo) string {
+ var s strings.Builder
+ var identities, vars, capsForms []string
+
+ for _, identity := range disco.Identity {
+ identities = append(identities, fmt.Sprintf(
+ "%s/%s//%s",
+ identity.Category,
+ identity.Type,
+ identity.Name,
+ ))
+ }
+ sort.Slice(identities, iOctetComparator)
+ for _, identity := range identities {
+ s.WriteString(identity)
+ s.WriteString(">")
+ }
+
+ for _, feature := range disco.Features {
+ vars = append(vars, feature.Var)
+ }
+ sort.Slice(vars, iOctetComparator)
+ for _, var := range vars {
+ s.WriteString(var)
+ s.WriteString(">")
+ }
+
+ for disco
+ s.WriteString(
+}