revert thorstenp patches for now. They introduce bugs.

This commit is contained in:
Yann Leboulanger 2008-10-20 21:38:06 +00:00
parent f801a50260
commit 06ab4a7b6d
75 changed files with 592 additions and 486 deletions

View file

@ -46,7 +46,8 @@ from message_control import MessageControl
from conversation_textview import ConversationTextview from conversation_textview import ConversationTextview
from message_textview import MessageTextView from message_textview import MessageTextView
from common.contacts import GC_Contact from common.contacts import GC_Contact
from common.logger import constants from common.logger import Constants
constants = Constants()
from common.rst_xhtml_generator import create_xhtml from common.rst_xhtml_generator import create_xhtml
from common.pep import MOODS, ACTIVITIES from common.pep import MOODS, ACTIVITIES
from common.xmpp.protocol import NS_XHTML, NS_FILE, NS_MUC, NS_RECEIPTS from common.xmpp.protocol import NS_XHTML, NS_FILE, NS_MUC, NS_RECEIPTS
@ -151,7 +152,7 @@ class ChatControlBase(MessageControl):
contact = c contact = c
MessageControl.__init__(self, type_id, parent_win, widget_name, MessageControl.__init__(self, type_id, parent_win, widget_name,
contact, acct, resource = resource) contact, acct, resource = resource);
widget = self.xml.get_widget('history_button') widget = self.xml.get_widget('history_button')
id = widget.connect('clicked', self._on_history_menuitem_activate) id = widget.connect('clicked', self._on_history_menuitem_activate)
@ -294,7 +295,7 @@ class ChatControlBase(MessageControl):
if lang: if lang:
self.msg_textview.lang = lang self.msg_textview.lang = lang
spell.set_language(lang) spell.set_language(lang)
except (gobject.GError, RuntimeError): except (gobject.GError, RuntimeError), msg:
dialogs.AspellDictError(lang) dialogs.AspellDictError(lang)
self.conv_textview.tv.show() self.conv_textview.tv.show()
self._paint_banner() self._paint_banner()
@ -434,6 +435,7 @@ class ChatControlBase(MessageControl):
def show_emoticons_menu(self): def show_emoticons_menu(self):
if not gajim.config.get('emoticons_theme'): if not gajim.config.get('emoticons_theme'):
return return
msg_tv = self.msg_textview
def set_emoticons_menu_position(w, msg_tv = self.msg_textview): def set_emoticons_menu_position(w, msg_tv = self.msg_textview):
window = msg_tv.get_window(gtk.TEXT_WINDOW_WIDGET) window = msg_tv.get_window(gtk.TEXT_WINDOW_WIDGET)
# get the window position # get the window position
@ -447,7 +449,7 @@ class ChatControlBase(MessageControl):
cursor.x, cursor.y) cursor.x, cursor.y)
x = origin[0] + cursor[0] x = origin[0] + cursor[0]
y = origin[1] + size[1] y = origin[1] + size[1]
menu_height = gajim.interface.emoticons_menu.size_request()[1] menu_width, menu_height = gajim.interface.emoticons_menu.size_request()
#FIXME: get_line_count is not so good #FIXME: get_line_count is not so good
#get the iter of cursor, then tv.get_line_yrange #get the iter of cursor, then tv.get_line_yrange
# so we know in which y we are typing (not how many lines we have # so we know in which y we are typing (not how many lines we have
@ -954,7 +956,7 @@ class ChatControlBase(MessageControl):
conv_buf.set_text(self.sent_history[self.sent_history_pos]) conv_buf.set_text(self.sent_history[self.sent_history_pos])
elif direction == 'down': elif direction == 'down':
if self.sent_history_pos >= size - 1: if self.sent_history_pos >= size - 1:
conv_buf.set_text(self.orig_msg) conv_buf.set_text(self.orig_msg);
self.orig_msg = None self.orig_msg = None
self.sent_history_pos = size self.sent_history_pos = size
return return
@ -1118,7 +1120,7 @@ class ChatControl(ChatControlBase):
if session: if session:
# Don't use previous session if we want to a specific resource # Don't use previous session if we want to a specific resource
# and it's not the same # and it's not the same
r = gajim.get_room_and_nick_from_fjid(str(session.jid))[1] j, r = gajim.get_room_and_nick_from_fjid(str(session.jid))
if resource and resource != r: if resource and resource != r:
session = None session = None
@ -1424,6 +1426,7 @@ class ChatControl(ChatControlBase):
banner_name_label = self.xml.get_widget('banner_name_label') banner_name_label = self.xml.get_widget('banner_name_label')
banner_name_tooltip = gtk.Tooltips() banner_name_tooltip = gtk.Tooltips()
banner_eventbox = self.xml.get_widget('banner_eventbox')
name = contact.get_shown_name() name = contact.get_shown_name()
if self.resource: if self.resource:
@ -1825,6 +1828,7 @@ class ChatControl(ChatControlBase):
if contact is set to print_queue: it is incomming from queue if contact is set to print_queue: it is incomming from queue
if contact is not set: it's an incomming message''' if contact is not set: it's an incomming message'''
contact = self.contact contact = self.contact
jid = contact.jid
if frm == 'status': if frm == 'status':
if not gajim.config.get('print_status_in_chats'): if not gajim.config.get('print_status_in_chats'):
@ -2212,7 +2216,7 @@ class ChatControl(ChatControlBase):
def on_cancel(): def on_cancel():
on_no(self) on_no(self)
dialogs.ConfirmationDialog( dialog = dialogs.ConfirmationDialog(
# %s is being replaced in the code with JID # %s is being replaced in the code with JID
_('You just received a new message from "%s"') % self.contact.jid, _('You just received a new message from "%s"') % self.contact.jid,
_('If you close this tab and you have history disabled, '\ _('If you close this tab and you have history disabled, '\
@ -2303,6 +2307,7 @@ class ChatControl(ChatControlBase):
path = treeview.get_selection().get_selected_rows()[1][0] path = treeview.get_selection().get_selected_rows()[1][0]
iter = model.get_iter(path) iter = model.get_iter(path)
type = model[iter][2] type = model[iter][2]
account = model[iter][4].decode('utf-8')
if type != 'contact': # source is not a contact if type != 'contact': # source is not a contact
return return
dropped_jid = data.decode('utf-8') dropped_jid = data.decode('utf-8')
@ -2365,7 +2370,7 @@ class ChatControl(ChatControlBase):
pending_how_many, timeout, self.account) pending_how_many, timeout, self.account)
except exceptions.DatabaseMalformed: except exceptions.DatabaseMalformed:
dialogs.ErrorDialog(_('Database Error'), dialogs.ErrorDialog(_('Database Error'),
_('The database file (%s) cannot be read. Try to repair it or remove it (all history will be lost).') % constants.LOG_DB_PATH) _('The database file (%s) cannot be read. Try to repair it or remove it (all history will be lost).') % common.logger.LOG_DB_PATH)
rows = [] rows = []
local_old_kind = None local_old_kind = None
for row in rows: # row[0] time, row[1] has kind, row[2] the message for row in rows: # row[0] time, row[1] has kind, row[2] the message

View file

@ -182,9 +182,6 @@ if gajim.HAVE_GPG:
output = proc.handles['stdout'].read() output = proc.handles['stdout'].read()
proc.handles['stdout'].close() proc.handles['stdout'].close()
try: proc.wait()
except IOError: pass
keys = {} keys = {}
lines = output.split('\n') lines = output.split('\n')
for line in lines: for line in lines:
@ -196,6 +193,8 @@ if gajim.HAVE_GPG:
# make it unicode instance # make it unicode instance
keys[sline[4][8:]] = helpers.decode_string(name) keys[sline[4][8:]] = helpers.decode_string(name)
return keys return keys
try: proc.wait()
except IOError: pass
def get_secret_keys(self): def get_secret_keys(self):
return self.get_keys(True) return self.get_keys(True)

View file

@ -24,6 +24,7 @@
## ##
from itertools import * from itertools import *
import xmpp
import xmpp.features_nb import xmpp.features_nb
import gajim import gajim
import helpers import helpers
@ -145,7 +146,7 @@ class CapsCache(object):
# prepopulate data which we are sure of; note: we do not log these info # prepopulate data which we are sure of; note: we do not log these info
for account in gajim.connections: for account in gajim.connections:
gajimcaps = self[('sha-1', gajim.caps_hash[account])] gajimcaps = self[('sha-1', gajim.caps_hash[accout])]
gajimcaps.identities = [gajim.gajim_identity] gajimcaps.identities = [gajim.gajim_identity]
gajimcaps.features = gajim.gajim_common_features + \ gajimcaps.features = gajim.gajim_common_features + \
gajim.gajim_optional_features[account] gajim.gajim_optional_features[account]

View file

@ -27,7 +27,6 @@ import os
import sys import sys
import stat import stat
import exceptions
from common import gajim from common import gajim
import logger import logger

View file

@ -71,7 +71,7 @@ class AdHocCommand:
' bad-request')) ' bad-request'))
def cancel(self, request): def cancel(self, request):
response = self.buildResponse(request, status = 'canceled')[0] response, cmd = self.buildResponse(request, status = 'canceled')
self.connection.connection.send(response) self.connection.connection.send(response)
return False # finish the session return False # finish the session

View file

@ -415,6 +415,7 @@ class Connection(ConnectionHandlers):
if data: if data:
hostname = data['hostname'] hostname = data['hostname']
usessl = data['usessl']
self.try_connecting_for_foo_secs = 45 self.try_connecting_for_foo_secs = 45
p = data['proxy'] p = data['proxy']
use_srv = True use_srv = True
@ -960,6 +961,7 @@ class Connection(ConnectionHandlers):
sshow = helpers.get_xmpp_show(show) sshow = helpers.get_xmpp_show(show)
if not msg: if not msg:
msg = '' msg = ''
keyID = gajim.config.get_per('accounts', self.name, 'keyid')
if show == 'offline': if show == 'offline':
p = common.xmpp.Presence(typ = 'unavailable', to = jid) p = common.xmpp.Presence(typ = 'unavailable', to = jid)
p = self.add_sha(p, False) p = self.add_sha(p, False)
@ -983,6 +985,7 @@ class Connection(ConnectionHandlers):
sshow = helpers.get_xmpp_show(show) sshow = helpers.get_xmpp_show(show)
if not msg: if not msg:
msg = '' msg = ''
keyID = gajim.config.get_per('accounts', self.name, 'keyid')
sign_msg = False sign_msg = False
if not auto and not show == 'offline': if not auto and not show == 'offline':
sign_msg = True sign_msg = True
@ -1396,7 +1399,7 @@ class Connection(ConnectionHandlers):
return return
iq = common.xmpp.Iq(typ='get') iq = common.xmpp.Iq(typ='get')
iq2 = iq.addChild(name='query', namespace=common.xmpp.NS_PRIVATE) iq2 = iq.addChild(name='query', namespace=common.xmpp.NS_PRIVATE)
iq2.addChild(name='gajim', namespace='gajim:prefs') iq3 = iq2.addChild(name='gajim', namespace='gajim:prefs')
self.connection.send(iq) self.connection.send(iq)
def get_bookmarks(self): def get_bookmarks(self):
@ -1426,11 +1429,11 @@ class Connection(ConnectionHandlers):
# Note: need to handle both None and '' as empty # Note: need to handle both None and '' as empty
# thus shouldn't use "is not None" # thus shouldn't use "is not None"
if bm.get('nick', None): if bm.get('nick', None):
iq4.setTagData('nick', bm['nick']) iq5 = iq4.setTagData('nick', bm['nick'])
if bm.get('password', None): if bm.get('password', None):
iq4.setTagData('password', bm['password']) iq5 = iq4.setTagData('password', bm['password'])
if bm.get('print_status', None): if bm.get('print_status', None):
iq4.setTagData('print_status', bm['print_status']) iq5 = iq4.setTagData('print_status', bm['print_status'])
self.connection.send(iq) self.connection.send(iq)
def get_annotations(self): def get_annotations(self):
@ -1701,7 +1704,7 @@ class Connection(ConnectionHandlers):
if gajim.account_is_connected(self.name): if gajim.account_is_connected(self.name):
hostname = gajim.config.get_per('accounts', self.name, 'hostname') hostname = gajim.config.get_per('accounts', self.name, 'hostname')
iq = common.xmpp.Iq(typ = 'set', to = hostname) iq = common.xmpp.Iq(typ = 'set', to = hostname)
iq.setTag(common.xmpp.NS_REGISTER + ' query').setTag('remove') q = iq.setTag(common.xmpp.NS_REGISTER + ' query').setTag('remove')
con.send(iq) con.send(iq)
on_remove_success(True) on_remove_success(True)
return return

View file

@ -764,6 +764,7 @@ class ConnectionDisco:
if node: if node:
q.setAttr('node', node) q.setAttr('node', node)
q.addChild('identity', attrs = gajim.gajim_identity) q.addChild('identity', attrs = gajim.gajim_identity)
extension = None
if node and node.find('#') != -1: if node and node.find('#') != -1:
extension = node[node.index('#') + 1:] extension = node[node.index('#') + 1:]
client_version = 'http://gajim.org#' + gajim.caps_hash[self.name] client_version = 'http://gajim.org#' + gajim.caps_hash[self.name]
@ -979,7 +980,7 @@ class ConnectionVcard:
j = gajim.get_jid_from_account(self.name) j = gajim.get_jid_from_account(self.name)
self.awaiting_answers[id] = (VCARD_ARRIVED, j, groupchat_jid) self.awaiting_answers[id] = (VCARD_ARRIVED, j, groupchat_jid)
if groupchat_jid: if groupchat_jid:
room_jid = gajim.get_room_and_nick_from_fjid(groupchat_jid)[0] room_jid, nick = gajim.get_room_and_nick_from_fjid(groupchat_jid)
if not room_jid in self.room_jids: if not room_jid in self.room_jids:
self.room_jids.append(room_jid) self.room_jids.append(room_jid)
self.groupchat_jids[id] = groupchat_jid self.groupchat_jids[id] = groupchat_jid
@ -1388,7 +1389,6 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco,
try: try:
idle.init() idle.init()
except Exception: except Exception:
global HAS_IDLE
HAS_IDLE = False HAS_IDLE = False
self.gmail_last_tid = None self.gmail_last_tid = None
@ -1414,7 +1414,7 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco,
method = iq_obj.getTagAttr('confirm', 'method') method = iq_obj.getTagAttr('confirm', 'method')
url = iq_obj.getTagAttr('confirm', 'url') url = iq_obj.getTagAttr('confirm', 'url')
msg = iq_obj.getTagData('body') # In case it's a message with a body msg = iq_obj.getTagData('body') # In case it's a message with a body
self.dispatch('HTTP_AUTH', (method, url, id, iq_obj, msg)) self.dispatch('HTTP_AUTH', (method, url, id, iq_obj, msg));
raise common.xmpp.NodeProcessed raise common.xmpp.NodeProcessed
def _ErrorCB(self, con, iq_obj): def _ErrorCB(self, con, iq_obj):
@ -1518,7 +1518,7 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco,
iq_obj = iq_obj.buildReply('result') iq_obj = iq_obj.buildReply('result')
qp = iq_obj.getTag('query') qp = iq_obj.getTag('query')
if not HAS_IDLE: if not HAS_IDLE:
qp.attrs['seconds'] = '0' qp.attrs['seconds'] = '0';
else: else:
qp.attrs['seconds'] = idle.getIdleSec() qp.attrs['seconds'] = idle.getIdleSec()

View file

@ -23,6 +23,8 @@
## along with Gajim. If not, see <http://www.gnu.org/licenses/>. ## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
## ##
import re
docdir = '../' docdir = '../'
datadir = '../' datadir = '../'

View file

@ -256,11 +256,12 @@ def get_resource_from_jid(jid):
return jids[1] # abc@doremi.org/res/res-continued return jids[1] # abc@doremi.org/res/res-continued
else: else:
return '' return ''
'''\
# [15:34:28] <asterix> we should add contact.fake_jid I think [15:34:28] <asterix> we should add contact.fake_jid I think
# [15:34:46] <asterix> so if we know real jid, it wil be in contact.jid, or we look in contact.fake_jid [15:34:46] <asterix> so if we know real jid, it wil be in contact.jid, or we look in contact.fake_jid
# [15:32:54] <asterix> they can have resource if we know the real jid [15:32:54] <asterix> they can have resource if we know the real jid
# [15:33:07] <asterix> and that resource is in contact.resource [15:33:07] <asterix> and that resource is in contact.resource
'''
def get_number_of_accounts(): def get_number_of_accounts():
'''returns the number of ALL accounts''' '''returns the number of ALL accounts'''

View file

@ -847,6 +847,7 @@ def sanitize_filename(filename):
.replace('*', '_').replace('<', '_').replace('>', '_') .replace('*', '_').replace('<', '_').replace('>', '_')
# 48 is the limit # 48 is the limit
if len(filename) > 48: if len(filename) > 48:
extension = filename.split('.')[-1]
filename = filename[0:48] filename = filename[0:48]
return filename return filename
@ -1026,7 +1027,7 @@ def get_notification_icon_tooltip_dict():
def get_notification_icon_tooltip_text(): def get_notification_icon_tooltip_text():
text = None text = None
# How many events must there be before they're shown summarized, not per-user # How many events must there be before they're shown summarized, not per-user
# max_ungrouped_events = 10 max_ungrouped_events = 10
# Character which should be used to indent in the tooltip. # Character which should be used to indent in the tooltip.
indent_with = ' ' indent_with = ' '

View file

@ -178,7 +178,7 @@ class Logger:
and after that all okay''' and after that all okay'''
if jid.find('/') > -1: if jid.find('/') > -1:
possible_room_jid = jid.split('/', 1)[1] possible_room_jid, possible_nick = jid.split('/', 1)
return self.jid_is_room_jid(possible_room_jid) return self.jid_is_room_jid(possible_room_jid)
else: else:
# it's not a full jid, so it's not a pm one # it's not a full jid, so it's not a pm one
@ -466,6 +466,7 @@ class Logger:
and are already logged but pending to be viewed, and are already logged but pending to be viewed,
returns a list of tupples containg time, kind, message, returns a list of tupples containg time, kind, message,
list with empty tupple if nothing found to meet our demands''' list with empty tupple if nothing found to meet our demands'''
jid_id = self.get_jid_id(jid)
where_sql = self._build_contact_where(account, jid) where_sql = self._build_contact_where(account, jid)
now = int(float(time.time())) now = int(float(time.time()))
@ -503,6 +504,7 @@ class Logger:
'''returns contact_name, time, kind, show, message '''returns contact_name, time, kind, show, message
for each row in a list of tupples, for each row in a list of tupples,
returns list with empty tupple if we found nothing to meet our demands''' returns list with empty tupple if we found nothing to meet our demands'''
jid_id = self.get_jid_id(jid)
where_sql = self._build_contact_where(account, jid) where_sql = self._build_contact_where(account, jid)
start_of_day = self.get_unix_time_from_date(year, month, day) start_of_day = self.get_unix_time_from_date(year, month, day)
@ -523,6 +525,7 @@ class Logger:
'''returns contact_name, time, kind, show, message '''returns contact_name, time, kind, show, message
for each row in a list of tupples, for each row in a list of tupples,
returns list with empty tupple if we found nothing to meet our demands''' returns list with empty tupple if we found nothing to meet our demands'''
jid_id = self.get_jid_id(jid)
if False: #query.startswith('SELECT '): # it's SQL query (FIXME) if False: #query.startswith('SELECT '): # it's SQL query (FIXME)
try: try:
@ -545,6 +548,7 @@ class Logger:
def get_days_with_logs(self, jid, year, month, max_day, account): def get_days_with_logs(self, jid, year, month, max_day, account):
'''returns the list of days that have logs (not status messages)''' '''returns the list of days that have logs (not status messages)'''
jid_id = self.get_jid_id(jid)
days_with_logs = [] days_with_logs = []
where_sql = self._build_contact_where(account, jid) where_sql = self._build_contact_where(account, jid)
@ -704,7 +708,7 @@ class Logger:
# the data field contains binary object (gzipped data), this is a hack # the data field contains binary object (gzipped data), this is a hack
# to get that data without trying to convert it to unicode # to get that data without trying to convert it to unicode
try: try:
self.cur.execute('SELECT hash_method, hash, data FROM caps_cache;') self.cur.execute('SELECT hash_method, hash, data FROM caps_cache;');
except sqlite.OperationalError: except sqlite.OperationalError:
# might happen when there's no caps_cache table yet # might happen when there's no caps_cache table yet
# -- there's no data to read anyway then # -- there's no data to read anyway then

View file

@ -268,7 +268,7 @@ class IdleCommand(IdleObject):
def pollin(self): def pollin(self):
try: try:
res = self.pipe.read() res = self.pipe.read()
except Exception: except Exception, e:
res = '' res = ''
if res == '': if res == '':
return self.pollend() return self.pollend()
@ -316,6 +316,7 @@ if __name__ == '__main__':
resolver = Resolver(idlequeue) resolver = Resolver(idlequeue)
def clicked(widget): def clicked(widget):
global resolver
host = text_view.get_text() host = text_view.get_text()
def on_result(host, result_array): def on_result(host, result_array):
print 'Result:\n' + repr(result_array) print 'Result:\n' + repr(result_array)

View file

@ -264,7 +264,7 @@ class OptionsParser:
) )
con.commit() con.commit()
gajim.logger.init_vars() gajim.logger.init_vars()
except sqlite.OperationalError: except sqlite.OperationalError, e:
pass pass
con.close() con.close()
@ -336,7 +336,7 @@ class OptionsParser:
''' '''
) )
con.commit() con.commit()
except sqlite.OperationalError: except sqlite.OperationalError, e:
pass pass
con.close() con.close()
gajim.config.set('version', '0.10.1.3') gajim.config.set('version', '0.10.1.3')
@ -457,7 +457,7 @@ class OptionsParser:
''' '''
) )
con.commit() con.commit()
except sqlite.OperationalError: except sqlite.OperationalError, e:
pass pass
con.close() con.close()
gajim.config.set('version', '0.11.1.3') gajim.config.set('version', '0.11.1.3')
@ -499,7 +499,7 @@ class OptionsParser:
''' '''
) )
con.commit() con.commit()
except sqlite.OperationalError: except sqlite.OperationalError, e:
pass pass
con.close() con.close()
gajim.config.set('version', '0.11.1.5') gajim.config.set('version', '0.11.1.5')
@ -535,7 +535,7 @@ class OptionsParser:
''' '''
) )
con.commit() con.commit()
except sqlite.OperationalError: except sqlite.OperationalError, e:
pass pass
con.close() con.close()
gajim.config.set('version', '0.11.4.1') gajim.config.set('version', '0.11.4.1')
@ -572,7 +572,7 @@ class OptionsParser:
''' '''
) )
con.commit() con.commit()
except sqlite.OperationalError: except sqlite.OperationalError, e:
pass pass
con.close() con.close()
gajim.config.set('version', '0.11.4.3') gajim.config.set('version', '0.11.4.3')
@ -586,7 +586,7 @@ class OptionsParser:
try: try:
cur.executescript('DROP TABLE caps_cache;') cur.executescript('DROP TABLE caps_cache;')
con.commit() con.commit()
except sqlite.OperationalError: except sqlite.OperationalError, e:
pass pass
try: try:
cur.executescript( cur.executescript(

View file

@ -67,7 +67,7 @@ class GnomePasswordStorage(PasswordStorage):
if conf is None: if conf is None:
return None return None
try: try:
auth_token = conf.split('gnomekeyring:')[1] unused, auth_token = conf.split('gnomekeyring:')
auth_token = int(auth_token) auth_token = int(auth_token)
except ValueError: except ValueError:
password = conf password = conf

View file

@ -169,7 +169,7 @@ def user_mood(items, name, jid):
if 'text' in acc.mood: if 'text' in acc.mood:
del acc.mood['text'] del acc.mood['text']
user = gajim.get_room_and_nick_from_fjid(jid)[0] (user, resource) = gajim.get_room_and_nick_from_fjid(jid)
for contact in gajim.contacts.get_contacts(name, user): for contact in gajim.contacts.get_contacts(name, user):
if has_child: if has_child:
if 'mood' in contact.mood: if 'mood' in contact.mood:
@ -255,7 +255,7 @@ def user_tune(items, name, jid):
if 'length' in acc.tune: if 'length' in acc.tune:
del acc.tune['length'] del acc.tune['length']
user = gajim.get_room_and_nick_from_fjid(jid)[0] (user, resource) = gajim.get_room_and_nick_from_fjid(jid)
for contact in gajim.contacts.get_contacts(name, user): for contact in gajim.contacts.get_contacts(name, user):
if has_child: if has_child:
if 'artist' in contact.tune: if 'artist' in contact.tune:
@ -344,7 +344,7 @@ def user_activity(items, name, jid):
if 'text' in acc.activity: if 'text' in acc.activity:
del acc.activity['text'] del acc.activity['text']
user = gajim.get_room_and_nick_from_fjid(jid)[0] (user, resource) = gajim.get_room_and_nick_from_fjid(jid)
for contact in gajim.contacts.get_contacts(name, user): for contact in gajim.contacts.get_contacts(name, user):
if has_child: if has_child:
if 'activity' in contact.activity: if 'activity' in contact.activity:
@ -491,7 +491,7 @@ def user_retract_nickname(account):
gajim.connections[account].send_pb_retract('', xmpp.NS_NICK, '0') gajim.connections[account].send_pb_retract('', xmpp.NS_NICK, '0')
def delete_pep(jid, name): def delete_pep(jid, name):
user = gajim.get_room_and_nick_from_fjid(jid)[0] (user, resource) = gajim.get_room_and_nick_from_fjid(jid)
if jid == gajim.get_jid_from_account(name): if jid == gajim.get_jid_from_account(name):
acc = gajim.connections[name] acc = gajim.connections[name]

View file

@ -107,10 +107,11 @@ class ProxyResolver:
self.state = S_RESOLVED self.state = S_RESOLVED
#FIXME: re-enable proxy testing #FIXME: re-enable proxy testing
self.state = S_FINISHED self.state = S_FINISHED
#self.receiver_tester = ReceiverTester(self.host, self.port, self.jid, return
# self.sid, self.sender_jid, self._on_receiver_success, self.receiver_tester = ReceiverTester(self.host, self.port, self.jid,
# self._on_connect_failure) self.sid, self.sender_jid, self._on_receiver_success,
#self.receiver_tester.connect() self._on_connect_failure)
self.receiver_tester.connect()
def _on_receiver_success(self): def _on_receiver_success(self):
self.host_tester = HostTester(self.host, self.port, self.jid, self.host_tester = HostTester(self.host, self.port, self.jid,
@ -279,7 +280,7 @@ class HostTester(Socks5, IdleObject):
self._send = self._sock.send self._send = self._sock.send
self._recv = self._sock.recv self._recv = self._sock.recv
except Exception, ee: except Exception, ee:
errnum = ee[0] (errnum, errstr) = ee
# 56 is for freebsd # 56 is for freebsd
if errnum in (errno.EINPROGRESS, errno.EALREADY, errno.EWOULDBLOCK): if errnum in (errno.EINPROGRESS, errno.EALREADY, errno.EWOULDBLOCK):
# still trying to connect # still trying to connect
@ -391,7 +392,7 @@ class ReceiverTester(Socks5, IdleObject):
self._send = self._sock.send self._send = self._sock.send
self._recv = self._sock.recv self._recv = self._sock.recv
except Exception, ee: except Exception, ee:
errnum = ee[0] (errnum, errstr) = ee
# 56 is for freebsd # 56 is for freebsd
if errnum in (errno.EINPROGRESS, errno.EALREADY, errno.EWOULDBLOCK): if errnum in (errno.EINPROGRESS, errno.EALREADY, errno.EWOULDBLOCK):
# still trying to connect # still trying to connect

View file

@ -87,7 +87,6 @@ class SleepyWindows:
class SleepyUnix: class SleepyUnix:
def __init__(self, away_interval = 60, xa_interval = 120): def __init__(self, away_interval = 60, xa_interval = 120):
global SUPPORTED
self.away_interval = away_interval self.away_interval = away_interval
self.xa_interval = xa_interval self.xa_interval = xa_interval
self.state = STATE_AWAKE # assume we are awake self.state = STATE_AWAKE # assume we are awake

View file

@ -31,7 +31,6 @@ from errno import EWOULDBLOCK
from errno import ENOBUFS from errno import ENOBUFS
from errno import EINTR from errno import EINTR
from errno import EISCONN from errno import EISCONN
from errno import EINPROGRESS
from xmpp.idlequeue import IdleObject from xmpp.idlequeue import IdleObject
MAX_BUFF_LEN = 65536 MAX_BUFF_LEN = 65536
@ -421,7 +420,7 @@ class Socks5:
received = '' received = ''
try: try:
add = self._recv(64) add = self._recv(64)
except Exception: except Exception, e:
add='' add=''
received +=add received +=add
if len(add) == 0: if len(add) == 0:
@ -431,8 +430,8 @@ class Socks5:
def send_raw(self,raw_data): def send_raw(self,raw_data):
''' Writes raw outgoing data. ''' ''' Writes raw outgoing data. '''
try: try:
self._send(raw_data) lenn = self._send(raw_data)
except Exception: except Exception, e:
self.disconnect() self.disconnect()
return len(raw_data) return len(raw_data)
@ -486,7 +485,8 @@ class Socks5:
return -1 return -1
def get_file_contents(self, timeout): def get_file_contents(self, timeout):
''' read file contents from socket and write them to file ''' ''' read file contents from socket and write them to file ''', \
self.file_props['type'], self.file_props['sid']
if self.file_props is None or \ if self.file_props is None or \
('file-name' in self.file_props) is False: ('file-name' in self.file_props) is False:
self.file_props['error'] = -2 self.file_props['error'] = -2
@ -512,7 +512,7 @@ class Socks5:
fd = self.get_fd() fd = self.get_fd()
try: try:
buff = self._recv(MAX_BUFF_LEN) buff = self._recv(MAX_BUFF_LEN)
except Exception: except Exception, e:
buff = '' buff = ''
current_time = self.idlequeue.current_time() current_time = self.idlequeue.current_time()
self.file_props['elapsed-time'] += current_time - \ self.file_props['elapsed-time'] += current_time - \
@ -576,7 +576,7 @@ class Socks5:
mechanisms ''' mechanisms '''
auth_mechanisms = [] auth_mechanisms = []
try: try:
num_auth = struct.unpack('!BB', buff[:2])[1] ver, num_auth = struct.unpack('!BB', buff[:2])
for i in xrange(num_auth): for i in xrange(num_auth):
mechanism, = struct.unpack('!B', buff[1 + i]) mechanism, = struct.unpack('!B', buff[1 + i])
auth_mechanisms.append(mechanism) auth_mechanisms.append(mechanism)
@ -605,7 +605,8 @@ class Socks5:
def _parse_request_buff(self, buff): def _parse_request_buff(self, buff):
try: # don't trust on what comes from the outside try: # don't trust on what comes from the outside
req_type, host_type = struct.unpack('!xBxB', buff[:4]) version, req_type, reserved, host_type, = \
struct.unpack('!BBBB', buff[:4])
if host_type == 0x01: if host_type == 0x01:
host_arr = struct.unpack('!iiii', buff[4:8]) host_arr = struct.unpack('!iiii', buff[4:8])
host, = '.'.join(str(s) for s in host_arr) host, = '.'.join(str(s) for s in host_arr)
@ -767,7 +768,7 @@ class Socks5Sender(Socks5, IdleObject):
return -1 # invalid auth methods received return -1 # invalid auth methods received
elif self.state == 3: # get next request elif self.state == 3: # get next request
buff = self.receive() buff = self.receive()
req_type, self.sha_msg = self._parse_request_buff(buff)[:2] (req_type, self.sha_msg, port) = self._parse_request_buff(buff)
if req_type != 0x01: if req_type != 0x01:
return -1 # request is not of type 'connect' return -1 # request is not of type 'connect'
self.state += 1 # go to the next step self.state += 1 # go to the next step
@ -902,10 +903,10 @@ class Socks5Receiver(Socks5, IdleObject):
self._sock.setblocking(False) self._sock.setblocking(False)
self._server=ai[4] self._server=ai[4]
break break
except socket.error, e: except Exception:
if not isinstance(e, basestring) and e[0] == EINPROGRESS: if sys.exc_value[0] == errno.EINPROGRESS:
break break
# for all other errors, we try other addresses #for all errors, we try other addresses
continue continue
self.fd = self._sock.fileno() self.fd = self._sock.fileno()
self.state = 0 # about to be connected self.state = 0 # about to be connected
@ -975,7 +976,7 @@ class Socks5Receiver(Socks5, IdleObject):
self._send=self._sock.send self._send=self._sock.send
self._recv=self._sock.recv self._recv=self._sock.recv
except Exception, ee: except Exception, ee:
errnum = ee[0] (errnum, errstr) = ee
self.connect_timeout += 1 self.connect_timeout += 1
if errnum == 111 or self.connect_timeout > 1000: if errnum == 111 or self.connect_timeout > 1000:
self.queue._connection_refused(self.streamhost, self.queue._connection_refused(self.streamhost,
@ -1020,8 +1021,8 @@ class Socks5Receiver(Socks5, IdleObject):
sub_buff = buff[:4] sub_buff = buff[:4]
if len(sub_buff) < 4: if len(sub_buff) < 4:
return None return None
version, address_type = struct.unpack('!BxxB', buff[:4]) version, command, rsvd, address_type = struct.unpack('!BBBB', buff[:4])
addrlen = 0 addrlen, address, port = 0, 0, 0
if address_type == 0x03: if address_type == 0x03:
addrlen = ord(buff[4]) addrlen = ord(buff[4])
address = struct.unpack('!%ds' % addrlen, buff[5:addrlen + 5]) address = struct.unpack('!%ds' % addrlen, buff[5:addrlen + 5])

View file

@ -28,7 +28,6 @@ from common import gajim
from common import xmpp from common import xmpp
from common import exceptions from common import exceptions
import itertools
import random import random
import string import string
@ -92,8 +91,8 @@ class StanzaSession(object):
return any_removed return any_removed
def generate_thread_id(self): def generate_thread_id(self):
return ''.join([f(string.ascii_letters) for f in itertools.repeat( return ''.join([random.choice(string.ascii_letters) for x in xrange(0,
random.choice, 32)]) 32)])
def send(self, msg): def send(self, msg):
if self.thread_id: if self.thread_id:
@ -284,7 +283,7 @@ class EncryptedStanzaSession(StanzaSession):
return stanza return stanza
def is_xep_200_encrypted(self, msg): def is_xep_200_encrypted(self, msg):
msg.getTag('c', namespace=xmpp.NS_STANZA_CRYPTO) msg.getTag('c', namespace=common.xmpp.NS_STANZA_CRYPTO)
def hmac(self, key, content): def hmac(self, key, content):
return HMAC.new(key, content, self.hash_alg).digest() return HMAC.new(key, content, self.hash_alg).digest()
@ -387,9 +386,10 @@ class EncryptedStanzaSession(StanzaSession):
parsed = xmpp.Node(node='<node>' + plaintext + '</node>') parsed = xmpp.Node(node='<node>' + plaintext + '</node>')
if self.negotiated['recv_pubkey'] == 'hash': if self.negotiated['recv_pubkey'] == 'hash':
# fingerprint = parsed.getTagData('fingerprint') fingerprint = parsed.getTagData('fingerprint')
# XXX find stored pubkey or terminate session # XXX find stored pubkey or terminate session
raise NotImplementedError() raise 'unimplemented'
else: else:
if self.negotiated['sign_algs'] == (XmlDsig + 'rsa-sha256'): if self.negotiated['sign_algs'] == (XmlDsig + 'rsa-sha256'):
keyvalue = parsed.getTag(name='RSAKeyValue', namespace=XmlDsig) keyvalue = parsed.getTag(name='RSAKeyValue', namespace=XmlDsig)
@ -771,7 +771,7 @@ class EncryptedStanzaSession(StanzaSession):
else: else:
srses = secrets.secrets().retained_secrets(self.conn.name, srses = secrets.secrets().retained_secrets(self.conn.name,
self.jid.getStripped()) self.jid.getStripped())
rshashes = [self.hmac(self.n_s, rs[0]) for rs in srses] rshashes = [self.hmac(self.n_s, rs) for (rs,v) in srses]
if not rshashes: if not rshashes:
# we've never spoken before, but we'll pretend we have # we've never spoken before, but we'll pretend we have
@ -838,7 +838,7 @@ class EncryptedStanzaSession(StanzaSession):
rshashes = [base64.b64decode(rshash) for rshash in form.getField( rshashes = [base64.b64decode(rshash) for rshash in form.getField(
'rshashes').getValues()] 'rshashes').getValues()]
for secret in (s[0] for s in srses): for (secret, verified) in srses:
if self.hmac(self.n_o, secret) in rshashes: if self.hmac(self.n_o, secret) in rshashes:
srs = secret srs = secret
break break
@ -889,7 +889,7 @@ class EncryptedStanzaSession(StanzaSession):
srshash = base64.b64decode(form['srshash']) srshash = base64.b64decode(form['srshash'])
for secret in (s[0] for s in srses): for (secret, verified) in srses:
if self.hmac(secret, 'Shared Retained Secret') == srshash: if self.hmac(secret, 'Shared Retained Secret') == srshash:
srs = secret srs = secret
break break

View file

@ -61,14 +61,8 @@ class NonSASL(PlugIn):
token=query.getTagData('token') token=query.getTagData('token')
seq=query.getTagData('sequence') seq=query.getTagData('sequence')
self.DEBUG("Performing zero-k authentication",'ok') self.DEBUG("Performing zero-k authentication",'ok')
hash = sha.new(sha.new(self.password).hexdigest()+token).hexdigest()
def hasher(s): for foo in xrange(int(seq)): hash = sha.new(hash).hexdigest()
return sha.new(s).hexdigest()
def hash_n_times(s, count):
return count and hasher(hash_n_times(s, count-1)) or s
hash = hash_n_times(hasher(hasher(self.password)+token), int(seq))
query.setTagData('hash',hash) query.setTagData('hash',hash)
method='0k' method='0k'
else: else:
@ -188,8 +182,10 @@ class SASL(PlugIn):
resp['username']=self.username resp['username']=self.username
resp['realm']=self._owner.Server resp['realm']=self._owner.Server
resp['nonce']=chal['nonce'] resp['nonce']=chal['nonce']
resp['cnonce'] = ''.join("%x" % randint(0, 2**28) for randint in cnonce=''
itertools.repeat(random.randint, 7)) for i in range(7):
cnonce+=hex(int(random.random()*65536*4096))[2:]
resp['cnonce']=cnonce
resp['nc']=('00000001') resp['nc']=('00000001')
resp['qop']='auth' resp['qop']='auth'
resp['digest-uri']='xmpp/'+self._owner.Server resp['digest-uri']='xmpp/'+self._owner.Server

View file

@ -17,14 +17,11 @@
Provides library with all Non-SASL and SASL authentication mechanisms. Provides library with all Non-SASL and SASL authentication mechanisms.
Can be used both for client and transport authentication. Can be used both for client and transport authentication.
''' '''
import sys
from protocol import * from protocol import *
from auth import * from auth import *
from client import PlugIn from client import PlugIn
import sha import sha,base64,random,dispatcher_nb
import base64
import random
import itertools
import dispatcher_nb
try: try:
import kerberos import kerberos
@ -145,8 +142,8 @@ class SASL(PlugIn):
self._owner.RegisterHandler('failure', self.SASLHandler, xmlns=NS_SASL) self._owner.RegisterHandler('failure', self.SASLHandler, xmlns=NS_SASL)
self._owner.RegisterHandler('success', self.SASLHandler, xmlns=NS_SASL) self._owner.RegisterHandler('success', self.SASLHandler, xmlns=NS_SASL)
if "GSSAPI" in mecs and have_kerberos: if "GSSAPI" in mecs and have_kerberos:
self.gss_vc = kerberos.authGSSClientInit( rc, self.gss_vc = kerberos.authGSSClientInit('xmpp@' +
'xmpp@' + self._owner.Server)[1] self._owner.Server)
response = kerberos.authGSSClientResponse(self.gss_vc) response = kerberos.authGSSClientResponse(self.gss_vc)
node=Node('auth',attrs={'xmlns': NS_SASL, 'mechanism': 'GSSAPI'}, node=Node('auth',attrs={'xmlns': NS_SASL, 'mechanism': 'GSSAPI'},
payload=(response or "")) payload=(response or ""))
@ -227,8 +224,10 @@ class SASL(PlugIn):
else: else:
resp['realm'] = self._owner.Server resp['realm'] = self._owner.Server
resp['nonce']=chal['nonce'] resp['nonce']=chal['nonce']
resp['cnonce'] = ''.join("%x" % randint(0, 2**28) for randint in cnonce=''
itertools.repeat(random.randint, 7)) for i in range(7):
cnonce += hex(int(random.random() * 65536 * 4096))[2:]
resp['cnonce'] = cnonce
resp['nc'] = ('00000001') resp['nc'] = ('00000001')
resp['qop'] = 'auth' resp['qop'] = 'auth'
resp['digest-uri'] = 'xmpp/'+self._owner.Server resp['digest-uri'] = 'xmpp/'+self._owner.Server
@ -279,7 +278,7 @@ class NonBlockingNonSASL(PlugIn):
self.DEBUG('Querying server about possible auth methods', 'start') self.DEBUG('Querying server about possible auth methods', 'start')
self.owner = owner self.owner = owner
owner.Dispatcher.SendAndWaitForResponse( resp = owner.Dispatcher.SendAndWaitForResponse(
Iq('get', NS_AUTH, payload=[Node('username', payload=[self.user])]), func=self._on_username Iq('get', NS_AUTH, payload=[Node('username', payload=[self.user])]), func=self._on_username
) )
@ -303,14 +302,9 @@ class NonBlockingNonSASL(PlugIn):
token=query.getTagData('token') token=query.getTagData('token')
seq=query.getTagData('sequence') seq=query.getTagData('sequence')
self.DEBUG("Performing zero-k authentication",'ok') self.DEBUG("Performing zero-k authentication",'ok')
hash = sha.new(sha.new(self.password).hexdigest()+token).hexdigest()
def hasher(s): for foo in xrange(int(seq)):
return sha.new(s).hexdigest() hash = sha.new(hash).hexdigest()
def hash_n_times(s, count):
return count and hasher(hash_n_times(s, count-1)) or s
hash = hash_n_times(hasher(hasher(self.password) + token), int(seq))
query.setTagData('hash',hash) query.setTagData('hash',hash)
self._method='0k' self._method='0k'
else: else:
@ -345,7 +339,7 @@ class NonBlockingNonSASL(PlugIn):
self.DEBUG('waiting on handshake', 'notify') self.DEBUG('waiting on handshake', 'notify')
return return
self._owner.onreceive(None) self._owner.onreceive(None)
self._owner._registered_name=self.user owner._registered_name=self.user
if self.handshake+1: if self.handshake+1:
return self.on_auth('ok') return self.on_auth('ok')
self.on_auth(None) self.on_auth(None)
@ -382,7 +376,7 @@ class NonBlockingBind(Bind):
self._resource = [] self._resource = []
self._owner.onreceive(None) self._owner.onreceive(None)
self._owner.Dispatcher.SendAndWaitForResponse( resp=self._owner.Dispatcher.SendAndWaitForResponse(
Protocol('iq',typ='set', Protocol('iq',typ='set',
payload=[Node('bind', attrs={'xmlns':NS_BIND}, payload=self._resource)]), payload=[Node('bind', attrs={'xmlns':NS_BIND}, payload=self._resource)]),
func=self._on_bound) func=self._on_bound)
@ -444,14 +438,12 @@ class NBComponentBind(ComponentBind):
def Bind(self, domain = None, on_bind = None): def Bind(self, domain = None, on_bind = None):
''' Perform binding. Use provided domain name (if not provided). ''' ''' Perform binding. Use provided domain name (if not provided). '''
def wrapper(resp): self._owner.onreceive(self._on_bound)
self._on_bound(resp, domain)
self._owner.onreceive(wrapper)
self.on_bind = on_bind self.on_bind = on_bind
def _on_bound(self, resp, domain=None): def _on_bound(self, resp):
if resp: if data:
self.Dispatcher.ProcessNonBlocking(resp) self.Dispatcher.ProcessNonBlocking(data)
if self.bound is None: if self.bound is None:
return return
self._owner.onreceive(None) self._owner.onreceive(None)
@ -459,7 +451,7 @@ class NBComponentBind(ComponentBind):
Protocol('bind', attrs={'name':domain}, xmlns=NS_COMPONENT_1), Protocol('bind', attrs={'name':domain}, xmlns=NS_COMPONENT_1),
func=self._on_bind_reponse) func=self._on_bind_reponse)
def _on_bind_reponse(self, resp): def _on_bind_reponse(self, res):
if resp and resp.getAttr('error'): if resp and resp.getAttr('error'):
self.DEBUG('Binding failed: %s.' % resp.getAttr('error'), 'error') self.DEBUG('Binding failed: %s.' % resp.getAttr('error'), 'error')
elif resp: elif resp:

View file

@ -26,8 +26,6 @@ automatically called when user requests some node of your disco tree.
from dispatcher import * from dispatcher import *
from client import PlugIn from client import PlugIn
DBG_BROWSER = "Browser"
class Browser(PlugIn): class Browser(PlugIn):
""" WARNING! This class is for components only. It will not work in client mode! """ WARNING! This class is for components only. It will not work in client mode!
@ -82,7 +80,7 @@ class Browser(PlugIn):
def __init__(self): def __init__(self):
"""Initialises internal variables. Used internally.""" """Initialises internal variables. Used internally."""
PlugIn.__init__(self) PlugIn.__init__(self)
self.DBG_LINE = DBG_BROWSER DBG_LINE='browser'
self._exported_methods=[] self._exported_methods=[]
self._handlers={'':{}} self._handlers={'':{}}
@ -91,7 +89,6 @@ class Browser(PlugIn):
Used internally.""" Used internally."""
owner.RegisterHandler('iq',self._DiscoveryHandler,typ='get',ns=NS_DISCO_INFO) owner.RegisterHandler('iq',self._DiscoveryHandler,typ='get',ns=NS_DISCO_INFO)
owner.RegisterHandler('iq',self._DiscoveryHandler,typ='get',ns=NS_DISCO_ITEMS) owner.RegisterHandler('iq',self._DiscoveryHandler,typ='get',ns=NS_DISCO_ITEMS)
owner.debug_flags.append(DBG_BROWSER)
def plugout(self): def plugout(self):
""" Unregisters browser's iq handlers from your application dispatcher instance. """ Unregisters browser's iq handlers from your application dispatcher instance.

View file

@ -21,6 +21,7 @@ examples of xmpppy structures usage.
These classes can be used for simple applications "AS IS" though. These classes can be used for simple applications "AS IS" though.
""" """
import socket
import debug import debug
Debug=debug Debug=debug
Debug.DEBUGGING_IS_ON=1 Debug.DEBUGGING_IS_ON=1

View file

@ -23,6 +23,9 @@ examples of xmpppy structures usage.
These classes can be used for simple applications "AS IS" though. These classes can be used for simple applications "AS IS" though.
''' '''
import socket
import debug
import transports_nb, dispatcher_nb, auth_nb, roster_nb import transports_nb, dispatcher_nb, auth_nb, roster_nb
from client import * from client import *

View file

@ -31,12 +31,9 @@ What it supplies:
A means of handling requests, by redirection though the command manager. A means of handling requests, by redirection though the command manager.
""" """
import math
from protocol import * from protocol import *
from client import PlugIn from client import PlugIn
DBG_COMMANDS = 'commands'
class Commands(PlugIn): class Commands(PlugIn):
"""Commands is an ancestor of PlugIn and can be attached to any session. """Commands is an ancestor of PlugIn and can be attached to any session.
@ -49,7 +46,7 @@ class Commands(PlugIn):
def __init__(self, browser): def __init__(self, browser):
"""Initialises class and sets up local variables""" """Initialises class and sets up local variables"""
PlugIn.__init__(self) PlugIn.__init__(self)
self.DBG_LINE = DBG_COMMANDS DBG_LINE='commands'
self._exported_methods=[] self._exported_methods=[]
self._handlers={'':{}} self._handlers={'':{}}
self._browser = browser self._browser = browser
@ -61,14 +58,13 @@ class Commands(PlugIn):
owner.RegisterHandler('iq',self._CommandHandler,typ='set',ns=NS_COMMANDS) owner.RegisterHandler('iq',self._CommandHandler,typ='set',ns=NS_COMMANDS)
owner.RegisterHandler('iq',self._CommandHandler,typ='get',ns=NS_COMMANDS) owner.RegisterHandler('iq',self._CommandHandler,typ='get',ns=NS_COMMANDS)
self._browser.setDiscoHandler(self._DiscoHandler,node=NS_COMMANDS,jid='') self._browser.setDiscoHandler(self._DiscoHandler,node=NS_COMMANDS,jid='')
owner.debug_flags.append(DBG_COMMANDS)
def plugout(self): def plugout(self):
"""Removes handlers from the session""" """Removes handlers from the session"""
# unPlug from the session and the disco manager # unPlug from the session and the disco manager
self._owner.UnregisterHandler('iq',self._CommandHandler,ns=NS_COMMANDS) self._owner.UnregisterHandler('iq',self_CommandHandler,ns=NS_COMMANDS)
for jid in self._handlers: for jid in self._handlers:
self._browser.delDiscoHandler(self._DiscoHandler,node=NS_COMMANDS,jid=jid) self._browser.delDiscoHandler(self._DiscoHandler,node=NS_COMMANDS)
def _CommandHandler(self,conn,request): def _CommandHandler(self,conn,request):
"""The internal method to process the routing of command execution requests""" """The internal method to process the routing of command execution requests"""
@ -197,7 +193,7 @@ class Command_Handler_Prototype(PlugIn):
def __init__(self,jid=''): def __init__(self,jid=''):
"""Set up the class""" """Set up the class"""
PlugIn.__init__(self) PlugIn.__init__(self)
self.DBG_LINE='command' DBG_LINE='command'
self.sessioncount = 0 self.sessioncount = 0
self.sessions = {} self.sessions = {}
# Disco information for command list pre-formatted as a tuple # Disco information for command list pre-formatted as a tuple
@ -285,10 +281,10 @@ class TestCommand(Command_Handler_Prototype):
session = None session = None
if session is None: if session is None:
session = self.getSessionID() session = self.getSessionID()
self.sessions[session]={'jid':request.getFrom(),'actions':{'cancel':self.cmdCancel,'next':self.cmdSecondStage},'data':{'type':None}} sessions[session]={'jid':request.getFrom(),'actions':{'cancel':self.cmdCancel,'next':self.cmdSecondStage},'data':{'type':None}}
# As this is the first stage we only send a form # As this is the first stage we only send a form
reply = request.buildReply('result') reply = request.buildReply('result')
form = DataForm(title='Select type of operation',data=['Use the combobox to select the type of calculation you would like to do, then click Next',DataField(name='calctype',label='Calculation Type',value=self.sessions[session]['data']['type'],options=[['circlediameter','Calculate the Diameter of a circle'],['circlearea','Calculate the area of a circle']],typ='list-single',required=1)]) form = DataForm(title='Select type of operation',data=['Use the combobox to select the type of calculation you would like to do, then click Next',DataField(name='calctype',label='Calculation Type',value=sessions[session]['data']['type'],options=[['circlediameter','Calculate the Diameter of a circle'],['circlearea','Calculate the area of a circle']],typ='list-single',required=1)])
replypayload = [Node('actions',attrs={'execute':'next'},payload=[Node('next')]),form] replypayload = [Node('actions',attrs={'execute':'next'},payload=[Node('next')]),form]
reply.addChild(name='command',attrs={'xmlns':NS_COMMAND,'node':request.getTagAttr('command','node'),'sessionid':session,'status':'executing'},payload=replypayload) reply.addChild(name='command',attrs={'xmlns':NS_COMMAND,'node':request.getTagAttr('command','node'),'sessionid':session,'status':'executing'},payload=replypayload)
self._owner.send(reply) self._owner.send(reply)
@ -316,9 +312,9 @@ class TestCommand(Command_Handler_Prototype):
except Exception: except Exception:
self.cmdSecondStageReply(conn,request) self.cmdSecondStageReply(conn,request)
if sessions[request.getTagAttr('command','sessionid')]['data']['type'] == 'circlearea': if sessions[request.getTagAttr('command','sessionid')]['data']['type'] == 'circlearea':
result = num*(math.pi**2) result = num*(pi**2)
else: else:
result = num*2*math.pi result = num*2*pi
reply = result.buildReply(request) reply = result.buildReply(request)
form = DataForm(typ='result',data=[DataField(label='result',name='result',value=result)]) form = DataForm(typ='result',data=[DataField(label='result',name='result',value=result)])
reply.addChild(name='command',attrs={'xmlns':NS_COMMAND,'node':request.getTagAttr('command','node'),'sessionid':request.getTagAttr('command','sessionid'),'status':'completed'},payload=form) reply.addChild(name='command',attrs={'xmlns':NS_COMMAND,'node':request.getTagAttr('command','node'),'sessionid':request.getTagAttr('command','sessionid'),'status':'completed'},payload=form)
@ -329,7 +325,7 @@ class TestCommand(Command_Handler_Prototype):
reply = request.buildReply('result') reply = request.buildReply('result')
reply.addChild(name='command',attrs={'xmlns':NS_COMMAND,'node':request.getTagAttr('command','node'),'sessionid':request.getTagAttr('command','sessionid'),'status':'cancelled'}) reply.addChild(name='command',attrs={'xmlns':NS_COMMAND,'node':request.getTagAttr('command','node'),'sessionid':request.getTagAttr('command','sessionid'),'status':'cancelled'})
self._owner.send(reply) self._owner.send(reply)
del self.sessions[request.getTagAttr('command','sessionid')] del sessions[request.getTagAttr('command','sessionid')]

View file

@ -12,7 +12,10 @@
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU Lesser General Public License for more details. ## GNU Lesser General Public License for more details.
""" _version_ = '1.4.0'
"""\
Generic debug class Generic debug class
Other modules can always define extra debug flags for local usage, as long as Other modules can always define extra debug flags for local usage, as long as
@ -31,9 +34,9 @@ by the individual classes.
For samples of usage, see samples subdir in distro source, and selftest For samples of usage, see samples subdir in distro source, and selftest
in this code in this code
""" """
_version_ = '1.4.0'
import sys import sys
@ -41,6 +44,8 @@ import traceback
import time import time
import os import os
import types
if 'TERM' in os.environ: if 'TERM' in os.environ:
colors_enabled=True colors_enabled=True
else: else:
@ -65,34 +70,36 @@ color_bright_cyan = chr(27) + "[36;1m"
color_white = chr(27) + "[37;1m" color_white = chr(27) + "[37;1m"
# Define your flags in yor modules like this: """
# Define your flags in yor modules like this:
# from debug import *
# from debug import *
# DBG_INIT = 'init' ; debug_flags.append( DBG_INIT )
# DBG_CONNECTION = 'connection' ; debug_flags.append( DBG_CONNECTION ) DBG_INIT = 'init' ; debug_flags.append( DBG_INIT )
# DBG_CONNECTION = 'connection' ; debug_flags.append( DBG_CONNECTION )
# The reason for having a double statement wis so we can validate params
# and catch all undefined debug flags The reason for having a double statement wis so we can validate params
# and catch all undefined debug flags
# This gives us control over all used flags, and makes it easier to allow
# global debugging in your code, just do something like This gives us control over all used flags, and makes it easier to allow
# global debugging in your code, just do something like
# foo = Debug( debug_flags )
# foo = Debug( debug_flags )
# group flags, that is a flag in it self containing multiple flags should be
# defined without the debug_flags.append() sequence, since the parts are already group flags, that is a flag in it self containing multiple flags should be
# in the list, also they must of course be defined after the flags they depend on ;) defined without the debug_flags.append() sequence, since the parts are already
# example: in the list, also they must of course be defined after the flags they depend on ;)
# example:
# DBG_MULTI = [ DBG_INIT, DBG_CONNECTION ]
# DBG_MULTI = [ DBG_INIT, DBG_CONNECTION ]
#
#
# NoDebug
# ------- NoDebug
# To speed code up, typically for product releases or such -------
# use this class instead if you globaly want to disable debugging To speed code up, typically for product releases or such
use this class instead if you globaly want to disable debugging
"""
class NoDebug: class NoDebug:

View file

@ -28,14 +28,12 @@ from client import PlugIn
DefaultTimeout=25 DefaultTimeout=25
ID=0 ID=0
DBG_DISPATCHER = 'dispatcher'
class Dispatcher(PlugIn): class Dispatcher(PlugIn):
""" Ancestor of PlugIn class. Handles XMPP stream, i.e. aware of stream headers. """ Ancestor of PlugIn class. Handles XMPP stream, i.e. aware of stream headers.
Can be plugged out/in to restart these headers (used for SASL f.e.). """ Can be plugged out/in to restart these headers (used for SASL f.e.). """
def __init__(self): def __init__(self):
PlugIn.__init__(self) PlugIn.__init__(self)
self.DBG_LINE = DBG_DISPATCHER DBG_LINE='dispatcher'
self.handlers={} self.handlers={}
self._expected={} self._expected={}
self._defaultHandler=None self._defaultHandler=None
@ -84,7 +82,6 @@ class Dispatcher(PlugIn):
self._owner.lastErr=None self._owner.lastErr=None
self._owner.lastErrCode=None self._owner.lastErrCode=None
self.StreamInit() self.StreamInit()
owner.debug_flags.append(DBG_DISPATCHER)
def plugout(self): def plugout(self):
""" Prepares instance to be destructed. """ """ Prepares instance to be destructed. """
@ -295,6 +292,7 @@ class Dispatcher(PlugIn):
for key in list: for key in list:
if key: chain = chain + self.handlers[xmlns][name][key] if key: chain = chain + self.handlers[xmlns][name][key]
output=''
if ID in session._expected: if ID in session._expected:
user=0 user=0
if isinstance(session._expected[ID], tuple): if isinstance(session._expected[ID], tuple):
@ -325,6 +323,7 @@ class Dispatcher(PlugIn):
lastErrNode, lastErr and lastErrCode are set accordingly. """ lastErrNode, lastErr and lastErrCode are set accordingly. """
if timeout is None: timeout=DefaultTimeout if timeout is None: timeout=DefaultTimeout
self._expected[ID]=None self._expected[ID]=None
has_timed_out=0
abort_time=time.time() + timeout abort_time=time.time() + timeout
self.DEBUG("Waiting for ID:%s with timeout %s..." % (ID,timeout),'wait') self.DEBUG("Waiting for ID:%s with timeout %s..." % (ID,timeout),'wait')
while not self._expected[ID]: while not self._expected[ID]:

View file

@ -37,7 +37,7 @@ class Dispatcher(PlugIn):
Can be plugged out/in to restart these headers (used for SASL f.e.). ''' Can be plugged out/in to restart these headers (used for SASL f.e.). '''
def __init__(self): def __init__(self):
PlugIn.__init__(self) PlugIn.__init__(self)
self.DBG_LINE='dispatcher' DBG_LINE='dispatcher'
self.handlers={} self.handlers={}
self._expected={} self._expected={}
self._defaultHandler=None self._defaultHandler=None
@ -334,6 +334,7 @@ class Dispatcher(PlugIn):
for key in list: for key in list:
if key: chain = chain + self.handlers[xmlns][name][key] if key: chain = chain + self.handlers[xmlns][name][key]
output=''
if ID in session._expected: if ID in session._expected:
user=0 user=0
if isinstance(session._expected[ID], tuple): if isinstance(session._expected[ID], tuple):

View file

@ -49,10 +49,10 @@ def _discover(disp,ns,jid,node=None,fb2b=0,fb2a=1):
def discoverItems(disp,jid,node=None): def discoverItems(disp,jid,node=None):
""" Query remote object about any items that it contains. Return items list. """ """ Query remote object about any items that it contains. Return items list. """
# According to JEP-0030: """ According to JEP-0030:
# query MAY have node attribute query MAY have node attribute
# item: MUST HAVE jid attribute and MAY HAVE name, node, action attributes. item: MUST HAVE jid attribute and MAY HAVE name, node, action attributes.
# action attribute of item can be either of remove or update value. action attribute of item can be either of remove or update value."""
ret=[] ret=[]
for i in _discover(disp,NS_DISCO_ITEMS,jid,node): for i in _discover(disp,NS_DISCO_ITEMS,jid,node):
if i.getName()=='agent' and i.getTag('name'): i.setAttr('name',i.getTagData('name')) if i.getName()=='agent' and i.getTag('name'): i.setAttr('name',i.getTagData('name'))
@ -61,10 +61,10 @@ def discoverItems(disp,jid,node=None):
def discoverInfo(disp,jid,node=None): def discoverInfo(disp,jid,node=None):
""" Query remote object about info that it publishes. Returns identities and features lists.""" """ Query remote object about info that it publishes. Returns identities and features lists."""
# According to JEP-0030: """ According to JEP-0030:
# query MAY have node attribute query MAY have node attribute
# identity: MUST HAVE category and name attributes and MAY HAVE type attribute. identity: MUST HAVE category and name attributes and MAY HAVE type attribute.
# feature: MUST HAVE var attribute""" feature: MUST HAVE var attribute"""
identities , features = [] , [] identities , features = [] , []
for i in _discover(disp,NS_DISCO_INFO,jid,node): for i in _discover(disp,NS_DISCO_INFO,jid,node):
if i.getName()=='identity': identities.append(i.attrs) if i.getName()=='identity': identities.append(i.attrs)

View file

@ -58,10 +58,10 @@ def _discover(disp, ns, jid, node = None, fb2b=0, fb2a=1, cb=None):
# this function is not used in gajim ??? # this function is not used in gajim ???
def discoverItems(disp,jid,node=None, cb=None): def discoverItems(disp,jid,node=None, cb=None):
""" Query remote object about any items that it contains. Return items list. """ """ Query remote object about any items that it contains. Return items list. """
# According to JEP-0030: """ According to JEP-0030:
# query MAY have node attribute query MAY have node attribute
# item: MUST HAVE jid attribute and MAY HAVE name, node, action attributes. item: MUST HAVE jid attribute and MAY HAVE name, node, action attributes.
# action attribute of item can be either of remove or update value. action attribute of item can be either of remove or update value."""
def _on_response(result_array): def _on_response(result_array):
ret=[] ret=[]
for result in result_array: for result in result_array:
@ -75,10 +75,10 @@ def discoverItems(disp,jid,node=None, cb=None):
# this one is # this one is
def discoverInfo(disp,jid,node=None, cb=None): def discoverInfo(disp,jid,node=None, cb=None):
""" Query remote object about info that it publishes. Returns identities and features lists.""" """ Query remote object about info that it publishes. Returns identities and features lists."""
# According to JEP-0030: """ According to JEP-0030:
# query MAY have node attribute query MAY have node attribute
# identity: MUST HAVE category and name attributes and MAY HAVE type attribute. identity: MUST HAVE category and name attributes and MAY HAVE type attribute.
# feature: MUST HAVE var attribute feature: MUST HAVE var attribute"""
def _on_response(result): def _on_response(result):
identities , features = [] , [] identities , features = [] , []
for i in result: for i in result:
@ -118,6 +118,7 @@ def getRegInfo(disp, host, info={}, sync=True):
disp.SendAndCallForResponse(iq, _ReceivedRegInfo, {'agent': host }) disp.SendAndCallForResponse(iq, _ReceivedRegInfo, {'agent': host })
def _ReceivedRegInfo(con, resp, agent): def _ReceivedRegInfo(con, resp, agent):
iq=Iq('get',NS_REGISTER,to=agent)
if not isResultNode(resp): if not isResultNode(resp):
error_msg = resp.getErrorMsg() error_msg = resp.getErrorMsg()
con.Event(NS_REGISTER,REGISTER_DATA_RECEIVED,(agent,None,False,error_msg)) con.Event(NS_REGISTER,REGISTER_DATA_RECEIVED,(agent,None,False,error_msg))

View file

@ -58,14 +58,16 @@ class IBB(PlugIn):
def StreamOpenHandler(self,conn,stanza): def StreamOpenHandler(self,conn,stanza):
""" Handles opening of new incoming stream. Used internally. """ """ Handles opening of new incoming stream. Used internally. """
# <iq type='set' """
# from='romeo@montague.net/orchard' <iq type='set'
# to='juliet@capulet.com/balcony' from='romeo@montague.net/orchard'
# id='inband_1'> to='juliet@capulet.com/balcony'
# <open sid='mySID' id='inband_1'>
# block-size='4096' <open sid='mySID'
# xmlns='http://jabber.org/protocol/ibb'/> block-size='4096'
# </iq> xmlns='http://jabber.org/protocol/ibb'/>
</iq>
"""
err=None err=None
sid,blocksize=stanza.getTagAttr('open','sid'),stanza.getTagAttr('open','block-size') sid,blocksize=stanza.getTagAttr('open','sid'),stanza.getTagAttr('open','block-size')
self.DEBUG('StreamOpenHandler called sid->%s blocksize->%s'%(sid,blocksize),'info') self.DEBUG('StreamOpenHandler called sid->%s blocksize->%s'%(sid,blocksize),'info')
@ -99,8 +101,7 @@ class IBB(PlugIn):
self.DEBUG('SendHandler called','info') self.DEBUG('SendHandler called','info')
for sid in self._streams.keys(): for sid in self._streams.keys():
stream=self._streams[sid] stream=self._streams[sid]
if stream['direction'][:2]=='|>': if stream['direction'][:2]=='|>': cont=1
pass
elif stream['direction'][0]=='>': elif stream['direction'][0]=='>':
chunk=stream['fp'].read(stream['block-size']) chunk=stream['fp'].read(stream['block-size'])
if chunk: if chunk:
@ -109,27 +110,29 @@ class IBB(PlugIn):
if stream['seq']==65536: stream['seq']=0 if stream['seq']==65536: stream['seq']=0
conn.send(Protocol('message',stream['direction'][1:],payload=[datanode,self._ampnode])) conn.send(Protocol('message',stream['direction'][1:],payload=[datanode,self._ampnode]))
else: else:
# notify the other side about stream closing """ notify the other side about stream closing
# notify the local user about sucessfull send notify the local user about sucessfull send
# delete the local stream delete the local stream"""
conn.send(Protocol('iq',stream['direction'][1:],'set',payload=[Node(NS_IBB+' close',{'sid':sid})])) conn.send(Protocol('iq',stream['direction'][1:],'set',payload=[Node(NS_IBB+' close',{'sid':sid})]))
conn.Event(self.DBG_LINE,'SUCCESSFULL SEND',stream) conn.Event(self.DBG_LINE,'SUCCESSFULL SEND',stream)
del self._streams[sid] del self._streams[sid]
self._owner.UnregisterCycleHandler(self.SendHandler) self._owner.UnregisterCycleHandler(self.SendHandler)
# <message from='romeo@montague.net/orchard' to='juliet@capulet.com/balcony' id='msg1'> """
# <data xmlns='http://jabber.org/protocol/ibb' sid='mySID' seq='0'> <message from='romeo@montague.net/orchard' to='juliet@capulet.com/balcony' id='msg1'>
# qANQR1DBwU4DX7jmYZnncmUQB/9KuKBddzQH+tZ1ZywKK0yHKnq57kWq+RFtQdCJ <data xmlns='http://jabber.org/protocol/ibb' sid='mySID' seq='0'>
# WpdWpR0uQsuJe7+vh3NWn59/gTc5MDlX8dS9p0ovStmNcyLhxVgmqS8ZKhsblVeu qANQR1DBwU4DX7jmYZnncmUQB/9KuKBddzQH+tZ1ZywKK0yHKnq57kWq+RFtQdCJ
# IpQ0JgavABqibJolc3BKrVtVV1igKiX/N7Pi8RtY1K18toaMDhdEfhBRzO/XB0+P WpdWpR0uQsuJe7+vh3NWn59/gTc5MDlX8dS9p0ovStmNcyLhxVgmqS8ZKhsblVeu
# AQhYlRjNacGcslkhXqNjK5Va4tuOAPy2n1Q8UUrHbUd0g+xJ9Bm0G0LZXyvCWyKH IpQ0JgavABqibJolc3BKrVtVV1igKiX/N7Pi8RtY1K18toaMDhdEfhBRzO/XB0+P
# kuNEHFQiLuCY6Iv0myq6iX6tjuHehZlFSh80b5BVV9tNLwNR5Eqz1klxMhoghJOA AQhYlRjNacGcslkhXqNjK5Va4tuOAPy2n1Q8UUrHbUd0g+xJ9Bm0G0LZXyvCWyKH
# </data> kuNEHFQiLuCY6Iv0myq6iX6tjuHehZlFSh80b5BVV9tNLwNR5Eqz1klxMhoghJOA
# <amp xmlns='http://jabber.org/protocol/amp'> </data>
# <rule condition='deliver-at' value='stored' action='error'/> <amp xmlns='http://jabber.org/protocol/amp'>
# <rule condition='match-resource' value='exact' action='error'/> <rule condition='deliver-at' value='stored' action='error'/>
# </amp> <rule condition='match-resource' value='exact' action='error'/>
# </message> </amp>
</message>
"""
def ReceiveHandler(self,conn,stanza): def ReceiveHandler(self,conn,stanza):
""" Receive next portion of incoming datastream and store it write """ Receive next portion of incoming datastream and store it write

View file

@ -19,6 +19,7 @@ class IdleObject:
''' '''
def __init__(self): def __init__(self):
self.fd = -1 self.fd = -1
pass
def pollend(self): def pollend(self):
''' called on stream failure ''' ''' called on stream failure '''

View file

@ -19,7 +19,7 @@ Protocol module contains tools that is needed for processing of
xmpp-related data structures. xmpp-related data structures.
""" """
from simplexml import Node, NodeBuilder from simplexml import Node,NodeBuilder,ustr
import time import time
NS_ACTIVITY ='http://jabber.org/protocol/activity' # XEP-0108 NS_ACTIVITY ='http://jabber.org/protocol/activity' # XEP-0108
NS_ADDRESS ='http://jabber.org/protocol/address' # XEP-0033 NS_ADDRESS ='http://jabber.org/protocol/address' # XEP-0033
@ -458,7 +458,7 @@ class Message(Protocol):
self.setTag('html',namespace=NS_XHTML_IM).addChild(node=dom) self.setTag('html',namespace=NS_XHTML_IM).addChild(node=dom)
except Exception, e: except Exception, e:
print "Error", e print "Error", e
#FIXME: log. we could not set xhtml (parse error, whatever) pass #FIXME: log. we could not set xhtml (parse error, whatever)
def setSubject(self,val): def setSubject(self,val):
""" Sets the subject of the message. """ """ Sets the subject of the message. """
self.setTagData('subject',val) self.setTagData('subject',val)

View file

@ -13,6 +13,7 @@
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details. ## GNU General Public License for more details.
__version__="$Id"
""" """
When your handler is called it is getting the session instance as the first argument. When your handler is called it is getting the session instance as the first argument.
@ -22,10 +23,6 @@ one client for each connection. Is is specifically important when you are
writing the server. writing the server.
""" """
__version__="$Id"
import random
import simplexml
from protocol import * from protocol import *
# Transport-level flags # Transport-level flags
@ -252,6 +249,7 @@ class Session:
features=Node('stream:features') features=Node('stream:features')
if NS_TLS in self.waiting_features: if NS_TLS in self.waiting_features:
features.T.starttls.setNamespace(NS_TLS) features.T.starttls.setNamespace(NS_TLS)
features.T.starttls.T.required
if NS_SASL in self.waiting_features: if NS_SASL in self.waiting_features:
features.T.mechanisms.setNamespace(NS_SASL) features.T.mechanisms.setNamespace(NS_SASL)
for mec in self._owner.SASL.mechanisms: for mec in self._owner.SASL.mechanisms:

View file

@ -27,13 +27,11 @@ Transports are stackable so you - f.e. TLS use HTPPROXYsocket or TCPsocket as mo
Also exception 'error' is defined to allow capture of this module specific exceptions. Also exception 'error' is defined to allow capture of this module specific exceptions.
""" """
import socket import socket,select,base64,dispatcher
import select
import base64
import dispatcher
from simplexml import ustr from simplexml import ustr
from client import PlugIn from client import PlugIn
from protocol import * from protocol import *
import sys
import os import os
import errno import errno
@ -66,15 +64,13 @@ class error:
"""Serialise exception into pre-cached descriptive string.""" """Serialise exception into pre-cached descriptive string."""
return self._comment return self._comment
DBG_SOCKET = "socket"
class TCPsocket(PlugIn): class TCPsocket(PlugIn):
""" This class defines direct TCP connection method. """ """ This class defines direct TCP connection method. """
def __init__(self, server=None, use_srv=True): def __init__(self, server=None, use_srv=True):
""" Cache connection point 'server'. 'server' is the tuple of (host, port) """ Cache connection point 'server'. 'server' is the tuple of (host, port)
absolutely the same as standard tcp socket uses. """ absolutely the same as standard tcp socket uses. """
PlugIn.__init__(self) PlugIn.__init__(self)
self.DBG_LINE = DBG_SOCKET self.DBG_LINE='socket'
self._exported_methods=[self.send,self.disconnect] self._exported_methods=[self.send,self.disconnect]
self._server = server self._server = server
@ -87,7 +83,6 @@ class TCPsocket(PlugIn):
if not self.connect(self._server): return if not self.connect(self._server): return
self._owner.Connection=self self._owner.Connection=self
self._owner.RegisterDisconnectHandler(self.disconnected) self._owner.RegisterDisconnectHandler(self.disconnected)
owner.debug_flags.append(DBG_SOCKET)
return 'ok' return 'ok'
def getHost(self): def getHost(self):
@ -238,7 +233,7 @@ class TLS(PlugIn):
""" """
if 'TLS' in owner.__dict__: return # Already enabled. if 'TLS' in owner.__dict__: return # Already enabled.
PlugIn.PlugIn(self,owner) PlugIn.PlugIn(self,owner)
self.DBG_LINE='TLS' DBG_LINE='TLS'
if now: return self._startSSL() if now: return self._startSSL()
if self._owner.Dispatcher.Stream.features: if self._owner.Dispatcher.Stream.features:
try: self.FeaturesHandler(self._owner.Dispatcher,self._owner.Dispatcher.Stream.features) try: self.FeaturesHandler(self._owner.Dispatcher,self._owner.Dispatcher.Stream.features)
@ -271,7 +266,7 @@ class TLS(PlugIn):
def _startSSL(self): def _startSSL(self):
""" Immidiatedly switch socket to TLS mode. Used internally.""" """ Immidiatedly switch socket to TLS mode. Used internally."""
# Here we should switch pending_data to hint mode. """ Here we should switch pending_data to hint mode."""
tcpsock=self._owner.Connection tcpsock=self._owner.Connection
tcpsock._sslObj = socket.ssl(tcpsock._sock, None, None) tcpsock._sslObj = socket.ssl(tcpsock._sock, None, None)
tcpsock._sslIssuer = tcpsock._sslObj.issuer() tcpsock._sslIssuer = tcpsock._sslObj.issuer()

View file

@ -14,9 +14,7 @@
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details. ## GNU General Public License for more details.
import socket import socket,select,base64,dispatcher_nb
import base64
import dispatcher_nb
import struct import struct
from simplexml import ustr from simplexml import ustr
from client import PlugIn from client import PlugIn
@ -30,6 +28,7 @@ import errno
import time import time
import traceback import traceback
import thread
import logging import logging
log = logging.getLogger('gajim.c.x.transports_nb') log = logging.getLogger('gajim.c.x.transports_nb')
@ -38,7 +37,6 @@ import common.gajim
USE_PYOPENSSL = False USE_PYOPENSSL = False
DBG_NONBLOCKINGTLS= 'NonBlockingTLS'
try: try:
#raise ImportError("Manually disabled PyOpenSSL") #raise ImportError("Manually disabled PyOpenSSL")
import OpenSSL.SSL import OpenSSL.SSL
@ -140,10 +138,10 @@ class SSLWrapper:
can indicate that the socket has been closed, so to be sure, we avoid can indicate that the socket has been closed, so to be sure, we avoid
this by returning None. """ this by returning None. """
raise NotImplementedError() raise NotImplementedException()
def send(self, data, flags=None, now = False): def send(self, data, flags=None, now = False):
raise NotImplementedError() raise NotImplementedException()
class PyOpenSSLWrapper(SSLWrapper): class PyOpenSSLWrapper(SSLWrapper):
'''Wrapper class for PyOpenSSL's recv() and send() methods''' '''Wrapper class for PyOpenSSL's recv() and send() methods'''
@ -663,8 +661,6 @@ class NonBlockingTcp(PlugIn, IdleObject):
''' Return the 'port' value that is connection is [will be] made to.''' ''' Return the 'port' value that is connection is [will be] made to.'''
return self._server[1] return self._server[1]
DBG_NONBLOCKINGTLS = "NonBlockingTLS"
class NonBlockingTLS(PlugIn): class NonBlockingTLS(PlugIn):
''' TLS connection used to encrypts already estabilished tcp connection.''' ''' TLS connection used to encrypts already estabilished tcp connection.'''
@ -683,13 +679,12 @@ class NonBlockingTLS(PlugIn):
if 'NonBlockingTLS' in owner.__dict__: if 'NonBlockingTLS' in owner.__dict__:
return # Already enabled. return # Already enabled.
PlugIn.PlugIn(self, owner) PlugIn.PlugIn(self, owner)
self.DBG_LINE = DBG_NONBLOCKINGTLS DBG_LINE='NonBlockingTLS'
owner.debug_flags.append(DBG_NONBLOCKINGTLS)
self.on_tls_start = on_tls_start self.on_tls_start = on_tls_start
if now: if now:
try: try:
res = self._startSSL() res = self._startSSL()
except Exception: except Exception, e:
log.error("PlugIn: while trying _startSSL():", exc_info=True) log.error("PlugIn: while trying _startSSL():", exc_info=True)
#traceback.print_exc() #traceback.print_exc()
self._owner.socket.pollend() self._owner.socket.pollend()
@ -864,7 +859,7 @@ class NonBlockingTLS(PlugIn):
self.DEBUG('Got starttls proceed response. Switching to TLS/SSL...','ok') self.DEBUG('Got starttls proceed response. Switching to TLS/SSL...','ok')
try: try:
self._startSSL() self._startSSL()
except Exception: except Exception, e:
log.error("StartTLSHandler:", exc_info=True) log.error("StartTLSHandler:", exc_info=True)
#traceback.print_exc() #traceback.print_exc()
self._owner.socket.pollend() self._owner.socket.pollend()
@ -1105,9 +1100,9 @@ class NBSOCKS5PROXYsocket(NonBlockingTcp):
return return
# Get the bound address/port # Get the bound address/port
elif reply[3] == "\x01": elif reply[3] == "\x01":
pass # begin, end = 3, 7 begin, end = 3, 7
elif reply[3] == "\x03": elif reply[3] == "\x03":
pass # begin, end = 4, 4 + reply[4] begin, end = 4, 4 + reply[4]
else: else:
self.DEBUG('Invalid proxy reply', 'error') self.DEBUG('Invalid proxy reply', 'error')
self._owner.disconnected() self._owner.disconnected()

View file

@ -71,7 +71,7 @@ class ZeroconfListener(IdleObject):
# will fail when port is busy, or we don't have rights to bind # will fail when port is busy, or we don't have rights to bind
try: try:
self._serv.bind((ai[4][0], self.port)) self._serv.bind((ai[4][0], self.port))
except Exception: except Exception, e:
# unable to bind, show error dialog # unable to bind, show error dialog
return None return None
self._serv.listen(socket.SOMAXCONN) self._serv.listen(socket.SOMAXCONN)
@ -87,14 +87,14 @@ class ZeroconfListener(IdleObject):
def pollin(self): def pollin(self):
''' accept a new incomming connection and notify queue''' ''' accept a new incomming connection and notify queue'''
sock = self.accept_conn() sock = self.accept_conn()
# loop through roster to find who has connected to us ''' loop through roster to find who has connected to us'''
from_jid = None from_jid = None
ipaddr = sock[1][0] ipaddr = sock[1][0]
for jid in self.conn_holder.getRoster().keys(): for jid in self.conn_holder.getRoster().keys():
entry = self.conn_holder.getRoster().getItem(jid) entry = self.conn_holder.getRoster().getItem(jid)
if (entry['address'] == ipaddr): if (entry['address'] == ipaddr):
from_jid = jid from_jid = jid
break break;
P2PClient(sock[0], ipaddr, sock[1][1], self.conn_holder, [], from_jid) P2PClient(sock[0], ipaddr, sock[1][1], self.conn_holder, [], from_jid)
def disconnect(self): def disconnect(self):
@ -158,7 +158,7 @@ class P2PClient(IdleObject):
self.conn_holder.add_connection(self, self.Server, port, self.to) self.conn_holder.add_connection(self, self.Server, port, self.to)
# count messages in queue # count messages in queue
for val in self.stanzaqueue: for val in self.stanzaqueue:
is_message = val[1] stanza, is_message = val
if is_message: if is_message:
if self.fd == -1: if self.fd == -1:
if on_not_ok: if on_not_ok:
@ -482,6 +482,18 @@ class P2PConnection(IdleObject, PlugIn):
self.disconnect() self.disconnect()
return True return True
def onreceive(self, recv_handler):
if not recv_handler:
if hasattr(self._owner, 'Dispatcher'):
self.on_receive = self._owner.Dispatcher.ProcessNonBlocking
else:
self.on_receive = None
return
_tmp = self.on_receive
# make sure this cb is not overriden by recursive calls
if not recv_handler(None) and _tmp == self.on_receive:
self.on_receive = recv_handler
def disconnect(self): def disconnect(self):
''' Closes the socket. ''' ''' Closes the socket. '''
gajim.idlequeue.remove_timeout(self.fd) gajim.idlequeue.remove_timeout(self.fd)

View file

@ -23,6 +23,7 @@
## along with Gajim. If not, see <http://www.gnu.org/licenses/>. ## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
## ##
import os
import time import time
import socket import socket
@ -76,6 +77,7 @@ class ConnectionBytestream(connection_handlers.ConnectionBytestream):
receiver = file_props['receiver'] receiver = file_props['receiver']
if sender is None: if sender is None:
sender = file_props['sender'] sender = file_props['sender']
proxyhosts = []
sha_str = helpers.get_auth_sha(file_props['sid'], sender, sha_str = helpers.get_auth_sha(file_props['sid'], sender,
receiver) receiver)
file_props['sha_str'] = sha_str file_props['sha_str'] = sha_str
@ -381,7 +383,6 @@ class ConnectionHandlersZeroconf(ConnectionVcard, ConnectionBytestream, connecti
try: try:
idle.init() idle.init()
except Exception: except Exception:
global HAS_IDLE
HAS_IDLE = False HAS_IDLE = False
def _messageCB(self, ip, con, msg): def _messageCB(self, ip, con, msg):

View file

@ -56,7 +56,8 @@ class Roster:
if not contact: if not contact:
return return
host, address, port, txt = contact[4:7] + contact[8] (service_jid, domain, interface, protocol, host, address, port, bare_jid, txt) \
= contact
self._data[jid]={} self._data[jid]={}
self._data[jid]['ask'] = 'no' #? self._data[jid]['ask'] = 'no' #?

View file

@ -292,7 +292,7 @@ class Zeroconf:
return True return True
else: else:
return False return False
except dbus.DBusException: except dbus.DBusException, e:
gajim.log.debug("Can't remove service. That should not happen") gajim.log.debug("Can't remove service. That should not happen")
def browse_domain(self, interface, protocol, domain): def browse_domain(self, interface, protocol, domain):

View file

@ -18,6 +18,7 @@
## ##
from common import gajim from common import gajim
import sys
import select import select
import re import re
from string import split from string import split
@ -115,8 +116,7 @@ class Zeroconf:
} }
# Split on '.' but do not split on '\.' # Split on '.' but do not split on '\.'
result = re.split('(?<!\\\\)\.', fullname) name, stype, protocol, domain, dummy = re.split('(?<!\\\\)\.', fullname)
name, protocol, domain = result[0] + result[2:4]
# Replace the escaped values # Replace the escaped values
for src, trg in escaping.items(): for src, trg in escaping.items():
@ -252,7 +252,7 @@ class Zeroconf:
self.announced = False self.announced = False
return True return True
except pybonjour.BonjourError, e: except pybonjour.BonjourError, e:
gajim.log.debug(e) geajim.log.debug(e)
return False return False
@ -330,7 +330,7 @@ class Zeroconf:
try: try:
pybonjour.DNSServiceUpdateRecord(self.service_sdRef, None, 0, self.txt) pybonjour.DNSServiceUpdateRecord(self.service_sdRef, None, 0, self.txt)
except pybonjour.BonjourError: except pybonjour.BonjourError, e:
return False return False
return True return True

View file

@ -57,7 +57,7 @@ from common import connection
from common import passwords from common import passwords
from common import zeroconf from common import zeroconf
from common import dataforms from common import dataforms
from common import GnuPG from common import pep
from common.exceptions import GajimGeneralException from common.exceptions import GajimGeneralException
@ -308,6 +308,9 @@ class PreferencesWindow:
self.xml.get_widget('sounds_scrolledwindow').set_sensitive(False) self.xml.get_widget('sounds_scrolledwindow').set_sensitive(False)
self.xml.get_widget('browse_sounds_hbox').set_sensitive(False) self.xml.get_widget('browse_sounds_hbox').set_sensitive(False)
# sound player
player = gajim.config.get('soundplayer')
# sounds treeview # sounds treeview
self.sound_tree = self.xml.get_widget('sounds_treeview') self.sound_tree = self.xml.get_widget('sounds_treeview')
@ -610,6 +613,7 @@ class PreferencesWindow:
helpers.update_optional_features() helpers.update_optional_features()
def apply_speller(self): def apply_speller(self):
for acct in gajim.connections:
for ctrl in gajim.interface.msg_win_mgr.controls(): for ctrl in gajim.interface.msg_win_mgr.controls():
if isinstance(ctrl, chat_control.ChatControlBase): if isinstance(ctrl, chat_control.ChatControlBase):
try: try:
@ -621,6 +625,7 @@ class PreferencesWindow:
gtkspell.Spell(ctrl.msg_textview) gtkspell.Spell(ctrl.msg_textview)
def remove_speller(self): def remove_speller(self):
for acct in gajim.connections:
for ctrl in gajim.interface.msg_win_mgr.controls(): for ctrl in gajim.interface.msg_win_mgr.controls():
if isinstance(ctrl, chat_control.ChatControlBase): if isinstance(ctrl, chat_control.ChatControlBase):
try: try:
@ -640,7 +645,7 @@ class PreferencesWindow:
lang = gajim.LANG lang = gajim.LANG
tv = gtk.TextView() tv = gtk.TextView()
try: try:
gtkspell.Spell(tv, lang) spell = gtkspell.Spell(tv, lang)
except: except:
dialogs.ErrorDialog( dialogs.ErrorDialog(
_('Dictionary for lang %s not available') % lang, _('Dictionary for lang %s not available') % lang,
@ -1027,6 +1032,7 @@ class PreferencesWindow:
return return
buf = self.xml.get_widget('msg_textview').get_buffer() buf = self.xml.get_widget('msg_textview').get_buffer()
first_iter, end_iter = buf.get_bounds() first_iter, end_iter = buf.get_bounds()
name = model.get_value(iter, 0)
model.set_value(iter, 1, buf.get_text(first_iter, end_iter)) model.set_value(iter, 1, buf.get_text(first_iter, end_iter))
def on_msg_treeview_key_press_event(self, widget, event): def on_msg_treeview_key_press_event(self, widget, event):
@ -1684,7 +1690,7 @@ class AccountsWindow:
gajim.interface.instances[account]['remove_account'] = \ gajim.interface.instances[account]['remove_account'] = \
RemoveAccountWindow(account) RemoveAccountWindow(account)
if win_opened: if win_opened:
dialogs.ConfirmationDialog( dialog = dialogs.ConfirmationDialog(
_('You have opened chat in account %s') % account, _('You have opened chat in account %s') % account,
_('All chat and groupchat windows will be closed. Do you want to ' _('All chat and groupchat windows will be closed. Do you want to '
'continue?'), 'continue?'),
@ -1889,7 +1895,7 @@ class AccountsWindow:
def on_synchronise_contacts_button1_clicked(self, widget): def on_synchronise_contacts_button1_clicked(self, widget):
try: try:
dialogs.SynchroniseSelectAccountDialog(self.current_account) dialog = dialogs.SynchroniseSelectAccountDialog(self.current_account)
except GajimGeneralException: except GajimGeneralException:
# If we showed ErrorDialog, there will not be dialog instance # If we showed ErrorDialog, there will not be dialog instance
return return
@ -1903,7 +1909,7 @@ class AccountsWindow:
self.xml.get_widget('password_entry1').set_text(new_password) self.xml.get_widget('password_entry1').set_text(new_password)
try: try:
dialogs.ChangePasswordDialog(self.current_account, on_changed) dialog = dialogs.ChangePasswordDialog(self.current_account, on_changed)
except GajimGeneralException: except GajimGeneralException:
# if we showed ErrorDialog, there will not be dialog instance # if we showed ErrorDialog, there will not be dialog instance
return return
@ -2068,10 +2074,14 @@ class AccountsWindow:
gajim.config.set_per('accounts', self.current_account, 'keyid', gajim.config.set_per('accounts', self.current_account, 'keyid',
keyID[0]) keyID[0])
dialogs.ChooseGPGKeyDialog(_('OpenPGP Key Selection'), instance = dialogs.ChooseGPGKeyDialog(_('OpenPGP Key Selection'),
_('Choose your OpenPGP key'), secret_keys, on_key_selected) _('Choose your OpenPGP key'), secret_keys, on_key_selected)
def on_use_gpg_agent_checkbutton_toggled(self, widget): def on_use_gpg_agent_checkbutton_toggled(self, widget):
if self.current_account == gajim.ZEROCONF_ACC_NAME:
wiget_name_ext = '2'
else:
wiget_name_ext = '1'
self.on_checkbutton_toggled(widget, 'use_gpg_agent') self.on_checkbutton_toggled(widget, 'use_gpg_agent')
def on_edit_details_button1_clicked(self, widget): def on_edit_details_button1_clicked(self, widget):
@ -2461,7 +2471,7 @@ class GroupchatConfigWindow:
return return
model = self.affiliation_treeview[affiliation].get_model() model = self.affiliation_treeview[affiliation].get_model()
model.append((jid,'', '', '')) model.append((jid,'', '', ''))
dialogs.InputDialog(title, prompt, ok_handler=on_ok) instance = dialogs.InputDialog(title, prompt, ok_handler=on_ok)
def on_remove_button_clicked(self, widget, affiliation): def on_remove_button_clicked(self, widget, affiliation):
selection = self.affiliation_treeview[affiliation].get_selection() selection = self.affiliation_treeview[affiliation].get_selection()
@ -2567,7 +2577,7 @@ class RemoveAccountWindow:
gajim.connections[self.account].unregister_account( gajim.connections[self.account].unregister_account(
self._on_remove_success) self._on_remove_success)
dialogs.PassphraseDialog( w = dialogs.PassphraseDialog(
_('Password Required'), _('Password Required'),
_('Enter your password for account %s') % self.account, _('Enter your password for account %s') % self.account,
_('Save password'), ok_handler=on_ok) _('Save password'), ok_handler=on_ok)
@ -2578,7 +2588,7 @@ class RemoveAccountWindow:
self._on_remove_success(True) self._on_remove_success(True)
if gajim.connections[self.account].connected: if gajim.connections[self.account].connected:
dialogs.ConfirmationDialog( dialog = dialogs.ConfirmationDialog(
_('Account "%s" is connected to the server') % self.account, _('Account "%s" is connected to the server') % self.account,
_('If you remove it, the connection will be lost.'), _('If you remove it, the connection will be lost.'),
on_response_ok=remove) on_response_ok=remove)

View file

@ -597,7 +597,7 @@ class ConversationTextview:
def on_textview_motion_notify_event(self, widget, event): def on_textview_motion_notify_event(self, widget, event):
'''change the cursor to a hand when we are over a mail or an '''change the cursor to a hand when we are over a mail or an
url''' url'''
pointer_x, pointer_y = self.tv.window.get_pointer()[0:2] pointer_x, pointer_y, spam = self.tv.window.get_pointer()
x, y = self.tv.window_to_buffer_coords(gtk.TEXT_WINDOW_TEXT, x, y = self.tv.window_to_buffer_coords(gtk.TEXT_WINDOW_TEXT,
pointer_x, pointer_y) pointer_x, pointer_y)
tags = self.tv.get_iter_at_location(x, y).get_tags() tags = self.tv.get_iter_at_location(x, y).get_tags()

View file

@ -567,6 +567,7 @@ class SingleForm(gtk.Table, object):
def on_jid_multi_remove_button_clicked(self, widget, treeview, field): def on_jid_multi_remove_button_clicked(self, widget, treeview, field):
selection = treeview.get_selection() selection = treeview.get_selection()
model = treeview.get_model()
deleted = [] deleted = []
def remove(model, path, iter_, deleted): def remove(model, path, iter_, deleted):

View file

@ -427,6 +427,7 @@ class ChangeActivityDialog:
''' '''
Return activity and messsage (None if no activity selected) Return activity and messsage (None if no activity selected)
''' '''
message = None
if self.checkbutton.get_active(): if self.checkbutton.get_active():
pep.user_send_activity(self.account, self.activity, pep.user_send_activity(self.account, self.activity,
self.subactivity, self.subactivity,
@ -650,7 +651,7 @@ class ChangeStatusMessageDialog:
self.preset_messages_dict[msg_name] = msg_text self.preset_messages_dict[msg_name] = msg_text
gajim.config.set_per('statusmsg', msg_name, 'message', gajim.config.set_per('statusmsg', msg_name, 'message',
msg_text_1l) msg_text_1l)
ConfirmationDialog(_('Overwrite Status Message?'), dlg2 = ConfirmationDialog(_('Overwrite Status Message?'),
_('This name is already used. Do you want to overwrite this ' _('This name is already used. Do you want to overwrite this '
'status message?'), on_response_ok=on_ok2) 'status message?'), on_response_ok=on_ok2)
return return
@ -1576,7 +1577,7 @@ class DubbleInputDialog:
def on_cancelbutton_clicked(self, widget): def on_cancelbutton_clicked(self, widget):
self.dialog.destroy() self.dialog.destroy()
if not self.cancel_handler: if not cancel_handler:
return return
if isinstance(self.cancel_handler, tuple): if isinstance(self.cancel_handler, tuple):
self.cancel_handler[0](*self.cancel_handler[1:]) self.cancel_handler[0](*self.cancel_handler[1:])
@ -1852,7 +1853,7 @@ class SynchroniseSelectAccountDialog:
return return
else: else:
try: try:
SynchroniseSelectContactsDialog(self.account, remote_account) dialog = SynchroniseSelectContactsDialog(self.account, remote_account)
except GajimGeneralException: except GajimGeneralException:
# if we showed ErrorDialog, there will not be dialog instance # if we showed ErrorDialog, there will not be dialog instance
return return
@ -2194,7 +2195,7 @@ class SingleMessageWindow:
if lang: if lang:
spell1.set_language(lang) spell1.set_language(lang)
spell2.set_language(lang) spell2.set_language(lang)
except gobject.GError: except gobject.GError, msg:
AspellDictError(lang) AspellDictError(lang)
self.prepare_widgets_for(self.action) self.prepare_widgets_for(self.action)
@ -2968,7 +2969,7 @@ class InvitationReceivedDialog:
except GajimGeneralException: except GajimGeneralException:
pass pass
YesNoDialog(pritext, sectext, on_response_yes=on_yes) dialog = YesNoDialog(pritext, sectext, on_response_yes=on_yes)
class ProgressDialog: class ProgressDialog:
def __init__(self, title_text, during_text, messages_queue): def __init__(self, title_text, during_text, messages_queue):
@ -3155,6 +3156,7 @@ class AddSpecialNotificationDialog:
self.window.destroy() self.window.destroy()
def on_listen_sound_combobox_changed(self, widget): def on_listen_sound_combobox_changed(self, widget):
model = widget.get_model()
active = widget.get_active() active = widget.get_active()
if active == 1: # user selected 'choose sound' if active == 1: # user selected 'choose sound'
def on_ok(widget, path_to_snd_file): def on_ok(widget, path_to_snd_file):
@ -3657,6 +3659,9 @@ class TransformChatToMUC:
'server_and_guests_hseparator', 'server_select_label'): 'server_and_guests_hseparator', 'server_select_label'):
self.__dict__[widget_to_add] = self.xml.get_widget(widget_to_add) self.__dict__[widget_to_add] = self.xml.get_widget(widget_to_add)
# set comboboxentry
renderer_servers = gtk.CellRendererText()
server_list = [] server_list = []
self.servers = gtk.ListStore(str) self.servers = gtk.ListStore(str)
self.server_list_comboboxentry.set_model(self.servers) self.server_list_comboboxentry.set_model(self.servers)
@ -3899,7 +3904,7 @@ class GPGInfoWindow:
'encrypt messages.') 'encrypt messages.')
image = 'security-low-big.png' image = 'security-low-big.png'
else: else:
error = gajim.connections[account].gpg.encrypt('test', [keyID])[1] msgenc, error = gajim.connections[account].gpg.encrypt('test', [keyID])
if error: if error:
verification_status = _('''Contact's identity NOT verified''') verification_status = _('''Contact's identity NOT verified''')
info = _('GPG key is assigned to this contact, but <b>you do not ' info = _('GPG key is assigned to this contact, but <b>you do not '

View file

@ -969,6 +969,7 @@ _('This service does not contain any items to browse.'))
def _agent_info(self, jid, node, identities, features, data): def _agent_info(self, jid, node, identities, features, data):
'''Callback for when we receive info about an agent's item.''' '''Callback for when we receive info about an agent's item.'''
addr = get_agent_address(jid, node)
iter = self._find_item(jid, node) iter = self._find_item(jid, node)
if not iter: if not iter:
# Not in the treeview, stop # Not in the treeview, stop
@ -1098,7 +1099,7 @@ class ToplevelAgentBrowser(AgentBrowser):
if not props or self.tooltip.id != props[0]: if not props or self.tooltip.id != props[0]:
self.tooltip.hide_tooltip() self.tooltip.hide_tooltip()
if props: if props:
row = props[0] [row, col, x, y] = props
iter = None iter = None
try: try:
iter = self.model.get_iter(row) iter = self.model.get_iter(row)
@ -1429,7 +1430,7 @@ class ToplevelAgentBrowser(AgentBrowser):
def _find_category(self, cat, type_=None): def _find_category(self, cat, type_=None):
'''Looks up a category row and returns the iterator to it, or None.''' '''Looks up a category row and returns the iterator to it, or None.'''
cat = self._friendly_category(cat, type_)[0] cat, prio = self._friendly_category(cat, type_)
iter = self.model.get_iter_root() iter = self.model.get_iter_root()
while iter: while iter:
if self.model.get_value(iter, 3).decode('utf-8') == cat: if self.model.get_value(iter, 3).decode('utf-8') == cat:
@ -1539,6 +1540,7 @@ class ToplevelAgentBrowser(AgentBrowser):
self._expand_all() self._expand_all()
def _update_error(self, iter_, jid, node): def _update_error(self, iter_, jid, node):
addr = get_agent_address(jid, node)
self.model[iter_][4] = 2 self.model[iter_][4] = 2
self._progress += 1 self._progress += 1
self._update_progressbar() self._update_progressbar()
@ -1633,6 +1635,7 @@ class MucBrowser(AgentBrowser):
room = model[iter][1].decode('utf-8') room = model[iter][1].decode('utf-8')
if 'join_gc' not in gajim.interface.instances[self.account]: if 'join_gc' not in gajim.interface.instances[self.account]:
try: try:
room_jid = '%s@%s' % (service, room)
dialogs.JoinGroupchatWindow(self.account, service) dialogs.JoinGroupchatWindow(self.account, service)
except GajimGeneralException: except GajimGeneralException:
pass pass

View file

@ -28,6 +28,8 @@ import sys
import gtk import gtk
import gtkgui_helpers import gtkgui_helpers
import dialogs
from common import gajim from common import gajim
from common import helpers from common import helpers
@ -149,6 +151,7 @@ class FeaturesWindow:
if not rows: if not rows:
return return
path = rows[0] path = rows[0]
available = self.model[path][1]
feature = self.model[path][0].decode('utf-8') feature = self.model[path][0].decode('utf-8')
text = self.features[feature][1] + '\n' text = self.features[feature][1] + '\n'
if os.name == 'nt': if os.name == 'nt':
@ -184,6 +187,7 @@ class FeaturesWindow:
def gpg_available(self): def gpg_available(self):
if os.name == 'nt': if os.name == 'nt':
return False return False
from common import gajim
return gajim.HAVE_GPG return gajim.HAVE_GPG
def network_manager_available(self): def network_manager_available(self):
@ -296,6 +300,7 @@ class FeaturesWindow:
return False return False
def pycrypto_available(self): def pycrypto_available(self):
from common import gajim
return gajim.HAVE_PYCRYPTO return gajim.HAVE_PYCRYPTO
def docutils_available(self): def docutils_available(self):
@ -306,6 +311,7 @@ class FeaturesWindow:
return True return True
def pysexy_available(self): def pysexy_available(self):
from common import gajim
return gajim.HAVE_PYSEXY return gajim.HAVE_PYSEXY
# vim: se ts=3: # vim: se ts=3:

View file

@ -150,7 +150,7 @@ class FileTransfersWindow:
dialog.destroy() dialog.destroy()
if 'file-name' not in file_props: if 'file-name' not in file_props:
return return
path = os.path.split(file_props['file-name'])[0] (path, file) = os.path.split(file_props['file-name'])
if os.path.exists(path) and os.path.isdir(path): if os.path.exists(path) and os.path.isdir(path):
helpers.launch_file_manager(path) helpers.launch_file_manager(path)
self.tree.get_selection().unselect_all() self.tree.get_selection().unselect_all()
@ -276,7 +276,7 @@ _('Connection with peer cannot be established.'))
return return
(jid, resource) = contact.split('/', 1) (jid, resource) = contact.split('/', 1)
contact = gajim.contacts.create_contact(jid=jid, resource=resource) contact = gajim.contacts.create_contact(jid=jid, resource=resource)
file_name = os.path.split(file_path)[1] (file_dir, file_name) = os.path.split(file_path)
file_props = self.get_send_file_props(account, contact, file_props = self.get_send_file_props(account, contact,
file_path, file_name, file_desc) file_path, file_name, file_desc)
if file_props is None: if file_props is None:
@ -307,7 +307,7 @@ _('Connection with peer cannot be established.'))
if 'desc' in file_props: if 'desc' in file_props:
sec_text += '\n\t' + _('Description: %s') % file_props['desc'] sec_text += '\n\t' + _('Description: %s') % file_props['desc']
prim_text = _('%s wants to send you a file:') % contact.jid prim_text = _('%s wants to send you a file:') % contact.jid
dialog = None dialog, dialog2 = None, None
def on_response_ok(account, contact, file_props): def on_response_ok(account, contact, file_props):
@ -600,7 +600,7 @@ _('Connection with peer cannot be established.'))
text_labels += '<b>' + _('Recipient: ') + '</b>' text_labels += '<b>' + _('Recipient: ') + '</b>'
if file_props['type'] == 'r': if file_props['type'] == 'r':
file_name = os.path.split(file_props['file-name'])[1] (file_path, file_name) = os.path.split(file_props['file-name'])
else: else:
file_name = file_props['name'] file_name = file_props['name']
text_props = gobject.markup_escape_text(file_name) + '\n' text_props = gobject.markup_escape_text(file_name) + '\n'
@ -621,13 +621,14 @@ _('Connection with peer cannot be established.'))
def on_transfers_list_motion_notify_event(self, widget, event): def on_transfers_list_motion_notify_event(self, widget, event):
pointer = self.tree.get_pointer() pointer = self.tree.get_pointer()
orig = widget.window.get_origin()
props = widget.get_path_at_pos(int(event.x), int(event.y)) props = widget.get_path_at_pos(int(event.x), int(event.y))
self.height_diff = pointer[1] - int(event.y) self.height_diff = pointer[1] - int(event.y)
if self.tooltip.timeout > 0: if self.tooltip.timeout > 0:
if not props or self.tooltip.id != props[0]: if not props or self.tooltip.id != props[0]:
self.tooltip.hide_tooltip() self.tooltip.hide_tooltip()
if props: if props:
row = props[0] [row, col, x, y] = props
iter = None iter = None
try: try:
iter = self.model.get_iter(row) iter = self.model.get_iter(row)
@ -889,7 +890,7 @@ _('Connection with peer cannot be established.'))
self.tooltip.hide_tooltip() self.tooltip.hide_tooltip()
iter = None iter = None
try: try:
iter = self.tree.get_selection().get_selected()[1] store, iter = self.tree.get_selection().get_selected()
except TypeError: except TypeError:
self.tree.get_selection().unselect_all() self.tree.get_selection().unselect_all()
@ -907,7 +908,8 @@ _('Connection with peer cannot be established.'))
self.tooltip.hide_tooltip() self.tooltip.hide_tooltip()
path = None path = None
try: try:
path = self.tree.get_path_at_pos(int(event.x), int(event.y))[0] path, column, x, y = self.tree.get_path_at_pos(int(event.x),
int(event.y))
except TypeError: except TypeError:
self.tree.get_selection().unselect_all() self.tree.get_selection().unselect_all()
if path is None: if path is None:
@ -920,7 +922,8 @@ _('Connection with peer cannot be established.'))
self.tooltip.hide_tooltip() self.tooltip.hide_tooltip()
path, iter = None, None path, iter = None, None
try: try:
path = self.tree.get_path_at_pos(int(event.x), int(event.y))[0] path, column, x, y = self.tree.get_path_at_pos(int(event.x),
int(event.y))
except TypeError: except TypeError:
self.tree.get_selection().unselect_all() self.tree.get_selection().unselect_all()
if event.button == 3: # Right click if event.button == 3: # Right click
@ -940,7 +943,7 @@ _('Connection with peer cannot be established.'))
file_props = self.files_props[sid[0]][sid[1:]] file_props = self.files_props[sid[0]][sid[1:]]
if 'file-name' not in file_props: if 'file-name' not in file_props:
return return
path = os.path.split(file_props['file-name'])[0] (path, file) = os.path.split(file_props['file-name'])
if os.path.exists(path) and os.path.isdir(path): if os.path.exists(path) and os.path.isdir(path):
helpers.launch_file_manager(path) helpers.launch_file_manager(path)

View file

@ -28,6 +28,7 @@
# gajim-remote help will show you the D-BUS API of Gajim # gajim-remote help will show you the D-BUS API of Gajim
import sys import sys
import os
import locale import locale
import signal import signal
signal.signal(signal.SIGINT, signal.SIG_DFL) # ^C exits the application signal.signal(signal.SIGINT, signal.SIG_DFL) # ^C exits the application

View file

@ -111,7 +111,7 @@ def parseOpts():
try: try:
shortargs = 'hqvl:p:c:' shortargs = 'hqvl:p:c:'
longargs = 'help quiet verbose loglevel= profile= config_path=' longargs = 'help quiet verbose loglevel= profile= config_path='
opts = getopt.getopt(sys.argv[1:], shortargs, longargs.split())[0] opts, args = getopt.getopt(sys.argv[1:], shortargs, longargs.split())
except getopt.error, msg: except getopt.error, msg:
print msg print msg
print 'for help use --help' print 'for help use --help'
@ -251,6 +251,7 @@ from session import ChatControlSession
import common.sleepy import common.sleepy
from common.xmpp import idlequeue from common.xmpp import idlequeue
from common.zeroconf import connection_zeroconf
from common import nslookup from common import nslookup
from common import proxy65_manager from common import proxy65_manager
from common import socks5 from common import socks5

View file

@ -121,7 +121,7 @@ class GajimThemesWindow:
model.clear() model.clear()
for config_theme in gajim.config.get_per('themes'): for config_theme in gajim.config.get_per('themes'):
theme = config_theme.replace('_', ' ') theme = config_theme.replace('_', ' ')
model.append([theme]) iter = model.append([theme])
def select_active_theme(self): def select_active_theme(self):
model = self.themes_tree.get_model() model = self.themes_tree.get_model()

View file

@ -45,6 +45,7 @@ from common import helpers
from chat_control import ChatControl from chat_control import ChatControl
from chat_control import ChatControlBase from chat_control import ChatControlBase
from conversation_textview import ConversationTextview
from common.exceptions import GajimGeneralException from common.exceptions import GajimGeneralException
#(status_image, type, nick, shown_nick) #(status_image, type, nick, shown_nick)
@ -174,7 +175,7 @@ class GroupchatControl(ChatControlBase):
def __init__(self, parent_win, contact, acct, is_continued=False): def __init__(self, parent_win, contact, acct, is_continued=False):
ChatControlBase.__init__(self, self.TYPE_ID, parent_win, ChatControlBase.__init__(self, self.TYPE_ID, parent_win,
'muc_child_vbox', contact, acct) 'muc_child_vbox', contact, acct);
self.is_continued=is_continued self.is_continued=is_continued
self.is_anonymous = True self.is_anonymous = True
@ -990,6 +991,7 @@ class GroupchatControl(ChatControlBase):
contact in a room''' contact in a room'''
if nick is None: if nick is None:
nick = model[iter_][C_NICK].decode('utf-8') nick = model[iter_][C_NICK].decode('utf-8')
fjid = gajim.construct_fjid(self.room_jid, nick) # 'fake' jid
ctrl = self._start_private_message(nick) ctrl = self._start_private_message(nick)
if ctrl and msg: if ctrl and msg:
@ -1790,7 +1792,7 @@ class GroupchatControl(ChatControlBase):
on_minimize(self) on_minimize(self)
return return
if method == self.parent_win.CLOSE_ESC: if method == self.parent_win.CLOSE_ESC:
iter = self.list_treeview.get_selection().get_selected()[1] model, iter = self.list_treeview.get_selection().get_selected()
if iter: if iter:
self.list_treeview.get_selection().unselect_all() self.list_treeview.get_selection().unselect_all()
on_no(self) on_no(self)
@ -1819,7 +1821,7 @@ class GroupchatControl(ChatControlBase):
sectext = _('If you close this window, you will be disconnected ' sectext = _('If you close this window, you will be disconnected '
'from this group chat.') 'from this group chat.')
dialogs.ConfirmationDialogCheck(pritext, sectext, dialog = dialogs.ConfirmationDialogCheck(pritext, sectext,
_('Do _not ask me again'), on_response_ok=on_ok, _('Do _not ask me again'), on_response_ok=on_ok,
on_response_cancel=on_cancel) on_response_cancel=on_cancel)
return return
@ -1853,7 +1855,7 @@ class GroupchatControl(ChatControlBase):
# will work yet # will work yet
gajim.connections[self.account].send_gc_subject(self.room_jid, subject) gajim.connections[self.account].send_gc_subject(self.room_jid, subject)
dialogs.InputTextDialog(_('Changing Subject'), instance = dialogs.InputTextDialog(_('Changing Subject'),
_('Please specify the new subject:'), input_str=self.subject, _('Please specify the new subject:'), input_str=self.subject,
ok_handler=on_ok) ok_handler=on_ok)
@ -1885,7 +1887,7 @@ class GroupchatControl(ChatControlBase):
jid) jid)
# Ask for a reason # Ask for a reason
dialogs.DubbleInputDialog(_('Destroying %s') % self.room_jid, instance = dialogs.DubbleInputDialog(_('Destroying %s') % self.room_jid,
_('You are going to definitively destroy this room.\n' _('You are going to definitively destroy this room.\n'
'You may specify a reason below:'), 'You may specify a reason below:'),
_('You may also enter an alternate venue:'), ok_handler=on_ok) _('You may also enter an alternate venue:'), ok_handler=on_ok)
@ -1908,6 +1910,7 @@ class GroupchatControl(ChatControlBase):
path = treeview.get_selection().get_selected_rows()[1][0] path = treeview.get_selection().get_selected_rows()[1][0]
iter = model.get_iter(path) iter = model.get_iter(path)
type = model[iter][2] type = model[iter][2]
account = model[iter][4].decode('utf-8')
if type != 'contact': # source is not a contact if type != 'contact': # source is not a contact
return return
contact_jid = data.decode('utf-8') contact_jid = data.decode('utf-8')
@ -2035,7 +2038,7 @@ class GroupchatControl(ChatControlBase):
def on_list_treeview_key_press_event(self, widget, event): def on_list_treeview_key_press_event(self, widget, event):
if event.keyval == gtk.keysyms.Escape: if event.keyval == gtk.keysyms.Escape:
selection = widget.get_selection() selection = widget.get_selection()
iter = selection.get_selected()[1] model, iter = selection.get_selected()
if iter: if iter:
widget.get_selection().unselect_all() widget.get_selection().unselect_all()
return True return True
@ -2059,7 +2062,7 @@ class GroupchatControl(ChatControlBase):
'none', reason) 'none', reason)
# ask for reason # ask for reason
dialogs.InputDialog(_('Kicking %s') % nick, instance = dialogs.InputDialog(_('Kicking %s') % nick,
_('You may specify a reason below:'), ok_handler=on_ok) _('You may specify a reason below:'), ok_handler=on_ok)
def mk_menu(self, event, iter_): def mk_menu(self, event, iter_):
@ -2213,13 +2216,13 @@ class GroupchatControl(ChatControlBase):
def on_list_treeview_button_press_event(self, widget, event): def on_list_treeview_button_press_event(self, widget, event):
'''popup user's group's or agent menu''' '''popup user's group's or agent menu'''
if event.button == 3: # right click
try: try:
pos = widget.get_path_at_pos(int(event.x), int(event.y)) path, column, x, y = widget.get_path_at_pos(int(event.x),
path, x = pos[0] + pos[2] int(event.y))
except TypeError: except TypeError:
widget.get_selection().unselect_all() widget.get_selection().unselect_all()
return return
if event.button == 3: # right click
widget.get_selection().select_path(path) widget.get_selection().select_path(path)
model = widget.get_model() model = widget.get_model()
iter = model.get_iter(path) iter = model.get_iter(path)
@ -2228,6 +2231,12 @@ class GroupchatControl(ChatControlBase):
return True return True
elif event.button == 2: # middle click elif event.button == 2: # middle click
try:
path, column, x, y = widget.get_path_at_pos(int(event.x),
int(event.y))
except TypeError:
widget.get_selection().unselect_all()
return
widget.get_selection().select_path(path) widget.get_selection().select_path(path)
model = widget.get_model() model = widget.get_model()
iter = model.get_iter(path) iter = model.get_iter(path)
@ -2237,6 +2246,13 @@ class GroupchatControl(ChatControlBase):
return True return True
elif event.button == 1: # left click elif event.button == 1: # left click
try:
path, column, x, y = widget.get_path_at_pos(int(event.x),
int(event.y))
except TypeError:
widget.get_selection().unselect_all()
return
if gajim.single_click and not event.state & gtk.gdk.SHIFT_MASK: if gajim.single_click and not event.state & gtk.gdk.SHIFT_MASK:
self.on_row_activated(widget, path) self.on_row_activated(widget, path)
return True return True
@ -2350,7 +2366,7 @@ class GroupchatControl(ChatControlBase):
# to ban we know the real jid. so jid is not fakejid # to ban we know the real jid. so jid is not fakejid
nick = gajim.get_nick_from_jid(jid) nick = gajim.get_nick_from_jid(jid)
# ask for reason # ask for reason
dialogs.InputDialog(_('Banning %s') % nick, instance = dialogs.InputDialog(_('Banning %s') % nick,
_('You may specify a reason below:'), ok_handler=on_ok) _('You may specify a reason below:'), ok_handler=on_ok)
def grant_membership(self, widget, jid): def grant_membership(self, widget, jid):

View file

@ -21,6 +21,8 @@
'''Window to create new post for discussion groups service.''' '''Window to create new post for discussion groups service.'''
import gtk
from common import gajim, xmpp from common import gajim, xmpp
import gtkgui_helpers import gtkgui_helpers

View file

@ -82,6 +82,7 @@ def _info(type_, value, tb):
# on expand the details the dialog remains centered on screen # on expand the details the dialog remains centered on screen
dialog.set_position(gtk.WIN_POS_CENTER_ALWAYS) dialog.set_position(gtk.WIN_POS_CENTER_ALWAYS)
close_clicked = False
def on_dialog_response(dialog, response): def on_dialog_response(dialog, response):
if response == RESPONSE_REPORT_BUG: if response == RESPONSE_REPORT_BUG:
url = 'http://trac.gajim.org/wiki/HowToCreateATicket' url = 'http://trac.gajim.org/wiki/HowToCreateATicket'
@ -103,6 +104,6 @@ if os.name == 'nt' or not sys.stderr.isatty():
if __name__ == '__main__': if __name__ == '__main__':
_excepthook_save = sys.excepthook _excepthook_save = sys.excepthook
sys.excepthook = _info sys.excepthook = _info
raise Exception() print x # this always tracebacks
# vim: se ts=3: # vim: se ts=3:

View file

@ -97,7 +97,7 @@ def popup_emoticons_under_button(menu, button, parent_win):
x = window_x + button_x x = window_x + button_x
y = window_y + button_y y = window_y + button_y
menu_height = menu.size_request()[1] menu_width, menu_height = menu.size_request()
## should we pop down or up? ## should we pop down or up?
if (y + button.allocation.height + menu_height if (y + button.allocation.height + menu_height
@ -494,7 +494,7 @@ def file_is_locked(path_to_file):
win32con.FILE_ATTRIBUTE_NORMAL, # normal file win32con.FILE_ATTRIBUTE_NORMAL, # normal file
0 # no attr. template 0 # no attr. template
) )
except pywintypes.error: except pywintypes.error, e:
return True return True
else: # in case all went ok, close file handle (go to hell WinAPI) else: # in case all went ok, close file handle (go to hell WinAPI)
hfile.Close() hfile.Close()
@ -808,6 +808,10 @@ default_name = ''):
dialog.destroy() dialog.destroy()
def on_ok(widget): def on_ok(widget):
def on_ok2(file_path, pixbuf):
pixbuf.save(file_path, 'jpeg')
dialog.destroy()
file_path = dialog.get_filename() file_path = dialog.get_filename()
file_path = decode_filechooser_file_paths((file_path,))[0] file_path = decode_filechooser_file_paths((file_path,))[0]
if os.path.exists(file_path): if os.path.exists(file_path):

View file

@ -220,7 +220,7 @@ class HistoryManager:
def on_no(): def on_no():
gtk.main_quit() gtk.main_quit()
dialogs.YesNoDialog( dialog = dialogs.YesNoDialog(
_('Do you want to clean up the database? ' _('Do you want to clean up the database? '
'(STRONGLY NOT RECOMMENDED IF GAJIM IS RUNNING)'), '(STRONGLY NOT RECOMMENDED IF GAJIM IS RUNNING)'),
_('Normally allocated database size will not be freed, ' _('Normally allocated database size will not be freed, '
@ -296,7 +296,7 @@ class HistoryManager:
(user will see the first pm as if it was message in room's public chat) (user will see the first pm as if it was message in room's public chat)
and after that all okay''' and after that all okay'''
possible_room_jid = jid.split('/', 1)[0] possible_room_jid, possible_nick = jid.split('/', 1)
self.cur.execute('SELECT jid_id FROM jids WHERE jid = ? AND type = ?', self.cur.execute('SELECT jid_id FROM jids WHERE jid = ? AND type = ?',
(possible_room_jid, constants.JID_ROOM_TYPE)) (possible_room_jid, constants.JID_ROOM_TYPE))
@ -421,6 +421,9 @@ class HistoryManager:
xml.get_widget('delete_menuitem').connect('activate', xml.get_widget('delete_menuitem').connect('activate',
self.on_delete_menuitem_activate, widget) self.on_delete_menuitem_activate, widget)
liststore, list_of_paths = self.jids_listview.get_selection()\
.get_selected_rows()
xml.signal_autoconnect(self) xml.signal_autoconnect(self)
xml.get_widget('context_menu').popup(None, None, None, xml.get_widget('context_menu').popup(None, None, None,
event.button, event.time) event.button, event.time)

View file

@ -321,7 +321,7 @@ class HistoryWindow:
# first day of month is 1 not 0 # first day of month is 1 not 0
widget.clear_marks() widget.clear_marks()
month = gtkgui_helpers.make_gtk_month_python_month(month) month = gtkgui_helpers.make_gtk_month_python_month(month)
days_in_this_month = calendar.monthrange(year, month)[1] weekday, days_in_this_month = calendar.monthrange(year, month)
log_days = gajim.logger.get_days_with_logs(self.jid, year, log_days = gajim.logger.get_days_with_logs(self.jid, year,
month, days_in_this_month, self.account) month, days_in_this_month, self.account)
for day in log_days: for day in log_days:
@ -509,7 +509,7 @@ class HistoryWindow:
'''a row was double clicked, get date from row, and select it in calendar '''a row was double clicked, get date from row, and select it in calendar
which results to showing conversation logs for that date''' which results to showing conversation logs for that date'''
# get currently selected date # get currently selected date
cur_year, cur_month = self.calendar.get_date()[0:2] cur_year, cur_month, cur_day = self.calendar.get_date()
cur_month = gtkgui_helpers.make_gtk_month_python_month(cur_month) cur_month = gtkgui_helpers.make_gtk_month_python_month(cur_month)
model = widget.get_model() model = widget.get_model()
# make it a tupple (Y, M, D, 0, 0, 0...) # make it a tupple (Y, M, D, 0, 0, 0...)

View file

@ -91,76 +91,77 @@ element_styles['tt'] = element_styles['kbd']
element_styles['i'] = element_styles['em'] element_styles['i'] = element_styles['em']
element_styles['b'] = element_styles['strong'] element_styles['b'] = element_styles['strong']
# ========== '''
# JEP-0071 ==========
# ========== JEP-0071
# ==========
# This Integration Set includes a subset of the modules defined for
# XHTML 1.0 but does not redefine any existing modules, nor This Integration Set includes a subset of the modules defined for
# does it define any new modules. Specifically, it includes the XHTML 1.0 but does not redefine any existing modules, nor
# following modules only: does it define any new modules. Specifically, it includes the
# following modules only:
# - Structure
# - Text - Structure
# - Text
# * Block
# * Block
# phrasal
# addr, blockquote, pre phrasal
# Struc addr, blockquote, pre
# div,p Struc
# Heading div,p
# h1, h2, h3, h4, h5, h6 Heading
# h1, h2, h3, h4, h5, h6
# * Inline
# * Inline
# phrasal
# abbr, acronym, cite, code, dfn, em, kbd, q, samp, strong, var phrasal
# structural abbr, acronym, cite, code, dfn, em, kbd, q, samp, strong, var
# br, span structural
# br, span
# - Hypertext (a)
# - List (ul, ol, dl) - Hypertext (a)
# - Image (img) - List (ul, ol, dl)
# - Style Attribute - Image (img)
# - Style Attribute
# Therefore XHTML-IM uses the following content models:
# Therefore XHTML-IM uses the following content models:
# Block.mix
# Block-like elements, e.g., paragraphs Block.mix
# Flow.mix Block-like elements, e.g., paragraphs
# Any block or inline elements Flow.mix
# Inline.mix Any block or inline elements
# Character-level elements Inline.mix
# InlineNoAnchor.class Character-level elements
# Anchor element InlineNoAnchor.class
# InlinePre.mix Anchor element
# Pre element InlinePre.mix
# Pre element
# XHTML-IM also uses the following Attribute Groups:
# XHTML-IM also uses the following Attribute Groups:
# Core.extra.attrib
# TBD Core.extra.attrib
# I18n.extra.attrib TBD
# TBD I18n.extra.attrib
# Common.extra TBD
# style Common.extra
# style
#
# ...
# block level: ...
# Heading h #block level:
#Heading h
# ( pres = h1 | h2 | h3 | h4 | h5 | h6 ) # ( pres = h1 | h2 | h3 | h4 | h5 | h6 )
# Block ( phrasal = address | blockquote | pre ) #Block ( phrasal = address | blockquote | pre )
# NOT ( presentational = hr ) #NOT ( presentational = hr )
# ( structural = div | p ) # ( structural = div | p )
# other: section #other: section
# Inline ( phrasal = abbr | acronym | cite | code | dfn | em | #Inline ( phrasal = abbr | acronym | cite | code | dfn | em | kbd | q | samp | strong | var )
# kbd | q | samp | strong | var ) #NOT ( presentational = b | big | i | small | sub | sup | tt )
# NOT ( presentational = b | big | i | small | sub | sup | tt )
# ( structural = br | span ) # ( structural = br | span )
# Param/Legacy param, font, basefont, center, s, strike, u, dir, menu, #Param/Legacy param, font, basefont, center, s, strike, u, dir, menu, isindex
# isindex #
'''
BLOCK_HEAD = set(( 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', )) BLOCK_HEAD = set(( 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', ))
BLOCK_PHRASAL = set(( 'address', 'blockquote', 'pre', )) BLOCK_PHRASAL = set(( 'address', 'blockquote', 'pre', ))
@ -1034,7 +1035,7 @@ if __name__ == '__main__':
def on_textview_motion_notify_event(widget, event): def on_textview_motion_notify_event(widget, event):
'''change the cursor to a hand when we are over a mail or an url''' '''change the cursor to a hand when we are over a mail or an url'''
global change_cursor global change_cursor
pointer_x, pointer_y = htmlview.window.get_pointer()[0:2] pointer_x, pointer_y, spam = htmlview.window.get_pointer()
x, y = htmlview.window_to_buffer_coords(gtk.TEXT_WINDOW_TEXT, pointer_x, x, y = htmlview.window_to_buffer_coords(gtk.TEXT_WINDOW_TEXT, pointer_x,
pointer_y) pointer_y)
tags = htmlview.get_iter_at_location(x, y).get_tags() tags = htmlview.get_iter_at_location(x, y).get_tags()
@ -1043,6 +1044,7 @@ if __name__ == '__main__':
gtk.gdk.Cursor(gtk.gdk.XTERM)) gtk.gdk.Cursor(gtk.gdk.XTERM))
change_cursor = None change_cursor = None
tag_table = htmlview.get_buffer().get_tag_table() tag_table = htmlview.get_buffer().get_tag_table()
over_line = False
for tag in tags: for tag in tags:
try: try:
if tag.is_anchor: if tag.is_anchor:

View file

@ -48,6 +48,7 @@ import sys
import os import os
import pango import pango
from StringIO import StringIO from StringIO import StringIO
import thread
try: try:
import IPython import IPython
@ -213,7 +214,7 @@ class IterableIPShell:
possibilities = self.IP.complete(split_line[-1]) possibilities = self.IP.complete(split_line[-1])
try: try:
all(()) __builtins__.all
except AttributeError: except AttributeError:
def all(iterable): def all(iterable):
for element in iterable: for element in iterable:
@ -245,6 +246,7 @@ class IterableIPShell:
@param header: Header to be printed before output @param header: Header to be printed before output
@type header: string @type header: string
''' '''
stat = 0
if verbose or debug: print header+cmd if verbose or debug: print header+cmd
# flush stdout so we don't mangle python's buffering # flush stdout so we don't mangle python's buffering
if not debug: if not debug:

View file

@ -142,6 +142,7 @@ class MessageControl:
self.session = session self.session = session
new_key = None
if session: if session:
session.control = self session.control = self
new_key = session.thread_id new_key = session.thread_id

View file

@ -213,6 +213,7 @@ class MessageWindow(object):
self.on_delete_ok -= 1 self.on_delete_ok -= 1
# Make sure all controls are okay with being deleted # Make sure all controls are okay with being deleted
ctrl_to_minimize = []
self.on_delete_ok = self.get_nb_controls() self.on_delete_ok = self.get_nb_controls()
for ctrl in self.controls(): for ctrl in self.controls():
ctrl.allow_shutdown(self.CLOSE_CLOSE_BUTTON, on_yes, on_no, ctrl.allow_shutdown(self.CLOSE_CLOSE_BUTTON, on_yes, on_no,
@ -670,7 +671,11 @@ class MessageWindow(object):
yield ctrl yield ctrl
def get_nb_controls(self): def get_nb_controls(self):
return sum(len(jid_dict) for jid_dict in self._controls.values()) nb_ctrl = 0
for jid_dict in self._controls.values():
for ctrl in jid_dict.values():
nb_ctrl += 1
return nb_ctrl
def move_to_next_unread_tab(self, forward): def move_to_next_unread_tab(self, forward):
ind = self.notebook.get_current_page() ind = self.notebook.get_current_page()
@ -771,7 +776,7 @@ class MessageWindow(object):
selection, type_, time): selection, type_, time):
'''Reorder the tabs according to the drop position''' '''Reorder the tabs according to the drop position'''
source_page_num = int(selection.data) source_page_num = int(selection.data)
dest_page_num = self.get_tab_at_xy(x, y)[0] dest_page_num, to_right = self.get_tab_at_xy(x, y)
source_child = self.notebook.get_nth_page(source_page_num) source_child = self.notebook.get_nth_page(source_page_num)
if dest_page_num != source_page_num: if dest_page_num != source_page_num:
self.notebook.reorder_child(source_child, dest_page_num) self.notebook.reorder_child(source_child, dest_page_num)

View file

@ -23,6 +23,7 @@
## along with Gajim. If not, see <http://www.gnu.org/licenses/>. ## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
## ##
import os
import gobject import gobject
if __name__ == '__main__': if __name__ == '__main__':
# install _() func before importing dbus_support # install _() func before importing dbus_support

View file

@ -22,6 +22,8 @@
import gtkgui_helpers import gtkgui_helpers
import dataforms_widget import dataforms_widget
import dialogs
from common import dataforms from common import dataforms
from common import gajim from common import gajim
from common import xmpp from common import xmpp

View file

@ -443,9 +443,7 @@ class DesktopNotification:
self.event_type = event_type self.event_type = event_type
self.title = title self.title = title
self.text = text self.text = text
# 0.3.1 is the only version of notification daemon that has no way '''0.3.1 is the only version of notification daemon that has no way to determine which version it is. If no method exists, it means they're using that one.'''
# to determine which version it is. If no method exists, it means
# they're using that one.
self.default_version = [0, 3, 1] self.default_version = [0, 3, 1]
self.account = account self.account = account
self.jid = jid self.jid = jid
@ -521,8 +519,8 @@ class DesktopNotification:
if gajim.interface.systray_enabled and \ if gajim.interface.systray_enabled and \
gajim.config.get('attach_notifications_to_systray'): gajim.config.get('attach_notifications_to_systray'):
x, y = gajim.interface.systray.img_tray.window.get_position() x, y = gajim.interface.systray.img_tray.window.get_position()
width, height = \ x_, y_, width, height, depth = \
gajim.interface.systray.img_tray.window.get_geometry()[2:4] gajim.interface.systray.img_tray.window.get_geometry()
pos_x = x + (width / 2) pos_x = x + (width / 2)
pos_y = y + (height / 2) pos_y = y + (height / 2)
hints = {'x': pos_x, 'y': pos_y} hints = {'x': pos_x, 'y': pos_y}

View file

@ -14,6 +14,7 @@ try:
import _growl import _growl
except Exception: except Exception:
_growl = False _growl = False
import types
import struct import struct
import md5 import md5
import socket import socket

View file

@ -1,6 +1,6 @@
import sys, os import sys, os
from growl.Growl import GrowlNotifier from growl.Growl import GrowlNotifier
from common import gajim from common import gajim, helpers
if sys.platform != "darwin": if sys.platform != "darwin":
@ -22,7 +22,7 @@ growler = None
def init(): def init():
global growler global growler, notifications
icon = open(os.path.join(gajim.DATA_DIR, "pixmaps", "gajim.icns"), "r") icon = open(os.path.join(gajim.DATA_DIR, "pixmaps", "gajim.icns"), "r")
growler = GrowlNotifier(applicationName = "Gajim", growler = GrowlNotifier(applicationName = "Gajim",
notifications = notifications, notifications = notifications,
@ -33,6 +33,7 @@ def init():
def notify(event_type, jid, account, msg_type, path_to_image, title, text): def notify(event_type, jid, account, msg_type, path_to_image, title, text):
global notifications
if not event_type in notifications: if not event_type in notifications:
event_type = GENERIC_NOTIF event_type = GENERIC_NOTIF
if not text: if not text:

View file

@ -1,4 +1,3 @@
import sys
from distutils.core import setup, Extension from distutils.core import setup, Extension
import commands import commands

View file

@ -6,6 +6,7 @@ copy_item = None
def menu_item_activate_cb(item, user_data): def menu_item_activate_cb(item, user_data):
global open_item, copy_item
print "Item activated: %s" % user_data print "Item activated: %s" % user_data
#g_object_get (G_OBJECT (copy_item), #g_object_get (G_OBJECT (copy_item),

View file

@ -33,6 +33,8 @@ import dialogs
import vcard import vcard
from common import gajim from common import gajim
from common.i18n import Q_
class ProfileWindow: class ProfileWindow:
'''Class for our information window''' '''Class for our information window'''

View file

@ -327,7 +327,8 @@ class SignalObject(dbus.service.Object):
'''Shows the tabbed window for new message to 'jid', using account '''Shows the tabbed window for new message to 'jid', using account
(optional) 'account' ''' (optional) 'account' '''
if not jid: if not jid:
raise dbus_support.MissingArgument() raise MissingArgument
return DBUS_BOOLEAN(False)
jid = self._get_real_jid(jid, account) jid = self._get_real_jid(jid, account)
try: try:
jid = helpers.parse_jid(jid) jid = helpers.parse_jid(jid)
@ -407,7 +408,8 @@ class SignalObject(dbus.service.Object):
if not isinstance(jid, unicode): if not isinstance(jid, unicode):
jid = unicode(jid) jid = unicode(jid)
if not jid: if not jid:
raise dbus_support.MissingArgument() raise MissingArgument
return DBUS_DICT_SV()
jid = self._get_real_jid(jid) jid = self._get_real_jid(jid)
cached_vcard = gajim.connections.values()[0].get_cached_vcard(jid) cached_vcard = gajim.connections.values()[0].get_cached_vcard(jid)

View file

@ -50,6 +50,7 @@ import cell_renderer_image
import tooltips import tooltips
import message_control import message_control
import adhoc_commands import adhoc_commands
import notify
import features_window import features_window
from common import gajim from common import gajim
@ -61,10 +62,13 @@ from common import pep
from message_window import MessageWindowMgr from message_window import MessageWindowMgr
from session import ChatControlSession
from common import dbus_support from common import dbus_support
if dbus_support.supported: if dbus_support.supported:
from music_track_listener import MusicTrackListener from music_track_listener import MusicTrackListener
import dbus import dbus
from lastfm_track_listener import LastFMTrackListener
from common.xmpp.protocol import NS_COMMANDS, NS_FILE, NS_MUC from common.xmpp.protocol import NS_COMMANDS, NS_FILE, NS_MUC
from common.pep import MOODS, ACTIVITIES from common.pep import MOODS, ACTIVITIES
@ -517,6 +521,7 @@ class RosterWindow:
# Family might has changed (actual big brother not on top). # Family might has changed (actual big brother not on top).
# Remove childs first then big brother # Remove childs first then big brother
family_in_roster = False family_in_roster = False
big_brother_jid = None
for data in nearby_family: for data in nearby_family:
_account = data['account'] _account = data['account']
_jid = data['jid'] _jid = data['jid']
@ -834,6 +839,7 @@ class RosterWindow:
def remove_transport(self, jid, account): def remove_transport(self, jid, account):
'''Remove transport from roster and redraw account and group.''' '''Remove transport from roster and redraw account and group.'''
contact = gajim.contacts.get_contact_with_highest_priority(account, jid)
self.remove_contact(jid, account, force=True, backend=True) self.remove_contact(jid, account, force=True, backend=True)
return True return True
@ -1148,8 +1154,8 @@ class RosterWindow:
is_big_brother = False is_big_brother = False
have_visible_children = False have_visible_children = False
if family: if family:
bb_jid, bb_account = \ nearby_family, bb_jid, bb_account = \
self._get_nearby_family_and_big_brother(family, account)[1:] self._get_nearby_family_and_big_brother(family, account)
is_big_brother = (jid, account) == (bb_jid, bb_account) is_big_brother = (jid, account) == (bb_jid, bb_account)
iters = self._get_contact_iter(jid, account) iters = self._get_contact_iter(jid, account)
have_visible_children = iters \ have_visible_children = iters \
@ -1710,7 +1716,7 @@ class RosterWindow:
obj = bus.get_object('com.google.code.Awn', '/com/google/code/Awn') obj = bus.get_object('com.google.code.Awn', '/com/google/code/Awn')
awn = dbus.Interface(obj, 'com.google.code.Awn') awn = dbus.Interface(obj, 'com.google.code.Awn')
awn.SetTaskIconByName('Gajim', os.path.abspath(path)) awn.SetTaskIconByName('Gajim', os.path.abspath(path))
except Exception: except Exception, e:
pass pass
def music_track_changed(self, unused_listener, music_track_info, def music_track_changed(self, unused_listener, music_track_info,
@ -1722,10 +1728,14 @@ class RosterWindow:
artist = '' artist = ''
title = '' title = ''
source = '' source = ''
track = ''
length = ''
elif hasattr(music_track_info, 'paused') and music_track_info.paused == 0: elif hasattr(music_track_info, 'paused') and music_track_info.paused == 0:
artist = '' artist = ''
title = '' title = ''
source = '' source = ''
track = ''
length = ''
else: else:
artist = music_track_info.artist artist = music_track_info.artist
title = music_track_info.title title = music_track_info.title
@ -1893,6 +1903,7 @@ class RosterWindow:
self.set_connecting_state(account) self.set_connecting_state(account)
if not gajim.connections[account].password: if not gajim.connections[account].password:
passphrase = ''
text = _('Enter your password for account %s') % account text = _('Enter your password for account %s') % account
if passwords.USER_HAS_GNOMEKEYRING and \ if passwords.USER_HAS_GNOMEKEYRING and \
not passwords.USER_USES_GNOMEKEYRING: not passwords.USER_USES_GNOMEKEYRING:
@ -1906,7 +1917,7 @@ class RosterWindow:
passwords.save_password(account, passphrase) passwords.save_password(account, passphrase)
keyid = gajim.config.get_per('accounts', account, 'keyid') keyid = gajim.config.get_per('accounts', account, 'keyid')
if keyid and not gajim.connections[account].gpg: if keyid and not gajim.connections[account].gpg:
dialogs.WarningDialog(_('GPG is not usable'), dialog = dialogs.WarningDialog(_('GPG is not usable'),
_('You will be connected to %s without OpenPGP.') % \ _('You will be connected to %s without OpenPGP.') % \
account) account)
self.send_status_continue(account, status, txt, auto, to) self.send_status_continue(account, status, txt, auto, to)
@ -1919,14 +1930,14 @@ class RosterWindow:
gajim.interface.systray.change_status('offline') gajim.interface.systray.change_status('offline')
self.update_status_combobox() self.update_status_combobox()
dialogs.PassphraseDialog(_('Password Required'), text, w = dialogs.PassphraseDialog(_('Password Required'), text,
_('Save password'), ok_handler=on_ok, _('Save password'), ok_handler=on_ok,
cancel_handler=on_cancel) cancel_handler=on_cancel)
return return
keyid = gajim.config.get_per('accounts', account, 'keyid') keyid = gajim.config.get_per('accounts', account, 'keyid')
if keyid and not gajim.connections[account].gpg: if keyid and not gajim.connections[account].gpg:
dialogs.WarningDialog(_('GPG is not usable'), dialog = dialogs.WarningDialog(_('GPG is not usable'),
_('You will be connected to %s without OpenPGP.') % account) _('You will be connected to %s without OpenPGP.') % account)
self.send_status_continue(account, status, txt, auto, to) self.send_status_continue(account, status, txt, auto, to)
@ -2256,7 +2267,7 @@ class RosterWindow:
break break
if unread or recent: if unread or recent:
dialogs.ConfirmationDialog(_('You have unread messages'), dialog = dialogs.ConfirmationDialog(_('You have unread messages'),
_('Messages will only be available for reading them later if you' _('Messages will only be available for reading them later if you'
' have history enabled and contact is in your roster.'), ' have history enabled and contact is in your roster.'),
on_response_ok=(on_continue2, message)) on_response_ok=(on_continue2, message))
@ -2364,7 +2375,7 @@ class RosterWindow:
if not props or self.tooltip.id != props[0]: if not props or self.tooltip.id != props[0]:
self.tooltip.hide_tooltip() self.tooltip.hide_tooltip()
if props: if props:
row = props[0] [row, col, x, y] = props
titer = None titer = None
try: try:
titer = model.get_iter(row) titer = model.get_iter(row)
@ -2518,6 +2529,7 @@ class RosterWindow:
if msg is None: if msg is None:
# user pressed Cancel to change status message dialog # user pressed Cancel to change status message dialog
return return
model = self.modelfilter
accounts = [] accounts = []
if group is None: if group is None:
for (contact, account) in list_: for (contact, account) in list_:
@ -2560,6 +2572,7 @@ class RosterWindow:
def on_unblock(self, widget, list_, group=None): def on_unblock(self, widget, list_, group=None):
''' When clicked on the 'unblock' button in context menu. ''' ''' When clicked on the 'unblock' button in context menu. '''
model = self.modelfilter
accounts = [] accounts = []
if group is None: if group is None:
for (contact, account) in list_: for (contact, account) in list_:
@ -2631,6 +2644,7 @@ class RosterWindow:
if 'rename' in gajim.interface.instances: if 'rename' in gajim.interface.instances:
gajim.interface.instances['rename'].dialog.present() gajim.interface.instances['rename'].dialog.present()
return return
model = self.modelfilter
# account is offline, don't allow to rename # account is offline, don't allow to rename
if gajim.connections[account].connected < 2: if gajim.connections[account].connected < 2:
@ -2743,7 +2757,7 @@ class RosterWindow:
u.keyID = helpers.prepare_and_validate_gpg_keyID(account, u.keyID = helpers.prepare_and_validate_gpg_keyID(account,
contact.jid, keyID) contact.jid, keyID)
dialogs.ChooseGPGKeyDialog(_('Assign OpenPGP Key'), instance = dialogs.ChooseGPGKeyDialog(_('Assign OpenPGP Key'),
_('Select a key to apply to the contact'), public_keys, _('Select a key to apply to the contact'), public_keys,
on_key_selected, selected=keyID) on_key_selected, selected=keyID)
@ -2860,7 +2874,7 @@ class RosterWindow:
resource = None): resource = None):
''' resource parameter MUST NOT be used if more than one contact in ''' resource parameter MUST NOT be used if more than one contact in
list ''' list '''
for contact in (e[0] for e in list_): for (contact, acct) in list_:
contact_jid = contact.jid contact_jid = contact.jid
if resource: # we MUST have one contact only in list_ if resource: # we MUST have one contact only in list_
contact_jid += '/' + resource contact_jid += '/' + resource
@ -2905,10 +2919,10 @@ class RosterWindow:
helpers.launch_browser_mailer('url', url) helpers.launch_browser_mailer('url', url)
def on_change_activity_activate(self, widget, account): def on_change_activity_activate(self, widget, account):
dialogs.ChangeActivityDialog(account) dlg = dialogs.ChangeActivityDialog(account)
def on_change_mood_activate(self, widget, account): def on_change_mood_activate(self, widget, account):
dialogs.ChangeMoodDialog(account) dlg = dialogs.ChangeMoodDialog(account)
def on_change_status_message_activate(self, widget, account): def on_change_status_message_activate(self, widget, account):
show = gajim.SHOW_LIST[gajim.connections[account].connected] show = gajim.SHOW_LIST[gajim.connections[account].connected]
@ -2967,7 +2981,8 @@ class RosterWindow:
def on_roster_treeview_button_release_event(self, widget, event): def on_roster_treeview_button_release_event(self, widget, event):
try: try:
path = self.tree.get_path_at_pos(int(event.x), int(event.y))[0] path, column, x, y = self.tree.get_path_at_pos(int(event.x),
int(event.y))
except TypeError: except TypeError:
return False return False
@ -2983,8 +2998,8 @@ class RosterWindow:
# hide tooltip, no matter the button is pressed # hide tooltip, no matter the button is pressed
self.tooltip.hide_tooltip() self.tooltip.hide_tooltip()
try: try:
pos = self.tree.get_path_at_pos(int(event.x), int(event.y)) path, column, x, y = self.tree.get_path_at_pos(int(event.x),
path, x = pos[0] + pos[2] int(event.y))
except TypeError: except TypeError:
self.tree.get_selection().unselect_all() self.tree.get_selection().unselect_all()
return False return False
@ -3095,6 +3110,7 @@ class RosterWindow:
if len(list_) == 1: if len(list_) == 1:
contact = list_[0][0] contact = list_[0][0]
account = list_[0][1]
pritext = _('Contact "%s" will be removed from your roster') % \ pritext = _('Contact "%s" will be removed from your roster') % \
contact.get_shown_name() contact.get_shown_name()
if contact.sub == 'to': if contact.sub == 'to':
@ -3233,7 +3249,7 @@ class RosterWindow:
def on_cancel(): def on_cancel():
self.update_status_combobox() self.update_status_combobox()
dialogs.ConfirmationDialog( dialog = dialogs.ConfirmationDialog(
_('You are participating in one or more group chats'), _('You are participating in one or more group chats'),
_('Changing your status to invisible will result in ' _('Changing your status to invisible will result in '
'disconnection from those group chats. Are you sure you want to ' 'disconnection from those group chats. Are you sure you want to '
@ -3387,7 +3403,7 @@ class RosterWindow:
gajim.interface.msg_win_mgr.one_window_opened(): gajim.interface.msg_win_mgr.one_window_opened():
# let message window close the tab # let message window close the tab
return return
list_of_paths = self.tree.get_selection().get_selected_rows()[1] model, list_of_paths = self.tree.get_selection().get_selected_rows()
if not len(list_of_paths) and gajim.interface.systray_enabled and \ if not len(list_of_paths) and gajim.interface.systray_enabled and \
not gajim.config.get('quit_on_roster_x_button'): not gajim.config.get('quit_on_roster_x_button'):
self.tooltip.hide_tooltip() self.tooltip.hide_tooltip()
@ -3506,8 +3522,8 @@ class RosterWindow:
jid = model[titer][C_JID].decode('utf-8') jid = model[titer][C_JID].decode('utf-8')
account = model[titer][C_ACCOUNT].decode('utf-8') account = model[titer][C_ACCOUNT].decode('utf-8')
family = gajim.contacts.get_metacontacts_family(account, jid) family = gajim.contacts.get_metacontacts_family(account, jid)
nearby_family = \ nearby_family, bb_jid, bb_account = \
self._get_nearby_family_and_big_brother(family, account)[0] self._get_nearby_family_and_big_brother(family, account)
# Redraw all brothers to show pending events # Redraw all brothers to show pending events
for data in nearby_family: for data in nearby_family:
self.draw_contact(data['jid'], data['account']) self.draw_contact(data['jid'], data['account'])
@ -3546,8 +3562,8 @@ class RosterWindow:
jid = model[titer][C_JID].decode('utf-8') jid = model[titer][C_JID].decode('utf-8')
account = model[titer][C_ACCOUNT].decode('utf-8') account = model[titer][C_ACCOUNT].decode('utf-8')
family = gajim.contacts.get_metacontacts_family(account, jid) family = gajim.contacts.get_metacontacts_family(account, jid)
nearby_family = \ nearby_family, bb_jid, bb_account = \
self._get_nearby_family_and_big_brother(family, account)[0] self._get_nearby_family_and_big_brother(family, account)
# Redraw all brothers to show pending events # Redraw all brothers to show pending events
for data in nearby_family: for data in nearby_family:
self.draw_contact(data['jid'], data['account']) self.draw_contact(data['jid'], data['account'])
@ -3812,7 +3828,7 @@ class RosterWindow:
def drag_drop(self, treeview, context, x, y, timestamp): def drag_drop(self, treeview, context, x, y, timestamp):
target_list = treeview.drag_dest_get_target_list() target_list = treeview.drag_dest_get_target_list()
target = treeview.drag_dest_find_target(context, target_list) target = treeview.drag_dest_find_target(context, target_list)
treeview.drag_get_data(context, target) selection = treeview.drag_get_data(context, target)
context.finish(False, True) context.finish(False, True)
return True return True
@ -5388,11 +5404,10 @@ class RosterWindow:
else: else:
execute_command_menuitem.set_sensitive(False) execute_command_menuitem.set_sensitive(False)
# This does nothing: our_jid_other_resource = None
# our_jid_other_resource = None if our_jid:
# if our_jid: # It's another resource of us, be sure to send invite to her
# # It's another resource of us, be sure to send invite to her our_jid_other_resource = contact.resource
# our_jid_other_resource = contact.resource
# Else this var is useless but harmless in next connect calls # Else this var is useless but harmless in next connect calls
if gajim.capscache.is_supported(contact, NS_FILE): if gajim.capscache.is_supported(contact, NS_FILE):
@ -5753,6 +5768,7 @@ class RosterWindow:
def make_groupchat_menu(self, event, titer): def make_groupchat_menu(self, event, titer):
model = self.modelfilter model = self.modelfilter
path = model.get_path(titer)
jid = model[titer][C_JID].decode('utf-8') jid = model[titer][C_JID].decode('utf-8')
account = model[titer][C_ACCOUNT].decode('utf-8') account = model[titer][C_ACCOUNT].decode('utf-8')
contact = gajim.contacts.get_contact_with_highest_priority(account, jid) contact = gajim.contacts.get_contact_with_highest_priority(account, jid)
@ -6034,52 +6050,52 @@ class RosterWindow:
return True return True
def setup_for_osx(self): def setup_for_osx(self):
# This is broken
return
'''Massage the GTK menu so it will match up to the OS/X nib style menu '''Massage the GTK menu so it will match up to the OS/X nib style menu
when passed to sync-menu and merged''' when passed to sync-menu and merged'''
pass main_menu = self.xml.get_widget('menubar')
# This is broken app_item = gtk.MenuItem('Gajim')
# main_menu = self.xml.get_widget('menubar') main_menu.insert(app_item, 0)
# app_item = gtk.MenuItem('Gajim') win_item = gtk.MenuItem('Window')
# main_menu.insert(app_item, 0) main_menu.insert(win_item, 4)
# win_item = gtk.MenuItem('Window') actions_menu = self.xml.get_widget('actions_menu_menu')
# main_menu.insert(win_item, 4) quit_item = self.xml.get_widget('quit_menuitem')
# actions_menu = self.xml.get_widget('actions_menu_menu') actions_menu.remove(quit_item)
# quit_item = self.xml.get_widget('quit_menuitem') actions_menu.remove(self.xml.get_widget('separator1'))
# actions_menu.remove(quit_item) edit_menu = self.xml.get_widget('edit_menu_menu')
# actions_menu.remove(self.xml.get_widget('separator1')) #edit_menu.remove(self.xml.get_widget('preferences_menuitem'))
# edit_menu = self.xml.get_widget('edit_menu_menu') edit_menu.remove(self.xml.get_widget('separator2'))
# #edit_menu.remove(self.xml.get_widget('preferences_menuitem')) help_menu = self.xml.get_widget('help_menu_menu')
# edit_menu.remove(self.xml.get_widget('separator2')) about_item = self.xml.get_widget('about_menuitem')
# help_menu = self.xml.get_widget('help_menu_menu') help_menu.remove(about_item)
# about_item = self.xml.get_widget('about_menuitem') # Build up App menu
# help_menu.remove(about_item) app_menu = gtk.Menu()
# # Build up App menu app_item.set_submenu(app_menu)
# app_menu = gtk.Menu() app_menu.append(about_item)
# app_item.set_submenu(app_menu) app_menu.append(gtk.MenuItem('__SKIP__'))
# app_menu.append(about_item) prefs_item = gtk.MenuItem('Preferences...')
# app_menu.append(gtk.MenuItem('__SKIP__')) prefs_item.connect('activate', self.on_preferences_menuitem_activate)
# prefs_item = gtk.MenuItem('Preferences...') accels = gtk.AccelGroup()
# prefs_item.connect('activate', self.on_preferences_menuitem_activate) self.xml.get_widget('roster_window').add_accel_group(accels)
# accels = gtk.AccelGroup() prefs_item.add_accelerator('activate', accels, ord(','),
# self.xml.get_widget('roster_window').add_accel_group(accels) gtk.gdk.CONTROL_MASK, gtk.ACCEL_VISIBLE)
# prefs_item.add_accelerator('activate', accels, ord(','), app_menu.append(prefs_item)
# gtk.gdk.CONTROL_MASK, gtk.ACCEL_VISIBLE) app_menu.append(gtk.MenuItem('__SKIP__'))
# app_menu.append(prefs_item) app_menu.append(gtk.MenuItem('__SKIP__'))
# app_menu.append(gtk.MenuItem('__SKIP__')) app_menu.append(gtk.MenuItem('__SKIP__'))
# app_menu.append(gtk.MenuItem('__SKIP__')) app_menu.append(gtk.MenuItem('__SKIP__'))
# app_menu.append(gtk.MenuItem('__SKIP__')) app_menu.append(gtk.MenuItem('__SKIP__'))
# app_menu.append(gtk.MenuItem('__SKIP__')) app_menu.append(gtk.MenuItem('__SKIP__'))
# app_menu.append(gtk.MenuItem('__SKIP__')) app_menu.append(gtk.MenuItem('__SKIP__'))
# app_menu.append(gtk.MenuItem('__SKIP__')) app_menu.append(quit_item)
# app_menu.append(gtk.MenuItem('__SKIP__')) app_menu.show_all()
# app_menu.append(quit_item) # Do the merge baby!
# app_menu.show_all() syncmenu.takeover_menu(main_menu)
# # Do the merge baby! self.make_menu(force=True)
# syncmenu.takeover_menu(main_menu) # Hide the GTK menubar itself and let the OS/X menubar do its thing
# self.make_menu(force=True) #self.xml.get_widget('menubar').hide()
# # Hide the GTK menubar itself and let the OS/X menubar do its thing return
# #self.xml.get_widget('menubar').hide()
# return
################################################################################ ################################################################################
### ###
@ -6328,7 +6344,8 @@ class RosterWindow:
if not gajim.ZEROCONF_ACC_NAME in gajim.config.get_per('accounts'): if not gajim.ZEROCONF_ACC_NAME in gajim.config.get_per('accounts'):
# Create zeroconf in config file # Create zeroconf in config file
from common.zeroconf import connection_zeroconf from common.zeroconf import connection_zeroconf
connection_zeroconf.ConnectionZeroconf(gajim.ZEROCONF_ACC_NAME) zeroconf = connection_zeroconf.ConnectionZeroconf(
gajim.ZEROCONF_ACC_NAME)
if sys.platform == 'darwin': if sys.platform == 'darwin':
self.setup_for_osx() self.setup_for_osx()

View file

@ -21,7 +21,6 @@
from common.configpaths import gajimpaths from common.configpaths import gajimpaths
import Crypto
from common import crypto from common import crypto
from common import exceptions from common import exceptions

View file

@ -655,7 +655,7 @@ class FileTransfersTooltip(BaseTooltip):
properties = [] properties = []
name = file_props['name'] name = file_props['name']
if file_props['type'] == 'r': if file_props['type'] == 'r':
file_name = os.path.split(file_props['file-name'])[1] (file_path, file_name) = os.path.split(file_props['file-name'])
else: else:
file_name = file_props['name'] file_name = file_props['name']
properties.append((_('Name: '), properties.append((_('Name: '),

View file

@ -39,6 +39,7 @@ import locale
import os import os
import gtkgui_helpers import gtkgui_helpers
import message_control
from common import helpers from common import helpers
from common import gajim from common import gajim