]> git.pld-linux.org Git - packages/gajim.git/blame - gajim-remote.patch
- 0.8.1
[packages/gajim.git] / gajim-remote.patch
CommitLineData
b656cd37 1diff -urN gajim-0.8.orig/scripts/gajim-remote gajim-0.8/scripts/gajim-remote
2--- gajim-0.8.orig/scripts/gajim-remote 2005-08-19 12:58:20.182083440 +0200
3+++ gajim-0.8/scripts/gajim-remote 2005-08-19 12:59:44.453272272 +0200
4@@ -22,6 +22,6 @@
5 echo "You must not launch gajim-remote as root, it is INSECURE"
6 fi
7
8-cd PREFIX/share/gajim/scripts
9+cd PREFIX/share/gajim/src
10 export PYTHONPATH="$PYTHONPATH:PREFIXLIB/gajim"
11 python gajim-remote.py $@
12diff -urN gajim-0.8.orig/src/gajim-remote.py gajim-0.8/src/gajim-remote.py
13--- gajim-0.8.orig/src/gajim-remote.py 1970-01-01 01:00:00.000000000 +0100
14+++ gajim-0.8/src/gajim-remote.py 2005-08-19 12:47:58.598578496 +0200
15@@ -0,0 +1,493 @@
16+#!/bin/sh
17+''':'
18+exec python -OOt "$0" ${1+"$@"}
19+' '''
20+## scripts/gajim-remote.py
21+##
22+## Gajim Team:
23+## - Yann Le Boulanger <asterix@lagaule.org>
24+## - Vincent Hanquez <tab@snarc.org>
25+## - Nikos Kouremenos <kourem@gmail.com>
26+## - Dimitur Kirov <dkirov@gmail.com>
27+##
28+## Copyright (C) 2003-2005 Gajim Team
29+##
30+## This program is free software; you can redistribute it and/or modify
31+## it under the terms of the GNU General Public License as published
32+## by the Free Software Foundation; version 2 only.
33+##
34+## This program is distributed in the hope that it will be useful,
35+## but WITHOUT ANY WARRANTY; without even the implied warranty of
36+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
37+## GNU General Public License for more details.
38+##
39+
40+# gajim-remote help will show you the DBUS API of Gajim
41+
42+import sys
43+import gtk
44+import gobject
45+
46+import signal
47+
48+signal.signal(signal.SIGINT, signal.SIG_DFL) # ^C exits the application
49+
50+import i18n
51+
52+_ = i18n._
53+i18n.init()
54+
55+
56+try:
57+ import dbus
58+except:
59+ send_error('Dbus is not supported.\n')
60+
61+_version = getattr(dbus, 'version', (0, 20, 0))
62+if _version[1] >= 41:
63+ import dbus.service
64+ import dbus.glib
65+
66+OBJ_PATH = '/org/gajim/dbus/RemoteObject'
67+INTERFACE = 'org.gajim.dbus.RemoteInterface'
68+SERVICE = 'org.gajim.dbus'
69+BASENAME = 'gajim-remote'
70+
71+class GajimRemote:
72+
73+ def __init__(self):
74+ self.argv_len = len(sys.argv)
75+ # define commands dict. Prototype :
76+ # {
77+ # 'command': [comment, [list of arguments] ]
78+ # }
79+ #
80+ # each argument is defined as a tuple:
81+ # (argument name, help on argument, is mandatory)
82+ #
83+ self.commands = {
84+ 'help':[
85+ _('show a help on specific command'),
86+ [
87+ #parameter, named "on_command". User gets help for the command, specified by this parameter
88+ (_('on_command'),
89+ _('show help on command'), False)
90+ ]
91+ ],
92+ 'toggle_roster_appearance' : [
93+ _('Shows or hides the roster window'),
94+ []
95+ ],
96+ 'show_next_unread': [
97+ _('Popup a window with the next unread message'),
98+ []
99+ ],
100+ 'list_contacts': [
101+ _('Print a list of all contacts in the roster. \
102+Each contact appear on a separate line'),
103+ [
104+ (_('account'), _('show only contacts of the \
105+given account'), False)
106+ ]
107+
108+ ],
109+ 'list_accounts': [
110+ _('Print a list of registered accounts'),
111+ []
112+ ],
113+ 'change_status': [
114+ _('Change the status of account or accounts'),
115+ [
116+ (_('status'), _('one of: offline, online, chat, away, \
117+xa, dnd, invisible '), True),
118+ (_('message'), _('status message'), False),
119+ (_('account'), _('change status of account "account". \
120+If not specified, try to change status of all accounts that \
121+have "sync with global status" option set'), False)
122+ ]
123+ ],
124+ 'open_chat': [
125+ _('Show the chat dialog so that you can send message to a \
126+contact'),
127+ [
128+ #tell nkour that should be JID of the contact
129+ ('jid', _('jid of the contact that you want to chat \
130+with'),
131+ True),
132+ (_('account'), _('if specified, contact is taken from \
133+the contact list of this account'), False)
134+ ]
135+ ],
136+ 'send_message':[
137+ #OpenPGP key here too (tlel that to nkour)
138+ _('Send new message to a contact in the roster. Both OpenPGP \
139+key and account are optional. If you want to set only \'account\', without \
140+\'pgp key\', just set \'pgp key\' to \'\'.'),
141+ [
142+ #tell nkour that should be JID of the contact
143+ ('jid', _('jid of the contact that will receive the \
144+message'), True),
145+ (_('message'), _('message contents'), True),
146+ #tell to nkour it should be OpenPGP key
147+ (_('pgp key'), _('if specified, the message will be \
148+encrypted using this public key'), False),
149+ (_('account'), _('if specified, the message will be \
150+sent using this account'), False),
151+ ]
152+ ],
153+ 'contact_info': [
154+ _('Get detailed info on a contact'),
155+ [
156+ #JID of the contact (tell that to nkour)
157+ ('jid', _('jid of the contact'), True)
158+ ]
159+ ]
160+ }
161+ if self.argv_len < 2 or \
162+ sys.argv[1] not in self.commands.keys(): # no args or bad args
163+ self.send_error(self.compose_help())
164+ self.command = sys.argv[1]
165+
166+ if self.command == 'help':
167+ if self.argv_len == 3:
168+ print self.help_on_command(sys.argv[2])
169+ else:
170+ print self.compose_help()
171+ sys.exit()
172+
173+ self.init_connection()
174+ self.check_arguments()
175+
176+ if self.command == 'contact_info':
177+ if self.argv_len < 3:
178+ self.send_error(_('Missing argument "contact_jid"'))
179+ try:
180+ id = self.sbus.add_signal_receiver(self.show_vcard_info,
181+ 'VcardInfo', INTERFACE, SERVICE, OBJ_PATH)
182+ except:
183+ self.send_error(_('Service not available'))
184+
185+ res = self.call_remote_method()
186+ self.print_result(res)
187+
188+ if self.command == 'contact_info':
189+ gobject.timeout_add(10000, self.gtk_quit) # wait 10 sec for response
190+ gtk.main()
191+
192+ def print_result(self, res):
193+ ''' Print retrieved result to the output '''
194+ if res is not None:
195+ if self.command in ['open_chat', 'send_message']:
196+ if self.command == 'send_message':
197+ self.argv_len -= 2
198+
199+ if res == False:
200+ if self.argv_len < 4:
201+ self.send_error(_('\'%s\' is not in your roster.\n\
202+Please specify account for sending the message.') % sys.argv[2])
203+ else:
204+ self.send_error(_('You have no active account'))
205+ elif self.command == 'list_accounts':
206+ if type(res) == list:
207+ for account in res:
208+ print account
209+ elif self.command == 'list_contacts':
210+ for single_res in res:
211+ accounts = self.unrepr(single_res)
212+ for account_dict in accounts:
213+ print self.print_info(0, account_dict)
214+ elif res:
215+ print res
216+
217+ def init_connection(self):
218+ ''' create the onnection to the session dbus,
219+ or exit if it is not possible '''
220+ try:
221+ self.sbus = dbus.SessionBus()
222+ except:
223+ self.send_error(_('Session bus is not available.'))
224+
225+ if _version[1] >= 30 and _version[1] <= 42:
226+ obj = self.sbus.get_object(SERVICE, OBJ_PATH)
227+ interface = dbus.Interface(obj, INTERFACE)
228+ elif _version[1] < 30:
229+ self.service = self.sbus.get_service(SERVICE)
230+ interface = self.service.get_object(OBJ_PATH, INTERFACE)
231+ else:
232+ #say to nkour that this should be Unknown D-Bus version: %s (thanks nebulam)
233+ send_error(_('Unknown dbus version: %s') % _version)
234+
235+ # get the function asked
236+ self.method = interface.__getattr__(self.command)
237+
238+ def make_arguments_row(self, args):
239+ ''' return arguments list. Mandatory arguments are enclosed with:
240+ '<', '>', optional arguments - with '[', ']' '''
241+ str = ''
242+ for argument in args:
243+ str += ' '
244+ if argument[2]:
245+ str += '<'
246+ else:
247+ str += '['
248+ str += argument[0]
249+ if argument[2]:
250+ str += '>'
251+ else:
252+ str += ']'
253+ return str
254+
255+ def help_on_command(self, command):
256+ ''' return help message for a given command '''
257+ if command in self.commands:
258+ command_props = self.commands[command]
259+ arguments_str = self.make_arguments_row(command_props[1])
260+ str = _('Usage: %s %s %s \n\t') % (BASENAME, command,
261+ arguments_str)
262+ str += command_props[0] + '\n\n' + _('Arguments:') + '\n'
263+ for argument in command_props[1]:
264+ str += ' ' + argument[0] + ' - ' + argument[1] + '\n'
265+ return str
266+ self.send_error(_('%s not found') % command)
267+
268+ def compose_help(self):
269+ ''' print usage, and list available commands '''
270+ str = _('Usage: %s command [arguments]\nCommand is one of:\n' ) % BASENAME
271+ for command in self.commands.keys():
272+ str += ' ' + command
273+ for argument in self.commands[command][1]:
274+ str += ' '
275+ if argument[2]:
276+ str += '<'
277+ else:
278+ str += '['
279+ str += argument[0]
280+ if argument[2]:
281+ str += '>'
282+ else:
283+ str += ']'
284+ str += '\n'
285+ return str
286+
287+ def print_info(self, level, prop_dict):
288+ ''' return formated string from serialized vcard data '''
289+ if prop_dict is None or type(prop_dict) \
290+ not in [dict, list, tuple]:
291+ return ''
292+ ret_str = ''
293+ if type(prop_dict) in [list, tuple]:
294+ ret_str = ''
295+ spacing = ' ' * level * 4
296+ for val in prop_dict:
297+ if val is None:
298+ ret_str +='\t'
299+ elif type(val) == unicode or type(val) == int or \
300+ type(val) == str:
301+ ret_str +='\t' + str(val)
302+ elif type(val) == list or type(val) == tuple:
303+ res = ''
304+ for items in val:
305+ res += self.print_info(level+1, items)
306+ if res != '':
307+ ret_str += '\t' + res
308+ ret_str = '%s(%s)\n' % (spacing, ret_str[1:])
309+ elif type(prop_dict) is dict:
310+ for key in prop_dict.keys():
311+ val = prop_dict[key]
312+ spacing = ' ' * level * 4
313+ if type(val) == unicode or type(val) == int or \
314+ type(val) == str:
315+ if val is not None:
316+ val = val.strip()
317+ ret_str += '%s%-10s: %s\n' % (spacing, key, val)
318+ elif type(val) == list or type(val) == tuple:
319+ res = ''
320+ for items in val:
321+ res += self.print_info(level+1, items)
322+ if res != '':
323+ ret_str += '%s%s: \n%s' % (spacing, key, res)
324+ elif type(val) == dict:
325+ res = self.print_info(level+1, val)
326+ if res != '':
327+ ret_str += '%s%s: \n%s' % (spacing, key, res)
328+ else:
329+ self.send_warning(_('Unknown type %s ') % type(val))
330+ return ret_str
331+
332+ def unrepr(self, serialized_data):
333+ ''' works the same as eval, but only for structural values,
334+ not functions! e.g. dicts, lists, strings, tuples '''
335+ if not serialized_data:
336+ return (None, '')
337+ value = serialized_data.strip()
338+ first_char = value[0]
339+ is_unicode = False
340+ is_int = False
341+
342+ if first_char == 'u':
343+ is_unicode = True
344+ value = value[1:]
345+ first_char = value[0]
346+ elif '0123456789.'.find(first_char) != -1:
347+ is_int = True
348+ _str = first_char
349+ if first_char == '.':
350+ is_float = True
351+ else:
352+ is_float = False
353+ for i in range(len(value) - 1):
354+ chr = value[i+1]
355+ if chr == '.':
356+ is_float = True
357+ elif '0123456789'.find(chr) == -1:
358+ break
359+ _str += chr
360+ if is_float:
361+ return (float(_str), value[len(_str):])
362+ else:
363+ return (int(_str), value[len(_str):])
364+ elif first_char == 'N':
365+ if value[1:4] == 'one':
366+ return (None, value[4:])
367+ else:
368+ return (None, '')
369+ if first_char == "'" or first_char == '"': # handle strings and unicode
370+ if len(value) < 2:
371+ return ('',value[1:])
372+ _str = ''
373+ previous_slash = False
374+ for i in range(len(value) - 1):
375+ chr = value[i+1]
376+ if previous_slash:
377+ previous_slash = False
378+ if chr == '\\':
379+ _str += '\\'
380+ elif chr == 'n':
381+ _str += '\n'
382+ elif chr == 't':
383+ _str += '\t'
384+ elif chr == 'r':
385+ _str += '\r'
386+ elif chr == 'b':
387+ _str += '\b'
388+ elif chr == '\'':
389+ _str += '\''
390+ elif chr == '\"':
391+ _str += '\"'
392+ elif chr == 'u' and is_unicode:
393+ _str += '\\u'
394+ elif chr == first_char:
395+ break
396+ elif chr == '\\':
397+ previous_slash = True
398+ else:
399+ _str += chr
400+ substr_len = len(_str)+2
401+ if is_unicode and _str:
402+ _str = _str.decode('unicode-escape').encode('utf-8')
403+ return (_str, value[substr_len :])
404+ elif first_char == '{': # dict
405+ _dict = {}
406+ while True:
407+ if value[1] == '}':
408+ break
409+ key, next = self.unrepr(value[1:])
410+ if type(key) != str and type(key) != unicode:
411+ send_error('Wrong string: %s' % value)
412+ next = next.strip()
413+ if not next or next[0] != ':':
414+ send_error('Wrong string: %s' % (value))
415+ val, next = self.unrepr(next[1:])
416+ _dict[key] = val
417+ next = next.strip()
418+ if not next:
419+ break
420+ if next[0] == ',':
421+ value = next
422+ elif next[0] == '}':
423+ break
424+ else:
425+ break
426+ return (_dict, next[1:])
427+ elif first_char in ['[', '(']: # return list
428+ _tuple = []
429+ while True:
430+ if value[1] == ']':
431+ break
432+ val, next = self.unrepr(value[1:])
433+ next = next.strip()
434+ if not next:
435+ send_error('Wrong string: %s' % val)
436+ _tuple.append(val)
437+ next = next.strip()
438+ if not next:
439+ break
440+ if next[0] == ',':
441+ value = next
442+ elif next[0] in [']', ')']:
443+ break
444+ return (_tuple, next[1:])
445+
446+ def show_vcard_info(self, *args, **keyword):
447+ ''' write user vcart in a formated output '''
448+ props_dict = None
449+ if _version[1] >= 30:
450+ props_dict = self.unrepr(args[0])
451+ else:
452+ if args and len(args) >= 5:
453+ props_dict = self.unrepr(args[4].get_args_list()[0])
454+
455+ if props_dict:
456+ print self.print_info(0,props_dict[0])
457+ # remove_signal_receiver is broken in lower versions (< 0.35),
458+ # so we leave the leak - nothing can be done
459+ if _version[1] >= 41:
460+ self.sbus.remove_signal_receiver(show_vcard_info, 'VcardInfo',
461+ INTERFACE, SERVICE, OBJ_PATH)
462+
463+ gtk.main_quit()
464+
465+ def check_arguments(self):
466+ ''' Make check if all necessary arguments are given '''
467+ argv_len = self.argv_len - 2
468+ args = self.commands[self.command][1]
469+ if len(args) > argv_len:
470+ if args[argv_len][2]:
471+ self.send_error(_('Argument "%s" is not specified. \n\
472+Type "%s help %s" for more info') % (args[argv_len][0], BASENAME, self.command))
473+
474+ def gtk_quit(self):
475+ if _version[1] >= 41:
476+ self.sbus.remove_signal_receiver(show_vcard_info, 'VcardInfo',
477+ INTERFACE, SERVICE, OBJ_PATH)
478+ gtk.main_quit()
479+
480+ # FIXME - didn't find more clever way for the below method.
481+ # method(sys.argv[2:]) doesn't work, cos sys.argv[2:] is a tuple
482+ def call_remote_method(self):
483+ ''' calls self.method with arguments from sys.argv[2:] '''
484+ try:
485+ if self.argv_len == 2:
486+ res = self.method()
487+ elif self.argv_len == 3:
488+ res = self.method(sys.argv[2])
489+ elif self.argv_len == 4:
490+ res = self.method(sys.argv[2], sys.argv[3])
491+ elif self.argv_len == 5:
492+ res = self.method(sys.argv[2], sys.argv[3], sys.argv[4])
493+ elif argv_len == 6:
494+ res = self.method(sys.argv[2], sys.argv[3], sys.argv[4],
495+ sys.argv[5])
496+ return res
497+ except:
498+ self.send_error(_('Service not available'))
499+ return None
500+
501+ def send_error(self, error_message):
502+ ''' Writes error message to stderr and exits '''
503+ sys.stderr.write(error_message + '\n')
504+ sys.stderr.flush()
505+ sys.exit(1)
506+
507+if __name__ == '__main__':
508+ GajimRemote()
509diff -urN gajim-0.8.orig/src/i18n.py gajim-0.8/src/i18n.py
510--- gajim-0.8.orig/src/i18n.py 1970-01-01 01:00:00.000000000 +0100
511+++ gajim-0.8/src/i18n.py 2005-08-19 13:05:59.485258744 +0200
512@@ -0,0 +1,41 @@
513+## common/i18n.py
514+##
515+## Gajim Team:
516+## - Yann Le Boulanger <asterix@lagaule.org>
517+## - Vincent Hanquez <tab@snarc.org>
518+## - Nikos Kouremenos <kourem@gmail.com>
519+## - Dimitur Kirov <dkirov@gmail.com>
520+##
521+## Copyright (C) 2003-2005 Gajim Team
522+##
523+## This program is free software; you can redistribute it and/or modify
524+## it under the terms of the GNU General Public License as published
525+## by the Free Software Foundation; version 2 only.
526+##
527+## This program is distributed in the hope that it will be useful,
528+## but WITHOUT ANY WARRANTY; without even the implied warranty of
529+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
530+## GNU General Public License for more details.
531+##
532+
533+APP='gajim'
534+DIR='../po'
535+
536+import locale
537+import gettext
538+
539+locale.setlocale(locale.LC_ALL, '')
540+_translation = None
541+
542+def init():
543+ global _translation
544+ try:
545+ _translation = gettext.translation(APP, DIR)
546+ except IOError:
547+ _translation = gettext.NullTranslations()
548+
549+def _(s):
550+ if s == '':
551+ return s
552+ assert s
553+ return _translation.gettext(s)
This page took 0.105127 seconds and 4 git commands to generate.