Changes in / [537d9b9:ba52ac5]


Ignore:
Files:
4 deleted
70 edited

Legend:

Unmodified
Added
Removed
  • .travis.yml

    r537d9b9 rba52ac5  
    33
    44script:
    5  - ./configure --pam=1 --ldap=1
     5 - ./configure
    66 - make check
    77 - BITLBEE_SKYPE=plugin dpkg-buildpackage -uc -us -d
     
    2929    - libpurple-dev
    3030    - check
    31     - libpam0g-dev
    32     - libldap2-dev
    3331  coverity_scan:
    3432    project:
     
    3634      description: "An IRC to other chat networks gateway"
    3735    notification_email: dx@dxzone.com.ar
    38     build_command_prepend: ./configure --otr=1 --debug=1 --pam=1 --ldap=1
     36    build_command_prepend: ./configure --otr=1 --debug=1
    3937    build_command: make
    4038    branch_pattern: coverity_scan
  • Makefile

    r537d9b9 rba52ac5  
    1010
    1111# Program variables
    12 objects = bitlbee.o dcc.o help.o ipc.o irc.o irc_im.o irc_cap.o irc_channel.o irc_commands.o irc_send.o irc_user.o irc_util.o nick.o $(OTR_BI) query.o root_commands.o set.o storage.o $(STORAGE_OBJS) auth.o $(AUTH_OBJS) unix.o conf.o log.o
     12objects = bitlbee.o dcc.o help.o ipc.o irc.o irc_im.o irc_cap.o irc_channel.o irc_commands.o irc_send.o irc_user.o irc_util.o nick.o $(OTR_BI) query.o root_commands.o set.o storage.o $(STORAGE_OBJS) unix.o conf.o log.o
    1313headers = $(wildcard $(_SRCDIR_)*.h $(_SRCDIR_)lib/*.h $(_SRCDIR_)protocols/*.h)
    1414subdirs = lib protocols
  • bitlbee.conf

    r537d9b9 rba52ac5  
    5252# AuthMode = Open
    5353
    54 ## AuthBackend
    55 ##
    56 ## By default, the authentication data for a user is stored in the storage
    57 ## backend. If you want to authenticate against another authentication system
    58 ## (e.g. ldap), you can specify that here.
    59 ##
    60 ## Beware that this disables password changes and causes passwords for the
    61 ## accounts people create to be stored in plain text instead of encrypted with
    62 ## their bitlbee password.
    63 ##
    64 ## Currently available backends:
    65 ##
    66 ## - storage (internal storage)
    67 ## - pam (Linux PAM authentication)
    68 ## - ldap (LDAP server configured in the openldap settings)
    69 #
    70 # AuthBackend = storage
    71 #
    72 
    7354## AuthPassword
    7455##
     
    8869## or
    8970# OperPassword = md5:I0mnZbn1t4R731zzRdDN2/pK7lRX
    90 
    91 ## AllowAccountAdd
    92 ##
    93 ## Whether to allow registered and identified users to add new accounts using
    94 ## 'account add'
    95 ##
    96 # AllowAccountAdd 1
    9771
    9872## HostName
  • bitlbee.h

    r537d9b9 rba52ac5  
    3636
    3737#define PACKAGE "BitlBee"
    38 #define BITLBEE_VERSION "3.4.2"
     38#define BITLBEE_VERSION "3.4.1"
    3939#define VERSION BITLBEE_VERSION
    4040#define BITLBEE_VER(a, b, c) (((a) << 16) + ((b) << 8) + (c))
    41 #define BITLBEE_VERSION_CODE BITLBEE_VER(3, 4, 2)
    42 #define BITLBEE_ABI_VERSION_CODE 1
     41#define BITLBEE_VERSION_CODE BITLBEE_VER(3, 4, 1)
    4342
    4443#define MAX_STRING 511
     
    134133#include "irc.h"
    135134#include "storage.h"
    136 #include "auth.h"
    137135#include "set.h"
    138136#include "nogaim.h"
     
    156154        conf_t *conf;
    157155        GList *storage; /* The first backend in the list will be used for saving */
    158         GList *auth;    /* Authentication backends */
    159156        char *helpfile;
    160157        int restart;
     
    173170gboolean root_command_add(const char *command, int params, void (*func)(irc_t *, char **args), int flags);
    174171gboolean cmd_identify_finish(gpointer data, gint fd, b_input_condition cond);
    175 void cmd_chat_list_finish(struct im_connection *ic);
    176172gboolean bitlbee_shutdown(gpointer data, gint fd, b_input_condition cond);
    177173
  • conf.c

    r537d9b9 rba52ac5  
    5555        conf->runmode = RUNMODE_INETD;
    5656        conf->authmode = AUTHMODE_OPEN;
    57         conf->auth_backend = NULL;
    5857        conf->auth_pass = NULL;
    5958        conf->oper_pass = NULL;
    60         conf->allow_account_add = 1;
    6159        conf->configdir = g_strdup(CONFIG);
    6260        conf->plugindir = g_strdup(PLUGINDIR);
     
    242240                                        conf->authmode = AUTHMODE_OPEN;
    243241                                }
    244                         } else if (g_strcasecmp(ini->key, "authbackend") == 0) {
    245                                 if (g_strcasecmp(ini->value, "storage") == 0) {
    246                                         conf->auth_backend = NULL;
    247                                 } else if (g_strcasecmp(ini->value, "pam") == 0 ||
    248                                          g_strcasecmp(ini->value, "ldap") == 0) {
    249                                         g_free(conf->auth_backend);
    250                                         conf->auth_backend = g_strdup(ini->value);
    251                                 } else {
    252                                         fprintf(stderr, "Invalid %s value: %s\n", ini->key, ini->value);
    253                                         return 0;
    254                                 }
    255242                        } else if (g_strcasecmp(ini->key, "authpassword") == 0) {
    256243                                g_free(conf->auth_pass);
     
    259246                                g_free(conf->oper_pass);
    260247                                conf->oper_pass = g_strdup(ini->value);
    261                         } else if (g_strcasecmp(ini->key, "allowaccountadd") == 0) {
    262                                 if (!is_bool(ini->value)) {
    263                                         fprintf(stderr, "Invalid %s value: %s\n", ini->key, ini->value);
    264                                         return 0;
    265                                 }
    266                                 conf->allow_account_add = bool2int(ini->value);
    267248                        } else if (g_strcasecmp(ini->key, "hostname") == 0) {
    268249                                g_free(conf->hostname);
  • conf.h

    r537d9b9 rba52ac5  
    3737        runmode_t runmode;
    3838        authmode_t authmode;
    39         char *auth_backend;
    4039        char *auth_pass;
    4140        char *oper_pass;
    42         int allow_account_add;
    4341        char *hostname;
    4442        char *configdir;
  • configure

    r537d9b9 rba52ac5  
    5454ssl=auto
    5555
    56 pam=0
    57 ldap=0
    58 
    5956pie=1
    6057
    6158arch=$(uname -s)
     59cpu=$(uname -m)
    6260
    6361GLIB_MIN_VERSION=2.16
     
    140138--rpc=0/1       Disable/enable RPC plugin interface     $rpc
    141139
    142 --pam=0/1       Disable/enable PAM authentication       $pam
    143 --ldap=0/1      Disable/enable LDAP authentication      $ldap
    144 
    145140--doc=0/1       Disable/enable help.txt generation      $doc
    146141--debug=0/1     Disable/enable debugging                $debug
     
    205200
    206201TARGET=$target
     202ARCH=$arch
     203CPU=$cpu
    207204
    208205INSTALL=install -p
     
    252249#define PIDFILE "$pidfile"
    253250#define IPCSOCKET "$ipcsocket"
     251#define ARCH "$arch"
     252#define CPU "$cpu"
    254253EOF
    255254
     
    349348fi
    350349
    351 if ! $PKG_CONFIG --version > /dev/null 2>/dev/null; then
    352         echo
    353         echo 'Cannot find pkg-config, aborting.'
    354         exit 1
    355 fi
    356 
    357 if $PKG_CONFIG glib-2.0; then
     350if $PKG_CONFIG --version > /dev/null 2>/dev/null && $PKG_CONFIG glib-2.0; then
    358351        if $PKG_CONFIG glib-2.0 --atleast-version=$GLIB_MIN_VERSION; then
    359352                cat<<EOF >>Makefile.settings
     
    648641done
    649642echo "STORAGE_OBJS="$STORAGE_OBJS >> Makefile.settings
    650 
    651 authobjs=
    652 authlibs=
    653 if [ "$pam" = 0 ]; then
    654         echo '#undef WITH_PAM' >> config.h
    655 else
    656         if ! echo '#include <security/pam_appl.h>' | $CC -E - >/dev/null 2>/dev/null; then
    657                 echo 'Cannot find libpam development libraries, aborting. (Install libpam0g-dev?)'
    658                 exit 1
    659         fi
    660         echo '#define WITH_PAM' >> config.h
    661         authobjs=$authobjs'auth_pam.o '
    662         authlibs=$authlibs'-lpam '
    663 fi
    664 if [ "$ldap" = 0 ]; then
    665         echo '#undef WITH_LDAP' >> config.h
    666 else
    667         if ! echo '#include <ldap.h>' | $CC -E - >/dev/null 2>/dev/null; then
    668                 echo 'Cannot find libldap development libraries, aborting. (Install libldap2-dev?)'
    669                 exit 1
    670         fi
    671         echo '#define WITH_LDAP' >> config.h
    672         authobjs=$authobjs'auth_ldap.o '
    673         authlibs=$authlibs'-lldap '
    674 fi
    675 echo AUTH_OBJS=$authobjs >> Makefile.settings
    676 echo EFLAGS+=$authlibs >> Makefile.settings
    677643
    678644if [ "$strip" = 0 ]; then
  • debian/bitlbee-common.postinst

    r537d9b9 rba52ac5  
    99
    1010CONFDIR=/var/lib/bitlbee/
     11
     12update-rc.d bitlbee defaults > /dev/null 2>&1
    1113
    1214## Load default option. Don't want to put this in debconf (yet?)
     
    6466fi
    6567
    66 if [ "$BITLBEE_UPGRADE_DONT_RESTART" != "1" -a  -n "$2" -a -x "/etc/init.d/bitlbee" ]; then
     68if [ "$BITLBEE_UPGRADE_DONT_RESTART" != "1" -a  -n "$2" ]; then
    6769        invoke-rc.d bitlbee restart
    6870fi
     
    9092fi
    9193
    92 #DEBHELPER#
     94if [ -z "$2" ]; then
     95        invoke-rc.d bitlbee start
     96fi
  • debian/bitlbee-common.postrm

    r537d9b9 rba52ac5  
    33set -e
    44
    5 if [ "$1" = "purge" ]; then
    6         rm -f /etc/default/bitlbee
    7         deluser --system bitlbee || true
    8         rm -rf /var/lib/bitlbee ## deluser doesn't seem to do this for homedirs in /var
     5[ "$1" = "purge" ] || exit 0
     6
     7if [ -e /usr/share/debconf/confmodule ]; then
     8        . /usr/share/debconf/confmodule;
     9        db_purge;
    910fi
    1011
    11 #DEBHELPER#
     12update-rc.d bitlbee remove > /dev/null 2>&1 || true
     13rm -f /etc/default/bitlbee
     14
     15deluser --system bitlbee || true
     16rm -rf /var/lib/bitlbee ## deluser doesn't seem to do this for homedirs in /var
  • debian/bitlbee-common.prerm

    r537d9b9 rba52ac5  
    1111                mv /usr/share/bitlbee/help.txt /usr/share/bitlbee/help.upgrading
    1212        fi
     13else
     14        invoke-rc.d bitlbee stop
    1315fi
    14 
    15 #DEBHELPER#
  • debian/bitlbee.prerm

    r537d9b9 rba52ac5  
    66        invoke-rc.d bitlbee stop
    77fi
    8 
    9 #DEBHELPER#
  • debian/changelog

    r537d9b9 rba52ac5  
    1 bitlbee (3.4.2-1) unstable; urgency=medium
    2 
    3   [ Jelmer Vernooij ]
    4   * Make the build reproducible by not encoding ARCH / CPU defines in
    5     the binary.
    6   * Fix Vcs-* control headers after migration to Git.
    7   * Don't start synopsis with an article.
    8   * Bump standards version to 3.9.8 (no changes).
    9   * Use dh_prep rather than deprecated 'dh_clean -k'.
    10 
    11   [ Wilmer van der Gaast ]
    12   * New upstream release.
    13 
    14  -- Wilmer van der Gaast <wilmer@gaast.net>  Sun, 12 Jun 2016 22:31:18 +0100
    15 
    161bitlbee (3.4.1-1) unstable; urgency=medium
    172
  • debian/control

    r537d9b9 rba52ac5  
    33Priority: optional
    44Maintainer: Wilmer van der Gaast <wilmer@gaast.net>
    5 Uploaders: Jelmer Vernooij <jelmer@debian.org>
    6 Standards-Version: 3.9.8
    7 Build-Depends: libglib2.0-dev (>= 2.4), libevent-dev, libgnutls28-dev | libgnutls-dev | gnutls-dev, po-debconf, libpurple-dev, libotr5-dev, debhelper (>= 6.0.7~), dh-systemd (>= 1.5) | debhelper (<< 9.20131227)
     5Uploaders: Jelmer Vernooij <jelmer@debian.org>
     6Standards-Version: 3.9.5
     7Build-Depends: libglib2.0-dev (>= 2.4), libevent-dev, libgnutls28-dev | libgnutls-dev | gnutls-dev, po-debconf, libpurple-dev, libotr5-dev, debhelper (>= 6.0.7~)
    88Homepage: http://www.bitlbee.org/
    9 Vcs-Git: https://github.com/bitlbee/bitlbee
    10 Vcs-Browser: https://github.com/bitlbee/bitlbee
     9Vcs-Bzr: http://code.bitlbee.org/bitlbee/
    1110
    1211Package: bitlbee
     
    1514Conflicts: bitlbee-libpurple
    1615Replaces: bitlbee-libpurple
    17 Description: IRC to other chat networks gateway (default version)
     16Description: An IRC to other chat networks gateway (default version)
    1817 This program can be used as an IRC server which forwards everything you
    1918 say to people on other chat networks: Jabber (which includes Google Talk
     
    2524Conflicts: bitlbee
    2625Replaces: bitlbee
    27 Description: IRC to other chat networks gateway (using libpurple)
     26Description: An IRC to other chat networks gateway (using libpurple)
    2827 This program can be used as an IRC server which forwards everything you
    2928 say to people on other chat networks: Jabber (which includes Google Talk
     
    4140Depends: ${misc:Depends}, net-tools, adduser
    4241Replaces: bitlbee
    43 Description: IRC to other chat networks gateway (common files/docs)
     42Description: An IRC to other chat networks gateway (common files/docs)
    4443 This program can be used as an IRC server which forwards everything you
    4544 say to people on other chat networks: Jabber (which includes Google Talk
     
    5251Architecture: all
    5352Depends: ${misc:Depends}, bitlbee (>= ${source:Version}) | bitlbee-libpurple (>= ${source:Version}), bitlbee (<< ${source:Version}.1~) | bitlbee-libpurple (<< ${source:Version}.1~), bitlbee-common (= ${source:Version})
    54 Description: IRC to other chat networks gateway (dev files)
     53Description: An IRC to other chat networks gateway (dev files)
    5554 This program can be used as an IRC server which forwards everything you
    5655 say to people on other chat networks: Jabber (which includes Google Talk
     
    6261Architecture: any
    6362Depends: ${misc:Depends}, ${shlibs:Depends}, bitlbee (= ${binary:Version}) | bitlbee-libpurple (= ${binary:Version}), bitlbee-common (= ${source:Version})
    64 Description: IRC to other chat networks gateway (OTR plugin)
     63Description: An IRC to other chat networks gateway (OTR plugin)
    6564 This program can be used as an IRC server which forwards everything you
    6665 say to people on other chat networks: Jabber (which includes Google Talk
     
    7473Depends: ${misc:Depends}, ${shlibs:Depends}, bitlbee (= ${binary:Version}) | bitlbee-libpurple (= ${binary:Version}), bitlbee-common (= ${source:Version})
    7574Recommends: skyped
    76 Description: IRC to other chat networks gateway (Skype plugin)
     75Description: An IRC to other chat networks gateway (Skype plugin)
    7776 This program can be used as an IRC server which forwards everything you
    7877 say to people on other chat networks: Jabber (which includes Google Talk
  • debian/rules

    r537d9b9 rba52ac5  
    4040CONFIGURE_OVERRIDES:=CPPFLAGS="$(CPPFLAGS)" CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)"
    4141
    42 HAS_DH_SYSTEMD:=$(shell dpkg-query -W -f='$${Status}' dh-systemd 2>/dev/null | grep -c "ok installed")
    43 
    4442build: build-stamp
    4543build-stamp:
     
    7472        dh_testdir
    7573        dh_testroot
    76         dh_prep
     74        dh_clean -k
    7775        dh_installdirs
    7876
     
    8280        $(MAKE) -C debian/build-native install-plugin-otr DESTDIR=`pwd`/debian/bitlbee-plugin-otr
    8381        $(MAKE) -C debian/build-native install-plugin-skype DESTDIR=`pwd`/debian/skyped
    84 
    85 ifeq ($(HAS_DH_SYSTEMD),1)
    86         $(MAKE) -C debian/build-native install-systemd DESTDIR=`pwd`/debian/bitlbee-common
    87 endif
    8882
    8983ifneq ($(BITLBEE_SKYPE),0)
     
    114108        for p in bitlbee bitlbee-libpurple bitlbee-dev bitlbee-plugin-otr; do rm -r debian/$$p/usr/share/doc/$$p && ln -s bitlbee-common debian/$$p/usr/share/doc/$$p || true; done
    115109        dh_installdebconf
    116 ifeq ($(HAS_DH_SYSTEMD),1)
    117         dh_systemd_enable
    118110        dh_installinit --init-script=bitlbee
    119         dh_systemd_start
    120 else
    121         dh_installinit --init-script=bitlbee
    122 endif
    123111        dh_installman
    124112        dh_lintian
  • doc/CHANGES

    r537d9b9 rba52ac5  
    33
    44https://github.com/bitlbee/bitlbee/commits/master
    5 
    6 Version 3.4.2:
    7 - irc:
    8   * Self-messages (messages sent by yourself from other IM clients), given
    9     support by the IM protocols and your IRC client. See this for details:
    10     https://wiki.bitlbee.org/SelfMessages
    11   * IRCv3.1 support and part of 3.2: cap-3.2, sasl-3.2, multi-prefix,
    12     away-notify, extended-join, userhost-in-names
    13   * Send numeric errors when failing to join a channel, to not confuse clients
    14   * Channel autojoins should be more reliable now.
    15 - jabber:
    16   * Carbons (XEP-0280), for self-message support. It's not widely supported
    17     by most public XMPP servers (easier if you host your own), but this will
    18     probably change in the next few years. Thanks kormat for the original patch.
    19   * Fix typing notifications between two bitlbee users or with gtalk users
    20   * Remove facebook XMPP code, point people at bitlbee-facebook.
    21   * Show groupchat kick/ban/leave reasons
    22   * SASL ANONYMOUS (XEP-0175), for "guest" logins, see "help set anonymous"
    23   * Hipchat: 'chat add hipchat "channel name"' now tries to guess the JID
    24 - purple:
    25   * Fix problems remembering SSL certificates as trusted
    26   * Fix /join #channel, which joined a differently named channel
    27   * Fix crash when doing "chat with" with skypeweb
    28   * Fix html entities appearing in some protocols
    29   * Fix setting away states in jabber, which failed silently
    30   * Implement notify_message UI op, to be able to show some error messages.
    31 - skype:
    32   * Show all messages as groupchats since we can't tell which ones are private.
    33   * This plugin is mostly-deprecated and mostly-broken but it's still useful
    34     for p2p-based groupchats, which aren't delivered over newer protocols.
    35     Everyone else should use the skypeweb purple plugin or msn instead.
    36 - msn:
    37   * Minor tweaks. Faster login, better error reporting, fixed add/remove.
    38     Still MSNP21. Disregard that "Next release!" in the previous release.
    39 - otr:
    40   * Don't use NOTICE for user messages (revmischa)
    41   * Fix crashes when using the jabber xmlconsole
    42   * A few minor fixes: color multiline messages, filter incoming color codes.
    43 - Packaging:
    44   * Show ./configure args in bitlbee -V, config.h and Makefile.settings
    45   * Allow setting the plugin dir in bitlbee.conf, for NixOS (anderspapitto)
    46   * Improved cross compiler support (gamaral)
    47 - Other important bugfixes:
    48   * Fix potential crashes when leaving temporary channels
    49   * Fix all sorts of crashing bugs when cancelling in-progress connections.
    50 
    51 Finished 19 Mar 2016
    525
    536Version 3.4.1:
  • doc/user-guide/commands.xml

    r537d9b9 rba52ac5  
    258258
    259259                        <para>
    260                                 Available actions: add, with, list. See <emphasis>help chat &lt;action&gt;</emphasis> for more information.
     260                                Available actions: add, with. See <emphasis>help chat &lt;action&gt;</emphasis> for more information.
    261261                        </para>
    262262
     
    264264
    265265                <bitlbee-command name="add">
    266                         <syntax>chat add &lt;account id&gt; &lt;room|!index&gt; [&lt;channel&gt;]</syntax>
     266                        <syntax>chat add &lt;account id&gt; &lt;room&gt; [&lt;channel&gt;]</syntax>
    267267
    268268                        <description>
     
    272272
    273273                                <para>
    274                                         After adding a room to your list, you can simply use the IRC /join command to enter the room. Also, you can tell BitlBee to automatically join the room when you log in. (<emphasis>channel &lt;channel&gt; set auto_join true</emphasis>)
     274                                        After adding a room to your list, you can simply use the IRC /join command to enter the room. Also, you can tell BitlBee to automatically join the room when you log in. (See <emphasis>chat set</emphasis>)
    275275                                </para>
    276276
     
    280280                        </description>
    281281
    282                 </bitlbee-command>
    283 
    284                 <bitlbee-command name="list">
    285                         <syntax>chat list &lt;account id&gt; [&lt;server&gt;]</syntax>
    286 
    287                         <description>
    288                                 <para>
    289                                         List existing chatrooms provided by an account. BitlBee needs this to propogate an internal list of chats. The existing chat can then be added with <emphasis>chat add</emphasis>, using the number in the index column after a "!" as a shortcut.
    290                                 </para>
    291                         </description>
    292 
    293                         <ircexample>
    294                                 <ircline nick="dx">chat list facebook</ircline>
    295                                 <ircline pre="1" nick="root">Index  Title                 Topic</ircline>
    296                                 <ircline pre="1" nick="root">    1  869891016470949       cool kids club</ircline>
    297                                 <ircline pre="1" nick="root">    2  457892181062459       uncool kids club</ircline>
    298                                 <ircline nick="root">2 facebook chatrooms</ircline>
    299                                 <ircline nick="dx">chat add facebook !1 #cool-kids-club</ircline>
    300                         </ircexample>
    301282                </bitlbee-command>
    302283
     
    307288                                <para>
    308289                                        While most <emphasis>chat</emphasis> subcommands are about named chatrooms, this command can be used to open an unnamed groupchat with one or more persons. This command is what <emphasis>/join #nickname</emphasis> used to do in older BitlBee versions.
    309                                 </para>
    310 
    311                                 <para>
    312                                         Another way to do this is to join to a new, empty channel with <emphasis>/join #newchannel</emphasis> and invite the first person with <emphasis>/invite nickname</emphasis>
    313290                                </para>
    314291                        </description>
     
    668645                        <para>
    669646                                When you're already connected to a BitlBee server and you connect (and identify) again, BitlBee will offer to migrate your existing session to the new connection. If for whatever reason you don't want this, you can disable this setting.
    670                         </para>
    671                 </description>
    672         </bitlbee-setting>
    673 
    674         <bitlbee-setting name="always_use_nicks" type="boolean" scope="channel">
    675                 <default>false</default>
    676 
    677                 <description>
    678                         <para>
    679                                 Jabber groupchat specific. This setting ensures that the nicks defined by the other members of a groupchat are used, instead of the username part of their JID. This only applies to groupchats where their real JID is known (either "non-anonymous" ones, or "semi-anonymous" from the point of view of the channel moderators)
    680                         </para>
    681 
    682                         <para>
    683                                 Enabling this may have the side effect of changing the nick of existing contacts, either in your buddy list or in other groupchats. If a contact is in multiple groupchats with different nicks, enabling this setting for all those would result in multiple nick changes when joining, and the order of those changes may vary.
    684                         </para>
    685 
    686                         <para>
    687                                 Note that manual nick changes done through the <emphasis>rename</emphasis> command always take priority
    688647                        </para>
    689648                </description>
     
    15321491                                and any modes they should have. The following statuses are currently
    15331492                                recognised: <emphasis>online</emphasis> (i.e. available, not
    1534                                 away), <emphasis>special</emphasis> (specific to the protocol),
    1535                                 <emphasis>away</emphasis>, and <emphasis>offline</emphasis>.
     1493                                away), <emphasis>special</emphasis>, <emphasis>away</emphasis>,
     1494                                and <emphasis>offline</emphasis>.
    15361495                        </para>
    15371496                       
     
    15391498                                If a status is followed by a valid channel mode character
    15401499                                (@, % or +), it will be given to users with that status.
    1541                                 For example, <emphasis>online@,special%,away+,offline</emphasis> 
     1500                                For example, <emphasis>online@,special%,away+,offline</emphasis>
    15421501                                will show all users in the channel. Online people will
    15431502                                have +o, people who are online but away will have +v,
     
    18581817        </bitlbee-command>
    18591818
    1860         <bitlbee-command name="plugins">
    1861                 <short-description>List all the external plugins and protocols</short-description>
    1862                 <syntax>plugins</syntax>
    1863 
    1864                 <description>
    1865                         <para>
    1866                                 This gives you a list of all the external plugins and protocols.
    1867                         </para>
    1868                 </description>
    1869 
    1870         </bitlbee-command>
    1871 
    18721819        <bitlbee-command name="qlist">
    18731820                <short-description>List all the unanswered questions root asked</short-description>
  • doc/user-guide/genhelp.py

    r537d9b9 rba52ac5  
    6565
    6666    # Actually normalize whitespace
    67     if 'pre' not in tag.attrib:
    68         tag.text = normalize(tag.text)
     67    tag.text = normalize(tag.text)
    6968    tag.tail = normalize(tag.tail)
    7069
  • doc/user-guide/misc.xml

    r537d9b9 rba52ac5  
    445445</sect1>
    446446
    447 <sect1 id="whatsnew030402">
    448 <title>New stuff in BitlBee 3.4.2</title>
    449 
    450 <simplelist>
    451         <member><emphasis>irc:</emphasis> Self-messages (messages sent by yourself from other IM clients), see <emphasis>help set self_messages</emphasis>. IRCv3.1 support and part of 3.2. Many important groupchat related bugfixes.</member>
    452         <member><emphasis>jabber:</emphasis> Carbons, see <emphasis>help set carbons</emphasis>. Removed facebook XMPP, use bitlbee-facebook instead. SASL ANONYMOUS login, see <emphasis>help set anonymous</emphasis>.</member>
    453         <member><emphasis>hipchat:</emphasis> Channels can now be added with <emphasis>chat add hipchat "channel name"</emphasis> which tries to guess the channel JID.</member>
    454         <member><emphasis>skype:</emphasis> Show all messages as groupchats since we can't tell which ones are private. This plugin is mostly-deprecated and mostly-broken, use the skypeweb purple plugin or msn instead.</member>
    455         <member><emphasis>purple:</emphasis> Fix problems remembering SSL certificates as trusted. Groupchat related fixes. Better error reporting. Fixed setting jabber away states.</member>
    456 </simplelist>
    457 
    458 <para>
    459         And lots of bugfixes / stability improvements. See the full changelog for details!
    460 </para>
    461 
    462 </sect1>
    463 
    464447</chapter>
  • init/bitlbee.service.in

    r537d9b9 rba52ac5  
    55[Service]
    66ExecStart=@sbindir@bitlbee -F -n
    7 KillMode=process
    87
    98[Install]
  • irc.h

    r537d9b9 rba52ac5  
    2929#define IRC_MAX_LINE 512
    3030#define IRC_MAX_ARGS 16
    31 #define IRC_WORD_WRAP 425
    3231
    3332#define IRC_LOGIN_TIMEOUT 60
     
    9392                           logging in, this may contain a password we should
    9493                           send to identify after USER/NICK are received. */
    95         char *auth_backend;
    9694
    9795        char umode[8];
  • irc_cap.c

    r537d9b9 rba52ac5  
    177177
    178178        } else if (g_strcasecmp(cmd[1], "END") == 0) {
    179                 if (!(irc->status & USTATUS_CAP_PENDING)) {
    180                         return;
    181                 }
    182179                irc->status &= ~USTATUS_CAP_PENDING;
    183180
  • irc_channel.c

    r537d9b9 rba52ac5  
    245245        ic->users = g_slist_insert_sorted(ic->users, icu, irc_channel_user_cmp);
    246246
    247         if (iu == ic->irc->user || iu == ic->irc->root) {
    248                 irc_channel_update_ops(ic, set_getstr(&ic->irc->b->set, "ops"));
    249         }
     247        irc_channel_update_ops(ic, set_getstr(&ic->irc->b->set, "ops"));
    250248
    251249        if (iu == ic->irc->user || ic->flags & IRC_CHANNEL_JOINED) {
  • irc_commands.c

    r537d9b9 rba52ac5  
    9797        /* just check the password here to be able to reply with useful numerics
    9898         * the actual identification will be handled later */
    99         status = auth_check_pass(irc, user, pass);
     99        status = storage_check_pass(user, pass);
    100100
    101101        if (status == STORAGE_OK) {
     
    767767static void irc_cmd_version(irc_t *irc, char **cmd)
    768768{
    769         irc_send_num(irc, 351, "%s-%s. %s :",
    770                      PACKAGE, BITLBEE_VERSION, irc->root->host);
     769        irc_send_num(irc, 351, "%s-%s. %s :%s/%s ",
     770                     PACKAGE, BITLBEE_VERSION, irc->root->host, ARCH, CPU);
    771771}
    772772
  • irc_im.c

    r537d9b9 rba52ac5  
    120120        }
    121121
     122        if ((irc->caps & CAP_AWAY_NOTIFY) &&
     123            ((bu->flags & BEE_USER_AWAY) != (old->flags & BEE_USER_AWAY) ||
     124             (bu->flags & BEE_USER_ONLINE) != (old->flags & BEE_USER_ONLINE))) {
     125                irc_send_away_notify(iu);
     126        }
     127
    122128        if ((bu->flags & BEE_USER_ONLINE) != (old->flags & BEE_USER_ONLINE)) {
    123129                if (bu->flags & BEE_USER_ONLINE) {
     
    147153
    148154        bee_irc_channel_update(irc, NULL, iu);
    149 
    150         /* If away-notify enabled, send status updates when:
    151          * Away or Online state changes
    152          * Status changes (e.g. "Away" to "Mobile")
    153          * Status message changes
    154          */
    155         if ((irc->caps & CAP_AWAY_NOTIFY) &&
    156             ((bu->flags & BEE_USER_AWAY) != (old->flags & BEE_USER_AWAY) ||
    157              (bu->flags & BEE_USER_ONLINE) != (old->flags & BEE_USER_ONLINE) ||
    158              (g_strcmp0(bu->status, old->status) != 0) ||
    159              (g_strcmp0(bu->status_msg, old->status_msg) != 0))) {
    160                 irc_send_away_notify(iu);
    161         }
    162155
    163156        return TRUE;
     
    299292        }
    300293
    301         wrapped = word_wrap(msg, IRC_WORD_WRAP);
     294        wrapped = word_wrap(msg, 425);
    302295        irc_send_msg(src_iu, message_type, dst, wrapped, prefix);
    303296        g_free(wrapped);
     
    349342}
    350343
    351 static gboolean bee_irc_user_nick_update(irc_user_t *iu, gboolean offline_only);
     344static gboolean bee_irc_user_nick_update(irc_user_t *iu);
    352345
    353346static gboolean bee_irc_user_fullname(bee_t *bee, bee_user_t *bu)
     
    377370        }
    378371
    379         bee_irc_user_nick_update(iu, TRUE);
     372        bee_irc_user_nick_update(iu);
    380373
    381374        return TRUE;
     
    384377static gboolean bee_irc_user_nick_hint(bee_t *bee, bee_user_t *bu, const char *hint)
    385378{
    386         bee_irc_user_nick_update((irc_user_t *) bu->ui_data, TRUE);
    387 
    388         return TRUE;
    389 }
    390 
    391 static gboolean bee_irc_user_nick_change(bee_t *bee, bee_user_t *bu, const char *nick)
    392 {
    393         bee_irc_user_nick_update((irc_user_t *) bu->ui_data, FALSE);
     379        bee_irc_user_nick_update((irc_user_t *) bu->ui_data);
    394380
    395381        return TRUE;
     
    400386        irc_user_t *iu = (irc_user_t *) bu->ui_data;
    401387        irc_t *irc = (irc_t *) bee->ui_data;
     388        bee_user_flags_t online;
     389
     390        /* Take the user offline temporarily so we can change the nick (if necessary). */
     391        if ((online = bu->flags & BEE_USER_ONLINE)) {
     392                bu->flags &= ~BEE_USER_ONLINE;
     393        }
    402394
    403395        bee_irc_channel_update(irc, NULL, iu);
    404         bee_irc_user_nick_update(iu, FALSE);
    405 
    406         return TRUE;
    407 }
    408 
    409 static gboolean bee_irc_user_nick_update(irc_user_t *iu, gboolean offline_only)
     396        bee_irc_user_nick_update(iu);
     397
     398        if (online) {
     399                bu->flags |= online;
     400                bee_irc_channel_update(irc, NULL, iu);
     401        }
     402
     403        return TRUE;
     404}
     405
     406static gboolean bee_irc_user_nick_update(irc_user_t *iu)
    410407{
    411408        bee_user_t *bu = iu->bu;
    412409        char *newnick;
    413410
    414         if (offline_only && bu->flags & BEE_USER_ONLINE) {
     411        if (bu->flags & BEE_USER_ONLINE) {
    415412                /* Ignore if the user is visible already. */
    416413                return TRUE;
     
    435432{
    436433        bee_user_t *bu = iu->bu;
     434        bee_user_flags_t online;
    437435
    438436        if (bu == FALSE) {
     
    440438        }
    441439
     440        /* In this case, pretend the user is offline. */
     441        if ((online = bu->flags & BEE_USER_ONLINE)) {
     442                bu->flags &= ~BEE_USER_ONLINE;
     443        }
     444
    442445        nick_del(bu);
    443         bee_irc_user_nick_update(iu, FALSE);
    444 
     446        bee_irc_user_nick_update(iu);
     447
     448        bu->flags |= online;
    445449}
    446450
     
    457461        }
    458462
    459         if (iu->last_channel == NULL &&
    460             (away = irc_user_get_away(iu)) &&
     463        if ((away = irc_user_get_away(iu)) &&
    461464            time(NULL) >= iu->away_reply_timeout) {
    462465                irc_send_num(iu->irc, 301, "%s :%s", iu->nick, away);
     
    673676        }
    674677
    675         wrapped = word_wrap(msg, IRC_WORD_WRAP);
     678        wrapped = word_wrap(msg, 425);
    676679        irc_send_msg(iu, "PRIVMSG", ic->name, wrapped, ts);
    677680        g_free(ts);
     
    11431146
    11441147        bee_irc_log,
    1145         bee_irc_user_nick_change,
    11461148};
  • irc_send.c

    r537d9b9 rba52ac5  
    4141{
    4242        irc_send_num(irc,   1, ":Welcome to the %s gateway, %s", PACKAGE, irc->user->nick);
    43         irc_send_num(irc,   2, ":Host %s is running %s %s.", irc->root->host,
    44                      PACKAGE, BITLBEE_VERSION);
     43        irc_send_num(irc,   2, ":Host %s is running %s %s %s/%s.", irc->root->host,
     44                     PACKAGE, BITLBEE_VERSION, ARCH, CPU);
    4545        irc_send_num(irc,   3, ":%s", IRCD_INFO);
    4646        irc_send_num(irc,   4, "%s %s %s %s", irc->root->host, BITLBEE_VERSION, UMODES UMODES_PRIV, CMODES);
     
    5454void irc_send_motd(irc_t *irc)
    5555{
    56         char *motd;
    57         size_t len;
    58 
    59         g_file_get_contents(global.conf->motdfile, &motd, &len, NULL);
    60 
    61         if (!motd || !len) {
     56        char motd[2048];
     57        ssize_t len;
     58        int fd;
     59
     60        fd = open(global.conf->motdfile, O_RDONLY);
     61        if (fd == -1 || (len = read(fd, motd, sizeof(motd) - 1)) <= 0) {
    6262                irc_send_num(irc, 422, ":We don't need MOTDs.");
    6363        } else {
     
    6666
    6767                in = motd;
     68                motd[len] = '\0';
    6869                linebuf[79] = len = 0;
    6970                max = sizeof(linebuf) - 1;
     
    100101        }
    101102
    102         g_free(motd);
    103 
     103        if (fd != -1) {
     104                close(fd);
     105        }
    104106}
    105107
     
    346348                }
    347349
    348                 /* If this is the account nick, check configuration to see if away */
    349                 if (iu == irc->user) {
    350                         /* rfc1459 doesn't mention this: G means gone, H means here */
    351                         status_prefix[0] = set_getstr(&irc->b->set, "away") ? 'G' : 'H';
    352                 } else {
    353                         status_prefix[0] = iu->flags & IRC_USER_AWAY ? 'G' : 'H';
    354                 }
     350                /* rfc1459 doesn't mention this: G means gone, H means here */
     351                status_prefix[0] = iu->flags & IRC_USER_AWAY ? 'G' : 'H';
    355352
    356353                irc_send_num(irc, 352, "%s %s %s %s %s %s :0 %s",
  • irc_user.c

    r537d9b9 rba52ac5  
    251251        if (g_strcasecmp(ctcp[0], "VERSION") == 0) {
    252252                irc_send_msg_f(iu, "NOTICE", iu->irc->user->nick, "\001%s %s\001",
    253                                ctcp[0], PACKAGE " " BITLBEE_VERSION);
     253                               ctcp[0], PACKAGE " " BITLBEE_VERSION " " ARCH "/" CPU);
    254254        } else if (g_strcasecmp(ctcp[0], "PING") == 0) {
    255255                irc_send_msg_f(iu, "NOTICE", iu->irc->user->nick, "\001%s %s\001",
  • lib/http_client.c

    r537d9b9 rba52ac5  
    9595        request = g_strdup_printf("GET %s HTTP/1.0\r\n"
    9696                                  "Host: %s\r\n"
    97                                   "User-Agent: BitlBee " BITLBEE_VERSION "\r\n"
     97                                  "User-Agent: BitlBee " BITLBEE_VERSION " " ARCH "/" CPU "\r\n"
    9898                                  "\r\n", url->file, url->host);
    9999
  • lib/misc.c

    r537d9b9 rba52ac5  
    549549}
    550550
     551/* Word wrapping. Yes, I know this isn't UTF-8 clean. I'm willing to take the risk. */
    551552char *word_wrap(const char *msg, int line_len)
    552553{
     
    581582                }
    582583                if (i == 0) {
    583                         const char *end;
    584                         size_t len;
    585 
    586                         g_utf8_validate(msg, line_len, &end);
    587 
    588                         len = (end != msg) ? end - msg : line_len;
    589 
    590                         g_string_append_len(ret, msg, len);
     584                        g_string_append_len(ret, msg, line_len);
    591585                        g_string_append_c(ret, '\n');
    592                         msg += len;
     586                        msg += line_len;
    593587                }
    594588        }
     
    793787        return string;
    794788}
    795 
    796 /* Returns a string that is exactly 'char_len' utf8 characters long (not bytes),
    797  * padded to the right with spaces or truncated with the 'ellipsis' parameter
    798  * if specified (can be NULL).
    799  * Returns a newly allocated string, or NULL on invalid parameters. */
    800 char *str_pad_and_truncate(const char *string, long char_len, const char *ellipsis)
    801 {
    802         size_t string_len = strlen(string);
    803         size_t ellipsis_len = (ellipsis) ? strlen(ellipsis) : 0;
    804         long orig_len = g_utf8_strlen(string, -1);
    805 
    806         g_return_val_if_fail(char_len > ellipsis_len, NULL);
    807 
    808         if (orig_len > char_len) {
    809                 char *ret = g_malloc(string_len + 1);
    810                 g_utf8_strncpy(ret, string, char_len - ellipsis_len);
    811                 if (ellipsis) {
    812                         g_strlcat(ret, ellipsis, string_len);
    813                 }
    814                 return ret;
    815         } else if (orig_len < char_len) {
    816                 return g_strdup_printf("%s%*s", string, (int) (char_len - orig_len), "");
    817         } else {
    818                 return g_strdup(string);
    819         }
    820 }
  • lib/misc.h

    r537d9b9 rba52ac5  
    151151G_MODULE_EXPORT gboolean parse_int64(char *string, int base, guint64 *number);
    152152G_MODULE_EXPORT char *str_reject_chars(char *string, const char *reject, char replacement);
    153 G_MODULE_EXPORT char *str_pad_and_truncate(const char *string, long char_len, const char *ellipsis);
    154153
    155154#endif
  • lib/proxy.c

    r537d9b9 rba52ac5  
    8787}
    8888
    89 /* calls phb->func safely by ensuring that the phb struct doesn't exist in the
    90  * case that proxy_disconnect() is called down there */
    91 static gboolean phb_connected(struct PHB *phb, gint source)
    92 {
    93         /* save func and data here */
    94         b_event_handler func = phb->func;
    95         gpointer data = phb->data;
    96 
    97         /* free the struct so that it can't be freed by the callback */
    98         phb_free(phb, TRUE);
    99 
    100         /* if any proxy_disconnect() call happens here, it will use the
    101          * fd (still open), look it up in the hash table, get NULL, and
    102          * proceed to close the fd and do nothing else */
    103         func(data, source, B_EV_IO_READ);
    104 
    105         return FALSE;
    106 }
    107 
    10889static gboolean proxy_connected(gpointer data, gint source, b_input_condition cond)
    10990{
     
    144125                phb->proxy_func(phb->proxy_data, source, B_EV_IO_READ);
    145126        } else {
    146                 phb_connected(phb, source);
     127                phb->func(phb->data, source, B_EV_IO_READ);
     128                phb_free(phb, TRUE);
    147129        }
    148130
     
    240222        if ((memcmp(HTTP_GOODSTRING, inputline, strlen(HTTP_GOODSTRING)) == 0) ||
    241223            (memcmp(HTTP_GOODSTRING2, inputline, strlen(HTTP_GOODSTRING2)) == 0)) {
    242                 return phb_connected(phb, source);
     224                phb->func(phb->data, source, B_EV_IO_READ);
     225                return phb_free(phb, TRUE);
    243226        }
    244227
     
    312295        memset(packet, 0, sizeof(packet));
    313296        if (read(source, packet, 9) >= 4 && packet[1] == 90) {
    314                 return phb_connected(phb, source);
     297                phb->func(phb->data, source, B_EV_IO_READ);
     298                return phb_free(phb, TRUE);
    315299        }
    316300
     
    400384        }
    401385
    402         return phb_connected(phb, source);
     386        phb->func(phb->data, source, B_EV_IO_READ);
     387        return phb_free(phb, TRUE);
    403388}
    404389
  • lib/sha1.c

    r537d9b9 rba52ac5  
    2424#define HMAC_BLOCK_SIZE 64
    2525
    26 void b_hmac(GChecksumType checksum_type, const char *key_, size_t key_len,
    27             const char *payload, size_t payload_len, guint8 **digest)
     26/* BitlBee addition: */
     27void sha1_hmac(const char *key_, size_t key_len, const char *payload, size_t payload_len, guint8 digest[SHA1_HASH_SIZE])
    2828{
    29         GChecksum *checksum;
    30         size_t hash_len;
    31         guint8 *hash;
     29        sha1_state_t sha1;
     30        guint8 hash[SHA1_HASH_SIZE];
    3231        guint8 key[HMAC_BLOCK_SIZE + 1];
    3332        int i;
    34 
    35         hash_len = g_checksum_type_get_length(checksum_type);
    36 
    37         if (hash_len == (size_t) -1) {
    38                 return;
    39         }
    40 
    41         hash = g_malloc(hash_len);
    4233
    4334        if (key_len == 0) {
     
    5243        memset(key, 0, HMAC_BLOCK_SIZE + 1);
    5344        if (key_len > HMAC_BLOCK_SIZE) {
    54                 checksum = g_checksum_new(checksum_type);
    55                 g_checksum_update(checksum, (guint8 *) key_, key_len);
    56                 g_checksum_get_digest(checksum, key, &hash_len);
    57                 g_checksum_free(checksum);
     45                sha1_init(&sha1);
     46                sha1_append(&sha1, (guint8 *) key_, key_len);
     47                sha1_finish(&sha1, key);
    5848        } else {
    5949                memcpy(key, key_, key_len);
     
    6151
    6252        /* Inner part: H(K XOR 0x36, text) */
    63         checksum = g_checksum_new(checksum_type);
     53        sha1_init(&sha1);
    6454        for (i = 0; i < HMAC_BLOCK_SIZE; i++) {
    6555                key[i] ^= 0x36;
    6656        }
    67         g_checksum_update(checksum, key, HMAC_BLOCK_SIZE);
    68         g_checksum_update(checksum, (const guint8 *) payload, payload_len);
    69         g_checksum_get_digest(checksum, hash, &hash_len);
    70         g_checksum_free(checksum);
     57        sha1_append(&sha1, key, HMAC_BLOCK_SIZE);
     58        sha1_append(&sha1, (const guint8 *) payload, payload_len);
     59        sha1_finish(&sha1, hash);
    7160
    7261        /* Final result: H(K XOR 0x5C, inner stuff) */
    73         checksum = g_checksum_new(checksum_type);
     62        sha1_init(&sha1);
    7463        for (i = 0; i < HMAC_BLOCK_SIZE; i++) {
    7564                key[i] ^= 0x36 ^ 0x5c;
    7665        }
    77         g_checksum_update(checksum, key, HMAC_BLOCK_SIZE);
    78         g_checksum_update(checksum, hash, hash_len);
    79         g_checksum_get_digest(checksum, *digest, &hash_len);
    80         g_checksum_free(checksum);
    81 
    82         g_free(hash);
     66        sha1_append(&sha1, key, HMAC_BLOCK_SIZE);
     67        sha1_append(&sha1, hash, SHA1_HASH_SIZE);
     68        sha1_finish(&sha1, digest);
    8369}
    84 
    85 void sha1_hmac(const char *key_, size_t key_len, const char *payload, size_t payload_len, guint8 digest[SHA1_HASH_SIZE])
    86 {
    87         b_hmac(G_CHECKSUM_SHA1, key_, key_len, payload, payload_len, &digest);
    88 }
    89 
    9070
    9171/* I think this follows the scheme described on:
  • lib/ssl_gnutls.c

    r537d9b9 rba52ac5  
    4242#include <limits.h>
    4343
     44#if defined(ULONG_MAX) && ULONG_MAX > 4294967295UL
     45#define GNUTLS_STUPID_CAST (long)
     46#else
     47#define GNUTLS_STUPID_CAST (int)
     48#endif
     49
    4450#define SSLDEBUG 0
    4551
     
    329335
    330336        sock_make_nonblocking(conn->fd);
    331         gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr_t) (long) conn->fd);
     337        gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr_t) GNUTLS_STUPID_CAST conn->fd);
    332338
    333339        ssl_cache_resume(conn);
  • lib/ssl_openssl.c

    r537d9b9 rba52ac5  
    6767        SSL_library_init();
    6868
    69         meth = SSLv23_client_method();
     69        meth = TLSv1_client_method();
    7070        ssl_ctx = SSL_CTX_new(meth);
    71         SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
    7271
    7372        initialized = TRUE;
  • otr.c

    r537d9b9 rba52ac5  
    268268}
    269269
    270 #ifndef OTR_BI
    271 struct plugin_info *init_plugin_info(void)
    272 {
    273         static struct plugin_info info = {
    274                 BITLBEE_ABI_VERSION_CODE,
    275                 "otr",
    276                 BITLBEE_VERSION,
    277                 "Off-the-Record communication",
    278                 NULL,
    279                 NULL
    280         };
    281 
    282         return &info;
    283 }
    284 #endif
    285 
    286270gboolean otr_irc_new(irc_t *irc)
    287271{
     
    429413
    430414        /* don't do OTR on certain (not classic IM) protocols, e.g. twitter */
    431         if (a->prpl->options & PRPL_OPT_NOOTR) {
     415        if (a->prpl->options & OPT_NOOTR) {
    432416                return 0;
    433417        }
     
    457441
    458442        /* don't do OTR on certain (not classic IM) protocols, e.g. twitter */
    459         if (ic->acc->prpl->options & PRPL_OPT_NOOTR ||
     443        if (ic->acc->prpl->options & OPT_NOOTR ||
    460444            iu->bu->flags & BEE_USER_NOOTR) {
    461445                return msg;
     
    14001384void display_otr_message(void *opdata, ConnContext *ctx, const char *fmt, ...)
    14011385{
    1402         char *msg_, *msg;
    14031386        struct im_connection *ic =
    14041387                check_imc(opdata, ctx->accountname, ctx->protocol);
     
    14081391
    14091392        va_start(va, fmt);
    1410         msg_ = g_strdup_vprintf(fmt, va);
     1393        char *msg = g_strdup_vprintf(fmt, va);
    14111394        va_end(va);
    1412 
    1413         msg = word_wrap(msg_, IRC_WORD_WRAP);
    14141395
    14151396        if (u) {
     
    14201401        }
    14211402
    1422         g_free(msg_);
    14231403        g_free(msg);
    14241404}
  • protocols/account.c

    r537d9b9 rba52ac5  
    6363
    6464        s = set_add(&a->set, "password", NULL, set_eval_account, a);
    65         s->flags |= SET_NOSAVE | SET_NULL_OK | SET_PASSWORD | ACC_SET_LOCKABLE;
     65        s->flags |= SET_NOSAVE | SET_NULL_OK | SET_PASSWORD;
    6666
    6767        s = set_add(&a->set, "tag", NULL, set_eval_account, a);
     
    6969
    7070        s = set_add(&a->set, "username", NULL, set_eval_account, a);
    71         s->flags |= SET_NOSAVE | ACC_SET_OFFLINE_ONLY | ACC_SET_LOCKABLE;
     71        s->flags |= SET_NOSAVE | ACC_SET_OFFLINE_ONLY;
    7272        set_setstr(&a->set, "username", user);
    7373
  • protocols/account.h

    r537d9b9 rba52ac5  
    6161        ACC_SET_OFFLINE_ONLY = 0x02,    /* Allow changes only if the acct is offline. */
    6262        ACC_SET_ONLINE_ONLY = 0x04,     /* Allow changes only if the acct is online. */
    63         ACC_SET_LOCKABLE = 0x08         /* Setting cannot be changed if the account is locked down */
    6463} account_set_flag_t;
    6564
     
    6968        ACC_FLAG_HANDLE_DOMAINS = 0x04, /* Contact handles need a domain portion. */
    7069        ACC_FLAG_LOCAL_CONTACTS = 0x08, /* Contact list is local. */
    71         ACC_FLAG_LOCKED = 0x10,         /* Account is locked (cannot be deleted, certain settings can't changed) */
    7270} account_flag_t;
    7371
  • protocols/bee.h

    r537d9b9 rba52ac5  
    8484} bee_user_t;
    8585
    86 typedef struct bee_chat_info {
    87         char *title;
    88         char *topic;
    89 } bee_chat_info_t;
    90 
    9186/* This one's mostly used so save space and make it easier (cheaper) to
    9287   compare groups of contacts, etc. */
     
    136131
    137132        void (*log)(bee_t *bee, const char *tag, const char *msg);
    138         gboolean (*user_nick_change)(bee_t *bee, bee_user_t *bu, const char *hint);
    139133} bee_ui_funcs_t;
    140134
     
    190184G_MODULE_EXPORT void imcb_chat_invite(struct im_connection *ic, const char *name, const char *who, const char *msg);
    191185
    192 G_GNUC_DEPRECATED G_MODULE_EXPORT void bee_chat_list_finish(struct im_connection *ic);
    193 G_MODULE_EXPORT void imcb_chat_list_finish(struct im_connection *ic);
    194 G_MODULE_EXPORT void imcb_chat_list_free(struct im_connection *ic);
    195 
    196186#endif /* __BEE_H__ */
  • protocols/bee_chat.c

    r537d9b9 rba52ac5  
    274274        }
    275275}
    276 
    277 void imcb_chat_list_finish(struct im_connection *ic)
    278 {
    279         cmd_chat_list_finish(ic);
    280 }
    281 
    282 void bee_chat_list_finish(struct im_connection *ic)
    283 {
    284         imcb_log(ic, "Warning: using deprecated bee_chat_list_finish. This will be removed in the stable release.");
    285         imcb_chat_list_finish(ic);
    286 }
    287 
    288 void imcb_chat_list_free(struct im_connection *ic)
    289 {
    290         bee_chat_info_t *ci;
    291         GSList *l = ic->chatlist;
    292 
    293         while (l) {
    294                 ci = l->data;
    295                 l = g_slist_delete_link(l, l);
    296 
    297                 g_free(ci->title);
    298                 g_free(ci->topic);
    299                 g_free(ci);
    300         }
    301 
    302         ic->chatlist = NULL;
    303 }
  • protocols/bee_ft.c

    r537d9b9 rba52ac5  
    3131        bee_user_t *bu = bee_user_by_handle(bee, ic, handle);
    3232
    33         if (bee->ui->ft_in_start && bu) {
     33        if (bee->ui->ft_in_start) {
    3434                return bee->ui->ft_in_start(bee, bu, file_name, file_size);
    3535        } else {
  • protocols/jabber/conference.c

    r537d9b9 rba52ac5  
    2828static xt_status jabber_chat_self_message(struct im_connection *ic, struct xt_node *node, struct xt_node *orig);
    2929
    30 struct groupchat *jabber_chat_join(struct im_connection *ic, const char *room, const char *nick, const char *password,
    31                                    gboolean always_use_nicks)
     30struct groupchat *jabber_chat_join(struct im_connection *ic, const char *room, const char *nick, const char *password)
    3231{
    3332        struct jabber_chat *jc;
     
    5857                g_free(jc);
    5958                return NULL;
    60         }
    61 
    62         if (always_use_nicks) {
    63                 jc->flags = JCFLAG_ALWAYS_USE_NICKS;
    6459        }
    6560
     
    10095        g_free(cserv);
    10196
    102         c = jabber_chat_join(ic, rjid, jd->username, NULL, FALSE);
     97        c = jabber_chat_join(ic, rjid, jd->username, NULL);
    10398        g_free(rjid);
    10499        if (c == NULL) {
     
    249244}
    250245
    251 static int jabber_chat_has_other_resources(struct im_connection *ic, struct jabber_buddy *bud)
    252 {
    253         struct jabber_buddy *cur;
    254 
    255         for (cur = jabber_buddy_by_jid(ic, bud->bare_jid, GET_BUDDY_FIRST); cur; cur = cur->next) {
    256                 if (cur != bud && jabber_compare_jid(cur->ext_jid, bud->ext_jid)) {
    257                         return TRUE;
    258                 }
    259         }
    260        
    261         return FALSE;
    262 }
    263 
    264246/* Not really the same syntax as the normal pkt_ functions, but this isn't
    265247   called by the xmltree parser directly and this way I can add some extra
     
    346328                        *s = 0; /* Should NEVER be NULL, but who knows... */
    347329                }
    348 
    349                 if (bud != jc->me && (jc->flags & JCFLAG_ALWAYS_USE_NICKS) && !(bud->flags & JBFLAG_IS_ANONYMOUS)) {
    350                         imcb_buddy_nick_change(ic, bud->ext_jid, bud->resource);
    351                 }
    352 
    353330                imcb_chat_add_buddy(chat, bud->ext_jid);
    354331                if (s) {
     
    356333                }
    357334        } else if (type) { /* type can only be NULL or "unavailable" in this function */
    358                 if ((bud->flags & JBFLAG_IS_CHATROOM) && bud->ext_jid && !jabber_chat_has_other_resources(ic, bud)) {
     335                if ((bud->flags & JBFLAG_IS_CHATROOM) && bud->ext_jid) {
    359336                        char *reason = NULL;
    360337                        char *status = NULL;
     
    466443
    467444        if (subject && chat) {
    468                 char empty[1] = "";
    469                 char *subject_text = subject->text_len > 0 ? subject->text : empty;
     445                char *subject_text = subject->text_len > 0 ? subject->text : "";
    470446                if (g_strcmp0(chat->topic, subject_text) != 0) {
    471447                        bare_jid = (bud) ? jabber_get_bare_jid(bud->ext_jid) : NULL;
     
    503479                bare_jid = jabber_get_bare_jid(bud->ext_jid ? bud->ext_jid : bud->full_jid);
    504480                final_from = bare_jid;
    505                 if (bud == jc->me || (g_strcasecmp(final_from, ic->acc->user) == 0)) {
    506                         flags = OPT_SELFMESSAGE;
    507                 }
     481                flags = (bud == jc->me) ? OPT_SELFMESSAGE : 0;
    508482        } else {
    509483                final_from = nick;
  • protocols/jabber/iq.c

    r537d9b9 rba52ac5  
    6767                        xt_add_child(reply, xt_new_node("name", set_getstr(&ic->acc->set, "user_agent"), NULL));
    6868                        xt_add_child(reply, xt_new_node("version", BITLBEE_VERSION, NULL));
     69                        xt_add_child(reply, xt_new_node("os", ARCH, NULL));
    6970                } else if (strcmp(s, XMLNS_TIME_OLD) == 0) {
    7071                        time_t time_ep;
     
    233234                imcb_log(ic, "Warning: Received incomplete IQ packet while authenticating");
    234235                imc_logout(ic, FALSE);
    235                 return XT_ABORT;
     236                return XT_HANDLED;
    236237        }
    237238
     
    286287                imcb_log(ic, "Warning: Received incomplete IQ packet while authenticating");
    287288                imc_logout(ic, FALSE);
    288                 return XT_ABORT;
     289                return XT_HANDLED;
    289290        }
    290291
     
    10591060        return XT_HANDLED;
    10601061}
    1061 
    1062 xt_status jabber_iq_disco_muc_response(struct im_connection *ic, struct xt_node *node, struct xt_node *orig);
    1063 
    1064 int jabber_iq_disco_muc(struct im_connection *ic, const char *muc_server)
    1065 {
    1066         struct xt_node *node;
    1067         int st;
    1068 
    1069         node = xt_new_node("query", NULL, NULL);
    1070         xt_add_attr(node, "xmlns", XMLNS_DISCO_ITEMS);
    1071         node = jabber_make_packet("iq", "get", (char *) muc_server, node);
    1072 
    1073         jabber_cache_add(ic, node, jabber_iq_disco_muc_response);
    1074         st = jabber_write_packet(ic, node);
    1075 
    1076         return st;
    1077 }
    1078 
    1079 xt_status jabber_iq_disco_muc_response(struct im_connection *ic, struct xt_node *node, struct xt_node *orig)
    1080 {
    1081         struct xt_node *query, *c;
    1082         struct jabber_error *err;
    1083         GSList *rooms =  NULL;
    1084 
    1085         if ((err = jabber_error_parse(xt_find_node(node->children, "error"), XMLNS_STANZA_ERROR))) {
    1086                 imcb_error(ic, "The server replied with an error: %s%s%s",
    1087                            err->code, err->text ? ": " : "", err->text ? err->text : "");
    1088                 jabber_error_free(err);
    1089                 return XT_HANDLED;
    1090         }
    1091 
    1092         if (!(query = xt_find_node(node->children, "query"))) {
    1093                 imcb_error(ic, "Received incomplete MUC list reply");
    1094                 return XT_HANDLED;
    1095         }
    1096 
    1097         c = query->children;
    1098         while ((c = xt_find_node(c, "item"))) {
    1099                 char *jid = xt_find_attr(c, "jid");
    1100 
    1101                 if (!jid || !strchr(jid, '@')) {
    1102                         c = c->next;
    1103                         continue;
    1104                 }
    1105 
    1106                 bee_chat_info_t *ci = g_new(bee_chat_info_t, 1);
    1107                 ci->title = g_strdup(xt_find_attr(c, "jid"));
    1108                 ci->topic = g_strdup(xt_find_attr(c, "name"));
    1109                 rooms = g_slist_prepend(rooms, ci);
    1110 
    1111                 c = c->next;
    1112         }
    1113 
    1114         imcb_chat_list_free(ic);
    1115         ic->chatlist = g_slist_reverse(rooms);
    1116         imcb_chat_list_finish(ic);
    1117 
    1118         return XT_HANDLED;
    1119 }
  • protocols/jabber/jabber.c

    r537d9b9 rba52ac5  
    8282        s->flags |= SET_NOSAVE | ACC_SET_OFFLINE_ONLY | SET_NULL_OK;
    8383
    84         set_add(&acc->set, "oauth", "false", set_eval_oauth, acc);
    85 
    8684        if (strcmp(acc->prpl->name, "hipchat") == 0) {
    8785                set_setstr(&acc->set, "server", "chat.hipchat.com");
    8886        } else {
     87                set_add(&acc->set, "oauth", "false", set_eval_oauth, acc);
     88
    8989                /* this reuses set_eval_oauth, which clears the password */
    9090                set_add(&acc->set, "anonymous", "false", set_eval_oauth, acc);
     
    321321        struct jabber_data *jd = ic->proto_data;
    322322
    323         imcb_chat_list_free(ic);
    324 
    325323        while (jd->filetransfers) {
    326324                imcb_file_canceled(ic, (( struct jabber_transfer *) jd->filetransfers->data)->ft, "Logging out");
     
    399397        if (g_strcasecmp(who, JABBER_OAUTH_HANDLE) == 0 &&
    400398            !(jd->flags & OPT_LOGGED_IN) && jd->fd == -1) {
    401 
    402                 if (jd->flags & JFLAG_HIPCHAT) {
    403                         sasl_oauth2_got_token(ic, message, NULL, NULL);
    404                         return 1;
    405                 } else if (sasl_oauth2_get_refresh_token(ic, message)) {
     399                if (sasl_oauth2_get_refresh_token(ic, message)) {
    406400                        return 1;
    407401                } else {
     
    583577        } else {
    584578                /* jabber_chat_join without the underscore is the conference.c one */
    585                 return jabber_chat_join(ic, room, final_nick, set_getstr(sets, "password"),
    586                                         set_getbool(sets, "always_use_nicks"));
     579                return jabber_chat_join(ic, room, final_nick, set_getstr(sets, "password"));
    587580        }
    588581
     
    593586{
    594587        return jabber_chat_with(ic, who);
    595 }
    596 
    597 static void jabber_chat_list_(struct im_connection *ic, const char *server)
    598 {
    599         struct jabber_data *jd = ic->proto_data;
    600 
    601         if (server && *server) {
    602                 jabber_iq_disco_muc(ic, server);
    603         } else if (jd->muc_host && *jd->muc_host) {
    604                 jabber_iq_disco_muc(ic, jd->muc_host);
    605         } else {
    606                 /* throw an error here, don't query conference.[server] directly.
    607                  * for things like jabber.org it gets you 18000 results of garbage */
    608                 imcb_error(ic, "Please specify a server name such as `conference.%s'", jd->server);
    609         }
    610588}
    611589
     
    708686void jabber_chat_add_settings(account_t *acc, set_t **head)
    709687{
    710         set_add(head, "always_use_nicks", "false", set_eval_bool, NULL);
    711 
    712688        /* Meh. Stupid room passwords. Not trying to obfuscate/hide
    713689           them from the user for now. */
     
    717693void jabber_chat_free_settings(account_t *acc, set_t **head)
    718694{
    719         set_del(head, "always_use_nicks");
    720 
    721695        set_del(head, "password");
    722696}
     
    785759        ret->chat_join = jabber_chat_join_;
    786760        ret->chat_with = jabber_chat_with_;
    787         ret->chat_list = jabber_chat_list_;
    788761        ret->chat_add_settings = jabber_chat_add_settings;
    789762        ret->chat_free_settings = jabber_chat_free_settings;
  • protocols/jabber/jabber.h

    r537d9b9 rba52ac5  
    7575        JCFLAG_MESSAGE_SENT = 1,        /* Set this after sending the first message, so
    7676                                           we can detect echoes/backlogs. */
    77         JCFLAG_ALWAYS_USE_NICKS = 2,
    7877} jabber_chat_flags_t;
    7978
     
    263262void jabber_iq_version_send(struct im_connection *ic, struct jabber_buddy *bud, void *data);
    264263int jabber_iq_disco_server(struct im_connection *ic);
    265 int jabber_iq_disco_muc(struct im_connection *ic, const char *muc_server);
    266264
    267265/* si.c */
     
    341339int sasl_oauth2_get_refresh_token(struct im_connection *ic, const char *msg);
    342340int sasl_oauth2_refresh(struct im_connection *ic, const char *refresh_token);
    343 void sasl_oauth2_got_token(gpointer data, const char *access_token, const char *refresh_token, const char *error);
    344341
    345342extern const struct oauth2_service oauth2_service_google;
    346343
    347344/* conference.c */
    348 struct groupchat *jabber_chat_join(struct im_connection *ic, const char *room, const char *nick, const char *password,
    349                                    gboolean always_use_nicks);
     345struct groupchat *jabber_chat_join(struct im_connection *ic, const char *room, const char *nick, const char *password);
    350346struct groupchat *jabber_chat_with(struct im_connection *ic, char *who);
    351347struct groupchat *jabber_chat_by_jid(struct im_connection *ic, const char *name);
  • protocols/jabber/jabber_util.c

    r537d9b9 rba52ac5  
    315315        int i;
    316316
    317         if (!jid1 || !jid2) {
    318                 return FALSE;
    319         }
    320 
    321317        for (i = 0;; i++) {
    322318                if (jid1[i] == '\0' || jid1[i] == '/' || jid2[i] == '\0' || jid2[i] == '/') {
  • protocols/jabber/message.c

    r537d9b9 rba52ac5  
    2727{
    2828        struct im_connection *ic = data;
     29        struct jabber_data *jd = ic->proto_data;
    2930        char *from = xt_find_attr(node, carbons_sent ? "to" : "from");
    3031        char *type = xt_find_attr(node, "type");
     
    3738        if (!from) {
    3839                return XT_HANDLED; /* Consider this packet corrupted. */
     40        }
     41
     42        /* try to detect hipchat's own version of self-messages */
     43        if (jd->flags & JFLAG_HIPCHAT) {
     44                struct xt_node *c;
     45
     46                if ((c = xt_find_node_by_attr(node->children, "delay", "xmlns", XMLNS_DELAY)) &&
     47                    (s = xt_find_attr(c, "from_jid")) &&
     48                    jabber_compare_jid(s, jd->me)) {
     49                        carbons_sent = TRUE;
     50                }
    3951        }
    4052
  • protocols/jabber/presence.c

    r537d9b9 rba52ac5  
    222222        cap = xt_new_node("c", NULL, NULL);
    223223        xt_add_attr(cap, "xmlns", XMLNS_CAPS);
    224         xt_add_attr(cap, "node", "http://bitlbee.org/xmpp/caps");
     224
     225        if (jd->flags & JFLAG_HIPCHAT) {
     226                /* hipchat specific node, whitelisted by request to receive self-messages */
     227                xt_add_attr(cap, "node", "http://bitlbee.org/xmpp/caps/hipchat");
     228        } else {
     229                xt_add_attr(cap, "node", "http://bitlbee.org/xmpp/caps");
     230        }
    225231        xt_add_attr(cap, "ver", BITLBEE_VERSION);   /* The XEP wants this hashed, but nobody's doing that. */
    226232        xt_add_child(node, cap);
  • protocols/jabber/s5bytestream.c

    r537d9b9 rba52ac5  
    928928                proxy = next;
    929929        }
    930 
    931         g_free(proxysetting);
    932930}
    933931
  • protocols/jabber/sasl.c

    r537d9b9 rba52ac5  
    3939};
    4040
    41 /* """"""""""""""""""""""""""""""oauth"""""""""""""""""""""""""""""" */
    42 #define HIPCHAT_SO_CALLED_OAUTH_URL "https://hipchat.com/account/api"
    43 
    4441xt_status sasl_pkt_mechanisms(struct xt_node *node, gpointer data)
    4542{
     
    4845        struct xt_node *c, *reply;
    4946        char *s;
    50         int sup_plain = 0, sup_digest = 0, sup_gtalk = 0, sup_anonymous = 0, sup_hipchat_oauth = 0;
     47        int sup_plain = 0, sup_digest = 0, sup_gtalk = 0, sup_anonymous = 0;
    5148        int want_oauth = FALSE, want_hipchat = FALSE, want_anonymous = FALSE;
    5249        GString *mechs;
     
    8380                } else if (c->text && g_strcasecmp(c->text, "X-OAUTH2") == 0) {
    8481                        sup_gtalk = 1;
    85                 } else if (c->text && g_strcasecmp(c->text, "X-HIPCHAT-OAUTH2") == 0) {
    86                         sup_hipchat_oauth = 1;
    8782                }
    8883
     
    9590
    9691        if (!want_oauth && !sup_plain && !sup_digest) {
    97                 if (sup_gtalk || sup_hipchat_oauth) {
     92                if (!sup_gtalk) {
    9893                        imcb_error(ic, "This server requires OAuth "
    9994                                   "(supported schemes:%s)", mechs->str);
     
    115110        }
    116111
    117         if ((sup_gtalk || sup_hipchat_oauth) && want_oauth) {
    118                 GString *gs;
    119 
    120                 gs = g_string_sized_new(128);
    121 
    122                 g_string_append_c(gs, '\0');
    123 
    124                 if (sup_gtalk) {
    125                         /* X-OAUTH2 is not *the* standard OAuth2 SASL/XMPP implementation.
    126                            It's currently used by GTalk and vaguely documented on
    127                            http://code.google.com/apis/cloudprint/docs/rawxmpp.html */
    128                         xt_add_attr(reply, "mechanism", "X-OAUTH2");
    129 
    130                         g_string_append(gs, jd->username);
    131                         g_string_append_c(gs, '\0');
    132                         g_string_append(gs, jd->oauth2_access_token);
    133                 } else if (sup_hipchat_oauth) {
    134                         /* Hipchat's variant, not standard either, is documented here:
    135                            https://docs.atlassian.com/hipchat.xmpp/latest/xmpp/auth.html */
    136                         xt_add_attr(reply, "mechanism", "oauth2");
    137 
    138                         g_string_append(gs, jd->oauth2_access_token);
    139                         g_string_append_c(gs, '\0');
    140                         g_string_append(gs, set_getstr(&ic->acc->set, "resource"));
    141                 }
    142 
    143                 reply->text = base64_encode((unsigned char *) gs->str, gs->len);
     112        if (sup_gtalk && want_oauth) {
     113                int len;
     114
     115                /* X-OAUTH2 is, not *the* standard OAuth2 SASL/XMPP implementation.
     116                   It's currently used by GTalk and vaguely documented on
     117                   http://code.google.com/apis/cloudprint/docs/rawxmpp.html . */
     118                xt_add_attr(reply, "mechanism", "X-OAUTH2");
     119
     120                len = strlen(jd->username) + strlen(jd->oauth2_access_token) + 2;
     121                s = g_malloc(len + 1);
     122                s[0] = 0;
     123                strcpy(s + 1, jd->username);
     124                strcpy(s + 2 + strlen(jd->username), jd->oauth2_access_token);
     125                reply->text = base64_encode((unsigned char *) s, len);
    144126                reply->text_len = strlen(reply->text);
    145                 g_string_free(gs, TRUE);
    146 
     127                g_free(s);
    147128        } else if (want_oauth) {
    148129                imcb_error(ic, "OAuth requested, but not supported by server");
     
    168149                /* The rest will be done later, when we receive a <challenge/>. */
    169150        } else if (sup_plain) {
     151                int len;
    170152                GString *gs;
    171153                char *username;
     
    192174                }
    193175
    194                 reply->text = base64_encode((unsigned char *) gs->str, gs->len);
     176                len = gs->len;
     177                s = g_string_free(gs, FALSE);
     178
     179                reply->text = base64_encode((unsigned char *) s, len);
    195180                reply->text_len = strlen(reply->text);
    196                 g_string_free(gs, TRUE);
     181                g_free(s);
    197182        }
    198183
     
    443428{
    444429        struct jabber_data *jd = ic->proto_data;
     430        char *msg, *url;
    445431
    446432        imcb_log(ic, "Starting OAuth authentication");
     
    448434        /* Temporary contact, just used to receive the OAuth response. */
    449435        imcb_add_buddy(ic, JABBER_OAUTH_HANDLE, NULL);
    450 
    451         if (jd->flags & JFLAG_HIPCHAT) {
    452                 imcb_buddy_msg(ic, JABBER_OAUTH_HANDLE,
    453                         "Open this URL and generate a token with 'View Group' and 'Send Message' scopes: "
    454                         HIPCHAT_SO_CALLED_OAUTH_URL, 0, 0);
    455         } else {
    456                 char *msg, *url;
    457 
    458                 url = oauth2_url(jd->oauth2_service);
    459                 msg = g_strdup_printf("Open this URL in your browser to authenticate: %s", url);
    460                 imcb_buddy_msg(ic, JABBER_OAUTH_HANDLE, msg, 0, 0);
    461 
    462                 g_free(msg);
    463                 g_free(url);
    464         }
     436        url = oauth2_url(jd->oauth2_service);
     437        msg = g_strdup_printf("Open this URL in your browser to authenticate: %s", url);
     438        imcb_buddy_msg(ic, JABBER_OAUTH_HANDLE, msg, 0, 0);
    465439        imcb_buddy_msg(ic, JABBER_OAUTH_HANDLE, "Respond to this message with the returned "
    466440                       "authorization token.", 0, 0);
    467441
     442        g_free(msg);
     443        g_free(url);
    468444}
    469445
     
    477453        return FALSE;
    478454}
     455
     456static void sasl_oauth2_got_token(gpointer data, const char *access_token, const char *refresh_token,
     457                                  const char *error);
    479458
    480459int sasl_oauth2_get_refresh_token(struct im_connection *ic, const char *msg)
     
    507486}
    508487
    509 void sasl_oauth2_got_token(gpointer data, const char *access_token, const char *refresh_token, const char *error)
     488static void sasl_oauth2_got_token(gpointer data, const char *access_token, const char *refresh_token, const char *error)
    510489{
    511490        struct im_connection *ic = data;
  • protocols/jabber/si.c

    r537d9b9 rba52ac5  
    393393        struct jabber_transfer *tf = NULL;
    394394        struct jabber_data *jd = ic->proto_data;
    395         struct jabber_error *err;
    396395
    397396        if (!(tgt_jid = xt_find_attr(node, "from")) ||
    398             !(ini_jid = xt_find_attr(node, "to")) ||
    399             !(iq_id   = xt_find_attr(node, "id"))) {
     397            !(ini_jid = xt_find_attr(node, "to"))) {
    400398                imcb_log(ic, "Invalid SI response from=%s to=%s", tgt_jid, ini_jid);
    401                 return XT_HANDLED;
    402         }
    403 
    404         /* Let's see if we can find out what this bytestream should be for... */
    405 
    406         for (tflist = jd->filetransfers; tflist; tflist = g_slist_next(tflist)) {
    407                 struct jabber_transfer *tft = tflist->data;
    408                 if ((strcmp(tft->iq_id, iq_id) == 0)) {
    409                         tf = tft;
    410                         break;
    411                 }
    412         }
    413 
    414         if (!tf) {
    415                 imcb_log(ic, "WARNING: Received bytestream request from %s that doesn't match an SI request", ini_jid);
    416                 return XT_HANDLED;
    417         }
    418 
    419         err = jabber_error_parse(xt_find_node(node->children, "error"), XMLNS_STANZA_ERROR);
    420 
    421         if (err) {
    422                 if (g_strcmp0(err->code, "forbidden") == 0) {
    423                         imcb_log(ic, "File %s: %s rejected the transfer", tf->ft->file_name, tgt_jid);
    424                 } else {
    425                         imcb_log(ic, "Error: Stream initiation request failed: %s (%s)", err->code, err->text);
    426                 }
    427                 imcb_file_canceled(ic, tf->ft, "Stream initiation request failed");
    428                 jabber_error_free(err);
    429399                return XT_HANDLED;
    430400        }
     
    439409         *                                      <value>
    440410         */
    441         if (!(c = xt_find_node(node->children, "si")) ||
     411        if (!(tgt_jid = xt_find_attr(node, "from")) ||
     412            !(ini_jid = xt_find_attr(node, "to")) ||
     413            !(iq_id   = xt_find_attr(node, "id")) ||
     414            !(c = xt_find_node(node->children, "si")) ||
    442415            !(cmp = xt_find_attr(c, "xmlns")) ||
    443416            !(strcmp(cmp, XMLNS_SI) == 0) ||
     
    466439        }
    467440
     441        /* Let's see if we can find out what this bytestream should be for... */
     442
     443        for (tflist = jd->filetransfers; tflist; tflist = g_slist_next(tflist)) {
     444                struct jabber_transfer *tft = tflist->data;
     445                if ((strcmp(tft->iq_id, iq_id) == 0)) {
     446                        tf = tft;
     447                        break;
     448                }
     449        }
     450
     451        if (!tf) {
     452                imcb_log(ic, "WARNING: Received bytestream request from %s that doesn't match an SI request", ini_jid);
     453                return XT_HANDLED;
     454        }
     455
    468456        tf->ini_jid = g_strdup(ini_jid);
    469457        tf->tgt_jid = g_strdup(tgt_jid);
  • protocols/nogaim.c

    r537d9b9 rba52ac5  
    4040
    4141#ifdef WITH_PLUGINS
    42 GList *plugins = NULL;
    43 
    44 static gint pluginscmp(gconstpointer a, gconstpointer b, gpointer data)
    45 {
    46         const struct plugin_info *ia = a;
    47         const struct plugin_info *ib = b;
    48 
    49         return g_strcasecmp(ia->name, ib->name);
    50 }
    51 
    5242gboolean load_plugin(char *path)
    5343{
    54         GList *l;
    55         struct plugin_info *i;
    56         struct plugin_info *info;
    57         struct plugin_info * (*info_function) (void) = NULL;
    5844        void (*init_function) (void);
    5945
    6046        GModule *mod = g_module_open(path, G_MODULE_BIND_LAZY);
    61         gboolean loaded = FALSE;
    6247
    6348        if (!mod) {
    64                 log_message(LOGLVL_ERROR, "Error loading plugin `%s': %s\n", path, g_module_error());
     49                log_message(LOGLVL_ERROR, "Can't find `%s', not loading (%s)\n", path, g_module_error());
    6550                return FALSE;
    66         }
    67 
    68         if (g_module_symbol(mod, "init_plugin_info", (gpointer *) &info_function)) {
    69                 info = info_function();
    70 
    71                 if (info->abiver != BITLBEE_ABI_VERSION_CODE) {
    72                         log_message(LOGLVL_ERROR,
    73                                     "`%s' uses ABI %u but %u is required\n",
    74                                     path, info->abiver,
    75                                     BITLBEE_ABI_VERSION_CODE);
    76                         g_module_close(mod);
    77                         return FALSE;
    78                 }
    79 
    80                 if (!info->name || !info->version) {
    81                         log_message(LOGLVL_ERROR,
    82                                     "Name or version missing from the "
    83                                     "plugin info in `%s'\n", path);
    84                         g_module_close(mod);
    85                         return FALSE;
    86                 }
    87 
    88                 for (l = plugins; l; l = l->next) {
    89                         i = l->data;
    90 
    91                         if (g_strcasecmp(i->name, info->name) == 0) {
    92                                 loaded = TRUE;
    93                                 break;
    94                         }
    95                 }
    96 
    97                 if (loaded) {
    98                         log_message(LOGLVL_WARNING,
    99                                     "%s plugin already loaded\n",
    100                                     info->name);
    101                         g_module_close(mod);
    102                         return FALSE;
    103                 }
    104         } else {
    105                 log_message(LOGLVL_WARNING, "Can't find function `init_plugin_info' in `%s'\n", path);
    10651        }
    10752
    10853        if (!g_module_symbol(mod, "init_plugin", (gpointer *) &init_function)) {
    10954                log_message(LOGLVL_WARNING, "Can't find function `init_plugin' in `%s'\n", path);
    110                 g_module_close(mod);
    11155                return FALSE;
    11256        }
    11357
    114         if (info_function) {
    115                 plugins = g_list_insert_sorted_with_data(plugins, info,
    116                                                          pluginscmp, NULL);
    117         }
    118 
    11958        init_function();
     59
    12060        return TRUE;
    12161}
     
    13373
    13474                while ((entry = g_dir_read_name(dir))) {
    135                         if (!g_str_has_suffix(entry, "." G_MODULE_SUFFIX)) {
    136                                 continue;
    137                         }
    138 
    13975                        path = g_build_filename(global.conf->plugindir, entry, NULL);
    14076                        if (!path) {
     
    15086                g_dir_close(dir);
    15187        }
    152 }
    153 
    154 GList *get_plugins()
    155 {
    156         return plugins;
    15788}
    15889#endif
     
    237168        load_plugins();
    238169#endif
    239 }
    240 
    241 GList *get_protocols()
    242 {
    243         return protocols;
    244 }
    245 
    246 GList *get_protocols_disabled()
    247 {
    248         return disabled_protocols;
    249170}
    250171
     
    574495}
    575496
    576 /* Implements either imcb_buddy_nick_hint() or imcb_buddy_nick_change() depending on the value of 'change' */
    577 static void buddy_nick_hint_or_change(struct im_connection *ic, const char *handle, const char *nick, gboolean change)
     497/* Mainly meant for ICQ (and now also for Jabber conferences) to allow IM
     498   modules to suggest a nickname for a handle. */
     499void imcb_buddy_nick_hint(struct im_connection *ic, const char *handle, const char *nick)
    578500{
    579501        bee_t *bee = ic->bee;
     
    587509        bu->nick = g_strdup(nick);
    588510
    589         if (change && bee->ui->user_nick_change) {
    590                 bee->ui->user_nick_change(bee, bu, nick);
    591         } else if (!change && bee->ui->user_nick_hint) {
     511        if (bee->ui->user_nick_hint) {
    592512                bee->ui->user_nick_hint(bee, bu, nick);
    593513        }
    594 }
    595 
    596 /* Soft variant, for newly created users. Does nothing if it's already online */
    597 void imcb_buddy_nick_hint(struct im_connection *ic, const char *handle, const char *nick)
    598 {
    599         buddy_nick_hint_or_change(ic, handle, nick, FALSE);
    600 }
    601 
    602 /* Hard variant, always changes the nick */
    603 void imcb_buddy_nick_change(struct im_connection *ic, const char *handle, const char *nick)
    604 {
    605         buddy_nick_hint_or_change(ic, handle, nick, TRUE);
    606514}
    607515
     
    759667        if (away && *away) {
    760668                GList *m = ic->acc->prpl->away_states(ic);
    761                 if (m == NULL) {
    762                         return 0;
    763                 }
    764669                msg = ic->acc->flags & ACC_FLAG_AWAY_MESSAGE ? away : NULL;
    765670                away = imc_away_state_find(m, away, &msg) ? :
  • protocols/nogaim.h

    r537d9b9 rba52ac5  
    102102
    103103        GSList *groupchats;
    104         GSList *chatlist;
    105104};
    106105
     
    145144        char *description;
    146145};
    147 
    148 /* This enum takes a few things from libpurple and a few things from old OPT_ flags.
    149  * The only flag that was used before this struct was PRPL_OPT_NOOTR.
    150  *
    151  * The libpurple ones only use the same values as the PurpleProtocolOptions
    152  * enum for convenience, but there's no promise of direct compatibility with
    153  * those values. As of libpurple 2.8.0 they use up to 0x800 (1 << 11), which is
    154  * a nice coincidence.
    155  */
    156 typedef enum {
    157         /* The protocol doesn't use passwords
    158          * Mirrors libpurple's OPT_PROTO_NO_PASSWORD */
    159         PRPL_OPT_NO_PASSWORD = 1 << 4,
    160 
    161         /* The protocol doesn't require passwords, but may use them
    162          * Mirrors libpurple's OPT_PROTO_PASSWORD_OPTIONAL */
    163         PRPL_OPT_PASSWORD_OPTIONAL = 1 << 7,
    164 
    165         /* The protocol is not suitable for OTR, see OPT_NOOTR */
    166         PRPL_OPT_NOOTR = 1 << 12,
    167 } prpl_options_t;
    168146
    169147struct prpl {
     
    291269        gboolean (* handle_is_self) (struct im_connection *, const char *who);
    292270
    293         /* This sets/updates the im_connection->chatlist field with a
    294          * bee_chat_info_t GSList. This function should ensure the
    295          * bee_chat_list_finish() function gets called at some point
    296          * after the chat list is completely updated.
    297          */
    298         void (* chat_list) (struct im_connection *, const char *server);
    299 
    300271        /* Some placeholders so eventually older plugins may cooperate with newer BitlBees. */
    301272        void *resv1;
     
    306277};
    307278
    308 struct plugin_info
    309 {
    310         guint abiver;
    311         const char *name;
    312         const char *version;
    313         const char *description;
    314         const char *author;
    315         const char *url;
    316 };
    317 
    318 #ifdef WITH_PLUGINS
    319 G_MODULE_EXPORT GList *get_plugins();
    320 #endif
    321 
    322279/* im_api core stuff. */
    323280void nogaim_init();
    324 G_MODULE_EXPORT GList *get_protocols();
    325 G_MODULE_EXPORT GList *get_protocols_disabled();
    326281G_MODULE_EXPORT GSList *get_connections();
    327282G_MODULE_EXPORT struct prpl *find_protocol(const char *name);
     
    375330G_MODULE_EXPORT void imcb_rename_buddy(struct im_connection *ic, const char *handle, const char *realname);
    376331G_MODULE_EXPORT void imcb_buddy_nick_hint(struct im_connection *ic, const char *handle, const char *nick);
    377 G_MODULE_EXPORT void imcb_buddy_nick_change(struct im_connection *ic, const char *handle, const char *nick);
    378332G_MODULE_EXPORT void imcb_buddy_action_response(bee_user_t *bu, const char *action, char * const args[], void *data);
    379333G_MODULE_EXPORT GSList *imcb_get_local_contacts(struct im_connection *ic);
  • protocols/oscar/conn.c

    r537d9b9 rba52ac5  
    383383{
    384384        aim_conn_t *connstruct;
     385        guint16 port = AIM_LOGIN_PORT;
     386        char *host;
     387        int i;
    385388
    386389        if (!(connstruct = aim_conn_getnext(sess))) {
     
    397400        }
    398401
    399         /* The code that used to be here was very broken */
    400         g_return_val_if_reached(connstruct);
     402        /*
     403         * As of 23 Jul 1999, AOL now sends the port number, preceded by a
     404         * colon, in the BOS redirect.  This fatally breaks all previous
     405         * libfaims.  Bad, bad AOL.
     406         *
     407         * We put this here to catch every case.
     408         *
     409         */
     410
     411        for (i = 0; i < (int) strlen(dest); i++) {
     412                if (dest[i] == ':') {
     413                        port = atoi(&(dest[i + 1]));
     414                        break;
     415                }
     416        }
     417
     418        host = (char *) g_malloc(i + 1);
     419        strncpy(host, dest, i);
     420        host[i] = '\0';
     421
     422        connstruct->fd = proxy_connect(host, port, NULL, NULL);
     423
     424        g_free(host);
    401425
    402426        return connstruct;
  • protocols/purple/bpurple.h

    r537d9b9 rba52ac5  
    1313    GHashTable *input_requests;
    1414    guint next_request_id;
    15     char *chat_list_server;
    16     GSList *filetransfers;
    1715};
    1816
  • protocols/purple/ft.c

    r537d9b9 rba52ac5  
    4242        char *fn, *handle;
    4343        gboolean ui_wants_data;
    44         int timeout;
    4544};
    4645
     
    6564        struct prpl_xfer_data *px = ft->data;
    6665
    67         if (px->xfer) {
    68                 if (!purple_xfer_is_completed(px->xfer) && !purple_xfer_is_canceled(px->xfer)) {
    69                         purple_xfer_cancel_local(px->xfer);
    70                 }
    71                 px->xfer->ui_data = NULL;
    72                 purple_xfer_unref(px->xfer);
    73                 px->xfer = NULL;
    74         }
    75 }
    76 
    77 static void prpl_xfer_free(struct file_transfer *ft)
    78 {
    79         struct prpl_xfer_data *px = ft->data;
    80         struct purple_data *pd = px->ic->proto_data;
    81 
    82         pd->filetransfers = g_slist_remove(pd->filetransfers, px);
    83 
    84         if (px->xfer) {
    85                 px->xfer->ui_data = NULL;
    86                 purple_xfer_unref(px->xfer);
    87         }
    88 
    89         if (px->timeout) {
    90                 b_event_remove(px->timeout);
    91         }
    92 
    93         g_free(px->fn);
    94         g_free(px->handle);
    95         if (px->fd >= 0) {
    96                 close(px->fd);
    97         }
    98         g_free(px);
     66        purple_xfer_request_denied(px->xfer);
    9967}
    10068
    10169static void prplcb_xfer_new(PurpleXfer *xfer)
    10270{
    103         purple_xfer_ref(xfer);
    104 
    10571        if (purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE) {
    10672                struct prpl_xfer_data *px = g_new0(struct prpl_xfer_data, 1);
    107                 struct purple_data *pd;
    10873
    10974                xfer->ui_data = px;
     
    11378                px->ic = purple_ic_by_pa(xfer->account);
    11479
    115                 pd = px->ic->proto_data;
    116                 pd->filetransfers = g_slist_prepend(pd->filetransfers, px);
    117 
    11880                purple_xfer_set_local_filename(xfer, px->fn);
    11981
     
    150112        px->ft->accept = prpl_xfer_accept;
    151113        px->ft->canceled = prpl_xfer_canceled;
    152         px->ft->free = prpl_xfer_free;
    153114        px->ft->write_request = prpl_xfer_write_request;
    154115
     
    203164
    204165
     166/* Generic (IM<>UI): */
    205167static void prplcb_xfer_destroy(PurpleXfer *xfer)
    206168{
    207169        struct prpl_xfer_data *px = xfer->ui_data;
    208170
    209         if (px) {
    210                 px->xfer = NULL;
    211         }
     171        g_free(px->fn);
     172        g_free(px->handle);
     173        if (px->fd >= 0) {
     174                close(px->fd);
     175        }
     176        g_free(px);
    212177}
    213178
     
    259224        struct prpl_xfer_data *px = xfer->ui_data;
    260225
    261         if (px && px->ft) {
     226        if (px->ft) {
    262227                imcb_file_canceled(px->ic, px->ft, "Canceled by remote end");
    263         } else if (px) {
     228        } else {
    264229                /* px->ft == NULL for sends, because of the two stages. :-/ */
    265230                imcb_error(px->ic, "File transfer cancelled by remote end");
     
    275240{
    276241        struct prpl_xfer_data *px = g_new0(struct prpl_xfer_data, 1);
    277         struct purple_data *pd;
    278242        char *dir, *basename;
    279243
    280244        ft->data = px;
    281245        px->ft = ft;
    282         px->ft->free = prpl_xfer_free;
    283246
    284247        dir = g_strdup("/tmp/bitlbee-purple-ft.XXXXXX");
     
    309272        px->handle = g_strdup(handle);
    310273
    311         pd = px->ic->proto_data;
    312         pd->filetransfers = g_slist_prepend(pd->filetransfers, px);
    313 
    314274        imcb_log(ic,
    315275                 "Due to libpurple limitations, the file has to be cached locally before proceeding with the actual file transfer. Please wait...");
    316276
    317         px->timeout = b_timeout_add(0, purple_transfer_request_cb, ft);
     277        b_timeout_add(0, purple_transfer_request_cb, ft);
    318278}
    319279
     
    335295        struct prpl_xfer_data *px = ft->data;
    336296
    337         px->timeout = 0;
    338 
    339297        if (ft->write == NULL) {
    340298                ft->write = prpl_xfer_write;
     
    364322                px->ft = NULL;
    365323        } else {
    366                 px->timeout = b_timeout_add(0, purple_transfer_request_cb, ft);
     324                b_timeout_add(0, purple_transfer_request_cb, ft);
    367325        }
    368326
    369327        return TRUE;
    370 }
    371 
    372 void purple_transfer_cancel_all(struct im_connection *ic)
    373 {
    374         struct purple_data *pd = ic->proto_data;
    375 
    376         while (pd->filetransfers) {
    377                 struct prpl_xfer_data *px = pd->filetransfers->data;
    378 
    379                 if (px->ft) {
    380                         imcb_file_canceled(ic, px->ft, "Logging out");
    381                 }
    382 
    383                 pd->filetransfers = g_slist_remove(pd->filetransfers, px);
    384         }
    385328}
    386329
  • protocols/purple/purple.c

    r537d9b9 rba52ac5  
    4343                                   const char *message, const char *who);
    4444
    45 void purple_transfer_cancel_all(struct im_connection *ic);
    46 
    4745/* purple_request_input specific stuff */
    4846typedef void (*ri_callback_t)(gpointer, const gchar *);
     
    5654};
    5755
    58 struct purple_roomlist_data {
    59         GSList *chats;
    60         gint topic;
    61         gboolean initialized;
    62 };
    63 
    64 
    6556struct im_connection *purple_ic_by_pa(PurpleAccount *pa)
    6657{
     
    10394}
    10495
    105 static char *purple_get_account_prpl_id(account_t *acc)
    106 {
    107         /* "oscar" is how non-purple bitlbee calls it,
    108          * and it might be icq or aim, depending on the username */
    109         if (g_strcmp0(acc->prpl->name, "oscar") == 0) {
    110                 return (g_ascii_isdigit(acc->user[0])) ? "prpl-icq" : "prpl-aim";
    111         }
    112 
    113         return acc->prpl->data;
    114 }
    115 
    11696static void purple_init(account_t *acc)
    11797{
    118         char *prpl_id = purple_get_account_prpl_id(acc);
    119         PurplePlugin *prpl = purple_plugins_find_with_id(prpl_id);
     98        PurplePlugin *prpl = purple_plugins_find_with_id((char *) acc->prpl->data);
    12099        PurplePluginProtocolInfo *pi = prpl->info->extra_info;
    121100        PurpleAccount *pa;
     
    283262        /* Go through all away states to figure out if away/status messages
    284263           are possible. */
    285         pa = purple_account_new(acc->user, prpl_id);
     264        pa = purple_account_new(acc->user, (char *) acc->prpl->data);
    286265        for (st = purple_account_get_status_types(pa); st; st = st->next) {
    287266                PurpleStatusPrimitive prim = purple_status_type_get_primitive(st->data);
     
    366345
    367346        ic->proto_data = pd = g_new0(struct purple_data, 1);
    368         pd->account = purple_account_new(acc->user, purple_get_account_prpl_id(acc));
     347        pd->account = purple_account_new(acc->user, (char *) acc->prpl->data);
    369348        pd->input_requests = g_hash_table_new_full(g_direct_hash, g_direct_equal,
    370349                                                   NULL, g_free);
     
    392371        }
    393372
    394         if (pd->filetransfers) {
    395                 purple_transfer_cancel_all(ic);
    396         }
    397 
    398373        purple_account_set_enabled(pd->account, "BitlBee", FALSE);
    399374        purple_connections = g_slist_remove(purple_connections, ic);
    400375        purple_accounts_remove(pd->account);
    401         imcb_chat_list_free(ic);
    402         g_free(pd->chat_list_server);
    403376        g_hash_table_destroy(pd->input_requests);
    404377        g_free(pd);
     
    700673}
    701674
    702 void purple_chat_set_topic(struct groupchat *gc, char *topic)
    703 {
    704         PurpleConversation *pc = gc->data;
    705         PurpleConvChat *pcc = PURPLE_CONV_CHAT(pc);
    706         struct purple_data *pd = gc->ic->proto_data;
    707         PurplePlugin *prpl = purple_plugins_find_with_id(pd->account->protocol_id);
    708         PurplePluginProtocolInfo *pi = prpl->info->extra_info;
    709 
    710         if (pi->set_chat_topic) {
    711                 pi->set_chat_topic(purple_account_get_connection(pd->account),
    712                                    purple_conv_chat_get_id(pcc),
    713                                    topic);
    714         }
    715 }
    716 
    717675void purple_chat_kick(struct groupchat *gc, char *who, const char *message)
    718676{
     
    739697        GHashTable *chat_hash;
    740698        PurpleConversation *conv;
    741         struct groupchat *gc;
    742699        GList *info, *l;
    743700
     
    773730        g_list_free(info);
    774731
    775         /* do this before serv_join_chat to handle cases where prplcb_conv_new is called immediately (not async) */
    776         gc = imcb_chat_new(ic, room);
    777 
    778732        serv_join_chat(purple_account_get_connection(pd->account), chat_hash);
    779733
    780734        g_hash_table_destroy(chat_hash);
    781735
    782         return gc;
    783 }
    784 
    785 void purple_chat_list(struct im_connection *ic, const char *server)
    786 {
    787         PurpleRoomlist *list;
    788         struct purple_data *pd = ic->proto_data;
    789         PurplePlugin *prpl = purple_plugins_find_with_id(pd->account->protocol_id);
    790         PurplePluginProtocolInfo *pi = prpl->info->extra_info;
    791 
    792         if (!pi || !pi->roomlist_get_list) {
    793                 imcb_log(ic, "Room listing unsupported by this purple plugin");
    794                 return;
    795         }
    796 
    797         g_free(pd->chat_list_server);
    798         pd->chat_list_server = (server && *server) ? g_strdup(server) : NULL;
    799 
    800         list = purple_roomlist_get_list(pd->account->gc);
    801 
    802         if (list) {
    803                 struct purple_roomlist_data *rld = list->ui_data;
    804                 rld->initialized = TRUE;
    805 
    806                 purple_roomlist_ref(list);
    807         }
     736        return imcb_chat_new(ic, room);
    808737}
    809738
     
    1041970
    1042971/* Generic handler for IM or chat messages, covers write_chat, write_im and write_conv */
    1043 static void handle_conv_msg(PurpleConversation *conv, const char *who, const char *message_, guint32 bee_flags, time_t mtime)
     972static void handle_conv_msg(PurpleConversation *conv, const char *who, const char *message, guint32 bee_flags, time_t mtime)
    1044973{
    1045974        struct im_connection *ic = purple_ic_by_pa(conv->account);
    1046975        struct groupchat *gc = conv->ui_data;
    1047         char *message = g_strdup(message_);
    1048976        PurpleBuddy *buddy;
    1049977
     
    1054982
    1055983        if (conv->type == PURPLE_CONV_TYPE_IM) {
    1056                 imcb_buddy_msg(ic, who, message, bee_flags, mtime);
     984                imcb_buddy_msg(ic, (char *) who, (char *) message, bee_flags, mtime);
    1057985        } else if (gc) {
    1058                 imcb_chat_msg(gc, who, message, bee_flags, mtime);
    1059         }
    1060 
    1061         g_free(message);
     986                imcb_chat_msg(gc, who, (char *) message, bee_flags, mtime);
     987        }
    1062988}
    1063989
     
    12451171        struct im_connection *ic = purple_ic_by_pa(account);
    12461172        struct purple_data *pd = ic->proto_data;
    1247         struct request_input_data *ri;
    1248         guint id;
    1249 
    1250         /* hack so that jabber's chat list doesn't ask for conference server twice */
    1251         if (pd->chat_list_server && title && g_strcmp0(title, "Enter a Conference Server") == 0) {
    1252                 ((ri_callback_t) ok_cb)(user_data, pd->chat_list_server);
    1253                 g_free(pd->chat_list_server);
    1254                 pd->chat_list_server = NULL;
    1255                 return NULL;
    1256         }
    1257 
    1258         id = pd->next_request_id++;
    1259         ri = g_new0(struct request_input_data, 1);
     1173        struct request_input_data *ri = g_new0(struct request_input_data, 1);
     1174        guint id = pd->next_request_id++;
    12601175
    12611176        ri->id = id;
     
    12671182
    12681183        imcb_add_buddy(ic, ri->buddy, NULL);
    1269 
    1270         if (title && *title) {
    1271                 imcb_buddy_msg(ic, ri->buddy, title, 0, 0);
    1272         }
    1273 
    1274         if (primary && *primary) {
    1275                 imcb_buddy_msg(ic, ri->buddy, primary, 0, 0);
    1276         }
    1277 
    1278         if (secondary && *secondary) {
    1279                 imcb_buddy_msg(ic, ri->buddy, secondary, 0, 0);
    1280         }
     1184        imcb_buddy_msg(ic, ri->buddy, secondary, 0, 0);
    12811185
    12821186        return ri;
     
    13521256        prplcb_privacy_deny_added,         /* deny_added */
    13531257        prplcb_privacy_deny_removed,       /* deny_removed */
    1354 };
    1355 
    1356 static void prplcb_roomlist_create(PurpleRoomlist *list)
    1357 {
    1358         struct purple_roomlist_data *rld;
    1359 
    1360         list->ui_data = rld = g_new0(struct purple_roomlist_data, 1);
    1361         rld->topic = -1;
    1362 }
    1363 
    1364 static void prplcb_roomlist_set_fields(PurpleRoomlist *list, GList *fields)
    1365 {
    1366         gint topic = -1;
    1367         GList *l;
    1368         guint i;
    1369         PurpleRoomlistField *field;
    1370         struct purple_roomlist_data *rld = list->ui_data;
    1371 
    1372         for (i = 0, l = fields; l; i++, l = l->next) {
    1373                 field = l->data;
    1374 
    1375                 /* Use the first visible string field as a fallback topic */
    1376                 if (i != 0 && topic < 0 && !field->hidden &&
    1377                     field->type == PURPLE_ROOMLIST_FIELD_STRING) {
    1378                         topic = i;
    1379                 }
    1380 
    1381                 if ((g_strcasecmp(field->name, "description") == 0) ||
    1382                     (g_strcasecmp(field->name, "topic") == 0)) {
    1383                         if (field->type == PURPLE_ROOMLIST_FIELD_STRING) {
    1384                                 rld->topic = i;
    1385                         }
    1386                 }
    1387         }
    1388 
    1389         if (rld->topic < 0) {
    1390                 rld->topic = topic;
    1391         }
    1392 }
    1393 
    1394 static void prplcb_roomlist_add_room(PurpleRoomlist *list, PurpleRoomlistRoom *room)
    1395 {
    1396         bee_chat_info_t *ci;
    1397         const char *title;
    1398         const char *topic;
    1399         GList *fields;
    1400         struct purple_roomlist_data *rld = list->ui_data;
    1401 
    1402         fields = purple_roomlist_room_get_fields(room);
    1403         title = purple_roomlist_room_get_name(room);
    1404 
    1405         if (rld->topic >= 0) {
    1406                 topic = g_list_nth_data(fields, rld->topic);
    1407         } else {
    1408                 topic = NULL;
    1409         }
    1410 
    1411         ci = g_new(bee_chat_info_t, 1);
    1412         ci->title = g_strdup(title);
    1413         ci->topic = g_strdup(topic);
    1414         rld->chats = g_slist_prepend(rld->chats, ci);
    1415 }
    1416 
    1417 static void prplcb_roomlist_in_progress(PurpleRoomlist *list, gboolean in_progress)
    1418 {
    1419         struct im_connection *ic;
    1420         struct purple_data *pd;
    1421         struct purple_roomlist_data *rld = list->ui_data;
    1422 
    1423         if (in_progress || !rld) {
    1424                 return;
    1425         }
    1426 
    1427         ic = purple_ic_by_pa(list->account);
    1428         imcb_chat_list_free(ic);
    1429 
    1430         pd = ic->proto_data;
    1431         g_free(pd->chat_list_server);
    1432         pd->chat_list_server = NULL;
    1433 
    1434         ic->chatlist = g_slist_reverse(rld->chats);
    1435         rld->chats = NULL;
    1436 
    1437         imcb_chat_list_finish(ic);
    1438 
    1439         if (rld->initialized) {
    1440                 purple_roomlist_unref(list);
    1441         }
    1442 }
    1443 
    1444 static void prplcb_roomlist_destroy(PurpleRoomlist *list)
    1445 {
    1446         g_free(list->ui_data);
    1447         list->ui_data = NULL;
    1448 }
    1449 
    1450 static PurpleRoomlistUiOps bee_roomlist_uiops =
    1451 {
    1452         NULL,                         /* show_with_account */
    1453         prplcb_roomlist_create,       /* create */
    1454         prplcb_roomlist_set_fields,   /* set_fields */
    1455         prplcb_roomlist_add_room,     /* add_room */
    1456         prplcb_roomlist_in_progress,  /* in_progress */
    1457         prplcb_roomlist_destroy,      /* destroy */
    14581258};
    14591259
     
    16221422        purple_request_set_ui_ops(&bee_request_uiops);
    16231423        purple_privacy_set_ui_ops(&bee_privacy_uiops);
    1624         purple_roomlist_set_ui_ops(&bee_roomlist_uiops);
    16251424        purple_notify_set_ui_ops(&bee_notify_uiops);
    16261425        purple_accounts_set_ui_ops(&bee_account_uiops);
     
    16391438        char *dir;
    16401439
    1641         if (purple_get_core() != NULL) {
    1642                 log_message(LOGLVL_ERROR, "libpurple already initialized. "
    1643                             "Please use inetd or ForkDaemon mode instead.");
    1644                 return;
    1645         }
    1646 
    16471440        g_assert((int) B_EV_IO_READ == (int) PURPLE_INPUT_READ);
    16481441        g_assert((int) B_EV_IO_WRITE == (int) PURPLE_INPUT_WRITE);
     
    16501443        dir = g_strdup_printf("%s/purple", global.conf->configdir);
    16511444        purple_util_set_user_dir(dir);
    1652         g_free(dir);
    1653 
    1654         dir = g_strdup_printf("%s/purple", global.conf->plugindir);
    1655         purple_plugins_add_search_path(dir);
    16561445        g_free(dir);
    16571446
     
    17171506        funcs.chat_with = purple_chat_with;
    17181507        funcs.chat_invite = purple_chat_invite;
    1719         funcs.chat_topic = purple_chat_set_topic;
    17201508        funcs.chat_kick = purple_chat_kick;
    17211509        funcs.chat_leave = purple_chat_leave;
    17221510        funcs.chat_join = purple_chat_join;
    1723         funcs.chat_list = purple_chat_list;
    17241511        funcs.transfer_request = purple_transfer_request;
    17251512
     
    17301517        for (prots = purple_plugins_get_protocols(); prots; prots = prots->next) {
    17311518                PurplePlugin *prot = prots->data;
    1732                 PurplePluginProtocolInfo *pi = prot->info->extra_info;
    17331519                struct prpl *ret;
    17341520
     
    17441530                        ret->name += 5;
    17451531                }
    1746 
    1747                 if (pi->options & OPT_PROTO_NO_PASSWORD) {
    1748                         ret->options |= PRPL_OPT_NO_PASSWORD;
    1749                 }
    1750 
    1751                 if (pi->options & OPT_PROTO_PASSWORD_OPTIONAL) {
    1752                         ret->options |= PRPL_OPT_PASSWORD_OPTIONAL;
    1753                 }
    1754 
    17551532                register_protocol(ret);
    17561533
     
    17621539                        ret = g_memdup(&funcs, sizeof(funcs));
    17631540                        ret->name = "oscar";
    1764                         /* purple_get_account_prpl_id() determines the actual protocol ID (icq/aim) */
    1765                         ret->data = NULL;
     1541                        ret->data = prot->info->id;
    17661542                        register_protocol(ret);
    17671543                }
  • protocols/skype/skype.c

    r537d9b9 rba52ac5  
    17631763        register_protocol(ret);
    17641764}
    1765 
    1766 struct plugin_info *init_plugin_info(void)
    1767 {
    1768         static struct plugin_info info = {
    1769                 BITLBEE_ABI_VERSION_CODE,
    1770                 "skype",
    1771                 BITLBEE_VERSION,
    1772                 "Skype protocol plugin",
    1773                 NULL,
    1774                 NULL
    1775         };
    1776 
    1777         return &info;
    1778 }
  • protocols/twitter/twitter.c

    r537d9b9 rba52ac5  
    345345                imcb_log(ic, "Getting contact list");
    346346                twitter_get_friends_ids(ic, -1);
    347                 twitter_get_mutes_ids(ic, -1);
    348                 twitter_get_noretweets_ids(ic, -1);
    349347        } else {
    350348                twitter_main_loop_start(ic);
     
    471469        g_regex_match(regex, msg, 0, &match_info);
    472470        while (g_match_info_matches(match_info)) {
    473                 gchar *url;
     471                gchar *s, *url;
    474472
    475473                url = g_match_info_fetch(match_info, 2);
    476474                url_len_diff += target_len - g_utf8_strlen(url, -1);
    477475
     476                /* Add another character for https://t.co/... URLs */
     477                if ((s = g_match_info_fetch(match_info, 3))) {
     478                        url_len_diff += 1;
     479                        g_free(s);
     480                }
    478481                g_free(url);
    479482                g_match_info_next(match_info, NULL);
     
    538541        if (strcmp(acc->prpl->name, "twitter") == 0) {
    539542                def_url = TWITTER_API_URL;
    540                 def_tul = "23";
     543                def_tul = "22";
    541544                def_mentions = "true";
    542545        } else {                /* if( strcmp( acc->prpl->name, "identica" ) == 0 ) */
     
    687690                }
    688691
    689                 g_slist_foreach(td->mutes_ids, (GFunc) g_free, NULL);
    690                 g_slist_free(td->mutes_ids);
    691 
    692                 g_slist_foreach(td->noretweets_ids, (GFunc) g_free, NULL);
    693                 g_slist_free(td->noretweets_ids);
    694 
    695692                http_close(td->stream);
    696693                twitter_filter_remove_all(ic);
     
    951948        } else if ((g_strcasecmp(cmd[0], "favourite") == 0 ||
    952949                    g_strcasecmp(cmd[0], "favorite") == 0 ||
    953                     g_strcasecmp(cmd[0], "fav") == 0 ||
    954                     g_strcasecmp(cmd[0], "like") == 0) && cmd[1]) {
     950                    g_strcasecmp(cmd[0], "fav") == 0) && cmd[1]) {
    955951                if ((id = twitter_message_id_from_command_arg(ic, cmd[1], NULL))) {
    956952                        twitter_favourite_tweet(ic, id);
     
    964960        } else if (g_strcasecmp(cmd[0], "unfollow") == 0 && cmd[1]) {
    965961                twitter_remove_buddy(ic, cmd[1], NULL);
    966                 goto eof;
    967         } else if (g_strcasecmp(cmd[0], "mute") == 0 && cmd[1]) {
    968                 twitter_mute_create_destroy(ic, cmd[1], 1);
    969                 goto eof;
    970         } else if (g_strcasecmp(cmd[0], "unmute") == 0 && cmd[1]) {
    971                 twitter_mute_create_destroy(ic, cmd[1], 0);
    972962                goto eof;
    973963        } else if ((g_strcasecmp(cmd[0], "report") == 0 ||
     
    10921082        struct prpl *ret = g_new0(struct prpl, 1);
    10931083
    1094         ret->options = PRPL_OPT_NOOTR | PRPL_OPT_NO_PASSWORD;
     1084        ret->options = OPT_NOOTR;
    10951085        ret->name = "twitter";
    10961086        ret->login = twitter_login;
     
    11191109        ret = g_memdup(ret, sizeof(struct prpl));
    11201110        ret->name = "identica";
    1121         ret->options =  PRPL_OPT_NOOTR;
    11221111        register_protocol(ret);
    11231112}
  • protocols/twitter/twitter.h

    r537d9b9 rba52ac5  
    6161
    6262        GSList *follow_ids;
    63         GSList *mutes_ids;
    64         GSList *noretweets_ids;
    6563        GSList *filters;
    6664
  • protocols/twitter/twitter_http.c

    r537d9b9 rba52ac5  
    7979        g_string_printf(request, "%s %s%s%s%s HTTP/1.1\r\n"
    8080                        "Host: %s\r\n"
    81                         "User-Agent: BitlBee " BITLBEE_VERSION "\r\n",
     81                        "User-Agent: BitlBee " BITLBEE_VERSION " " ARCH "/" CPU "\r\n",
    8282                        is_post ? "POST" : "GET",
    8383                        base_url ? base_url->file : td->url_path,
  • protocols/twitter/twitter_lib.c

    r537d9b9 rba52ac5  
    245245
    246246static void twitter_http_get_friends_ids(struct http_request *req);
    247 static void twitter_http_get_mutes_ids(struct http_request *req);
    248 static void twitter_http_get_noretweets_ids(struct http_request *req);
    249247
    250248/**
     
    259257        args[1] = g_strdup_printf("%" G_GINT64_FORMAT, next_cursor);
    260258        twitter_http(ic, TWITTER_FRIENDS_IDS_URL, twitter_http_get_friends_ids, ic, 0, args, 2);
    261 
    262         g_free(args[1]);
    263 }
    264 
    265 /**
    266  * Get the muted users ids.
    267  */
    268 void twitter_get_mutes_ids(struct im_connection *ic, gint64 next_cursor)
    269 {
    270         char *args[2];
    271 
    272         args[0] = "cursor";
    273         args[1] = g_strdup_printf("%" G_GINT64_FORMAT, next_cursor);
    274         twitter_http(ic, TWITTER_MUTES_IDS_URL, twitter_http_get_mutes_ids, ic, 0, args, 2);
    275 
    276         g_free(args[1]);
    277 }
    278 
    279 /**
    280  * Get the ids for users from whom we should ignore retweets.
    281  */
    282 void twitter_get_noretweets_ids(struct im_connection *ic, gint64 next_cursor)
    283 {
    284         char *args[2];
    285 
    286         args[0] = "cursor";
    287         args[1] = g_strdup_printf("%" G_GINT64_FORMAT, next_cursor);
    288         twitter_http(ic, TWITTER_NORETWEETS_IDS_URL, twitter_http_get_noretweets_ids, ic, 0, args, 2);
    289259
    290260        g_free(args[1]);
     
    364334                twitter_get_users_lookup(ic);
    365335        }
    366 
    367         txl->list = NULL;
    368         txl_free(txl);
    369 }
    370 
    371 /**
    372  * Callback for getting the mutes ids.
    373  */
    374 static void twitter_http_get_mutes_ids(struct http_request *req)
    375 {
    376         struct im_connection *ic = req->data;
    377         JSON_Value *parsed;
    378         struct twitter_xml_list *txl;
    379         struct twitter_data *td;
    380 
    381         // Check if the connection is stil active
    382         if (!g_slist_find(twitter_connections, ic)) {
    383                 return;
    384         }
    385 
    386         td = ic->proto_data;
    387 
    388         if (req->status_code != 200) {
    389                 /* Fail silently */
    390                 return;
    391         }
    392 
    393         // Parse the data.
    394         if (!(parsed = twitter_parse_response(ic, req))) {
    395                 return;
    396         }
    397 
    398         txl = g_new0(struct twitter_xml_list, 1);
    399         txl->list = td->mutes_ids;
    400 
    401         /* mute ids API response is similar enough to friends response
    402            to reuse this method */
    403         twitter_xt_get_friends_id_list(parsed, txl);
    404         json_value_free(parsed);
    405 
    406         td->mutes_ids = txl->list;
    407         if (txl->next_cursor) {
    408                 /* Recurse while there are still more pages */
    409                 twitter_get_mutes_ids(ic, txl->next_cursor);
    410         }
    411 
    412         txl->list = NULL;
    413         txl_free(txl);
    414 }
    415 
    416 /**
    417  * Callback for getting the no-retweets ids.
    418  */
    419 static void twitter_http_get_noretweets_ids(struct http_request *req)
    420 {
    421         struct im_connection *ic = req->data;
    422         JSON_Value *parsed;
    423         struct twitter_xml_list *txl;
    424         struct twitter_data *td;
    425 
    426         // Check if the connection is stil active
    427         if (!g_slist_find(twitter_connections, ic)) {
    428                 return;
    429         }
    430 
    431         if (req->status_code != 200) {
    432                 /* Fail silently */
    433                 return;
    434         }
    435 
    436         td = ic->proto_data;
    437 
    438         // Parse the data.
    439         if (!(parsed = twitter_parse_response(ic, req))) {
    440                 return;
    441         }
    442 
    443         txl = g_new0(struct twitter_xml_list, 1);
    444         txl->list = td->noretweets_ids;
    445        
    446         // Process the retweet ids
    447         txl->type = TXL_ID;
    448         if (json_type(parsed) == JSONArray) {
    449                 JSON_Array *arr = json_array(parsed);
    450                 unsigned int i;
    451                 for (i = 0; i < json_array_get_count(arr); i++) {
    452                         jint id = json_array_get_integer(arr, i);
    453                         txl->list = g_slist_prepend(txl->list,
    454                                                     g_strdup_printf("%lld", id));
    455                 }
    456         }
    457 
    458         json_value_free(parsed);
    459         td->noretweets_ids = txl->list;
    460336
    461337        txl->list = NULL;
     
    591467#endif
    592468
    593 static void expand_entities(char **text, const JSON_Object *node, const JSON_Object *extended_node);
     469static void expand_entities(char **text, const JSON_Object *node);
    594470
    595471/**
     
    603479static struct twitter_xml_status *twitter_xt_get_status(const JSON_Object *node)
    604480{
    605         struct twitter_xml_status *txs = {0};
     481        struct twitter_xml_status *txs;
    606482        const JSON_Object *rt = NULL;
    607         const JSON_Value *text_value = NULL;
    608         const JSON_Object *extended_node = NULL;
    609483
    610484        if (!node) {
     
    614488
    615489        JSON_O_FOREACH(node, k, v) {
    616                 if (strcmp("text", k) == 0 && json_type(v) == JSONString && text_value == NULL) {
    617                         text_value = v;
    618                 } else if (strcmp("full_text", k) == 0 && json_type(v) == JSONString) {
    619                         text_value = v;
    620                 } else if (strcmp("extended_tweet", k) == 0 && json_type(v) == JSONObject) {
    621                         text_value = json_object_get_value(json_object(v), "full_text");
    622                         extended_node = json_object(v);
     490                if (strcmp("text", k) == 0 && (txs->text = g_strdup(json_string(v)))) {
     491                        // TODO: Huh strip html? In json? Not sure whether I have to..
     492                        strip_html(txs->text);
    623493                } else if (strcmp("retweeted_status", k) == 0 && (rt = json_object(v))) {
    624494                        // Handling below.
     
    646516                struct twitter_xml_status *rtxs = twitter_xt_get_status(rt);
    647517                if (rtxs) {
     518                        g_free(txs->text);
    648519                        txs->text = g_strdup_printf("RT @%s: %s", rtxs->user->screen_name, rtxs->text);
    649520                        txs->id = rtxs->id;
    650521                        txs_free(rtxs);
    651522                }
    652         } else if (text_value && json_type(text_value) == JSONString) {
    653                 txs->text = g_strdup(json_string(text_value));
    654                 strip_html(txs->text);
    655                 expand_entities(&txs->text, node, extended_node);
     523        } else {
     524                expand_entities(&txs->text, node);
    656525        }
    657526
     
    695564        }
    696565
    697         expand_entities(&txs->text, node, NULL);
     566        expand_entities(&txs->text, node);
    698567
    699568        if (txs->text && txs->user && txs->id) {
     
    705574}
    706575
    707 static void expand_entities(char **text, const JSON_Object *node, const JSON_Object *extended_node)
    708 {
    709         JSON_Object *entities, *extended_entities, *quoted;
     576static void expand_entities(char **text, const JSON_Object *node)
     577{
     578        JSON_Object *entities, *quoted;
    710579        char *quote_url = NULL, *quote_text = NULL;
    711580
     
    725594        }
    726595
    727         if (extended_node) {
    728                 extended_entities = json_object_get_object(extended_node, "entities");
    729                 if (extended_entities) {
    730                         entities = extended_entities;
    731                 }
    732         }
    733 
    734596        JSON_O_FOREACH(entities, k, v) {
    735597                int i;
     
    975837        struct twitter_data *td = ic->proto_data;
    976838        char *last_id_str;
    977         char *uid_str;
    978839
    979840        if (status->user == NULL || status->text == NULL) {
    980                 return;
    981         }
    982        
    983         /* Check this is not a tweet that should be muted */
    984         uid_str = g_strdup_printf("%" G_GUINT64_FORMAT, status->user->uid);
    985 
    986         if (g_slist_find_custom(td->mutes_ids, uid_str, (GCompareFunc)strcmp)) {
    987                 g_free(uid_str);
    988                 return;
    989         }
    990         if (status->id != status->rt_id && g_slist_find_custom(td->noretweets_ids, uid_str, (GCompareFunc)strcmp)) {
    991                 g_free(uid_str);
    992841                return;
    993842        }
     
    1014863        set_setstr(&ic->acc->set, "_last_tweet", last_id_str);
    1015864        g_free(last_id_str);
    1016         g_free(uid_str);
    1017865}
    1018866
     
    1032880        }
    1033881
     882        ic->flags |= OPT_PONGED;
    1034883        td = ic->proto_data;
    1035884
     
    1047896                imc_logout(ic, TRUE);
    1048897                return;
    1049         }
    1050 
    1051         if (req == td->stream) {
    1052                 ic->flags |= OPT_PONGED;
    1053898        }
    1054899
     
    1154999        JSON_Object *target = json_object_get_object(o, "target");
    11551000        const char *type = json_object_get_string(o, "event");
    1156         struct twitter_xml_user *us = NULL;
    1157         struct twitter_xml_user *ut = NULL;
    11581001
    11591002        if (!type || !source || !target) {
     
    11621005
    11631006        if (strcmp(type, "follow") == 0) {
    1164                 us = twitter_xt_get_user(source);
    1165                 ut = twitter_xt_get_user(target);
     1007                struct twitter_xml_user *us = twitter_xt_get_user(source);
     1008                struct twitter_xml_user *ut = twitter_xt_get_user(target);
    11661009                if (g_strcasecmp(us->screen_name, td->user) == 0) {
    11671010                        twitter_add_buddy(ic, ut->screen_name, ut->name);
    11681011                }
    1169         } else if (strcmp(type, "mute") == 0) {
    1170                 GSList *found;
    1171                 char *uid_str;
    1172                 ut = twitter_xt_get_user(target);
    1173                 uid_str = g_strdup_printf("%" G_GUINT64_FORMAT, ut->uid);
    1174                 if (!(found = g_slist_find_custom(td->mutes_ids, uid_str,
    1175                                                   (GCompareFunc)strcmp))) {
    1176                         td->mutes_ids = g_slist_prepend(td->mutes_ids, uid_str);
    1177                 }
    1178                 twitter_log(ic, "Muted user %s", ut->screen_name);
    1179                 if (getenv("BITLBEE_DEBUG")) {
    1180                         fprintf(stderr, "New mute: %s %"G_GUINT64_FORMAT"\n",
    1181                                 ut->screen_name, ut->uid);
    1182                 }
    1183         } else if (strcmp(type, "unmute") == 0) {
    1184                 GSList *found;
    1185                 char *uid_str;
    1186                 ut = twitter_xt_get_user(target);
    1187                 uid_str = g_strdup_printf("%" G_GUINT64_FORMAT, ut->uid);
    1188                 if ((found = g_slist_find_custom(td->mutes_ids, uid_str,
    1189                                                 (GCompareFunc)strcmp))) {
    1190                         char *found_str = found->data;
    1191                         td->mutes_ids = g_slist_delete_link(td->mutes_ids, found);
    1192                         g_free(found_str);
    1193                 }
    1194                 g_free(uid_str);
    1195                 twitter_log(ic, "Unmuted user %s", ut->screen_name);
    1196                 if (getenv("BITLBEE_DEBUG")) {
    1197                         fprintf(stderr, "New unmute: %s %"G_GUINT64_FORMAT"\n",
    1198                                 ut->screen_name, ut->uid);
    1199                 }
    1200         }
    1201 
    1202         txu_free(us);
    1203         txu_free(ut);
     1012                txu_free(us);
     1013                txu_free(ut);
     1014        }
    12041015
    12051016        return TRUE;
     
    14981309        td->flags &= ~TWITTER_GOT_TIMELINE;
    14991310
    1500         char *args[8];
     1311        char *args[6];
    15011312        args[0] = "cursor";
    15021313        args[1] = g_strdup_printf("%" G_GINT64_FORMAT, next_cursor);
    15031314        args[2] = "include_entities";
    15041315        args[3] = "true";
    1505         args[4] = "tweet_mode";
    1506         args[5] = "extended";
    15071316        if (td->timeline_id) {
    1508                 args[6] = "since_id";
    1509                 args[7] = g_strdup_printf("%" G_GUINT64_FORMAT, td->timeline_id);
     1317                args[4] = "since_id";
     1318                args[5] = g_strdup_printf("%" G_GUINT64_FORMAT, td->timeline_id);
    15101319        }
    15111320
    15121321        if (twitter_http(ic, TWITTER_HOME_TIMELINE_URL, twitter_http_get_home_timeline, ic, 0, args,
    1513                          td->timeline_id ? 8 : 6) == NULL) {
     1322                         td->timeline_id ? 6 : 4) == NULL) {
    15141323                if (++td->http_fails >= 5) {
    15151324                        imcb_error(ic, "Could not retrieve %s: %s",
     
    15221331        g_free(args[1]);
    15231332        if (td->timeline_id) {
    1524                 g_free(args[7]);
     1333                g_free(args[5]);
    15251334        }
    15261335}
     
    15371346        td->flags &= ~TWITTER_GOT_MENTIONS;
    15381347
    1539         char *args[8];
     1348        char *args[6];
    15401349        args[0] = "cursor";
    15411350        args[1] = g_strdup_printf("%" G_GINT64_FORMAT, next_cursor);
     
    15491358                args[5] = g_strdup_printf("%d", set_getint(&ic->acc->set, "show_old_mentions"));
    15501359        }
    1551         args[6] = "tweet_mode";
    1552         args[7] = "extended";
    15531360
    15541361        if (twitter_http(ic, TWITTER_MENTIONS_URL, twitter_http_get_mentions,
    1555                          ic, 0, args, 8) == NULL) {
     1362                         ic, 0, args, 6) == NULL) {
    15561363                if (++td->http_fails >= 5) {
    15571364                        imcb_error(ic, "Could not retrieve %s: %s",
     
    17221529}
    17231530
    1724 /**
    1725  * Mute or unmute a user
    1726  */
    1727 void twitter_mute_create_destroy(struct im_connection *ic, char *who, int create)
    1728 {
    1729         char *args[2];
    1730 
    1731         args[0] = "screen_name";
    1732         args[1] = who;
    1733         twitter_http(ic, create ? TWITTER_MUTES_CREATE_URL : TWITTER_MUTES_DESTROY_URL,
    1734                      twitter_http_post, ic, 1, args, 2);
    1735 }
    1736 
    17371531void twitter_status_destroy(struct im_connection *ic, guint64 id)
    17381532{
  • protocols/twitter/twitter_lib.h

    r537d9b9 rba52ac5  
    6363#define TWITTER_FRIENDS_IDS_URL "/friends/ids.json"
    6464#define TWITTER_FOLLOWERS_IDS_URL "/followers/ids.json"
    65 #define TWITTER_MUTES_IDS_URL "/mutes/users/ids.json"
    66 #define TWITTER_NORETWEETS_IDS_URL "/friendships/no_retweets/ids.json"
    6765
    6866/* Account URLs */
     
    7876#define TWITTER_BLOCKS_DESTROY_URL "/blocks/destroy/"
    7977
    80 /* Mute URLs */
    81 #define TWITTER_MUTES_CREATE_URL "/mutes/users/create.json"
    82 #define TWITTER_MUTES_DESTROY_URL "/mutes/users/destroy.json"
    83 
    8478/* Report spam */
    8579#define TWITTER_REPORT_SPAM_URL "/users/report_spam.json"
     
    9387gboolean twitter_get_timeline(struct im_connection *ic, gint64 next_cursor);
    9488void twitter_get_friends_ids(struct im_connection *ic, gint64 next_cursor);
    95 void twitter_get_mutes_ids(struct im_connection *ic, gint64 next_cursor);
    96 void twitter_get_noretweets_ids(struct im_connection *ic, gint64 next_cursor);
    9789void twitter_get_statuses_friends(struct im_connection *ic, gint64 next_cursor);
    9890
     
    10092void twitter_direct_messages_new(struct im_connection *ic, char *who, char *message);
    10193void twitter_friendships_create_destroy(struct im_connection *ic, char *who, int create);
    102 void twitter_mute_create_destroy(struct im_connection *ic, char *who, int create);
    10394void twitter_status_destroy(struct im_connection *ic, guint64 id);
    10495void twitter_status_retweet(struct im_connection *ic, guint64 id);
  • root_commands.c

    r537d9b9 rba52ac5  
    143143        }
    144144
    145         status = auth_check_pass(irc, irc->user->nick, password);
    146         if (load && (status == STORAGE_OK)) {
     145        if (load) {
    147146                status = storage_load(irc, password);
     147        } else {
     148                status = storage_check_pass(irc->user->nick, password);
    148149        }
    149150
     
    158159                irc_rootmsg(irc, "Password accepted%s",
    159160                            load ? ", settings and accounts loaded" : "");
     161                irc_setpass(irc, password);
    160162                irc->status |= USTATUS_IDENTIFIED;
    161163                irc_umode_set(irc, "+R", 1);
     
    266268        storage_status_t status;
    267269
    268         status = auth_check_pass(irc, irc->user->nick, cmd[1]);
    269         if (status == STORAGE_OK) {
    270                 status = storage_remove(irc->user->nick);
    271         }
    272 
     270        status = storage_remove(irc->user->nick, cmd[1]);
    273271        switch (status) {
    274272        case STORAGE_NO_SUCH_USER:
     
    342340                int st;
    343341
    344                 if (s && s->flags & SET_LOCKED) {
    345                         irc_rootmsg(irc, "This setting can not be changed");
    346                         return 0;
    347                 }
    348342                if (s && checkflags && checkflags(irc, s) == 0) {
    349343                        return 0;
     
    394388                irc_rootmsg(irc, "This setting can only be changed when the account is %s-line", "on");
    395389                return 0;
    396         } else if (a->flags & ACC_FLAG_LOCKED && s && s->flags & ACC_SET_LOCKABLE) {
    397                 irc_rootmsg(irc, "This setting can not be changed for locked accounts");
    398                 return 0;
    399390        }
    400391
     
    418409
    419410                MIN_ARGS(3);
    420 
    421                 if (!global.conf->allow_account_add) {
    422                         irc_rootmsg(irc, "This server does not allow adding new accounts");
    423                         return;
    424                 }
    425411
    426412                if (cmd[4] == NULL) {
     
    470456                                irc_rootmsg(irc, "No need to enter a password for this "
    471457                                            "account since it's using OAuth");
    472                         } else if (prpl->options & PRPL_OPT_NO_PASSWORD) {
    473                                 *a->pass = '\0';
    474                         } else if (prpl->options & PRPL_OPT_PASSWORD_OPTIONAL) {
    475                                 *a->pass = '\0';
    476                                 irc_rootmsg(irc, "Passwords are optional for this account. "
    477                                             "If you wish to enter the password with /OPER, do "
    478                                             "account %s set -del password", a->tag);
    479458                        } else {
    480459                                irc_rootmsg(irc, "You can now use the /OPER command to "
     
    486465                                }
    487466                        }
    488                 } else if (prpl->options & PRPL_OPT_NO_PASSWORD) {
    489                         irc_rootmsg(irc, "Note: this account doesn't use password for login");
    490467                }
    491468
     
    576553
    577554        if (len >= 1 && g_strncasecmp(cmd[2], "del", len) == 0) {
    578                 if (a->flags & ACC_FLAG_LOCKED) {
    579                         irc_rootmsg(irc, "Account is locked, can't delete");
    580                 }
    581                 else if (a->ic) {
     555                if (a->ic) {
    582556                        irc_rootmsg(irc, "Account is still logged in, can't delete");
    583557                } else {
     
    11341108}
    11351109
    1136 static gint prplcmp(gconstpointer a, gconstpointer b)
    1137 {
    1138         const struct prpl *pa = a;
    1139         const struct prpl *pb = b;
    1140 
    1141         return g_strcasecmp(pa->name, pb->name);
    1142 }
    1143 
    1144 static void prplstr(GList *prpls, GString *gstr)
    1145 {
    1146         const char *last = NULL;
    1147         GList *l;
    1148         struct prpl *p;
    1149 
    1150         prpls = g_list_copy(prpls);
    1151         prpls = g_list_sort(prpls, prplcmp);
    1152 
    1153         for (l = prpls; l; l = l->next) {
    1154                 p = l->data;
    1155 
    1156                 if (last && g_strcasecmp(p->name, last) == 0) {
    1157                         /* Ignore duplicates (mainly for libpurple) */
    1158                         continue;
    1159                 }
    1160 
    1161                 if (gstr->len != 0) {
    1162                         g_string_append(gstr, ", ");
    1163                 }
    1164 
    1165                 g_string_append(gstr, p->name);
    1166                 last = p->name;
    1167         }
    1168 
    1169         g_list_free(prpls);
    1170 }
    1171 
    1172 static void cmd_plugins(irc_t *irc, char **cmd)
    1173 {
    1174         GList *prpls;
    1175         GString *gstr;
    1176 
    1177 #ifdef WITH_PLUGINS
    1178         GList *l;
    1179         struct plugin_info *info;
    1180 
    1181         for (l = get_plugins(); l; l = l->next) {
    1182                 info = l->data;
    1183                 irc_rootmsg(irc, "%s:", info->name);
    1184                 irc_rootmsg(irc, "  Version: %s", info->version);
    1185 
    1186                 if (info->description) {
    1187                         irc_rootmsg(irc, "  Description: %s", info->description);
    1188                 }
    1189 
    1190                 if (info->author) {
    1191                         irc_rootmsg(irc, "  Author: %s", info->author);
    1192                 }
    1193 
    1194                 if (info->url) {
    1195                         irc_rootmsg(irc, "  URL: %s", info->url);
    1196                 }
    1197 
    1198                 irc_rootmsg(irc, "");
    1199         }
    1200 #endif
    1201 
    1202         gstr = g_string_new(NULL);
    1203         prpls = get_protocols();
    1204 
    1205         if (prpls) {
    1206                 prplstr(prpls, gstr);
    1207                 irc_rootmsg(irc, "Enabled Protocols: %s", gstr->str);
    1208                 g_string_truncate(gstr, 0);
    1209         }
    1210 
    1211         prpls = get_protocols_disabled();
    1212 
    1213         if (prpls) {
    1214                 prplstr(prpls, gstr);
    1215                 irc_rootmsg(irc, "Disabled Protocols: %s", gstr->str);
    1216         }
    1217 
    1218         g_string_free(gstr, TRUE);
    1219 }
    1220 
    12211110static void cmd_qlist(irc_t *irc, char **cmd)
    12221111{
     
    12451134
    12461135        if (g_strcasecmp(cmd[1], "add") == 0) {
    1247                 bee_chat_info_t *ci;
    1248                 char *channel, *room, *s;
     1136                char *channel, *s;
    12491137                struct irc_channel *ic;
    1250                 guint i;
    12511138
    12521139                MIN_ARGS(3);
     
    12601147                }
    12611148
    1262                 if (cmd[3][0] == '!') {
    1263                         if (!acc->ic || !(acc->ic->flags & OPT_LOGGED_IN)) {
    1264                                 irc_rootmsg(irc, "Not logged in to account.");
    1265                                 return;
    1266                         } else if (!acc->prpl->chat_list) {
    1267                                 irc_rootmsg(irc, "Listing chatrooms not supported on that account.");
    1268                                 return;
    1269                         }
    1270 
    1271                         i = g_ascii_strtoull(cmd[3] + 1, NULL, 10);
    1272                         ci = g_slist_nth_data(acc->ic->chatlist, i - 1);
    1273 
    1274                         if (ci == NULL) {
    1275                                 irc_rootmsg(irc, "Invalid chatroom index");
    1276                                 return;
    1277                         }
    1278 
    1279                         room = ci->title;
    1280                 } else {
    1281                         room = cmd[3];
    1282                 }
    1283 
    12841149                if (cmd[4] == NULL) {
    1285                         channel = g_strdup(room);
     1150                        channel = g_strdup(cmd[3]);
    12861151                        if ((s = strchr(channel, '@'))) {
    12871152                                *s = 0;
     
    13031168                    set_setstr(&ic->set, "chat_type", "room") &&
    13041169                    set_setstr(&ic->set, "account", cmd[2]) &&
    1305                     set_setstr(&ic->set, "room", room)) {
     1170                    set_setstr(&ic->set, "room", cmd[3])) {
    13061171                        irc_rootmsg(irc, "Chatroom successfully added.");
    13071172                } else {
     
    13131178                }
    13141179                g_free(channel);
    1315         } else if (g_strcasecmp(cmd[1], "list") == 0) {
    1316                 MIN_ARGS(2);
    1317 
    1318                 if (!(acc = account_get(irc->b, cmd[2]))) {
    1319                         irc_rootmsg(irc, "Invalid account");
    1320                         return;
    1321                 } else if (!acc->ic || !(acc->ic->flags & OPT_LOGGED_IN)) {
    1322                         irc_rootmsg(irc, "Not logged in to account.");
    1323                         return;
    1324                 } else if (!acc->prpl->chat_list) {
    1325                         irc_rootmsg(irc, "Listing chatrooms not supported on that account.");
    1326                         return;
    1327                 }
    1328 
    1329                 acc->prpl->chat_list(acc->ic, cmd[3]);
    13301180        } else if (g_strcasecmp(cmd[1], "with") == 0) {
    13311181                irc_user_t *iu;
     
    13421192                        irc_rootmsg(irc, "Can't open a groupchat with %s.", cmd[2]);
    13431193                }
    1344         } else if (g_strcasecmp(cmd[1], "set") == 0 ||
     1194        } else if (g_strcasecmp(cmd[1], "list") == 0 ||
     1195                   g_strcasecmp(cmd[1], "set") == 0 ||
    13451196                   g_strcasecmp(cmd[1], "del") == 0) {
    13461197                irc_rootmsg(irc,
     
    13521203                            cmd[1]);
    13531204        }
    1354 }
    1355 
    1356 /* some arbitrary numbers */
    1357 #define CHAT_TITLE_LEN_MIN 20
    1358 #define CHAT_TITLE_LEN_MAX 100
    1359 
    1360 void cmd_chat_list_finish(struct im_connection *ic)
    1361 {
    1362         account_t *acc = ic->acc;
    1363         bee_chat_info_t *ci;
    1364         char *hformat, *iformat, *topic, *padded;
    1365         GSList *l;
    1366         guint i = 0;
    1367         long title_len, new_len;
    1368         irc_t *irc = ic->bee->ui_data;
    1369 
    1370         if (ic->chatlist == NULL) {
    1371                 irc_rootmsg(irc, "No existing chatrooms");
    1372                 return;
    1373         }
    1374 
    1375         /* find a reasonable width for the table */
    1376         title_len = CHAT_TITLE_LEN_MIN;
    1377 
    1378         for (l = ic->chatlist; l; l = l->next) {
    1379                 ci = l->data;
    1380                 new_len = g_utf8_strlen(ci->title, -1);
    1381 
    1382                 if (new_len >= CHAT_TITLE_LEN_MAX) {
    1383                         title_len = CHAT_TITLE_LEN_MAX;
    1384                         break;
    1385                 } else if (title_len < new_len) {
    1386                         title_len = new_len;
    1387                 }
    1388         }
    1389 
    1390         if (strchr(irc->umode, 'b') != NULL) {
    1391                 hformat = "%s\t%s\t%s";
    1392                 iformat = "%u\t%s\t%s";
    1393         } else {
    1394                 hformat = "%s  %s  %s";
    1395                 iformat = "%5u  %s  %s";
    1396         }
    1397 
    1398         padded = str_pad_and_truncate("Title", title_len, NULL);
    1399         irc_rootmsg(irc, hformat, "Index", padded, "Topic");
    1400         g_free(padded);
    1401 
    1402         for (l = ic->chatlist; l; l = l->next) {
    1403                 ci = l->data;
    1404                 topic = ci->topic ? ci->topic : "";
    1405 
    1406                 padded = str_pad_and_truncate(ci->title, title_len, "[...]");
    1407                 irc_rootmsg(irc, iformat, ++i, padded, topic);
    1408                 g_free(padded);
    1409         }
    1410 
    1411         irc_rootmsg(irc, "%u %s chatrooms", i, acc->tag);
    14121205}
    14131206
     
    14631256{
    14641257        GSList *files = irc->file_transfers;
    1465         GSList *next;
    14661258
    14671259        enum { LIST, REJECT, CANCEL };
     
    14811273        }
    14821274
    1483         for (; files; files = next) {
    1484                 next = files->next;
     1275        for (; files; files = g_slist_next(files)) {
    14851276                file_transfer_t *file = files->data;
    14861277
     
    15661357        { "nick",           1, cmd_nick,           0 },
    15671358        { "no",             0, cmd_yesno,          0 },
    1568         { "plugins",        0, cmd_plugins,        0 },
    15691359        { "qlist",          0, cmd_qlist,          0 },
    15701360        { "register",       0, cmd_register,       0 },
  • set.h

    r537d9b9 rba52ac5  
    4949        SET_PASSWORD = 0x0400, /* Value shows up in settings list as "********". */
    5050        SET_HIDDEN_DEFAULT = 0x0800, /* Hide unless changed from default. */
    51         SET_LOCKED = 0x1000    /* Setting is locked, don't allow changing it */
    5251} set_flags_t;
    5352
  • storage.c

    r537d9b9 rba52ac5  
    2929#include "bitlbee.h"
    3030
     31extern storage_t storage_text;
    3132extern storage_t storage_xml;
    3233
     
    9192}
    9293
    93 storage_status_t storage_check_pass(irc_t *irc, const char *nick, const char *password)
     94storage_status_t storage_check_pass(const char *nick, const char *password)
    9495{
    9596        GList *gl;
     
    101102                storage_status_t status;
    102103
    103                 status = st->check_pass(irc, nick, password);
     104                status = st->check_pass(nick, password);
    104105                if (status != STORAGE_NO_SUCH_USER) {
    105106                        return status;
     
    175176}
    176177
    177 storage_status_t storage_remove(const char *nick)
     178storage_status_t storage_remove(const char *nick, const char *password)
    178179{
    179180        GList *gl;
     
    189190                storage_status_t status;
    190191
    191                 status = st->remove(nick);
     192                status = st->remove(nick, password);
    192193                ok |= status == STORAGE_OK;
    193194                if (status != STORAGE_NO_SUCH_USER && status != STORAGE_OK) {
  • storage.h

    r537d9b9 rba52ac5  
    3131        STORAGE_NO_SUCH_USER,
    3232        STORAGE_INVALID_PASSWORD,
    33         STORAGE_CHECK_BACKEND,
    3433        STORAGE_ALREADY_EXISTS,
    3534        STORAGE_OTHER_ERROR /* Error that isn't caused by user input, such as
     
    4443        void (*init)(void);
    4544
    46         storage_status_t (*check_pass)(irc_t *irc, const char *nick, const char *password);
     45        storage_status_t (*check_pass)(const char *nick, const char *password);
    4746
    4847        storage_status_t (*load)(irc_t *irc, const char *password);
    4948        storage_status_t (*save)(irc_t *irc, int overwrite);
    50         storage_status_t (*remove)(const char *nick);
     49        storage_status_t (*remove)(const char *nick, const char *password);
    5150
    5251        /* May be NULL if not supported by backend */
     
    5453} storage_t;
    5554
    56 storage_status_t storage_check_pass(irc_t *irc, const char *nick, const char *password);
     55storage_status_t storage_check_pass(const char *nick, const char *password);
    5756
    5857storage_status_t storage_load(irc_t * irc, const char *password);
    5958storage_status_t storage_save(irc_t *irc, char *password, int overwrite);
    60 storage_status_t storage_remove(const char *nick);
     59storage_status_t storage_remove(const char *nick, const char *password);
    6160
    6261void register_storage_backend(storage_t *);
  • storage_xml.c

    r537d9b9 rba52ac5  
    3434
    3535typedef enum {
    36         XML_PASS_CHECK = 0,
    37         XML_LOAD
    38 } xml_action;
     36        XML_PASS_CHECK_ONLY = -1,
     37        XML_PASS_UNKNOWN = 0,
     38        XML_PASS_WRONG,
     39        XML_PASS_OK
     40} xml_pass_st;
    3941
    4042/* To make it easier later when extending the format: */
     
    6365{
    6466        struct xt_node *c;
    65         struct set *s;
    6667
    6768        for (c = node->children; (c = xt_find_node(c, "setting")); c = c->next) {
    6869                char *name = xt_find_attr(c, "name");
    69                 char *locked = xt_find_attr(c, "locked");
    7070
    7171                if (!name) {
     
    8080                }
    8181                set_setstr(head, name, c->text);
    82                 if (locked && !g_strcasecmp(locked, "true")) {
    83                         s = set_find(head, name);
    84                         if (s) {
    85                                 s->flags |= SET_LOCKED;
    86                         }
    87                 }
    8882        }
    8983}
     
    111105{
    112106        struct xml_parsedata *xd = data;
    113         char *protocol, *handle, *server, *password = NULL, *autoconnect, *tag, *locked;
     107        char *protocol, *handle, *server, *password = NULL, *autoconnect, *tag;
    114108        char *pass_b64 = NULL;
    115109        unsigned char *pass_cr = NULL;
     
    124118        autoconnect = xt_find_attr(node, "autoconnect");
    125119        tag = xt_find_attr(node, "tag");
    126         locked = xt_find_attr(node, "locked");
    127120
    128121        protocol = xt_find_attr(node, "protocol");
     
    137130        if (!handle || !pass_b64 || !protocol || !prpl) {
    138131                return XT_ABORT;
    139         }
    140 
    141         pass_len = base64_decode(pass_b64, (unsigned char **) &pass_cr);
    142         if (xd->irc->auth_backend) {
    143                 password = g_strdup((char *)pass_cr);
     132        } else if ((pass_len = base64_decode(pass_b64, (unsigned char **) &pass_cr)) &&
     133                   arc_decode(pass_cr, pass_len, &password, xd->given_pass) >= 0) {
     134                acc = account_add(xd->irc->b, prpl, handle, password);
     135                if (server) {
     136                        set_setstr(&acc->set, "server", server);
     137                }
     138                if (autoconnect) {
     139                        set_setstr(&acc->set, "auto_connect", autoconnect);
     140                }
     141                if (tag) {
     142                        set_setstr(&acc->set, "tag", tag);
     143                }
     144                if (prpl == &protocol_missing) {
     145                        set_t *s = set_add(&acc->set, "_protocol_name", protocol, NULL, NULL);
     146                        s->flags |= SET_HIDDEN | SET_NOSAVE |
     147                                    ACC_SET_OFFLINE_ONLY | ACC_SET_ONLINE_ONLY;
     148                }
    144149        } else {
    145                 pass_len = arc_decode(pass_cr, pass_len, &password, xd->given_pass);
    146                 if (pass_len < 0) {
    147                         g_free(pass_cr);
    148                         g_free(password);
    149                         return XT_ABORT;
    150                 }
    151         }
    152 
    153         acc = account_add(xd->irc->b, prpl, handle, password);
    154         if (server) {
    155                 set_setstr(&acc->set, "server", server);
    156         }
    157         if (autoconnect) {
    158                 set_setstr(&acc->set, "auto_connect", autoconnect);
    159         }
    160         if (tag) {
    161                 set_setstr(&acc->set, "tag", tag);
    162         }
    163         if (locked && !g_strcasecmp(locked, "true")) {
    164                 acc->flags |= ACC_FLAG_LOCKED;
    165         }
    166         if (prpl == &protocol_missing) {
    167                 set_t *s = set_add(&acc->set, "_protocol_name", protocol, NULL, NULL);
    168                 s->flags |= SET_HIDDEN | SET_NOSAVE |
    169                             ACC_SET_OFFLINE_ONLY | ACC_SET_ONLINE_ONLY;
     150                g_free(pass_cr);
     151                g_free(password);
     152                return XT_ABORT;
    170153        }
    171154
     
    227210};
    228211
    229 static storage_status_t xml_load_real(irc_t *irc, const char *my_nick, const char *password, xml_action action)
     212static storage_status_t xml_load_real(irc_t *irc, const char *my_nick, const char *password, xml_pass_st action)
    230213{
    231214        struct xml_parsedata xd[1];
     
    269252        }
    270253
    271         if (action == XML_PASS_CHECK) {
     254        {
    272255                char *nick = xt_find_attr(node, "nick");
    273256                char *pass = xt_find_attr(node, "password");
    274                 char *backend = xt_find_attr(node, "auth_backend");
    275 
    276                 if (!nick || !(pass || backend)) {
     257
     258                if (!nick || !pass) {
    277259                        goto error;
    278                 }
    279 
    280                 if (backend) {
    281                         g_free(xd->irc->auth_backend);
    282                         xd->irc->auth_backend = g_strdup(backend);
    283                         ret = STORAGE_CHECK_BACKEND;
    284260                } else if ((st = md5_verify_password(xd->given_pass, pass)) != 0) {
    285261                        ret = STORAGE_INVALID_PASSWORD;
    286                 } else {
    287                         ret = STORAGE_OK;
    288                 }
    289                 goto error;
    290         }
    291 
     262                        goto error;
     263                }
     264        }
     265
     266        if (action == XML_PASS_CHECK_ONLY) {
     267                ret = STORAGE_OK;
     268                goto error;
     269        }
     270
     271        /* DO NOT call xt_handle() before verifying the password! */
    292272        if (xt_handle(xp, NULL, 1) == XT_HANDLED) {
    293273                ret = STORAGE_OK;
     
    304284static storage_status_t xml_load(irc_t *irc, const char *password)
    305285{
    306         return xml_load_real(irc, irc->user->nick, password, XML_LOAD);
    307 }
    308 
    309 static storage_status_t xml_check_pass(irc_t *irc, const char *my_nick, const char *password)
    310 {
    311         return xml_load_real(irc, my_nick, password, XML_PASS_CHECK);
     286        return xml_load_real(irc, irc->user->nick, password, XML_PASS_UNKNOWN);
     287}
     288
     289static storage_status_t xml_check_pass(const char *my_nick, const char *password)
     290{
     291        return xml_load_real(NULL, my_nick, password, XML_PASS_CHECK_ONLY);
    312292}
    313293
     
    324304        struct xt_node *root, *cur;
    325305
     306        /* Generate a salted md5sum of the password. Use 5 bytes for the salt
     307           (to prevent dictionary lookups of passwords) to end up with a 21-
     308           byte password hash, more convenient for base64 encoding. */
     309        random_bytes(pass_md5 + 16, 5);
     310        md5_init(&md5_state);
     311        md5_append(&md5_state, (md5_byte_t *) irc->password, strlen(irc->password));
     312        md5_append(&md5_state, pass_md5 + 16, 5);   /* Add the salt. */
     313        md5_finish(&md5_state, pass_md5);
     314        /* Save the hash in base64-encoded form. */
     315        pass_buf = base64_encode(pass_md5, 21);
     316
    326317        root = cur = xt_new_node("user", NULL, NULL);
    327         if (irc->auth_backend) {
    328                 xt_add_attr(cur, "auth_backend", irc->auth_backend);
    329         } else {
    330                 /* Generate a salted md5sum of the password. Use 5 bytes for the salt
    331                    (to prevent dictionary lookups of passwords) to end up with a 21-
    332                    byte password hash, more convenient for base64 encoding. */
    333                 random_bytes(pass_md5 + 16, 5);
    334                 md5_init(&md5_state);
    335                 md5_append(&md5_state, (md5_byte_t *) irc->password, strlen(irc->password));
    336                 md5_append(&md5_state, pass_md5 + 16, 5);   /* Add the salt. */
    337                 md5_finish(&md5_state, pass_md5);
    338                 /* Save the hash in base64-encoded form. */
    339                 pass_buf = base64_encode(pass_md5, 21);
    340                 xt_add_attr(cur, "password", pass_buf);
    341                 g_free(pass_buf);
    342         }
    343 
    344318        xt_add_attr(cur, "nick", irc->user->nick);
     319        xt_add_attr(cur, "password", pass_buf);
    345320        xt_add_attr(cur, "version", XML_FORMAT_VERSION);
     321
     322        g_free(pass_buf);
    346323
    347324        xml_generate_settings(cur, &irc->b->set);
     
    354331                int pass_len;
    355332
    356                 if(irc->auth_backend) {
    357                         /* If we don't "own" the password, it may change without us
    358                          * knowing, so we cannot encrypt the data, as we then may not be
    359                          * able to decrypt it */
    360                         pass_b64 = base64_encode((unsigned char *)acc->pass, strlen(acc->pass));
    361                 } else {
    362                         pass_len = arc_encode(acc->pass, strlen(acc->pass), (unsigned char **) &pass_cr, irc->password, 12);
    363                         pass_b64 = base64_encode(pass_cr, pass_len);
    364                         g_free(pass_cr);
    365                 }
     333                pass_len = arc_encode(acc->pass, strlen(acc->pass), (unsigned char **) &pass_cr, irc->password, 12);
     334                pass_b64 = base64_encode(pass_cr, pass_len);
     335                g_free(pass_cr);
    366336
    367337                cur = xt_new_node("account", NULL, NULL);
     
    378348                        xt_add_attr(cur, "server", acc->server);
    379349                }
    380                 if (acc->flags & ACC_FLAG_LOCKED) {
    381                         xt_add_attr(cur, "locked", "true");
    382                 }
    383350
    384351                g_free(pass_b64);
     
    425392                        xt_add_child(cur, xset = xt_new_node("setting", set->value, NULL));
    426393                        xt_add_attr(xset, "name", set->key);
    427                         if (set->flags & SET_LOCKED) {
    428                                 xt_add_attr(xset, "locked", "true");
    429                         }
    430394                }
    431395        }
     
    486450
    487451
    488 static storage_status_t xml_remove(const char *nick)
     452static storage_status_t xml_remove(const char *nick, const char *password)
    489453{
    490454        char s[512], *lc;
     455        storage_status_t status;
     456
     457        status = xml_check_pass(nick, password);
     458        if (status != STORAGE_OK) {
     459                return status;
     460        }
    491461
    492462        lc = g_strdup(nick);
  • tests/Makefile

    r537d9b9 rba52ac5  
    1515distclean: clean
    1616
    17 main_objs = bitlbee.o conf.o dcc.o help.o ipc.o irc.o irc_cap.o irc_channel.o irc_commands.o irc_im.o irc_send.o irc_user.o irc_util.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o $(STORAGE_OBJS) auth.o $(AUTH_OBJS)
     17main_objs = bitlbee.o conf.o dcc.o help.o ipc.o irc.o irc_cap.o irc_channel.o irc_commands.o irc_im.o irc_send.o irc_user.o irc_util.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o storage_xml.o
    1818
    1919test_objs = check.o check_util.o check_nick.o check_md5.o check_arc.o check_irc.o check_help.o check_user.o check_set.o check_jabber_sasl.o check_jabber_util.o
  • tests/check_jabber_util.c

    r537d9b9 rba52ac5  
    103103        fail_unless(jabber_compare_jid("bugtest@google.com/A", "bugtest@google.com/A"));
    104104        fail_if(jabber_compare_jid("", "bugtest@google.com/A"));
    105         fail_if(jabber_compare_jid(NULL, ""));
    106         fail_if(jabber_compare_jid("", NULL));
    107105}
    108106
  • tests/check_util.c

    r537d9b9 rba52ac5  
    137137                5,
    138138                "aaaaa\naaaaa\naaaaa\naaaaa\naaaaa\naaaaa\naaaaa\na",
    139         },
    140         {
    141                 "áááááááááá",
    142                 11,
    143                 "ááááá\nááááá",
    144139        },
    145140        {
  • unix.c

    r537d9b9 rba52ac5  
    8080        }
    8181
    82         if (global.conf->runmode == RUNMODE_INETD) {
    83                 log_link(LOGLVL_ERROR, LOGOUTPUT_IRC);
    84                 log_link(LOGLVL_WARNING, LOGOUTPUT_IRC);
    85         } else {
    86                 log_link(LOGLVL_ERROR, LOGOUTPUT_CONSOLE);
    87                 log_link(LOGLVL_WARNING, LOGOUTPUT_CONSOLE);
    88         }
    89 
    9082        b_main_init();
    9183
     
    112104        }
    113105
    114         global.auth = auth_init(global.conf->auth_backend);
    115         if (global.conf->auth_backend && global.auth == NULL) {
    116                 log_message(LOGLVL_ERROR, "Unable to load authentication backend '%s'", global.conf->auth_backend);
    117                 return(1);
    118         }
    119 
    120106        if (global.conf->runmode == RUNMODE_INETD) {
     107                log_link(LOGLVL_ERROR, LOGOUTPUT_IRC);
     108                log_link(LOGLVL_WARNING, LOGOUTPUT_IRC);
     109
    121110                i = bitlbee_inetd_init();
    122111                log_message(LOGLVL_INFO, "%s %s starting in inetd mode.", PACKAGE, BITLBEE_VERSION);
    123112
    124113        } else if (global.conf->runmode == RUNMODE_DAEMON) {
     114                log_link(LOGLVL_ERROR, LOGOUTPUT_CONSOLE);
     115                log_link(LOGLVL_WARNING, LOGOUTPUT_CONSOLE);
     116
    125117                i = bitlbee_daemon_init();
    126118                log_message(LOGLVL_INFO, "%s %s starting in daemon mode.", PACKAGE, BITLBEE_VERSION);
    127119        } else if (global.conf->runmode == RUNMODE_FORKDAEMON) {
     120                log_link(LOGLVL_ERROR, LOGOUTPUT_CONSOLE);
     121                log_link(LOGLVL_WARNING, LOGOUTPUT_CONSOLE);
     122
    128123                /* In case the operator requests a restart, we need this. */
    129124                old_cwd = g_malloc(256);
Note: See TracChangeset for help on using the changeset viewer.