process.c

Go to the documentation of this file.
00001 /* Main processing code for Services.
00002  *
00003  * (C) 2003-2013 Anope Team
00004  * Contact us at team@anope.org
00005  *
00006  * Please read COPYING and README for further details.
00007  *
00008  * Based on the original code of Epona by Lara.
00009  * Based on the original code of Services by Andy Church.
00010  *
00011  *
00012  */
00013 
00014 #include "services.h"
00015 #include "messages.h"
00016 #include "modules.h"
00017 
00018 /*************************************************************************/
00019 
00020 /* Use ignore code? */
00021 int allow_ignore = 1;
00022 
00023 /* Masks to ignore. */
00024 IgnoreData *ignore;
00025 
00026 /*************************************************************************/
00027 
00033 void add_ignore(const char *nick, time_t delta)
00034 {
00035     IgnoreData *ign;
00036     char tmp[BUFSIZE];
00037     char *mask, *user, *host;
00038     User *u;
00039     time_t now;
00040 
00041     if (!nick)
00042         return;
00043     now = time(NULL);
00044 
00045     /* If it s an existing user, we ignore the hostmask. */ 
00046     if ((u = finduser(nick))) {
00047         snprintf(tmp, sizeof(tmp), "*!*@%s", u->host);
00048         mask = sstrdup(tmp);
00049 
00050     /* Determine whether we get a nick or a mask. */ 
00051     } else if ((host = strchr(nick, '@'))) {
00052         /* Check whether we have a nick too.. */ 
00053         if ((user = strchr(nick, '!'))) {
00054             /* this should never happen */ 
00055             if (user > host)
00056                 return;
00057             mask = sstrdup(nick);
00058         } else {
00059             /* We have user@host. Add nick wildcard. */
00060             snprintf(tmp, sizeof(tmp), "*!%s", nick);
00061             mask = sstrdup(tmp);
00062         }
00063     /* We only got a nick.. */
00064     } else {
00065         snprintf(tmp, sizeof(tmp), "%s!*@*", nick);
00066         mask = sstrdup(tmp);
00067     }
00068 
00069     /* Check if we already got an identical entry. */
00070     for (ign = ignore; ign; ign = ign->next)
00071         if (stricmp(ign->mask, mask) == 0)
00072             break;
00073 
00074     /* Found one.. */
00075     if (ign) {
00076         if (delta == 0)
00077             ign->time = 0;
00078         else if (ign->time < now + delta)
00079             ign->time = now + delta;
00080 
00081     /* Create new entry.. */ 
00082     } else {
00083         ign = scalloc(sizeof(*ign), 1);
00084         ign->mask = mask;
00085         ign->time = (delta == 0 ? 0 : now + delta);
00086         ign->prev = NULL;
00087         ign->next = ignore;
00088         if (ignore)
00089             ignore->prev = ign;
00090         ignore = ign;
00091         if (debug)
00092             alog("debug: Added new ignore entry for %s", mask);
00093     }
00094 }
00095 
00096 /*************************************************************************/
00097 
00105 IgnoreData *get_ignore(const char *nick)
00106 {
00107     IgnoreData *ign;
00108     char tmp[BUFSIZE];
00109     char *user, *host;
00110     time_t now;
00111     User *u;
00112 
00113     if (!nick)
00114         return NULL;
00115 
00116     /* User has disabled the IGNORE system */
00117     if (!allow_ignore)
00118         return NULL;
00119 
00120     now = time(NULL);
00121     u = finduser(nick);
00122 
00123     /* If we find a real user, match his mask against the ignorelist. */
00124     if (u) {
00125         /* Opers are not ignored, even if a matching entry may be present. */ 
00126         if (is_oper(u))
00127             return NULL;
00128         for (ign = ignore; ign; ign = ign->next)
00129             if (match_usermask_full(ign->mask, u, true))
00130                 break;
00131     } else {
00132         /* We didn't get a user.. generate a valid mask. */ 
00133         if ((host = strchr(nick, '@'))) {
00134             if ((user = strchr(nick, '!'))) {
00135                 /* this should never happen */
00136                 if (user > host)
00137                     return NULL;
00138                 snprintf(tmp, sizeof(tmp), "%s", nick);
00139             } else {
00140                 /* We have user@host. Add nick wildcard. */ 
00141                 snprintf(tmp, sizeof(tmp), "*!%s", nick);
00142             }
00143 
00144         /* We only got a nick.. */ 
00145         } else
00146             snprintf(tmp, sizeof(tmp), "%s!*@*", nick);
00147         for (ign = ignore; ign; ign = ign->next)
00148             if (match_wild_nocase(ign->mask, tmp))
00149                 break;
00150     }
00151 
00152     /* Check whether the entry has timed out */ 
00153     if (ign && ign->time != 0 && ign->time <= now) {
00154         if (debug)
00155             alog("debug: Expiring ignore entry %s", ign->mask);
00156         if (ign->prev)
00157             ign->prev->next = ign->next;
00158         else if (ignore == ign)
00159             ignore = ign->next;
00160         if (ign->next)
00161             ign->next->prev = ign->prev;
00162         free(ign->mask);
00163         free(ign);
00164         ign = NULL;
00165     }
00166     if (ign && debug)
00167         alog("debug: Found ignore entry (%s) for %s", ign->mask, nick);
00168     return ign;
00169 }
00170 
00171 /*************************************************************************/ 
00172 
00178 int delete_ignore(const char *nick) 
00179 {
00180     IgnoreData *ign;
00181     char tmp[BUFSIZE];
00182     char *user, *host;
00183     User *u;
00184 
00185     if (!nick)
00186         return 0;
00187 
00188     /* If it s an existing user, we ignore the hostmask. */ 
00189     if ((u = finduser(nick))) {
00190         snprintf(tmp, sizeof(tmp), "*!*@%s", u->host);
00191 
00192     /* Determine whether we get a nick or a mask. */ 
00193     } else if ((host = strchr(nick, '@'))) {
00194         /* Check whether we have a nick too.. */ 
00195         if ((user = strchr(nick, '!'))) {
00196             /* this should never happen */ 
00197             if (user > host)
00198                 return 0;
00199             snprintf(tmp, sizeof(tmp), "%s", nick);
00200         } else {
00201             /* We have user@host. Add nick wildcard. */ 
00202             snprintf(tmp, sizeof(tmp), "*!%s", nick);
00203         }
00204 
00205     /* We only got a nick.. */
00206     } else
00207        snprintf(tmp, sizeof(tmp), "%s!*@*", nick);
00208 
00209     for (ign = ignore; ign; ign = ign->next)
00210         if (stricmp(ign->mask, tmp) == 0)
00211             break;
00212 
00213     /* No matching ignore found. */
00214     if (!ign)
00215         return 0;
00216 
00217     if (debug)
00218         alog("Deleting ignore entry %s", ign->mask);
00219 
00220     /* Delete the entry and all references to it. */ 
00221     if (ign->prev)
00222         ign->prev->next = ign->next;
00223     else if (ignore == ign)
00224         ignore = ign->next;
00225     if (ign->next)
00226         ign->next->prev = ign->prev;
00227     free(ign->mask);
00228     free(ign);
00229     ign = NULL;
00230 
00231     return 1;
00232 }
00233 
00234 /*************************************************************************/ 
00235 
00240 int clear_ignores() 
00241 {
00242     IgnoreData *ign, *next;
00243     int i = 0;
00244 
00245     if (!ignore)
00246         return 0;
00247 
00248     for (ign = ignore; ign; ign = next) {
00249         next = ign->next;
00250         if (debug)
00251             alog("Deleting ignore entry %s", ign->mask);
00252         free(ign->mask);
00253         free(ign);
00254         i++;
00255     }
00256     ignore = NULL;
00257     return i;
00258 }
00259 
00260 /*************************************************************************/
00261 
00262 /* split_buf:  Split a buffer into arguments and store the arguments in an
00263  *             argument vector pointed to by argv (which will be malloc'd
00264  *             as necessary); return the argument count.  If colon_special
00265  *             is non-zero, then treat a parameter with a leading ':' as
00266  *             the last parameter of the line, per the IRC RFC.  Destroys
00267  *             the buffer by side effect.
00268  */
00269 int split_buf(char *buf, char ***argv, int colon_special)
00270 {
00271     int argvsize = 8;
00272     int argc;
00273     char *s;
00274 
00275     *argv = scalloc(sizeof(char *) * argvsize, 1);
00276     argc = 0;
00277     while (*buf) {
00278         if (argc == argvsize) {
00279             argvsize += 8;
00280             *argv = srealloc(*argv, sizeof(char *) * argvsize);
00281         }
00282         if (*buf == ':') {
00283             (*argv)[argc++] = buf + 1;
00284             buf = "";
00285         } else {
00286             s = strpbrk(buf, " ");
00287             if (s) {
00288                 *s++ = 0;
00289                 while (*s == ' ')
00290                     s++;
00291             } else {
00292                 s = buf + strlen(buf);
00293             }
00294             (*argv)[argc++] = buf;
00295             buf = s;
00296         }
00297     }
00298     return argc;
00299 }
00300 
00301 /*************************************************************************/
00302 
00303 /* process:  Main processing routine.  Takes the string in inbuf (global
00304  *           variable) and does something appropriate with it. */
00305 
00306 void process()
00307 {
00308     int retVal = 0;
00309     Message *current = NULL;
00310     char source[64];
00311     char cmd[64];
00312     char buf[4096];             /* Most need only 512, InspIRCd 2.0 is seriously oversized though.. */
00313     char *s;
00314     int ac;                     /* Parameters for the command */
00315     char **av;
00316     Message *m;
00317 
00318     /* zero out the buffers before we do much else */
00319     *buf = '\0';
00320     *source = '\0';
00321     *cmd = '\0';
00322 
00323     /* If debugging, log the buffer */
00324     if (debug) {
00325         alog("debug: Received: %s", inbuf);
00326     }
00327 
00328     /* First make a copy of the buffer so we have the original in case we
00329      * crash - in that case, we want to know what we crashed on. */
00330     strscpy(buf, inbuf, sizeof(buf));
00331 
00332     doCleanBuffer((char *) buf);
00333 
00334     /* Split the buffer into pieces. */
00335     if (*buf == ':') {
00336         s = strpbrk(buf, " ");
00337         if (!s)
00338             return;
00339         *s = 0;
00340         while (isspace(*++s));
00341         strscpy(source, buf + 1, sizeof(source));
00342         memmove(buf, s, strlen(s) + 1);
00343     } else {
00344         *source = 0;
00345     }
00346     if (!*buf)
00347         return;
00348     s = strpbrk(buf, " ");
00349     if (s) {
00350         *s = 0;
00351         while (isspace(*++s));
00352     } else
00353         s = buf + strlen(buf);
00354     strscpy(cmd, buf, sizeof(cmd));
00355     ac = split_buf(s, &av, 1);
00356     if (protocoldebug) {
00357         protocol_debug(source, cmd, ac, av);
00358     }
00359     if (mod_current_buffer) {
00360         free(mod_current_buffer);
00361     }
00362     /* fix to moduleGetLastBuffer() bug 296 */
00363     /* old logic was that since its meant for PRIVMSG that we would get
00364        the NICK as AV[0] and the rest would be in av[1], however on Bahamut
00365        based systems when you do /cs it assumes we will translate the command
00366        to the NICK and thus AV[0] is the message. The new logic is to check
00367        av[0] to see if its a service nick if so assign mod_current_buffer the
00368        value from AV[1] else just assign av[0] - TSL */
00369     /* First check if the ircd proto module overrides this -GD */
00370     /* fix to moduleGetLastBuffer() bug 476:
00371      fixed in part by adding {} to nickIsServices()
00372      however if you have a pseudo they could not use moduleGetLastBuffer()
00373      cause they are not part of nickIsServices, even those the ac count is 2
00374      that was ignored and only the first param was passed on which is fine for
00375      Bahmut ircd aliases but not for pseudo clients on. So additional logic is
00376      that if the ac is greater then 1 copy av[1] else copy av[0] 
00377      I also changed from if statments, cause attempting to access a array member
00378      that is not set can lead to odd things - TSL (3/12/06) */
00379     if (!anope_set_mod_current_buffer(ac, av)) {
00380         if (ac >= 1) {
00381             if (nickIsServices(av[0], 1)) {
00382                 mod_current_buffer =
00383                     (ac > 1 ? sstrdup(av[1]) : sstrdup(av[0]));
00384             } else {
00385                 mod_current_buffer =
00386                     (ac > 1 ? sstrdup(av[1]) : sstrdup(av[0]));
00387             }
00388         } else {
00389             mod_current_buffer = NULL;
00390         }
00391     }
00392     /* Do something with the message. */
00393     m = find_message(cmd);
00394     if (m) {
00395         if (m->func) {
00396             mod_current_module_name = m->mod_name;
00397             mod_current_module = findModule(m->mod_name);
00398             retVal = m->func(source, ac, av);
00399             mod_current_module_name = NULL;
00400             mod_current_module = NULL;
00401             if (retVal == MOD_CONT) {
00402                 current = m->next;
00403                 while (current && current->func && retVal == MOD_CONT) {
00404                     mod_current_module_name = current->mod_name;
00405                     mod_current_module = findModule(current->mod_name);
00406                     retVal = current->func(source, ac, av);
00407                     mod_current_module_name = NULL;
00408                     mod_current_module = NULL;
00409                     current = current->next;
00410                 }
00411             }
00412         }
00413     } else {
00414         if (debug)
00415             alog("debug: unknown message from server (%s)", inbuf);
00416     }
00417 
00418     /* Load/unload modules if needed */
00419     handleModuleOperationQueue();
00420 
00421     /* Free argument list we created */
00422     free(av);
00423 }
00424 
00425 /*************************************************************************/