Changes in / [36cf9fd:2288705]


Ignore:
Files:
9 added
18 edited

Legend:

Unmodified
Added
Removed
  • Makefile

    r36cf9fd r2288705  
    1010
    1111# Program variables
    12 objects = account.o bitlbee.o chat.o crypting.o help.o ipc.o irc.o irc_commands.o nick.o query.o root_commands.o set.o storage.o $(STORAGE_OBJS) user.o
    13 headers = account.h bitlbee.h commands.h conf.h config.h crypting.h help.h ipc.h irc.h log.h nick.h query.h set.h sock.h storage.h user.h lib/events.h lib/http_client.h lib/ini.h lib/md5.h lib/misc.h lib/proxy.h lib/sha1.h lib/ssl_client.h lib/url.h protocols/nogaim.h
     12objects = account.o bitlbee.o chat.o crypting.o dcc.o help.o ipc.o irc.o irc_commands.o nick.o query.o root_commands.o set.o storage.o $(STORAGE_OBJS) user.o
     13headers = account.h bitlbee.h commands.h conf.h config.h crypting.h help.h ipc.h irc.h log.h nick.h query.h set.h sock.h storage.h user.h lib/events.h lib/ftutil.h lib/http_client.h lib/ini.h lib/md5.h lib/misc.h lib/proxy.h lib/sha1.h lib/ssl_client.h lib/url.h protocols/ft.h protocols/nogaim.h
    1414subdirs = lib protocols
    1515
  • conf.c

    r36cf9fd r2288705  
    6363        conf->ping_timeout = 300;
    6464        conf->user = NULL;
     65        conf->ft_max_size = SIZE_MAX;
     66        conf->ft_max_kbps = G_MAXUINT;
     67        conf->ft_listen = NULL;
    6568        proxytype = 0;
    6669       
     
    306309                                conf->user = g_strdup( ini->value );
    307310                        }
     311                        else if( g_strcasecmp( ini->key, "ft_max_size" ) == 0 )
     312                        {
     313                                size_t ft_max_size;
     314                                if( sscanf( ini->value, "%zu", &ft_max_size ) != 1 )
     315                                {
     316                                        fprintf( stderr, "Invalid %s value: %s\n", ini->key, ini->value );
     317                                        return 0;
     318                                }
     319                                conf->ft_max_size = ft_max_size;
     320                        }
     321                        else if( g_strcasecmp( ini->key, "ft_max_kbps" ) == 0 )
     322                        {
     323                                if( sscanf( ini->value, "%d", &i ) != 1 )
     324                                {
     325                                        fprintf( stderr, "Invalid %s value: %s\n", ini->key, ini->value );
     326                                        return 0;
     327                                }
     328                                conf->ft_max_kbps = i;
     329                        }
     330                        else if( g_strcasecmp( ini->key, "ft_listen" ) == 0 )
     331                        {
     332                                g_free( conf->ft_listen );
     333                                conf->ft_listen = g_strdup( ini->value );
     334                        }
    308335                        else
    309336                        {
  • conf.h

    r36cf9fd r2288705  
    5050        int ping_timeout;
    5151        char *user;
     52        size_t ft_max_size;
     53        int ft_max_kbps;
     54        char *ft_listen;
    5255} conf_t;
    5356
  • doc/user-guide/commands.xml

    r36cf9fd r2288705  
    960960
    961961        </bitlbee-command>
     962       
     963        <bitlbee-command name="transfers">
     964                <short-description>Monitor, cancel, or reject file transfers</short-description>
     965                <syntax>transfers [&lt;cancel&gt; id | &lt;reject&gt;]</syntax>
     966               
     967                <description>
     968                        <para>
     969                                Without parameters the currently pending file transfers and their status will be listed. Available actions are <emphasis>cancel</emphasis> and <emphasis>reject</emphasis>. See <emphasis>help transfers &lt;action&gt;</emphasis> for more information.
     970                        </para>
     971
     972                        <ircexample>
     973                                <ircline nick="ulim">transfers</ircline>
     974                        </ircexample>
     975                </description>
     976               
     977                <bitlbee-command name="cancel">
     978                        <short-description>Cancels the file transfer with the given id</short-description>
     979                        <syntax>transfers &lt;cancel&gt; id</syntax>
     980
     981                        <description>
     982                                <para>Cancels the file transfer with the given id</para>
     983                        </description>
     984
     985                        <ircexample>
     986                                <ircline nick="ulim">transfers cancel 1</ircline>
     987                                <ircline nick="root">Canceling file transfer for test</ircline>
     988                        </ircexample>
     989                </bitlbee-command>
     990
     991                <bitlbee-command name="reject">
     992                        <short-description>Rejects all incoming transfers</short-description>
     993                        <syntax>transfers &lt;reject&gt;</syntax>
     994
     995                        <description>
     996                                <para>Rejects all incoming (not already transferring) file transfers. Since you probably have only one incoming transfer at a time, no id is neccessary. Or is it?</para>
     997                        </description>
     998
     999                        <ircexample>
     1000                                <ircline nick="ulim">transfers reject</ircline>
     1001                        </ircexample>
     1002                </bitlbee-command>
     1003        </bitlbee-command>
     1004       
    9621005</chapter>
  • irc.c

    r36cf9fd r2288705  
    2929#include "crypting.h"
    3030#include "ipc.h"
     31#include "dcc.h"
    3132
    3233static gboolean irc_userping( gpointer _irc, int fd, b_input_condition cond );
     
    10831084                        return( 1 );
    10841085                }
     1086                else if( g_strncasecmp( s + 1, "DCC", 3 ) == 0 )
     1087                {
     1088                        if( u && u->ic && u->ic->acc->prpl->transfer_request )
     1089                        {
     1090                                file_transfer_t *ft = dcc_request( u->ic, s + 5 );
     1091                                if ( ft )
     1092                                        u->ic->acc->prpl->transfer_request( u->ic, ft, u->handle );
     1093                        }
     1094                        return( 1 );
     1095                }               
    10851096                else
    10861097                {
    1087                         irc_usermsg( irc, "Non-ACTION CTCP's aren't supported" );
     1098                        irc_usermsg( irc, "Supported CTCPs are ACTION, VERSION, PING, TYPING, DCC" );
    10881099                        return( 0 );
    10891100                }
  • irc.h

    r36cf9fd r2288705  
    8383        struct query *queries;
    8484        struct account *accounts;
     85        GSList *file_transfers;
    8586        struct chat *chatrooms;
    8687       
  • lib/Makefile

    r36cf9fd r2288705  
    1010
    1111# [SH] Program variables
    12 objects = arc.o base64.o $(EVENT_HANDLER) http_client.o ini.o md5.o misc.o proxy.o sha1.o $(SSL_CLIENT) url.o xmltree.o
     12objects = arc.o base64.o $(EVENT_HANDLER) http_client.o ini.o md5.o misc.o proxy.o sha1.o $(SSL_CLIENT) url.o xmltree.o ftutil.o
    1313
    1414CFLAGS += -Wall
  • protocols/jabber/Makefile

    r36cf9fd r2288705  
    1010
    1111# [SH] Program variables
    12 objects = conference.o io.o iq.o jabber.o jabber_util.o message.o presence.o sasl.o
     12objects = conference.o io.o iq.o jabber.o jabber_util.o message.o presence.o sasl.o si.o s5bytestream.o
    1313
    1414CFLAGS += -Wall
  • protocols/jabber/iq.c

    r36cf9fd r2288705  
    9191                        pack = 0;
    9292                }
    93                 else if( strcmp( s, XMLNS_DISCOVER ) == 0 )
    94                 {
    95                         const char *features[] = { XMLNS_DISCOVER,
     93                else if( strcmp( s, XMLNS_DISCO_INFO ) == 0 )
     94                {
     95                        const char *features[] = { XMLNS_DISCO_INFO,
    9696                                                   XMLNS_VERSION,
    9797                                                   XMLNS_TIME,
     
    9999                                                   XMLNS_MUC,
    100100                                                   XMLNS_PING,
     101                                                   XMLNS_SI,
     102                                                   XMLNS_BYTESTREAMS,
     103                                                   XMLNS_FILETRANSFER,
    101104                                                   NULL };
    102105                        const char **f;
     
    118121                {
    119122                        xt_free_node( reply );
    120                         reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel" );
     123                        reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel", NULL );
    121124                        pack = 0;
    122125                }
     
    124127        else if( strcmp( type, "set" ) == 0 )
    125128        {
    126                 if( !( c = xt_find_node( node->children, "query" ) ) ||
     129                if(  ( c = xt_find_node( node->children, "si" ) ) &&
     130                     ( strcmp( xt_find_attr( c, "xmlns" ), XMLNS_SI ) == 0 ) )
     131                {
     132                        return jabber_si_handle_request( ic, node, c );
     133                } else if( !( c = xt_find_node( node->children, "query" ) ) ||
    127134                    !( s = xt_find_attr( c, "xmlns" ) ) )
    128135                {
    129136                        imcb_log( ic, "Warning: Received incomplete IQ-%s packet", type );
    130137                        return XT_HANDLED;
    131                 }
    132                
     138                } else if( strcmp( s, XMLNS_ROSTER ) == 0 )
     139                {
    133140                /* This is a roster push. XMPP servers send this when someone
    134141                   was added to (or removed from) the buddy list. AFAIK they're
    135142                   sent even if we added this buddy in our own session. */
    136                 if( strcmp( s, XMLNS_ROSTER ) == 0 )
    137                 {
    138143                        int bare_len = strlen( ic->acc->user );
    139144                       
     
    152157                               
    153158                                xt_free_node( reply );
    154                                 reply = jabber_make_error_packet( node, "not-allowed", "cancel" );
     159                                reply = jabber_make_error_packet( node, "not-allowed", "cancel", NULL );
    155160                                pack = 0;
    156161                        }
    157                 }
    158                 else
     162                } else if( strcmp( s, XMLNS_BYTESTREAMS ) == 0 )
     163                {
     164                        /* Bytestream Request (stage 2 of file transfer) */
     165                        return jabber_bs_recv_request( ic, node, c );
     166                } else
    159167                {
    160168                        xt_free_node( reply );
    161                         reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel" );
     169                        reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel", NULL );
    162170                        pack = 0;
    163171                }
     
    594602        return st;
    595603}
     604
     605xt_status jabber_iq_parse_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig );
     606
     607xt_status jabber_iq_query_features( struct im_connection *ic, char *bare_jid )
     608{
     609        struct xt_node *node, *query;
     610        struct jabber_buddy *bud;
     611       
     612        if( ( bud = jabber_buddy_by_jid( ic, bare_jid , 0 ) ) == NULL )
     613        {
     614                /* Who cares about the unknown... */
     615                imcb_log( ic, "Couldn't find buddy: %s", bare_jid);
     616                return 0;
     617        }
     618       
     619        if( bud->features ) /* been here already */
     620                return XT_HANDLED;
     621       
     622        node = xt_new_node( "query", NULL, NULL );
     623        xt_add_attr( node, "xmlns", XMLNS_DISCO_INFO );
     624       
     625        if( !( query = jabber_make_packet( "iq", "get", bare_jid, node ) ) )
     626        {
     627                imcb_log( ic, "WARNING: Couldn't generate feature query" );
     628                xt_free_node( node );
     629                return 0;
     630        }
     631
     632        jabber_cache_add( ic, query, jabber_iq_parse_features );
     633
     634        return jabber_write_packet( ic, query );
     635}
     636
     637xt_status jabber_iq_parse_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig )
     638{
     639        struct xt_node *c;
     640        struct jabber_buddy *bud;
     641        char *feature;
     642
     643        if( !( c = xt_find_node( node->children, "query" ) ) ||
     644            !( strcmp( xt_find_attr( c, "xmlns" ), XMLNS_DISCO_INFO ) == 0 ) )
     645        {
     646                imcb_log( ic, "WARNING: Received incomplete IQ-result packet for discover" );
     647                return XT_HANDLED;
     648        }
     649        if( ( bud = jabber_buddy_by_jid( ic, xt_find_attr( node, "from") , 0 ) ) == NULL )
     650        {
     651                /* Who cares about the unknown... */
     652                imcb_log( ic, "Couldn't find buddy: %s", xt_find_attr( node, "from"));
     653                return 0;
     654        }
     655       
     656        c = c->children;
     657        while( ( c = xt_find_node( c, "feature" ) ) ) {
     658                feature = xt_find_attr( c, "var" );
     659                bud->features = g_slist_append(bud->features, g_strdup(feature) );
     660                c = c->next;
     661        }
     662
     663        return XT_HANDLED;
     664}
     665
     666xt_status jabber_iq_parse_server_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig );
     667
     668xt_status jabber_iq_query_server( struct im_connection *ic, char *jid, char *xmlns )
     669{
     670        struct xt_node *node, *query;
     671        struct jabber_data *jd = ic->proto_data;
     672       
     673        node = xt_new_node( "query", NULL, NULL );
     674        xt_add_attr( node, "xmlns", xmlns );
     675       
     676        if( !( query = jabber_make_packet( "iq", "get", jid, node ) ) )
     677        {
     678                imcb_log( ic, "WARNING: Couldn't generate server query" );
     679                xt_free_node( node );
     680        }
     681
     682        jd->have_streamhosts--;
     683        jabber_cache_add( ic, query, jabber_iq_parse_server_features );
     684
     685        return jabber_write_packet( ic, query );
     686}
     687
     688/*
     689 * Query the server for "items", query each "item" for identities, query each "item" that's a proxy for it's bytestream info
     690 */
     691xt_status jabber_iq_parse_server_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig )
     692{
     693        struct xt_node *c;
     694        struct jabber_data *jd = ic->proto_data;
     695
     696        if( !( c = xt_find_node( node->children, "query" ) ) ||
     697            !xt_find_attr( node, "from" ) )
     698        {
     699                imcb_log( ic, "WARNING: Received incomplete IQ-result packet for discover" );
     700                return XT_HANDLED;
     701        }
     702
     703        jd->have_streamhosts++;
     704
     705        if( strcmp( xt_find_attr( c, "xmlns" ), XMLNS_DISCO_ITEMS ) == 0 )
     706        {
     707                char *item, *itemjid;
     708
     709                /* answer from server */
     710       
     711                c = c->children;
     712                while( ( c = xt_find_node( c, "item" ) ) )
     713                {
     714                        item = xt_find_attr( c, "name" );
     715                        itemjid = xt_find_attr( c, "jid" );
     716
     717                        jabber_iq_query_server( ic, itemjid, XMLNS_DISCO_INFO );
     718
     719                        c = c->next;
     720                }
     721        } else if( strcmp( xt_find_attr( c, "xmlns" ), XMLNS_DISCO_INFO ) == 0 )
     722        {
     723                char *category, *type;
     724
     725                /* answer from potential proxy */
     726
     727                c = c->children;
     728                while( ( c = xt_find_node( c, "identity" ) ) )
     729                {
     730                        category = xt_find_attr( c, "category" );
     731                        type = xt_find_attr( c, "type" );
     732
     733                        if( type && ( strcmp( type, "bytestreams" ) == 0 ) &&
     734                            category && ( strcmp( category, "proxy" ) == 0 ) )
     735                                jabber_iq_query_server( ic, xt_find_attr( node, "from" ), XMLNS_BYTESTREAMS );
     736
     737                        c = c->next;
     738                }
     739        } else if( strcmp( xt_find_attr( c, "xmlns" ), XMLNS_BYTESTREAMS ) == 0 )
     740        {
     741                char *host, *jid;
     742                int port;
     743
     744                /* answer from proxy */
     745
     746                if( ( c = xt_find_node( c->children, "streamhost" ) ) &&
     747                    ( host = xt_find_attr( c, "host" ) ) &&
     748                    ( port = atoi( xt_find_attr( c, "port" ) ) ) &&
     749                    ( jid = xt_find_attr( c, "jid" ) ) )
     750                {
     751                        jabber_streamhost_t *sh = g_new0( jabber_streamhost_t, 1 );
     752                        sh->jid = g_strdup( jid );
     753                        sh->host = g_strdup( host );
     754                        sprintf( sh->port, "%u", port );
     755
     756                        imcb_log( ic, "Proxy found: jid %s host %s port %u", jid, host, port );
     757                        jd->streamhosts = g_slist_append( jd->streamhosts, sh );
     758                }
     759        }
     760
     761        if( jd->have_streamhosts == 0 )
     762                jd->have_streamhosts++;
     763        return XT_HANDLED;
     764}
  • protocols/jabber/jabber.c

    r36cf9fd r2288705  
    8080        s = set_add( &acc->set, "xmlconsole", "false", set_eval_bool, acc );
    8181        s->flags |= ACC_SET_OFFLINE_ONLY;
     82
     83        s = set_add( &acc->set, "proxy", "<local>;<auto>", NULL, acc );
    8284}
    8385
     
    260262        struct jabber_data *jd = ic->proto_data;
    261263       
     264        while( jd->filetransfers )
     265                imcb_file_canceled( ( ( struct jabber_transfer *) jd->filetransfers->data )->ft, "Logging out" );
     266
     267        while( jd->streamhosts )
     268        {
     269                jabber_streamhost_t *sh = jd->streamhosts->data;
     270                jd->streamhosts = g_slist_remove( jd->streamhosts, sh );
     271                g_free( sh->jid );
     272                g_free( sh->host );
     273                g_free( sh );
     274        }
     275
    262276        if( jd->fd >= 0 )
    263277                jabber_end_stream( ic );
     
    546560        ret->send_typing = jabber_send_typing;
    547561        ret->handle_cmp = g_strcasecmp;
     562        ret->transfer_request = jabber_si_transfer_request;
    548563
    549564        register_protocol( ret );
  • protocols/jabber/jabber.h

    r36cf9fd r2288705  
    6060} jabber_buddy_flags_t;
    6161
     62/* Stores a streamhost's(a.k.a. proxy) data */
     63typedef struct
     64{
     65        char *jid;
     66        char *host;
     67        char port[6];
     68} jabber_streamhost_t;
     69
    6270typedef enum
    6371{
     
    9098        GHashTable *node_cache;
    9199        GHashTable *buddies;
     100
     101        GSList *filetransfers;
     102        GSList *streamhosts;
     103        int have_streamhosts;
    92104};
    93105
     
    119131        struct jabber_away_state *away_state;
    120132        char *away_message;
     133        GSList *features;
    121134       
    122135        time_t last_act;
     
    132145        char *my_full_jid; /* Separate copy because of case sensitivity. */
    133146        struct jabber_buddy *me;
     147};
     148
     149struct jabber_transfer
     150{
     151        /* bitlbee's handle for this transfer */
     152        file_transfer_t *ft;
     153
     154        /* the stream's private handle */
     155        gpointer streamhandle;
     156
     157        /* timeout for discover queries */
     158        gint disco_timeout;
     159        gint disco_timeout_fired;
     160
     161        struct im_connection *ic;
     162
     163        struct jabber_buddy *bud;
     164
     165        int watch_in;
     166        int watch_out;
     167
     168        char *ini_jid;
     169        char *tgt_jid;
     170        char *iq_id;
     171        char *sid;
     172        int accepted;
     173
     174        size_t bytesread, byteswritten;
     175        int fd;
     176        struct sockaddr_storage saddr;
    134177};
    135178
     
    159202
    160203/* Some supported extensions/legacy stuff */
    161 #define XMLNS_AUTH         "jabber:iq:auth"                     /* XEP-0078 */
    162 #define XMLNS_VERSION      "jabber:iq:version"                  /* XEP-0092 */
    163 #define XMLNS_TIME         "jabber:iq:time"                     /* XEP-0090 */
    164 #define XMLNS_PING         "urn:xmpp:ping"                      /* XEP-0199 */
    165 #define XMLNS_VCARD        "vcard-temp"                         /* XEP-0054 */
    166 #define XMLNS_DELAY        "jabber:x:delay"                     /* XEP-0091 */
    167 #define XMLNS_CHATSTATES   "http://jabber.org/protocol/chatstates"  /* 0085 */
    168 #define XMLNS_DISCOVER     "http://jabber.org/protocol/disco#info"  /* 0030 */
    169 #define XMLNS_MUC          "http://jabber.org/protocol/muc"     /* XEP-0045 */
    170 #define XMLNS_MUC_USER     "http://jabber.org/protocol/muc#user"/* XEP-0045 */
    171 #define XMLNS_CAPS         "http://jabber.org/protocol/caps"    /* XEP-0115 */
     204#define XMLNS_AUTH         "jabber:iq:auth"                                      /* XEP-0078 */
     205#define XMLNS_VERSION      "jabber:iq:version"                                   /* XEP-0092 */
     206#define XMLNS_TIME         "jabber:iq:time"                                      /* XEP-0090 */
     207#define XMLNS_PING         "urn:xmpp:ping"                                       /* XEP-0199 */
     208#define XMLNS_VCARD        "vcard-temp"                                          /* XEP-0054 */
     209#define XMLNS_DELAY        "jabber:x:delay"                                      /* XEP-0091 */
     210#define XMLNS_XDATA        "jabber:x:data"                                       /* XEP-0004 */
     211#define XMLNS_CHATSTATES   "http://jabber.org/protocol/chatstates"               /* XEP-0085 */
     212#define XMLNS_DISCO_INFO   "http://jabber.org/protocol/disco#info"               /* XEP-0030 */
     213#define XMLNS_DISCO_ITEMS  "http://jabber.org/protocol/disco#items"              /* XEP-0030 */
     214#define XMLNS_MUC          "http://jabber.org/protocol/muc"                      /* XEP-0045 */
     215#define XMLNS_MUC_USER     "http://jabber.org/protocol/muc#user"                 /* XEP-0045 */
     216#define XMLNS_CAPS         "http://jabber.org/protocol/caps"                     /* XEP-0115 */
     217#define XMLNS_FEATURE      "http://jabber.org/protocol/feature-neg"              /* XEP-0020 */
     218#define XMLNS_SI           "http://jabber.org/protocol/si"                       /* XEP-0095 */
     219#define XMLNS_FILETRANSFER "http://jabber.org/protocol/si/profile/file-transfer" /* XEP-0096 */
     220#define XMLNS_BYTESTREAMS  "http://jabber.org/protocol/bytestreams"              /* XEP-0065 */
     221#define XMLNS_IBB          "http://jabber.org/protocol/ibb"                      /* XEP-0047 */
    172222
    173223/* iq.c */
     
    179229int jabber_add_to_roster( struct im_connection *ic, char *handle, char *name );
    180230int jabber_remove_from_roster( struct im_connection *ic, char *handle );
     231xt_status jabber_iq_query_features( struct im_connection *ic, char *bare_jid );
     232xt_status jabber_iq_query_server( struct im_connection *ic, char *jid, char *xmlns );
     233
     234/* si.c */
     235int jabber_si_handle_request( struct im_connection *ic, struct xt_node *node, struct xt_node *sinode );
     236void jabber_si_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *who );
     237void jabber_si_free_transfer( file_transfer_t *ft);
     238
     239/* s5bytestream.c */
     240int jabber_bs_recv_request( struct im_connection *ic, struct xt_node *node, struct xt_node *qnode);
     241gboolean jabber_bs_send_start( struct jabber_transfer *tf );
     242gboolean jabber_bs_send_write( file_transfer_t *ft, char *buffer, unsigned int len );
    181243
    182244/* message.c */
     
    192254char *set_eval_tls( set_t *set, char *value );
    193255struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_node *children );
    194 struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type );
     256struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type, char *err_code );
    195257void jabber_cache_add( struct im_connection *ic, struct xt_node *node, jabber_cache_event func );
    196258struct xt_node *jabber_cache_get( struct im_connection *ic, char *id );
  • protocols/jabber/jabber_util.c

    r36cf9fd r2288705  
    9999}
    100100
    101 struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type )
     101struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type, char *err_code )
    102102{
    103103        struct xt_node *node, *c;
     
    111111        c = xt_new_node( "error", NULL, c );
    112112        xt_add_attr( c, "type", err_type );
     113       
     114        /* Add the error code, if present */
     115        if (err_code)
     116                xt_add_attr( c, "code", err_code );
    113117       
    114118        /* To make the actual error packet, we copy the original packet and
  • protocols/msn/Makefile

    r36cf9fd r2288705  
    1010
    1111# [SH] Program variables
    12 objects = msn.o msn_util.o ns.o passport.o sb.o tables.o
     12objects = msn.o msn_util.o ns.o passport.o sb.o tables.o invitation.o
    1313
    1414CFLAGS += -Wall
  • protocols/msn/msn.c

    r36cf9fd r2288705  
    7777        if( md )
    7878        {
     79                while( md->filetransfers ) {
     80                        imcb_file_canceled( md->filetransfers->data, "Closing msn connection" );
     81                }
     82               
    7983                if( md->fd >= 0 )
    8084                        closesocket( md->fd );
     
    338342        ret->send_typing = msn_send_typing;
    339343        ret->handle_cmp = g_strcasecmp;
     344        ret->transfer_request = msn_ftp_transfer_request;
    340345
    341346        register_protocol(ret);
  • protocols/msn/msn.h

    r36cf9fd r2288705  
    6969        int sb_failures;
    7070        time_t first_sb_failure;
     71        GSList *filetransfers;
    7172       
    7273        const struct msn_away_state *away_state;
     
    181182int msn_sb_write_msg( struct im_connection *ic, struct msn_message *m );
    182183
     184/* invitation.c */
     185void msn_ftp_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *who );
     186
    183187#endif //_MSN_H
  • protocols/msn/sb.c

    r36cf9fd r2288705  
    2929#include "passport.h"
    3030#include "md5.h"
     31#include "invitation.h"
    3132
    3233static gboolean msn_sb_callback( gpointer data, gint source, b_input_condition cond );
     
    168169               
    169170                /* Build the message. Convert LF to CR-LF for normal messages. */
    170                 if( strcmp( text, TYPING_NOTIFICATION_MESSAGE ) != 0 )
     171                if( strcmp( text, TYPING_NOTIFICATION_MESSAGE ) == 0 )
     172                {
     173                        i = strlen( MSN_TYPING_HEADERS ) + strlen( sb->ic->acc->user );
     174                        buf = g_new0( char, i );
     175                        i = g_snprintf( buf, i, MSN_TYPING_HEADERS, sb->ic->acc->user );
     176                } else if( strncmp( text, MSN_INVITE_HEADERS, sizeof( MSN_INVITE_HEADERS ) - 1 ) == 0 )
     177                {
     178                        buf = g_strdup( text );
     179                        i = strlen( buf );
     180                } else
    171181                {
    172182                        buf = g_new0( char, sizeof( MSN_MESSAGE_HEADERS ) + strlen( text ) * 2 + 1 );
     
    181191                                buf[i++] = text[j];
    182192                        }
    183                 }
    184                 else
    185                 {
    186                         i = strlen( MSN_TYPING_HEADERS ) + strlen( sb->ic->acc->user );
    187                         buf = g_new0( char, i );
    188                         i = g_snprintf( buf, i, MSN_TYPING_HEADERS, sb->ic->acc->user );
    189193                }
    190194               
     
    687691                else if( g_strncasecmp( ct, "text/x-msmsgsinvite", 19 ) == 0 )
    688692                {
    689                         char *itype = msn_findheader( body, "Application-GUID:", blen );
    690                         char buf[1024];
     693                        char *command = msn_findheader( body, "Invitation-Command:", blen );
     694                        char *cookie = msn_findheader( body, "Invitation-Cookie:", blen );
     695                        unsigned int icookie;
    691696                       
    692697                        g_free( ct );
    693698                       
    694                         *buf = 0;
    695                        
    696                         if( !itype )
    697                                 return( 1 );
    698                        
    699                         /* File transfer. */
    700                         if( strcmp( itype, "{5D3E02AB-6190-11d3-BBBB-00C04F795683}" ) == 0 )
    701                         {
    702                                 char *name = msn_findheader( body, "Application-File:", blen );
    703                                 char *size = msn_findheader( body, "Application-FileSize:", blen );
    704                                
    705                                 if( name && size )
    706                                 {
    707                                         g_snprintf( buf, sizeof( buf ), "<< \x02""BitlBee\x02"" - Filetransfer: `%s', %s bytes >>\n"
    708                                                     "Filetransfers are not supported by BitlBee for now...", name, size );
    709                                 }
    710                                 else
    711                                 {
    712                                         strcpy( buf, "<< \x02""BitlBee\x02"" - Corrupted MSN filetransfer invitation message >>" );
    713                                 }
    714                                
    715                                 if( name ) g_free( name );
    716                                 if( size ) g_free( size );
    717                         }
    718                         else
    719                         {
    720                                 char *iname = msn_findheader( body, "Application-Name:", blen );
    721                                
    722                                 g_snprintf( buf, sizeof( buf ), "<< \x02""BitlBee\x02"" - Unknown MSN invitation - %s (%s) >>",
    723                                                                 itype, iname ? iname : "no name" );
    724                                
    725                                 if( iname ) g_free( iname );
    726                         }
    727                        
    728                         g_free( itype );
    729                        
    730                         if( !*buf )
    731                                 return( 1 );
    732                        
    733                         if( sb->who )
    734                         {
    735                                 imcb_buddy_msg( ic, cmd[1], buf, 0, 0 );
    736                         }
    737                         else if( sb->chat )
    738                         {
    739                                 imcb_chat_msg( sb->chat, cmd[1], buf, 0, 0 );
    740                         }
    741                         else
    742                         {
    743                                 /* PANIC! */
    744                         }
     699                        /* Every invite should have both a Command and Cookie header */
     700                        if( !command || !cookie ) {
     701                                g_free( command );
     702                                g_free( cookie );
     703                                imcb_log( ic, "Warning: No command or cookie from %s", sb->who );
     704                                return 1;
     705                        }
     706                       
     707                        icookie = strtoul( cookie, NULL, 10 );
     708                        g_free( cookie );
     709                       
     710                        if( g_strncasecmp( command, "INVITE", 6 ) == 0 ) {
     711                                msn_invitation_invite( sb, cmd[1], icookie, body, blen );
     712                        } else if( g_strncasecmp( command, "ACCEPT", 6 ) == 0 ) {
     713                                msn_invitation_accept( sb, cmd[1], icookie, body, blen );
     714                        } else if( g_strncasecmp( command, "CANCEL", 6 ) == 0 ) {
     715                                msn_invitation_cancel( sb, cmd[1], icookie, body, blen );
     716                        } else {
     717                                imcb_log( ic, "Warning: Received invalid invitation with "
     718                                                "command %s from %s", command, sb->who );
     719                        }
     720                       
     721                        g_free( command );
     722                }
     723                else if( g_strncasecmp( ct, "application/x-msnmsgrp2p", 24 ) == 0 )
     724                {
     725                        imcb_error( sb->ic, "Cannot receive file from %s: BitlBee does not "
     726                                        "support msnmsgrp2p yet.", sb->who );
     727                        g_free( ct );
    745728                }
    746729                else if( g_strncasecmp( ct, "text/x-msmsgscontrol", 20 ) == 0 )
  • protocols/nogaim.h

    r36cf9fd r2288705  
    4545#include "proxy.h"
    4646#include "query.h"
     47#include "md5.h"
     48#include "ft.h"
    4749
    4850#define BUDDY_ALIAS_MAXLEN 388   /* because MSN names can be 387 characters */
     
    229231        void (* auth_allow)     (struct im_connection *, const char *who);
    230232        void (* auth_deny)      (struct im_connection *, const char *who);
     233
     234        /* Incoming transfer request */
     235        void (* transfer_request) (struct im_connection *, file_transfer_t *ft, char *handle );
    231236};
    232237
  • root_commands.c

    r36cf9fd r2288705  
    11881188        }
    11891189#endif
     1190}
     1191
     1192static void cmd_transfers( irc_t *irc, char **cmd )
     1193{
     1194        GSList *files = irc->file_transfers;
     1195        enum { LIST, REJECT, CANCEL };
     1196        int subcmd = LIST;
     1197        int fid;
     1198
     1199        if( !files )
     1200        {
     1201                irc_usermsg( irc, "No pending transfers" );
     1202                return;
     1203        }
     1204
     1205        if( cmd[1] &&
     1206            ( strcmp( cmd[1], "reject" ) == 0 ) )
     1207        {
     1208                subcmd = REJECT;
     1209        }
     1210        else if( cmd[1] &&
     1211                 ( strcmp( cmd[1], "cancel" ) == 0 ) &&
     1212                 cmd[2] &&
     1213                 ( fid = atoi( cmd[2] ) ) )
     1214        {
     1215                subcmd = CANCEL;
     1216        }
     1217
     1218        for( ; files; files = g_slist_next( files ) )
     1219        {
     1220                file_transfer_t *file = files->data;
     1221               
     1222                switch( subcmd ) {
     1223                case LIST:
     1224                        if ( file->status == FT_STATUS_LISTENING )
     1225                                irc_usermsg( irc,
     1226                                        "Pending file(id %d): %s (Listening...)", file->local_id, file->file_name);
     1227                        else
     1228                        {
     1229                                int kb_per_s = 0;
     1230                                time_t diff = time( NULL ) - file->started ? : 1;
     1231                                if ( ( file->started > 0 ) && ( file->bytes_transferred > 0 ) )
     1232                                        kb_per_s = file->bytes_transferred / 1024 / diff;
     1233                                       
     1234                                irc_usermsg( irc,
     1235                                        "Pending file(id %d): %s (%10zd/%zd kb, %d kb/s)", file->local_id, file->file_name,
     1236                                        file->bytes_transferred/1024, file->file_size/1024, kb_per_s);
     1237                        }
     1238                        break;
     1239                case REJECT:
     1240                        if( file->status == FT_STATUS_LISTENING )
     1241                        {
     1242                                irc_usermsg( irc, "Rejecting file transfer for %s", file->file_name );
     1243                                imcb_file_canceled( file, "Denied by user" );
     1244                        }
     1245                        break;
     1246                case CANCEL:
     1247                        if( file->local_id == fid )
     1248                        {
     1249                                irc_usermsg( irc, "Canceling file transfer for %s", file->file_name );
     1250                                imcb_file_canceled( file, "Canceled by user" );
     1251                        }
     1252                        break;
     1253                }
     1254        }
    11901255}
    11911256
     
    12111276        { "join_chat",      2, cmd_join_chat,      0 },
    12121277        { "chat",           1, cmd_chat,           0 },
     1278        { "transfers",      0, cmd_transfers,      0 },
    12131279        { NULL }
    12141280};
Note: See TracChangeset for help on using the changeset viewer.