root/xmppony/features.py @ 0:2b766784ee99

Revision 0:2b766784ee99, 8.3 kB (checked in by elghinn, 18 months ago)

* initial import

Line 
1##   features.py
2##
3##   Copyright (C) 2003-2004 Alexey "Snake" Nezhdanov
4##
5##   This program is free software; you can redistribute it and/or modify
6##   it under the terms of the GNU General Public License as published by
7##   the Free Software Foundation; either version 2, or (at your option)
8##   any later version.
9##
10##   This program is distributed in the hope that it will be useful,
11##   but WITHOUT ANY WARRANTY; without even the implied warranty of
12##   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13##   GNU General Public License for more details.
14
15# $Id: features.py,v 1.24 2006/03/25 05:47:22 snakeru Exp $
16
17"""
18This module contains variable stuff that is not worth splitting into separate modules.
19Here is:
20    DISCO client and agents-to-DISCO and browse-to-DISCO emulators.
21    IBR and password manager.
22    jabber:iq:privacy methods
23All these methods takes 'disp' first argument that should be already connected
24(and in most cases already authorised) dispatcher instance.
25"""
26
27from protocol import *
28
29REGISTER_DATA_RECEIVED='REGISTER DATA RECEIVED'
30
31### DISCO ### http://jabber.org/protocol/disco ### JEP-0030 ####################
32### Browse ### jabber:iq:browse ### JEP-0030 ###################################
33### Agents ### jabber:iq:agents ### JEP-0030 ###################################
34def _discover(disp,ns,jid,node=None,fb2b=0,fb2a=1):
35    """ Try to obtain info from the remote object.
36        If remote object doesn't support disco fall back to browse (if fb2b is true)
37        and if it doesnt support browse (or fb2b is not true) fall back to agents protocol
38        (if gb2a is true). Returns obtained info. Used internally. """
39    iq=Iq(to=jid,typ='get',queryNS=ns)
40    if node: iq.setQuerynode(node)
41    rep=disp.SendAndWaitForResponse(iq)
42    if fb2b and not isResultNode(rep): rep=disp.SendAndWaitForResponse(Iq(to=jid,typ='get',queryNS=NS_BROWSE))   # Fallback to browse
43    if fb2a and not isResultNode(rep): rep=disp.SendAndWaitForResponse(Iq(to=jid,typ='get',queryNS=NS_AGENTS))   # Fallback to agents
44    if isResultNode(rep): return rep.getQueryPayload()
45    return []
46
47def discoverItems(disp,jid,node=None):
48    """ Query remote object about any items that it contains. Return items list. """
49    """ According to JEP-0030:
50        query MAY have node attribute
51        item: MUST HAVE jid attribute and MAY HAVE name, node, action attributes.
52        action attribute of item can be either of remove or update value."""
53    ret=[]
54    for i in _discover(disp,NS_DISCO_ITEMS,jid,node):
55        if i.getName()=='agent' and i.getTag('name'): i.setAttr('name',i.getTagData('name'))
56        ret.append(i.attrs)
57    return ret
58
59def discoverInfo(disp,jid,node=None):
60    """ Query remote object about info that it publishes. Returns identities and features lists."""
61    """ According to JEP-0030:
62        query MAY have node attribute
63        identity: MUST HAVE category and name attributes and MAY HAVE type attribute.
64        feature: MUST HAVE var attribute"""
65    identities , features = [] , []
66    for i in _discover(disp,NS_DISCO_INFO,jid,node):
67        if i.getName()=='identity': identities.append(i.attrs)
68        elif i.getName()=='feature': features.append(i.getAttr('var'))
69        elif i.getName()=='agent':
70            if i.getTag('name'): i.setAttr('name',i.getTagData('name'))
71            if i.getTag('description'): i.setAttr('name',i.getTagData('description'))
72            identities.append(i.attrs)
73            if i.getTag('groupchat'): features.append(NS_GROUPCHAT)
74            if i.getTag('register'): features.append(NS_REGISTER)
75            if i.getTag('search'): features.append(NS_SEARCH)
76    return identities , features
77
78### Registration ### jabber:iq:register ### JEP-0077 ###########################
79def getRegInfo(disp,host,info={},sync=True):
80    """ Gets registration form from remote host.
81        You can pre-fill the info dictionary.
82        F.e. if you are requesting info on registering user joey than specify
83        info as {'username':'joey'}. See JEP-0077 for details.
84        'disp' must be connected dispatcher instance."""
85    iq=Iq('get',NS_REGISTER,to=host)
86    for i in info.keys(): iq.setTagData(i,info[i])
87    if sync:
88        resp=disp.SendAndWaitForResponse(iq)
89        _ReceivedRegInfo(disp.Dispatcher,resp, host)
90        return resp
91    else: disp.SendAndCallForResponse(iq,_ReceivedRegInfo, {'agent': host})
92
93def _ReceivedRegInfo(con, resp, agent):
94    iq=Iq('get',NS_REGISTER,to=agent)
95    if not isResultNode(resp): return
96    df=resp.getTag('query',namespace=NS_REGISTER).getTag('x',namespace=NS_DATA)
97    if df:
98        con.Event(NS_REGISTER,REGISTER_DATA_RECEIVED,(agent, DataForm(node=df)))
99        return
100    df=DataForm(typ='form')
101    for i in resp.getQueryPayload():
102        if type(i)<>type(iq): pass
103        elif i.getName()=='instructions': df.addInstructions(i.getData())
104        else: df.setField(i.getName()).setValue(i.getData())
105    con.Event(NS_REGISTER,REGISTER_DATA_RECEIVED,(agent, df))
106
107def register(disp,host,info):
108    """ Perform registration on remote server with provided info.
109        disp must be connected dispatcher instance.
110        Returns true or false depending on registration result.
111        If registration fails you can get additional info from the dispatcher's owner
112        attributes lastErrNode, lastErr and lastErrCode.
113    """
114    iq=Iq('set',NS_REGISTER,to=host)
115    if type(info)<>type({}): info=info.asDict()
116    for i in info.keys(): iq.setTag('query').setTagData(i,info[i])
117    resp=disp.SendAndWaitForResponse(iq)
118    if isResultNode(resp): return 1
119
120def unregister(disp,host):
121    """ Unregisters with host (permanently removes account).
122        disp must be connected and authorized dispatcher instance.
123        Returns true on success."""
124    resp=disp.SendAndWaitForResponse(Iq('set',NS_REGISTER,to=host,payload=[Node('remove')]))
125    if isResultNode(resp): return 1
126
127def changePasswordTo(disp,newpassword,host=None):
128    """ Changes password on specified or current (if not specified) server.
129        disp must be connected and authorized dispatcher instance.
130        Returns true on success."""
131    if not host: host=disp._owner.Server
132    resp=disp.SendAndWaitForResponse(Iq('set',NS_REGISTER,to=host,payload=[Node('username',payload=[disp._owner.Server]),Node('password',payload=[newpassword])]))
133    if isResultNode(resp): return 1
134
135### Privacy ### jabber:iq:privacy ### draft-ietf-xmpp-im-19 ####################
136#type=[jid|group|subscription]
137#action=[allow|deny]
138
139def getPrivacyLists(disp):
140    """ Requests privacy lists from connected server.
141        Returns dictionary of existing lists on success."""
142    try:
143        dict={'lists':[]}
144        resp=disp.SendAndWaitForResponse(Iq('get',NS_PRIVACY))
145        if not isResultNode(resp): return
146        for list in resp.getQueryPayload():
147            if list.getName()=='list': dict['lists'].append(list.getAttr('name'))
148            else: dict[list.getName()]=list.getAttr('name')
149        return dict
150    except: pass
151
152def getPrivacyList(disp,listname):
153    """ Requests specific privacy list listname. Returns list of XML nodes (rules)
154        taken from the server responce."""
155    try:
156        resp=disp.SendAndWaitForResponse(Iq('get',NS_PRIVACY,payload=[Node('list',{'name':listname})]))
157        if isResultNode(resp): return resp.getQueryPayload()[0]
158    except: pass
159
160def setActivePrivacyList(disp,listname=None,typ='active'):
161    """ Switches privacy list 'listname' to specified type.
162        By default the type is 'active'. Returns true on success."""
163    if listname: attrs={'name':listname}
164    else: attrs={}
165    resp=disp.SendAndWaitForResponse(Iq('set',NS_PRIVACY,payload=[Node(typ,attrs)]))
166    if isResultNode(resp): return 1
167
168def setDefaultPrivacyList(disp,listname=None):
169    """ Sets the default privacy list as 'listname'. Returns true on success."""
170    return setActivePrivacyList(disp,listname,'default')
171
172def setPrivacyList(disp,list):
173    """ Set the ruleset. 'list' should be the simpleXML node formatted
174        according to RFC 3921 (XMPP-IM) (I.e. Node('list',{'name':listname},payload=[...]) )
175        Returns true on success."""
176    resp=disp.SendAndWaitForResponse(Iq('set',NS_PRIVACY,payload=[list]))
177    if isResultNode(resp): return 1
178
179def delPrivacyList(disp,listname):
180    """ Deletes privacy list 'listname'. Returns true on success."""
181    resp=disp.SendAndWaitForResponse(Iq('set',NS_PRIVACY,payload=[Node('list',{'name':listname})]))
182    if isResultNode(resp): return 1
Note: See TracBrowser for help on using the browser.