Newer
Older

Yann Leboulanger
committed
else:
reduced_text = ''
return reduced_text

Yann Leboulanger
committed
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
def get_account_status(account):
status = reduce_chars_newlines(account['status_line'], 100, 1)
return status
def get_notification_icon_tooltip_dict():
'''returns a dict of the form {acct: {'show': show, 'message': message,
'event_lines': [list of text lines to show in tooltip]}'''
# How many events must there be before they're shown summarized, not per-user
max_ungrouped_events = 10
accounts = get_accounts_info()
# Gather events. (With accounts, when there are more.)
for account in accounts:
account_name = account['name']
account['event_lines'] = []
# Gather events per-account
pending_events = gajim.events.get_events(account = account_name)
messages, non_messages, total_messages, total_non_messages = {}, {}, 0, 0
for jid in pending_events:
for event in pending_events[jid]:
if event.type_.count('file') > 0:
# This is a non-messagee event.
messages[jid] = non_messages.get(jid, 0) + 1
total_non_messages = total_non_messages + 1
else:
# This is a message.
messages[jid] = messages.get(jid, 0) + 1
total_messages = total_messages + 1
# Display unread messages numbers, if any
if total_messages > 0:
if total_messages > max_ungrouped_events:
text = ngettext(
'%d message pending',
'%d messages pending',
total_messages, total_messages, total_messages)
account['event_lines'].append(text)
else:
for jid in messages.keys():
text = ngettext(
'%d message pending',
'%d messages pending',
messages[jid], messages[jid], messages[jid])
contact = gajim.contacts.get_first_contact_from_jid(
account['name'], jid)
if jid in gajim.gc_connected[account['name']]:
text += _(' from room %s') % (jid)
elif contact:
name = contact.get_shown_name()
text += _(' from user %s') % (name)
else:
text += _(' from %s') % (jid)
account['event_lines'].append(text)
# Display unseen events numbers, if any
if total_non_messages > 0:
if total_non_messages > max_ungrouped_events:
text = ngettext(
'%d event pending',
'%d events pending',
total_non_messages, total_non_messages, total_non_messages)
accounts[account]['event_lines'].append(text)
else:
for jid in non_messages.keys():
text = ngettext(
'%d event pending',
'%d events pending',
non_messages[jid], non_messages[jid], non_messages[jid])
text += _(' from user %s') % (jid)
accounts[account]['event_lines'].append(text)
return accounts
def get_notification_icon_tooltip_text():
text = None

Yann Leboulanger
committed
# How many events must there be before they're shown summarized, not per-user
max_ungrouped_events = 10
# Character which should be used to indent in the tooltip.
indent_with = ' '

Yann Leboulanger
committed
accounts = get_notification_icon_tooltip_dict()

Yann Leboulanger
committed
if len(accounts) == 0:
# No configured account
return _('Gajim')
# at least one account present
# Is there more that one account?
if len(accounts) == 1:
show_more_accounts = False

Yann Leboulanger
committed
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
show_more_accounts = True
# If there is only one account, its status is shown on the first line.
if show_more_accounts:
text = _('Gajim')
else:
text = _('Gajim - %s') % (get_account_status(accounts[0]))
# Gather and display events. (With accounts, when there are more.)
for account in accounts:
account_name = account['name']
# Set account status, if not set above
if (show_more_accounts):
message = '\n' + indent_with + ' %s - %s'
text += message % (account_name, get_account_status(account))
# Account list shown, messages need to be indented more
indent_how = 2
else:
# If no account list is shown, messages could have default indenting.
indent_how = 1
for line in account['event_lines']:
text += '\n' + indent_with * indent_how + ' '
text += line
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
return text
def get_accounts_info():
'''helper for notification icon tooltip'''
accounts = []
accounts_list = gajim.contacts.get_accounts()
accounts_list.sort()
for account in accounts_list:
status_idx = gajim.connections[account].connected
# uncomment the following to hide offline accounts
# if status_idx == 0: continue
status = gajim.SHOW_LIST[status_idx]
message = gajim.connections[account].status
single_line = get_uf_show(status)
if message is None:
message = ''
else:
message = message.strip()
if message != '':
single_line += ': ' + message
accounts.append({'name': account, 'status_line': single_line,
'show': status, 'message': message})
return accounts
def get_avatar_path(prefix):
'''Returns the filename of the avatar, distinguishes between user- and
contact-provided one. Returns None if no avatar was found at all.
prefix is the path to the requested avatar just before the ".png" or
".jpeg".'''
# First, scan for a local, user-set avatar
for type_ in ('jpeg', 'png'):
file_ = prefix + '_local.' + type_
if os.path.exists(file_):
return file_
# If none available, scan for a contact-provided avatar
for type_ in ('jpeg', 'png'):
file_ = prefix + '.' + type_
if os.path.exists(file_):
return file_
return None

nicfit
committed
def datetime_tuple(timestamp):
'''Converts timestamp using strptime and the format: %Y%m%dT%H:%M:%S
Because of various datetime formats are used the following exceptions
are handled:
- Optional milliseconds appened to the string are removed
- Optional Z (that means UTC) appened to the string are removed

nicfit
committed
- XEP-082 datetime strings have all '-' cahrs removed to meet
the above format.'''
timestamp = timestamp.split('.')[0]
timestamp = timestamp.replace('-', '')
timestamp = timestamp.replace('z', '')
timestamp = timestamp.replace('Z', '')

nicfit
committed
from time import strptime
return strptime(timestamp, '%Y%m%dT%H:%M:%S')
def get_iconset_path(iconset):
if os.path.isdir(os.path.join(gajim.DATA_DIR, 'iconsets', iconset)):
return os.path.join(gajim.DATA_DIR, 'iconsets', iconset)
elif os.path.isdir(os.path.join(gajim.MY_ICONSETS_PATH, iconset)):
return os.path.join(gajim.MY_ICONSETS_PATH, iconset)

Yann Leboulanger
committed
def get_mood_iconset_path(iconset):
if os.path.isdir(os.path.join(gajim.DATA_DIR, 'moods', iconset)):
return os.path.join(gajim.DATA_DIR, 'moods', iconset)
elif os.path.isdir(os.path.join(gajim.MY_MOOD_ICONSETS_PATH, iconset)):
return os.path.join(gajim.MY_MOOD_ICONSETS_PATH, iconset)

Yann Leboulanger
committed
def get_transport_path(transport):
if os.path.isdir(os.path.join(gajim.DATA_DIR, 'iconsets', 'transports',
transport)):
return os.path.join(gajim.DATA_DIR, 'iconsets', 'transports', transport)
elif os.path.isdir(os.path.join(gajim.MY_ICONSETS_PATH, 'transports',
transport)):
return os.path.join(gajim.MY_ICONSETS_PATH, 'transports', transport)
# No transport folder found, use default jabber one
return get_iconset_path(gajim.config.get('iconset'))
def prepare_and_validate_gpg_keyID(account, jid, keyID):
'''Returns an eight char long keyID that can be used with for GPG encryption with this contact.
If the given keyID is None, return UNKNOWN; if the key does not match the assigned key
XXXXXXXXMISMATCH is returned. If the key is trusted and not yet assigned, assign it'''
if gajim.connections[account].USE_GPG:
if keyID and len(keyID) == 16:
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
keyID = keyID[8:]
attached_keys = gajim.config.get_per('accounts', account,
'attached_gpg_keys').split()
if jid in attached_keys and keyID:
attachedkeyID = attached_keys[attached_keys.index(jid) + 1]
if attachedkeyID != keyID:
# Mismatch! Another gpg key was expected
keyID += 'MISMATCH'
elif jid in attached_keys:
# An unsigned presence, just use the assigned key
keyID = attached_keys[attached_keys.index(jid) + 1]
elif keyID:
public_keys = gajim.connections[account].ask_gpg_keys()
# Assign the corresponding key, if we have it in our keyring
if public_keys.has_key(keyID):
for u in gajim.contacts.get_contacts(account, jid):
u.keyID = keyID
keys_str = gajim.config.get_per('accounts', account, 'attached_gpg_keys')
keys_str += jid + ' ' + keyID + ' '
gajim.config.set_per('accounts', account, 'attached_gpg_keys', keys_str)
elif keyID is None:
keyID = 'UNKNOWN'
return keyID
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
def sort_identities_func(i1, i2):
cat1 = i1['category']
cat2 = i2['category']
if cat1 < cat2:
return -1
if cat1 > cat2:
return 1
if i1.has_key('type'):
type1 = i1['type']
else:
type1 = ''
if i2.has_key('type'):
type2 = i2['type']
else:
type2 = ''
if type1 < type2:
return -1
if type1 > type2:
return 1
if i1.has_key('xml:lang'):
lang1 = i1['xml:lang']
else:
lang1 = ''
if i2.has_key('xml:lang'):
lang2 = i2['xml:lang']
else:
lang2 = ''
if lang1 < lang2:
return -1
if lang1 > lang2:
return 1
return 0
def sort_dataforms_func(d1, d2):
f1 = d1.getField('FORM_TYPE')
f2 = d2.getField('FORM_TYPE')
if f1 and f2 and (f1.getValue() < f2.getValue()):
return -1
return 1
def compute_caps_hash(identities, features, dataforms=[], hash_method='sha-1'):
'''Compute caps hash according to XEP-0115, V1.5
dataforms are xmpp.DataForms objects as common.dataforms don't allow several
values without a field type list-multi'''
S = ''
identities.sort(cmp=sort_identities_func)
for i in identities:
c = i['category']
if i.has_key('type'):
type_ = i['type']
else:
type_ = ''
if i.has_key('xml:lang'):
lang = i['xml:lang']
else:
lang = ''
if i.has_key('name'):
name = i['name']
else:
name = ''
S += '%s/%s/%s/%s<' % (c, type_, lang, name)
features.sort()
for f in features:
S += '%s<' % f
dataforms.sort(cmp=sort_dataforms_func)
for dataform in dataforms:
# fields indexed by var
fields = {}
for f in dataform.getChildren():
fields[f.getVar()] = f
form_type = fields.get('FORM_TYPE')
if form_type:
S += form_type.getValue() + '<'
del fields['FORM_TYPE']
vars = fields.keys()
vars.sort()
for var in vars:
S += '%s<' % var
values = fields[var].getValues()
values.sort()
for value in values:
S += '%s<' % value
if hash_method == 'sha-1':
elif hash_method == 'md5':
else:
return ''
return base64.b64encode(hash.digest())

Yann Leboulanger
committed
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
def update_optional_features(account = None):
if account:
accounts = [account]
else:
accounts = [a for a in gajim.connections]
for a in accounts:
gajim.gajim_optional_features[a] = []
if gajim.config.get_per('accounts', a, 'publish_mood'):
gajim.gajim_optional_features[a].append(xmpp.NS_MOOD)
if gajim.config.get_per('accounts', a, 'subscribe_mood'):
gajim.gajim_optional_features[a].append(xmpp.NS_MOOD + '+notify')
if gajim.config.get_per('accounts', a, 'publish_activity'):
gajim.gajim_optional_features[a].append(xmpp.NS_ACTIVITY)
if gajim.config.get_per('accounts', a, 'subscribe_activity'):
gajim.gajim_optional_features[a].append(xmpp.NS_ACTIVITY + '+notify')
if gajim.config.get_per('accounts', a, 'publish_tune'):
gajim.gajim_optional_features[a].append(xmpp.NS_TUNE)
if gajim.config.get_per('accounts', a, 'subscribe_tune'):
gajim.gajim_optional_features[a].append(xmpp.NS_TUNE + '+notify')
if gajim.config.get_per('accounts', a, 'publish_nick'):
gajim.gajim_optional_features[a].append(xmpp.NS_NICK)
if gajim.config.get_per('accounts', a, 'subscribe_nick'):
gajim.gajim_optional_features[a].append(xmpp.NS_NICK + '+notify')
if gajim.config.get('outgoing_chat_state_notifactions') != 'disabled':
gajim.gajim_optional_features[a].append(xmpp.NS_CHATSTATES)
if not gajim.config.get('ignore_incoming_xhtml'):
gajim.gajim_optional_features[a].append(xmpp.NS_XHTML_IM)
if gajim.HAVE_PYCRYPTO \
and gajim.config.get_per('accounts', a, 'enable_esessions'):
gajim.gajim_optional_features[a].append(xmpp.NS_ESESSION)
if gajim.config.get_per('accounts', a, 'answer_receipts'):
gajim.gajim_optional_features[a].append(xmpp.NS_RECEIPTS)

Yann Leboulanger
committed
gajim.caps_hash[a] = compute_caps_hash([gajim.gajim_identity],
gajim.gajim_common_features + gajim.gajim_optional_features[a])
# re-send presence with new hash
connected = gajim.connections[a].connected
if connected > 1 and gajim.SHOW_LIST[connected] != 'invisible':

Yann Leboulanger
committed
gajim.connections[a].change_status(gajim.SHOW_LIST[connected],
gajim.connections[a].status)