Compare commits
No commits in common. "oauth" and "master" have entirely different histories.
|
|
@ -9,7 +9,6 @@ Can be run as a XMPP client or XMPP component.
|
||||||
|
|
||||||
* [go-xmpp](https://git.kingpenguin.tk/chteufleur/go-xmpp) for the XMPP part.
|
* [go-xmpp](https://git.kingpenguin.tk/chteufleur/go-xmpp) for the XMPP part.
|
||||||
* [cfg](https://github.com/jimlawless/cfg) for the configuration file.
|
* [cfg](https://github.com/jimlawless/cfg) for the configuration file.
|
||||||
* [oauth2.v3](https://github.com/go-oauth2/oauth2) for OAuth2 support.
|
|
||||||
|
|
||||||
### Build and run
|
### Build and run
|
||||||
|
|
||||||
|
|
@ -53,9 +52,6 @@ If ``http_bind_address_ipv4`` is set to ``0.0.0.0``, it will bind all address on
|
||||||
The lang messages file must be placed into the same directory than the configuration file.
|
The lang messages file must be placed into the same directory than the configuration file.
|
||||||
An example of this file can be found in [the repos](https://git.kingpenguin.tk/chteufleur/HTTPAuthentificationOverXMPP/src/master/messages.lang)
|
An example of this file can be found in [the repos](https://git.kingpenguin.tk/chteufleur/HTTPAuthentificationOverXMPP/src/master/messages.lang)
|
||||||
|
|
||||||
### OAuth configuration
|
|
||||||
OAuth configuration is made by a file that can be found in [the repos](https://git.kingpenguin.tk/chteufleur/HTTPAuthentificationOverXMPP/src/oauth/clientStore.json) and must be place following [XDG specification](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html) (example ``/etc/xdg/http-auth/clientStore.json``).
|
|
||||||
|
|
||||||
### Usage
|
### Usage
|
||||||
To ask authorization, just send an HTTP request to the path ``/auth`` with parameters:
|
To ask authorization, just send an HTTP request to the path ``/auth`` with parameters:
|
||||||
* __jid__ : JID of the user (user@host/resource or user@host)
|
* __jid__ : JID of the user (user@host/resource or user@host)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
[
|
|
||||||
{
|
|
||||||
"ID": "key",
|
|
||||||
"Secret": "secret",
|
|
||||||
"Domain": "http://localhost:9094"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
56
http/http.go
56
http/http.go
|
|
@ -42,6 +42,8 @@ var (
|
||||||
KeyPath = "./key.pem"
|
KeyPath = "./key.pem"
|
||||||
|
|
||||||
ChanRequest = make(chan interface{}, 5)
|
ChanRequest = make(chan interface{}, 5)
|
||||||
|
TimeoutSec = 60 // 1 min
|
||||||
|
MaxTimeout = 300 // 5 min
|
||||||
|
|
||||||
BindAddressIPv4 = "127.0.0.1"
|
BindAddressIPv4 = "127.0.0.1"
|
||||||
BindAddressIPv6 = "[::1]"
|
BindAddressIPv6 = "[::1]"
|
||||||
|
|
@ -70,24 +72,52 @@ func authHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
timeoutStr := strings.Join(r.Form[TIMEOUTE], "")
|
timeoutStr := strings.Join(r.Form[TIMEOUTE], "")
|
||||||
|
log.Printf("%sAuth %s", LogInfo, jid)
|
||||||
timeout, err := strconv.Atoi(timeoutStr)
|
timeout, err := strconv.Atoi(timeoutStr)
|
||||||
if err != nil {
|
if err != nil || timeout <= 0 {
|
||||||
timeout = 0
|
timeout = TimeoutSec
|
||||||
|
}
|
||||||
|
if timeout > MaxTimeout {
|
||||||
|
timeout = MaxTimeout
|
||||||
}
|
}
|
||||||
|
|
||||||
answer := xmpp.Confirm(jid, method, domain, transaction, timeout)
|
chanAnswer := make(chan string)
|
||||||
switch answer {
|
|
||||||
case xmpp.REPLY_OK:
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
|
|
||||||
case xmpp.REPLY_DENY:
|
confirmation := new(xmpp.Confirmation)
|
||||||
|
confirmation.JID = jid
|
||||||
|
confirmation.Method = method
|
||||||
|
confirmation.Domain = domain
|
||||||
|
confirmation.Transaction = transaction
|
||||||
|
confirmation.ChanReply = chanAnswer
|
||||||
|
confirmation.SendConfirmation()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case answer := <-chanAnswer:
|
||||||
|
switch answer {
|
||||||
|
case xmpp.REPLY_OK:
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
|
||||||
|
case xmpp.REPLY_DENY:
|
||||||
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
|
||||||
|
case xmpp.REPLY_UNREACHABLE:
|
||||||
|
w.WriteHeader(StatusUnreachable)
|
||||||
|
|
||||||
|
default:
|
||||||
|
w.WriteHeader(StatusUnknownError)
|
||||||
|
}
|
||||||
|
case <-time.After(time.Duration(timeout) * time.Second):
|
||||||
w.WriteHeader(http.StatusUnauthorized)
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
}
|
||||||
|
|
||||||
case xmpp.REPLY_UNREACHABLE:
|
switch confirmation.TypeSend {
|
||||||
w.WriteHeader(StatusUnreachable)
|
case xmpp.TYPE_SEND_IQ:
|
||||||
|
log.Printf("%sDelete IQ", LogDebug)
|
||||||
|
delete(xmpp.WaitIqMessages, confirmation.IdMap)
|
||||||
|
|
||||||
default:
|
case xmpp.TYPE_SEND_MESSAGE:
|
||||||
w.WriteHeader(StatusUnknownError)
|
log.Printf("%sDelete Message", LogDebug)
|
||||||
|
delete(xmpp.WaitMessageAnswers, confirmation.IdMap)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -97,10 +127,6 @@ func Run() {
|
||||||
http.HandleFunc(ROUTE_ROOT, indexHandler)
|
http.HandleFunc(ROUTE_ROOT, indexHandler)
|
||||||
http.HandleFunc(ROUTE_AUTH, authHandler)
|
http.HandleFunc(ROUTE_AUTH, authHandler)
|
||||||
|
|
||||||
// OAuth2
|
|
||||||
LoadOAuth()
|
|
||||||
LoadServer()
|
|
||||||
|
|
||||||
if HttpPortBind > 0 {
|
if HttpPortBind > 0 {
|
||||||
go runHttp(BindAddressIPv4)
|
go runHttp(BindAddressIPv4)
|
||||||
if BindAddressIPv4 != "0.0.0.0" {
|
if BindAddressIPv4 != "0.0.0.0" {
|
||||||
|
|
|
||||||
148
http/oauth.go
148
http/oauth.go
|
|
@ -1,148 +0,0 @@
|
||||||
package http
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"git.kingpenguin.tk/chteufleur/HTTPAuthentificationOverXMPP.git/xmpp"
|
|
||||||
|
|
||||||
"gopkg.in/oauth2.v3/errors"
|
|
||||||
"gopkg.in/oauth2.v3/manage"
|
|
||||||
"gopkg.in/oauth2.v3/models"
|
|
||||||
"gopkg.in/oauth2.v3/server"
|
|
||||||
"gopkg.in/oauth2.v3/store"
|
|
||||||
"gopkg.in/session.v1"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
ROUTE_LOGIN = "/login"
|
|
||||||
ROUTE_AUTHORIZE = "/authorize"
|
|
||||||
ROUTE_TOKEN = "/token"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
globalSessions *session.Manager
|
|
||||||
manager *manage.Manager
|
|
||||||
clientList []models.Client
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
globalSessions, _ = session.NewManager("memory", `{"cookieName":"gosessionid","gclifetime":3600}`)
|
|
||||||
go globalSessions.GC()
|
|
||||||
}
|
|
||||||
|
|
||||||
func LoadConfigClient(configFile string) error {
|
|
||||||
file, err := ioutil.ReadFile(configFile)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return json.Unmarshal(file, &clientList)
|
|
||||||
}
|
|
||||||
|
|
||||||
func LoadOAuth() {
|
|
||||||
manager = manage.NewDefaultManager()
|
|
||||||
// token store
|
|
||||||
manager.MustTokenStorage(store.NewMemoryTokenStore())
|
|
||||||
|
|
||||||
clientStore := store.NewClientStore()
|
|
||||||
for _, c := range clientList {
|
|
||||||
clientStore.Set(c.ID, &c)
|
|
||||||
}
|
|
||||||
manager.MapClientStorage(clientStore)
|
|
||||||
}
|
|
||||||
|
|
||||||
func LoadServer() {
|
|
||||||
srv := server.NewServer(server.NewConfig(), manager)
|
|
||||||
srv.SetUserAuthorizationHandler(userAuthorizeHandler)
|
|
||||||
srv.SetInternalErrorHandler(func(err error) (re *errors.Response) {
|
|
||||||
log.Println("Internal Error:", err.Error())
|
|
||||||
return
|
|
||||||
})
|
|
||||||
srv.SetResponseErrorHandler(func(re *errors.Response) {
|
|
||||||
log.Println("Response Error:", re.Error.Error())
|
|
||||||
})
|
|
||||||
|
|
||||||
http.HandleFunc(ROUTE_LOGIN, loginHandler)
|
|
||||||
http.HandleFunc(ROUTE_AUTHORIZE, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
err := srv.HandleAuthorizeRequest(w, r)
|
|
||||||
if err != nil {
|
|
||||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
http.HandleFunc(ROUTE_TOKEN, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
err := srv.HandleTokenRequest(w, r)
|
|
||||||
if err != nil {
|
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func userAuthorizeHandler(w http.ResponseWriter, r *http.Request) (userID string, err error) {
|
|
||||||
us, err := globalSessions.SessionStart(w, r)
|
|
||||||
uid := us.Get("UserID")
|
|
||||||
if uid == nil {
|
|
||||||
if r.Form == nil {
|
|
||||||
r.ParseForm()
|
|
||||||
}
|
|
||||||
us.Set("Form", r.Form)
|
|
||||||
w.Header().Set("Location", ROUTE_LOGIN)
|
|
||||||
w.WriteHeader(http.StatusFound)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
userID = uid.(string)
|
|
||||||
us.Delete("UserID")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func loginHandler(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.Method == "POST" {
|
|
||||||
us, err := globalSessions.SessionStart(w, r)
|
|
||||||
if err != nil {
|
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
r.ParseForm()
|
|
||||||
jid := strings.Join(r.Form["jid"], "")
|
|
||||||
// TODO
|
|
||||||
answer := xmpp.Confirm(jid, "GET", "toto.fr", "oauth2", -1)
|
|
||||||
switch answer {
|
|
||||||
case xmpp.REPLY_OK:
|
|
||||||
us.Set("LoggedInUserID", jid)
|
|
||||||
form := us.Get("Form").(url.Values)
|
|
||||||
u := new(url.URL)
|
|
||||||
u.Path = ROUTE_AUTHORIZE
|
|
||||||
u.RawQuery = form.Encode()
|
|
||||||
w.Header().Set("Location", u.String())
|
|
||||||
w.WriteHeader(http.StatusFound)
|
|
||||||
us.Delete("Form")
|
|
||||||
us.Set("UserID", us.Get("LoggedInUserID"))
|
|
||||||
|
|
||||||
case xmpp.REPLY_DENY:
|
|
||||||
w.WriteHeader(http.StatusUnauthorized)
|
|
||||||
|
|
||||||
case xmpp.REPLY_UNREACHABLE:
|
|
||||||
w.WriteHeader(StatusUnreachable)
|
|
||||||
|
|
||||||
default:
|
|
||||||
w.WriteHeader(StatusUnknownError)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
outputHTML(w, r, "static/login.html")
|
|
||||||
}
|
|
||||||
|
|
||||||
func outputHTML(w http.ResponseWriter, req *http.Request, filename string) {
|
|
||||||
file, err := os.Open(filename)
|
|
||||||
if err != nil {
|
|
||||||
http.Error(w, err.Error(), 500)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
fi, _ := file.Stat()
|
|
||||||
http.ServeContent(w, req, file.Name(), fi.ModTime(), file)
|
|
||||||
}
|
|
||||||
77
main.go
77
main.go
|
|
@ -16,13 +16,11 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Version = "v0.5-dev"
|
Version = "v0.5-dev"
|
||||||
configurationDirectory = "http-auth"
|
configurationFilePath = "http-auth/httpAuth.conf"
|
||||||
configurationFilePath = "httpAuth.conf"
|
langFilePath = "http-auth/messages.lang"
|
||||||
langFilePath = "messages.lang"
|
PathConfEnvVariable = "XDG_CONFIG_DIRS"
|
||||||
oauthClientStoreFilePath = "clientStore.json"
|
DefaultXdgConfigDirs = "/etc/xdg"
|
||||||
PathConfEnvVariable = "XDG_CONFIG_DIRS"
|
|
||||||
DefaultXdgConfigDirs = "/etc/xdg"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -36,13 +34,12 @@ func init() {
|
||||||
log.Fatal("Failed to load configuration file.")
|
log.Fatal("Failed to load configuration file.")
|
||||||
}
|
}
|
||||||
loadLangFile()
|
loadLangFile()
|
||||||
loadOauthClientStore()
|
|
||||||
|
|
||||||
// HTTP config
|
// HTTP config
|
||||||
httpTimeout, err := strconv.Atoi(mapConfig["http_timeout_sec"])
|
httpTimeout, err := strconv.Atoi(mapConfig["http_timeout_sec"])
|
||||||
if err == nil && httpTimeout > 0 && httpTimeout < xmpp.MaxTimeout {
|
if err == nil && httpTimeout > 0 && httpTimeout < http.MaxTimeout {
|
||||||
log.Println("Define HTTP timeout to " + strconv.Itoa(httpTimeout) + " second")
|
log.Println("Define HTTP timeout to " + strconv.Itoa(httpTimeout) + " second")
|
||||||
xmpp.TimeoutSec = httpTimeout
|
http.TimeoutSec = httpTimeout
|
||||||
}
|
}
|
||||||
httpPort, err := strconv.Atoi(mapConfig["http_port"])
|
httpPort, err := strconv.Atoi(mapConfig["http_port"])
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
|
@ -81,56 +78,50 @@ func init() {
|
||||||
xmpp.VerifyCertValidity = mapConfig["xmpp_verify_cert_validity"] != "false" // Default TRUE
|
xmpp.VerifyCertValidity = mapConfig["xmpp_verify_cert_validity"] != "false" // Default TRUE
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadConfigurationFile(file string) string {
|
func loadConfigFile() bool {
|
||||||
ret := ""
|
ret := false
|
||||||
envVariable := os.Getenv(PathConfEnvVariable)
|
envVariable := os.Getenv(PathConfEnvVariable)
|
||||||
if envVariable == "" {
|
if envVariable == "" {
|
||||||
envVariable = DefaultXdgConfigDirs
|
envVariable = DefaultXdgConfigDirs
|
||||||
}
|
}
|
||||||
for _, path := range strings.Split(envVariable, ":") {
|
for _, path := range strings.Split(envVariable, ":") {
|
||||||
log.Println("Try to find file (" + file + ") into " + path)
|
log.Println("Try to find configuration file into " + path)
|
||||||
configFile := path + "/" + configurationDirectory + "/" + file
|
configFile := path + "/" + configurationFilePath
|
||||||
if _, err := os.Stat(configFile); err == nil {
|
if _, err := os.Stat(configFile); err == nil {
|
||||||
// The file exist
|
// The config file exist
|
||||||
ret = configFile
|
if cfg.Load(configFile, mapConfig) == nil {
|
||||||
break
|
// And has been loaded succesfully
|
||||||
|
log.Println("Find configuration file at " + configFile)
|
||||||
|
ret = true
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadConfigFile() bool {
|
|
||||||
ret := false
|
|
||||||
configFile := loadConfigurationFile(configurationFilePath)
|
|
||||||
if configFile != "" && cfg.Load(configFile, mapConfig) == nil {
|
|
||||||
// And has been loaded succesfully
|
|
||||||
log.Println("Find configuration file at " + configFile)
|
|
||||||
ret = true
|
|
||||||
}
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadLangFile() bool {
|
func loadLangFile() bool {
|
||||||
ret := false
|
ret := false
|
||||||
langFile := loadConfigurationFile(langFilePath)
|
envVariable := os.Getenv(PathConfEnvVariable)
|
||||||
if cfg.Load(langFile, xmpp.MapLangs) == nil {
|
if envVariable == "" {
|
||||||
// And has been loaded succesfully
|
envVariable = DefaultXdgConfigDirs
|
||||||
log.Println("Find messages lang file at " + langFile)
|
}
|
||||||
ret = true
|
for _, path := range strings.Split(envVariable, ":") {
|
||||||
|
log.Println("Try to find messages lang file into " + path)
|
||||||
|
langFile := path + "/" + langFilePath
|
||||||
|
if _, err := os.Stat(langFile); err == nil {
|
||||||
|
// The config file exist
|
||||||
|
if cfg.Load(langFile, xmpp.MapLangs) == nil {
|
||||||
|
// And has been loaded succesfully
|
||||||
|
log.Println("Find messages lang file at " + langFile)
|
||||||
|
ret = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadOauthClientStore() {
|
|
||||||
clientStore := loadConfigurationFile(oauthClientStoreFilePath)
|
|
||||||
err := http.LoadConfigClient(clientStore)
|
|
||||||
if err == nil {
|
|
||||||
log.Printf("Find OAuth client store file at " + clientStore)
|
|
||||||
} else {
|
|
||||||
log.Printf("Failed to load OAuth client store: ", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
go http.Run()
|
go http.Run()
|
||||||
|
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>HTTP authentication over XMPP</title>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div class="container">
|
|
||||||
<h1>HTTP authentication over XMPP</h1>
|
|
||||||
<form action="/login" method="POST">
|
|
||||||
<label for="username">Jabber ID</label>
|
|
||||||
<input type="text" class="form-control" name="jid" placeholder="Please enter your JID">
|
|
||||||
<button type="submit" class="btn btn-success">Login</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -6,14 +6,12 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
REPLY_UNREACHABLE = "reply_unreachable"
|
REPLY_UNREACHABLE = "reply_unreachable"
|
||||||
REPLY_DENY = "reply_deny"
|
REPLY_DENY = "reply_deny"
|
||||||
REPLY_OK = "reply_ok"
|
REPLY_OK = "reply_ok"
|
||||||
REPLY_TIMEOUT = "reply_timeout"
|
|
||||||
|
|
||||||
TYPE_SEND_MESSAGE = "type_send_message"
|
TYPE_SEND_MESSAGE = "type_send_message"
|
||||||
TYPE_SEND_IQ = "type_send_iq"
|
TYPE_SEND_IQ = "type_send_iq"
|
||||||
|
|
@ -26,9 +24,6 @@ const (
|
||||||
|
|
||||||
var (
|
var (
|
||||||
MapLangs = make(map[string]string)
|
MapLangs = make(map[string]string)
|
||||||
|
|
||||||
TimeoutSec = 60 // 1 min
|
|
||||||
MaxTimeout = 300 // 5 min
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Confirmation struct {
|
type Confirmation struct {
|
||||||
|
|
@ -43,46 +38,6 @@ type Confirmation struct {
|
||||||
ChanReply chan 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() {
|
func (confirmation *Confirmation) SendConfirmation() {
|
||||||
log.Printf("%sQuery JID %s", LogInfo, confirmation.JID)
|
log.Printf("%sQuery JID %s", LogInfo, confirmation.JID)
|
||||||
clientJID, _ := xmpp.ParseJID(confirmation.JID)
|
clientJID, _ := xmpp.ParseJID(confirmation.JID)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue