Skip to content
Snippets Groups Projects
helpers.py 38.9 KiB
Newer Older
						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
	# 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 = ' '
	accounts = get_notification_icon_tooltip_dict()
	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
		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
	return text

def get_accounts_info():
	'''helper for notification icon tooltip'''
	accounts = []
	accounts_list = sorted(gajim.contacts.get_accounts())
	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

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
		- 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', '')
	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)
js's avatar
js 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)

js's avatar
js committed
def get_activity_iconset_path(iconset):
	if os.path.isdir(os.path.join(gajim.DATA_DIR, 'activities', iconset)):
		return os.path.join(gajim.DATA_DIR, 'activities', iconset)
	elif os.path.isdir(os.path.join(gajim.MY_ACTIVITY_ICONSETS_PATH,
	iconset)):
		return os.path.join(gajim.MY_ACTIVITY_ICONSETS_PATH, iconset)

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'))
steve-e's avatar
steve-e committed

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:	
steve-e's avatar
steve-e committed
			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
steve-e's avatar
steve-e committed
				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

def sort_identities_func(i1, i2):
	cat1 = i1['category']
	cat2 = i2['category']
	if cat1 < cat2:
		return -1
	if cat1 > cat2:
		return 1
	type1 = i1.get('type', '')
	type2 = i2.get('type', '')
	if type1 < type2:
		return -1
	if type1 > type2:
		return 1
	lang1 = i1.get('xml:lang', '')
	lang2 = i2.get('xml:lang', '')
	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']
		type_ = i.get('type', '')
		lang = i.get('xml:lang', '')
		name = i.get('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']
			values = sorted(fields[var].getValues())
			for value in values:
				S += '%s<' % value

	if hash_method == 'sha-1':
		hash = hash_sha1(S)
	elif hash_method == 'md5':
		hash = hash_md5(S)
	else:
		return ''
	return base64.b64encode(hash.digest())

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, 'subscribe_mood'):
			gajim.gajim_optional_features[a].append(xmpp.NS_MOOD + '+notify')
		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, '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)
js's avatar
js committed
		if gajim.config.get_per('accounts', a, 'answer_receipts'):
			gajim.gajim_optional_features[a].append(xmpp.NS_RECEIPTS)
		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':
			gajim.connections[a].change_status(gajim.SHOW_LIST[connected],
				gajim.connections[a].status)