home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Linux / Divers / yagirc-0.51.tar.gz / yagirc-0.51.tar / yagirc-0.51 / dcc.c < prev    next >
C/C++ Source or Header  |  1998-05-11  |  18KB  |  712 lines

  1. /*
  2.  
  3.  dcc.c : DCC functions
  4.  
  5.     Copyright (C) 1998 Timo Sirainen
  6.  
  7.     This program is free software; you can redistribute it and/or modify
  8.     it under the terms of the GNU General Public License as published by
  9.     the Free Software Foundation; either version 2 of the License, or
  10.     (at your option) any later version.
  11.  
  12.     This program is distributed in the hope that it will be useful,
  13.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.     GNU General Public License for more details.
  16.  
  17.     You should have received a copy of the GNU General Public License
  18.     along with this program; if not, write to the Free Software
  19.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. */
  21.  
  22. #include <stdio.h>
  23. #include <string.h>
  24. #include <sys/time.h>
  25.  
  26. #include <netdb.h>
  27. #include <fcntl.h>
  28. #include <unistd.h>
  29. #include <sys/types.h>
  30. #include <sys/signal.h>
  31. #include <sys/param.h>
  32. #include <sys/socket.h>
  33. #include <netinet/in.h>
  34. #include <arpa/inet.h>
  35.  
  36. #include <glib.h>
  37.  
  38. #include "os.h"
  39. #include "dcc.h"
  40. #include "gui.h"
  41. #include "irc.h"
  42. #include "txt.h"
  43. #include "events.h"
  44. #include "network.h"
  45. #include "params.h"
  46. #include "script.h"
  47. #include "misc.h"
  48.  
  49. GList *dcclist;
  50.  
  51. /* Get next parameter */
  52. static char *get_param(char **data)
  53. {
  54.     char *pos;
  55.  
  56.     g_return_val_if_fail(data != NULL, NULL);
  57.     g_return_val_if_fail(*data != NULL, NULL);
  58.  
  59.     pos = *data;
  60.     while (**data != '\0' && **data != ' ') (*data)++;
  61.     if (**data == ' ') *(*data)++ = '\0';
  62.  
  63.     return pos;
  64. }
  65.  
  66. /* Initialize DCC */
  67. void dcc_init(void)
  68. {
  69.     dcclist = NULL;
  70. }
  71.  
  72. /* Deinitialize DCC */
  73. void dcc_deinit(void)
  74. {
  75.     GList *tmp;
  76.     DCC_REC *dcc;
  77.  
  78.     for (tmp = g_list_first(dcclist); tmp != NULL; tmp = tmp->next)
  79.     {
  80.         dcc = (DCC_REC *) tmp->data;
  81.         if (!dcc->handle != -1) net_disconnect(dcc->handle);
  82.         g_free(dcc->nick);
  83.         g_free(dcc->arg);
  84.         if (dcc->addr != NULL) g_free(dcc->addr);
  85.         g_free(dcc);
  86.     }
  87.     g_list_free(dcclist); dcclist = NULL;
  88. }
  89.  
  90. /* Create new DCC record */
  91. static DCC_REC *dcc_create(int type, int handle, char *nick, char *arg)
  92. {
  93.     DCC_REC *dcc;
  94.  
  95.     g_return_val_if_fail(nick != NULL, NULL);
  96.     g_return_val_if_fail(arg != NULL, NULL);
  97.  
  98.     dcc = (DCC_REC *) g_malloc(sizeof(DCC_REC));
  99.     memset(dcc, 0, sizeof(DCC_REC));
  100.     dcc->type = type;
  101.     dcc->arg = g_strdup(arg);
  102.     dcc->nick = g_strdup(nick);
  103.     dcc->handle = handle;
  104.     /*dcc->addr = NULL;
  105.     dcc->port = 0;
  106.     dcc->buf = NULL;
  107.     dcc->starttime = 0;*/
  108.     dcclist = g_list_append(dcclist, dcc);
  109.  
  110.     return dcc;
  111. }
  112.  
  113. /* Destroy DCC record */
  114. static void dcc_destroy(DCC_REC *dcc, int dealloc)
  115. {
  116.     g_return_if_fail(dcc != NULL);
  117.  
  118.     if (dcc->fhandle != -1) { close(dcc->fhandle); dcc->fhandle = -1; }
  119.     if (dcc->handle != -1) { net_disconnect(dcc->handle); dcc->handle = -1; }
  120.     g_free(dcc->nick); dcc->nick = NULL;
  121.     g_free(dcc->arg); dcc->arg = NULL;
  122.     if (dcc->buf != NULL) { g_free(dcc->buf); dcc->buf = NULL; }
  123.     if (dcc->addr != NULL) { g_free(dcc->addr); dcc->addr = NULL; }
  124.     if (dcc->tag != -1) { gui_input_remove(dcc->tag); dcc->tag = -1; }
  125.     dcclist = g_list_remove(dcclist, dcc);
  126.     if (dealloc) g_free(dcc);
  127. }
  128.  
  129. /* Close specified DCC record */
  130. static int dcc_find_close(char *nick, int type, char *fname)
  131. {
  132.     DCC_REC *dcc;
  133.  
  134.     g_return_val_if_fail(nick != NULL, 0);
  135.     g_return_val_if_fail(fname != NULL, 0);
  136.  
  137.     dcc = dcc_find_item(type, nick, fname);
  138.     if (dcc == NULL) return 0;
  139.  
  140.     gui_dcc_force_close(dcc);
  141.     dcc_destroy(dcc, 1);
  142.     return 1;
  143. }
  144.  
  145. #if 0
  146. /* Return size in bytes/kB/MB depending how big file is */
  147. static char *bytes2str(char *buf, long bytes)
  148. {
  149.     g_return_val_if_fail(buf != NULL, NULL);
  150.  
  151.     if (bytes < 1024)
  152.         sprintf(buf, "%lu bytes", bytes);
  153.     else if (bytes < 1024*1024)
  154.         sprintf(buf, "%0.2f kB", bytes/1024.0);
  155.     else
  156.         sprintf(buf, "%0.2f MB", bytes/(float)(1024*1024));
  157.  
  158.     return buf;
  159. }
  160. #endif
  161.  
  162. /* input function: DCC GET received data */
  163. static void dcc_receive(DCC_REC *dcc)
  164. {
  165.     char buf[1024];
  166.     int len;
  167.     long recd;
  168.  
  169.     g_return_if_fail(dcc != NULL);
  170.  
  171.     if (dcc->starttime == 0) dcc->starttime = time(NULL);
  172.     for (;;)
  173.     {
  174.         len = net_receive(dcc->handle, buf, sizeof(buf));
  175.         if (len == 0) break;
  176.         if (len < 0)
  177.         {
  178.             /* socket closed - transmit complete (or other side died..) */
  179.             dcc_destroy(dcc, 0);
  180.             gui_dcc_close(dcc);
  181.             return;
  182.         }
  183.  
  184.         write(dcc->fhandle, buf, len);
  185.         dcc->transfd += len;
  186.     }
  187.  
  188.     /* send number of total bytes received */
  189.     recd = htonl(dcc->transfd);
  190.     net_transmit(dcc->handle, (char *) &recd, 4);
  191.  
  192.     /* Update GUI window */
  193.     gui_dcc_update(dcc);
  194. }
  195.  
  196. /* /DCC GET command */
  197. int dcc_get(char *data)
  198. {
  199.     GList *tmp;
  200.     DCC_REC *dcc;
  201.     char *str;
  202.  
  203.     g_return_val_if_fail(data != NULL, RET_ERR_PARAM);
  204.     if (*data == '\0') return RET_NOT_ENOUGH_PARAMS;
  205.  
  206.     for (tmp = g_list_first(dcclist); tmp != NULL; tmp = tmp->next)
  207.     {
  208.         dcc = (DCC_REC *) tmp->data;
  209.  
  210.         if (dcc->type == DCC_TYPE_GET && dcc->handle == -1 &&
  211.             strcasecmp(dcc->nick, data) == 0)
  212.         {
  213.             /* found! */
  214.             break;
  215.         }
  216.     }
  217.  
  218.     if (tmp == NULL)
  219.     {
  220.         drawtext(curwin, TXT_TYPE_DCC, IRCTXT_DCC_GET_NOT_FOUND, data);
  221.         return RET_ERROR;
  222.     }
  223.     
  224.     dcc->handle = net_connect(dcc->addr, dcc->port);
  225.     if (dcc->handle == -1)
  226.     {
  227.         /* error connecting */
  228.         drawtext(curwin, TXT_TYPE_DCC, IRCTXT_DCC_CONNECT_ERROR, dcc->addr, dcc->port);
  229.         dcc_destroy(dcc, 1);
  230.     }
  231.     else
  232.     {
  233.         /* ok connect */
  234.         str = strrchr(dcc->arg, '/');
  235.         if (str == NULL) str = dcc->arg; else str++;
  236.  
  237.         dcc->fhandle = open(str, O_WRONLY | O_TRUNC | O_CREAT, FILE_CREATE_MODE);
  238.         if (dcc->handle == -1)
  239.         {
  240.             drawtext(curwin, TXT_TYPE_DCC, IRCTXT_DCC_CANT_CREATE, str);
  241.             return RET_ERROR;
  242.         }
  243.         drawtext(curwin, TXT_TYPE_DCC, IRCTXT_DCC_GET_CONNECTED,
  244.                  dcc->arg, dcc->nick, dcc->addr, dcc->port);
  245.         dcc->transfd = 0;
  246.         gui_dcc_init(dcc);
  247.         dcc->tag = gui_input_add(dcc->handle, GUI_INPUT_READ, (GUI_INPUT_FUNC) dcc_receive, dcc);
  248.     }
  249.     return RET_OK;
  250. }
  251.  
  252. /* Abort DCC transfer */
  253. int dcc_abort(DCC_REC *dcc)
  254. {
  255.     g_return_val_if_fail(dcc != NULL, 0);
  256.  
  257.     dcc_destroy(dcc, 0);
  258.     gui_dcc_close(dcc);
  259.     return 1;
  260. }
  261.  
  262. /* DCC SEND - send more data */
  263. static void dcc_send_data(DCC_REC *dcc)
  264. {
  265.     char buf[1024];
  266.     int n;
  267.  
  268.     g_return_if_fail(dcc != NULL);
  269.  
  270.     n = read(dcc->fhandle, buf, sizeof(buf));
  271.     if (n <= 0)
  272.     {
  273.         /* end of file .. or some error .. */
  274.         dcc_abort(dcc);
  275.         return;
  276.     }
  277.  
  278.     dcc->transfd += net_transmit(dcc->handle, buf, n);
  279.     gui_dcc_update(dcc);
  280. }
  281.  
  282. /* input function: DCC SEND received some data */
  283. static void dcc_send_func(DCC_REC *dcc)
  284. {
  285.     long bytes;
  286.     int ret;
  287.  
  288.     g_return_if_fail(dcc != NULL);
  289.  
  290.     /* we need to get 4 bytes.. */
  291.     ret = net_receive(dcc->handle, dcc->buf+dcc->bufpos, 4-dcc->bufpos);
  292.     if (ret == -1)
  293.     {
  294.         dcc_abort(dcc);
  295.         return;
  296.     }
  297.  
  298.     dcc->bufpos += ret;
  299.     if (dcc->bufpos < 4)
  300.     {
  301.         /* those 4 bytes haven't came yet, wait more.. */
  302.         return;
  303.     }
  304.  
  305.     dcc->bufpos = 0;
  306.     bytes = 0; memcpy(&bytes, dcc->buf, 4); bytes = ntohl(bytes);
  307.  
  308.     if (bytes == dcc->transfd)
  309.     {
  310.         /* ok, all bytes are sent - send more */
  311.         dcc_send_data(dcc);
  312.     }
  313. }
  314.  
  315. /* input function: DCC SEND - someone tried to connect to our socket */
  316. static void dcc_send_init(DCC_REC *dcc)
  317. {
  318.     char addr[40];
  319.     int handle, port;
  320.  
  321.     g_return_if_fail(dcc != NULL);
  322.  
  323.     /* accept connection */
  324.     handle = net_accept(dcc->handle, addr, &port);
  325.     if (handle == -1) return;
  326.  
  327.     drawtext(curwin, TXT_TYPE_DCC, IRCTXT_DCC_SEND_CONNECTED,
  328.              dcc->arg, dcc->nick, addr, port);
  329.     gui_input_remove(dcc->tag);
  330.     close(dcc->handle);
  331.     dcc->handle = handle;
  332.     dcc->addr = g_strdup(addr);
  333.     dcc->port = port;
  334.     dcc->transfd = 0;
  335.     dcc->buf = (char *) g_malloc(4);
  336.     dcc->bufpos = 0;
  337.     dcc->starttime = time(NULL);
  338.     dcc->tag = gui_input_add(handle, GUI_INPUT_READ, (GUI_INPUT_FUNC) dcc_send_func, dcc);
  339.  
  340.     /* send first bytes */
  341.     dcc_send_data(dcc);
  342. }
  343.  
  344. /* /DCC SEND command */
  345. int dcc_send(char *data)
  346. {
  347.     char tmp[512], addr[50], *target, *fname, *ptr;
  348.     int fh, h, port;
  349.     long fsize;
  350.     DCC_REC *dcc;
  351.  
  352.     g_return_val_if_fail(data != NULL, RET_ERR_PARAM);
  353.     if (curwin->defserv == NULL) return RET_NOT_CONNECTED;
  354.  
  355.     target = get_param(&data);
  356.     fname = get_param(&data);
  357.  
  358.     if (dcc_find_item(DCC_TYPE_SEND, target, fname))
  359.     {
  360.         drawtext(curwin, TXT_TYPE_DCC, IRCTXT_DCC_SEND_EXISTS, fname, target);
  361.         return RET_ERROR;
  362.     }
  363.  
  364.     ptr = convhome(fname);
  365.     fh = open(ptr, O_RDONLY);
  366.     g_free(ptr);
  367.     if (fh == -1)
  368.     {
  369.         drawtext(curwin, TXT_TYPE_DCC, IRCTXT_DCC_SEND_NOT_FOUND, fname);
  370.         return RET_ERROR;
  371.     }
  372.     fsize = lseek(fh, 0, SEEK_END);
  373.     lseek(fh, 0, SEEK_SET);
  374.  
  375.     /* get the IP address we use with IRC server */
  376.     if (!net_getsockname(curwin->defserv->handle, addr, NULL))
  377.     {
  378.         close(fh);
  379.         return RET_ERR_GETSOCKNAME;
  380.     }
  381.  
  382.     /* start listening in any port */
  383.     port = 0;
  384.     h = net_listen(addr, &port);
  385.     if (h == -1)
  386.     {
  387.         close(fh);
  388.         return RET_ERR_LISTEN;
  389.     }
  390.  
  391.     /* skip path */
  392.     ptr = strrchr(fname, '/');
  393.     if (ptr != NULL) fname = ptr+1;
  394.  
  395.     dcc = dcc_create(DCC_TYPE_SEND, h, target, fname);
  396.     dcc->size = fsize;
  397.     dcc->fhandle = fh;
  398.     dcc->tag = gui_input_add(h, GUI_INPUT_READ, (GUI_INPUT_FUNC) dcc_send_init, dcc);
  399.  
  400.     /* send DCC request */
  401.     sprintf(tmp, "PRIVMSG %s :\001DCC SEND %s %lu %d %lu\001",
  402.             target, fname, (unsigned long) htonl(inet_addr(addr)), port, fsize);
  403.     irc_send_cmd(curwin->defserv, tmp);
  404.  
  405.     gui_dcc_init(dcc);
  406.  
  407.     return RET_OK;
  408. }
  409.  
  410. /* input function: DCC CHAT received some data.. */
  411. static void dcc_chat_input(DCC_REC *dcc)
  412. {
  413.     char tmp[512];
  414.     int n;
  415.  
  416.     g_return_if_fail(dcc != NULL);
  417.     do
  418.     {
  419.         n = read_line(1, dcc->handle, tmp, dcc->buf, 512, &dcc->bufpos);
  420.         if (n == -1)
  421.         {
  422.             /* connection lost */
  423.             drawtext(curwin, TXT_TYPE_DCC, IRCTXT_DCC_CHAT_DISCONNECTED, dcc->nick);
  424.             dcc_destroy(dcc, 1);
  425.             return;
  426.         }
  427.  
  428.         if (n > 0)
  429.         {
  430.             dcc->transfd += n;
  431. #ifdef USE_SCRIPT
  432.             script_event(NULL, dcc->nick, dcc->addr, "CTCP", tmp);
  433. #endif
  434.             gui_dcc_chat_write(dcc, tmp);
  435.         }
  436.     }
  437.     while (n > 0);
  438. }
  439.  
  440. /* input function: DCC CHAT - someone tried to connect to our socket */
  441. static void dcc_chat_listen(DCC_REC *dcc)
  442. {
  443.     char addr[40];
  444.     int handle, port;
  445.  
  446.     g_return_if_fail(dcc != NULL);
  447.  
  448.     /* accept connection */
  449.     handle = net_accept(dcc->handle, addr, &port);
  450.     if (handle == -1) return;
  451.  
  452.     drawtext(curwin, TXT_TYPE_DCC, IRCTXT_DCC_CHAT_CONNECTED,
  453.              dcc->nick, addr, port);
  454.     gui_input_remove(dcc->tag);
  455.     close(dcc->handle);
  456.     dcc->handle = handle;
  457.     dcc->addr = g_strdup(addr);
  458.     dcc->port = port;
  459.     dcc->transfd = 0;
  460.     dcc->buf = (char *) g_malloc(512);
  461.     dcc->bufpos = 0;
  462.     dcc->starttime = time(NULL);
  463.     dcc->tag = gui_input_add(handle, GUI_INPUT_READ, (GUI_INPUT_FUNC) dcc_chat_input, dcc);
  464. }
  465.  
  466. /* /DCC CHAT command */
  467. int dcc_chat(char *data)
  468. {
  469.     DCC_REC *dcc;
  470.     int port, handle;
  471.     char str[512], addr[50];
  472.  
  473.     g_return_val_if_fail(data != NULL, 2);
  474.  
  475.     dcc = dcc_find_item(DCC_TYPE_CHAT, data, NULL);
  476.     if (dcc != NULL)
  477.     {
  478.         /* found from dcc list - so we're the connecting side.. */
  479.         if (dcc->handle != -1)
  480.         {
  481.             /* already connected.. */
  482.             return RET_OK;
  483.         }
  484.  
  485.         dcc->handle = net_connect(dcc->addr, dcc->port);
  486.         if (dcc->handle == -1)
  487.         {
  488.             /* error connecting */
  489.             drawtext(curwin, TXT_TYPE_DCC, IRCTXT_DCC_CONNECT_ERROR, dcc->addr, dcc->port);
  490.             dcc_destroy(dcc, 1);
  491.         }
  492.         else
  493.         {
  494.             /* connect ok. */
  495.             dcc->buf = (char *) g_malloc(512);
  496.             gui_dcc_chat_init(dcc);
  497.             dcc->tag = gui_input_add(dcc->handle, GUI_INPUT_READ, (GUI_INPUT_FUNC) dcc_chat_input, dcc);
  498.         }
  499.         return RET_OK;
  500.     }
  501.  
  502.     /* send dcc chat request */
  503.  
  504.     if (curwin->defserv == NULL) return RET_NOT_CONNECTED;
  505.  
  506.     if (!net_getsockname(curwin->defserv->handle, addr, NULL))
  507.         return RET_ERR_GETSOCKNAME;
  508.  
  509.     port = 0;
  510.     handle = net_listen(addr, &port);
  511.     if (handle == -1) return RET_ERR_LISTEN;
  512.  
  513.     dcc = dcc_create(DCC_TYPE_CHAT, handle, data, "chat");
  514.     dcc->handle = handle;
  515.     dcc->tag = gui_input_add(dcc->handle, GUI_INPUT_READ, (GUI_INPUT_FUNC) dcc_chat_listen, dcc);
  516.  
  517.     /* send the request */
  518.     sprintf(str, "PRIVMSG %s :\001DCC CHAT CHAT %lu %d\001",
  519.             data, (unsigned long) htonl(inet_addr(addr)), port);
  520.     irc_send_cmd(curwin->defserv, str);
  521.  
  522.     return RET_OK;
  523. }
  524.  
  525. /* Send text to DCC chat */
  526. int dcc_chat_write(DCC_REC *dcc, char *str)
  527. {
  528.     g_return_val_if_fail(dcc != NULL, 0);
  529.     g_return_val_if_fail(str != NULL, 0);
  530.  
  531.     net_transmit(dcc->handle, str, strlen(str));
  532.     net_transmit(dcc->handle, "\r\n", 2);
  533.     return 1;
  534. }
  535.  
  536. /* /DCC LIST */
  537. int dcc_list(char *data)
  538. {
  539.     DCC_REC *dcc;
  540.     GList *tmp;
  541.  
  542.     g_return_val_if_fail(data != NULL, RET_ERR_PARAM);
  543.  
  544.     drawtext(curwin, TXT_TYPE_DCC, "%!DCC%! connections (under work..)\n");
  545.     for (tmp = g_list_first(dcclist); tmp != NULL; tmp = tmp->next)
  546.     {
  547.         dcc = (DCC_REC *) tmp->data;
  548.  
  549.         drawtext(curwin, TXT_TYPE_DCC, " %s: (%d) %s (%lu/%lu)\n",  dcc->nick, dcc->type,
  550.                  dcc->arg, dcc->transfd, dcc->size);
  551.     }
  552.  
  553.     return RET_OK;
  554. }
  555.  
  556. /* /DCC CLOSE */
  557. int dcc_close(char *data)
  558. {
  559.     DCC_REC *dcc, *found;
  560.     GList *tmp;
  561.     char *type, *nick, *arg;
  562.     int itype;
  563.  
  564.     g_return_val_if_fail(data != NULL, RET_ERR_PARAM);
  565.  
  566.     type = get_param(&data);
  567.     nick = get_param(&data);
  568.     arg = get_param(&data);
  569.  
  570.     strupr(type);
  571.     if (strcmp(type, "CHAT") == 0)
  572.         itype = DCC_TYPE_CHAT;
  573.     else if (strcmp(type, "GET") == 0)
  574.         itype = DCC_TYPE_GET;
  575.     else if (strcmp(type, "SEND") == 0)
  576.         itype = DCC_TYPE_SEND;
  577.     else
  578.     {
  579.         drawtext(curwin, TXT_TYPE_DCC, IRCTXT_DCC_UNKNOWN_TYPE, type);
  580.         return RET_ERROR;
  581.     }
  582.  
  583.     dcc = found = NULL;
  584.     for (tmp = g_list_first(dcclist); tmp != NULL; tmp = tmp->next)
  585.     {
  586.         dcc = (DCC_REC *) tmp->data;
  587.  
  588.         if (dcc->type == itype && strcasecmp(nick, dcc->nick) == 0)
  589.         {
  590.             if (found != NULL)
  591.             {
  592.                 /* multiple matches found - quit */
  593.                 return RET_MULTIPLE_MATCHES;
  594.             }
  595.             found = dcc;
  596.             if (*arg != '\0' && strcmp(arg, dcc->arg) == 0)
  597.             {
  598.                 /* identical match */
  599.                 break;
  600.             }
  601.         }
  602.     }
  603.  
  604.     if (found != NULL)
  605.     {
  606.         drawtext(curwin, TXT_TYPE_DCC, IRCTXT_DCC_CLOSE, type, dcc->nick, dcc->arg);
  607.         dcc_destroy(found, 1);
  608.     }
  609.  
  610.     return RET_OK;
  611. }
  612.  
  613. /* Find DCC record, arg can be NULL */
  614. DCC_REC *dcc_find_item(int type, char *nick, char *arg)
  615. {
  616.     DCC_REC *dcc;
  617.     GList *tmp;
  618.  
  619.     g_return_val_if_fail(nick != NULL, NULL);
  620.  
  621.     for (tmp = g_list_first(dcclist); tmp != NULL; tmp = tmp->next)
  622.     {
  623.         dcc = (DCC_REC *) tmp->data;
  624.  
  625.         if (dcc->type == type && strcasecmp(dcc->nick, nick) == 0 &&
  626.            (arg == NULL || strcmp(dcc->arg, arg) == 0))
  627.             return dcc;
  628.     }
  629.  
  630.     return NULL;
  631. }
  632.  
  633. /* Handle DCC CTCP commands */
  634. int dcc_handle_ctcp(char *sender, char *data)
  635. {
  636.     char *type, *arg;
  637.     int port;
  638.     unsigned long size, addr;
  639.     DCC_REC *dcc;
  640.  
  641.     g_return_val_if_fail(data != NULL, 1);
  642.     g_return_val_if_fail(sender != NULL, 1);
  643.  
  644.     type = event_get_param(&data);
  645.     arg = event_get_param(&data);
  646.     if (sscanf(event_get_param(&data), "%lu", &addr) != 1) addr = 0;
  647.     if (sscanf(event_get_param(&data), "%d", &port) != 1) port = 0;
  648.     if (sscanf(event_get_param(&data), "%lu", &size) != 1) size = 0;
  649.  
  650.     addr = (long) ntohl(addr);
  651.  
  652.     dcc = dcc_create(0, -1, sender, arg);
  653.     dcc->fhandle = -1;
  654.     dcc->handle = -1;
  655.     dcc->addr = g_strdup(inet_ntoa(*((struct in_addr *) &addr)));
  656.     dcc->port = port;
  657.     dcc->tag = -1;
  658.     dcc->size = size;
  659.  
  660.     if (strcasecmp(type, "SEND") == 0)
  661.     {
  662.         dcc->type = DCC_TYPE_GET;
  663.         drawtext(curwin, TXT_TYPE_DCC, IRCTXT_DCC_SEND, type, sender, dcc->addr, port, arg, size);
  664.     }
  665.     else if (strcasecmp(type, "CHAT") == 0)
  666.     {
  667.         dcc->type = DCC_TYPE_CHAT;
  668.         drawtext(curwin, TXT_TYPE_DCC, IRCTXT_DCC_CHAT, sender, dcc->addr, port);
  669.     }
  670.     else
  671.     {
  672.         /* unknown DCC command */
  673.         drawtext(curwin, TXT_TYPE_DCC, IRCTXT_DCC_UNKNOWN_CTCP, type, sender, dcc->addr, port, arg, size);
  674.         dcc_destroy(dcc, 1); dcc = NULL;
  675.     }
  676.  
  677.     return 0;
  678. }
  679.  
  680. /* Handle DCC replies */
  681. int dcc_reply(char *sender, char *data)
  682. {
  683.     char *cmd;
  684.  
  685.     g_return_val_if_fail(data != NULL, 0);
  686.     g_return_val_if_fail(sender != NULL, 0);
  687.  
  688.     cmd = get_param(&data);
  689.  
  690.     if (strcasecmp(cmd, "REJECT") == 0)
  691.     {
  692.         cmd = get_param(&data);
  693.         if (strcasecmp(cmd, "GET") == 0)
  694.         {
  695.             drawtext(curwin, TXT_TYPE_DCC, IRCTXT_DCC_REJECTED, "GET", sender, data);
  696.             dcc_find_close(sender, DCC_TYPE_GET, data);
  697.         }
  698.         else if (strcasecmp(cmd, "SEND") == 0)
  699.         {
  700.             drawtext(curwin, TXT_TYPE_DCC, IRCTXT_DCC_REJECTED, "SEND", sender, data);
  701.             dcc_find_close(sender, DCC_TYPE_SEND, data);
  702.         }
  703.     }
  704.     else
  705.     {
  706.         /* unknown DCC reply */
  707.         drawtext(curwin, TXT_TYPE_DCC, IRCTXT_DCC_UNKNOWN_REPLY, cmd, sender, data);
  708.     }
  709.  
  710.     return 1;
  711. }
  712.