HTTPAuthentificationOverXMPP/xmpp/confirmation.go

143 lines
4.1 KiB
Go

package xmpp
import (
"git.kingpenguin.tk/chteufleur/go-xmpp.git/src/xmpp"
"log"
"strconv"
"strings"
"time"
)
const (
REPLY_UNREACHABLE = "reply_unreachable"
REPLY_DENY = "reply_deny"
REPLY_OK = "reply_ok"
REPLY_TIMEOUT = "reply_timeout"
TYPE_SEND_MESSAGE = "type_send_message"
TYPE_SEND_IQ = "type_send_iq"
TEMPLATE_DOMAIN = "_DOMAIN_"
TEMPLATE_METHOD = "_METHOD_"
TEMPLATE_VALIDATION_CODE = "_VALIDE_CODE_"
DEFAULT_MESSAGE = "_DOMAIN_ (with method _METHOD_) need to validate your identity, do you agree ?\nValidation code : _VALIDE_CODE_\nPlease check that this code is the same as on _DOMAIN_.\n\nIf your client doesn't support that functionnality, please send back the validation code to confirm the request."
)
var (
MapLangs = make(map[string]string)
TimeoutSec = 60 // 1 min
MaxTimeout = 300 // 5 min
)
type Confirmation struct {
JID string
Method string
Domain string
Transaction string
TypeSend string
IdMap string
ChanReply chan string
}
func Confirm(jid, method, domain, transaction string, timeout int) string {
// TODO check param validity
ret := ""
log.Printf("%sAuth %s", LogInfo, jid)
chanAnswer := make(chan string)
if timeout <= 0 {
timeout = TimeoutSec
}
if timeout > MaxTimeout {
timeout = MaxTimeout
}
confirmation := new(Confirmation)
confirmation.JID = jid
confirmation.Method = method
confirmation.Domain = domain
confirmation.Transaction = transaction
confirmation.ChanReply = chanAnswer
confirmation.SendConfirmation()
select {
case answer := <-chanAnswer:
ret = answer
case <-time.After(time.Duration(timeout) * time.Second):
ret = REPLY_TIMEOUT
}
switch confirmation.TypeSend {
case TYPE_SEND_IQ:
log.Printf("%sDelete IQ", LogDebug)
delete(WaitIqMessages, confirmation.IdMap)
case TYPE_SEND_MESSAGE:
log.Printf("%sDelete Message", LogDebug)
delete(WaitMessageAnswers, confirmation.IdMap)
}
return ret
}
func (confirmation *Confirmation) SendConfirmation() {
log.Printf("%sQuery JID %s", LogInfo, confirmation.JID)
clientJID, _ := xmpp.ParseJID(confirmation.JID)
if clientJID.Resource == "" {
confirmation.askViaMessage()
} else {
confirmation.askViaIQ()
}
}
func (confirmation *Confirmation) askViaIQ() {
stanzaID++
stanzaIDstr := strconv.Itoa(stanzaID)
m := xmpp.IQ{Type: xmpp.IQTypeGet, To: confirmation.JID, From: jid.Full(), ID: stanzaIDstr}
confirm := &xmpp.Confirm{ID: confirmation.Transaction, Method: confirmation.Method, URL: confirmation.Domain}
m.PayloadEncode(confirm)
WaitIqMessages[stanzaIDstr] = confirmation
comp.Out <- m
confirmation.TypeSend = TYPE_SEND_IQ
confirmation.IdMap = stanzaIDstr
}
func (confirmation *Confirmation) askViaMessage() {
m := xmpp.Message{From: jid.Full(), To: confirmation.JID, Type: xmpp.MessageTypeNormal}
m.Thread = xmpp.SessionID()
confirmation.setBodies(&m)
m.Confirm = &xmpp.Confirm{ID: confirmation.Transaction, Method: confirmation.Method, URL: confirmation.Domain}
log.Printf("%sSend message %v", LogInfo, m)
WaitMessageAnswers[confirmation.Transaction] = confirmation
comp.Out <- m
confirmation.TypeSend = TYPE_SEND_MESSAGE
confirmation.IdMap = confirmation.Transaction
}
func (confirmation *Confirmation) setBodies(message *xmpp.Message) {
msg := DEFAULT_MESSAGE
if len(MapLangs) == 0 {
msg = strings.Replace(msg, TEMPLATE_DOMAIN, confirmation.Domain, -1)
msg = strings.Replace(msg, TEMPLATE_METHOD, confirmation.Method, -1)
msg = strings.Replace(msg, TEMPLATE_VALIDATION_CODE, confirmation.Transaction, -1)
message.Body = append(message.Body, xmpp.MessageBody{Lang: "en", Value: msg})
} else {
for key, val := range MapLangs {
msg = val
msg = strings.Replace(msg, TEMPLATE_DOMAIN, confirmation.Domain, -1)
msg = strings.Replace(msg, TEMPLATE_METHOD, confirmation.Method, -1)
msg = strings.Replace(msg, TEMPLATE_VALIDATION_CODE, confirmation.Transaction, -1)
msg = strings.Replace(msg, "\\n", "\n", -1)
msg = strings.Replace(msg, "\\r", "\r", -1)
msg = strings.Replace(msg, "\\t", "\t", -1)
message.Body = append(message.Body, xmpp.MessageBody{Lang: key, Value: msg})
}
}
}