merge from trunk

This commit is contained in:
Yann Leboulanger 2012-04-12 22:07:30 +02:00
commit 0c36f50196
118 changed files with 7893 additions and 6967 deletions

View file

@ -1,4 +1,4 @@
Gajim 0.15 (XX XX 2011)
Gajim 0.15 (18 March 2012)
* Plugin system
* Whiteboard (via a plugin)
@ -9,6 +9,7 @@ Gajim 0.15 (XX XX 2011)
* Roster filtrering
* UPower support
* GPG support for windows
* Spell checking support for windows
Gajim 0.14.4 (22 July 2011)

View file

@ -15,12 +15,13 @@
<h2>Runtime Requirements</h2>
<ul>
<li>python2.5 or higher</li>
<li>pygtk2.16 or higher</li>
<li>pygtk2.22 or higher</li>
</ul>
<h2>Optional Runtime Requirements</h2>
<ul>
<li><a href="http://pyopenssl.sourceforge.net/">PyOpenSSL</a> (python-pyopenssl package in Debian) (>=0.9) for <em>secure</em> SSL/TLS. Python's default SSL is insecure, so this package is highly recommended!</li>
<li><a href="http://pyopenssl.sourceforge.net/">PyOpenSSL</a> (python-pyopenssl package in Debian) (>=0.12) for <em>secure</em> SSL/TLS. Python's default SSL is insecure, so this package is highly recommended!</li>
<li>python-pyasn1 to check SSL/TLS certificate</li>
<li>python-crypto to enable End to end encryption</li>
<li>For idle module, libxss library</li>
<li>For zeroconf (bonjour), the "enable link-local messaging" checkbox, you need dbus-glib, python-avahi</li>
@ -111,7 +112,7 @@ Wiki can be found at <a href="http://trac.gajim.org/wiki">http://trac.gajim.org/
<br/>
<br/>
<br/>
(C) 2003-2011<br/>
(C) 2003-2012<br/>
The Gajim Team<br/>
http://gajim.org<br/>
<br/>

View file

@ -1,5 +1,5 @@
#!/usr/bin/env bash
gajimversion="0.15-beta2"
gajimversion="0.15"
if [ -d ".hg" ]; then
node=$(hg tip --template "{node}")
hgversion="-${node:0:12}"
@ -20,8 +20,12 @@
&& for p in `ls data/gui/*.ui`; do echo "[type: gettext/glade]$p" >> \
po/POTFILES.in; done \
&& ls -1 data/gajim.desktop.in.in \
src/*py src/common/*py src/common/zeroconf/*.py src/plugins/*.py| grep -v ipython_view.py >> \
po/POTFILES.in || exit 1
src/*.py src/common/*.py src/command_system/implementation/*.py src/common/zeroconf/*.py src/plugins/*.py | grep -v ipython_view.py >> \
po/POTFILES.in \
&& echo -e "data/gajim.desktop.in\nsrc/ipython_view.py" > po/POTFILES.skip || exit 1
if [ $(find plugins/ -name '*.py' | wc -l) -gt 0 ];then
ls -1 plugins/*/*.py plugins/*/*.ui >> po/POTFILES.skip
fi
if test -z `which pkg-config 2>/dev/null`;then
echo "***Error: pkg-config not found***"
echo "See README.html for build requirements."

View file

@ -47,12 +47,12 @@ AC_ARG_ENABLE(site-packages,
instead of DATADIR/gajim/src.])]
,
AC_SUBST([gajim_srcdir], [\${pkgpythondir}])
AC_SUBST([gajim_pluginsdir], [\${pkgpythondir}])
,
AC_SUBST([gajim_srcdir], [\${datadir}/\${PACKAGE}/src])
AC_SUBST([gajim_pluginsdir], [\${datadir}/\${PACKAGE}/plugins])
)
AC_SUBST([gajim_pluginsdir], [\${datadir}/\${PACKAGE}/plugins])
AS_AC_EXPAND(GAJIM_SRCDIR, "${gajim_srcdir}")
AS_AC_EXPAND(PKGDATADIR, "${datadir}/${PACKAGE}")
AS_AC_EXPAND(DOCDIR, "${docdir}")

View file

@ -308,7 +308,7 @@
<property name="homogeneous">True</property>
<child>
<object class="GtkButton" id="synchronise_contacts_button1">
<property name="label" translatable="yes">Synchronise contacts</property>
<property name="label" translatable="yes">Synchronize contacts</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>

View file

@ -1,24 +1,25 @@
<?xml version="1.0"?>
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="2.16"/>
<!-- interface-naming-policy toplevel-contextual -->
<object class="GtkWindow" id="advanced_configuration_window">
<property name="can_focus">False</property>
<property name="border_width">6</property>
<property name="title" translatable="yes">Advanced Configuration Editor</property>
<property name="role">ace</property>
<property name="default_width">650</property>
<property name="default_height">540</property>
<property name="type_hint">dialog</property>
<signal name="destroy" handler="on_advanced_configuration_window_destroy"/>
<signal name="destroy" handler="on_advanced_configuration_window_destroy" swapped="no"/>
<child>
<object class="GtkVBox" id="vbox70">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="border_width">6</property>
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkTable" id="table26">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="n_rows">2</property>
<property name="n_columns">2</property>
<property name="column_spacing">12</property>
@ -26,6 +27,7 @@
<child>
<object class="GtkLabel" id="label248">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Filter:</property>
</object>
@ -38,7 +40,7 @@
<object class="GtkEntry" id="advanced_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<signal name="changed" handler="on_advanced_entry_changed"/>
<signal name="changed" handler="on_advanced_entry_changed" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
@ -51,14 +53,16 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">never</property>
<property name="vscrollbar_policy">automatic</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkTreeView" id="advanced_treeview">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="rules_hint">True</property>
<signal name="row_activated" handler="on_advanced_treeview_row_activated"/>
<signal name="row-activated" handler="on_advanced_treeview_row_activated" swapped="no"/>
<child internal-child="selection">
<object class="GtkTreeSelection" id="treeview-selection1"/>
</child>
</object>
</child>
</object>
@ -71,23 +75,28 @@
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkFrame" id="frame36">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="border_width">3</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkAlignment" id="alignment90">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="border_width">6</property>
<property name="left_padding">12</property>
<child>
<object class="GtkLabel" id="advanced_desc_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="wrap">True</property>
</object>
@ -97,6 +106,7 @@
<child type="label">
<object class="GtkLabel" id="label357">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">&lt;b&gt;Description&lt;/b&gt;</property>
<property name="use_markup">True</property>
</object>
@ -104,11 +114,13 @@
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="restart_label">
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">&lt;b&gt;NOTE:&lt;/b&gt; You should restart Gajim for some settings to take effect</property>
<property name="use_markup">True</property>
@ -123,27 +135,50 @@
<child>
<object class="GtkHButtonBox" id="hbuttonbox18">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">6</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="reset_button">
<property name="label" translatable="yes">_Reset to default</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="image">image1</property>
<property name="use_underline">True</property>
<signal name="clicked" handler="on_reset_button_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="advanced_close_button">
<property name="label">gtk-close</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
<signal name="clicked" handler="on_advanced_close_button_clicked"/>
<signal name="clicked" handler="on_advanced_close_button_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="padding">6</property>
<property name="position">3</property>
</packing>
@ -151,4 +186,9 @@
</object>
</child>
</object>
<object class="GtkImage" id="image1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-undo</property>
</object>
</interface>

View file

@ -60,7 +60,7 @@
<object class="GtkLabel" id="banner_label">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">label</property>
<property name="label">label</property>
<property name="use_markup">True</property>
<property name="selectable">True</property>
<signal name="populate_popup" handler="on_banner_label_populate_popup"/>

View file

@ -54,7 +54,7 @@
<object class="GtkLabel" id="banner_label">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">label</property>
<property name="label">label</property>
<property name="use_markup">True</property>
<property name="selectable">True</property>
</object>

View file

@ -202,7 +202,7 @@
<child>
<object class="GtkCheckMenuItem" id="show_transports_menuitem">
<property name="visible">True</property>
<property name="label" translatable="yes">Show T_rans_ports</property>
<property name="label" translatable="yes">Show T_ransports</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_show_transports_menuitem_activate"/>
</object>

BIN
data/sounds/attention.wav Normal file

Binary file not shown.

View file

@ -1,7 +1,7 @@
gajim for Debian
----------------
For video chat support, you have to install python-farsight.
For video chat support, you have to install python-farstream.
-- Yann Le Boulanger <asterix@lagaule.org>, Mon, 20 Jun 2005 12:02:31 +0200
-- Julien Valroff <julien@debian.org> Sat, 07 May 2011 13:50:27 +0200

4
debian/changelog vendored
View file

@ -1,11 +1,11 @@
gajim (0.15~alpha1-1) unstable; urgency=low
gajim (0.15-1) unstable; urgency=low
* New upstream release.
* remove 00_debian-copying.diff because upstream doesn't install it anymore
* remove 01_configure-ac.diff because upstream changed configure dependencies
* remove python-gnupginterface from recommands list, it's no more used
-- Yann Leboulanger <asterix@lagaule.org> Fri, 26 Aug 2011 12:13:51 +0200
-- Yann Leboulanger <asterix@lagaule.org> Sat, 18 Mar 2012 10:32:38 +0100
gajim (0.14.4-1) unstable; urgency=low

8
debian/control vendored
View file

@ -3,16 +3,16 @@ Section: net
Priority: optional
Maintainer: Yann Leboulanger <asterix@lagaule.org>
Build-Depends: debhelper (>= 7.0.50~), python (>= 2.6.6-3~), gettext (>= 0.17-4), intltool (>= 0.40.1), imagemagick, libglib2.0-dev
Standards-Version: 3.9.2
Standards-Version: 3.9.3
Homepage: http://www.gajim.org
Vcs-Hg: http://hg.gajim.org/gajim/
Vcs-Browser: http://hg.gajim.org/gajim/file
Package: gajim
Architecture: all
Depends: ${misc:Depends}, ${python:Depends}, python-gtk2 (>= 2.16.0), dnsutils
Recommends: dbus, python-dbus, notification-daemon, python-openssl (>= 0.9), python-crypto
Suggests: python-gconf, python-gnome2, nautilus-sendto, avahi-daemon, python-avahi, network-manager, libgtkspell0, aspell-en, python-gnomekeyring, gnome-keyring, python-kerberos (>= 1.1), texlive-latex-base, dvipng, python-farsight, gstreamer0.10-plugins-ugly
Depends: ${misc:Depends}, ${python:Depends}, python-gtk2 (>= 2.22.0), dnsutils
Recommends: dbus, python-dbus, notification-daemon, python-openssl (>= 0.12), python-crypto, python-pyasn1
Suggests: python-gconf, python-gnome2, nautilus-sendto, avahi-daemon, python-avahi, network-manager, libgtkspell0, aspell-en, python-gnomekeyring, gnome-keyring, python-kerberos (>= 1.1), texlive-latex-base, dvipng, python-farstream, gstreamer0.10-plugins-ugly, python-pycurl, python-gupnp-igd
Description: Jabber client written in PyGTK
Gajim is a Jabber client. It has a tabbed user interface with normal chats,
group chats, and has many features such as, TLS, GPG, SSL, multiple accounts,

2
debian/copyright vendored
View file

@ -9,7 +9,7 @@ Upstream Authors:
- Yann Leboulanger <asterix@lagaule.org>
Copyright: (c) 2003-2011 Gajim Team
Copyright: (c) 2003-2012 Gajim Team
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

138
gajim.nsi
View file

@ -224,18 +224,8 @@ Section "Gtk+ 2" SecGtk
SetOutPath "$INSTDIR\bin\gtk"
File /r "bin\gtk\bin"
File /r "bin\gtk\etc"
SetOutPath "$INSTDIR\bin\gtk\lib\gtk-2.0\2.10.0"
File /r "bin\gtk\lib\gtk-2.0\2.10.0\loaders"
SetOutPath "$INSTDIR\bin\gtk\lib\gtk-2.0\2.10.0\engines"
File "bin\gtk\lib\gtk-2.0\2.10.0\engines\libclearlooks.dll"
File "bin\gtk\lib\gtk-2.0\2.10.0\engines\libpixmap.dll"
File "bin\gtk\lib\gtk-2.0\2.10.0\engines\libsvg.dll"
SetOutPath "$INSTDIR\bin\gtk\lib\gtk-2.0\2.10.0"
SetOutPath "$INSTDIR\bin\gtk\lib"
File "bin\gtk\lib\charset.alias"
SetOutPath "$INSTDIR\bin\gtk\share"
File /r "bin\gtk\share\gtkthemeselector"
File /r "bin\gtk\share\xml"
File /r "bin\gtk\lib"
File /r "bin\gtk\share"
SectionEnd
Section "Plugins" SecPlugins
@ -527,128 +517,8 @@ SectionEnd
Section "Uninstall"
RMDir /r "$INSTDIR\bin\gtk\bin"
RMDir /r "$INSTDIR\bin\gtk\etc"
RMDir /r "$INSTDIR\bin\gtk\lib\gtk-2.0\2.10.0\loaders"
Delete "$INSTDIR\bin\gtk\lib\gtk-2.0\2.10.0\engines\libclearlooks.dll"
Delete "$INSTDIR\bin\gtk\lib\gtk-2.0\2.10.0\engines\libpixmap.dll"
Delete "$INSTDIR\bin\gtk\lib\gtk-2.0\2.10.0\engines\libsvg.dll"
Delete "$INSTDIR\bin\gtk\lib\gtk-2.0\2.10.0\engines\libwimp.dll"
RMDir "$INSTDIR\bin\gtk\lib\gtk-2.0\2.10.0\engines"
RMDir "$INSTDIR\bin\gtk\lib\gtk-2.0\2.10.0"
RMDir "$INSTDIR\bin\gtk\lib\gtk-2.0"
Delete "$INSTDIR\bin\gtk\lib\charset.alias"
RMDir "$INSTDIR\bin\gtk\lib"
RMDir /r "$INSTDIR\bin\gtk\share\locale\de"
RMDir /r "$INSTDIR\bin\gtk\share\locale\en_GB"
RMDir /r "$INSTDIR\bin\gtk\share\locale\es"
RMDir /r "$INSTDIR\bin\gtk\share\locale\fr"
RMDir /r "$INSTDIR\bin\gtk\share\locale\it"
RMDir /r "$INSTDIR\bin\gtk\share\locale\ru"
RMDir /r "$INSTDIR\bin\gtk\share\locale\af"
RMDir /r "$INSTDIR\bin\gtk\share\locale\am"
RMDir /r "$INSTDIR\bin\gtk\share\locale\ang"
RMDir /r "$INSTDIR\bin\gtk\share\locale\ar"
RMDir /r "$INSTDIR\bin\gtk\share\locale\as"
RMDir /r "$INSTDIR\bin\gtk\share\locale\az"
RMDir /r "$INSTDIR\bin\gtk\share\locale\az_IR"
RMDir /r "$INSTDIR\bin\gtk\share\locale\be"
RMDir /r "$INSTDIR\bin\gtk\share\locale\be@latin"
RMDir /r "$INSTDIR\bin\gtk\share\locale\bg"
RMDir /r "$INSTDIR\bin\gtk\share\locale\bn"
RMDir /r "$INSTDIR\bin\gtk\share\locale\bn_IN"
RMDir /r "$INSTDIR\bin\gtk\share\locale\br"
RMDir /r "$INSTDIR\bin\gtk\share\locale\bs"
RMDir /r "$INSTDIR\bin\gtk\share\locale\ca"
RMDir /r "$INSTDIR\bin\gtk\share\locale\ca@valencia"
RMDir /r "$INSTDIR\bin\gtk\share\locale\cs"
RMDir /r "$INSTDIR\bin\gtk\share\locale\cy"
RMDir /r "$INSTDIR\bin\gtk\share\locale\da"
RMDir /r "$INSTDIR\bin\gtk\share\locale\dz"
RMDir /r "$INSTDIR\bin\gtk\share\locale\el"
RMDir /r "$INSTDIR\bin\gtk\share\locale\en_CA"
RMDir /r "$INSTDIR\bin\gtk\share\locale\eo"
RMDir /r "$INSTDIR\bin\gtk\share\locale\et"
RMDir /r "$INSTDIR\bin\gtk\share\locale\eu"
RMDir /r "$INSTDIR\bin\gtk\share\locale\fa"
RMDir /r "$INSTDIR\bin\gtk\share\locale\fi"
RMDir /r "$INSTDIR\bin\gtk\share\locale\ga"
RMDir /r "$INSTDIR\bin\gtk\share\locale\gl"
RMDir /r "$INSTDIR\bin\gtk\share\locale\gu"
RMDir /r "$INSTDIR\bin\gtk\share\locale\he"
RMDir /r "$INSTDIR\bin\gtk\share\locale\hi"
RMDir /r "$INSTDIR\bin\gtk\share\locale\hr"
RMDir /r "$INSTDIR\bin\gtk\share\locale\hu"
RMDir /r "$INSTDIR\bin\gtk\share\locale\hy"
RMDir /r "$INSTDIR\bin\gtk\share\locale\ia"
RMDir /r "$INSTDIR\bin\gtk\share\locale\id"
RMDir /r "$INSTDIR\bin\gtk\share\locale\io"
RMDir /r "$INSTDIR\bin\gtk\share\locale\is"
RMDir /r "$INSTDIR\bin\gtk\share\locale\ja"
RMDir /r "$INSTDIR\bin\gtk\share\locale\ka"
RMDir /r "$INSTDIR\bin\gtk\share\locale\kn"
RMDir /r "$INSTDIR\bin\gtk\share\locale\ko"
RMDir /r "$INSTDIR\bin\gtk\share\locale\ku"
RMDir /r "$INSTDIR\bin\gtk\share\locale\li"
RMDir /r "$INSTDIR\bin\gtk\share\locale\lt"
RMDir /r "$INSTDIR\bin\gtk\share\locale\lv"
RMDir /r "$INSTDIR\bin\gtk\share\locale\mai"
RMDir /r "$INSTDIR\bin\gtk\share\locale\mg"
RMDir /r "$INSTDIR\bin\gtk\share\locale\mi"
RMDir /r "$INSTDIR\bin\gtk\share\locale\mk"
RMDir /r "$INSTDIR\bin\gtk\share\locale\ml"
RMDir /r "$INSTDIR\bin\gtk\share\locale\mn"
RMDir /r "$INSTDIR\bin\gtk\share\locale\mr"
RMDir /r "$INSTDIR\bin\gtk\share\locale\ms"
RMDir /r "$INSTDIR\bin\gtk\share\locale\nb"
RMDir /r "$INSTDIR\bin\gtk\share\locale\ne"
RMDir /r "$INSTDIR\bin\gtk\share\locale\nl"
RMDir /r "$INSTDIR\bin\gtk\share\locale\nn"
RMDir /r "$INSTDIR\bin\gtk\share\locale\nso"
RMDir /r "$INSTDIR\bin\gtk\share\locale\oc"
RMDir /r "$INSTDIR\bin\gtk\share\locale\or"
RMDir /r "$INSTDIR\bin\gtk\share\locale\pa"
RMDir /r "$INSTDIR\bin\gtk\share\locale\pl"
RMDir /r "$INSTDIR\bin\gtk\share\locale\ps"
RMDir /r "$INSTDIR\bin\gtk\share\locale\pt"
RMDir /r "$INSTDIR\bin\gtk\share\locale\pt_BR"
RMDir /r "$INSTDIR\bin\gtk\share\locale\ro"
RMDir /r "$INSTDIR\bin\gtk\share\locale\rw"
RMDir /r "$INSTDIR\bin\gtk\share\locale\si"
RMDir /r "$INSTDIR\bin\gtk\share\locale\sk"
RMDir /r "$INSTDIR\bin\gtk\share\locale\sl"
RMDir /r "$INSTDIR\bin\gtk\share\locale\sq"
RMDir /r "$INSTDIR\bin\gtk\share\locale\sr"
RMDir /r "$INSTDIR\bin\gtk\share\locale\sr@ije"
RMDir /r "$INSTDIR\bin\gtk\share\locale\sr@latin"
RMDir /r "$INSTDIR\bin\gtk\share\locale\sv"
RMDir /r "$INSTDIR\bin\gtk\share\locale\ta"
RMDir /r "$INSTDIR\bin\gtk\share\locale\te"
RMDir /r "$INSTDIR\bin\gtk\share\locale\th"
RMDir /r "$INSTDIR\bin\gtk\share\locale\tk"
RMDir /r "$INSTDIR\bin\gtk\share\locale\tl"
RMDir /r "$INSTDIR\bin\gtk\share\locale\tr"
RMDir /r "$INSTDIR\bin\gtk\share\locale\tt"
RMDir /r "$INSTDIR\bin\gtk\share\locale\ug"
RMDir /r "$INSTDIR\bin\gtk\share\locale\uk"
RMDir /r "$INSTDIR\bin\gtk\share\locale\ur"
RMDir /r "$INSTDIR\bin\gtk\share\locale\uz"
RMDir /r "$INSTDIR\bin\gtk\share\locale\uz@cyrillic"
RMDir /r "$INSTDIR\bin\gtk\share\locale\vi"
RMDir /r "$INSTDIR\bin\gtk\share\locale\wa"
RMDir /r "$INSTDIR\bin\gtk\share\locale\xh"
RMDir /r "$INSTDIR\bin\gtk\share\locale\yi"
RMDir /r "$INSTDIR\bin\gtk\share\locale\zh_CN"
RMDir /r "$INSTDIR\bin\gtk\share\locale\zh_HK"
RMDir /r "$INSTDIR\bin\gtk\share\locale\zh_TW"
RMDir "$INSTDIR\bin\gtk\share\locale"
RMDir /r "$INSTDIR\bin\gtk\share\themes\Clearlooks"
RMDir /r "$INSTDIR\bin\gtk\share\themes\Default"
RMDir /r "$INSTDIR\bin\gtk\share\themes\Glossy"
RMDir /r "$INSTDIR\bin\gtk\share\themes\Glossy-js"
RMDir /r "$INSTDIR\bin\gtk\share\themes\MS-Windows"
RMDir "$INSTDIR\bin\gtk\share\themes"
RMDir /r "$INSTDIR\bin\gtk\share\gtkthemeselector"
RMDir /r "$INSTDIR\bin\gtk\share\xml"
RMDir "$INSTDIR\bin\gtk\share"
RMDir /r "$INSTDIR\bin\gtk\lib"
RMDir /r "$INSTDIR\bin\gtk\share"
RMDir "$INSTDIR\bin\gtk"
Delete "$INSTDIR\bin\_bsddb.pyd"
Delete "$INSTDIR\bin\_ctypes.pyd"

View file

@ -501,7 +501,7 @@ if dbus_support.supported:
for node in path:
key += node + '#'
key += name
prefs_dict[DBUS_STRING(key)] = DBUS_STRING(value[1])
prefs_dict[DBUS_STRING(key)] = DBUS_STRING(value)
gajim.config.foreach(get_prefs)
return prefs_dict

View file

@ -1,772 +0,0 @@
"""
A python version of the main functions to use Snarl
(http://www.fullphat.net/snarl)
Version 1.0
This module can be used in two ways. One is the normal way
the other snarl interfaces work. This means you can call snShowMessage
and get an ID back for manipulations.
The other way is there is a class this module exposes called SnarlMessage.
This allows you to keep track of the message as a python object. If you
use the send without specifying False as the argument it will set the ID
to what the return of the last SendMessage was. This is of course only
useful for the SHOW message.
Requires one of:
pywin32 extensions from http://pywin32.sourceforge.net
ctypes (included in Python 2.5, downloadable for earlier versions)
Creator: Sam Listopad II (samlii@users.sourceforge.net)
Copyright 2006-2008 Samuel Listopad II
Licensed under the Apache License, Version 2.0 (the "License"); you may not
use this file except in compliance with the License. You may obtain a copy
of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required
by applicable law or agreed to in writing, software distributed under the
License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
OF ANY KIND, either express or implied. See the License for the specific
language governing permissions and limitations under the License.
"""
import array, struct
def LOWORD(dword):
"""Return the low WORD of the passed in integer"""
return dword & 0x0000ffff
#get the hi word
def HIWORD(dword):
"""Return the high WORD of the passed in integer"""
return dword >> 16
class Win32FuncException(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)
class Win32Funcs:
"""Just a little class to hide the details of finding and using the
correct win32 functions. The functions may throw a UnicodeEncodeError if
there is not a unicode version and it is sent a unicode string that cannot
be converted to ASCII."""
WM_USER = 0x400
WM_COPYDATA = 0x4a
#Type of String the functions are expecting.
#Used like function(myWin32Funcs.strType(param)).
__strType = str
#FindWindow function to use
__FindWindow = None
#FindWindow function to use
__FindWindowEx = None
#SendMessage function to use
__SendMessage = None
#SendMessageTimeout function to use
__SendMessageTimeout = None
#IsWindow function to use
__IsWindow = None
#RegisterWindowMessage to use
__RegisterWindowMessage = None
#GetWindowText to use
__GetWindowText = None
def FindWindow(self, lpClassName, lpWindowName):
"""Wraps the windows API call of FindWindow"""
if lpClassName is not None:
lpClassName = self.__strType(lpClassName)
if lpWindowName is not None:
lpWindowName = self.__strType(lpWindowName)
return self.__FindWindow(lpClassName, lpWindowName)
def FindWindowEx(self, hwndParent, hwndChildAfter, lpClassName, lpWindowName):
"""Wraps the windows API call of FindWindow"""
if lpClassName is not None:
lpClassName = self.__strType(lpClassName)
if lpWindowName is not None:
lpWindowName = self.__strType(lpWindowName)
return self.__FindWindowEx(hwndParent, hwndChildAfter, lpClassName, lpWindowName)
def SendMessage(self, hWnd, Msg, wParam, lParam):
"""Wraps the windows API call of SendMessage"""
return self.__SendMessage(hWnd, Msg, wParam, lParam)
def SendMessageTimeout(self, hWnd, Msg,
wParam, lParam, fuFlags,
uTimeout, lpdwResult = None):
"""Wraps the windows API call of SendMessageTimeout"""
idToRet = None
try:
idFromMsg = array.array('I', [0])
result = idFromMsg.buffer_info()[0]
response = self.__SendMessageTimeout(hWnd, Msg, wParam,
lParam, fuFlags,
uTimeout, result)
if response == 0:
raise Win32FuncException, "SendMessageTimeout TimedOut"
idToRet = idFromMsg[0]
except TypeError:
idToRet = self.__SendMessageTimeout(hWnd, Msg, wParam,
lParam, fuFlags,
uTimeout)
if lpdwResult is not None and lpdwResult.typecode == 'I':
lpdwResult[0] = idToRet
return idToRet
def IsWindow(self, hWnd):
"""Wraps the windows API call of IsWindow"""
return self.__IsWindow(hWnd)
def RegisterWindowMessage(self, lpString):
"""Wraps the windows API call of RegisterWindowMessage"""
return self.__RegisterWindowMessage(self.__strType(lpString))
def GetWindowText(self, hWnd, lpString = None, nMaxCount = None):
"""Wraps the windows API call of SendMessageTimeout"""
text = ''
if hWnd == 0:
return text
if nMaxCount is None:
nMaxCount = 1025
try:
arrayType = 'c'
if self.__strType == unicode:
arrayType = 'u'
path_string = array.array(arrayType, self.__strType('\x00') * nMaxCount)
path_buffer = path_string.buffer_info()[0]
result = self.__GetWindowText(hWnd,
path_buffer,
nMaxCount)
if result > 0:
if self.__strType == unicode:
text = path_string[0:result].tounicode()
else:
text = path_string[0:result].tostring()
except TypeError:
text = self.__GetWindowText(hWnd)
if lpString is not None and lpString.typecode == 'c':
lpdwResult[0:len(text)] = array.array('c', str(text));
if lpString is not None and lpString.typecode == 'u':
lpdwResult[0:len(text)] = array.array('u', unicode(text));
return text
def __init__(self):
"""Load up my needed functions"""
# First see if they already have win32gui imported. If so use it.
# This has to be checked first since the auto check looks for ctypes
# first.
try:
self.__FindWindow = win32gui.FindWindow
self.__FindWindowEx = win32gui.FindWindowEx
self.__GetWindowText = win32gui.GetWindowText
self.__IsWindow = win32gui.IsWindow
self.__SendMessage = win32gui.SendMessage
self.__SendMessageTimeout = win32gui.SendMessageTimeout
self.__RegisterWindowMessage = win32gui.RegisterWindowMessage
self.__strType = unicode
#Something threw a NameError, most likely the win32gui lines
#so do auto check
except NameError:
try:
from ctypes import windll
self.__FindWindow = windll.user32.FindWindowW
self.__FindWindowEx = windll.user32.FindWindowExW
self.__GetWindowText = windll.user32.GetWindowTextW
self.__IsWindow = windll.user32.IsWindow
self.__SendMessage = windll.user32.SendMessageW
self.__SendMessageTimeout = windll.user32.SendMessageTimeoutW
self.__RegisterWindowMessage = windll.user32.RegisterWindowMessageW
self.__strType = unicode
#FindWindowW wasn't found, look for FindWindowA
except AttributeError:
try:
self.__FindWindow = windll.user32.FindWindowA
self.__FindWindowEx = windll.user32.FindWindowExA
self.__GetWindowText = windll.user32.GetWindowTextA
self.__IsWindow = windll.user32.IsWindow
self.__SendMessage = windll.user32.SendMessageA
self.__SendMessageTimeout = windll.user32.SendMessageTimeoutA
self.__RegisterWindowMessage = windll.user32.RegisterWindowMessageA
# Couldn't find either so Die and tell user why.
except AttributeError:
import sys
sys.stderr.write("Your Windows TM setup seems to be corrupt."+
" No FindWindow found in user32.\n")
sys.stderr.flush()
sys.exit(3)
except ImportError:
try:
import win32gui
self.__FindWindow = win32gui.FindWindow
self.__FindWindowEx = win32gui.FindWindowEx
self.__GetWindowText = win32gui.GetWindowText
self.__IsWindow = win32gui.IsWindow
self.__SendMessage = win32gui.SendMessage
self.__SendMessageTimeout = win32gui.SendMessageTimeout
self.__RegisterWindowMessage = win32gui.RegisterWindowMessage
self.__strType = unicode
except ImportError:
import sys
sys.stderr.write("You need to have either"+
" ctypes or pywin32 installed.\n")
sys.stderr.flush()
#sys.exit(2)
myWin32Funcs = Win32Funcs()
SHOW = 1
HIDE = 2
UPDATE = 3
IS_VISIBLE = 4
GET_VERSION = 5
REGISTER_CONFIG_WINDOW = 6
REVOKE_CONFIG_WINDOW = 7
REGISTER_ALERT = 8
REVOKE_ALERT = 9
REGISTER_CONFIG_WINDOW_2 = 10
GET_VERSION_EX = 11
SET_TIMEOUT = 12
EX_SHOW = 32
GLOBAL_MESSAGE = "SnarlGlobalMessage"
GLOBAL_MSG = "SnarlGlobalEvent"
#Messages That may be received from Snarl
SNARL_LAUNCHED = 1
SNARL_QUIT = 2
SNARL_ASK_APPLET_VER = 3
SNARL_SHOW_APP_UI = 4
SNARL_NOTIFICATION_CLICKED = 32 #notification was right-clicked by user
SNARL_NOTIFICATION_CANCELLED = SNARL_NOTIFICATION_CLICKED #Name clarified
SNARL_NOTIFICATION_TIMED_OUT = 33
SNARL_NOTIFICATION_ACK = 34 #notification was left-clicked by user
#Snarl Test Message
WM_SNARLTEST = myWin32Funcs.WM_USER + 237
M_ABORTED = 0x80000007L
M_ACCESS_DENIED = 0x80000009L
M_ALREADY_EXISTS = 0x8000000CL
M_BAD_HANDLE = 0x80000006L
M_BAD_POINTER = 0x80000005L
M_FAILED = 0x80000008L
M_INVALID_ARGS = 0x80000003L
M_NO_INTERFACE = 0x80000004L
M_NOT_FOUND = 0x8000000BL
M_NOT_IMPLEMENTED = 0x80000001L
M_OK = 0x00000000L
M_OUT_OF_MEMORY = 0x80000002L
M_TIMED_OUT = 0x8000000AL
ErrorCodeRev = {
0x80000007L : "M_ABORTED",
0x80000009L : "M_ACCESS_DENIED",
0x8000000CL : "M_ALREADY_EXISTS",
0x80000006L : "M_BAD_HANDLE",
0x80000005L : "M_BAD_POINTER",
0x80000008L : "M_FAILED",
0x80000003L : "M_INVALID_ARGS",
0x80000004L : "M_NO_INTERFACE",
0x8000000BL : "M_NOT_FOUND",
0x80000001L : "M_NOT_IMPLEMENTED",
0x00000000L : "M_OK",
0x80000002L : "M_OUT_OF_MEMORY",
0x8000000AL : "M_TIMED_OUT"
}
class SnarlMessage(object):
"""The main Snarl interface object.
ID = Snarl Message ID for most operations. See SDK for more info
as to other values to put here.
type = Snarl Message Type. Valid values are : SHOW, HIDE, UPDATE,
IS_VISIBLE, GET_VERSION, REGISTER_CONFIG_WINDOW, REVOKE_CONFIG_WINDOW
all which are constants in the PySnarl module.
timeout = Timeout in seconds for the Snarl Message
data = Snarl Message data. This is dependant upon message type. See SDK
title = Snarl Message title.
text = Snarl Message text.
icon = Path to the icon to display in the Snarl Message.
"""
__msgType = 0
__msgID = 0
__msgTimeout = 0
__msgData = 0
__msgTitle = ""
__msgText = ""
__msgIcon = ""
__msgClass = ""
__msgExtra = ""
__msgExtra2 = ""
__msgRsvd1 = 0
__msgRsvd2 = 0
__msgHWnd = 0
lastKnownHWnd = 0
def getType(self):
"""Type Attribute getter."""
return self.__msgType
def setType(self, value):
"""Type Attribute setter."""
if( isinstance(value, (int, long)) ):
self.__msgType = value
type = property(getType, setType, doc="The Snarl Message Type")
def getID(self):
"""ID Attribute getter."""
return self.__msgID
def setID(self, value):
"""ID Attribute setter."""
if( isinstance(value, (int, long)) ):
self.__msgID = value
ID = property(getID, setID, doc="The Snarl Message ID")
def getTimeout(self):
"""Timeout Attribute getter."""
return self.__msgTimeout
def updateTimeout(self, value):
"""Timeout Attribute setter."""
if( isinstance(value, (int, long)) ):
self.__msgTimeout = value
timeout = property(getTimeout, updateTimeout,
doc="The Snarl Message Timeout")
def getData(self):
"""Data Attribute getter."""
return self.__msgData
def setData(self, value):
"""Data Attribute setter."""
if( isinstance(value, (int, long)) ):
self.__msgData = value
data = property(getData, setData, doc="The Snarl Message Data")
def getTitle(self):
"""Title Attribute getter."""
return self.__msgTitle
def setTitle(self, value):
"""Title Attribute setter."""
if( isinstance(value, basestring) ):
self.__msgTitle = value
title = property(getTitle, setTitle, doc="The Snarl Message Title")
def getText(self):
"""Text Attribute getter."""
return self.__msgText
def setText(self, value):
"""Text Attribute setter."""
if( isinstance(value, basestring) ):
self.__msgText = value
text = property(getText, setText, doc="The Snarl Message Text")
def getIcon(self):
"""Icon Attribute getter."""
return self.__msgIcon
def setIcon(self, value):
"""Icon Attribute setter."""
if( isinstance(value, basestring) ):
self.__msgIcon = value
icon = property(getIcon, setIcon, doc="The Snarl Message Icon")
def getClass(self):
"""Class Attribute getter."""
return self.__msgClass
def setClass(self, value):
"""Class Attribute setter."""
if( isinstance(value, basestring) ):
self.__msgClass = value
msgclass = property(getClass, setClass, doc="The Snarl Message Class")
def getExtra(self):
"""Extra Attribute getter."""
return self.__msgExtra
def setExtra(self, value):
"""Extra Attribute setter."""
if( isinstance(value, basestring) ):
self.__msgExtra = value
extra = property(getExtra, setExtra, doc="Extra Info for the Snarl Message")
def getExtra2(self):
"""Extra2 Attribute getter."""
return self.__msgExtra2
def setExtra2(self, value):
"""Extra2 Attribute setter."""
if( isinstance(value, basestring) ):
self.__msgExtra2 = value
extra2 = property(getExtra2, setExtra2,
doc="More Extra Info for the Snarl Message")
def getRsvd1(self):
"""Rsvd1 Attribute getter."""
return self.__msgRsvd1
def setRsvd1(self, value):
"""Rsvd1 Attribute setter."""
if( isinstance(value, (int, long)) ):
self.__msgRsvd1 = value
rsvd1 = property(getRsvd1, setRsvd1, doc="The Snarl Message Field Rsvd1")
def getRsvd2(self):
"""Rsvd2 Attribute getter."""
return self.__msgRsvd2
def setRsvd2(self, value):
"""Rsvd2 Attribute setter."""
if( isinstance(value, (int, long)) ):
self.__msgRsvd2 = value
rsvd2 = property(getRsvd2, setRsvd2, doc="The Snarl Message Field Rsvd2")
def getHwnd(self):
"""hWnd Attribute getter."""
return self.__msgHWnd
def setHwnd(self, value):
"""hWnd Attribute setter."""
if( isinstance(value, (int, long)) ):
self.__msgHWnd = value
hWnd = property(getHwnd, setHwnd, doc="The hWnd of the window this message is being sent from")
def __init__(self, title="", text="", icon="", msg_type=1, msg_id=0):
self.__msgTimeout = 0
self.__msgData = 0
self.__msgClass = ""
self.__msgExtra = ""
self.__msgExtra2 = ""
self.__msgRsvd1 = 0
self.__msgRsvd2 = 0
self.__msgType = msg_type
self.__msgText = text
self.__msgTitle = title
self.__msgIcon = icon
self.__msgID = msg_id
def createCopyStruct(self):
"""Creates the struct to send as the copyData in the message."""
return struct.pack("ILLL1024s1024s1024s1024s1024s1024sLL",
self.__msgType,
self.__msgID,
self.__msgTimeout,
self.__msgData,
self.__msgTitle.encode('utf-8'),
self.__msgText.encode('utf-8'),
self.__msgIcon.encode('utf-8'),
self.__msgClass.encode('utf-8'),
self.__msgExtra.encode('utf-8'),
self.__msgExtra2.encode('utf-8'),
self.__msgRsvd1,
self.__msgRsvd2
)
__lpData = None
__cds = None
def packData(self, dwData):
"""This packs the data in the necessary format for a
WM_COPYDATA message."""
self.__lpData = None
self.__cds = None
item = self.createCopyStruct()
self.__lpData = array.array('c', item)
lpData_ad = self.__lpData.buffer_info()[0]
cbData = self.__lpData.buffer_info()[1]
self.__cds = array.array('c',
struct.pack("IIP",
dwData,
cbData,
lpData_ad)
)
cds_ad = self.__cds.buffer_info()[0]
return cds_ad
def reset(self):
"""Reset this SnarlMessage to the default state."""
self.__msgType = 0
self.__msgID = 0
self.__msgTimeout = 0
self.__msgData = 0
self.__msgTitle = ""
self.__msgText = ""
self.__msgIcon = ""
self.__msgClass = ""
self.__msgExtra = ""
self.__msgExtra2 = ""
self.__msgRsvd1 = 0
self.__msgRsvd2 = 0
def send(self, setid=True):
"""Send this SnarlMessage to the Snarl window.
Args:
setid - Boolean defining whether or not to set the ID
of this SnarlMessage to the return value of
the SendMessage call. Default is True to
make simple case of SHOW easy.
"""
hwnd = myWin32Funcs.FindWindow(None, "Snarl")
if myWin32Funcs.IsWindow(hwnd):
if self.type == REGISTER_CONFIG_WINDOW or self.type == REGISTER_CONFIG_WINDOW_2:
self.hWnd = self.data
try:
response = myWin32Funcs.SendMessageTimeout(hwnd,
myWin32Funcs.WM_COPYDATA,
self.hWnd, self.packData(2),
2, 500)
except Win32FuncException:
return False
idFromMsg = response
if setid:
self.ID = idFromMsg
return True
else:
return idFromMsg
print "No snarl window found"
return False
def hide(self):
"""Hide this message. Type will revert to type before calling hide
to allow for better reuse of object."""
oldType = self.__msgType
self.__msgType = HIDE
retVal = bool(self.send(False))
self.__msgType = oldType
return retVal
def isVisible(self):
"""Is this message visible. Type will revert to type before calling
hide to allow for better reuse of object."""
oldType = self.__msgType
self.__msgType = IS_VISIBLE
retVal = bool(self.send(False))
self.__msgType = oldType
return retVal
def update(self, title=None, text=None, icon=None):
"""Update this message with given title and text. Type will revert
to type before calling hide to allow for better reuse of object."""
oldType = self.__msgType
self.__msgType = UPDATE
if text:
self.__msgText = text
if title:
self.__msgTitle = title
if icon:
self.__msgIcon = icon
retVal = self.send(False)
self.__msgType = oldType
return retVal
def setTimeout(self, timeout):
"""Set the timeout in seconds of the message"""
oldType = self.__msgType
oldData = self.__msgData
self.__msgType = SET_TIMEOUT
#self.timeout = timeout
#self.__msgData = self.__msgTimeout
self.__msgData = timeout
retVal = self.send(False)
self.__msgType = oldType
self.__msgData = oldData
return retVal
def show(self, timeout=None, title=None,
text=None, icon=None,
replyWindow=None, replyMsg=None, msgclass=None, soundPath=None):
"""Show a message"""
oldType = self.__msgType
oldTimeout = self.__msgTimeout
self.__msgType = SHOW
if text:
self.__msgText = text
if title:
self.__msgTitle = title
if timeout:
self.__msgTimeout = timeout
if icon:
self.__msgIcon = icon
if replyWindow:
self.__msgID = replyMsg
if replyMsg:
self.__msgData = replyWindow
if soundPath:
self.__msgExtra = soundPath
if msgclass:
self.__msgClass = msgclass
if ((self.__msgClass and self.__msgClass != "") or
(self.__msgExtra and self.__msgExtra != "")):
self.__msgType = EX_SHOW
retVal = bool(self.send())
self.__msgType = oldType
self.__msgTimeout = oldTimeout
return retVal
def snGetVersion():
""" Get the version of Snarl that is running as a tuple. (Major, Minor)
If Snarl is not running or there was an error it will
return False."""
msg = SnarlMessage(msg_type=GET_VERSION)
version = msg.send(False)
if not version:
return False
return (HIWORD(version), LOWORD(version))
def snGetVersionEx():
""" Get the internal version of Snarl that is running.
If Snarl is not running or there was an error it will
return False."""
sm = SnarlMessage(msg_type=GET_VERSION_EX)
verNum = sm.send(False)
if not verNum:
return False
return verNum
def snGetGlobalMessage():
"""Get the Snarl global message id from windows."""
return myWin32Funcs.RegisterWindowMessage(GLOBAL_MSG)
def snShowMessage(title, text, timeout=0, iconPath="",
replyWindow=0, replyMsg=0):
"""Show a message using Snarl and return its ID. See SDK for arguments."""
sm = SnarlMessage( title, text, iconPath, msg_id=replyMsg)
sm.data = replyWindow
if sm.show(timeout):
return sm.ID
else:
return False
def snShowMessageEx(msgClass, title, text, timeout=0, iconPath="",
replyWindow=0, replyMsg=0, soundFile=None, hWndFrom=None):
"""Show a message using Snarl and return its ID. See SDK for arguments.
One added argument is hWndFrom that allows one to make the messages appear
to come from a specific window. This window should be the one you registered
earlier with RegisterConfig"""
sm = SnarlMessage( title, text, iconPath, msg_id=replyMsg)
sm.data = replyWindow
if hWndFrom is not None:
sm.hWnd = hWndFrom
else:
sm.hWnd = SnarlMessage.lastKnownHWnd
if sm.show(timeout, msgclass=msgClass, soundPath=soundFile):
return sm.ID
else:
return False
def snUpdateMessage(msgId, msgTitle, msgText, icon=None):
"""Update a message"""
sm = SnarlMessage(msg_id=msgId)
if icon:
sm.icon = icon
return sm.update(msgTitle, msgText)
def snHideMessage(msgId):
"""Hide a message"""
return SnarlMessage(msg_id=msgId).hide()
def snSetTimeout(msgId, timeout):
"""Update the timeout of a message already shown."""
sm = SnarlMessage(msg_id=msgId)
return sm.setTimeout(timeout)
def snIsMessageVisible(msgId):
"""Returns True if the message is visible False otherwise."""
return SnarlMessage(msg_id=msgId).isVisible()
def snRegisterConfig(replyWnd, appName, replyMsg):
"""Register a config window. See SDK for more info."""
global lastRegisteredSnarlMsg
sm = SnarlMessage(msg_type=REGISTER_CONFIG_WINDOW,
title=appName,
msg_id=replyMsg)
sm.data = replyWnd
SnarlMessage.lastKnownHWnd = replyWnd
return sm.send(False)
def snRegisterConfig2(replyWnd, appName, replyMsg, icon):
"""Register a config window. See SDK for more info."""
global lastRegisteredSnarlMsg
sm = SnarlMessage(msg_type=REGISTER_CONFIG_WINDOW_2,
title=appName,
msg_id=replyMsg,
icon=icon)
sm.data = replyWnd
SnarlMessage.lastKnownHWnd = replyWnd
return sm.send(False)
def snRegisterAlert(appName, classStr) :
"""Register an alert for an already registered config. See SDK for more info."""
sm = SnarlMessage(msg_type=REGISTER_ALERT,
title=appName,
text=classStr)
return sm.send(False)
def snRevokeConfig(replyWnd):
"""Revoke a config window"""
sm = SnarlMessage(msg_type=REVOKE_CONFIG_WINDOW)
sm.data = replyWnd
if replyWnd == SnarlMessage.lastKnownHWnd:
SnarlMessage.lastKnownHWnd = 0
return sm.send(False)
def snGetSnarlWindow():
"""Returns the hWnd of the snarl window"""
return myWin32Funcs.FindWindow(None, "Snarl")
def snGetAppPath():
"""Returns the application path of the currently running snarl window"""
app_path = None
snarl_handle = snGetSnarlWindow()
if snarl_handle != 0:
pathwin_handle = myWin32Funcs.FindWindowEx(snarl_handle,
0,
"static",
None)
if pathwin_handle != 0:
try:
result = myWin32Funcs.GetWindowText(pathwin_handle)
app_path = result
except Win32FuncException:
pass
return app_path
def snGetIconsPath():
"""Returns the path to the icons of the program"""
s = snGetAppPath()
if s is None:
return ""
else:
return s + "etc\\icons\\"
def snSendTestMessage(data=None):
"""Sends a test message to Snarl. Used to make sure the
api is connecting"""
param = 0
command = 0
if data:
param = struct.pack("I", data)
command = 1
myWin32Funcs.SendMessage(snGetSnarlWindow(), WM_SNARLTEST, command, param)

View file

@ -1 +0,0 @@
from plugin import SnarlNotificationsPlugin

View file

@ -1,11 +0,0 @@
[info]
name: Snarl Notifications
short_name: snarl_notifications
version: 0.1
description: Shows events notification using Snarl (http://www.fullphat.net/) under Windows. Snarl needs to be installed in system.
PySnarl bindings are used (http://code.google.com/p/pysnarl/).
authors = Mateusz Biliński <mateusz@bilinski.it>
homepage = http://blog.bilinski.it

View file

@ -1,71 +0,0 @@
# -*- coding: utf-8 -*-
##
## This file is part of Gajim.
##
## Gajim is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published
## by the Free Software Foundation; version 3 only.
##
## Gajim is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
##
'''
Events notifications using Snarl
Fancy events notifications under Windows using Snarl infrastructure.
:note: plugin is at proof-of-concept state.
:author: Mateusz Biliński <mateusz@bilinski.it>
:since: 15th August 2008
:copyright: Copyright (2008) Mateusz Biliński <mateusz@bilinski.it>
:license: GPL
'''
import new
from pprint import pformat
#import PySnarl
from common import gajim
from plugins import GajimPlugin
from plugins.helpers import log_calls, log
from common import ged
class SnarlNotificationsPlugin(GajimPlugin):
@log_calls('SnarlNotificationsPlugin')
def init(self):
self.description = _('Shows events notification using Snarl '
'(http://www.fullphat.net/) under Windows. '
'Snarl needs to be installed in system.\n'
'PySnarl bindings are used (http://code.google.com/p/pysnarl/).')
self.config_dialog = None
#self.gui_extension_points = {}
#self.config_default_values = {}
self.events_handlers = {'notification' : (ged.POSTCORE, self.notif)}
@log_calls('SnarlNotificationsPlugin')
def activate(self):
pass
@log_calls('SnarlNotificationsPlugin')
def deactivate(self):
pass
@log_calls('SnarlNotificationsPlugin')
def notif(self, obj):
print "Event '%s' occured.\n\n===\n" % obj.popup_event_type
#if PySnarl.snGetVersion() != False:
#(major, minor) = PySnarl.snGetVersion()
#print "Found Snarl version",str(major)+"."+str(minor),"running."
#PySnarl.snShowMessage(obj.popup_title, obj.popup_text)
#else:
#print "Sorry Snarl does not appear to be running"

View file

@ -1,3 +0,0 @@
data/gajim.desktop.in
src/eggtrayicon.c
src/ipython_view.py

3525
po/fr.po

File diff suppressed because it is too large Load diff

3526
po/ja.po

File diff suppressed because it is too large Load diff

2262
po/ru.po

File diff suppressed because it is too large Load diff

2578
po/uk.po

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
## setup_win32.py (run me as python setup_win32.py py2exe -O2)
##
## Copyright (C) 2003-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2003-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2005-2006 Nikos Kouremenos <kourem AT gmail.com>
## Copyright (C) 2008 Jonathan Schleifer <js-gajim AT webkeks.org>
##

View file

@ -3,7 +3,7 @@
##
## Copyright (C) 2006 Nikos Kouremenos <kourem AT gmail.com>
## Copyright (C) 2006-2007 Tomasz Melcer <liori AT exroot.org>
## Copyright (C) 2006-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2006-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2008 Jonathan Schleifer <js-gajim AT webkeks.org>
## Stephan Erb <steve-e AT h3c.de>
##
@ -99,7 +99,7 @@ class CommandWindow:
self.stage1()
# displaying the window
self.window.set_title('Ad-hoc Commands - Gajim')
self.window.set_title(_('Ad-hoc Commands - Gajim'))
self.xml.connect_signals(self)
self.window.show_all()
@ -415,7 +415,7 @@ class CommandWindow:
return
self.data_form_widget.show()
if self.data_form_widget.title:
self.window.set_title('%s - Ad-hoc Commands - Gajim' % \
self.window.set_title(_('%s - Ad-hoc Commands - Gajim') % \
self.data_form_widget.title)
else:
self.data_form_widget.hide()

View file

@ -3,7 +3,7 @@
##
## Copyright (C) 2005 Travis Shirk <travis AT pobox.com>
## Vincent Hanquez <tab AT snarc.org>
## Copyright (C) 2005-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2005-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2005-2007 Nikos Kouremenos <kourem AT gmail.com>
## Copyright (C) 2006 Dimitur Kirov <dkirov AT gmail.com>
## Copyright (C) 2006-2007 Jean-Marie Traissard <jim AT lapin.org>
@ -81,6 +81,7 @@ class AdvancedConfigurationWindow(object):
self.entry = self.xml.get_object('advanced_entry')
self.desc_label = self.xml.get_object('advanced_desc_label')
self.restart_label = self.xml.get_object('restart_label')
self.reset_button = self.xml.get_object('reset_button')
# Format:
# key = option name (root/subopt/opt separated by \n then)
@ -174,6 +175,13 @@ class AdvancedConfigurationWindow(object):
else:
#we talk about option description in advanced configuration editor
self.desc_label.set_text(_('(None)'))
if len(opt_path) == 3 or (len(opt_path) == 1 and not \
model.iter_has_child(iter_)):
self.reset_button.set_sensitive(True)
else:
self.reset_button.set_sensitive(False)
else:
self.reset_button.set_sensitive(False)
def remember_option(self, option, oldval, newval):
if option in self.changed_opts:
@ -195,7 +203,6 @@ class AdvancedConfigurationWindow(object):
optname = optnamerow[0].decode('utf-8')
keyrow = self.model[modelpath[:2]]
key = keyrow[0].decode('utf-8')
gajim.config.get_desc_per(optname, key, option)
self.remember_option(option + '\n' + key + '\n' + optname,
modelrow[1], newval)
gajim.config.set_per(optname, key, option, newval)
@ -244,6 +251,42 @@ class AdvancedConfigurationWindow(object):
def on_advanced_configuration_window_destroy(self, widget):
del gajim.interface.instances['advanced_config']
def on_reset_button_clicked(self, widget):
model, iter_ = self.treeview.get_selection().get_selected()
# Check for GtkTreeIter
if iter_:
path = model.get_path(iter_)
opt_path = self.get_option_path(model, iter_)
if len(opt_path) == 1:
default = gajim.config.get_default(opt_path[0])
elif len(opt_path) == 3:
default = gajim.config.get_default_per(opt_path[2], opt_path[0])
if model[iter_][C_TYPE] == self.types['boolean']:
if self.right_true_dict[default] == model[iter_][C_VALUE]:
return
modelpath = self.modelfilter.convert_path_to_child_path(path)
modelrow = self.model[modelpath]
option = modelrow[0].decode('utf-8')
if len(modelpath) > 1:
optnamerow = self.model[modelpath[0]]
optname = optnamerow[0].decode('utf-8')
keyrow = self.model[modelpath[:2]]
key = keyrow[0].decode('utf-8')
self.remember_option(option + '\n' + key + '\n' + optname,
modelrow[C_VALUE], default)
gajim.config.set_per(optname, key, option, default)
else:
self.remember_option(option, modelrow[C_VALUE], default)
gajim.config.set(option, default)
gajim.interface.save_config()
modelrow[C_VALUE] = self.right_true_dict[default]
self.check_for_restart()
else:
if str(default) == model[iter_][C_VALUE]:
return
self.on_config_edited(None, path, str(default))
def on_advanced_close_button_clicked(self, widget):
self.window.destroy()
@ -254,14 +297,18 @@ class AdvancedConfigurationWindow(object):
newparent = self.model.append(parent, [name, '', ''])
self.fill_model(item, newparent)
else: # Leaf
type_ = self.types[option[OPT_TYPE][0]]
if len(item) == 1:
type_ = self.types[gajim.config.get_type(name)]
elif len(item) == 3:
type_ = self.types[gajim.config.get_type_per(item[0],
item[2])]
if name == 'password':
value = _('Hidden')
else:
if type_ == self.types['boolean']:
value = self.right_true_dict[option[OPT_VAL]]
value = self.right_true_dict[option]
else:
value = option[OPT_VAL]
value = option
self.model.append(parent, [name, value, type_])
def visible_func(self, model, treeiter):

View file

@ -2,7 +2,7 @@
## src/atom_window.py
##
## Copyright (C) 2006 Tomasz Melcer <liori AT exroot.org>
## Copyright (C) 2006-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2006-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2007 Nikos Kouremenos <kourem AT gmail.com>
## Copyright (C) 2008 Jonathan Schleifer <js-gajim AT webkeks.org>
##

View file

@ -1,7 +1,7 @@
# -*- coding:utf-8 -*-
## src/cell_renderer_image.py
##
## Copyright (C) 2003-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2003-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2005 Vincent Hanquez <tab AT snarc.org>
## Copyright (C) 2005-2007 Nikos Kouremenos <kourem AT gmail.com>
## Copyright (C) 2006 Travis Shirk <travis AT pobox.com>

View file

@ -2,7 +2,7 @@
## src/chat_control.py
##
## Copyright (C) 2006 Dimitur Kirov <dkirov AT gmail.com>
## Copyright (C) 2006-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2006-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2006-2008 Jean-Marie Traissard <jim AT lapin.org>
## Nikos Kouremenos <kourem AT gmail.com>
## Travis Shirk <travis AT pobox.com>
@ -56,6 +56,7 @@ from common.xmpp.protocol import NS_RECEIPTS, NS_ESESSION
from common.xmpp.protocol import NS_JINGLE_RTP_AUDIO, NS_JINGLE_RTP_VIDEO, NS_JINGLE_ICE_UDP, NS_JINGLE_FILE_TRANSFER
from common.xmpp.protocol import NS_CHATSTATES
from common.connection_handlers_events import MessageOutgoingEvent
from common.exceptions import GajimGeneralException
from command_system.implementation.middleware import ChatCommandProcessor
from command_system.implementation.middleware import CommandTools
@ -469,7 +470,6 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
self.user_nick = None
self.smooth = True
self.msg_textview.grab_focus()
self.command_hits = []
self.last_key_tabs = False
@ -864,7 +864,7 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
def send_message(self, message, keyID='', type_='chat', chatstate=None,
msg_id=None, resource=None, xhtml=None, callback=None, callback_args=[],
process_commands=True):
process_commands=True, attention=False):
"""
Send the given message to the active tab. Doesn't return None if error
"""
@ -881,7 +881,7 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
keyID=keyID, type_=type_, chatstate=chatstate, msg_id=msg_id,
resource=resource, user_nick=self.user_nick, xhtml=xhtml,
label=label, callback=callback, callback_args=callback_args,
control=self))
control=self, attention=attention))
# Record the history of sent messages
self.save_message(message, 'sent')
@ -920,10 +920,9 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
self.received_history_pos = pos
def print_conversation_line(self, text, kind, name, tim,
other_tags_for_name=[], other_tags_for_time=[],
other_tags_for_text=[], count_as_new=True, subject=None,
old_kind=None, xhtml=None, simple=False, xep0184_id=None,
graphics=True, displaymarking=None):
other_tags_for_name=[], other_tags_for_time=[], other_tags_for_text=[],
count_as_new=True, subject=None, old_kind=None, xhtml=None, simple=False,
xep0184_id=None, graphics=True, displaymarking=None, msg_id=None):
"""
Print 'chat' type messages
"""
@ -934,9 +933,9 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
if self.was_at_the_end or kind == 'outgoing':
end = True
textview.print_conversation_line(text, jid, kind, name, tim,
other_tags_for_name, other_tags_for_time, other_tags_for_text,
subject, old_kind, xhtml, simple=simple, graphics=graphics,
displaymarking=displaymarking)
other_tags_for_name, other_tags_for_time, other_tags_for_text,
subject, old_kind, xhtml, simple=simple, graphics=graphics,
displaymarking=displaymarking)
if xep0184_id is not None:
textview.show_xep0184_warning(xep0184_id)
@ -979,18 +978,18 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
type_ = 'printed_' + self.type_id
event = 'message_received'
show_in_roster = notify.get_show_in_roster(event,
self.account, self.contact, self.session)
self.account, self.contact, self.session)
show_in_systray = notify.get_show_in_systray(event,
self.account, self.contact, type_)
self.account, self.contact, type_)
event = gajim.events.create_event(type_, (self,),
show_in_roster=show_in_roster,
event = gajim.events.create_event(type_, (text, subject, self,
msg_id), show_in_roster=show_in_roster,
show_in_systray=show_in_systray)
gajim.events.add_event(self.account, full_jid, event)
# We need to redraw contact if we show in roster
if show_in_roster:
gajim.interface.roster.draw_contact(self.contact.jid,
self.account)
self.account)
if not self.parent_win:
return
@ -1437,22 +1436,22 @@ class ChatControl(ChatControlBase):
def __init__(self, parent_win, contact, acct, session, resource=None):
ChatControlBase.__init__(self, self.TYPE_ID, parent_win,
'chat_control', contact, acct, resource)
'chat_control', contact, acct, resource)
self.gpg_is_active = False
# for muc use:
# widget = self.xml.get_object('muc_window_actions_button')
self.actions_button = self.xml.get_object('message_window_actions_button')
id_ = self.actions_button.connect('clicked',
self.on_actions_button_clicked)
self.on_actions_button_clicked)
self.handlers[id_] = self.actions_button
self._formattings_button = self.xml.get_object('formattings_button')
self._add_to_roster_button = self.xml.get_object(
'add_to_roster_button')
'add_to_roster_button')
id_ = self._add_to_roster_button.connect('clicked',
self._on_add_to_roster_menuitem_activate)
self._on_add_to_roster_menuitem_activate)
self.handlers[id_] = self._add_to_roster_button
self._audio_button = self.xml.get_object('audio_togglebutton')
@ -1460,14 +1459,14 @@ class ChatControl(ChatControlBase):
self.handlers[id_] = self._audio_button
# add a special img
gtkgui_helpers.add_image_to_button(self._audio_button,
'gajim-mic_inactive')
'gajim-mic_inactive')
self._video_button = self.xml.get_object('video_togglebutton')
id_ = self._video_button.connect('toggled', self.on_video_button_toggled)
self.handlers[id_] = self._video_button
# add a special img
gtkgui_helpers.add_image_to_button(self._video_button,
'gajim-cam_inactive')
'gajim-cam_inactive')
self._send_file_button = self.xml.get_object('send_file_button')
# add a special img for send file button
@ -1476,30 +1475,30 @@ class ChatControl(ChatControlBase):
img.set_from_file(path_to_upload_img)
self._send_file_button.set_image(img)
id_ = self._send_file_button.connect('clicked',
self._on_send_file_menuitem_activate)
self._on_send_file_menuitem_activate)
self.handlers[id_] = self._send_file_button
self._convert_to_gc_button = self.xml.get_object(
'convert_to_gc_button')
'convert_to_gc_button')
id_ = self._convert_to_gc_button.connect('clicked',
self._on_convert_to_gc_menuitem_activate)
self._on_convert_to_gc_menuitem_activate)
self.handlers[id_] = self._convert_to_gc_button
contact_information_button = self.xml.get_object(
'contact_information_button')
id_ = contact_information_button.connect('clicked',
self._on_contact_information_menuitem_activate)
self.handlers[id_] = contact_information_button
self._contact_information_button = self.xml.get_object(
'contact_information_button')
id_ = self._contact_information_button.connect('clicked',
self._on_contact_information_menuitem_activate)
self.handlers[id_] = self._contact_information_button
compact_view = gajim.config.get('compact_view')
self.chat_buttons_set_visible(compact_view)
self.widget_set_visible(self.xml.get_object('banner_eventbox'),
gajim.config.get('hide_chat_banner'))
gajim.config.get('hide_chat_banner'))
self.authentication_button = self.xml.get_object(
'authentication_button')
'authentication_button')
id_ = self.authentication_button.connect('clicked',
self._on_authentication_button_clicked)
self._on_authentication_button_clicked)
self.handlers[id_] = self.authentication_button
# Add lock image to show chat encryption
@ -1541,31 +1540,31 @@ class ChatControl(ChatControlBase):
# Hook up signals
id_ = self.parent_win.window.connect('motion-notify-event',
self._on_window_motion_notify)
self._on_window_motion_notify)
self.handlers[id_] = self.parent_win.window
message_tv_buffer = self.msg_textview.get_buffer()
id_ = message_tv_buffer.connect('changed',
self._on_message_tv_buffer_changed)
self._on_message_tv_buffer_changed)
self.handlers[id_] = message_tv_buffer
widget = self.xml.get_object('avatar_eventbox')
widget.set_property('height-request', gajim.config.get(
'chat_avatar_height'))
'chat_avatar_height'))
id_ = widget.connect('enter-notify-event',
self.on_avatar_eventbox_enter_notify_event)
self.on_avatar_eventbox_enter_notify_event)
self.handlers[id_] = widget
id_ = widget.connect('leave-notify-event',
self.on_avatar_eventbox_leave_notify_event)
self.on_avatar_eventbox_leave_notify_event)
self.handlers[id_] = widget
id_ = widget.connect('button-press-event',
self.on_avatar_eventbox_button_press_event)
self.on_avatar_eventbox_button_press_event)
self.handlers[id_] = widget
widget = self.xml.get_object('location_eventbox')
id_ = widget.connect('button-release-event',
self.on_location_eventbox_button_release_event)
self.on_location_eventbox_button_release_event)
self.handlers[id_] = widget
for key in ('1', '2', '3', '4', '5', '6', '7', '8', '9', '*', '0', '#'):
@ -1614,7 +1613,7 @@ class ChatControl(ChatControlBase):
if not resource:
resource = contact.resource
session = gajim.connections[self.account].find_controlless_session(
self.contact.jid, resource)
self.contact.jid, resource)
self.setup_seclabel(self.xml.get_object('label_selector'))
if session:
@ -1627,8 +1626,7 @@ class ChatControl(ChatControlBase):
# Enable encryption if needed
self.no_autonegotiation = False
e2e_is_active = self.session and self.session.enable_encryption
gpg_pref = gajim.config.get_per('contacts', contact.jid,
'gpg_enabled')
gpg_pref = gajim.config.get_per('contacts', contact.jid, 'gpg_enabled')
# try GPG first
if not e2e_is_active and gpg_pref and \
@ -1637,30 +1635,30 @@ class ChatControl(ChatControlBase):
self.gpg_is_active = True
gajim.encrypted_chats[self.account].append(contact.jid)
msg = _('GPG encryption enabled')
ChatControlBase.print_conversation_line(self, msg,
'status', '', None)
ChatControlBase.print_conversation_line(self, msg, 'status', '',
None)
if self.session:
self.session.loggable = gajim.config.get_per('accounts',
self.account, 'log_encrypted_sessions')
self.account, 'log_encrypted_sessions')
# GPG is always authenticated as we use GPG's WoT
self._show_lock_image(self.gpg_is_active, 'GPG', self.gpg_is_active,
self.session and self.session.is_loggable(), True)
self.session and self.session.is_loggable(), True)
self.update_ui()
# restore previous conversation
self.restore_conversation()
self.msg_textview.grab_focus()
# change tooltip text for audio and video buttons if python-farsight is
# change tooltip text for audio and video buttons if python-farstream is
# not installed
if not gajim.HAVE_FARSIGHT:
if not gajim.HAVE_FARSTREAM:
tooltip_text = self._audio_button.get_tooltip_text()
self._audio_button.set_tooltip_text(
'%s\n%s' % (tooltip_text, _('Requires python-farsight.')))
'%s\n%s' % (tooltip_text, _('Requires python-farstream.')))
tooltip_text = self._video_button.get_tooltip_text()
self._video_button.set_tooltip_text(
'%s\n%s' % (tooltip_text, _('Requires python-farsight.')))
'%s\n%s' % (tooltip_text, _('Requires python-farstream.')))
gajim.ged.register_event_handler('pep-received', ged.GUI1,
self._nec_pep_received)
@ -1708,7 +1706,7 @@ class ChatControl(ChatControlBase):
# Jingle detection
if self.contact.supports(NS_JINGLE_ICE_UDP) and \
gajim.HAVE_FARSIGHT and self.contact.resource:
gajim.HAVE_FARSTREAM and self.contact.resource:
self.audio_available = self.contact.supports(NS_JINGLE_RTP_AUDIO)
self.video_available = self.contact.supports(NS_JINGLE_RTP_VIDEO)
else:
@ -1724,18 +1722,19 @@ class ChatControl(ChatControlBase):
self._video_button.set_sensitive(self.video_available)
# Send file
if (self.contact.supports(NS_FILE) or self.contact.supports(NS_JINGLE_FILE_TRANSFER)) and self.contact.resource:
if (self.contact.supports(NS_FILE) or self.contact.supports(NS_JINGLE_FILE_TRANSFER)) and (self.type_id == 'chat' or \
self.gc_contact.resource):
self._send_file_button.set_sensitive(True)
self._send_file_button.set_tooltip_text('')
else:
self._send_file_button.set_sensitive(False)
if not (self.contact.supports(NS_FILE) or self.contact.supports(NS_JINGLE_FILE_TRANSFER)):
self._send_file_button.set_tooltip_text(_(
"This contact does not support file transfer."))
"This contact does not support file transfer."))
else:
self._send_file_button.set_tooltip_text(
_("You need to know the real JID of the contact to send him or "
"her a file."))
_("You need to know the real JID of the contact to send "
"him or her a file."))
# Convert to GC
if self.contact.supports(NS_MUC):
@ -1743,6 +1742,13 @@ class ChatControl(ChatControlBase):
else:
self._convert_to_gc_button.set_sensitive(False)
# Information
if gajim.account_is_disconnected(self.account):
self._contact_information_button.set_sensitive(False)
else:
self._contact_information_button.set_sensitive(True)
def update_all_pep_types(self):
for pep_type in self._pep_images:
self.update_pep(pep_type)
@ -2230,7 +2236,7 @@ class ChatControl(ChatControlBase):
dialogs.ESessionInfoWindow(self.session)
def send_message(self, message, keyID='', chatstate=None, xhtml=None,
process_commands=True):
process_commands=True, attention=False):
"""
Send a message to contact
"""
@ -2281,7 +2287,8 @@ class ChatControl(ChatControlBase):
ChatControlBase.send_message(self, message, keyID, type_='chat',
chatstate=chatstate_to_send, xhtml=xhtml, callback=_on_sent,
callback_args=[contact, message, encrypted, xhtml,
self.get_seclabel()], process_commands=process_commands)
self.get_seclabel()], process_commands=process_commands,
attention=attention)
def check_for_possible_paused_chatstate(self, arg):
"""
@ -2391,8 +2398,8 @@ class ChatControl(ChatControlBase):
return gajim.nicks[self.account]
def print_conversation(self, text, frm='', tim=None, encrypted=False,
subject=None, xhtml=None, simple=False, xep0184_id=None,
displaymarking=None):
subject=None, xhtml=None, simple=False, xep0184_id=None,
displaymarking=None, msg_id=None):
"""
Print a line in the conversation
@ -2423,21 +2430,22 @@ class ChatControl(ChatControlBase):
# ESessions
if not encrypted:
msg = _('The following message was NOT encrypted')
ChatControlBase.print_conversation_line(self, msg, 'status', '',
tim)
ChatControlBase.print_conversation_line(self, msg, 'status',
'', tim)
else:
# GPG encryption
if encrypted and not self.gpg_is_active:
msg = _('The following message was encrypted')
ChatControlBase.print_conversation_line(self, msg, 'status', '',
tim)
# turn on OpenPGP if this was in fact a XEP-0027 encrypted message
ChatControlBase.print_conversation_line(self, msg, 'status',
'', tim)
# turn on OpenPGP if this was in fact a XEP-0027 encrypted
# message
if encrypted == 'xep27':
self._toggle_gpg()
elif not encrypted and self.gpg_is_active:
msg = _('The following message was NOT encrypted')
ChatControlBase.print_conversation_line(self, msg, 'status', '',
tim)
ChatControlBase.print_conversation_line(self, msg, 'status',
'', tim)
if not frm:
kind = 'incoming'
name = contact.get_shown_name()
@ -2454,8 +2462,9 @@ class ChatControl(ChatControlBase):
if xhtml:
xhtml = '<body xmlns="%s">%s</body>' % (NS_XHTML, xhtml)
ChatControlBase.print_conversation_line(self, text, kind, name, tim,
subject=subject, old_kind=self.old_msg_kind, xhtml=xhtml,
simple=simple, xep0184_id=xep0184_id, displaymarking=displaymarking)
subject=subject, old_kind=self.old_msg_kind, xhtml=xhtml,
simple=simple, xep0184_id=xep0184_id, displaymarking=displaymarking,
msg_id=msg_id)
if text.startswith('/me ') or text.startswith('/me\n'):
self.old_msg_kind = None
else:
@ -3238,6 +3247,36 @@ class ChatControl(ChatControlBase):
b.connect('clicked', self._on_ok, file_props, type_)
self._add_info_bar_message(markup, [b], file_props, gtk.MESSAGE_ERROR)
def _on_accept_gc_invitation(self, widget, event):
room_jid = event.parameters[0]
password = event.parameters[2]
is_continued = event.parameters[3]
try:
if is_continued:
gajim.interface.join_gc_room(self.account, room_jid,
gajim.nicks[self.account], password, is_continued=True)
else:
dialogs.JoinGroupchatWindow(self.account, room_jid)
except GajimGeneralException:
pass
gajim.events.remove_events(self.account, self.contact.jid, event=event)
def _on_cancel_gc_invitation(self, widget, event):
gajim.events.remove_events(self.account, self.contact.jid, event=event)
def _get_gc_invitation(self, event):
room_jid = event.parameters[0]
comment = event.parameters[1]
markup = '<b>%s:</b> %s' % (_('Groupchat Invitation'), room_jid)
if comment:
markup += ' (%s)' % comment
b1 = gtk.Button(_('_Join'))
b1.connect('clicked', self._on_accept_gc_invitation, event)
b2 = gtk.Button(stock=gtk.STOCK_CANCEL)
b2.connect('clicked', self._on_cancel_gc_invitation, event)
self._add_info_bar_message(markup, [b1, b2], event.parameters,
gtk.MESSAGE_QUESTION)
def on_event_added(self, event):
if event.account != self.account:
return
@ -3259,6 +3298,8 @@ class ChatControl(ChatControlBase):
self._got_file_error(event.parameters, event.type_,
_('File transfer cancelled'),
_('Connection with peer cannot be established.'))
elif event.type_ == 'gc-invitation':
self._get_gc_invitation(event)
def on_event_removed(self, event_list):
"""
@ -3270,14 +3311,24 @@ class ChatControl(ChatControlBase):
if ev.jid != self.contact.jid:
continue
if ev.type_ not in ('file-request', 'file-completed', 'file-error',
'file-stopped', 'file-request-error', 'file-send-error'):
'file-stopped', 'file-request-error', 'file-send-error',
'gc-invitation'):
continue
i = 0
removed = False
for ib_msg in self.info_bar_queue:
if ib_msg[2] == ev.parameters:
self.info_bar_queue.remove(ib_msg)
if ev.type_ == 'gc-invitation':
if ev.parameters[0] == ib_msg[2][0]:
self.info_bar_queue.remove(ib_msg)
removed = True
else: # file-*
if ib_msg[2] == ev.parameters:
self.info_bar_queue.remove(ib_msg)
removed = True
if removed:
if i == 0:
# We are removing the one currently displayed
self.info_bar.set_no_show_all(True)
self.info_bar.hide()
# show next one?
gobject.idle_add(self._info_bar_show_message)

View file

@ -127,7 +127,7 @@ class StandardCommonCommands(CommandContainer):
@command(raw=True, empty=True)
@doc(_("""
Set current the status
Set the current the status
Status can be given as one of the following values: online, away,
chat, xa, dnd.
@ -136,6 +136,11 @@ class StandardCommonCommands(CommandContainer):
if status not in ('online', 'away', 'chat', 'xa', 'dnd'):
raise CommandError("Invalid status given")
for connection in gajim.connections.itervalues():
if not gajim.config.get_per('accounts', connection.name,
'sync_with_global_status'):
continue
if connection.connected < 2:
continue
connection.change_status(status, message)
@command(raw=True, empty=True)
@ -143,7 +148,13 @@ class StandardCommonCommands(CommandContainer):
def away(self, message):
if not message:
message = _("Away")
for connection in gajim.connections.itervalues():
if not gajim.config.get_per('accounts', connection.name,
'sync_with_global_status'):
continue
if connection.connected < 2:
continue
connection.change_status('away', message)
@command('back', raw=True, empty=True)
@ -151,7 +162,13 @@ class StandardCommonCommands(CommandContainer):
def online(self, message):
if not message:
message = _("Available")
for connection in gajim.connections.itervalues():
if not gajim.config.get_per('accounts', connection.name,
'sync_with_global_status'):
continue
if connection.connected < 2:
continue
connection.change_status('online', message)
class StandardCommonChatCommands(CommandContainer):
@ -213,6 +230,11 @@ class StandardCommonChatCommands(CommandContainer):
state = self._video_button.get_active()
self._video_button.set_active(not state)
@command(raw=True)
@doc(_("Send a message to the contact that will attract his (her) attention"))
def attention(self, message):
self.send_message(message, process_commands=False, attention=True)
class StandardChatCommands(CommandContainer):
"""
This command container contains standard commands which are unique

View file

@ -3,7 +3,7 @@
##
## Copyright (C) 2006 Jean-Marie Traissard <jim AT lapin.org>
## Tomasz Melcer <liori AT exroot.org>
## Copyright (C) 2006-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2006-2012 Yann Leboulanger <asterix AT lagaule.org>
##
## This file is part of Gajim.
##

View file

@ -3,7 +3,7 @@
##
## Copyright (C) 2007 Tomasz Melcer <liori AT exroot.org>
## Travis Shirk <travis AT pobox.com>
## Copyright (C) 2007-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2007-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2008 Brendan Taylor <whateley AT gmail.com>
## Jonathan Schleifer <js-gajim AT webkeks.org>
## Copyright (C) 2008-2009 Stephan Erb <steve-e AT h3c.de>

178
src/common/check_X509.py Normal file
View file

@ -0,0 +1,178 @@
import logging
log = logging.getLogger('gajim.c.check_X509')
try:
import OpenSSL.SSL
import OpenSSL.crypto
ver = OpenSSL.__version__
if ver < '0.12':
raise ImportError
from pyasn1.type import univ, constraint, char, namedtype, tag
from pyasn1.codec.der.decoder import decode
from common.helpers import prep, InvalidFormat
MAX = 64
oid_xmppaddr = '(1, 3, 6, 1, 5, 5, 7, 8, 5)'
oid_dnssrv = '(1, 3, 6, 1, 5, 5, 7, 8, 7)'
class DirectoryString(univ.Choice):
componentType = namedtype.NamedTypes(
namedtype.NamedType(
'teletexString', char.TeletexString().subtype(
subtypeSpec=constraint.ValueSizeConstraint(1, MAX))),
namedtype.NamedType(
'printableString', char.PrintableString().subtype(
subtypeSpec=constraint.ValueSizeConstraint(1, MAX))),
namedtype.NamedType(
'universalString', char.UniversalString().subtype(
subtypeSpec=constraint.ValueSizeConstraint(1, MAX))),
namedtype.NamedType(
'utf8String', char.UTF8String().subtype(
subtypeSpec=constraint.ValueSizeConstraint(1, MAX))),
namedtype.NamedType(
'bmpString', char.BMPString().subtype(
subtypeSpec=constraint.ValueSizeConstraint(1, MAX))),
namedtype.NamedType(
'ia5String', char.IA5String().subtype(
subtypeSpec=constraint.ValueSizeConstraint(1, MAX))),
namedtype.NamedType(
'gString', univ.OctetString().subtype(
subtypeSpec=constraint.ValueSizeConstraint(1, MAX))),
)
class AttributeValue(DirectoryString):
pass
class AttributeType(univ.ObjectIdentifier):
pass
class AttributeTypeAndValue(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.NamedType('type', AttributeType()),
namedtype.NamedType('value', AttributeValue()),
)
class RelativeDistinguishedName(univ.SetOf):
componentType = AttributeTypeAndValue()
class RDNSequence(univ.SequenceOf):
componentType = RelativeDistinguishedName()
class Name(univ.Choice):
componentType = namedtype.NamedTypes(
namedtype.NamedType('', RDNSequence()),
)
class GeneralName(univ.Choice):
componentType = namedtype.NamedTypes(
namedtype.NamedType('otherName', univ.Sequence().subtype(
implicitTag=tag.Tag(tag.tagClassContext,
tag.tagFormatConstructed, 0x0))),
namedtype.NamedType('rfc822Name', char.IA5String().subtype(
implicitTag=tag.Tag(tag.tagClassContext,
tag.tagFormatSimple, 1))),
namedtype.NamedType('dNSName', char.IA5String().subtype(
implicitTag=tag.Tag(tag.tagClassContext,
tag.tagFormatSimple, 2))),
namedtype.NamedType('x400Address', univ.Sequence().subtype(
implicitTag=tag.Tag(tag.tagClassContext,
tag.tagFormatConstructed, 0x3))),
namedtype.NamedType('directoryName', Name().subtype(
implicitTag=tag.Tag(tag.tagClassContext,
tag.tagFormatConstructed, 0x4))),
namedtype.NamedType('ediPartyName', univ.Sequence().subtype(
implicitTag=tag.Tag(tag.tagClassContext,
tag.tagFormatConstructed, 0x5))),
namedtype.NamedType('uniformResourceIdentifier',
char.IA5String().subtype(
implicitTag=tag.Tag(tag.tagClassContext,
tag.tagFormatSimple, 6))),
namedtype.NamedType('iPAddress', univ.OctetString().subtype(
implicitTag=tag.Tag(tag.tagClassContext,
tag.tagFormatSimple, 7))),
namedtype.NamedType('registeredID', univ.ObjectIdentifier().subtype(
implicitTag=tag.Tag(tag.tagClassContext,
tag.tagFormatSimple, 8))),
)
class GeneralNames(univ.SequenceOf):
componentType = GeneralName()
sizeSpec = univ.SequenceOf.sizeSpec + constraint.ValueSizeConstraint(1, MAX)
def _parse_asn1(asn1):
obj = decode(asn1, asn1Spec=GeneralNames())[0]
r = {}
for o in obj:
name = o.getName()
if name == 'dNSName':
if name not in r:
r[name] = []
r[name].append(str(o.getComponent()))
if name == 'otherName':
if name not in r:
r[name] = {}
tag = str(tuple(o.getComponent())[0])
val = str(tuple(o.getComponent())[1])
if tag not in r[name]:
r[name][tag] = []
r[name][tag].append(val)
if name == 'uniformResourceIdentifier':
r['uniformResourceIdentifier'] = True
return r
def check_certificate(cert, domain):
cnt = cert.get_extension_count()
if '.' in domain:
compared_domain = domain.split('.', 1)[1]
else:
compared_domain = ''
srv_domain = '_xmpp-client.' + domain
compared_srv_domain = '_xmpp-client.' + compared_domain
for i in range(0, cnt):
ext = cert.get_extension(i)
if ext.get_short_name() == 'subjectAltName':
r = _parse_asn1(ext.get_data())
if 'otherName' in r:
if oid_xmppaddr in r['otherName']:
for host in r['otherName'][oid_xmppaddr]:
try:
host = prep(None, host, None)
except InvalidFormat:
continue
if host == domain:
return True
if oid_dnssrv in r['otherName']:
for host in r['otherName'][oid_dnssrv]:
if host.startswith('_xmpp-client.*.'):
if host.replace('*.', '', 1) == compared_srv_domain:
return True
continue
if host == srv_domain:
return True
if 'dNSName' in r:
for host in r['dNSName']:
if host.startswith('*.'):
if host[2:] == compared_domain:
return True
continue
if host == domain:
return True
if r:
return False
break
subject = cert.get_subject()
if subject.commonName == domain:
return True
return False
except ImportError:
log.warn('Import of PyOpenSSL or pyasn1 failed. Cannot correctly check '
'SSL certificate')
def check_certificate(cert, domain):
subject = cert.get_subject()
if subject.commonName == domain:
return True
return False

View file

@ -3,7 +3,7 @@
##
## Copyright (C) 2005-2006 Travis Shirk <travis AT pobox.com>
## Nikos Kouremenos <kourem AT gmail.com>
## Copyright (C) 2005-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2005-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2006 Dimitur Kirov <dkirov AT gmail.com>
## Copyright (C) 2007 Tomasz Melcer <liori AT exroot.org>
## Copyright (C) 2008 Jean-Marie Traissard <jim AT lapin.org>

View file

@ -1,7 +1,7 @@
# -*- coding:utf-8 -*-
## src/common/commands.py
##
## Copyright (C) 2006-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2006-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2006-2007 Tomasz Melcer <liori AT exroot.org>
## Copyright (C) 2007 Jean-Marie Traissard <jim AT lapin.org>
## Copyright (C) 2008 Brendan Taylor <whateley AT gmail.com>
@ -56,10 +56,10 @@ class AdHocCommand:
assert status in ('executing', 'completed', 'canceled')
response = request.buildReply('result')
cmd = response.addChild('command', namespace=xmpp.NS_COMMANDS, attrs={
'sessionid': self.sessionid,
'node': self.commandnode,
'status': status})
cmd = response.getTag('command', namespace=xmpp.NS_COMMANDS)
cmd.setAttr('sessionid', self.sessionid)
cmd.setAttr('node', self.commandnode)
cmd.setAttr('status', status)
if defaultaction is not None or actions is not None:
if defaultaction is not None:
assert defaultaction in ('cancel', 'execute', 'prev', 'next',
@ -277,13 +277,17 @@ class ForwardMessagesCommand(AdHocCommand):
def execute(self, request):
account = self.connection.name
# Forward messages
events = gajim.events.get_events(account, types=['chat', 'normal'])
events = gajim.events.get_events(account, types=['chat', 'normal',
'printed_chat'])
j, resource = gajim.get_room_and_nick_from_fjid(self.jid)
for jid in events:
for event in events[jid]:
ev_typ = event.type_
if ev_typ == 'printed_chat':
ev_typ = 'chat'
self.connection.send_message(j, event.parameters[0], '',
type_=event.type_, subject=event.parameters[1],
resource=resource, forward_from=jid, delayed=event.time_)
type_=ev_typ, subject=event.parameters[1],
resource=resource, forward_from=jid, delayed=event.time_)
# Inform other client of completion
response, cmd = self.buildResponse(request, status = 'completed')

View file

@ -1,7 +1,7 @@
# -*- coding:utf-8 -*-
## src/common/config.py
##
## Copyright (C) 2003-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2003-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2004-2005 Vincent Hanquez <tab AT snarc.org>
## Copyright (C) 2005 Stéphan Kochen <stephan AT kochen.nl>
## Copyright (C) 2005-2006 Dimitur Kirov <dkirov AT gmail.com>
@ -65,7 +65,7 @@ class Config:
DEFAULT_MAILAPP = 'mozilla-thunderbird -compose'
DEFAULT_FILE_MANAGER = 'xffm'
__options = {
__options = ({
# name: [ type, default_value, help_string ]
'verbose': [ opt_bool, False, '', True ],
'autopopup': [ opt_bool, False ],
@ -99,6 +99,15 @@ class Config:
'statusmsgcolor': [ opt_color, '#4e9a06', _('Status message text color.'), True ],
'markedmsgcolor': [ opt_color, '#ff8080', '', True ],
'urlmsgcolor': [ opt_color, '#204a87', '', True ],
'notif_signin_color': [ opt_color, '#32CD32', _('Contact signed in notification color.') ], # limegreen
'notif_signout_color': [ opt_color, '#FF0000', _('Contact signout notification color') ], # red
'notif_message_color': [ opt_color, '#1E90FF', _('New message/email notification color.') ], # dodgerblue
'notif_ftrequest_color': [ opt_color, '#F0E68C', _('File transfer request notification color.') ], # khaki
'notif_fterror_color': [ opt_color, '#B22222', _('File transfer error notification color.') ], # firebrick
'notif_ftcomplete_color': [ opt_color, '#9ACD32', _('File transfer complete or stopped notification color.') ], # yellowgreen
'notif_invite_color': [ opt_color, '#D2B48C', _('Groupchat invitation notification color') ], # tan1
'notif_status_color': [ opt_color, '#D8BFD8', _('Status changed notification background color') ], # thistle2
'notif_other_color': [ opt_color, '#FFFFFF', _('Other dialogs color.') ], # white
'inmsgfont': [ opt_str, '', _('Incoming nickname font.'), True ],
'outmsgfont': [ opt_str, '', _('Outgoing nickname font.'), True ],
'inmsgtxtfont': [ opt_str, '', _('Incoming text font.'), True ],
@ -169,7 +178,7 @@ class Config:
'change_roster_title': [ opt_bool, True, _('Add * and [n] in roster title?')],
'restore_lines': [opt_int, 4, _('How many lines to remember from previous conversation when a chat tab/window is reopened.')],
'restore_timeout': [opt_int, 60, _('How many minutes should last lines from previous conversation last.')],
'muc_restore_lines': [opt_int, 20, _('How many lines to request to server when entering a groupchat. -1 means no limit')],
'muc_restore_lines': [opt_int, 20, _('How many lines to request from server when entering a groupchat. -1 means no limit')],
'muc_restore_timeout': [opt_int, 60, _('How many minutes back to request logs when a entering a groupchat. -1 means no limit')],
'muc_autorejoin_timeout': [opt_int, 1, _('How many seconds to wait before trying to autorejoin to a conference you are being disconnected from. Set to 0 to disable autorejoining.')],
'muc_autorejoin_on_kick': [opt_bool, False, _('Should autorejoin be activated when we are being kicked from a conference?')],
@ -291,7 +300,8 @@ class Config:
'stun_server': [opt_str, '', _('STUN server to use when using jingle')],
'show_affiliation_in_groupchat': [opt_bool, True, _('If True, Gajim will show affiliation of groupchat occupants by adding a colored square to the status icon')],
'global_proxy': [opt_str, '', _('Proxy used for all outgoing connections if the account does not have a specific proxy configured')],
}
'ignore_incoming_attention': [opt_bool, False, _('If True, Gajim will ignore incoming attention requestd ("wizz").')],
}, {})
__options_per_key = {
'accounts': ({
@ -386,7 +396,7 @@ class Config:
'ft_send_local_ips': [ opt_bool, True, _('If enabled, Gajim will send your local IPs so your contact can connect to your machine to transfer files.')],
'oauth2_refresh_token': [ opt_str, '', _('Latest token for Oauth2 authentication.')],
'oauth2_client_id': [ opt_str, '0000000044077801', _('client_id for Oauth2 authentication.')],
'oauth2_redirect_url': [ opt_str, 'http%3A%2F%2Fgajim.org%2Fmsnauth%2Findex.cgi', _('redirect_url for Oauth2 authentication.')],
'oauth2_redirect_url': [ opt_str, 'https%3A%2F%2Fgajim.org%2Fmsnauth%2Findex.cgi', _('redirect_url for Oauth2 authentication.')],
}, {}),
'statusmsg': ({
'message': [ opt_str, '' ],
@ -456,7 +466,7 @@ class Config:
'speller_language': [ opt_str, '', _('Language for which we want to check misspelled words')],
}, {}),
'plugins': ({
'active': [opt_bool, False, _('State whether plugins should be activated on exit (this is saved on Gajim exit). This option SHOULD NOT be used to (de)activate plug-ins. Use GUI instead.')],
'active': [opt_bool, False, _('State whether plugins should be activated on startup (this is saved on Gajim exit). This option SHOULD NOT be used to (de)activate plug-ins. Use GUI instead.')],
},{}),
}
@ -488,6 +498,7 @@ class Config:
}
soundevents_default = {
'attention_received': [True, 'attention.wav'],
'first_message_received': [ True, 'message1.wav' ],
'next_message_received_focused': [ True, 'message2.wav' ],
'next_message_received_unfocused': [ True, 'message2.wav' ],
@ -526,9 +537,9 @@ class Config:
_('Tor'): ['socks5', 'localhost', 9050],
}
def foreach(self, cb, data = None):
for opt in self.__options:
cb(data, opt, None, self.__options[opt])
def foreach(self, cb, data=None):
for opt in self.__options[1]:
cb(data, opt, None, self.__options[1][opt])
for opt in self.__options_per_key:
cb(data, opt, None, None)
dict_ = self.__options_per_key[opt][1]
@ -542,7 +553,7 @@ class Config:
Tree-like interface
"""
if node is None:
for child, option in self.__options.iteritems():
for child, option in self.__options[1].iteritems():
yield (child, ), option
for grandparent in self.__options_per_key:
yield (grandparent, ), None
@ -598,35 +609,44 @@ class Config:
return None
def set(self, optname, value):
if optname not in self.__options:
if optname not in self.__options[1]:
# raise RuntimeError, 'option %s does not exist' % optname
return
opt = self.__options[optname]
value = self.is_valid(opt[OPT_TYPE], value)
value = self.is_valid(self.__options[0][optname][OPT_TYPE], value)
if value is None:
# raise RuntimeError, 'value of %s cannot be None' % optname
return
opt[OPT_VAL] = value
self.__options[1][optname] = value
def get(self, optname = None):
def get(self, optname=None):
if not optname:
return self.__options.keys()
if optname not in self.__options:
return self.__options[1].keys()
if optname not in self.__options[1]:
return None
return self.__options[optname][OPT_VAL]
return self.__options[1][optname]
def get_default(self, optname):
if optname not in self.__options[0]:
return None
return self.__options[0][optname][OPT_VAL]
def get_type(self, optname):
if optname not in self.__options[0]:
return None
return self.__options[0][optname][OPT_TYPE][0]
def get_desc(self, optname):
if optname not in self.__options:
if optname not in self.__options[0]:
return None
if len(self.__options[optname]) > OPT_DESC:
return self.__options[optname][OPT_DESC]
if len(self.__options[0][optname]) > OPT_DESC:
return self.__options[0][optname][OPT_DESC]
def get_restart(self, optname):
if optname not in self.__options:
if optname not in self.__options[0]:
return None
if len(self.__options[optname]) > OPT_RESTART:
return self.__options[optname][OPT_RESTART]
if len(self.__options[0][optname]) > OPT_RESTART:
return self.__options[0][optname][OPT_RESTART]
def add_per(self, typename, name): # per_group_of_option
if typename not in self.__options_per_key:
@ -637,7 +657,9 @@ class Config:
if name in opt[1]:
# we already have added group name before
return 'you already have added %s before' % name
opt[1][name] = copy.deepcopy(opt[0])
opt[1][name] = {}
for o in opt[0]:
opt[1][name][o] = opt[0][o][OPT_VAL]
def del_per(self, typename, name, subname = None): # per_group_of_option
if typename not in self.__options_per_key:
@ -665,36 +687,50 @@ class Config:
if subname not in obj:
# raise RuntimeError, '%s is not a key of %s' % (subname, obj)
return
subobj = obj[subname]
value = self.is_valid(subobj[OPT_TYPE], value)
typ = self.__options_per_key[optname][0][subname][OPT_TYPE]
value = self.is_valid(typ, value)
if value is None:
# raise RuntimeError, '%s of %s cannot be None' % optname
return
subobj[OPT_VAL] = value
obj[subname] = value
def get_per(self, optname, key = None, subname = None): # per_group_of_option
def get_per(self, optname, key=None, subname=None): # per_group_of_option
if optname not in self.__options_per_key:
return None
dict_ = self.__options_per_key[optname][1]
if not key:
return dict_.keys()
if key not in dict_:
if optname in self.__options_per_key \
and subname in self.__options_per_key[optname][0]:
return self.__options_per_key \
[optname][0][subname][1]
if subname in self.__options_per_key[optname][0]:
return self.__options_per_key[optname][0][subname][1]
return None
obj = dict_[key]
if not subname:
return obj
if subname not in obj:
return None
return obj[subname][OPT_VAL]
return obj[subname]
def get_desc_per(self, optname, key = None, subname = None):
def get_default_per(self, optname, subname):
if optname not in self.__options_per_key:
return None
dict_ = self.__options_per_key[optname][1]
dict_ = self.__options_per_key[optname][0]
if subname not in dict_:
return None
return dict_[subname][OPT_VAL]
def get_type_per(self, optname, subname):
if optname not in self.__options_per_key:
return None
dict_ = self.__options_per_key[optname][0]
if subname not in dict_:
return None
return dict_[subname][OPT_TYPE][0]
def get_desc_per(self, optname, key=None, subname=None):
if optname not in self.__options_per_key:
return None
dict_ = self.__options_per_key[optname][0]
if not key:
return None
if key not in dict_:
@ -708,10 +744,10 @@ class Config:
return obj[subname][OPT_DESC]
return None
def get_restart_per(self, optname, key = None, subname = None):
def get_restart_per(self, optname, key=None, subname=None):
if optname not in self.__options_per_key:
return False
dict_ = self.__options_per_key[optname][1]
dict_ = self.__options_per_key[optname][0]
if not key:
return False
if key not in dict_:
@ -738,8 +774,13 @@ class Config:
return (account not in no_log_for) and (jid not in no_log_for)
def _init_options(self):
for opt in self.__options[0]:
self.__options[1][opt] = self.__options[0][opt][OPT_VAL]
def __init__(self):
#init default values
self._init_options()
for event in self.soundevents_default:
default = self.soundevents_default[event]
self.add_per('soundevents', event)

View file

@ -3,7 +3,7 @@
##
## Copyright (C) 2006 Jean-Marie Traissard <jim AT lapin.org>
## Junglecow J <junglecow AT gmail.com>
## Copyright (C) 2006-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2006-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2007 Brendan Taylor <whateley AT gmail.com>
## Copyright (C) 2008 Jonathan Schleifer <js-gajim AT webkeks.org>
##

View file

@ -2,7 +2,7 @@
## src/common/connection.py
##
## Copyright (C) 2003-2005 Vincent Hanquez <tab AT snarc.org>
## Copyright (C) 2003-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2003-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2005 Alex Mauer <hawke AT hawkesnest.net>
## Stéphan Kochen <stephan AT kochen.nl>
## Copyright (C) 2005-2006 Dimitur Kirov <dkirov AT gmail.com>
@ -58,6 +58,7 @@ from common import gajim
from common import gpg
from common import passwords
from common import exceptions
from common import check_X509
from connection_handlers import *
from xmpp import Smacks
@ -98,6 +99,7 @@ ssl_error = {
31: _("Authority and issuer serial number mismatch"),
32: _("Key usage does not include certificate signing"),
50: _("Application verification failure")
#100 is for internal usage: host not correct
}
class CommonConnection:
@ -251,7 +253,7 @@ class CommonConnection:
def _prepare_message(self, jid, msg, keyID, type_='chat', subject='',
chatstate=None, msg_id=None, resource=None, user_nick=None, xhtml=None,
session=None, forward_from=None, form_node=None, label=None,
original_message=None, delayed=None, callback=None):
original_message=None, delayed=None, attention=False, callback=None):
if not self.connection or self.connected < 2:
return 1
try:
@ -302,7 +304,8 @@ class CommonConnection:
msgtxt, original_message, fjid, resource,
jid, xhtml, subject, chatstate, msg_id,
label, forward_from, delayed, session,
form_node, user_nick, keyID, callback)
form_node, user_nick, keyID, attention,
callback)
gajim.nec.push_incoming_event(GPGTrustKeyEvent(None,
conn=self, callback=_on_always_trust))
else:
@ -310,7 +313,7 @@ class CommonConnection:
original_message, fjid, resource, jid, xhtml,
subject, chatstate, msg_id, label, forward_from,
delayed, session, form_node, user_nick, keyID,
callback)
attention, callback)
gajim.thread_interface(encrypt_thread, [msg, keyID, False],
_on_encrypted, [])
return
@ -318,18 +321,18 @@ class CommonConnection:
self._message_encrypted_cb(('', error), type_, msg, msgtxt,
original_message, fjid, resource, jid, xhtml, subject,
chatstate, msg_id, label, forward_from, delayed, session,
form_node, user_nick, keyID, callback)
form_node, user_nick, keyID, attention, callback)
return
self._on_continue_message(type_, msg, msgtxt, original_message, fjid,
resource, jid, xhtml, subject, msgenc, keyID, chatstate, msg_id,
label, forward_from, delayed, session, form_node, user_nick,
callback)
attention, callback)
def _message_encrypted_cb(self, output, type_, msg, msgtxt,
original_message, fjid, resource, jid, xhtml, subject, chatstate, msg_id,
label, forward_from, delayed, session, form_node, user_nick, keyID,
callback):
attention, callback):
msgenc, error = output
if msgenc and not error:
@ -342,7 +345,7 @@ class CommonConnection:
self._on_continue_message(type_, msg, msgtxt, original_message,
fjid, resource, jid, xhtml, subject, msgenc, keyID,
chatstate, msg_id, label, forward_from, delayed, session,
form_node, user_nick, callback)
form_node, user_nick, attention, callback)
return
# Encryption failed, do not send message
tim = localtime()
@ -351,7 +354,8 @@ class CommonConnection:
def _on_continue_message(self, type_, msg, msgtxt, original_message, fjid,
resource, jid, xhtml, subject, msgenc, keyID, chatstate, msg_id,
label, forward_from, delayed, session, form_node, user_nick, callback):
label, forward_from, delayed, session, form_node, user_nick, attention,
callback):
if type_ == 'chat':
msg_iq = common.xmpp.Message(to=fjid, body=msgtxt, typ=type_,
xhtml=xhtml)
@ -422,6 +426,10 @@ class CommonConnection:
if session.enable_encryption:
msg_iq = session.encrypt_stanza(msg_iq)
# XEP-0224
if attention:
msg_iq.setTag('attention', namespace=common.xmpp.NS_ATTENTION)
if callback:
callback(jid, msg, keyID, forward_from, session, original_message,
subject, type_, msg_iq, xhtml)
@ -808,6 +816,10 @@ class Connection(CommonConnection, ConnectionHandlers):
if not (self.sm and self.sm.resumption):
gajim.nec.push_incoming_event(OurShowEvent(None, conn=self,
show='offline'))
else:
self.sm.enabled = False
gajim.nec.push_incoming_event(OurShowEvent(None, conn=self,
show='error'))
self.disconnect()
if gajim.config.get_per('accounts', self.name, 'autoreconnect'):
self.connected = -1
@ -1012,7 +1024,7 @@ class Connection(CommonConnection, ConnectionHandlers):
proxy = {}
proxyptr = gajim.config.get_per('proxies', p)
for key in proxyptr.keys():
proxy[key] = proxyptr[key][1]
proxy[key] = proxyptr[key]
else:
proxy = None
use_srv = True
@ -1276,9 +1288,9 @@ class Connection(CommonConnection, ConnectionHandlers):
except AttributeError:
errnum = -1 # we don't have an errnum
if errnum > 0 and str(errnum) not in gajim.config.get_per('accounts',
self.name, 'ignore_ssl_errors'):
text = _('The authenticity of the %s certificate could be invalid.') %\
hostname
self.name, 'ignore_ssl_errors').split():
text = _('The authenticity of the %s certificate could be invalid.'
) % hostname
if errnum in ssl_error:
text += _('\nSSL Error: <b>%s</b>') % ssl_error[errnum]
else:
@ -1290,7 +1302,8 @@ class Connection(CommonConnection, ConnectionHandlers):
certificate=con.Connection.ssl_certificate))
return True
if hasattr(con.Connection, 'ssl_fingerprint_sha1'):
saved_fingerprint = gajim.config.get_per('accounts', self.name, 'ssl_fingerprint_sha1')
saved_fingerprint = gajim.config.get_per('accounts', self.name,
'ssl_fingerprint_sha1')
if saved_fingerprint:
# Check sha1 fingerprint
if con.Connection.ssl_fingerprint_sha1 != saved_fingerprint:
@ -1299,15 +1312,24 @@ class Connection(CommonConnection, ConnectionHandlers):
new_fingerprint=con.Connection.ssl_fingerprint_sha1))
return True
else:
gajim.config.set_per('accounts', self.name, 'ssl_fingerprint_sha1',
con.Connection.ssl_fingerprint_sha1)
gajim.config.set_per('accounts', self.name,
'ssl_fingerprint_sha1', con.Connection.ssl_fingerprint_sha1)
if not check_X509.check_certificate(con.Connection.ssl_certificate,
hostname) and '100' not in gajim.config.get_per('accounts',
self.name, 'ignore_ssl_errors').split():
txt = _('The authenticity of the %s certificate could be '
'invalid.\nThe certificate does not cover this domain.') % \
hostname
gajim.nec.push_incoming_event(SSLErrorEvent(None, conn=self,
error_text=txt, error_num=100,
cert=con.Connection.ssl_cert_pem,
fingerprint=con.Connection.ssl_fingerprint_sha1,
certificate=con.Connection.ssl_certificate))
return True
self._register_handlers(con, con_type)
con.auth(
user=name,
password=self.password,
resource=self.server_resource,
sasl=1,
on_auth=self.__on_auth)
con.auth(user=name, password=self.password,
resource=self.server_resource, sasl=1, on_auth=self.__on_auth)
def ssl_certificate_accepted(self):
if not self.connection:
@ -1317,7 +1339,10 @@ class Connection(CommonConnection, ConnectionHandlers):
msg=_('Connection with account %s has been lost. Retry '
'connecting.') % self.name))
return
name = gajim.config.get_per('accounts', self.name, 'name')
if gajim.config.get_per('accounts', self.name, 'anonymous_auth'):
name = None
else:
name = gajim.config.get_per('accounts', self.name, 'name')
self._register_handlers(self.connection, 'ssl')
self.connection.auth(name, self.password, self.server_resource, 1,
self.__on_auth)
@ -1372,7 +1397,7 @@ class Connection(CommonConnection, ConnectionHandlers):
gajim.nec.push_incoming_event(InformationEvent(None, conn=self,
level='error', pri_txt=_('Authentication failed with "%s"') % \
self._hostname, sec_txt=_('Please check your login and password'
'for correctness.')))
' for correctness.')))
if self.on_connect_auth:
self.on_connect_auth(None)
self.on_connect_auth = None
@ -1449,7 +1474,7 @@ class Connection(CommonConnection, ConnectionHandlers):
level='error', pri_txt=_('Error while removing privacy '
'list'), sec_txt=_('Privacy list %s has not been removed. '
'It is maybe active in one of your connected resources. '
'Deactivate it and tryagain.') % privacy_list))
'Deactivate it and try again.') % privacy_list))
common.xmpp.features_nb.delPrivacyList(self.connection, privacy_list,
_on_del_privacy_list_result)
@ -1775,8 +1800,8 @@ class Connection(CommonConnection, ConnectionHandlers):
def send_message(self, jid, msg, keyID=None, type_='chat', subject='',
chatstate=None, msg_id=None, resource=None, user_nick=None, xhtml=None,
label=None, session=None, forward_from=None, form_node=None,
original_message=None, delayed=None, callback=None, callback_args=[],
now=False):
original_message=None, delayed=None, attention=False, callback=None,
callback_args=[], now=False):
def cb(jid, msg, keyID, forward_from, session, original_message,
subject, type_, msg_iq, xhtml):
@ -1794,7 +1819,8 @@ class Connection(CommonConnection, ConnectionHandlers):
chatstate=chatstate, msg_id=msg_id, resource=resource,
user_nick=user_nick, xhtml=xhtml, label=label, session=session,
forward_from=forward_from, form_node=form_node,
original_message=original_message, delayed=delayed, callback=cb)
original_message=original_message, delayed=delayed,
attention=attention, callback=cb)
def _nec_message_outgoing(self, obj):
if obj.account != self.name:
@ -1819,7 +1845,7 @@ class Connection(CommonConnection, ConnectionHandlers):
resource=obj.resource, user_nick=obj.user_nick, xhtml=obj.xhtml,
label=obj.label, session=obj.session, forward_from=obj.forward_from,
form_node=obj.form_node, original_message=obj.original_message,
delayed=obj.delayed, callback=cb)
delayed=obj.delayed, attention=obj.attention, callback=cb)
def send_contacts(self, contacts, jid):
"""
@ -2289,7 +2315,8 @@ class Connection(CommonConnection, ConnectionHandlers):
room_id=resp.getTag('unique').getData()))
self.connection.SendAndCallForResponse(iq, _on_response)
def join_gc(self, nick, room_jid, password, change_nick=False):
def join_gc(self, nick, room_jid, password, change_nick=False,
rejoin=False):
# FIXME: This room JID needs to be normalized; see #1364
if not gajim.account_is_connected(self.name):
return
@ -2333,7 +2360,7 @@ class Connection(CommonConnection, ConnectionHandlers):
last_date = self.last_history_time[room_jid]
if last_date == 0:
last_date = time.time() - timeout
else:
elif not rejoin:
last_date = min(last_date, time.time() - timeout)
last_date = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime(
last_date))

View file

@ -6,7 +6,7 @@
## Copyright (C) 2006-2007 Tomasz Melcer <liori AT exroot.org>
## Travis Shirk <travis AT pobox.com>
## Nikos Kouremenos <kourem AT gmail.com>
## Copyright (C) 2006-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2006-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2007 Julien Pivotto <roidelapluie AT gmail.com>
## Copyright (C) 2007-2008 Brendan Taylor <whateley AT gmail.com>
## Jean-Marie Traissard <jim AT lapin.org>
@ -869,7 +869,7 @@ class ConnectionHandlersBase:
elif obj.contact.show in statuss:
obj.old_show = statuss.index(obj.contact.show)
if (resources != [''] and (len(obj.contact_list) != 1 or \
obj.contact_list[0].show != 'offline')) and \
obj.contact_list[0].show not in ('not in roster', 'offline'))) and \
not gajim.jid_is_transport(jid):
# Another resource of an existing contact connected
obj.old_show = 0
@ -897,7 +897,13 @@ class ConnectionHandlersBase:
obj.contact.show = obj.show
obj.contact.status = obj.status
obj.contact.priority = obj.prio
obj.contact.keyID = obj.keyID
attached_keys = gajim.config.get_per('accounts', account,
'attached_gpg_keys').split()
if jid in attached_keys:
obj.contact.keyID = attached_keys[attached_keys.index(jid) + 1]
else:
# Do not override assigned key
obj.contact.keyID = obj.keyID
if obj.timestamp:
obj.contact.last_status_time = obj.timestamp
elif not gajim.block_signed_in_notifications[account]:

View file

@ -1,7 +1,7 @@
# -*- coding:utf-8 -*-
## src/common/connection_handlers_events.py
##
## Copyright (C) 2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2010-2012 Yann Leboulanger <asterix AT lagaule.org>
##
## This file is part of Gajim.
##
@ -1017,15 +1017,20 @@ class MessageReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
return
self.jid = gajim.get_jid_without_resource(self.fjid)
forward_tag = self.stanza.getTag('forwarded', namespace=xmpp.NS_FORWARD)
carbon_marker = self.stanza.getTag('sent', namespace=xmpp.NS_CARBONS)
if not carbon_marker:
carbon_marker = self.stanza.getTag('received', namespace=xmpp.NS_CARBONS)
# Be sure it comes from one of our resource, else ignore forward element
if forward_tag and self.jid == gajim.get_jid_from_account(account):
received_tag = forward_tag.getTag('received',
namespace=xmpp.NS_CARBONS)
sent_tag = forward_tag.getTag('sent', namespace=xmpp.NS_CARBONS)
if received_tag:
if carbon_marker and self.jid == gajim.get_jid_from_account(account):
forward_tag = self.stanza.getTag('forwarded', namespace=xmpp.NS_FORWARD)
if forward_tag:
msg = forward_tag.getTag('message')
self.stanza = xmpp.Message(node=msg)
if carbon_marker.getName() == 'sent':
to = self.stanza.getTo()
self.stanza.setTo(self.stanza.getFrom())
self.stanza.setFrom(to)
self.sent = True
try:
self.get_jid_resource()
except helpers.InvalidFormat:
@ -1036,23 +1041,6 @@ class MessageReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
'has been ignored.')))
return
self.forwarded = True
elif sent_tag:
msg = forward_tag.getTag('message')
self.stanza = xmpp.Message(node=msg)
to = self.stanza.getTo()
self.stanza.setTo(self.stanza.getFrom())
self.stanza.setFrom(to)
try:
self.get_jid_resource()
except helpers.InvalidFormat:
gajim.nec.push_incoming_event(InformationEvent(None,
conn=self.conn, level='error',
pri_txt=_('Invalid Jabber ID'),
sec_txt=_('A message from a non-valid JID arrived, it '
'has been ignored.')))
return
self.forwarded = True
self.sent = True
self.enc_tag = self.stanza.getTag('x', namespace=xmpp.NS_ENCRYPTED)
@ -1205,6 +1193,7 @@ class DecryptedMessageReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
self.sent = self.msg_obj.sent
self.popup = False
self.msg_id = None # id in log database
self.attention = False # XEP-0224
self.receipt_request_tag = self.stanza.getTag('request',
namespace=xmpp.NS_RECEIPTS)
@ -1219,6 +1208,9 @@ class DecryptedMessageReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
if self.seclabel:
self.displaymarking = self.seclabel.getTag('displaymarking')
if self.stanza.getTag('attention', namespace=xmpp.NS_ATTENTION):
self.attention = True
self.form_node = self.stanza.getTag('x', namespace=xmpp.NS_DATA)
if gajim.config.get('ignore_incoming_xhtml'):
@ -1293,6 +1285,8 @@ class GcMessageReceivedEvent(nec.NetworkIncomingEvent):
if self.status_code != []:
gajim.nec.push_incoming_event(GcConfigChangedReceivedEvent(
None, conn=self.conn, msg_event=self))
if self.msg_obj.form_node:
return True
return
self.displaymarking = None
@ -2123,7 +2117,19 @@ class NotificationEvent(nec.NetworkIncomingEvent):
# we're online or chat
self.do_popup = True
if self.first_unread and helpers.allow_sound_notification(
if msg_obj.attention and not gajim.config.get(
'ignore_incoming_attention'):
self.popup_timeout = 0
self.do_popup = True
else:
self.popup_timeout = gajim.config.get('notification_timeout')
if msg_obj.attention and not gajim.config.get(
'ignore_incoming_attention') and gajim.config.get_per('soundevents',
'attention_received', 'enabled'):
self.sound_event = 'attention_received'
self.do_sound = True
elif self.first_unread and helpers.allow_sound_notification(
self.conn.name, 'first_message_received'):
self.do_sound = True
elif not self.first_unread and self.control_focused and \
@ -2236,6 +2242,8 @@ class NotificationEvent(nec.NetworkIncomingEvent):
self.popup_image = gtkgui_helpers.get_path_to_generic_or_avatar(
img_path, jid=self.jid, suffix=suffix)
self.popup_timeout = gajim.config.get('notification_timeout')
if event == 'status_change':
self.popup_title = _('%(nick)s Changed Status') % \
{'nick': gajim.get_name_from_jid(account, self.jid)}
@ -2280,6 +2288,7 @@ class NotificationEvent(nec.NetworkIncomingEvent):
self.popup_event_type = ''
self.popup_msg_type = ''
self.popup_image = ''
self.popup_timeout = -1
self.do_command = False
self.command = ''
@ -2322,6 +2331,7 @@ class MessageOutgoingEvent(nec.NetworkOutgoingEvent):
self.now = False
self.is_loggable = True
self.control = None
self.attention = False
def generate(self):
return True

View file

@ -4,7 +4,7 @@
## Copyright (C) 2006 Dimitur Kirov <dkirov AT gmail.com>
## Travis Shirk <travis AT pobox.com>
## Nikos Kouremenos <kourem AT gmail.com>
## Copyright (C) 2006-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2006-2012 Yann Leboulanger <asterix AT lagaule.org>
## Jean-Marie Traissard <jim AT lapin.org>
## Copyright (C) 2007 Lukas Petrovicky <lukas AT petrovicky.net>
## Tomasz Melcer <liori AT exroot.org>

View file

@ -3,7 +3,7 @@
## src/common/dataforms.py
##
## Copyright (C) 2006-2007 Tomasz Melcer <liori AT exroot.org>
## Copyright (C) 2006-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2006-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2007 Stephan Erb <steve-e AT h3c.de>
##
## This file is part of Gajim.

View file

@ -4,7 +4,7 @@
## Copyright (C) 2005 Andrew Sayman <lorien420 AT myrealbox.com>
## Dimitur Kirov <dkirov AT gmail.com>
## Copyright (C) 2005-2006 Nikos Kouremenos <kourem AT gmail.com>
## Copyright (C) 2005-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2005-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2006 Jean-Marie Traissard <jim AT lapin.org>
## Stefan Bethge <stefan AT lanpartei.de>
## Copyright (C) 2008 Jonathan Schleifer <js-gajim AT webkeks.org>

View file

@ -2,7 +2,7 @@
## src/common/defs.py
##
## Copyright (C) 2006 Nikos Kouremenos <kourem AT gmail.com>
## Copyright (C) 2006-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2006-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2006-2008 Jean-Marie Traissard <jim AT lapin.org>
## Copyright (C) 2007 Brendan Taylor <whateley AT gmail.com>
## Tomasz Melcer <liori AT exroot.org>
@ -27,12 +27,13 @@ docdir = '../'
basedir = '../'
localedir = '../po'
version = '0.15-beta3'
version = '0.15'
import subprocess
try:
node = subprocess.Popen('hg tip --template "{node|short}"', shell=True,
stdout=subprocess.PIPE).communicate()[0]
version += '-' + node
if node:
version += '-' + node
except Exception:
pass

View file

@ -27,6 +27,17 @@ These imports will not be delayed:
import __builtin__
_origimport = __import__
nothing = object()
try:
_origimport(__builtin__.__name__, {}, {}, None, -1)
except TypeError: # no level argument
def _import(name, globals, locals, fromlist, level):
"call _origimport with no level argument"
return _origimport(name, globals, locals, fromlist)
else:
_import = _origimport
class _demandmod(object):
"""module demand-loader and proxy"""
def __init__(self, name, globals, locals):
@ -50,7 +61,7 @@ class _demandmod(object):
h, t = p, None
if '.' in p:
h, t = p.split('.', 1)
if not hasattr(mod, h):
if getattr(mod, h, nothing) is nothing:
setattr(mod, h, _demandmod(p, mod.__dict__, mod.__dict__))
elif t:
subload(getattr(mod, h), t)
@ -78,20 +89,17 @@ class _demandmod(object):
self._load()
setattr(self._module, attr, val)
def _demandimport(name, globals=None, locals=None, fromlist=None, level=None):
def _demandimport(name, globals=None, locals=None, fromlist=None, level=-1):
if not locals or name in ignore or fromlist == ('*',):
# these cases we can't really delay
if level is None:
return _origimport(name, globals, locals, fromlist)
else:
return _origimport(name, globals, locals, fromlist, level)
return _import(name, globals, locals, fromlist, level)
elif not fromlist:
# import a [as b]
if '.' in name: # a.b
base, rest = name.split('.', 1)
# email.__init__ loading email.mime
if globals and globals.get('__name__', None) == base:
return _origimport(name, globals, locals, fromlist)
return _import(name, globals, locals, fromlist, level)
# if a is already demand-loaded, add b to its submodule list
if base in locals:
if isinstance(locals[base], _demandmod):
@ -99,19 +107,19 @@ def _demandimport(name, globals=None, locals=None, fromlist=None, level=None):
return locals[base]
return _demandmod(name, globals, locals)
else:
if level is not None:
if level != -1:
# from . import b,c,d or from .a import b,c,d
return _origimport(name, globals, locals, fromlist, level)
# from a import b,c,d
mod = _origimport(name, globals, locals)
# recurse down the module chain
for comp in name.split('.')[1:]:
if not hasattr(mod, comp):
if getattr(mod, comp, nothing) is nothing:
setattr(mod, comp, _demandmod(comp, mod.__dict__, mod.__dict__))
mod = getattr(mod, comp)
for x in fromlist:
# set requested submodules for demand load
if not hasattr(mod, x):
if getattr(mod, x, nothing) is nothing:
setattr(mod, x, _demandmod(x, mod.__dict__, locals))
return mod
@ -134,6 +142,8 @@ ignore = [
# raise ImportError if x not defined
'__main__',
'_ssl', # conditional imports in the stdlib, issue1964
'rfc822',
'mimetools',
]
def enable():

View file

@ -1,7 +1,7 @@
# -*- coding:utf-8 -*-
## src/common/dh.py
##
## Copyright (C) 2007-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2007-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2008 Brendan Taylor <whateley AT gmail.com>
##
## This file is part of Gajim.

View file

@ -3,7 +3,7 @@
##
## Copyright (C) 2006 Jean-Marie Traissard <jim AT lapin.org>
## Nikos Kouremenos <kourem AT gmail.com>
## Copyright (C) 2006-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2006-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2007 Julien Pivotto <roidelapluie AT gmail.com>
## Copyright (C) 2007-2008 Stephan Erb <steve-e AT h3c.de>
## Copyright (C) 2008 Brendan Taylor <whateley AT gmail.com>
@ -45,7 +45,7 @@ class Event:
where kind in error, incoming
file-*: file_props
gc_msg: None
printed_chat: control
printed_chat: [message, subject, control, msg_id]
printed_*: None
messages that are already printed in chat, but not read
gc-invitation: [room_jid, reason, password, is_continued]

View file

@ -2,7 +2,7 @@
## src/common/exceptions.py
##
## Copyright (C) 2005-2006 Nikos Kouremenos <kourem AT gmail.com>
## Copyright (C) 2005-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2005-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2006 Jean-Marie Traissard <jim AT lapin.org>
## Copyright (C) 2007 Brendan Taylor <whateley AT gmail.com>
##

View file

@ -2,7 +2,7 @@
## src/common/fuzzyclock.py
##
## Copyright (C) 2006 Christoph Neuroth <delmonico AT gmx.net>
## Copyright (C) 2006-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2006-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2007 Jean-Marie Traissard <jim AT lapin.org>
## Copyright (C) 2009 Benjamin Richter <br AT waldteufel-online.net>
##

View file

@ -1,7 +1,7 @@
# -*- coding:utf-8 -*-
## src/common/gajim.py
##
## Copyright (C) 2003-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2003-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2005-2006 Dimitur Kirov <dkirov AT gmail.com>
## Travis Shirk <travis AT pobox.com>
## Nikos Kouremenos <kourem AT gmail.com>
@ -171,21 +171,21 @@ else:
# read.
HAVE_LATEX = False
HAVE_FARSIGHT = True
HAVE_FARSTREAM = True
try:
farsight = __import__('farsight')
farstream = __import__('farstream')
import gst
import glib
try:
conference = gst.element_factory_make('fsrtpconference')
session = conference.new_session(farsight.MEDIA_TYPE_AUDIO)
session = conference.new_session(farstream.MEDIA_TYPE_AUDIO)
del session
del conference
except glib.GError:
HAVE_FARSIGHT = False
HAVE_FARSTREAM = False
except ImportError:
HAVE_FARSIGHT = False
HAVE_FARSTREAM = False
HAVE_UPNP_IGD = True
try:

View file

@ -27,6 +27,7 @@ Global Events Dispatcher module.
import traceback
from common.xmpp import NodeProcessed
import logging
log = logging.getLogger('gajim.c.ged')
@ -86,11 +87,16 @@ class GlobalEventsDispatcher(object):
def raise_event(self, event_name, *args, **kwargs):
log.debug('%s\nArgs: %s'%(event_name, str(args)))
if event_name in self.handlers:
node_processed = False
for priority, handler in self.handlers[event_name]:
try:
if handler(*args, **kwargs):
return True
except NodeProcessed:
node_processed = True
except Exception, e:
log.error('Error while running an even handler: %s' % \
handler)
traceback.print_exc()
if node_processed:
raise NodeProcessed

View file

@ -962,7 +962,7 @@ class Sign(object):
def handle_status(self, key, value):
if key in ("USERID_HINT", "NEED_PASSPHRASE", "BAD_PASSPHRASE",
"GOOD_PASSPHRASE", "BEGIN_SIGNING"):
"GOOD_PASSPHRASE", "BEGIN_SIGNING", "MISSING_PASSPHRASE"):
pass
elif key == "SIG_CREATED":
(self.type,

View file

@ -1,6 +1,6 @@
## src/common/gpg.py
##
## Copyright (C) 2003-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2003-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2005 Alex Mauer <hawke AT hawkesnest.net>
## Copyright (C) 2005-2006 Nikos Kouremenos <kourem AT gmail.com>
## Copyright (C) 2007 Stephan Erb <steve-e AT h3c.de>

View file

@ -1,7 +1,7 @@
# -*- coding:utf-8 -*-
## src/common/helpers.py
##
## Copyright (C) 2003-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2003-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2005-2006 Dimitur Kirov <dkirov AT gmail.com>
## Nikos Kouremenos <kourem AT gmail.com>
## Copyright (C) 2006 Alex Mauer <hawke AT hawkesnest.net>
@ -1330,7 +1330,7 @@ def update_optional_features(account = None):
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)
if gajim.HAVE_FARSIGHT:
if gajim.HAVE_FARSTREAM:
gajim.gajim_optional_features[a].append(xmpp.NS_JINGLE)
gajim.gajim_optional_features[a].append(xmpp.NS_JINGLE_RTP)
gajim.gajim_optional_features[a].append(xmpp.NS_JINGLE_RTP_AUDIO)
@ -1436,8 +1436,10 @@ def get_proxy_info(account):
if p:
proxy = {}
proxyptr = gajim.config.get_per('proxies', p)
if not proxyptr:
return proxy
for key in proxyptr.keys():
proxy[key] = proxyptr[key][1]
proxy[key] = proxyptr[key]
return proxy
def _get_img_direct(attrs):

View file

@ -1,7 +1,7 @@
# -*- coding:utf-8 -*-
## src/common/i18n.py
##
## Copyright (C) 2003-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2003-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2004 Vincent Hanquez <tab AT snarc.org>
## Copyright (C) 2005-2006 Nikos Kouremenos <kourem AT gmail.com>
## Copyright (C) 2009 Benjamin Richter <br AT waldteufel-online.net>

View file

@ -35,7 +35,7 @@ import helpers
import gajim
from jingle_session import JingleSession, JingleStates
if gajim.HAVE_FARSIGHT:
if gajim.HAVE_FARSTREAM:
from jingle_rtp import JingleAudio, JingleVideo
from jingle_ft import JingleFileTransfer
from jingle_transport import JingleTransportSocks5, JingleTransportIBB

View file

@ -21,7 +21,7 @@ import gobject
import socket
import xmpp
import farsight, gst
import farstream, gst
from glib import GError
import gajim
@ -42,8 +42,8 @@ class JingleRTPContent(JingleContent):
JingleContent.__init__(self, session, transport)
self.media = media
self._dtmf_running = False
self.farsight_media = {'audio': farsight.MEDIA_TYPE_AUDIO,
'video': farsight.MEDIA_TYPE_VIDEO}[media]
self.farstream_media = {'audio': farstream.MEDIA_TYPE_AUDIO,
'video': farstream.MEDIA_TYPE_VIDEO}[media]
self.pipeline = None
self.src_bin = None
@ -59,7 +59,7 @@ class JingleRTPContent(JingleContent):
self.callbacks['session-terminate'] += [self.__stop]
self.callbacks['session-terminate-sent'] += [self.__stop]
def setup_stream(self):
def setup_stream(self, on_src_pad_added):
# pipeline and bus
self.pipeline = gst.Pipeline()
bus = self.pipeline.get_bus()
@ -68,13 +68,12 @@ class JingleRTPContent(JingleContent):
# conference
self.conference = gst.element_factory_make('fsrtpconference')
self.conference.set_property('sdes-cname', self.session.ourjid)
self.pipeline.add(self.conference)
self.funnel = None
self.p2psession = self.conference.new_session(self.farsight_media)
self.p2psession = self.conference.new_session(self.farstream_media)
participant = self.conference.new_participant(self.session.peerjid)
participant = self.conference.new_participant()
# FIXME: Consider a workaround, here...
# pidgin and telepathy-gabble don't follow the XEP, and it won't work
# due to bad controlling-mode
@ -93,7 +92,9 @@ class JingleRTPContent(JingleContent):
params['stun-ip'] = ip
self.p2pstream = self.p2psession.new_stream(participant,
farsight.DIRECTION_RECV, 'nice', params)
farstream.DIRECTION_RECV)
self.p2pstream.connect('src-pad-added', on_src_pad_added)
self.p2pstream.set_transmitter('nice', params)
def is_ready(self):
return (JingleContent.is_ready(self) and self.candidates_ready)
@ -117,7 +118,7 @@ class JingleRTPContent(JingleContent):
# FIXME: connectivity should not be etablished yet
# Instead, it should be etablished after session-accept!
if self.sent:
self.p2pstream.set_remote_candidates(candidates)
self.p2pstream.add_remote_candidates(candidates)
def batch_dtmf(self, events):
"""
@ -140,15 +141,14 @@ class JingleRTPContent(JingleContent):
def _start_dtmf(self, event):
if event in ('*', '#'):
event = {'*': farsight.DTMF_EVENT_STAR,
'#': farsight.DTMF_EVENT_POUND}[event]
event = {'*': farstream.DTMF_EVENT_STAR,
'#': farstream.DTMF_EVENT_POUND}[event]
else:
event = int(event)
self.p2psession.start_telephony_event(event, 2,
farsight.DTMF_METHOD_RTP_RFC4733)
self.p2psession.start_telephony_event(event, 2)
def _stop_dtmf(self):
self.p2psession.stop_telephony_event(farsight.DTMF_METHOD_RTP_RFC4733)
self.p2psession.stop_telephony_event()
def _fill_content(self, content):
content.addChild(xmpp.NS_JINGLE_RTP + ' description',
@ -170,34 +170,33 @@ class JingleRTPContent(JingleContent):
if message.type == gst.MESSAGE_ELEMENT:
name = message.structure.get_name()
log.debug('gst element message: %s: %s' % (name, message))
if name == 'farsight-new-active-candidate-pair':
if name == 'farstream-new-active-candidate-pair':
pass
elif name == 'farsight-recv-codecs-changed':
elif name == 'farstream-recv-codecs-changed':
pass
elif name == 'farsight-codecs-changed':
if self.sent and self.p2psession.get_property('codecs-ready'):
elif name == 'farstream-codecs-changed':
if self.sent and self.p2psession.get_property('codecs'):
self.send_description_info()
elif name == 'farsight-local-candidates-prepared':
elif name == 'farstream-local-candidates-prepared':
self.candidates_ready = True
if self.is_ready():
self.session.on_session_state_changed(self)
elif name == 'farsight-new-local-candidate':
elif name == 'farstream-new-local-candidate':
candidate = message.structure['candidate']
self.transport.candidates.append(candidate)
if self.sent:
# FIXME: Is this case even possible?
self.send_candidate(candidate)
elif name == 'farsight-component-state-changed':
elif name == 'farstream-component-state-changed':
state = message.structure['state']
if state == farsight.STREAM_STATE_FAILED:
if state == farstream.STREAM_STATE_FAILED:
reason = xmpp.Node('reason')
reason.setTag('failed-transport')
self.session.remove_content(self.creator, self.name, reason)
elif name == 'farsight-error':
log.error('Farsight error #%d!\nMessage: %s\nDebug: %s' % (
elif name == 'farstream-error':
log.error('Farstream error #%d!\nMessage: %s' % (
message.structure['error-no'],
message.structure['error-msg'],
message.structure['debug-msg']))
message.structure['error-msg']))
elif message.type == gst.MESSAGE_ERROR:
# TODO: Fix it to fallback to videotestsrc anytime an error occur,
# or raise an error, Jingle way
@ -236,10 +235,10 @@ class JingleRTPContent(JingleContent):
def on_negotiated(self):
if self.accepted:
if self.transport.remote_candidates:
self.p2pstream.set_remote_candidates(self.transport.remote_candidates)
self.p2pstream.add_remote_candidates(self.transport.remote_candidates)
self.transport.remote_candidates = []
# TODO: farsight.DIRECTION_BOTH only if senders='both'
self.p2pstream.set_property('direction', farsight.DIRECTION_BOTH)
# TODO: farstream.DIRECTION_BOTH only if senders='both'
self.p2pstream.set_property('direction', farstream.DIRECTION_BOTH)
JingleContent.on_negotiated(self)
def __on_remote_codecs(self, stanza, content, error, action):
@ -252,8 +251,8 @@ class JingleRTPContent(JingleContent):
if not codec['id'] or not codec['name'] or not codec['clockrate']:
# ignore invalid payload-types
continue
c = farsight.Codec(int(codec['id']), codec['name'],
self.farsight_media, int(codec['clockrate']))
c = farstream.Codec(int(codec['id']), codec['name'],
self.farstream_media, int(codec['clockrate']))
if 'channels' in codec:
c.channels = int(codec['channels'])
else:
@ -318,7 +317,7 @@ class JingleAudio(JingleRTPContent):
self.out_volume.set_property('volume', vol)
def setup_stream(self):
JingleRTPContent.setup_stream(self)
JingleRTPContent.setup_stream(self, self._on_src_pad_added)
# Configure SPEEX
# Workaround for psi (not needed since rev
@ -326,10 +325,10 @@ class JingleAudio(JingleRTPContent):
# place 16kHz before 8kHz, as buggy psi versions will take in
# account only the first codec
codecs = [farsight.Codec(farsight.CODEC_ID_ANY, 'SPEEX',
farsight.MEDIA_TYPE_AUDIO, 16000),
farsight.Codec(farsight.CODEC_ID_ANY, 'SPEEX',
farsight.MEDIA_TYPE_AUDIO, 8000)]
codecs = [farstream.Codec(farstream.CODEC_ID_ANY, 'SPEEX',
farstream.MEDIA_TYPE_AUDIO, 16000),
farstream.Codec(farstream.CODEC_ID_ANY, 'SPEEX',
farstream.MEDIA_TYPE_AUDIO, 8000)]
self.p2psession.set_codec_preferences(codecs)
# the local parts
@ -348,9 +347,8 @@ class JingleAudio(JingleRTPContent):
self.src_bin.get_pad('src').link(self.p2psession.get_property(
'sink-pad'))
self.p2pstream.connect('src-pad-added', self._on_src_pad_added)
# The following is needed for farsight to process ICE requests:
# The following is needed for farstream to process ICE requests:
self.pipeline.set_state(gst.STATE_PLAYING)
@ -363,7 +361,7 @@ class JingleVideo(JingleRTPContent):
# TODO: Everything is not working properly:
# sometimes, one window won't show up,
# sometimes it'll freeze...
JingleRTPContent.setup_stream(self)
JingleRTPContent.setup_stream(self, self._on_src_pad_added)
# the local parts
if gajim.config.get('video_framerate'):
@ -395,9 +393,8 @@ class JingleVideo(JingleRTPContent):
self.src_bin.get_pad('src').link(self.p2psession.get_property(
'sink-pad'))
self.p2pstream.connect('src-pad-added', self._on_src_pad_added)
# The following is needed for farsight to process ICE requests:
# The following is needed for farstream to process ICE requests:
self.pipeline.set_state(gst.STATE_PLAYING)
def get_fallback_src(self):

View file

@ -323,7 +323,7 @@ class JingleTransportIBB(JingleTransport):
return transport
try:
import farsight
import farstream
except Exception:
pass
@ -332,11 +332,11 @@ class JingleTransportICEUDP(JingleTransport):
JingleTransport.__init__(self, TransportType.ICEUDP)
def make_candidate(self, candidate):
types = {farsight.CANDIDATE_TYPE_HOST: 'host',
farsight.CANDIDATE_TYPE_SRFLX: 'srflx',
farsight.CANDIDATE_TYPE_PRFLX: 'prflx',
farsight.CANDIDATE_TYPE_RELAY: 'relay',
farsight.CANDIDATE_TYPE_MULTICAST: 'multicast'}
types = {farstream.CANDIDATE_TYPE_HOST: 'host',
farstream.CANDIDATE_TYPE_SRFLX: 'srflx',
farstream.CANDIDATE_TYPE_PRFLX: 'prflx',
farstream.CANDIDATE_TYPE_RELAY: 'relay',
farstream.CANDIDATE_TYPE_MULTICAST: 'multicast'}
attrs = {
'component': candidate.component_id,
'foundation': '1', # hack
@ -348,7 +348,7 @@ class JingleTransportICEUDP(JingleTransport):
}
if candidate.type in types:
attrs['type'] = types[candidate.type]
if candidate.proto == farsight.NETWORK_PROTOCOL_UDP:
if candidate.proto == farstream.NETWORK_PROTOCOL_UDP:
attrs['protocol'] = 'udp'
else:
# we actually don't handle properly different tcp options in jingle
@ -367,29 +367,29 @@ class JingleTransportICEUDP(JingleTransport):
def parse_transport_stanza(self, transport):
candidates = []
for candidate in transport.iterTags('candidate'):
cand = farsight.Candidate()
cand = farstream.Candidate()
cand.component_id = int(candidate['component'])
cand.ip = str(candidate['ip'])
cand.port = int(candidate['port'])
cand.foundation = str(candidate['foundation'])
#cand.type = farsight.CANDIDATE_TYPE_LOCAL
#cand.type = farstream.CANDIDATE_TYPE_LOCAL
cand.priority = int(candidate['priority'])
if candidate['protocol'] == 'udp':
cand.proto = farsight.NETWORK_PROTOCOL_UDP
cand.proto = farstream.NETWORK_PROTOCOL_UDP
else:
# we actually don't handle properly different tcp options in jingle
cand.proto = farsight.NETWORK_PROTOCOL_TCP
cand.proto = farstream.NETWORK_PROTOCOL_TCP
cand.username = str(transport['ufrag'])
cand.password = str(transport['pwd'])
#FIXME: huh?
types = {'host': farsight.CANDIDATE_TYPE_HOST,
'srflx': farsight.CANDIDATE_TYPE_SRFLX,
'prflx': farsight.CANDIDATE_TYPE_PRFLX,
'relay': farsight.CANDIDATE_TYPE_RELAY,
'multicast': farsight.CANDIDATE_TYPE_MULTICAST}
types = {'host': farstream.CANDIDATE_TYPE_HOST,
'srflx': farstream.CANDIDATE_TYPE_SRFLX,
'prflx': farstream.CANDIDATE_TYPE_PRFLX,
'relay': farstream.CANDIDATE_TYPE_RELAY,
'multicast': farstream.CANDIDATE_TYPE_MULTICAST}
if 'type' in candidate and candidate['type'] in types:
cand.type = types[candidate['type']]
else:

View file

@ -5,7 +5,7 @@
## Copyright (C) 2005-2006 Alex Mauer <hawke AT hawkesnest.net>
## Travis Shirk <travis AT pobox.com>
## Copyright (C) 2005-2007 Nikos Kouremenos <kourem AT gmail.com>
## Copyright (C) 2005-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2005-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2006 Dimitur Kirov <dkirov AT gmail.com>
## Copyright (C) 2006-2008 Jean-Marie Traissard <jim AT lapin.org>
## Copyright (C) 2008 Jonathan Schleifer <js-gajim AT webkeks.org>
@ -59,8 +59,21 @@ def check_blacklist(str_):
def get_tmpfile_name():
random.seed()
int_ = random.randint(0, 100)
return os.path.join(gettempdir(), 'gajimtex_' + int_.__str__())
nb = 0
while(nb < 100):
int_ = random.randint(0, 10000)
filename = os.path.join(gettempdir(), 'gajimtex_' + int_.__str__())
# Check if a file to not overwrite it
ok = True
extensions = ['.tex', '.log', '.aux', '.dvi']
for ext in extensions:
if os.path.exists(filename + ext):
ok = False
break
if ok:
return filename
nb += 1
return filename
def write_latex(filename, str_):
texstr = '\\documentclass[12pt]{article}\\usepackage[dvips]{graphicx}'

View file

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
## src/common/location_listener.py
##
## Copyright (C) 2009-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2009-2012 Yann Leboulanger <asterix AT lagaule.org>
##
## This file is part of Gajim.
##

View file

@ -1,7 +1,7 @@
# -*- coding:utf-8 -*-
## src/common/logger.py
##
## Copyright (C) 2003-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2003-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2004-2005 Vincent Hanquez <tab AT snarc.org>
## Copyright (C) 2005-2006 Nikos Kouremenos <kourem AT gmail.com>
## Copyright (C) 2006 Dimitur Kirov <dkirov AT gmail.com>
@ -34,6 +34,7 @@ import time
import datetime
from gzip import GzipFile
from cStringIO import StringIO
import gobject
import exceptions
import gajim
@ -106,6 +107,7 @@ class Logger:
def __init__(self):
self.jids_already_in = [] # holds jids that we already have in DB
self.con = None
self.commit_timout_id = None
if not os.path.exists(LOG_DB_PATH):
# this can happen only the first time (the time we create the db)
@ -163,15 +165,25 @@ class Logger:
self.open_db()
self.get_jids_already_in_db()
def _really_commit(self):
try:
self.con.commit()
except sqlite.OperationalError, e:
print >> sys.stderr, str(e)
self.commit_timout_id = None
return False
def _timeout_commit(self):
if self.commit_timout_id:
return
self.commit_timout_id = gobject.timeout_add(500, self._really_commit)
def simple_commit(self, sql_to_commit):
"""
Helper to commit
"""
self.cur.execute(sql_to_commit)
try:
self.con.commit()
except sqlite.OperationalError, e:
print >> sys.stderr, str(e)
self._timeout_commit()
def get_jids_already_in_db(self):
try:
@ -398,12 +410,14 @@ class Logger:
except sqlite.OperationalError, e:
raise exceptions.PysqliteOperationalError(str(e))
message_id = None
try:
self.con.commit()
if write_unread:
if write_unread:
try:
self.con.commit()
message_id = self.cur.lastrowid
except sqlite.OperationalError, e:
print >> sys.stderr, str(e)
except sqlite.OperationalError, e:
print >> sys.stderr, str(e)
else:
self._timeout_commit()
if message_id:
self.insert_unread_events(message_id, values[0])
return message_id
@ -922,10 +936,7 @@ class Logger:
VALUES (?, ?, ?, ?);
''', (hash_method, hash_, buffer(data), int(time.time())))
# (1) -- note above
try:
self.con.commit()
except sqlite.OperationalError, e:
print >> sys.stderr, str(e)
self._timeout_commit()
def update_caps_time(self, method, hash_):
sql = '''UPDATE caps_cache SET last_seen = %d
@ -963,9 +974,9 @@ class Logger:
# Fill roster tables with the new roster
for jid in roster:
self.add_or_update_contact(account_jid, jid, roster[jid]['name'],
roster[jid]['subscription'], roster[jid]['ask'],
roster[jid]['groups'], commit=False)
self.con.commit()
roster[jid]['subscription'], roster[jid]['ask'],
roster[jid]['groups'], commit=False)
self._timeout_commit()
# At this point, we are sure the replacement works properly so we can
# set the new roster_version value.
@ -987,7 +998,7 @@ class Logger:
self.cur.execute(
'DELETE FROM roster_entry WHERE account_jid_id=? AND jid_id=?',
(account_jid_id, jid_id))
self.con.commit()
self._timeout_commit()
def add_or_update_contact(self, account_jid, jid, name, sub, ask, groups,
commit=True):
@ -1022,7 +1033,7 @@ class Logger:
self.convert_human_subscription_values_to_db_api_values(sub),
bool(ask)))
if commit:
self.con.commit()
self._timeout_commit()
def get_roster(self, account_jid):
"""
@ -1075,7 +1086,7 @@ class Logger:
(account_jid_id,))
self.cur.execute('DELETE FROM roster_group WHERE account_jid_id=?',
(account_jid_id,))
self.con.commit()
self._timeout_commit()
def save_if_not_exists(self, with_, direction, tim, msg='', nick=None):
if tim:

View file

@ -2,7 +2,7 @@
## src/common/optparser.py
##
## Copyright (C) 2003-2005 Vincent Hanquez <tab AT snarc.org>
## Copyright (C) 2003-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2003-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2005-2006 Dimitur Kirov <dkirov AT gmail.com>
## Nikos Kouremenos <kourem AT gmail.com>
## Copyright (C) 2006-2008 Jean-Marie Traissard <jim AT lapin.org>
@ -50,7 +50,7 @@ class OptionsParser:
except Exception:
if os.path.exists(self.__filename):
#we talk about a file
print _('error: cannot open %s for reading') % self.__filename
print _('Error: cannot open %s for reading') % self.__filename
return False
new_version = gajim.config.get('version')
@ -85,7 +85,6 @@ class OptionsParser:
def write_line(self, fd, opt, parents, value):
if value is None:
return
value = value[1]
# convert to utf8 before writing to file if needed
if isinstance(value, unicode):
value = value.encode('utf-8')

View file

@ -3,7 +3,7 @@
##
## Copyright (C) 2006 Gustavo J. A. M. Carneiro <gjcarneiro AT gmail.com>
## Nikos Kouremenos <kourem AT gmail.com>
## Copyright (C) 2006-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2006-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2007 Jean-Marie Traissard <jim AT lapin.org>
## Julien Pivotto <roidelapluie AT gmail.com>
## Copyright (C) 2008 Stephan Erb <steve-e AT h3c.de>
@ -63,7 +63,7 @@ class GnomePasswordStorage(PasswordStorage):
def __init__(self):
self.keyring = gnomekeyring.get_default_keyring_sync()
if self.keyring is None:
self.keyring = 'default'
self.keyring = 'login'
try:
gnomekeyring.create_sync(self.keyring, None)
except gnomekeyring.AlreadyExistsError:

View file

@ -2,7 +2,7 @@
## src/common/pep.py
##
## Copyright (C) 2007 Piotr Gaczkowski <doomhammerng AT gmail.com>
## Copyright (C) 2007-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2007-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2008 Brendan Taylor <whateley AT gmail.com>
## Jean-Marie Traissard <jim AT lapin.org>
## Jonathan Schleifer <js-common.gajim AT webkeks.org>

View file

@ -6,7 +6,7 @@
## Copyright (C) 2006-2007 Tomasz Melcer <liori AT exroot.org>
## Travis Shirk <travis AT pobox.com>
## Nikos Kouremenos <kourem AT gmail.com>
## Copyright (C) 2006-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2006-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2007 Julien Pivotto <roidelapluie AT gmail.com>
## Copyright (C) 2007-2008 Brendan Taylor <whateley AT gmail.com>
## Jean-Marie Traissard <jim AT lapin.org>

View file

@ -3,7 +3,7 @@
##
## Copyright (C) 2006 Dimitur Kirov <dkirov AT gmail.com>
## Jean-Marie Traissard <jim AT lapin.org>
## Copyright (C) 2007-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2007-2012 Yann Leboulanger <asterix AT lagaule.org>
##
## This file is part of Gajim.
##

View file

@ -2,7 +2,7 @@
## src/common/pubsub.py
##
## Copyright (C) 2006 Tomasz Melcer <liori AT exroot.org>
## Copyright (C) 2006-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2006-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2007 Jean-Marie Traissard <jim AT lapin.org>
## Copyright (C) 2008 Stephan Erb <steve-e AT h3c.de>
##

View file

@ -3,7 +3,7 @@
##
## Copyright (C) 2006 Santiago Gala
## Nikos Kouremenos <kourem AT gmail.com>
## Copyright (C) 2006-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2006-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2007 Jean-Marie Traissard <jim AT lapin.org>
##
## This file is part of Gajim.

View file

@ -1,7 +1,7 @@
# -*- coding:utf-8 -*-
## src/common/sleepy.py
##
## Copyright (C) 2003-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2003-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2005-2006 Nikos Kouremenos <kourem AT gmail.com>
## Copyright (C) 2007 Jean-Marie Traissard <jim AT lapin.org>
## Copyright (C) 2008 Mateusz Biliński <mateusz AT bilinski.it>

View file

@ -3,7 +3,7 @@
##
## Copyright (C) 2005-2006 Dimitur Kirov <dkirov AT gmail.com>
## Nikos Kouremenos <kourem AT gmail.com>
## Copyright (C) 2005-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2005-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2006-2008 Jean-Marie Traissard <jim AT lapin.org>
## Copyright (C) 2008 Jonathan Schleifer <js-gajim AT webkeks.org>
##

View file

@ -1,7 +1,7 @@
# -*- coding:utf-8 -*-
## src/common/stanza_session.py
##
## Copyright (C) 2007-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2007-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2007 Julien Pivotto <roidelapluie AT gmail.com>
## Copyright (C) 2007-2008 Brendan Taylor <whateley AT gmail.com>
## Jean-Marie Traissard <jim AT lapin.org>
@ -99,7 +99,7 @@ class StanzaSession(object):
for event in gajim.events.get_events(self.conn.name, j, types=types):
# the event wasn't in this session
if (event.type_ == 'chat' and event.parameters[8] != self) or \
(event.type_ == 'printed_chat' and event.parameters[0].session != \
(event.type_ == 'printed_chat' and event.parameters[2].session != \
self):
continue

View file

@ -577,8 +577,19 @@ class NonBlockingNonSASL(PlugIn):
else:
log.warn("Secure methods unsupported, performing plain text \
authentication")
query.setTagData('password', self.password)
self._method = 'plain'
self._owner._caller.get_password(self._on_password, self._method)
return
resp = self.owner.Dispatcher.SendAndWaitForResponse(iq,
func=self._on_auth)
def _on_password(self, password):
self.password = '' if password is None else password
iq=Iq('set', NS_AUTH)
query = iq.getTag('query')
query.setTagData('username', self.user)
query.setTagData('resource', self.resource)
query.setTagData('password', self.password)
resp = self.owner.Dispatcher.SendAndWaitForResponse(iq,
func=self._on_auth)

View file

@ -530,6 +530,7 @@ class NonBlockingClient:
sm.set_owner(self)
self.Dispatcher.sm = sm
nb_bind.PlugIn(self)
self.on_auth(self, 'sasl')
return
nb_bind.PlugIn(self)

View file

@ -41,6 +41,7 @@ NS_ARCHIVE_MANAGE = NS_ARCHIVE + ':manage' # XEP-0136
NS_ARCHIVE_MANUAL = NS_ARCHIVE + ':manual' # XEP-0136
NS_ARCHIVE_PREF = NS_ARCHIVE + ':pref'
NS_ATOM = 'http://www.w3.org/2005/Atom'
NS_ATTENTION = 'urn:xmpp:attention:0' # XEP-0224
NS_AUTH = 'jabber:iq:auth'
NS_AVATAR = 'http://www.xmpp.org/extensions/xep-0084.html#ns-metadata'
NS_BIND = 'urn:ietf:params:xml:ns:xmpp-bind'

View file

@ -103,6 +103,7 @@ class Smacks():
self.uqueue.pop(0)
if stanza.getName() == 'resumed':
self.enabled = True
self.resuming = True
self.con.set_oldst()
if self.uqueue != []:
@ -114,6 +115,7 @@ class Smacks():
# Ask for service discovery, etc..
if stanza.getTag('item-not-found'):
self.resuming = False
self.enabled = False
# we need to bind a resource
self._owner.NonBlockingBind.resuming = False
self._owner._on_auth_bind(None)

View file

@ -2,7 +2,7 @@
## src/common/xmpp/stringprepare.py
##
## Copyright (C) 2001-2005 Twisted Matrix Laboratories
## Copyright (C) 2005-2011 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2005-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2006 Stefan Bethge <stefan AT lanpartei.de>
## Copyright (C) 2007 Jean-Marie Traissard <jim AT lapin.org>
##

View file

@ -451,8 +451,6 @@ class NonBlockingTLS(PlugIn):
try:
self._owner.ssl_fingerprint_sha1 = cert.digest('sha1')
self._owner.ssl_certificate = cert
if errnum == 0:
return True
self._owner.ssl_errnum = errnum
self._owner.ssl_cert_pem = OpenSSL.crypto.dump_certificate(
OpenSSL.crypto.FILETYPE_PEM, cert)

View file

@ -803,11 +803,19 @@ class ClientZeroconf:
def on_ok(_waitid):
# if timeout:
# self._owner.set_timeout(timeout)
to = stanza.getTo()
to = unicode(stanza.getTo())
to = gajim.get_jid_without_resource(to)
try:
item = self.roster[to]
except KeyError:
# Contact offline
item = None
conn = None
if to in self.recipient_to_hash:
conn = self.connections[self.recipient_to_hash[to]]
elif item['address'] in self.ip_to_hash:
elif item and item['address'] in self.ip_to_hash:
hash_ = self.ip_to_hash[item['address']]
if self.hash_to_port[hash_] == item['port']:
conn = self.connections[hash_]

View file

@ -7,7 +7,7 @@
## - Travis Shirk <travis@pobox.com>
## - Stefan Bethge <stefan@lanpartei.de>
##
## Copyright (C) 2003-2010 Yann Leboulanger <asterix@lagaule.org>
## Copyright (C) 2003-2012 Yann Leboulanger <asterix@lagaule.org>
## Copyright (C) 2003-2004 Vincent Hanquez <tab@snarc.org>
## Copyright (C) 2006 Nikos Kouremenos <nkour@jabber.org>
## Dimitur Kirov <dkirov@gmail.com>
@ -336,8 +336,8 @@ class ConnectionZeroconf(CommonConnection, ConnectionHandlersZeroconf):
def send_message(self, jid, msg, keyID, type_='chat', subject='',
chatstate=None, msg_id=None, resource=None, user_nick=None, xhtml=None,
label=None, session=None, forward_from=None, form_node=None,
original_message=None, delayed=None, callback=None, callback_args=[],
now=True):
original_message=None, delayed=None, attention=False, callback=None,
callback_args=[], now=True):
def on_send_ok(msg_id):
gajim.nec.push_incoming_event(MessageSentEvent(None, conn=self,
@ -370,7 +370,8 @@ class ConnectionZeroconf(CommonConnection, ConnectionHandlersZeroconf):
chatstate=chatstate, msg_id=msg_id, resource=resource,
user_nick=user_nick, xhtml=xhtml, session=session,
forward_from=forward_from, form_node=form_node,
original_message=original_message, delayed=delayed, callback=cb)
original_message=original_message, delayed=delayed,
attention=attention, callback=cb)
def _nec_message_outgoing(self, obj):
if obj.account != self.name:
@ -411,7 +412,7 @@ class ConnectionZeroconf(CommonConnection, ConnectionHandlersZeroconf):
resource=obj.resource, user_nick=obj.user_nick, xhtml=obj.xhtml,
label=obj.label, session=obj.session, forward_from=obj.forward_from,
form_node=obj.form_node, original_message=obj.original_message,
delayed=obj.delayed, callback=cb)
delayed=obj.delayed, attention=obj.attention, callback=cb)
def send_stanza(self, stanza):
# send a stanza untouched

View file

@ -2,7 +2,7 @@
## src/config.py
##
## Copyright (C) 2003-2005 Vincent Hanquez <tab AT snarc.org>
## Copyright (C) 2003-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2003-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2005 Alex Podaras <bigpod AT gmail.com>
## Stéphan Kochen <stephan AT kochen.nl>
## Copyright (C) 2005-2006 Dimitur Kirov <dkirov AT gmail.com>
@ -1485,8 +1485,7 @@ class ManageProxiesWindow:
gajim.config.del_per('proxies', old_name)
gajim.config.add_per('proxies', new_name)
for option in config:
gajim.config.set_per('proxies', new_name, option,
config[option][common.config.OPT_VAL])
gajim.config.set_per('proxies', new_name, option, config[option])
model.set_value(iter_, 0, new_name)
def on_proxytype_combobox_changed(self, widget):
@ -2116,7 +2115,7 @@ class AccountsWindow:
gajim.config.add_per('accounts', new_name)
old_config = gajim.config.get_per('accounts', old_name)
for opt in old_config:
gajim.config.set_per('accounts', new_name, opt, old_config[opt][1])
gajim.config.set_per('accounts', new_name, opt, old_config[opt])
gajim.config.del_per('accounts', old_name)
if self.current_account == old_name:
self.current_account = new_name
@ -3655,7 +3654,11 @@ class AccountCreationWizardWindow:
password = self.xml.get_object('password_entry').get_text().decode(
'utf-8')
jid = username + '@' + server
if anonymous:
jid = ''
else:
jid = username + '@'
jid += server
# check if jid is conform to RFC and stringprep it
try:
jid = helpers.parse_jid(jid)
@ -3803,23 +3806,24 @@ class AccountCreationWizardWindow:
self.back_button.show()
self.forward_button.show()
self.is_form = obj.is_form
empty_config = True
if obj.is_form:
dataform = dataforms.ExtendForm(node=obj.config)
self.data_form_widget = dataforms_widget.DataFormWidget(dataform)
empty_config = False
else:
self.data_form_widget = FakeDataForm(obj.config)
empty_config = True
for field in obj.config:
if field in ('key', 'instructions', 'x', 'registered'):
continue
empty_config = False
break
if empty_config:
self.forward_button.set_sensitive(False)
self.notebook.set_current_page(4) # show form page
return
self.data_form_widget.show_all()
self.xml.get_object('form_vbox').pack_start(self.data_form_widget)
if empty_config:
self.forward_button.set_sensitive(False)
self.notebook.set_current_page(4) # show form page
return
self.ssl_fingerprint = obj.ssl_fingerprint
self.ssl_cert = obj.ssl_cert
if obj.ssl_msg:
@ -4183,6 +4187,7 @@ class ManageSoundsWindow:
# NOTE: sounds_ui_names MUST have all items of
# sounds = gajim.config.get_per('soundevents') as keys
sounds_dict = {
'attention_received': _('Attention Message Received'),
'first_message_received': _('First Message Received'),
'next_message_received_focused': _('Next Message Received Focused'),
'next_message_received_unfocused':

View file

@ -5,7 +5,7 @@
## Copyright (C) 2005-2006 Alex Mauer <hawke AT hawkesnest.net>
## Travis Shirk <travis AT pobox.com>
## Copyright (C) 2005-2007 Nikos Kouremenos <kourem AT gmail.com>
## Copyright (C) 2005-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2005-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2006 Dimitur Kirov <dkirov AT gmail.com>
## Copyright (C) 2006-2008 Jean-Marie Traissard <jim AT lapin.org>
## Copyright (C) 2008 Jonathan Schleifer <js-gajim AT webkeks.org>
@ -925,6 +925,9 @@ class ConversationTextview(gobject.GObject):
childs[7].hide() # hide add to roster menuitem
if kind == 'xmpp':
id_ = childs[0].connect('activate', self.on_copy_link_activate,
'xmpp:' + text)
self.handlers[id_] = childs[0]
childs[2].hide() # copy mail address
childs[3].hide() # open mail composer
childs[4].hide() # jid section separator
@ -934,7 +937,8 @@ class ConversationTextview(gobject.GObject):
childs[6].hide() # join group chat
childs[7].hide() # add to roster
childs[0].hide() # copy link location
if kind != 'xmpp':
childs[0].hide() # copy link location
childs[1].hide() # open link in browser
menu.popup(None, None, None, event.button, event.time)

View file

@ -1,7 +1,7 @@
# -*- coding:utf-8 -*-
## src/dataforms_widget.py
##
## Copyright (C) 2003-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2003-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2006 Tomasz Melcer <liori AT exroot.org>
## Copyright (C) 2006-2007 Jean-Marie Traissard <jim AT lapin.org>
##

View file

@ -2,7 +2,7 @@
## src/dialogs.py
##
## Copyright (C) 2003-2005 Vincent Hanquez <tab AT snarc.org>
## Copyright (C) 2003-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2003-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2005 Alex Mauer <hawke AT hawkesnest.net>
## Copyright (C) 2005-2006 Dimitur Kirov <dkirov AT gmail.com>
## Travis Shirk <travis AT pobox.com>
@ -233,7 +233,7 @@ class PassphraseDialog:
cancelbutton.connect('clicked', self.on_cancelbutton_clicked)
self.xml.connect_signals(self)
self.window.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
self.window.set_transient_for(gajim.interface.roster.window)
self.window.show_all()
self.check = bool(checkbuttontext)
@ -1936,6 +1936,9 @@ class CommonInputDialog:
def on_cancelbutton_clicked(self, widget):
self.dialog.destroy()
def destroy(self):
self.dialog.destroy()
class InputDialog(CommonInputDialog):
"""
Class for Input dialog
@ -2464,8 +2467,9 @@ class JoinGroupchatWindow:
'groupchat.'))
return
nickname = self._nickname_entry.get_text().decode('utf-8')
server = self.server_comboboxentry.child.get_text().decode('utf-8')
room = self._room_jid_entry.get_text().decode('utf-8')
server = self.server_comboboxentry.child.get_text().decode('utf-8').\
strip()
room = self._room_jid_entry.get_text().decode('utf-8').strip()
room_jid = room + '@' + server
password = self._password_entry.get_text().decode('utf-8')
try:
@ -2740,7 +2744,7 @@ class ChangePasswordDialog:
class PopupNotificationWindow:
def __init__(self, event_type, jid, account, msg_type='',
path_to_image=None, title=None, text=None):
path_to_image=None, title=None, text=None, timeout=-1):
self.account = account
self.jid = jid
self.msg_type = msg_type
@ -2760,8 +2764,8 @@ class PopupNotificationWindow:
title = ''
event_type_label.set_markup(
'<span foreground="black" weight="bold">%s</span>' %
gobject.markup_escape_text(title))
'<span foreground="black" weight="bold">%s</span>' %
gobject.markup_escape_text(title))
# set colors [ http://www.pitt.edu/~nisg/cis/web/cgi/rgb.html ]
self.window.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse('black'))
@ -2771,25 +2775,25 @@ class PopupNotificationWindow:
path_to_image = gtkgui_helpers.get_icon_path('gajim-chat_msg_recv', 48)
if event_type == _('Contact Signed In'):
bg_color = 'limegreen'
bg_color = gajim.config.get('notif_signin_color')
elif event_type == _('Contact Signed Out'):
bg_color = 'red'
bg_color = gajim.config.get('notif_signout_color')
elif event_type in (_('New Message'), _('New Single Message'),
_('New Private Message'), _('New E-mail')):
bg_color = 'dodgerblue'
bg_color = gajim.config.get('notif_message_color')
elif event_type == _('File Transfer Request'):
bg_color = 'khaki'
bg_color = gajim.config.get('notif_ftrequest_color')
elif event_type == _('File Transfer Error'):
bg_color = 'firebrick'
bg_color = gajim.config.get('notif_fterror_color')
elif event_type in (_('File Transfer Completed'),
_('File Transfer Stopped')):
bg_color = 'yellowgreen'
_('File Transfer Stopped')):
bg_color = gajim.config.get('notif_ftcomplete_color')
elif event_type == _('Groupchat Invitation'):
bg_color = 'tan1'
bg_color = gajim.config.get('notif_invite_color')
elif event_type == _('Contact Changed Status'):
bg_color = 'thistle2'
bg_color = gajim.config.get('notif_status_color')
else: # Unknown event! Shouldn't happen but deal with it
bg_color = 'white'
bg_color = gajim.config.get('notif_other_color')
popup_bg_color = gtk.gdk.color_parse(bg_color)
close_button.modify_bg(gtk.STATE_NORMAL, popup_bg_color)
eventbox.modify_bg(gtk.STATE_NORMAL, popup_bg_color)
@ -2808,13 +2812,13 @@ class PopupNotificationWindow:
pos_y = gajim.config.get('notification_position_y')
if pos_y < 0:
pos_y = gtk.gdk.screen_height() - \
gajim.interface.roster.popups_notification_height + pos_y + 1
gajim.interface.roster.popups_notification_height + pos_y + 1
self.window.move(pos_x, pos_y)
xml.connect_signals(self)
self.window.show_all()
timeout = gajim.config.get('notification_timeout')
gobject.timeout_add_seconds(timeout, self.on_timeout)
if timeout > 0:
gobject.timeout_add_seconds(timeout, self.on_timeout)
def on_close_button_clicked(self, widget):
self.adjust_height_and_move_popup_notification_windows()
@ -5154,6 +5158,7 @@ class VoIPCallReceivedDialog(object):
session = gajim.connections[self.account].get_jingle_session(self.fjid,
self.sid)
if not session:
dialog.destroy()
return
if response == gtk.RESPONSE_YES:
#TODO: Ensure that ctrl.contact.resource == resource

View file

@ -3,7 +3,7 @@
##
## Copyright (C) 2005-2006 Stéphan Kochen <stephan AT kochen.nl>
## Copyright (C) 2005-2007 Nikos Kouremenos <kourem AT gmail.com>
## Copyright (C) 2005-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2005-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2006 Dimitur Kirov <dkirov AT gmail.com>
## Copyright (C) 2006-2008 Jean-Marie Traissard <jim AT lapin.org>
## Copyright (C) 2007 Stephan Erb <steve-e AT h3c.de>

View file

@ -5,7 +5,7 @@
## Julien Pivotto <roidelapluie AT gmail.com>
## Stefan Bethge <stefan AT lanpartei.de>
## Stephan Erb <steve-e AT h3c.de>
## Copyright (C) 2007-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2007-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2008 Jonathan Schleifer <js-gajim AT webkeks.org>
##
## This file is part of Gajim.
@ -49,12 +49,12 @@ class FeaturesWindow:
self.features = {
_('SSL certificate validation'): (self.pyopenssl_available,
_('A library used to validate server certificates to ensure a secure connection.'),
_('Requires python-pyopenssl.'),
_('Requires python-pyopenssl.')),
_('Requires python-pyopenssl > 0.12 and pyasn1.'),
_('Requires python-pyopenssl > 0.12 and pyasn1.')),
_('Bonjour / Zeroconf'): (self.zeroconf_available,
_('Serverless chatting with autodetected clients in a local network.'),
_('Requires python-avahi.'),
_('Requires pybonjour (http://o2s.csail.mit.edu/o2s-wiki/pybonjour).')),
_('Requires pybonjour and bonjour SDK running (http://developer.apple.com/opensource/).')),
_('Command line'): (self.dbus_available,
_('A script to control Gajim via commandline.'),
_('Requires python-dbus.'),
@ -103,9 +103,9 @@ class FeaturesWindow:
_('Generate XHTML output from RST code (see http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html).'),
_('Requires python-docutils.'),
_('Requires python-docutils.')),
_('Audio / Video'): (self.farsight_available,
_('Audio / Video'): (self.farstream_available,
_('Ability to start audio and video chat.'),
_('Requires python-farsight and gstreamer-plugins-bad.'),
_('Requires python-farstream and gstreamer-plugins-bad.'),
_('Feature not available under Windows.')),
_('UPnP-IGD'): (self.gupnp_igd_available,
_('Ability to request your router to forward port for file transfer.'),
@ -169,6 +169,11 @@ class FeaturesWindow:
try:
import OpenSSL.SSL
import OpenSSL.crypto
ver = OpenSSL.__version__
ver_l = [int(i) for i in ver.split('.')]
if ver_l < [0, 12]:
raise ImportError
import pyasn1
except Exception:
return False
return True
@ -253,8 +258,8 @@ class FeaturesWindow:
return False
return True
def farsight_available(self):
return gajim.HAVE_FARSIGHT
def farstream_available(self):
return gajim.HAVE_FARSTREAM
def gupnp_igd_available(self):
return gajim.HAVE_UPNP_IGD

View file

@ -1,7 +1,7 @@
# -*- coding:utf-8 -*-
## src/filetransfers_window.py
##
## Copyright (C) 2003-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2003-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2005-2006 Dimitur Kirov <dkirov AT gmail.com>
## Copyright (C) 2005-2007 Nikos Kouremenos <kourem AT gmail.com>
## Copyright (C) 2006 Travis Shirk <travis AT pobox.com>

View file

@ -3,7 +3,7 @@
##
## Copyright (C) 2005-2006 Dimitur Kirov <dkirov AT gmail.com>
## Nikos Kouremenos <kourem AT gmail.com>
## Copyright (C) 2005-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2005-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2006 Junglecow <junglecow AT gmail.com>
## Travis Shirk <travis AT pobox.com>
## Copyright (C) 2006-2008 Jean-Marie Traissard <jim AT lapin.org>

View file

@ -1,7 +1,7 @@
# -*- coding:utf-8 -*-
## src/gajim.py
##
## Copyright (C) 2003-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2003-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2004-2005 Vincent Hanquez <tab AT snarc.org>
## Copyright (C) 2005 Alex Podaras <bigpod AT gmail.com>
## Norman Rasmussen <norman AT rasmussen.co.za>
@ -233,12 +233,12 @@ else:
elif sysname in ('FreeBSD', 'OpenBSD', 'NetBSD'):
libc.setproctitle('gajim')
if gtk.pygtk_version < (2, 16, 0):
pritext = _('Gajim needs PyGTK 2.16 or above')
sectext = _('Gajim needs PyGTK 2.16 or above to run. Quiting...')
elif gtk.gtk_version < (2, 16, 0):
pritext = _('Gajim needs GTK 2.16 or above')
sectext = _('Gajim needs GTK 2.16 or above to run. Quiting...')
if gtk.pygtk_version < (2, 22, 0):
pritext = _('Gajim needs PyGTK 2.22 or above')
sectext = _('Gajim needs PyGTK 2.22 or above to run. Quiting...')
elif gtk.gtk_version < (2, 22, 0):
pritext = _('Gajim needs GTK 2.22 or above')
sectext = _('Gajim needs GTK 2.22 or above to run. Quiting...')
from common import check_paths

View file

@ -1,7 +1,7 @@
# -*- coding:utf-8 -*-
## src/gajim_themes_window.py
##
## Copyright (C) 2003-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2003-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2005-2006 Dimitur Kirov <dkirov AT gmail.com>
## Nikos Kouremenos <kourem AT gmail.com>
## Copyright (C) 2006 Jean-Marie Traissard <jim AT lapin.org>

View file

@ -1,7 +1,7 @@
# -*- coding:utf-8 -*-
## src/groupchat_control.py
##
## Copyright (C) 2003-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2003-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2005-2007 Nikos Kouremenos <kourem AT gmail.com>
## Copyright (C) 2006 Dimitur Kirov <dkirov AT gmail.com>
## Alex Mauer <hawke AT hawkesnest.net>
@ -212,7 +212,8 @@ class PrivateChatControl(ChatControl):
self.parent_win.redraw_tab(self)
self.update_ui()
def send_message(self, message, xhtml=None, process_commands=True):
def send_message(self, message, xhtml=None, process_commands=True,
attention=False):
"""
Call this method to send the message
"""
@ -237,7 +238,7 @@ class PrivateChatControl(ChatControl):
return
ChatControl.send_message(self, message, xhtml=xhtml,
process_commands=process_commands)
process_commands=process_commands, attention=attention)
def update_ui(self):
if self.contact.show == 'offline':
@ -1274,7 +1275,7 @@ class GroupchatControl(ChatControlBase):
gajim.gc_connected[obj.conn.name][self.room_jid]:
return
password = gajim.gc_passwords.get(self.room_jid, '')
obj.conn.join_gc(self.nick, self.room_jid, password)
obj.conn.join_gc(self.nick, self.room_jid, password, rejoin=True)
def _nec_decrypted_message_received(self, obj):
if obj.conn.name != self.account:
@ -1307,7 +1308,6 @@ class GroupchatControl(ChatControlBase):
self._update_banner_state_image()
if self.parent_win:
self.parent_win.redraw_tab(self)
gobject.idle_add(self.msg_textview.grab_focus)
def got_disconnected(self):
self.list_treeview.set_model(None)
@ -1351,7 +1351,7 @@ class GroupchatControl(ChatControlBase):
return False
password = gajim.gc_passwords.get(self.room_jid, '')
gajim.connections[self.account].join_gc(self.nick, self.room_jid,
password)
password, rejoin=True)
return True
def draw_roster(self):

View file

@ -1,7 +1,7 @@
# -*- coding:utf-8 -*-
## src/groups.py
##
## Copyright (C) 2006-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2006-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2006 Tomasz Melcer <liori AT exroot.org>
##
## This file is part of Gajim.

View file

@ -2,7 +2,7 @@
## src/gtkexcepthook.py
##
## Copyright (C) 2005-2006 Nikos Kouremenos <kourem AT gmail.com>
## Copyright (C) 2005-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2005-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2008 Stephan Erb <steve-e AT h3c.de>
##
## This file is part of Gajim.

View file

@ -1,7 +1,7 @@
# -*- coding:utf-8 -*-
## src/gtkgui_helpers.py
##
## Copyright (C) 2003-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2003-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2005-2006 Dimitur Kirov <dkirov AT gmail.com>
## Copyright (C) 2005-2007 Nikos Kouremenos <kourem AT gmail.com>
## Copyright (C) 2006 Travis Shirk <travis AT pobox.com>

View file

@ -1,7 +1,7 @@
# -*- coding:utf-8 -*-
## src/gajim.py
##
## Copyright (C) 2003-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2003-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2004-2005 Vincent Hanquez <tab AT snarc.org>
## Copyright (C) 2005 Alex Podaras <bigpod AT gmail.com>
## Norman Rasmussen <norman AT rasmussen.co.za>
@ -330,6 +330,16 @@ class Interface:
if gc_control and gc_control.autorejoin:
gc_control.autorejoin = False
def handle_event_gc_message(self, obj):
if not obj.stanza.getTag('body'): # no <body>
# It could be a voice request. See
# http://www.xmpp.org/extensions/xep-0045.html#voiceapprove
if obj.msg_obj.form_node:
dialogs.SingleMessageWindow(obj.conn.name, obj.fjid,
action='receive', from_whom=obj.fjid,
subject='', message='', resource='', session=None,
form_node=obj.msg_obj.form_node)
def handle_event_presence(self, obj):
# 'NOTIFY' (account, (jid, status, status message, resource,
# priority, # keyID, timestamp, contact_nickname))
@ -1490,6 +1500,7 @@ class Interface:
'fingerprint-error': [self.handle_event_fingerprint_error],
'gc-invitation-received': [self.handle_event_gc_invitation],
'gc-presence-received': [self.handle_event_gc_presence],
'gc-message-received': [self.handle_event_gc_message],
'gmail-notify': [self.handle_event_gmail_notify],
'gpg-password-required': [self.handle_event_gpg_password_required],
'gpg-trust-key': [self.handle_event_gpg_trust_key],
@ -1625,7 +1636,7 @@ class Interface:
return
if type_ == 'printed_chat':
ctrl = event.parameters[0]
ctrl = event.parameters[2]
elif type_ == 'chat':
session = event.parameters[8]
ctrl = session.control
@ -1663,7 +1674,7 @@ class Interface:
event = gajim.events.get_first_event(account, jid, type_)
if type_ == 'printed_pm':
ctrl = event.parameters[0]
ctrl = event.parameters[2]
elif type_ == 'pm':
session = event.parameters[8]

View file

@ -1,7 +1,7 @@
# -*- coding:utf-8 -*-
## src/gui_menu_builder.py
##
## Copyright (C) 2009-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2009-2012 Yann Leboulanger <asterix AT lagaule.org>
##
## This file is part of Gajim.
##
@ -272,8 +272,9 @@ control=None, gc_contact=None):
# Unsensitive many items when account is offline
if gajim.account_is_disconnected(account):
for widget in (start_chat_menuitem, rename_menuitem,
edit_groups_menuitem, send_file_menuitem, convert_to_gc_menuitem):
for widget in (start_chat_menuitem, rename_menuitem,
edit_groups_menuitem, send_file_menuitem, convert_to_gc_menuitem,
information_menuitem):
widget.set_sensitive(False)
if not show_start_chat:

View file

@ -4,7 +4,7 @@
## Copyright (C) 2006 Dimitur Kirov <dkirov AT gmail.com>
## Copyright (C) 2006-2007 Jean-Marie Traissard <jim AT lapin.org>
## Nikos Kouremenos <kourem AT gmail.com>
## Copyright (C) 2006-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2006-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2007 Stephan Erb <steve-e AT h3c.de>
## Copyright (C) 2008 Jonathan Schleifer <js-gajim AT webkeks.org>
##

View file

@ -1,7 +1,7 @@
# -*- coding:utf-8 -*-
## src/history_window.py
##
## Copyright (C) 2003-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2003-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2005 Vincent Hanquez <tab AT snarc.org>
## Copyright (C) 2005-2006 Nikos Kouremenos <kourem AT gmail.com>
## Copyright (C) 2006 Dimitur Kirov <dkirov AT gmail.com>

View file

@ -4,7 +4,7 @@
## Copyright (C) 2005 Gustavo J. A. M. Carneiro
## Copyright (C) 2006 Santiago Gala
## Copyright (C) 2006-2007 Jean-Marie Traissard <jim AT lapin.org>
## Copyright (C) 2006-2010 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2006-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2007 Nikos Kouremenos <kourem AT gmail.com>
## Copyright (C) 2008 Jonathan Schleifer <js-gajim AT webkeks.org>
## Julien Pivotto <roidelapluie AT gmail.com>

Some files were not shown because too many files have changed in this diff Show more