Changes in / [aa31117:b79308b]


Ignore:
Files:
5 added
13 edited

Legend:

Unmodified
Added
Removed
  • Makefile

    raa31117 rb79308b  
    1010
    1111# Program variables
    12 objects = account.o bitlbee.o conf.o crypting.o help.o ipc.o irc.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o $(STORAGE_OBJS) unix.o 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 conf.o crypting.o help.o ipc.o irc.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o $(STORAGE_OBJS) unix.o user.o dcc.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 dcc.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 protocols/ft.h
    1414subdirs = lib protocols
    1515
  • conf.c

    raa31117 rb79308b  
    6262        conf->ping_timeout = 300;
    6363        conf->user = NULL;
     64        conf->max_filetransfer_size = G_MAXUINT;
    6465        proxytype = 0;
    6566       
  • conf.h

    raa31117 rb79308b  
    5050        int ping_timeout;
    5151        char *user;
     52        size_t max_filetransfer_size;
    5253} conf_t;
    5354
  • doc/user-guide/commands.xml

    raa31117 rb79308b  
    874874
    875875        </bitlbee-command>
     876       
     877        <bitlbee-command name="transfers">
     878                <short-description>Monitor, cancel, or reject file transfers</short-description>
     879                <syntax>transfers [&lt;cancel&gt; id | &lt;reject&gt;]</syntax>
     880               
     881                <description>
     882                        <para>
     883                                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.
     884                        </para>
     885
     886                        <ircexample>
     887                                <ircline nick="ulim">transfers</ircline>
     888                        </ircexample>
     889                </description>
     890               
     891                <bitlbee-command name="cancel">
     892                        <short-description>Cancels the file transfer with the given id</short-description>
     893                        <syntax>transfers &lt;cancel&gt; id</syntax>
     894
     895                        <description>
     896                                <para>Cancels the file transfer with the given id</para>
     897                        </description>
     898
     899                        <ircexample>
     900                                <ircline nick="ulim">transfers cancel 1</ircline>
     901                                <ircline nick="root">Canceling file transfer for test</ircline>
     902                        </ircexample>
     903                </bitlbee-command>
     904
     905                <bitlbee-command name="reject">
     906                        <short-description>Rejects all incoming transfers</short-description>
     907                        <syntax>transfers &lt;reject&gt;</syntax>
     908
     909                        <description>
     910                                <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>
     911                        </description>
     912
     913                        <ircexample>
     914                                <ircline nick="ulim">transfers reject</ircline>
     915                        </ircexample>
     916                </bitlbee-command>
     917        </bitlbee-command>
     918       
    876919</chapter>
  • irc.c

    raa31117 rb79308b  
    2828#include "crypting.h"
    2929#include "ipc.h"
     30#include "dcc.h"
     31
     32#include <regex.h>
     33#include <netinet/in.h>
    3034
    3135static gboolean irc_userping( gpointer _irc, int fd, b_input_condition cond );
     
    10701074                        return( 1 );
    10711075                }
     1076                else if( g_strncasecmp( s + 1, "DCC", 3 ) == 0 )
     1077                {
     1078                        if( u && u->ic && u->ic->acc->prpl->transfer_request )
     1079                        {
     1080                                file_transfer_t *ft = dcc_request( u->ic, s + 5 );
     1081                                if ( ft )
     1082                                        u->ic->acc->prpl->transfer_request( u->ic, ft, u->handle );
     1083                        }
     1084                        return( 1 );
     1085                }               
    10721086                else
    10731087                {
    1074                         irc_usermsg( irc, "Non-ACTION CTCP's aren't supported" );
     1088                        irc_usermsg( irc, "Supported CTCPs are ACTION, VERSION, PING, TYPING, DCC" );
    10751089                        return( 0 );
    10761090                }
  • irc.h

    raa31117 rb79308b  
    8787        struct query *queries;
    8888        struct account *accounts;
     89        GSList *file_transfers;
    8990       
    9091        struct __USER *users;
  • protocols/jabber/Makefile

    raa31117 rb79308b  
    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

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

    raa31117 rb79308b  
    530530        ret->send_typing = jabber_send_typing;
    531531        ret->handle_cmp = g_strcasecmp;
     532        ret->transfer_request = jabber_si_transfer_request;
    532533
    533534        register_protocol( ret );
  • protocols/jabber/jabber.h

    raa31117 rb79308b  
    5959} jabber_buddy_flags_t;
    6060
     61/* Stores a streamhost's(a.k.a. proxy) data */
     62typedef struct
     63{
     64        char *jid;
     65        char *host;
     66        char port[6];
     67} jabber_streamhost_t;
     68
    6169typedef enum
    6270{
     
    8997        GHashTable *node_cache;
    9098        GHashTable *buddies;
     99
     100        GSList *filetransfers;
     101        GSList *streamhosts;
     102        int have_streamhosts;
    91103};
    92104
     
    118130        struct jabber_away_state *away_state;
    119131        char *away_message;
     132        GSList *features;
    120133       
    121134        time_t last_act;
     
    131144        char *my_full_jid; /* Separate copy because of case sensitivity. */
    132145        struct jabber_buddy *me;
     146};
     147
     148struct jabber_transfer
     149{
     150        /* bitlbee's handle for this transfer */
     151        file_transfer_t *ft;
     152
     153        /* the stream's private handle */
     154        gpointer streamhandle;
     155
     156        struct im_connection *ic;
     157
     158        int watch_in;
     159        int watch_out;
     160
     161        char *ini_jid;
     162        char *tgt_jid;
     163        char *iq_id;
     164        char *sid;
     165        int accepted;
     166
     167        size_t bytesread, byteswritten;
     168        int fd;
     169        struct sockaddr_storage saddr;
    133170};
    134171
     
    162199
    163200/* Some supported extensions/legacy stuff */
    164 #define XMLNS_AUTH         "jabber:iq:auth"                     /* XEP-0078 */
    165 #define XMLNS_VERSION      "jabber:iq:version"                  /* XEP-0092 */
    166 #define XMLNS_TIME         "jabber:iq:time"                     /* XEP-0090 */
    167 #define XMLNS_PING         "urn:xmpp:ping"                      /* XEP-0199 */
    168 #define XMLNS_VCARD        "vcard-temp"                         /* XEP-0054 */
    169 #define XMLNS_DELAY        "jabber:x:delay"                     /* XEP-0091 */
    170 #define XMLNS_CHATSTATES   "http://jabber.org/protocol/chatstates"  /* 0085 */
    171 #define XMLNS_DISCOVER     "http://jabber.org/protocol/disco#info"  /* 0030 */
    172 #define XMLNS_MUC          "http://jabber.org/protocol/muc"     /* XEP-0045 */
    173 #define XMLNS_MUC_USER     "http://jabber.org/protocol/muc#user"/* XEP-0045 */
    174 #define XMLNS_CAPS         "http://jabber.org/protocol/caps"    /* XEP-0115 */
     201#define XMLNS_AUTH         "jabber:iq:auth"                                      /* XEP-0078 */
     202#define XMLNS_VERSION      "jabber:iq:version"                                   /* XEP-0092 */
     203#define XMLNS_TIME         "jabber:iq:time"                                      /* XEP-0090 */
     204#define XMLNS_PING         "urn:xmpp:ping"                                       /* XEP-0199 */
     205#define XMLNS_VCARD        "vcard-temp"                                          /* XEP-0054 */
     206#define XMLNS_DELAY        "jabber:x:delay"                                      /* XEP-0091 */
     207#define XMLNS_XDATA        "jabber:x:data"                                       /* XEP-0004 */
     208#define XMLNS_CHATSTATES   "http://jabber.org/protocol/chatstates"               /* XEP-0085 */
     209#define XMLNS_DISCO_INFO   "http://jabber.org/protocol/disco#info"               /* XEP-0030 */
     210#define XMLNS_DISCO_ITEMS  "http://jabber.org/protocol/disco#items"              /* XEP-0030 */
     211#define XMLNS_MUC          "http://jabber.org/protocol/muc"                      /* XEP-0045 */
     212#define XMLNS_MUC_USER     "http://jabber.org/protocol/muc#user"                 /* XEP-0045 */
     213#define XMLNS_CAPS         "http://jabber.org/protocol/caps"                     /* XEP-0115 */
     214#define XMLNS_FEATURE      "http://jabber.org/protocol/feature-neg"              /* XEP-0020 */
     215#define XMLNS_SI           "http://jabber.org/protocol/si"                       /* XEP-0095 */
     216#define XMLNS_FILETRANSFER "http://jabber.org/protocol/si/profile/file-transfer" /* XEP-0096 */
     217#define XMLNS_BYTESTREAMS  "http://jabber.org/protocol/bytestreams"              /* XEP-0065 */
     218#define XMLNS_IBB          "http://jabber.org/protocol/ibb"                      /* XEP-0047 */
    175219
    176220/* iq.c */
     
    182226int jabber_add_to_roster( struct im_connection *ic, char *handle, char *name );
    183227int jabber_remove_from_roster( struct im_connection *ic, char *handle );
     228xt_status jabber_iq_query_features( struct im_connection *ic, char *bare_jid );
     229xt_status jabber_iq_query_server( struct im_connection *ic, char *jid, char *xmlns );
     230
     231/* si.c */
     232int jabber_si_handle_request( struct im_connection *ic, struct xt_node *node, struct xt_node *sinode );
     233void jabber_si_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *who );
     234void jabber_si_free_transfer( file_transfer_t *ft);
     235
     236/* s5bytestream.c */
     237int jabber_bs_recv_request( struct im_connection *ic, struct xt_node *node, struct xt_node *qnode);
     238gboolean jabber_bs_send_start( struct jabber_transfer *tf );
     239gboolean jabber_bs_send_write( file_transfer_t *ft, char *buffer, unsigned int len );
    184240
    185241/* message.c */
     
    195251char *set_eval_tls( set_t *set, char *value );
    196252struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_node *children );
    197 struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type );
     253struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type, char *err_code );
    198254void jabber_cache_add( struct im_connection *ic, struct xt_node *node, jabber_cache_event func );
    199255struct xt_node *jabber_cache_get( struct im_connection *ic, char *id );
  • protocols/jabber/jabber_util.c

    raa31117 rb79308b  
    9797}
    9898
    99 struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type )
     99struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type, char *err_code )
    100100{
    101101        struct xt_node *node, *c;
     
    109109        c = xt_new_node( "error", NULL, c );
    110110        xt_add_attr( c, "type", err_type );
     111       
     112        /* Add the error code, if present */
     113        if (err_code)
     114                xt_add_attr( c, "code", err_code );
    111115       
    112116        /* To make the actual error packet, we copy the original packet and
     
    291295        new = g_new( char, len + 1 );
    292296        for( i = 0; i < len; i ++ )
     297        {
     298                /* don't normalize the resource */
     299                if( orig[i] == '/' )
     300                        break;
    293301                new[i] = tolower( orig[i] );
     302        }
     303        for( ; i < len; i ++ )
     304                new[i] = orig[i];
    294305       
    295306        new[i] = 0;
  • protocols/nogaim.h

    raa31117 rb79308b  
    4444#include "query.h"
    4545#include "md5.h"
     46#include "ft.h"
    4647
    4748#define BUF_LEN MSG_LEN
     
    229230         * - Most protocols will just want to set this to g_strcasecmp().*/
    230231        int (* handle_cmp) (const char *who1, const char *who2);
     232
     233        /* Incoming transfer request */
     234        void (* transfer_request) (struct im_connection *, file_transfer_t *ft, char *handle );
    231235};
    232236
  • root_commands.c

    raa31117 rb79308b  
    10351035                irc_usermsg( irc, "Tried to join chat, not sure if this was successful" );
    10361036                g_free( channel );
     1037        }
     1038}
     1039
     1040static void cmd_transfers( irc_t *irc, char **cmd )
     1041{
     1042        GSList *files = irc->file_transfers;
     1043        enum { LIST, REJECT, CANCEL };
     1044        int subcmd = LIST;
     1045        int fid;
     1046
     1047        if( !files )
     1048        {
     1049                irc_usermsg( irc, "No pending transfers" );
     1050                return;
     1051        }
     1052
     1053        if( cmd[1] &&
     1054            ( strcmp( cmd[1], "reject" ) == 0 ) )
     1055        {
     1056                subcmd = REJECT;
     1057        }
     1058        else if( cmd[1] &&
     1059                 ( strcmp( cmd[1], "cancel" ) == 0 ) &&
     1060                 cmd[2] &&
     1061                 ( fid = atoi( cmd[2] ) ) )
     1062        {
     1063                subcmd = CANCEL;
     1064        }
     1065
     1066        for( ; files; files = g_slist_next( files ) )
     1067        {
     1068                file_transfer_t *file = files->data;
     1069               
     1070                switch( subcmd ) {
     1071                case LIST:
     1072                        if ( file->status == FT_STATUS_LISTENING )
     1073                                irc_usermsg( irc,
     1074                                        "Pending file(id %d): %s (Listening...)", file->local_id, file->file_name);
     1075                        else
     1076                        {
     1077                                int kb_per_s = 0;
     1078                                time_t diff = time( NULL ) - file->started;
     1079                                if ( ( file->started > 0 ) && ( file->bytes_transferred > 0 ) )
     1080                                        kb_per_s = file->bytes_transferred / 1024 / diff;
     1081                                       
     1082                                irc_usermsg( irc,
     1083                                        "Pending file(id %d): %s (%10zd/%zd kb, %d kb/s)", file->local_id, file->file_name,
     1084                                        file->bytes_transferred/1024, file->file_size/1024, kb_per_s);
     1085                        }
     1086                        break;
     1087                case REJECT:
     1088                        if( file->status == FT_STATUS_LISTENING )
     1089                        {
     1090                                irc_usermsg( irc, "Rejecting file transfer for %s", file->file_name );
     1091                                imcb_file_canceled( file, "Denied by user" );
     1092                        }
     1093                        break;
     1094                case CANCEL:
     1095                        if( file->local_id == fid )
     1096                        {
     1097                                irc_usermsg( irc, "Canceling file transfer for %s", file->file_name );
     1098                                imcb_file_canceled( file, "Canceled by user" );
     1099                        }
     1100                        break;
     1101                }
    10371102        }
    10381103}
     
    10581123        { "qlist",          0, cmd_qlist,          0 },
    10591124        { "join_chat",      2, cmd_join_chat,      0 },
     1125        { "transfers",      0, cmd_transfers,      0 },
    10601126        { NULL }
    10611127};
Note: See TracChangeset for help on using the changeset viewer.