diff --git a/frontends/sortilege/sortilege.py b/frontends/sortilege/sortilege.py
deleted file mode 100755
index 7257760c..00000000
--- a/frontends/sortilege/sortilege.py
+++ /dev/null
@@ -1,387 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-"""
-sortilege: a SAT frontend
-Copyright (C) 2009 Jérôme Poisson (goffi@goffi.org)
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-"""
-
-
-import curses
-import pdb
-from window import Window
-from editbox import EditBox
-from statusbar import StatusBar
-from chat import Chat
-from tools.jid import JID
-import logging
-from logging import debug, info, error
-import locale
-import sys, os
-import gobject
-import time
-from curses import ascii
-import locale
-from signal import signal, SIGWINCH
-import fcntl
-import struct
-import termios
-from boxsizer import BoxSizer
-from quick_frontend.quick_chat_list import QuickChatList
-from quick_frontend.quick_contact_list import QuickContactList
-from quick_frontend.quick_app import QuickApp
-
-### logging configuration FIXME: put this elsewhere ###
-logging.basicConfig(level=logging.CRITICAL, #TODO: configure it top put messages in a log file
- format='%(message)s')
-###
-
-const_APP_NAME = "Sortilège"
-const_CONTACT_WIDTH = 30
-
-def ttysize():
- """This function return term size.
- Comes from Donn Cave from python list mailing list"""
- buf = 'abcdefgh'
- buf = fcntl.ioctl(0, termios.TIOCGWINSZ, buf)
- row, col, rpx, cpx = struct.unpack('hhhh', buf)
- return row, col
-
-def C(k):
- """return the value of Ctrl+key"""
- return ord(ascii.ctrl(k))
-
-class ChatList(QuickChatList):
- """This class manage the list of chat windows"""
-
- def __init__(self, host):
- QuickChatList.__init__(self, host)
- self.sizer=host.sizer
-
- def createChat(self, name):
- chat = Chat(name, self.host)
- self.sizer.appendColum(0,chat)
- self.sizer.update()
- return chat
-
-
-class ContactList(Window, QuickContactList):
-
- def __init__(self):
- QuickContactList.__init__(self)
- self.__index=0 #indicate which contact is selected (ie: where we are)
- Window.__init__(self, stdscr, stdscr.getmaxyx()[0]-2,const_CONTACT_WIDTH,0,0, True, "Contact List", code=code)
-
- def resize(self, height, width, y, x):
- Window.resize(self, height, width, y, x)
- self.update()
-
- def resizeAdapt(self):
- """Adapt window size to stdscr size.
- Must be called when stdscr is resized."""
- self.resize(stdscr.getmaxyx()[0]-2,const_CONTACT_WIDTH,0,0)
- self.update()
-
- def registerEnterCB(self, CB):
- self.__enterCB=CB
-
- def replace(self, jid, name="", show="", status="", group=""):
- """add a contact to the list"""
- self.jid_ids[jid] = name or jid
- self.update()
-
- def indexUp(self):
- """increment select contact index"""
- if self.__index < len(self.jid_ids)-1: #we dont want to select a missing contact
- self.__index = self.__index + 1
- self.update()
-
- def indexDown(self):
- """decrement select contact index"""
- if self.__index > 0:
- self.__index = self.__index - 1
- self.update()
-
- def remove(self, jid):
- """remove a contact from the list"""
- del self.jid_ids[jid]
- if self.__index >= len(self.jid_ids) and self.__index > 0: #if select index is out of border, we put it on the last contact
- self.__index = len(self.jid_ids)-1
- self.update()
-
- def update(self):
- """redraw all the window"""
- if self.isHidden():
- return
- Window.update(self)
- viewList=[]
- for jid in self.jid_ids:
- viewList.append(self.jid_ids[jid])
- viewList.sort()
- begin=0 if self.__index ", self.code)
- self.editBar.activate(False)
- self.statusBar = StatusBar(stdscr, self.code)
- self.statusBar.hide(True)
- self.addWin(self.contactList)
- self.addWin(self.editBar)
- self.addWin(self.statusBar)
- self.sizer=BoxSizer(stdscr)
- self.sizer.appendRow(self.contactList)
- self.sizer.appendRow(self.statusBar)
- self.sizer.appendRow(self.editBar)
- self.currentChat=None
-
- self.contactList.registerEnterCB(self.onContactChoosed)
- self.editBar.registerEnterCB(self.onTextEntered)
-
- self.chat_wins=ChatList(self)
-
- QuickApp.__init__(self) #XXX: yes it's an unusual place for the constructor of a parent class, but the init order is important
-
- signal (SIGWINCH, self.onResize) #we manage SIGWINCH ourselves, because the loop is not called otherwise
-
- #last but not least, we adapt windows' sizes
- self.sizer.update()
- self.editBar.replace_cur()
- curses.doupdate()
-
- self.loop.run()
-
- def addWin(self, win):
- self.listWins.append(win)
-
- def color(self, activate=True):
- if activate:
- debug ("Activation des couleurs")
- curses.init_pair(1, curses.COLOR_BLUE, curses.COLOR_BLACK)
- curses.init_pair(2, curses.COLOR_RED, curses.COLOR_BLACK)
- else:
- debug ("Desactivation des couleurs")
- curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_BLACK)
- curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_BLACK)
-
-
- def showChat(self, chat):
- debug ("show chat")
- if self.currentChat:
- debug ("hide de %s", self.currentChat)
- self.chat_wins[self.currentChat].hide()
- self.currentChat=chat
- debug ("show de %s", self.currentChat)
- self.chat_wins[self.currentChat].show()
- self.chat_wins[self.currentChat].update()
-
-
- ### EVENTS ###
-
- def onContactChoosed(self, jid_txt):
- """Called when a contact is selected in contact list."""
- jid=JID(jid_txt)
- debug ("contact choose: %s", jid)
- self.showChat(jid.short)
- self.statusBar.remove_item(jid.short)
- if len(self.statusBar)==0:
- self.statusBar.hide()
- self.sizer.update()
-
-
- def onTextEntered(self, text):
- jid=JID(self.whoami)
- self.bridge.sendMessage(self.currentChat, text)
-
- def showDialog(self, message, title, type="info"):
- if type==question:
- raise NotImplementedError
- pass
-
-
- def presenceUpdate(self, jabber_id, type, show, status, priority):
- QuickApp.presenceUpdate(self, jabber_id, type, show, status, priority)
- self.editBar.replace_cur()
- curses.doupdate()
-
- def askConfirmation(self, type, id, data):
- #FIXME
- info ("FIXME: askConfirmation not implemented")
-
- def actionResult(self, type, id, data):
- #FIXME
- info ("FIXME: actionResult not implemented")
-
- def newMessage(self, from_jid, msg, type, to_jid):
- QuickApp.newMessage(self, from_jid, msg, type, to_jid)
- sender=JID(from_jid)
- addr=JID(to_jid)
- win = addr if sender.short == self.whoami.short else sender #FIXME: duplicate code with QuickApp
- if (self.currentChat==None):
- self.currentChat=win.short
- self.showChat(win.short)
-
- # we show the window in the status bar
- if not self.currentChat == win.short:
- self.statusBar.add_item(win.short)
- self.statusBar.show()
- self.sizer.update()
- self.statusBar.update()
-
- self.editBar.replace_cur()
- curses.doupdate()
-
- def onResize(self, sig, stack):
- """Called on SIGWINCH.
- resize the screen and launch the loop"""
- height, width = ttysize()
- curses.resizeterm(height, width)
- gobject.idle_add(self.callOnceLoop)
-
- def callOnceLoop(self):
- """Call the loop and return false (for not being called again by gobject mainloop).
- Usefull for calling loop when there is no input in stdin"""
- self.loopCB()
- return False
-
- def __key_handling(self, k):
- """Handle key and transmit to active window."""
-
- ### General keys, handled _everytime_ ###
- if k == C('x'):
- if os.getenv('TERM')=='screen':
- os.system('screen -X remove')
- else:
- self.loop.quit()
-
- ## windows navigation
- elif k == C('l') and not self.contactList.isHidden():
- """We go to the contact list"""
- self.contactList.activate(not self.contactList.isActive())
- if self.currentChat:
- self.editBar.activate(not self.contactList.isActive())
-
- elif k == curses.KEY_F2:
- self.contactList.hide(not self.contactList.isHidden())
- if self.contactList.isHidden():
- self.contactList.activate(False) #TODO: auto deactivation when hiding ?
- if self.currentChat:
- self.editBar.activate(True)
- self.sizer.update()
-
- ## Chat Params ##
- elif k == C('c'):
- self.chatParams["color"] = not self.chatParams["color"]
- self.color(self.chatParams["color"])
- elif k == C('t'):
- self.chatParams["timestamp"] = not self.chatParams["timestamp"]
- self.chat_wins[self.currentChat].update()
- elif k == C('s'):
- self.chatParams["short_nick"] = not self.chatParams["short_nick"]
- self.chat_wins[self.currentChat].update()
-
- ## misc ##
- elif k == curses.KEY_RESIZE:
- stdscr.erase()
- height, width = stdscr.getmaxyx()
- if height<5 and width<35:
- stdscr.addstr("Pleeeeasse, I can't even breathe !")
- else:
- for win in self.listWins:
- win.resizeAdapt()
- for win in self.chat_wins.keys():
- self.chat_wins[win].resizeAdapt()
- self.sizer.update() # FIXME: everything need to be managed by the sizer
-
- ## we now throw the key to win handlers ##
- else:
- for win in self.listWins:
- if win.isActive():
- win.handleKey(k)
- if self.currentChat:
- self.chat_wins[self.currentChat].handleKey(k)
-
- def loopCB(self, source="", cb_condition=""):
- """This callback is called by the main loop"""
- #pressed = self.contactList.window.getch()
- pressed = stdscr.getch()
- if pressed != curses.ERR:
- self.__key_handling(pressed)
- self.editBar.replace_cur()
- curses.doupdate()
-
-
- return True
-
-
-sat = SortilegeApp()
-sat.start()
diff --git a/frontends/wix/main_window.py b/frontends/wix/main_window.py
index 1a8f1986..bb9da9e0 100644
--- a/frontends/wix/main_window.py
+++ b/frontends/wix/main_window.py
@@ -327,6 +327,9 @@ class MainWindow(wx.Frame, QuickApp):
)
dlg.ShowModal()
dlg.Destroy()
+ elif type == "FORM":
+ self.current_action_ids.remove(id)
+ info ("Form received !")
elif type == "DICT_DICT":
self.current_action_ids.remove(id)
if self.current_action_ids_cb.has_key(id):
diff --git a/frontends/wix/wix.py b/frontends/wix/wix.py
deleted file mode 100755
index 4c289965..00000000
--- a/frontends/wix/wix.py
+++ /dev/null
@@ -1,48 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-"""
-wix: a SAT frontend
-Copyright (C) 2009 Jérôme Poisson (goffi@goffi.org)
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-"""
-
-
-import wx
-from sat_bridge_frontend.DBus import DBusBridgeFrontend
-import pdb
-import logging
-from logging import debug, info, error
-from main_window import MainWindow
-
-### logging configuration FIXME: put this elsewhere ###
-logging.basicConfig(level=logging.DEBUG,
- format='%(message)s')
-###
-
-
-class SATApp(wx.App):
- def __init__(self, redirect=False, filename=None, useBestVisual=False, clearSigInt=True):
- super(SATApp,self).__init__(redirect, filename, useBestVisual, clearSigInt)
-
- def OnInit(self):
- self.main = MainWindow()
- self.main.Show(True)
- self.SetTopWindow(self.main)
- return True
-
-
-sat = SATApp()
-sat.MainLoop()
diff --git a/plugins/plugin_xep_0077.py b/plugins/plugin_xep_0077.py
index 1fadbd65..19a6f9ac 100755
--- a/plugins/plugin_xep_0077.py
+++ b/plugins/plugin_xep_0077.py
@@ -23,8 +23,11 @@ from logging import debug, info, error
from twisted.words.protocols.jabber import client, jid, xmlstream, error
from twisted.words.protocols.jabber.xmlstream import IQ
from twisted.internet import reactor
+from tools.xml_tools import XMLTools
import pdb
+from wokkel import data_form
+
NS_REG = 'jabber:iq:register'
PLUGIN_INFO = {
@@ -46,6 +49,9 @@ class XEP_0077():
def reg_ok(self, answer):
"""Called after the first get IQ"""
print "answer:",answer
+ form = data_form.Form.fromElement(answer.firstChildElement().firstChildElement())
+ xml_data = XMLTools.dataForm2xml(form)
+ self.host.bridge.actionResult("FORM", answer['id'], {"type":"registration", "xml":xml_data})
def reg_err(self, failure):
"""Called when something is wrong with registration"""
diff --git a/sat.tac b/sat.tac
index 88addcfc..47c48976 100644
--- a/sat.tac
+++ b/sat.tac
@@ -524,7 +524,7 @@ 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")
+ @type: result type ("PARAM", "SUCCESS", "ERROR", "FORM")
@data: dictionary
"""
self.bridge.actionResult(type, id, data)
@@ -532,7 +532,7 @@ class SAT(service.Service):
def actionResultExt(self, id, type, data):
"""Send the result of an action, extended version
@param id: same id used with action
- @type: result type ("PARAM", "SUCCESS", "ERROR")
+ @type: result type /!\ only "DICT_DICT" for this method
@data: dictionary of dictionaries
"""
if type != "DICT_DICT":
diff --git a/tools/xml_tools.py b/tools/xml_tools.py
new file mode 100644
index 00000000..5707e8c3
--- /dev/null
+++ b/tools/xml_tools.py
@@ -0,0 +1,52 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+"""
+SAT: a jabber client
+Copyright (C) 2009 Jérôme Poisson (goffi@goffi.org)
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+"""
+
+from logging import debug, info, error
+from xml.dom import minidom
+import pdb
+
+class XMLTools:
+ """This class help manage XML used in SàT (parameters, registration, etc) """
+
+
+ @staticmethod
+ def dataForm2xml(form):
+ """Take a data form (xep-0004, Wokkel's implementation) and convert it to a SàT xml"""
+ result_xml = [""]
+ if form.instructions:
+ result_xml.insert(1,"" % '\n'.join(form.instructions))
+ for field in form.fieldList:
+ if field.fieldType == 'text-single':
+ __field_type = "string"
+ elif field.fieldType == 'text-private':
+ __field_type = "password"
+ else:
+ error (u"FIXME FIXME FIXME: Type [%s] is not managed yet by SàT" % field.fieldType)
+ __field_type = "string_field"
+
+ result_xml.insert(-1,"" % (field.var, __field_type, field.label))
+
+ return '\n'.join(result_xml)
+
+
+
+
+ pdb.set_trace()