package main import ( "encoding/base64" "errors" "strings" "time" "github.com/ProtonMail/gopenpgp/v2/crypto" // MIT License "github.com/beevik/etree" // BSD-2-clause ) func oxNodeListRequest() (string, error) { nodeListRequest := etree.NewDocument() query := nodeListRequest.CreateElement("query") query.CreateAttr("xmlns", nsDiscoItems) nlr, err := nodeListRequest.WriteToString() if err != nil { return nlr, err } return nlr, nil } func oxNodeListReply(iqReply []byte) ([]string, error) { var nodes []string nodeListReply := etree.NewDocument() err := nodeListReply.ReadFromBytes(iqReply) if err != nil { return nodes, err } query := nodeListReply.SelectElement("query") if query == nil { return nodes, errors.New("error parsing iq reply") } items := query.SelectElements("item") if items == nil { return nodes, errors.New("error parsing iq reply") } for _, item := range items { node := item.SelectAttr("node") if node == nil { continue } if !strings.Contains(node.Value, nsOx) { continue } nodes = append(nodes, node.Value) } return nodes, nil } func oxDeleteNodeRequest(node string) (string, error) { deleteNodeRequest := etree.NewDocument() pubsub := deleteNodeRequest.CreateElement("pubsub") pubsub.CreateAttr("xmlns", nsPubsubOwner) delete := pubsub.CreateElement("delete") delete.CreateAttr("node", node) dnr, err := deleteNodeRequest.WriteToString() if err != nil { return dnr, err } return dnr, nil } func oxParseSignCrypt(message string) (oxSigncrypt, error) { var output oxSigncrypt doc := etree.NewDocument() err := doc.ReadFromString(message) if err != nil { return output, err } signcrypt := doc.SelectElement("signcrypt") if signcrypt == nil { return output, errors.New("ox: no signcrypt element") } to := signcrypt.SelectElement("to") if to == nil { return output, errors.New("ox: no to element") } jid := to.SelectAttr("jid") if jid == nil { return output, errors.New("ox: no jid attribute") } output.jid = jid.Value timestamp := signcrypt.SelectElement("time") if timestamp == nil { return output, errors.New("ox: no time element") } stamp := timestamp.SelectAttr("stamp") if stamp == nil { return output, errors.New("ox: no stamp attribute") } output.stamp = stamp.Value payload := signcrypt.SelectElement("payload") if payload == nil { return output, errors.New("ox: no payload element") } body := payload.SelectElement("body") if body == nil { return output, errors.New("ox: no body element") } output.body = body.Text() return output, nil } func oxPublishPubKeyRequest(pubKeyBase64 string, fingerprint string, keyCreated string) (string, error) { root := etree.NewDocument() pubsub := root.CreateElement("pubsub") pubsub.CreateAttr("xmlns", nsPubsub) publish := pubsub.CreateElement("publish") publish.CreateAttr("node", nsOxPubKeys+":"+fingerprint) item := publish.CreateElement("item") item.CreateAttr("id", keyCreated) pubkey := item.CreateElement("pubkey") pubkey.CreateAttr("xmlns", nsOx) data := pubkey.CreateElement("data") data.CreateText(pubKeyBase64) publishoptions := pubsub.CreateElement("publish-options") x := publishoptions.CreateElement("x") x.CreateAttr("xmlns", nsJabberData) x.CreateAttr("type", "submit") field := x.CreateElement("field") field.CreateAttr("var", "FORM_TYPE") field.CreateAttr("type", "hidden") value := field.CreateElement("value") value.CreateText(pubsubPubOptions) field = x.CreateElement("field") field.CreateAttr("var", "pubsub#access_model") value = field.CreateElement("value") value.CreateText("open") output, err := root.WriteToString() if err != nil { return output, err } return output, nil } func oxPublishPubKeyListRequest(fingerprint string, keyCreated string) (string, error) { root := etree.NewDocument() pubsub := root.CreateElement("pubsub") pubsub.CreateAttr("xmlns", nsPubsub) publish := pubsub.CreateElement("publish") publish.CreateAttr("node", nsOxPubKeys) item := publish.CreateElement("item") pubkeyslist := item.CreateElement("public-keys-list") pubkeyslist.CreateAttr("xmlns", nsOx) pubkeymeta := pubkeyslist.CreateElement("pubkey-metadata") pubkeymeta.CreateAttr("v4-fingerprint", fingerprint) pubkeymeta.CreateAttr("date", keyCreated) publishoptions := pubsub.CreateElement("publish-options") x := publishoptions.CreateElement("x") x.CreateAttr("xmlns", nsJabberData) x.CreateAttr("type", "submit") field := x.CreateElement("field") field.CreateAttr("var", "FORM_TYPE") field.CreateAttr("type", "hidden") value := field.CreateElement("value") value.CreateText(pubsubPubOptions) field = x.CreateElement("field") field.CreateAttr("var", "pubsub#access_model") value = field.CreateElement("value") value.CreateText("open") output, err := root.WriteToString() if err != nil { return output, err } return output, nil } func oxRecvPubKeysRequest(fingerprint string) (string, error) { opkr := etree.NewDocument() opkrPs := opkr.CreateElement("pubsub") opkrPs.CreateAttr("xmlns", nsPubsub) opkrPsItems := opkrPs.CreateElement("items") opkrPsItems.CreateAttr("node", nsOxPubKeys+":"+fingerprint) opkrPsItems.CreateAttr("max_items", "1") output, err := opkr.WriteToString() if err != nil { return output, err } return output, nil } func oxGetPubKeyRingRequest() (string, error) { oxPubKeyListReq := etree.NewDocument() oxPubKeyListReqPs := oxPubKeyListReq.CreateElement("pubsub") oxPubKeyListReqPs.CreateAttr("xmlns", nsPubsub) oxPubKeyListReqPsItems := oxPubKeyListReqPs.CreateElement("items") oxPubKeyListReqPsItems.CreateAttr("node", nsOxPubKeys) oxPubKeyListReqPsItems.CreateAttr("max_items", "1") output, err := oxPubKeyListReq.WriteToString() if err != nil { return output, err } return output, err } func oxCryptMessage(recipient string, message string) (string, error) { oxCryptMessage := etree.NewDocument() oxCryptMessageSc := oxCryptMessage.CreateElement("signcrypt") oxCryptMessageSc.CreateAttr("xmlns", nsOx) oxCryptMessageScTo := oxCryptMessageSc.CreateElement("to") oxCryptMessageScTo.CreateAttr("jid", recipient) oxCryptMessageScTime := oxCryptMessageSc.CreateElement("time") oxCryptMessageScTime.CreateAttr("stamp", time.Now().UTC().Format("2006-01-02T15:04:05Z")) oxCryptMessageScRpad := oxCryptMessageSc.CreateElement("rpad") oxCryptMessageScRpad.CreateText(getRpad(len(message))) oxCryptMessageScPayload := oxCryptMessageSc.CreateElement("payload") oxCryptMessageScPayloadBody := oxCryptMessageScPayload.CreateElement("body") oxCryptMessageScPayloadBody.CreateAttr("xmlns", nsJabberClient) oxCryptMessageScPayloadBody.CreateText(message) output, err := oxCryptMessage.WriteToString() if err != nil { return output, err } return output, nil } func oxMessage(recipient string, pgpMessage *crypto.PGPMessage) (string, error) { om := etree.NewDocument() omMessage := om.CreateElement("message") omMessage.CreateAttr("to", recipient) omMessage.CreateAttr("id", getID()) omMessageStore := omMessage.CreateElement("store") omMessageStore.CreateAttr("xmlns", nsHints) omMessageEme := omMessage.CreateElement("encryption") omMessageEme.CreateAttr("xmlns", nsEme) omMessageEme.CreateAttr("namespace", nsOx) omMessageOpgp := omMessage.CreateElement("openpgp") omMessageOpgp.CreateAttr("xmlns", nsOx) omMessageOpgp.CreateText(base64.StdEncoding.EncodeToString(pgpMessage.Data)) omMessageBody := omMessage.CreateElement("body") omMessageBody.CreateText(oxAltBody) output, err := om.WriteToString() if err != nil { return output, err } return output, nil }