Changes in / [eeb85a8:1ba7e8f]


Ignore:
Files:
5 added
13 edited

Legend:

Unmodified
Added
Removed
  • Makefile

    reeb85a8 r1ba7e8f  
    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

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

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

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

    reeb85a8 r1ba7e8f  
    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 );
     
    995999                        return( 1 );
    9961000                }
     1001                else if( g_strncasecmp( s + 1, "DCC", 3 ) == 0 )
     1002                {
     1003                        if( u && u->ic && u->ic->acc->prpl->transfer_request )
     1004                        {
     1005                                file_transfer_t *ft = dcc_request( u->ic, s + 5 );
     1006                                if ( ft )
     1007                                        u->ic->acc->prpl->transfer_request( u->ic, ft, u->handle );
     1008                        }
     1009                        return( 1 );
     1010                }               
    9971011                else
    9981012                {
    999                         irc_usermsg( irc, "Non-ACTION CTCP's aren't supported" );
     1013                        irc_usermsg( irc, "Supported CTCPs are ACTION, VERSION, PING, TYPING, DCC" );
    10001014                        return( 0 );
    10011015                }
  • irc.h

    reeb85a8 r1ba7e8f  
    8484        struct query *queries;
    8585        struct account *accounts;
     86        GSList *file_transfers;
    8687       
    8788        struct __USER *users;
  • protocols/jabber/Makefile

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

    reeb85a8 r1ba7e8f  
    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                }
     
    568576        return st;
    569577}
     578
     579xt_status jabber_iq_parse_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig );
     580
     581xt_status jabber_iq_query_features( struct im_connection *ic, char *bare_jid )
     582{
     583        struct xt_node *node, *query;
     584        struct jabber_buddy *bud;
     585       
     586        if( ( bud = jabber_buddy_by_jid( ic, bare_jid , 0 ) ) == NULL )
     587        {
     588                /* Who cares about the unknown... */
     589                imcb_log( ic, "Couldnt find the man: %s", bare_jid);
     590                return 0;
     591        }
     592       
     593        if( bud->features ) /* been here already */
     594                return XT_HANDLED;
     595       
     596        node = xt_new_node( "query", NULL, NULL );
     597        xt_add_attr( node, "xmlns", XMLNS_DISCO_INFO );
     598       
     599        if( !( query = jabber_make_packet( "iq", "get", bare_jid, node ) ) )
     600        {
     601                imcb_log( ic, "WARNING: Couldn't generate feature query" );
     602                xt_free_node( node );
     603        }
     604
     605        jabber_cache_add( ic, query, jabber_iq_parse_features );
     606
     607        return jabber_write_packet( ic, query );
     608}
     609
     610xt_status jabber_iq_parse_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig )
     611{
     612        struct xt_node *c;
     613        struct jabber_buddy *bud;
     614        char *feature;
     615
     616        if( !( c = xt_find_node( node->children, "query" ) ) ||
     617            !( strcmp( xt_find_attr( c, "xmlns" ), XMLNS_DISCO_INFO ) == 0 ) )
     618        {
     619                imcb_log( ic, "WARNING: Received incomplete IQ-result packet for discover" );
     620                return XT_HANDLED;
     621        }
     622        if( ( bud = jabber_buddy_by_jid( ic, xt_find_attr( node, "from") , 0 ) ) == NULL )
     623        {
     624                /* Who cares about the unknown... */
     625                imcb_log( ic, "Couldnt find the man: %s", xt_find_attr( node, "from"));
     626                return 0;
     627        }
     628       
     629        c = c->children;
     630        while( ( c = xt_find_node( c, "feature" ) ) ) {
     631                feature = xt_find_attr( c, "var" );
     632                bud->features = g_slist_append(bud->features, g_strdup(feature) );
     633                c = c->next;
     634        }
     635
     636        return XT_HANDLED;
     637}
     638
     639xt_status jabber_iq_parse_server_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig );
     640
     641xt_status jabber_iq_query_server( struct im_connection *ic, char *jid, char *xmlns )
     642{
     643        struct xt_node *node, *query;
     644        struct jabber_data *jd = ic->proto_data;
     645       
     646        node = xt_new_node( "query", NULL, NULL );
     647        xt_add_attr( node, "xmlns", xmlns );
     648       
     649        if( !( query = jabber_make_packet( "iq", "get", jid, node ) ) )
     650        {
     651                imcb_log( ic, "WARNING: Couldn't generate server query" );
     652                xt_free_node( node );
     653        }
     654
     655        jd->have_streamhosts--;
     656        jabber_cache_add( ic, query, jabber_iq_parse_server_features );
     657
     658        return jabber_write_packet( ic, query );
     659}
     660
     661/*
     662 * Query the server for "items", query each "item" for identities, query each "item" that's a proxy for it's bytestream info
     663 */
     664xt_status jabber_iq_parse_server_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig )
     665{
     666        struct xt_node *c;
     667        struct jabber_data *jd = ic->proto_data;
     668
     669        if( !( c = xt_find_node( node->children, "query" ) ) ||
     670            !xt_find_attr( node, "from" ) )
     671        {
     672                imcb_log( ic, "WARNING: Received incomplete IQ-result packet for discover" );
     673                return XT_HANDLED;
     674        }
     675
     676        jd->have_streamhosts++;
     677
     678        if( strcmp( xt_find_attr( c, "xmlns" ), XMLNS_DISCO_ITEMS ) == 0 )
     679        {
     680                char *item, *itemjid;
     681
     682                /* answer from server */
     683       
     684                c = c->children;
     685                while( ( c = xt_find_node( c, "item" ) ) )
     686                {
     687                        item = xt_find_attr( c, "name" );
     688                        itemjid = xt_find_attr( c, "jid" );
     689
     690                        jabber_iq_query_server( ic, itemjid, XMLNS_DISCO_INFO );
     691
     692                        c = c->next;
     693                }
     694        } else if( strcmp( xt_find_attr( c, "xmlns" ), XMLNS_DISCO_INFO ) == 0 )
     695        {
     696                char *category, *type;
     697
     698                /* answer from potential proxy */
     699
     700                c = c->children;
     701                while( ( c = xt_find_node( c, "identity" ) ) )
     702                {
     703                        category = xt_find_attr( c, "category" );
     704                        type = xt_find_attr( c, "type" );
     705
     706                        if( type && ( strcmp( type, "bytestreams" ) == 0 ) &&
     707                            category && ( strcmp( category, "proxy" ) == 0 ) )
     708                                jabber_iq_query_server( ic, xt_find_attr( node, "from" ), XMLNS_BYTESTREAMS );
     709
     710                        c = c->next;
     711                }
     712        } else if( strcmp( xt_find_attr( c, "xmlns" ), XMLNS_BYTESTREAMS ) == 0 )
     713        {
     714                char *host, *jid;
     715                int port;
     716
     717                /* answer from proxy */
     718
     719                if( ( c = xt_find_node( c->children, "streamhost" ) ) &&
     720                    ( host = xt_find_attr( c, "host" ) ) &&
     721                    ( port = atoi( xt_find_attr( c, "port" ) ) ) &&
     722                    ( jid = xt_find_attr( c, "jid" ) ) )
     723                {
     724                        jabber_streamhost_t *sh = g_new0( jabber_streamhost_t, 1 );
     725                        sh->jid = g_strdup( jid );
     726                        sh->host = g_strdup( host );
     727                        sprintf( sh->port, "%u", port );
     728
     729                        imcb_log( ic, "Proxy found: jid %s host %s port %u", jid, host, port );
     730                        jd->streamhosts = g_slist_append( jd->streamhosts, sh );
     731                }
     732        }
     733
     734        if( jd->have_streamhosts == 0 )
     735                jd->have_streamhosts++;
     736        return XT_HANDLED;
     737}
  • protocols/jabber/jabber.c

    reeb85a8 r1ba7e8f  
    529529        ret->send_typing = jabber_send_typing;
    530530        ret->handle_cmp = g_strcasecmp;
     531        ret->transfer_request = jabber_si_transfer_request;
    531532
    532533        register_protocol( ret );
  • protocols/jabber/jabber.h

    reeb85a8 r1ba7e8f  
    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

    reeb85a8 r1ba7e8f  
    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
     
    287291        new = g_new( char, len + 1 );
    288292        for( i = 0; i < len; i ++ )
     293        {
     294                /* don't normalize the resource */
     295                if( orig[i] == '/' )
     296                        break;
    289297                new[i] = tolower( orig[i] );
     298        }
     299        for( ; i < len; i ++ )
     300                new[i] = orig[i];
    290301       
    291302        new[i] = 0;
  • protocols/nogaim.h

    reeb85a8 r1ba7e8f  
    4343#include "proxy.h"
    4444#include "md5.h"
     45#include "ft.h"
    4546
    4647#define BUF_LEN MSG_LEN
     
    228229         * - Most protocols will just want to set this to g_strcasecmp().*/
    229230        int (* handle_cmp) (const char *who1, const char *who2);
     231
     232        /* Incoming transfer request */
     233        void (* transfer_request) (struct im_connection *, file_transfer_t *ft, char *handle );
    230234};
    231235
  • root_commands.c

    reeb85a8 r1ba7e8f  
    969969                irc_usermsg( irc, "Tried to join chat, not sure if this was successful" );
    970970                g_free( channel );
     971        }
     972}
     973
     974static void cmd_transfers( irc_t *irc, char **cmd )
     975{
     976        GSList *files = irc->file_transfers;
     977        enum { LIST, REJECT, CANCEL };
     978        int subcmd = LIST;
     979        int fid;
     980
     981        if( !files )
     982        {
     983                irc_usermsg( irc, "No pending transfers" );
     984                return;
     985        }
     986
     987        if( cmd[1] &&
     988            ( strcmp( cmd[1], "reject" ) == 0 ) )
     989        {
     990                subcmd = REJECT;
     991        }
     992        else if( cmd[1] &&
     993                 ( strcmp( cmd[1], "cancel" ) == 0 ) &&
     994                 cmd[2] &&
     995                 ( fid = atoi( cmd[2] ) ) )
     996        {
     997                subcmd = CANCEL;
     998        }
     999
     1000        for( ; files; files = g_slist_next( files ) )
     1001        {
     1002                file_transfer_t *file = files->data;
     1003               
     1004                switch( subcmd ) {
     1005                case LIST:
     1006                        if ( file->status == FT_STATUS_LISTENING )
     1007                                irc_usermsg( irc,
     1008                                        "Pending file(id %d): %s (Listening...)", file->local_id, file->file_name);
     1009                        else
     1010                        {
     1011                                int kb_per_s = 0;
     1012                                time_t diff = time( NULL ) - file->started;
     1013                                if ( ( file->started > 0 ) && ( file->bytes_transferred > 0 ) )
     1014                                        kb_per_s = file->bytes_transferred / 1024 / diff;
     1015                                       
     1016                                irc_usermsg( irc,
     1017                                        "Pending file(id %d): %s (%10zd/%zd kb, %d kb/s)", file->local_id, file->file_name,
     1018                                        file->bytes_transferred/1024, file->file_size/1024, kb_per_s);
     1019                        }
     1020                        break;
     1021                case REJECT:
     1022                        if( file->status == FT_STATUS_LISTENING )
     1023                        {
     1024                                irc_usermsg( irc, "Rejecting file transfer for %s", file->file_name );
     1025                                imcb_file_canceled( file, "Denied by user" );
     1026                        }
     1027                        break;
     1028                case CANCEL:
     1029                        if( file->local_id == fid )
     1030                        {
     1031                                irc_usermsg( irc, "Canceling file transfer for %s", file->file_name );
     1032                                imcb_file_canceled( file, "Canceled by user" );
     1033                        }
     1034                        break;
     1035                }
    9711036        }
    9721037}
     
    9921057        { "qlist",          0, cmd_qlist,          0 },
    9931058        { "join_chat",      2, cmd_join_chat,      0 },
     1059        { "transfers",      0, cmd_transfers,      0 },
    9941060        { NULL }
    9951061};
Note: See TracChangeset for help on using the changeset viewer.