home *** CD-ROM | disk | FTP | other *** search
/ Hackers Toolkit 2.0 / Hackers_Toolkit_v2.0.iso / HTML / archive / Unix / c-src / ctcp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-11-04  |  17.0 KB  |  777 lines

  1. /*
  2.  * ctcp.c:handles the client-to-client protocol(ctcp). 
  3.  *
  4.  * Written By Michael Sandrof 
  5.  *
  6.  * Copyright(c) 1990 
  7.  *
  8.  * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
  9.  */
  10. #ifdef sgi
  11. # include <stdio.h>
  12. #endif /* sgi*/
  13. #include <pwd.h>
  14. #include "irc.h"
  15. #include "ircaux.h"
  16. #include "hook.h"
  17. #include "crypt.h"
  18. #include "ctcp.h"
  19. #include "vars.h"
  20. #include "server.h"
  21. #include "status.h"
  22. #include "lastlog.h"
  23. #include "ignore.h"
  24. #include "output.h"
  25. #include "window.h"
  26. #include "dcc.h"
  27. #include "names.h"
  28.  
  29. #define    CTCP_SHUTUP    0
  30. #define    CTCP_VERBOSE    1
  31. #define    CTCP_NOREPLY    2
  32.  
  33. static    char    CTCP_Reply_Buffer[BIG_BUFFER_SIZE + 1] = "";
  34.  
  35. static    void    do_new_notice_ctcp();
  36.  
  37. extern    void    strmcat();
  38.  
  39. /* forward declarations for the built in CTCP functions */
  40. static    char    *do_sed();
  41. static    char    *do_version();
  42. static    char    *do_clientinfo();
  43. static    char    *do_echo();
  44. static    char    *do_userinfo();
  45. static    char    *do_finger();
  46. static    char    *do_time();
  47. static    char    *do_atmosphere();
  48. static    char    *do_dcc();
  49. extern    char    *do_utc();
  50.  
  51. static CtcpEntry ctcp_cmd[] =
  52. {
  53.     { "SED",    "contains simple_encrypted_data",
  54.         CTCP_SHUTUP | CTCP_NOREPLY, do_sed },
  55.     { "VERSION",    "shows client type, version and environment",
  56.         CTCP_VERBOSE, do_version },
  57.     { "CLIENTINFO",    "gives information about available CTCP commands",
  58.         CTCP_VERBOSE, do_clientinfo },
  59.     { "USERINFO",    "returns user settable information",
  60.         CTCP_VERBOSE, do_userinfo },
  61.     { "ERRMSG",    "returns error messages",
  62.         CTCP_VERBOSE, do_echo },
  63.     { "FINGER",    "shows real name, login name and idle time of user",
  64.         CTCP_VERBOSE, do_finger },
  65.     { "TIME",    "tells you the time on the user's host",
  66.         CTCP_VERBOSE, do_time },
  67.     { "ACTION",    "contains action descriptions for atmosphere",
  68.         CTCP_SHUTUP, do_atmosphere },
  69.     { "DCC",    "requests a direct_client_connection",
  70.         CTCP_SHUTUP | CTCP_NOREPLY, do_dcc },
  71.     { "UTC",    "substitutes the local timezone",
  72.         CTCP_SHUTUP | CTCP_NOREPLY, do_utc },
  73.     { "PING",     "returns the arguments it receives",
  74.         CTCP_VERBOSE, do_echo },
  75.     { "ECHO",     "returns the arguments it receives",
  76.         CTCP_VERBOSE, do_echo }
  77. };
  78.  
  79. char    *ctcp_type[] =
  80. {
  81.     "PRIVMSG",
  82.     "NOTICE"
  83. };
  84.  
  85. static    char    ctcp_buffer[BIG_BUFFER_SIZE + 1];
  86.  
  87. /*
  88.  * in_ctcp_flag is set to true when IRCII is handling a CTCP request.  This
  89.  * is used by the ctcp() sending function to force NOTICEs to be used in any
  90.  * CTCP REPLY 
  91.  */
  92. int    in_ctcp_flag = 0;
  93.  
  94. /*
  95.  * ctcp_last_reply_time: Used to stop flooding...  We only send one ctcp
  96.  * reply a second.. if the variable NOCTCP_FLOOD is set...  If the current
  97.  * second is still the same, we drop the request, and info the user.
  98.  */
  99. Long    ctcp_last_reply_time = 0;
  100.  
  101. int    ctcp_dropped;
  102.  
  103. extern    char    *FromUserHost;
  104. /*
  105.  * quote_it: This quotes the given string making it sendable via irc.  A
  106.  * pointer to the length of the data is required and the data need not be
  107.  * null terminated (it can contain nulls).  Returned is a malloced, null
  108.  * terminated string.   
  109.  */
  110. char    *ctcp_quote_it(str, len)
  111. char    *str;
  112. int    len;
  113. {
  114.     char    buffer[BIG_BUFFER_SIZE + 1];
  115.     char    *ptr;
  116.     int    i;
  117.  
  118.     ptr = buffer;
  119.     for (i = 0; i < len; i++)
  120.     {
  121.         switch (str[i])
  122.         {
  123.         case CTCP_DELIM_CHAR:
  124.             *(ptr++) = CTCP_QUOTE_CHAR;
  125.             *(ptr++) = 'a';
  126.             break;
  127.         case '\n':
  128.             *(ptr++) = CTCP_QUOTE_CHAR;
  129.             *(ptr++) = 'n';
  130.             break;
  131.         case '\r':
  132.             *(ptr++) = CTCP_QUOTE_CHAR;
  133.             *(ptr++) = 'r';
  134.             break;
  135.         case CTCP_QUOTE_CHAR:
  136.             *(ptr++) = CTCP_QUOTE_CHAR;
  137.             *(ptr++) = CTCP_QUOTE_CHAR;
  138.             break;
  139.         case '\0':
  140.             *(ptr++) = CTCP_QUOTE_CHAR;
  141.             *(ptr++) = '0';
  142.             break;
  143.         default:
  144.             *(ptr++) = str[i];
  145.             break;
  146.         }
  147.     }
  148.     *ptr = null(char);        /* null terminate it anyway */
  149.     str = null(char *);
  150.     malloc_strcpy(&str, buffer);
  151.     return (str);
  152. }
  153.  
  154. /*
  155.  * ctcp_unquote_it: This takes a null terminated string that had previously
  156.  * been quoted using ctcp_quote_it and unquotes it.  Returned is a malloced
  157.  * space pointing to the unquoted string.  NOTE: a trailing null is added for
  158.  * convenied, but the returned data may contain nulls!.  The len is modified
  159.  * to contain the size of the data returned. 
  160.  */
  161. char    *ctcp_unquote_it(str, len)
  162. char    *str;
  163. int    *len;
  164. {
  165.     char    *buffer;
  166.     char    *ptr;
  167.     char    c;
  168.     int    i,
  169.         new_size = 0;
  170.  
  171.     buffer = (char *) new_malloc(sizeof(char) * *len);
  172.     ptr = buffer;
  173.     i = 0;
  174.     while (i < *len)
  175.     {
  176.         if ((c = str[i++]) == CTCP_QUOTE_CHAR)
  177.         {
  178.             switch (c = str[i++])
  179.             {
  180.             case CTCP_QUOTE_CHAR:
  181.                 *(ptr++) = CTCP_QUOTE_CHAR;
  182.                 break;
  183.             case 'a':
  184.                 *(ptr++) = CTCP_DELIM_CHAR;
  185.                 break;
  186.             case 'n':
  187.                 *(ptr++) = '\n';
  188.                 break;
  189.             case 'r':
  190.                 *(ptr++) = '\r';
  191.                 break;
  192.             case '0':
  193.                 *(ptr++) = null(char);
  194.                 break;
  195.             default:
  196.                 *(ptr++) = c;
  197.                 break;
  198.             }
  199.         }
  200.         else
  201.             *(ptr++) = c;
  202.         new_size++;
  203.     }
  204.     *ptr = null(char);
  205.     *len = new_size;
  206.     return (buffer);
  207. }
  208.  
  209. /*
  210.  * do_sed: Performs the Simple Encrypted Data trasfer for ctcp.  Returns in a
  211.  * malloc string the decryped message (if a key is set for that user) or the
  212.  * text "[ENCRYPTED MESSAGE]" 
  213.  */
  214. static    char    *do_sed(ctcp, from, to, args)
  215. CtcpEntry    *ctcp;
  216. char    *from,
  217.     *to,
  218.     *args;
  219. {
  220.     char    *key,
  221.         *crypt_who;
  222.     char    *ret = null(char *);
  223.  
  224.     if (stricmp(to, get_server_nickname(from_server)))
  225.         crypt_who = to;
  226.     else
  227.         crypt_who = from;
  228.     if (key = is_crypted(crypt_who))
  229.     {
  230.         if ((ret = crypt_msg(args, key, 0)) == null(char *))
  231.             malloc_strcpy(&ret, "[ENCRYPTED MESSAGE]");
  232.     }
  233.     else
  234.         malloc_strcpy(&ret, "[ENCRYPTED MESSAGE]");
  235.     return (ret);
  236. }
  237.  
  238. /*
  239.  * do_clientinfo: performs the CLIENTINFO CTCP.  If cmd is empty, returns the
  240.  * list of all CTCPs currently recognized by IRCII.  If an arg is supplied,
  241.  * it returns specific information on that CTCP.  If a matching CTCP is not
  242.  * found, an ERRMSG ctcp is returned 
  243.  */
  244. static    char    *do_clientinfo(ctcp, from, to, cmd)
  245. CtcpEntry    *ctcp;
  246. char    *from,
  247.     *to,
  248.     *cmd;
  249. {
  250.     int    i;
  251.  
  252.     if (cmd && *cmd)
  253.     {
  254.         for (i = 0; i < NUMBER_OF_CTCPS; i++)
  255.         {
  256.             if (stricmp(cmd, ctcp_cmd[i].name) == 0)
  257.             {
  258.                 send_ctcp_reply(from, ctcp->name, "%s %s",
  259.                     ctcp_cmd[i].name, ctcp_cmd[i].desc);
  260.                 return (null(char *));
  261.             }
  262.         }
  263.         send_ctcp_reply(from, ctcp_cmd[CTCP_ERRMSG].name,
  264.                 "%s: %s is not a valid function",
  265.                 ctcp_cmd[CTCP_CLIENTINFO].name, cmd);
  266.     }
  267.     else
  268.     {
  269.         *buffer = null(char);
  270.         for (i = 0; i < NUMBER_OF_CTCPS; i++)
  271.         {
  272.             strmcat(buffer, ctcp_cmd[i].name, BIG_BUFFER_SIZE);
  273.             strmcat(buffer, " ", BIG_BUFFER_SIZE);
  274.         }
  275.         send_ctcp_reply(from, ctcp->name, 
  276.             "%s :Use CLIENTINFO <COMMAND> to get more specific \
  277. information",
  278.             buffer);
  279.     }
  280.     return (null(char *));
  281. }
  282.  
  283. /* do_version: does the CTCP VERSION command */
  284. static    char    *do_version(ctcp, from, to, cmd)
  285. CtcpEntry    *ctcp;
  286. char    *from,
  287.     *to,
  288.     *cmd;
  289. {
  290.     char    *tmp;
  291.  
  292.     send_ctcp_reply(from, ctcp->name, "ircII %s *IX :%s",
  293.         irc_version, (tmp = get_string_var(CLIENTINFO_VAR)) ?
  294.             tmp : IRCII_COMMENT);
  295.     return (null(char *));
  296. }
  297.  
  298. /* do_time: does the CTCP TIME command --- done by Veggen */
  299. static    char    *do_time(ctcp, from, to, cmd)
  300. CtcpEntry    *ctcp;
  301. char    *from,
  302.     *to,
  303.     *cmd;
  304. {
  305.     send_ctcp_reply(from, ctcp->name, update_clock(GET_TIME));
  306.     return (null(char *));
  307. }
  308.  
  309. /* do_userinfo: does the CTCP USERINFO command */
  310. static    char    *do_userinfo(ctcp, from, to, cmd)
  311. CtcpEntry    *ctcp;
  312. char    *from,
  313.     *to,
  314.     *cmd;
  315. {
  316.     send_ctcp_reply(from, ctcp->name, get_string_var(USERINFO_VAR));
  317.     return (null(char *));
  318. }
  319.  
  320. /*
  321.  * do_echo: does the CTCP ECHO, CTCP ERRMSG and CTCP ECHO commands. Does
  322.  * not send an error for ERRMSG and if the CTCP was sent to a channel.
  323.  */
  324. static    char    *do_echo(ctcp, from, to, cmd)
  325. CtcpEntry    *ctcp;
  326. char    *from,
  327.     *to,    
  328.     *cmd;
  329. {
  330.     if (!is_channel(to) || strcmp(from, "ERRMSG"))
  331.         send_ctcp_reply(from, ctcp->name, "%s", cmd);
  332.     return (null(char *));
  333. }
  334.  
  335. static    char    *do_finger(ctcp, from, to, cmd)
  336. CtcpEntry    *ctcp;
  337. char    *from,
  338.     *to,
  339.     *cmd;
  340. {
  341.     struct    passwd    *pwd;
  342.     Long    diff;
  343.     int    uid;
  344.     char    c;
  345.  
  346.     /*
  347.      * sojge complained that ircII says 'idle 1 seconds'
  348.      * well, now he won't ever get the chance to see that message again
  349.      *   *grin*  ;-)    -lynx
  350.      *
  351.      * Made this better by saying 'idle 1 second'  -phone
  352.      */
  353.  
  354.     diff = time(0) - idle_time;
  355.     c = (diff == 1)? ' ': 's';
  356.     uid = getuid();
  357. #ifdef DAEMON_UID
  358.     if (uid != DAEMON_UID)
  359.     {
  360. #endif /* DAEMON_UID */    
  361.         if (pwd = getpwuid(uid))
  362.         {
  363.             char    *tmp;
  364.  
  365. #ifdef GECOS_DELIMITER
  366.             if (tmp = index(pwd->pw_gecos, GECOS_DELIMITER))
  367. #else
  368.             if (tmp = index(pwd->pw_gecos, ','))
  369. #endif /* GECOS_DELIMITER */
  370.                 *tmp = '\0';
  371.                         /* Patched to allow fake ctcp info. */
  372.             send_ctcp_reply(from, ctcp->name,
  373.                 "%s (%s@%s) Idle %ld second%c", getenv("IRCNAME"),
  374.                 getenv("IRCUSER"), getenv("IRCHOST"), diff, c);
  375.         }
  376. #ifdef DAEMON_UID
  377.     }
  378.     else
  379.         send_ctcp_reply(from, ctcp->name,
  380.             "IRCII Telnet User (%s) Idle %ld second%c",
  381.             realname, diff, c);
  382. #endif /* DAEMON_UID */    
  383.     return (null(char *));
  384. }
  385.  
  386. /*
  387.  * do_ctcp: handles the client to client protocol embedded in PRIVMSGs.  Any
  388.  * such messages are removed from the original str, so after do_ctcp()
  389.  * returns, str will be changed
  390.  */
  391. char    *do_ctcp(from, to, str)
  392. char    *from,
  393.     *to,
  394.     *str;
  395. {
  396.     int    i = 0,
  397.         ctcp_flag = 1;
  398.     char    *end,
  399.         *cmd,
  400.         *args,
  401.         *ptr;
  402.     char    *arg_copy = NULL;
  403.     int    flag;
  404.  
  405.     flag = double_ignore(from, FromUserHost, IGNORE_CTCPS);
  406.  
  407.     if (!in_ctcp_flag)
  408.         in_ctcp_flag = 1;
  409.     *ctcp_buffer = null(char);
  410.     ctcp_dropped = 0;
  411.     while (cmd = index(str, CTCP_DELIM_CHAR))
  412.     {
  413.         *(cmd++) = null(char);
  414.         strcat(ctcp_buffer, str);
  415.         if (end = index(cmd, CTCP_DELIM_CHAR))
  416.         {
  417.             if (!ctcp_dropped && (time(NULL) -
  418.                 ctcp_last_reply_time) < 2 && 
  419.                 get_int_var(NO_CTCP_FLOOD_VAR))
  420.             {
  421.                 if (get_int_var(VERBOSE_CTCP_VAR))
  422.                     say("CTCP flood from %s", from);
  423.                 ctcp_dropped = 1;
  424.             }
  425.             if (flag == IGNORED)
  426.                 continue;
  427.             *(end++) = null(char);
  428.             if (args = index(cmd, ' '))
  429.                 *(args++) = null(char);
  430.             else
  431.                 args = empty_string;
  432.             malloc_strcpy(&arg_copy, args);
  433.             if (!ctcp_dropped)
  434.                 for (i = 0; i < NUMBER_OF_CTCPS; i++)
  435.                 {
  436.                 if (strcmp(cmd, ctcp_cmd[i].name) == 0)
  437.                 {
  438.         /*
  439.          * This test here to stop irc operators seeing ctcp replies
  440.          * when using global messages - phone, dec, 1992.
  441.          */
  442.                     if (*to != '$' && !(*to == '#' &&
  443.                       !lookup_channel(to, from_server, 0)) &&
  444.                       (ptr = ctcp_cmd[i].func(&(ctcp_cmd[i]),
  445.                       from, to, arg_copy)))
  446.                     {
  447.                         strcat(ctcp_buffer, ptr);
  448.                         new_free(&ptr);
  449.                     }
  450.                     ctcp_flag = ctcp_cmd[i].flag;
  451.                     cmd = ctcp_cmd[i].name;
  452.                     break;
  453.                 }
  454.                 }
  455.             new_free(&arg_copy);
  456.             if (!ctcp_dropped && in_ctcp_flag == 1 &&
  457.                 do_hook(CTCP_LIST, "%s %s %s %s", from, to, cmd,
  458.                 args) && get_int_var(VERBOSE_CTCP_VAR))
  459.             {
  460.                 int    lastlog_level;
  461.  
  462.                 lastlog_level = set_lastlog_msg_level(LOG_CTCP);
  463.                 message_from(null(char *), LOG_CTCP);
  464.                 if (i == NUMBER_OF_CTCPS)
  465.                 {
  466.                     say("Unknown CTCP %s from %s%s%s",
  467.                         cmd, from, *args ? ": " :
  468.                         empty_string, args);
  469.                 }
  470.                 else if (ctcp_flag & CTCP_VERBOSE)
  471.                 {
  472.                     if (stricmp(to,
  473.                         get_server_nickname(from_server)))
  474.                         say("CTCP %s from %s to %s: %s",
  475.                             cmd, from, to, args);
  476.                     else
  477.                         say("CTCP %s from %s%s%s", cmd,
  478.                             from, *args ? ": " :
  479.                             empty_string, args);
  480.                 }
  481.                 set_lastlog_msg_level(lastlog_level);
  482.             }
  483.             str = end;
  484.         }
  485.         else
  486.         {
  487.             strcat(ctcp_buffer, CTCP_DELIM_STR);
  488.             str = cmd;
  489.         }
  490.     }
  491.     if (in_ctcp_flag == 1)
  492.         in_ctcp_flag = 0;
  493.     if (CTCP_Reply_Buffer && *CTCP_Reply_Buffer)
  494.         ctcp_last_reply_time = time(NULL);
  495.     strcat(ctcp_buffer, str);
  496.     send_to_server("%s", CTCP_Reply_Buffer);
  497.     *CTCP_Reply_Buffer = '\0';
  498.     return (ctcp_buffer);
  499. }
  500.  
  501. char    *do_notice_ctcp(from, to, str)
  502. char    *from,
  503.     *to,
  504.     *str;
  505. {
  506.     char    *cmd;
  507.  
  508.     in_ctcp_flag = -1;
  509.     *ctcp_buffer = null(char);
  510.     /*
  511.      * The following used to say "While". It now says "if" because people
  512.      * Started using CTCP ERRMSG replies to CTCP bomb. The effect of this
  513.      * is that IRCII users can only send one CTCP/message if they expect a
  514.      * reply. This shouldn't be a problem as that is the way IRCII operates
  515.      *
  516.      * Changed this behavouir to follow NO_CTCP_FLOOD
  517.      */
  518.  
  519.     if (get_int_var(NO_CTCP_FLOOD_VAR))
  520.     {
  521.         if (cmd = index(str, CTCP_DELIM_CHAR))
  522.             do_new_notice_ctcp(from, to, &str, cmd);
  523.     }
  524.     else
  525.         while (cmd = index(str, CTCP_DELIM_CHAR))
  526.             do_new_notice_ctcp(from, to, &str, cmd);
  527.     in_ctcp_flag = 0;
  528.     strcat(ctcp_buffer, str);
  529.     return (ctcp_buffer);
  530. }
  531.  
  532. static    void    do_new_notice_ctcp(from, to, str, cmd)
  533. char    *from,
  534.     *to,
  535.     **str,
  536.     *cmd;
  537. {
  538.     char    *end,
  539.         *args,
  540.         *ptr,
  541.         *arg_copy = NULL;
  542.     int    flags,
  543.         i,
  544.         lastlog_level;
  545.  
  546.     flags = 0;
  547.     *(cmd++) = null(char);
  548.     strcat(ctcp_buffer, *str);
  549.     if (end = index(cmd, CTCP_DELIM_CHAR))
  550.     {
  551.         *(end++) = null(char);
  552.         if (args = index(cmd, ' '))
  553.             *(args++) = null(char);
  554.         malloc_strcpy(&arg_copy, args);
  555.         for (i = 0; i < NUMBER_OF_CTCPS; i++)
  556.         {
  557.             if ((strcmp(cmd, ctcp_cmd[i].name) == 0) &&
  558.                     ctcp_cmd[i].flag & CTCP_NOREPLY)
  559.             {
  560.                 if (ptr =
  561.                     ctcp_cmd[i].func(&(ctcp_cmd[i]),
  562.                     from, to, arg_copy))
  563.                 {
  564.                     strcat(ctcp_buffer, ptr);
  565.                     new_free(&ptr);
  566.                     flags = ctcp_cmd[i].flag;
  567.                 }
  568.                 break;
  569.             }
  570.         }
  571.         new_free(&arg_copy);
  572.         if (!args)
  573.             args = empty_string;
  574.         if (do_hook(CTCP_REPLY_LIST, "%s %s %s", from, cmd,
  575.                 args) && !(flags & CTCP_NOREPLY))
  576.         {
  577.             if (!strcmp(cmd, "PING"))
  578.             {
  579.                 char    buf[20];
  580.                 Long    timediff,
  581.                     currenttime;
  582.  
  583.                 currenttime = time(NULL);
  584.                 if (args && *args)
  585.                     timediff = currenttime-(Long)atoi(args);
  586.                 else
  587.                     timediff = (Long) 0;
  588.                 sprintf(buf, "%d second%s", timediff,
  589.                     (timediff == 1) ? "" : "s");
  590.                 args = buf;
  591.             }
  592.             lastlog_level = set_lastlog_msg_level(LOG_CTCP);
  593.             message_from(null(char *), LOG_CTCP);
  594.             say("CTCP %s reply from %s: %s", cmd, from,
  595.                 args);
  596.             set_lastlog_msg_level(lastlog_level);
  597.         }
  598.         *str = end;
  599.     }
  600.     else
  601.     {
  602.         strcat(ctcp_buffer, CTCP_DELIM_STR);
  603.         *str = cmd;
  604.     }
  605. }
  606.  
  607. /* in_ctcp: simply returns the value of the ctcp flag */
  608. int    in_ctcp()
  609. {
  610.     return (in_ctcp_flag);
  611. }
  612.  
  613. /*
  614.  * do_atmosphere: does the CTCP ACTION command --- done by lynX
  615.  * Changed this to make the default look less offensive to people
  616.  * who don't like it and added a /on ACTION. This is more in keeping
  617.  * with the design philosophy behind IRCII
  618.  */
  619. static    char    *do_atmosphere(ctcp, from, to, cmd)
  620. CtcpEntry    *ctcp;
  621. char    *from,
  622.     *to,
  623.     *cmd;
  624. {
  625.     if (cmd && *cmd)
  626.     {
  627.         int old;
  628.  
  629.         old = set_lastlog_msg_level(LOG_ACTION);
  630.         if (is_channel(to))
  631.         {
  632.             message_from(to, LOG_ACTION);
  633.             if (do_hook(ACTION_LIST, "%s %s %s", from, to, cmd))
  634.             {
  635.                 if (is_current_channel(to, 0))
  636.                     put_it("* %s %s", from, cmd);
  637.                 else
  638.                     put_it("* %s:%s %s", from, to, cmd);
  639.             }
  640.         }
  641.         else
  642.         {
  643.             message_from(from, LOG_ACTION);
  644.             if (do_hook(ACTION_LIST, "%s %s %s", from, to, cmd))
  645.                 put_it("*> %s %s", from, cmd);
  646.         }
  647.         message_from(NULL, LOG_CRAP);
  648.         set_lastlog_msg_level(old);
  649.     }
  650.     return null(char *);
  651. }
  652.  
  653. /*
  654.  * do_dcc: Records data on an incoming DCC offer. Makes sure it's a
  655.  *    user->user CTCP, as channel DCCs don't make any sense whatsoever
  656.  */
  657. static    char    *do_dcc(ctcp, from, to, args)
  658. CtcpEntry    *ctcp;
  659. char    *from,
  660.     *to,
  661.     *args;
  662. {
  663.     char    *type;
  664.     char    *description;
  665.     char    *inetaddr;
  666.     char    *port;
  667.     char    *size;
  668.  
  669.     if (stricmp(to, get_server_nickname(from_server)))
  670.         return null(char *);
  671.     if (!(type = next_arg(args, &args)) ||
  672.             !(description = next_arg(args, &args)) ||
  673.             !(inetaddr = next_arg(args, &args)) ||
  674.             !(port = next_arg(args, &args)))
  675.         return NULL;
  676.     size = next_arg(args, &args);
  677.     register_dcc_offer(from, type, description, inetaddr, port, size);
  678.     return NULL;
  679. }
  680.  
  681. char    *do_utc(ctcp, from, to, args)
  682. CtcpEntry    *ctcp;
  683. char    *from,
  684.     *to,
  685.     *args;
  686. {
  687.     Long    tm;
  688.     char    *date = NULL;
  689.  
  690.     if (!args || !*args)
  691.         return NULL;
  692.     tm = atol(args);
  693.     malloc_strcpy(&date, ctime(&tm));
  694.     date[strlen(date)-1] = '\0';
  695.     return date;
  696. }
  697.  
  698. /* These moved here because they belong here - phone */
  699.  
  700. /*
  701.  * send_ctcp_notice: A simply way to send CTCP replies.   I put this here
  702.  * rather than in ctcp.c to keep my compiler quiet 
  703.  */
  704. void    send_ctcp(type, to, datatag, format, arg0, arg1, arg2, arg3, arg4,
  705.     arg5, arg6, arg7, arg8, arg9)
  706. char    *type,
  707.     *to,
  708.     *datatag,
  709.     *format;
  710. char    *arg0,
  711.     *arg1,
  712.     *arg2,
  713.     *arg3,
  714.     *arg4,
  715.     *arg5,
  716.     *arg6,
  717.     *arg7,
  718.     *arg8,
  719.     *arg9;
  720. {
  721.     char putbuf[BIG_BUFFER_SIZE + 1];
  722.  
  723.     if (in_on_who)
  724.         return;    /* Silently drop it on the floor */
  725.     if (format)
  726.     {
  727.         sprintf(putbuf, format, arg0, arg1, arg2, arg3, arg4, arg5,
  728.             arg6, arg7, arg8, arg9);
  729.         send_to_server("%s %s :%c%s %s%c", type, to, CTCP_DELIM_CHAR,
  730.             datatag, putbuf, CTCP_DELIM_CHAR);
  731.     }
  732.     else
  733.         send_to_server("%s %s :%c%s%c", type, to, CTCP_DELIM_CHAR,
  734.             datatag, CTCP_DELIM_CHAR);
  735. }
  736.  
  737.  
  738. /*
  739.  * send_ctcp_notice: A simply way to send CTCP replies.   I put this here
  740.  * rather than in ctcp.c to keep my compiler quiet 
  741.  */
  742. void    send_ctcp_reply(to, datatag, format, arg0, arg1, arg2, arg3, arg4,
  743.         arg5, arg6, arg7, arg8, arg9)
  744. char    *to,
  745.     *datatag,
  746.     *format;
  747. char    *arg0,
  748.     *arg1,
  749.     *arg2,
  750.     *arg3,
  751.     *arg4,
  752.     *arg5,
  753.     *arg6,
  754.     *arg7,
  755.     *arg8,
  756.     *arg9;
  757. {
  758.     char    putbuf[BIG_BUFFER_SIZE + 1];
  759.  
  760.     if (in_on_who)
  761.         return;    /* Silently drop it on the floor */
  762.     if (!*CTCP_Reply_Buffer)
  763.         sprintf(CTCP_Reply_Buffer, "NOTICE %s :", to);
  764.     strmcat(CTCP_Reply_Buffer, "\001", BIG_BUFFER_SIZE);
  765.     strmcat(CTCP_Reply_Buffer, datatag, BIG_BUFFER_SIZE);
  766.     strmcat(CTCP_Reply_Buffer, " ", BIG_BUFFER_SIZE);
  767.     if (format)
  768.     {
  769.         sprintf(putbuf, format, arg0, arg1, arg2, arg3, arg4, arg5,
  770.             arg6, arg7, arg8, arg9);
  771.         strmcat(CTCP_Reply_Buffer, putbuf, BIG_BUFFER_SIZE);
  772.     }
  773.     else
  774.         strmcat(CTCP_Reply_Buffer, putbuf, BIG_BUFFER_SIZE);
  775.     strmcat(CTCP_Reply_Buffer, "\001", BIG_BUFFER_SIZE);
  776. }
  777.