Main Page | Modules | Namespace List | Class Hierarchy | Class List | File List | Class Members | File Members | Related Pages

infoserv.c

Go to the documentation of this file.
00001 
00011 /*
00012  * Portions Copyright (c) 2000, 2001 James Hess
00013  * Copyright (c) 1997 Dafydd James & Greg Poma.
00014  * All rights reserved.
00015  *
00016  * Redistribution and use in source and binary forms, with or without
00017  * modification, are permitted provided that the following conditions
00018  * are met:
00019  * 1. Redistributions of source code must retain the above copyright
00020  *    notice, this list of conditions and the following disclaimer.
00021  * 2. Redistributions in binary form must reproduce the above copyright
00022  *    notice, this list of conditions and the following disclaimer in the
00023  *    documentation and/or other materials provided with the distribution.
00024  * 3. Neither the name of the authors nor the names of its contributors
00025  *    may be used to endorse or promote products derived from this software
00026  *    without specific prior written permission.
00027  *
00028  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
00029  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00030  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00031  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
00032  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00033  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00034  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00035  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00036  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00037  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00038  * SUCH DAMAGE.
00039  */
00040 
00041 #include "services.h"
00042 #include "infoserv.h"
00043 #include "nickserv.h"
00044 #include "log.h"
00045 #include "db.h"
00046 
00047 // *INDENT-OFF*
00048 
00049 /* infoserv.c
00050  *
00051  * Concept by someone I forgot who, I think Mysidia...
00052  * designed to send important news/messages to users
00053  * -DuffJ
00054  *
00055  * Yeah, that's right.
00056  * -Mysid
00057  */
00058 
00062 time_t is_last_post_time = 0;
00063 
00067 interp::service_cmd_t infoserv_commands[] = {
00068 /*  command function    oper        log         addflood */
00069   { "help", is_help,        0,      LOG_NO, 0,  5   },
00070   { "read", is_sendinfo,    0,      LOG_NO, 0,  5   },
00071   { "list", is_listnews,    0,      LOG_NO, 0,  9   },
00072   { "post", is_postnews,    OOPER,  LOG_NO, 0,  3   },
00073   { "del",  is_delete,      OOPER,  LOG_NO, 0,  3   },
00074   { "save", is_save,        OOPER,  LOG_NO, 0,  3   },
00075   { NULL,   NULL,           0,      LOG_NO, 0,  0   }
00076 };
00077 
00081 SomeNews *is_listhead = NULL;
00082 
00084 const char *priority_names[] =
00085 {
00086     "IRCops Only",
00087     "Informational",
00088     "General announcement",
00089     "Important information",
00090     "URGENT Notice",
00091     "Critical message",
00092     "Unknown",
00093 };
00094 
00095 char* str_dup(const char *);
00096 
00097 // *INDENT-ON*
00098 /*------------------------------------------------------------------------*/
00099 
00103 void
00104 freeNews(SomeNews *theNews)
00105 {
00106     FREE(theNews->content);
00107     FREE(theNews->header);
00108     FREE(theNews);
00109 }
00110 
00115 void
00116 newsNag(UserList * nick)
00117 {
00118     SomeNews *news;
00119     int count = 0, ict = 0, tupdate = 0;
00120     if (!nick || !nick->reg || nick->reg->is_readtime >= is_last_post_time
00121         || nick->caccess < 2)
00122         return;
00123     for (news = is_listhead; news; news = news->next) {
00124         ++ict;
00125 
00126 
00127         switch(news->importance)
00128         {
00129             case 0:
00130                 if ((isOper(nick) 
00131                     || (nick->reg 
00132                         && (nick->reg->opflags & OOPER)
00133                        ))) 
00134                     ++count;
00135                 break;
00136             case 4:
00137                 sSend(":%s NOTICE %s :(%d) \"%s\": %s",
00138                       InfoServ, nick->nick, ict,
00139                       news->header, news->content);
00140                 tupdate = 1;
00141                 break;
00142 
00143             case 5:
00144                 sSend(":%s PRIVMSG %s :(%d) \"%s\": %s",
00145                       InfoServ, nick->nick, ict,
00146                       news->header, news->content);
00147                 tupdate = 1;
00148                 break;
00149             default:;
00150                 tupdate = 0;
00151                 if (news->timestamp < nick->reg->is_readtime
00152                     && news->importance >= 3)
00153                     ++count;
00154                 break;
00155         }
00156     }
00157     if (!count)
00158         return;
00159     if (tupdate && nick->reg)
00160         nick->reg->is_readtime = CTime;
00161 
00162     if (count == 1)
00163         PutReply(InfoServ, nick, RPL_IS_NEWITEM, 0, 0, 0);
00164     else
00165         PutReply(InfoServ, nick, RPL_IS_NEWITEMS_1ARG, count, 0, 0);
00166 
00167     PutReply(InfoServ, nick, RPL_IS_HOWTOLIST, 0, 0, 0);
00168 }
00169 
00170 
00182 void
00183 sendToInfoServ(UserList * nick, char **args, int numargs)
00184 {
00185     char *from = nick->nick;
00186     interp::parser * cmd;
00187 
00188     cmd =
00189         new interp::parser(InfoServ, getOpFlags(nick), infoserv_commands,
00190                            args[0]);
00191     if (!cmd)
00192         return;
00193 
00194     switch (cmd->run(nick, args, numargs)) {
00195     default:
00196         break;
00197     case RET_FAIL:
00198         PutReply(InfoServ, nick, ERR_IS_UNKNOWNCMD_1ARG, args[0], 0, 0);
00199         PutHelpInfo(InfoServ, nick, "HELP");
00200         break;
00201     }
00202 
00203     delete cmd;
00204 }
00205 
00206 /*------------------------------------------------------------------------*/
00207 
00211 ICMD(is_help)
00212 {
00213     help(nick->nick, InfoServ, args, numargs);
00214     return RET_OK;
00215 }
00216 
00220 ICMD(is_save)
00221 {
00222     char *from = nick->nick;
00223 
00224     if (isRoot(nick) == 0) {
00225         PutReply(NickServ, nick, ERR_NOACCESS, 0, 0, 0);
00226         return RET_NOPERM;
00227     }
00228 #ifdef GLOBOP_ON_SAVE
00229     sSend(":%s GLOBOPS :Saving database. (%s)", NickServ, from);
00230 #else
00231     sSend(":%s PRIVMSG " LOGCHAN " :Saving database. (%s)", NickServ,
00232           from);
00233 #endif
00234     saveInfoData();
00235     return RET_OK;
00236 }
00237 
00238 
00242 ICMD(is_sendinfo)
00243 {
00244     char *from = nick->nick, *p, *str;
00245     SomeNews *sn;
00246     int i, which;
00247     parse_t lineSplit;
00248 
00249     sn = is_listhead;
00250 
00251     if (numargs < 2) {
00252         PutReply(InfoServ, nick, ERR_IS_NEEDPARAM, 0, 0, 0);
00253         PutHelpInfo(InfoServ, nick, "HELP READ");
00254     }
00255 
00256     if (isdigit(*args[1]) == 0) {
00257         PutReply(InfoServ, nick, ERR_IS_NEEDNUM, 0, 0, 0);
00258         return RET_SYNTAX;
00259     }
00260 
00261     which = atoi(args[1]);
00262 
00263     for (i = 1; sn != 0; sn = sn->next, i++)
00264         if (i == which &&
00265             (isOper(nick) ||
00266              (nick->reg && (nick->reg->opflags & OOPER)) ||
00267               sn->importance != 0)) 
00268         {
00269             str = str_dup(sn->content);
00270             if ( parse_init(&lineSplit, str) != 0 )
00271                 continue;
00272 
00273             sSend(":%s NOTICE %s :#%d (%s) :: %s", InfoServ, from, i, sn->from, ctime(&sn->timestamp));
00274             sSend(":%s NOTICE %s :Subject: %s", InfoServ, from, sn->header);
00275             sSend(":%s NOTICE %s :Priority: %s", InfoServ, from, priority_names[sn->importance]);
00276             sSend(":%s NOTICE %s :+++", InfoServ, from);
00277             lineSplit.delim = '\n';
00278             while((p = parse_getarg(&lineSplit)))
00279                 sSend(":%s NOTICE %s :%s", InfoServ, from, (p && *p) ? p : " ");
00280             parse_cleanup(&lineSplit);
00281             FREE(str);
00282 
00283             return RET_OK;
00284         }
00285     PutReply(InfoServ, nick, ERR_IS_NOARTICLE_ARG1, atoi(args[1]), 0, 0);
00286     return RET_NOTARGET;
00287 }
00288 
00292 /* ARGSUSED1 */
00293 ICMD(is_listnews)
00294 {
00295 
00296     SomeNews *blah;
00297     int i = 1;
00298     struct tm *time;
00299     char timestr[80];
00300 
00301     blah = is_listhead;
00302 
00303     if (nick->reg)
00304         nick->reg->is_readtime = CTime;
00305 
00306     if (blah == NULL) {
00307         PutReply(InfoServ, nick, ERR_IS_NOARTICLES, 0, 0, 0);
00308         return RET_OK;
00309     }
00310 
00311     sSend(":%s NOTICE %s :List of articles", InfoServ, nick->nick);
00312     sSend
00313         (":%s NOTICE %s :Number  Header              Sender              Time posted",
00314          InfoServ, nick->nick);
00315 
00316     for (; blah != 0; blah = blah->next, i++) {
00317         if (blah->importance == 0 && !isOper(nick)
00318             && (!nick->reg || nick->caccess < 2
00319                 || !(nick->reg->opflags & OOPER))) continue;
00320 
00321         time = localtime(&blah->timestamp);
00322         strftime(timestr, 80, "%a %D %T %Z", time);
00323 
00324         sSend(":%s NOTICE %s :%-2d %-20s : %-20s :: %s", InfoServ,
00325               nick->nick, i, blah->from, timestr, blah->header);
00326     }
00327 
00328     PutReply(InfoServ, nick, RPL_IS_END_OF_LIST, 0, 0, 0);
00329     PutReply(InfoServ, nick, RPL_IS_READ_HELP, 0, 0, 0);
00330     return RET_OK;
00331 }
00332 
00333 
00341 ICMD(is_postnews)
00342 {
00343     SomeNews *newnews = 0;
00344     SomeNews *working = 0;
00345     char *from = nick->nick;
00346     char content[IRCBUF + 200];
00347     int i = 0;
00348 
00349     if (numargs < 4) {
00350         PutReply(InfoServ, nick, ERR_IS_NEEDPARAM, 0, 0, 0);
00351         PutHelpInfo(InfoServ, nick, "HELP POST");
00352         return RET_SYNTAX;
00353     }
00354 
00355     if (!isdigit(*args[1])) {
00356         PutReply(InfoServ, nick, ERR_IS_NEEDIMPORTANCE, 0, 0, 0);
00357         for(i = 0; i <= 5; i++)
00358             sSend(":%s NOTICE %s :%-2d  - %s",
00359              InfoServ, from, i, priority_names[i]);
00360         return RET_SYNTAX;
00361     }
00362 
00363     /* Compile the content into a string, and a length string */
00364     content[0] = 0;             /* Make sure that strcat() starts at the beginning */
00365     parse_str(args, numargs, 3, content, IRCBUF);
00366 
00367     /* refuse to post if an item will be truncated. - Liam
00368      */
00369     if (strlen(content) >= NEWSCONTENTLEN) {
00370         PutReply(InfoServ, nick, ERR_IS_TOOLONG, 0, 0, 0);
00371         sSend(":%s NOTICE %s :>>%s", InfoServ, from, &content[NEWSCONTENTLEN]);
00372         return RET_SYNTAX;
00373     }
00374 
00375     /* if is_listhead is null, allocate mem for it
00376      * and make that the new entry
00377      */
00378     if (is_listhead == 0)
00379         newnews = is_listhead = (SomeNews *) oalloc(sizeof(SomeNews));
00380     else {                      /* find the end */
00381         working = is_listhead;
00382 
00383         while (working->next != 0)
00384             working = working->next;
00385 
00386         newnews = working->next = (SomeNews *) oalloc(sizeof(SomeNews));
00387     }
00388 
00389 
00390     /* OK, let's fill up the news item structure
00391      * with all relevant data
00392      */
00393     strncpyzt(newnews->from, from, NICKLEN);    /* Sanity */
00394     newnews->importance = atoi(args[1]);
00395     if (newnews->importance > 0 && !opFlagged(nick, OINFOPOST))
00396         newnews->importance = 0;
00397     if (newnews->importance > 3 && !opFlagged(nick, OSERVOP))
00398         newnews->importance = 3;
00399     if (newnews->importance > 4 && !opFlagged(nick, OROOT))
00400         newnews->importance = 4;
00401     if (newnews->importance > 5)
00402         newnews->importance = 5;
00403 
00404     newnews->header = strdup(args[2]);
00405     newnews->timestamp = CTime;
00406     newnews->content = strdup(content);
00407     if (!newnews->content)
00408         abort();
00409     is_last_post_time = CTime;
00410 
00411     PutReply(InfoServ, nick, RPL_IS_POSTED, 0, 0, 0);
00412 
00413     sSend(":%s GLOBOPS :New article posted to database by %s, header: %s",
00414           InfoServ, newnews->from, newnews->header);
00415     if (newnews->importance <= 2);
00416     else if (newnews->importance <= 3)
00417         sSend
00418             (":%s NOTICE $*.sorcery.net :A new article flagged important has been posted to my database, type \2/msg infoserv list\2 to view InfoServ articles.",
00419              InfoServ);
00420     else if (newnews->importance <= 4)
00421         sSend
00422             (":%s NOTICE $*.sorcery.net :[\2Global Notice\2] (%s) %s [\2Please do not respond\2]",
00423              InfoServ, newnews->header, newnews->content);
00424     else
00425         sSend
00426             (":%s PRIVMSG $*.sorcery.net :[\2Global Notice\2] (%s) %s [\2Please do not respond\2]",
00427              InfoServ, newnews->header, newnews->content);
00428     return RET_OK_DB;
00429 }
00430 
00434 ICMD(is_delete)
00435 {
00436 
00437     SomeNews *news, *news2, *news3 = 0;
00438     int i = 1;
00439 
00440     if (numargs < 2) {
00441         PutReply(InfoServ, nick, ERR_IS_NEEDPARAM, 0, 0, 0);
00442         PutHelpInfo(InfoServ, nick, "HELP DELETE");
00443         return RET_SYNTAX;
00444     }
00445 
00446     if (isdigit(*args[1]) == 0) {
00447         PutReply(InfoServ, nick, ERR_IS_NEEDNUM, 0, 0, 0);
00448         return RET_SYNTAX;
00449     }
00450 
00451     for (news = is_listhead; news; news = news->next, i++)
00452         if (i == atoi(args[1])) {
00453             news2 = news->next;
00454             if (news3 == 0)
00455                 is_listhead = news->next;
00456             else
00457                 news3->next = news2;
00458             freeNews(news);
00459             news = news2;
00460             PutReply(InfoServ, nick, RPL_IS_DELETED_1ARG, i, 0, 0);
00461             return RET_OK_DB;
00462         } else
00463             news3 = news;
00464 
00465     PutReply(InfoServ, nick, ERR_IS_NOARTICLE_ARG1, i, 0, 0);
00466     return RET_NOTARGET;
00467 }
00468 
00469 /*------------------------------------------------------------------------*/
00470 
00471 /* $Id: infoserv.c,v 1.1.1.1 2003/07/04 02:54:05 Mysid Exp $ */

Generated at Sat Oct 25 20:56:08 2003 for Services using Doxygen.
Services Copyr. 1996-2001 Chip Norkus, Max Byrd, Greg Poma, Michael Graff, James Hess, Dafydd James. All rights reserved See LICENSE for licensing information.