Gateway registration, unregistration & edition
- default values added in form - DBus bridge: fixed array of struct management when adding dynamically a method - fixed doc for some methods - ugly fix for presence status - added dependency for XEP-0077 in XEP-0100 plugin - Wix: added unregister button in gateways manager - Wix: added privacy warning in gateways manager
This commit is contained in:
parent
914f7da809
commit
e3a3c1e975
8 changed files with 159 additions and 39 deletions
|
|
@ -100,8 +100,10 @@ class DBusBridgeFrontend(BridgeFrontend):
|
|||
def confirmationAnswer(self, id, accepted, data):
|
||||
return self.db_req_iface.confirmationAnswer(id, accepted, data)
|
||||
|
||||
def submitForm(self, target, data):
|
||||
return self.db_req_iface.submitForm(target, data)
|
||||
def gatewayRegister(self, action, target, data):
|
||||
if data == None:
|
||||
data = [('', '')] #XXX: we have to this awful hack because python dbus need to guess the signature
|
||||
return self.db_req_iface.gatewayRegister(action, target, data)
|
||||
|
||||
def getProgress(self, id):
|
||||
return self.db_req_iface.getProgress(id)
|
||||
|
|
|
|||
|
|
@ -103,23 +103,21 @@ class Form(wx.Frame):
|
|||
for ctrl in self.ctl_list:
|
||||
data.append((ctrl["name"], ctrl["control"].GetValue()))
|
||||
print "submitting:",data
|
||||
id = self.host.bridge.submitForm(self.target, data)
|
||||
id = self.host.bridge.gatewayRegister("SUBMIT",self.target, data)
|
||||
self.host.current_action_ids.add(id)
|
||||
print "action id:",id
|
||||
event.Skip()
|
||||
self.MakeModal(False)
|
||||
self.Destroy()
|
||||
|
||||
def onFormCancelled(self, event):
|
||||
"""Called when cancel button is clicked"""
|
||||
debug("Cancelling form")
|
||||
#id = self.host.bridge.submitForm("button", data)
|
||||
#self.host.current_action_ids.add(id)
|
||||
#print "action id:",id
|
||||
event.Skip()
|
||||
self.MakeModal(False)
|
||||
self.Close()
|
||||
|
||||
def onClose(self, event):
|
||||
"""Close event: we have to send the form."""
|
||||
debug("close")
|
||||
|
||||
self.MakeModal(False)
|
||||
event.Skip()
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@ from xml.dom import minidom
|
|||
from logging import debug, info, error
|
||||
from tools.jid import JID
|
||||
|
||||
WARNING_MSG = u"""Be careful ! Gateways allow you to use an external IM (legacy IM), so you can see your contact as jabber contacts.
|
||||
But when you do this, all your messages go throught the external legacy IM server, it is a huge privacy issue (i.e.: all your messages throught the gateway can be monitored, recorded, analyzed by the external server, most of time a private company)."""
|
||||
|
||||
class GatewaysManager(wx.Frame):
|
||||
def __init__(self, host, gateways, title="Gateways manager"):
|
||||
|
|
@ -44,8 +46,14 @@ class GatewaysManager(wx.Frame):
|
|||
self.ctl_list = {} # usefull to access ctrl, key = (name, category)
|
||||
|
||||
self.sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
warning = wx.TextCtrl(self, -1, value=WARNING_MSG, style = wx.TE_MULTILINE |
|
||||
wx.TE_READONLY |
|
||||
wx.TE_LEFT)
|
||||
warning.SetFont(self.bold_font)
|
||||
self.sizer.Add(warning, 0, wx.EXPAND)
|
||||
warning.ShowPosition(0)
|
||||
self.panel = wx.Panel(self)
|
||||
self.panel.sizer = wx.FlexGridSizer(cols=4)
|
||||
self.panel.sizer = wx.FlexGridSizer(cols=5)
|
||||
self.panel.SetSizer(self.panel.sizer)
|
||||
self.panel.SetAutoLayout(True)
|
||||
self.sizer.Add(self.panel, 1, flag=wx.EXPAND)
|
||||
|
|
@ -64,12 +72,14 @@ class GatewaysManager(wx.Frame):
|
|||
self.panel.sizer.Add(title_name)
|
||||
self.panel.sizer.Add(title_type)
|
||||
self.panel.sizer.Add(wx.Window(self.panel, -1))
|
||||
self.panel.sizer.Add(wx.Window(self.panel, -1))
|
||||
|
||||
for gateway in gateways:
|
||||
self.addGateway(gateway, gateways[gateway])
|
||||
|
||||
|
||||
self.panel.sizer.Fit(self)
|
||||
#self.panel.sizer.Fit(self)
|
||||
self.sizer.Fit(self)
|
||||
|
||||
self.Show()
|
||||
|
||||
|
|
@ -121,24 +131,40 @@ class GatewaysManager(wx.Frame):
|
|||
id = self.host.bridge.in_band_register(gateway_jid)
|
||||
self.host.current_action_ids.add(id)
|
||||
print "register id:",id
|
||||
self.MakeModal(False)
|
||||
self.Destroy()
|
||||
event.Skip()
|
||||
|
||||
def unregister_cb(event):
|
||||
"""Called when unregister button is clicked"""
|
||||
gateway_jid = event.GetEventObject().gateway_jid
|
||||
id = self.host.bridge.gatewayRegister("CANCEL",gateway_jid, None)
|
||||
self.host.current_action_ids.add(id)
|
||||
print "unregister id:",id
|
||||
self.MakeModal(False)
|
||||
self.Destroy()
|
||||
event.Skip()
|
||||
|
||||
button_font = wx.Font(6, wx.DEFAULT, wx.NORMAL, wx.BOLD)
|
||||
reg_button = wx.Button(self.panel, -1, "Register", size=wx.Size(-1, 8))
|
||||
reg_button.SetFont(button_font)
|
||||
reg_button.gateway_jid = JID(gateway)
|
||||
self.panel.Bind(wx.EVT_BUTTON, register_cb, reg_button)
|
||||
|
||||
unreg_button = wx.Button(self.panel, -1, "Unregister", size=wx.Size(-1, 8))
|
||||
unreg_button.SetFont(button_font)
|
||||
unreg_button.gateway_jid = JID(gateway)
|
||||
self.panel.Bind(wx.EVT_BUTTON, unregister_cb, unreg_button)
|
||||
|
||||
self.panel.sizer.Add(im_icon)
|
||||
self.panel.sizer.Add(label)
|
||||
self.panel.sizer.Add(type_label)
|
||||
self.panel.sizer.Add(reg_button, 1, wx.EXPAND)
|
||||
self.panel.sizer.Add(unreg_button, 1, wx.EXPAND)
|
||||
|
||||
|
||||
def onClose(self, event):
|
||||
"""Close event"""
|
||||
debug("close")
|
||||
#now we save the modifier params
|
||||
self.MakeModal(False)
|
||||
event.Skip()
|
||||
|
||||
|
|
|
|||
|
|
@ -40,16 +40,21 @@ PLUGIN_INFO = {
|
|||
}
|
||||
|
||||
class XEP_0077():
|
||||
|
||||
|
||||
def __init__(self, host):
|
||||
info("Plugin XEP_0077 initialization")
|
||||
self.host = host
|
||||
self.triggers = {} #used by other protocol (e.g. XEP-0100) to finish registration. key = target_jid
|
||||
host.bridge.addMethod("in_band_register", ".communication", in_sign='s', out_sign='s', method=self.in_band_register)
|
||||
host.bridge.addMethod("in_band_submit", ".request", in_sign='sa(ss)', out_sign='s', method=self.in_band_submit)
|
||||
|
||||
def addTrigger(self, target, cb):
|
||||
"""Add a callback which is called when registration to target is successful"""
|
||||
self.triggers[target] = cb
|
||||
|
||||
def reg_ok(self, answer):
|
||||
"""Called after the first get IQ"""
|
||||
form = data_form.Form.fromElement(answer.firstChildElement().firstChildElement())
|
||||
pdb.set_trace()
|
||||
xml_data = XMLTools.dataForm2xml(form)
|
||||
self.host.bridge.actionResult("FORM", answer['id'], {"target":answer["from"], "type":"registration", "xml":xml_data})
|
||||
|
||||
|
|
@ -62,6 +67,53 @@ class XEP_0077():
|
|||
answer_type = "ERROR"
|
||||
self.host.bridge.actionResult(answer_type, failure.value.stanza['id'], answer_data)
|
||||
|
||||
def unregistrationAnswer(self, answer):
|
||||
debug ("registration answer: %s" % answer.toXml())
|
||||
answer_type = "SUCCESS"
|
||||
answer_data={"message":"Your are now unregistred"}
|
||||
self.host.bridge.actionResult(answer_type, answer['id'], answer_data)
|
||||
|
||||
def unregistrationFailure(self, failure):
|
||||
info ("Unregistration failure: %s" % str(failure.value))
|
||||
answer_type = "ERROR"
|
||||
answer_data = {}
|
||||
answer_data['reason'] = 'unknown'
|
||||
answer_data={"message":"Unregistration failed: %s" % failure.value.condition}
|
||||
self.host.bridge.actionResult(answer_type, failure.value.stanza['id'], answer_data)
|
||||
|
||||
def registrationAnswer(self, answer):
|
||||
debug ("registration answer: %s" % answer.toXml())
|
||||
answer_type = "SUCCESS"
|
||||
answer_data={"message":"Registration successfull"}
|
||||
self.host.bridge.actionResult(answer_type, answer['id'], answer_data)
|
||||
if self.triggers.has_key(answer["from"]):
|
||||
self.triggers[answer["from"]](answer["from"])
|
||||
del self.triggers[answer["from"]]
|
||||
|
||||
def registrationFailure(self, failure):
|
||||
info ("Registration failure: %s" % str(failure.value))
|
||||
print failure.value.stanza.toXml()
|
||||
answer_type = "ERROR"
|
||||
answer_data = {}
|
||||
if failure.value.condition == 'conflict':
|
||||
answer_data['reason'] = 'conflict'
|
||||
answer_data={"message":"Username already exists, please choose an other one"}
|
||||
else:
|
||||
answer_data['reason'] = 'unknown'
|
||||
answer_data={"message":"Registration failed"}
|
||||
self.host.bridge.actionResult(answer_type, failure.value.stanza['id'], answer_data)
|
||||
if self.triggers.has_key(answer["from"]):
|
||||
del self.triggers[answer["from"]]
|
||||
|
||||
def in_band_submit(self, action, target, fields):
|
||||
"""Submit a form for registration, using data_form"""
|
||||
id, deferred = self.host.submitForm(action, target, fields)
|
||||
if action == 'CANCEL':
|
||||
deferred.addCallbacks(self.unregistrationAnswer, self.unregistrationFailure)
|
||||
else:
|
||||
deferred.addCallbacks(self.registrationAnswer, self.registrationFailure)
|
||||
return id
|
||||
|
||||
def in_band_register(self, target):
|
||||
"""register to a target JID"""
|
||||
to_jid = jid.JID(target)
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ PLUGIN_INFO = {
|
|||
"name": "Gateways Plugin",
|
||||
"import_name": "XEP_0100",
|
||||
"type": "XEP",
|
||||
"dependencies": [],
|
||||
"dependencies": ["XEP_0077"],
|
||||
"main": "XEP_0100",
|
||||
"description": """Implementation of Gateways protocol"""
|
||||
}
|
||||
|
|
@ -42,6 +42,7 @@ class XEP_0100():
|
|||
self.host = host
|
||||
self.__gateways = {} #dict used to construct the answer to findGateways. Key = target jid
|
||||
host.bridge.addMethod("findGateways", ".communication", in_sign='s', out_sign='s', method=self.findGateways)
|
||||
host.bridge.addMethod("gatewayRegister", ".request", in_sign='ssa(ss)', out_sign='s', method=self.gatewayRegister)
|
||||
|
||||
def discoInfo(self, disco, entity, request_id):
|
||||
"""Find disco infos about entity, to check if it is a gateway"""
|
||||
|
|
@ -76,6 +77,18 @@ class XEP_0100():
|
|||
debug ("item found: %s", item.name)
|
||||
self.host.disco.requestInfo(item.entity).addCallback(self.discoInfo, entity=item.entity, request_id=request_id)
|
||||
|
||||
def registrationSuccessful(self, target):
|
||||
"""Called when in_band registration is ok, we must now follow the rest of procedure"""
|
||||
print "Registration successful, doing the rest"
|
||||
self.host.addContact(target)
|
||||
self.host.setPresence(target)
|
||||
|
||||
def gatewayRegister(self, action, target, fields):
|
||||
"""Register gateway using in-band registration, then log-in to gateway"""
|
||||
if action == 'SUBMIT':
|
||||
self.host.plugins["XEP_0077"].addTrigger(target, self.registrationSuccessful)
|
||||
return self.host.plugins["XEP_0077"].in_band_submit(action, target, fields)
|
||||
|
||||
def findGateways(self, target):
|
||||
"""Find gateways in the target JID, using discovery protocol
|
||||
Return an id used for retrieving the list of gateways
|
||||
|
|
|
|||
49
sat.tac
49
sat.tac
|
|
@ -42,6 +42,7 @@ import signal, sys
|
|||
import os.path
|
||||
|
||||
from tools.memory import Memory
|
||||
from tools.xml_tools import XMLTools
|
||||
from glob import glob
|
||||
|
||||
try:
|
||||
|
|
@ -278,7 +279,6 @@ class SAT(service.Service):
|
|||
self.bridge.register("isConnected", self.isConnected)
|
||||
self.bridge.register("launchAction", self.launchAction)
|
||||
self.bridge.register("confirmationAnswer", self.confirmationAnswer)
|
||||
self.bridge.register("submitForm", self.submitForm)
|
||||
self.bridge.register("getProgress", self.getProgress)
|
||||
|
||||
self._import_plugins()
|
||||
|
|
@ -373,8 +373,8 @@ class SAT(service.Service):
|
|||
self.presence.available()
|
||||
|
||||
self.disco.requestInfo(jid.JID(self.memory.getParamA("Server", "Connection"))).addCallback(self.serverDisco)
|
||||
|
||||
## Misc methods ##
|
||||
|
||||
## Misc methods ##
|
||||
|
||||
def registerNewAccount(self, login, password, server, port = 5222, id = None):
|
||||
"""Connect to a server and create a new account using in-band registration"""
|
||||
|
|
@ -419,11 +419,29 @@ class SAT(service.Service):
|
|||
else:
|
||||
self.actionResult(action_id, "SUPPRESS", {})
|
||||
|
||||
def submitForm(self, target, fields):
|
||||
"""Called when a form is submited"""
|
||||
def submitForm(self, action, target, fields):
|
||||
"""submit a form
|
||||
@param target: target jid where we are submitting
|
||||
@param fields: list of tuples (name, value)
|
||||
@return: tuple: (id, deferred)
|
||||
"""
|
||||
to_jid = jid.JID(target)
|
||||
print "Form submitted !", fields
|
||||
return self.get_next_id()
|
||||
|
||||
iq = compat.IQ(self.xmlstream, 'set')
|
||||
iq["to"] = target
|
||||
iq["from"] = self.me.full()
|
||||
query = iq.addElement(('jabber:iq:register', 'query'))
|
||||
if action=='SUBMIT':
|
||||
form = XMLTools.tupleList2dataForm(fields)
|
||||
query.addChild(form.toElement())
|
||||
elif action=='CANCEL':
|
||||
query.addElement('remove')
|
||||
else:
|
||||
error ("FIXME FIXME FIXME: Unmanaged action (%s) in submitForm" % action)
|
||||
raise NotImplementedError
|
||||
|
||||
deferred = iq.send(target)
|
||||
return (iq['id'], deferred)
|
||||
|
||||
## Client management ##
|
||||
|
||||
|
|
@ -448,7 +466,7 @@ class SAT(service.Service):
|
|||
def launchAction(self, type, data):
|
||||
"""Launch a specific action asked by client
|
||||
@param type: action type (button)
|
||||
@data: needed data to launch the action
|
||||
@param data: needed data to launch the action
|
||||
|
||||
@return: action id for result, or empty string in case or error
|
||||
"""
|
||||
|
|
@ -489,6 +507,7 @@ class SAT(service.Service):
|
|||
#TODO: throw an error
|
||||
return
|
||||
to_jid=jid.JID(to)
|
||||
status = None if not status else {None:status} #FIXME: use the proper way here (change signature to use dict)
|
||||
#TODO: refactor subscription bridge API
|
||||
if type=="":
|
||||
self.presence.available(to_jid, show, status, priority)
|
||||
|
|
@ -531,16 +550,16 @@ class SAT(service.Service):
|
|||
def actionResult(self, id, type, data):
|
||||
"""Send the result of an action
|
||||
@param id: same id used with action
|
||||
@type: result type ("PARAM", "SUCCESS", "ERROR", "FORM")
|
||||
@data: dictionary
|
||||
@param type: result type ("PARAM", "SUCCESS", "ERROR", "FORM")
|
||||
@param data: dictionary
|
||||
"""
|
||||
self.bridge.actionResult(type, id, data)
|
||||
|
||||
def actionResultExt(self, id, type, data):
|
||||
"""Send the result of an action, extended version
|
||||
@param id: same id used with action
|
||||
@type: result type /!\ only "DICT_DICT" for this method
|
||||
@data: dictionary of dictionaries
|
||||
@param type: result type /!\ only "DICT_DICT" for this method
|
||||
@param data: dictionary of dictionaries
|
||||
"""
|
||||
if type != "DICT_DICT":
|
||||
error("type for actionResultExt must be DICT_DICT, fixing it")
|
||||
|
|
@ -552,9 +571,9 @@ class SAT(service.Service):
|
|||
def askConfirmation(self, id, type, data, cb):
|
||||
"""Add a confirmation callback
|
||||
@param id: id used to get answer
|
||||
@type: confirmation type ("YES/NO", "FILE_TRANSFERT")
|
||||
@data: data (depend of confirmation type)
|
||||
@cb: callback called with the answer
|
||||
@param type: confirmation type ("YES/NO", "FILE_TRANSFERT")
|
||||
@param data: data (depend of confirmation type)
|
||||
@param cb: callback called with the answer
|
||||
"""
|
||||
if self.__waiting_conf.has_key(id):
|
||||
error ("Attempt to register two callbacks for the same confirmation")
|
||||
|
|
|
|||
|
|
@ -186,11 +186,6 @@ class DbusObject(dbus.service.Object):
|
|||
debug("Answer for confirmation [%s]: %s", id, "Accepted" if accepted else "Refused")
|
||||
return self.cb["confirmationAnswer"](id, accepted, data)
|
||||
|
||||
@dbus.service.method(const_INT_PREFIX+const_REQ_SUFFIX,
|
||||
in_signature='sa(ss)', out_signature='s')
|
||||
def submitForm(self, target, fields):
|
||||
info ("Form submited")
|
||||
return self.cb["submitForm"](target, fields)
|
||||
|
||||
@dbus.service.method(const_INT_PREFIX+const_REQ_SUFFIX,
|
||||
in_signature='s', out_signature='a{ss}')
|
||||
|
|
@ -214,7 +209,7 @@ class DbusObject(dbus.service.Object):
|
|||
i+=1
|
||||
if i>=len(in_sign):
|
||||
raise Exception #FIXME: create an exception here (the '}' is not presend)
|
||||
if in_sign[i] == '}':
|
||||
if in_sign[i] == '}' or in_sign[i] == ')':
|
||||
break
|
||||
i+=1
|
||||
return attr_string
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
from logging import debug, info, error
|
||||
from xml.dom import minidom
|
||||
from wokkel import data_form
|
||||
import pdb
|
||||
|
||||
class XMLTools:
|
||||
|
|
@ -57,10 +58,24 @@ class XMLTools:
|
|||
elem.setAttribute('name', field.var)
|
||||
elem.setAttribute('type', __field_type)
|
||||
elem.setAttribute('label', field.label)
|
||||
#text = doc.createTextNode(field.value)
|
||||
#elem.appendChild(text)
|
||||
if field.value:
|
||||
text = doc.createTextNode(field.value)
|
||||
elem.appendChild(text)
|
||||
top_element.appendChild(elem)
|
||||
|
||||
result = doc.toxml()
|
||||
doc.unlink()
|
||||
return result
|
||||
|
||||
@staticmethod
|
||||
def tupleList2dataForm(values):
|
||||
"""convert a list of tuples (name,value) to a wokkel submit data form"""
|
||||
form = data_form.Form('submit')
|
||||
for value in values:
|
||||
field = data_form.Field(var=value[0], value=value[1])
|
||||
form.addField(field)
|
||||
|
||||
return form
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue