merge with default

This commit is contained in:
Yann Leboulanger 2010-03-19 08:23:24 +01:00
commit 9dedf990bd
14 changed files with 107 additions and 79 deletions

View File

@ -1,4 +1,4 @@
# Copyright (C) 2009 Alexander Cherniuk <ts33kr@gmail.com>
# Copyright (C) 2009-2010 Alexander Cherniuk <ts33kr@gmail.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View File

@ -1,4 +1,4 @@
# Copyright (C) 2009 Alexander Cherniuk <ts33kr@gmail.com>
# Copyright (C) 2009-2010 Alexander Cherniuk <ts33kr@gmail.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View File

@ -1,4 +1,4 @@
# Copyright (C) 2009 Alexander Cherniuk <ts33kr@gmail.com>
# Copyright (C) 2009-2010 Alexander Cherniuk <ts33kr@gmail.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -45,3 +45,9 @@ class CommandError(BaseError):
Used to indicate errors occured during command execution.
"""
pass
class NoCommandError(BaseError):
"""
Used to indicate an inability to find the specified command.
"""
pass

View File

@ -1,4 +1,4 @@
# Copyright (C) 2009 Alexander Cherniuk <ts33kr@gmail.com>
# Copyright (C) 2009-2010 Alexander Cherniuk <ts33kr@gmail.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -25,7 +25,7 @@ from inspect import getargspec
from dispatching import Dispatcher, HostDispatcher, ContainerDispatcher
from mapping import parse_arguments, adapt_arguments
from errors import DefinitionError, CommandError
from errors import DefinitionError, CommandError, NoCommandError
class CommandHost(object):
"""
@ -128,7 +128,7 @@ class CommandProcessor(object):
def get_command(self, name):
command = Dispatcher.get_command(self.COMMAND_HOST, name)
if not command:
raise CommandError("Command does not exist", name=name)
raise NoCommandError("Command does not exist", name=name)
return command
def list_commands(self):
@ -330,7 +330,7 @@ def command(*names, **properties):
return decorator
def documentation(text):
def doc(text):
"""
This decorator is used to bind a documentation (a help) to a
command.

View File

@ -1,4 +1,4 @@
# Copyright (C) 2009 Alexander Cherniuk <ts33kr@gmail.com>
# Copyright (C) 2009-2010 Alexander Cherniuk <ts33kr@gmail.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View File

@ -1,4 +1,4 @@
# Copyright (C) 2009 Alexander Cherniuk <ts33kr@gmail.com>
# Copyright (C) 2009-2010 Alexander Cherniuk <ts33kr@gmail.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -21,7 +21,7 @@ Keep in mind that this module is not being loaded, so the code will not
be executed and commands defined here will not be detected.
"""
from ..framework import CommandContainer, command, documentation
from ..framework import CommandContainer, command, doc
from hosts import ChatCommands, PrivateChatCommands, GroupChatCommands
class CustomCommonCommands(CommandContainer):
@ -58,7 +58,7 @@ class CustomChatCommands(CommandContainer):
HOSTS = (ChatCommands,)
@documentation(_("The same as using a doc-string, except it supports translation"))
@doc(_("The same as using a doc-string, except it supports translation"))
@command
def sing(self):
return "Are you phreaking kidding me? Buy yourself a damn stereo..."

View File

@ -1,4 +1,4 @@
# Copyright (C) 2009 Alexander Cherniuk <ts33kr@gmail.com>
# Copyright (C) 2009-2010 Alexander Cherniuk <ts33kr@gmail.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View File

@ -1,4 +1,4 @@
# Copyright (C) 2009 Alexander Cherniuk <ts33kr@gmail.com>
# Copyright (C) 2009-2010 Alexander Cherniuk <ts33kr@gmail.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -26,7 +26,7 @@ from traceback import print_exc
from common import gajim
from ..framework import CommandProcessor
from ..errors import CommandError
from ..errors import CommandError, NoCommandError
class ChatCommandProcessor(CommandProcessor):
"""
@ -44,33 +44,40 @@ class ChatCommandProcessor(CommandProcessor):
def execute_command(self, name, arguments):
try:
super(ChatCommandProcessor, self).execute_command(name, arguments)
except NoCommandError, error:
details = dict(name=error.name, message=error.message)
message = "%(name)s: %(message)s\n" % details
message += "Try using the //%(name)s or /say /%(name)s " % details
message += "construct if you intended to send it as a text."
self.echo(message, 'error')
except CommandError, error:
self.echo("%s: %s" %(error.name, error.message), 'error')
self.echo("%s: %s" % (error.name, error.message), 'error')
except Exception:
self.echo("An error occured while trying to execute the command", 'error')
print_exc()
def looks_like_command(self, text, body, name, arguments):
# Command escape stuff ggoes here. If text was prepended by the command
# prefix twice, like //not_a_command (if prefix is set to /) then it
# will be escaped, that is sent just as a regular message with one (only
# one) prefix removed, so message will be /not_a_command.
# Command escape stuff ggoes here. If text was prepended by the
# command prefix twice, like //not_a_command (if prefix is set
# to /) then it will be escaped, that is sent just as a regular
# message with one (only one) prefix removed, so message will be
# /not_a_command.
if body.startswith(self.COMMAND_PREFIX):
self.send(body)
return True
def command_preprocessor(self, command, name, arguments, args, kwargs):
# If command argument contain h or help option - forward it to the /help
# command. Dont forget to pass self, as all commands are unbound. And
# also don't forget to print output.
# If command argument contain h or help option - forward it to
# the /help command. Dont forget to pass self, as all commands
# are unbound. And also don't forget to print output.
if 'h' in kwargs or 'help' in kwargs:
help = self.get_command('help')
self.echo(help(self, name))
return True
def command_postprocessor(self, command, name, arguments, args, kwargs, value):
# If command returns a string - print it to a user. A convenient and
# sufficient in most simple cases shortcut to a using echo.
# If command returns a string - print it to a user. A convenient
# and sufficient in most simple cases shortcut to a using echo.
if value and isinstance(value, StringTypes):
self.echo(value)

View File

@ -1,4 +1,4 @@
# Copyright (C) 2009 Alexander Cherniuk <ts33kr@gmail.com>
# Copyright (C) 2009-2010 Alexander Cherniuk <ts33kr@gmail.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -27,7 +27,7 @@ from common.exceptions import GajimGeneralException
from common.logger import Constants
from ..errors import CommandError
from ..framework import CommandContainer, command, documentation
from ..framework import CommandContainer, command, doc
from ..mapping import generate_usage
from hosts import ChatCommands, PrivateChatCommands, GroupChatCommands
@ -45,18 +45,18 @@ class StandardCommonCommands(CommandContainer):
HOSTS = (ChatCommands, PrivateChatCommands, GroupChatCommands)
@command
@documentation(_("Clear the text window"))
@doc(_("Clear the text window"))
def clear(self):
self.conv_textview.clear()
@command
@documentation(_("Hide the chat buttons"))
@doc(_("Hide the chat buttons"))
def compact(self):
new_status = not self.hide_chat_buttons
self.chat_buttons_set_visible(new_status)
@command(overlap=True)
@documentation(_("Show help on a given command or a list of available commands if -(-a)ll is given"))
@doc(_("Show help on a given command or a list of available commands if -(-a)ll is given"))
def help(self, command=None, all=False):
if command:
command = self.get_command(command)
@ -83,17 +83,17 @@ class StandardCommonCommands(CommandContainer):
self.echo(help(self, 'help'))
@command(raw=True)
@documentation(_("Send a message to the contact"))
@doc(_("Send a message to the contact"))
def say(self, message):
self.send(message)
@command(raw=True)
@documentation(_("Send action (in the third person) to the current chat"))
@doc(_("Send action (in the third person) to the current chat"))
def me(self, action):
self.send("/me %s" % action)
@command('lastlog', overlap=True)
@documentation(_("Show logged messages which mention given text"))
@doc(_("Show logged messages which mention given text"))
def grep(self, text, limit=None):
results = gajim.logger.get_search_results_for_query(self.contact.jid,
text, self.account)
@ -129,7 +129,7 @@ class StandardCommonCommands(CommandContainer):
self.echo(formatted)
@command(raw=True, empty=True)
@documentation(_("""
@doc(_("""
Set current the status
Status can be given as one of the following values: online, away,
@ -142,7 +142,7 @@ class StandardCommonCommands(CommandContainer):
connection.change_status(status, message)
@command(raw=True, empty=True)
@documentation(_("Set the current status to away"))
@doc(_("Set the current status to away"))
def away(self, message):
if not message:
message = _("Away")
@ -150,36 +150,40 @@ class StandardCommonCommands(CommandContainer):
connection.change_status('away', message)
@command('back', raw=True, empty=True)
@documentation(_("Set the current status to online"))
@doc(_("Set the current status to online"))
def online(self, message):
if not message:
message = _("Available")
for connection in gajim.connections.itervalues():
connection.change_status('online', message)
class StandardChatCommands(CommandContainer):
class StandardCommonChatCommands(CommandContainer):
"""
This command container contains standard command which are unique to
a chat.
This command container contans standard commands, which are common
to a chat and a private chat only.
"""
HOSTS = (ChatCommands,)
HOSTS = (ChatCommands, PrivateChatCommands)
@command
@documentation(_("Send a ping to the contact"))
@doc(_("Toggle the GPG encryption"))
def gpg(self):
self._toggle_gpg()
@command
@doc(_("Send a ping to the contact"))
def ping(self):
if self.account == gajim.ZEROCONF_ACC_NAME:
raise CommandError(_('Command is not supported for zeroconf accounts'))
gajim.connections[self.account].sendPing(self.contact)
@command
@documentation(_("Sends DTMF events through an open audio session"))
@doc(_("Send DTMF events through an open audio session"))
def dtmf(self, events):
if not self.audio_sid:
raise CommandError(_("There is no open audio session with this contact"))
# Valid values for DTMF tones are *, # or a number
events = [event for event in events
if event in ('*', '#') or event.isdigit()]
events = filter(lambda e: e in ('*', '#') or e.isdigit (), events)
if events:
session = gajim.connections[self.account].get_jingle_session(
self.contact.get_full_jid(), self.audio_sid)
@ -189,7 +193,7 @@ class StandardChatCommands(CommandContainer):
raise CommandError(_("No valid DTMF event specified"))
@command
@documentation(_("Toggle audio session"))
@doc(_("Toggle audio session"))
def audio(self):
if self.audio_state == self.JINGLE_STATE_NOT_AVAILABLE:
raise CommandError(_("Video sessions are not available"))
@ -200,7 +204,7 @@ class StandardChatCommands(CommandContainer):
self._audio_button.set_active(not state)
@command
@documentation(_("Toggle video session"))
@doc(_("Toggle video session"))
def video(self):
if self.video_state == self.JINGLE_STATE_NOT_AVAILABLE:
raise CommandError(_("Video sessions are not available"))
@ -210,24 +214,32 @@ class StandardChatCommands(CommandContainer):
state = self._video_button.get_active()
self._video_button.set_active(not state)
class StandardChatCommands(CommandContainer):
"""
This command container contains standard commands which are unique
to a chat.
"""
HOSTS = (ChatCommands,)
class StandardPrivateChatCommands(CommandContainer):
"""
This command container contains standard command which are unique to
a private chat.
This command container contains standard commands which are unique
to a private chat.
"""
HOSTS = (PrivateChatCommands,)
class StandardGroupchatCommands(CommandContainer):
class StandardGroupChatCommands(CommandContainer):
"""
This command container contains standard command which are unique to
a group chat.
This command container contains standard commands which are unique
to a group chat.
"""
HOSTS = (GroupChatCommands,)
@command(raw=True)
@documentation(_("Change your nickname in a group chat"))
@doc(_("Change your nickname in a group chat"))
def nick(self, new_nick):
try:
new_nick = helpers.parse_resource(new_nick)
@ -237,7 +249,7 @@ class StandardGroupchatCommands(CommandContainer):
self.new_nick = new_nick
@command('query', raw=True)
@documentation(_("Open a private chat window with a specified occupant"))
@doc(_("Open a private chat window with a specified occupant"))
def chat(self, nick):
nicks = gajim.contacts.get_nick_list(self.account, self.room_jid)
if nick in nicks:
@ -246,7 +258,7 @@ class StandardGroupchatCommands(CommandContainer):
raise CommandError(_("Nickname not found"))
@command('msg', raw=True)
@documentation(_("Open a private chat window with a specified occupant and send him a message"))
@doc(_("Open a private chat window with a specified occupant and send him a message"))
def message(self, nick, a_message):
nicks = gajim.contacts.get_nick_list(self.account, self.room_jid)
if nick in nicks:
@ -255,7 +267,7 @@ class StandardGroupchatCommands(CommandContainer):
raise CommandError(_("Nickname not found"))
@command(raw=True, empty=True)
@documentation(_("Display or change a group chat topic"))
@doc(_("Display or change a group chat topic"))
def topic(self, new_topic):
if new_topic:
self.connection.send_gc_subject(self.room_jid, new_topic)
@ -263,13 +275,13 @@ class StandardGroupchatCommands(CommandContainer):
return self.subject
@command(raw=True, empty=True)
@documentation(_("Invite a user to a room for a reason"))
@doc(_("Invite a user to a room for a reason"))
def invite(self, jid, reason):
self.connection.send_invite(self.room_jid, jid, reason)
return _("Invited %s to %s") % (jid, self.room_jid)
@command(raw=True, empty=True)
@documentation(_("Join a group chat given by a jid, optionally using given nickname"))
@doc(_("Join a group chat given by a jid, optionally using given nickname"))
def join(self, jid, nick):
if not nick:
nick = self.nick
@ -286,12 +298,12 @@ class StandardGroupchatCommands(CommandContainer):
pass
@command('part', 'close', raw=True, empty=True)
@documentation(_("Leave the groupchat, optionally giving a reason, and close tab or window"))
@doc(_("Leave the groupchat, optionally giving a reason, and close tab or window"))
def leave(self, reason):
self.parent_win.remove_tab(self, self.parent_win.CLOSE_COMMAND, reason)
@command(raw=True, empty=True)
@documentation(_("""
@doc(_("""
Ban user by a nick or a jid from a groupchat
If given nickname is not found it will be treated as a jid.
@ -303,14 +315,14 @@ class StandardGroupchatCommands(CommandContainer):
self.connection.gc_set_affiliation(self.room_jid, who, 'outcast', reason or str())
@command(raw=True, empty=True)
@documentation(_("Kick user by a nick from a groupchat"))
@doc(_("Kick user by a nick from a groupchat"))
def kick(self, who, reason):
if not who in gajim.contacts.get_nick_list(self.account, self.room_jid):
raise CommandError(_("Nickname not found"))
self.connection.gc_set_role(self.room_jid, who, 'none', reason or str())
@command
@documentation(_("Display names of all group chat occupants"))
@doc(_("Display names of all group chat occupants"))
def names(self, verbose=False):
get_contact = lambda nick: gajim.contacts.get_gc_contact(self.account, self.room_jid, nick)
nicks = gajim.contacts.get_nick_list(self.account, self.room_jid)
@ -331,11 +343,11 @@ class StandardGroupchatCommands(CommandContainer):
return ', '.join(nicks)
@command('ignore', raw=True)
@documentation(_("Forbid an occupant to send you public or private messages"))
@doc(_("Forbid an occupant to send you public or private messages"))
def block(self, who):
self.on_block(None, who)
@command('unignore', raw=True)
@documentation(_("Allow an occupant to send you public or private messages"))
@doc(_("Allow an occupant to send you public or private messages"))
def unblock(self, who):
self.on_unblock(None, who)

View File

@ -1,4 +1,4 @@
# Copyright (C) 2009 Alexander Cherniuk <ts33kr@gmail.com>
# Copyright (C) 2009-2010 Alexander Cherniuk <ts33kr@gmail.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View File

@ -31,6 +31,7 @@ class DeviceManager(object):
element = gst.element_factory_make(name, '%spresencetest' % name)
if isinstance(element, gst.interfaces.PropertyProbe):
element.set_state(gst.STATE_READY)
element.probe_property_name('device')
devices = element.probe_get_values_name('device')
if devices:
self.devices[text % _(' Default device')] = pipe % name
@ -79,7 +80,7 @@ class VideoInputManager(DeviceManager):
'%s is-live=true')
# Auto src
self.detect_element('autovideosrc', _('Autodetect'))
# V4L2 src ; TODO: Figure out why it doesn't work
# V4L2 src
self.detect_element('v4l2src', _('V4L2: %s'))
# Funny things, just to test...
# self.devices['GOOM'] = 'audiotestsrc ! goom'
@ -96,3 +97,4 @@ class VideoOutputManager(DeviceManager):
# ximagesink
self.detect_element('ximagesink', _('X Window System (without Xv)'))
self.detect_element('autovideosink', _('Autodetect'))

View File

@ -422,13 +422,18 @@ class SASL(PlugIn):
self.on_sasl()
raise NodeProcessed
@staticmethod
def _convert_to_iso88591(string):
try:
string = string.decode('utf-8').encode('iso-8859-1')
except UnicodeEncodeError:
pass
return string
def set_password(self, password):
if password is None:
self.password = ''
else:
self.password = password
self.password = '' if password is None else password
if self.mechanism == 'SCRAM-SHA-1':
nonce = ''.join('%x' % randint(0, 2**28) for randint in \
nonce = ''.join('%x' % randint(0, 2 ** 28) for randint in \
itertools.repeat(random.randint, 7))
self.scram_soup = 'n=' + self.username + ',r=' + nonce
self.scram_gs2 = 'n,,' # No CB yet.
@ -437,15 +442,9 @@ class SASL(PlugIn):
node = Node('auth', attrs={'xmlns': NS_SASL,
'mechanism': self.mechanism}, payload=[sasl_data])
elif self.mechanism == 'DIGEST-MD5':
def convert_to_iso88591(string):
try:
string = string.decode('utf-8').encode('iso-8859-1')
except UnicodeEncodeError:
pass
return string
hash_username = convert_to_iso88591(self.resp['username'])
hash_realm = convert_to_iso88591(self.resp['realm'])
hash_password = convert_to_iso88591(self.password)
hash_username = self._convert_to_iso88591(self.resp['username'])
hash_realm = self._convert_to_iso88591(self.resp['realm'])
hash_password = self._convert_to_iso88591(self.password)
A1 = C([H(C([hash_username, hash_realm, hash_password])),
self.resp['nonce'], self.resp['cnonce']])
A2 = C(['AUTHENTICATE', self.resp['digest-uri']])

View File

@ -400,7 +400,7 @@ class SingleForm(gtk.Table, object):
check.set_active(value in field.values)
check.connect('toggled',
self.on_list_multi_checkbutton_toggled, field, value)
widget.pack_start(check, expand=False)
widget.pack_start(check, expand=False)
else:
# more than 5 options: show combobox
def on_list_multi_treeview_changed(selection, f):

View File

@ -534,6 +534,8 @@ class GajimRemote:
self.arguments += ['']*(len(args)-i)
def handle_uri(self):
if len(sys.argv) < 3:
send_error(_('No uri given'))
if not sys.argv[2].startswith('xmpp:'):
send_error(_('Wrong uri'))
sys.argv[2] = sys.argv[2][5:]