00001
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include "services.h"
00042 #include "infoserv.h"
00043 #include "nickserv.h"
00044 #include "log.h"
00045 #include "db.h"
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00062 time_t is_last_post_time = 0;
00063
00067 interp::service_cmd_t infoserv_commands[] = {
00068
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
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
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
00364 content[0] = 0;
00365 parse_str(args, numargs, 3, content, IRCBUF);
00366
00367
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
00376
00377
00378 if (is_listhead == 0)
00379 newnews = is_listhead = (SomeNews *) oalloc(sizeof(SomeNews));
00380 else {
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
00391
00392
00393 strncpyzt(newnews->from, from, NICKLEN);
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