mirror of
https://github.com/anope/anope.git
synced 2026-06-12 19:14:47 +02:00
811ce26663
git-svn-id: svn://svn.anope.org/anope/trunk@4 31f1291d-b8d6-0310-a050-a5561fc1590b git-svn-id: http://anope.svn.sourceforge.net/svnroot/anope/trunk@2 5417fbe8-f217-4b02-8779-1006273d7864
1176 lines
40 KiB
C
1176 lines
40 KiB
C
/* MemoServ functions.
|
|
*
|
|
* (C) 2003 Anope Team
|
|
* Contact us at info@anope.org
|
|
*
|
|
* Please read COPYING and README for furhter details.
|
|
*
|
|
* Based on the original code of Epona by Lara.
|
|
* Based on the original code of Services by Andy Church.
|
|
*
|
|
* $Id$
|
|
*
|
|
*/
|
|
|
|
#include "services.h"
|
|
#include "pseudo.h"
|
|
|
|
/*************************************************************************/
|
|
/* *INDENT-OFF* */
|
|
|
|
NickCore *nclists[1024];
|
|
static int delmemo(MemoInfo *mi, int num);
|
|
static int do_help(User *u);
|
|
static int do_send(User *u);
|
|
void memo_send(User *u, char *name, char *text, int z);
|
|
static int do_cancel(User *u);
|
|
static int do_list(User *u);
|
|
static int do_read(User *u);
|
|
static int do_del(User *u);
|
|
static int do_set(User *u);
|
|
static int do_set_notify(User *u, MemoInfo *mi, char *param);
|
|
static int do_set_limit(User *u, MemoInfo *mi, char *param);
|
|
static int do_info(User *u);
|
|
static int do_staff(User *u);
|
|
static int do_sendall(User *u);
|
|
void moduleAddMemoServCmds(void);
|
|
/*************************************************************************/
|
|
|
|
void moduleAddMemoServCmds(void) {
|
|
Command *c;
|
|
c = createCommand("HELP", do_help, NULL, -1, -1,-1,-1,-1); addCoreCommand(MEMOSERV,c);
|
|
c = createCommand("SEND", do_send, NULL, MEMO_HELP_SEND, -1,-1,-1,-1); addCoreCommand(MEMOSERV,c);
|
|
c = createCommand("CANCEL", do_cancel, NULL, MEMO_HELP_CANCEL, -1,-1,-1,-1); addCoreCommand(MEMOSERV,c);
|
|
c = createCommand("LIST", do_list, NULL, MEMO_HELP_LIST, -1,-1,-1,-1); addCoreCommand(MEMOSERV,c);
|
|
c = createCommand("READ", do_read, NULL, MEMO_HELP_READ, -1,-1,-1,-1); addCoreCommand(MEMOSERV,c);
|
|
c = createCommand("DEL", do_del, NULL, MEMO_HELP_DEL, -1,-1,-1,-1); addCoreCommand(MEMOSERV,c);
|
|
c = createCommand("STAFF", do_staff, is_services_oper, MEMO_HELP_STAFF, -1,-1,-1,-1); addCoreCommand(MEMOSERV,c);
|
|
c = createCommand("SET", do_set, NULL, MEMO_HELP_SET, -1,-1,-1,-1); addCoreCommand(MEMOSERV,c);
|
|
c = createCommand("SET NOTIFY", NULL, NULL, MEMO_HELP_SET_NOTIFY, -1,-1,-1,-1); addCoreCommand(MEMOSERV,c);
|
|
c = createCommand("SET LIMIT", NULL, NULL, -1,MEMO_HELP_SET_LIMIT, MEMO_SERVADMIN_HELP_SET_LIMIT,MEMO_SERVADMIN_HELP_SET_LIMIT, MEMO_SERVADMIN_HELP_SET_LIMIT); addCoreCommand(MEMOSERV,c);
|
|
c = createCommand("INFO", do_info, NULL, -1,MEMO_HELP_INFO, MEMO_SERVADMIN_HELP_INFO,MEMO_SERVADMIN_HELP_INFO, MEMO_SERVADMIN_HELP_INFO); addCoreCommand(MEMOSERV,c);
|
|
c = createCommand("SENDALL", do_sendall, is_services_admin, MEMO_HELP_SENDALL, -1,-1,-1,-1); addCoreCommand(MEMOSERV,c);
|
|
}
|
|
|
|
/*************************************************************************/
|
|
/*************************************************************************/
|
|
/* *INDENT-ON* */
|
|
|
|
/* MemoServ initialization. */
|
|
|
|
void ms_init(void)
|
|
{
|
|
Command *cmd;
|
|
moduleAddMemoServCmds();
|
|
cmd = findCommand(MEMOSERV, "SET LIMIT");
|
|
if (cmd)
|
|
cmd->help_param1 = (char *) (long) MSMaxMemos;
|
|
}
|
|
|
|
/*************************************************************************/
|
|
|
|
/* memoserv: Main MemoServ routine.
|
|
* Note that the User structure passed to the do_* routines will
|
|
* always be valid (non-NULL) and will always have a valid
|
|
* NickInfo pointer in the `ni' field.
|
|
*/
|
|
|
|
void memoserv(User * u, char *buf)
|
|
{
|
|
char *cmd, *s;
|
|
|
|
cmd = strtok(buf, " ");
|
|
if (!cmd) {
|
|
return;
|
|
} else if (stricmp(cmd, "\1PING") == 0) {
|
|
if (!(s = strtok(NULL, "")))
|
|
s = "\1";
|
|
notice(s_MemoServ, u->nick, "\1PING %s", s);
|
|
} else if (skeleton) {
|
|
notice_lang(s_MemoServ, u, SERVICE_OFFLINE, s_MemoServ);
|
|
} else {
|
|
if (!u->na && stricmp(cmd, "HELP") != 0)
|
|
notice_lang(s_MemoServ, u, NICK_NOT_REGISTERED_HELP,
|
|
s_NickServ);
|
|
else
|
|
mod_run_cmd(s_MemoServ, u, MEMOSERV, cmd);
|
|
}
|
|
}
|
|
|
|
/*************************************************************************/
|
|
|
|
/* check_memos: See if the given user has any unread memos, and send a
|
|
* NOTICE to that user if so (and if the appropriate flag is
|
|
* set).
|
|
*/
|
|
|
|
void check_memos(User * u)
|
|
{
|
|
NickCore *nc;
|
|
int i, newcnt = 0;
|
|
|
|
if (!(nc = (u->na ? u->na->nc : NULL)) || !nick_recognized(u) ||
|
|
!(nc->flags & NI_MEMO_SIGNON))
|
|
return;
|
|
|
|
for (i = 0; i < nc->memos.memocount; i++) {
|
|
if (nc->memos.memos[i].flags & MF_UNREAD)
|
|
newcnt++;
|
|
}
|
|
if (newcnt > 0) {
|
|
notice_lang(s_MemoServ, u,
|
|
newcnt == 1 ? MEMO_HAVE_NEW_MEMO : MEMO_HAVE_NEW_MEMOS,
|
|
newcnt);
|
|
if (newcnt == 1 && (nc->memos.memos[i - 1].flags & MF_UNREAD)) {
|
|
notice_lang(s_MemoServ, u, MEMO_TYPE_READ_LAST, s_MemoServ);
|
|
} else if (newcnt == 1) {
|
|
for (i = 0; i < nc->memos.memocount; i++) {
|
|
if (nc->memos.memos[i].flags & MF_UNREAD)
|
|
break;
|
|
}
|
|
notice_lang(s_MemoServ, u, MEMO_TYPE_READ_NUM, s_MemoServ,
|
|
nc->memos.memos[i].number);
|
|
} else {
|
|
notice_lang(s_MemoServ, u, MEMO_TYPE_LIST_NEW, s_MemoServ);
|
|
}
|
|
}
|
|
if (nc->memos.memomax > 0 && nc->memos.memocount >= nc->memos.memomax) {
|
|
if (nc->memos.memocount > nc->memos.memomax)
|
|
notice_lang(s_MemoServ, u, MEMO_OVER_LIMIT, nc->memos.memomax);
|
|
else
|
|
notice_lang(s_MemoServ, u, MEMO_AT_LIMIT, nc->memos.memomax);
|
|
}
|
|
}
|
|
|
|
/*************************************************************************/
|
|
/*********************** MemoServ private routines ***********************/
|
|
/*************************************************************************/
|
|
|
|
/* Return the MemoInfo corresponding to the given nick or channel name.
|
|
* Return in `ischan' 1 if the name was a channel name, else 0.
|
|
*/
|
|
|
|
static MemoInfo *getmemoinfo(const char *name, int *ischan)
|
|
{
|
|
if (*name == '#') {
|
|
ChannelInfo *ci;
|
|
if (ischan)
|
|
*ischan = 1;
|
|
ci = cs_findchan(name);
|
|
if (ci && !(ci->flags & CI_VERBOTEN))
|
|
return &ci->memos;
|
|
else
|
|
return NULL;
|
|
} else {
|
|
NickAlias *na;
|
|
if (ischan)
|
|
*ischan = 0;
|
|
na = findnick(name);
|
|
if (na && !(na->status & NS_VERBOTEN))
|
|
return &na->nc->memos;
|
|
else
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
/*************************************************************************/
|
|
|
|
/* Delete a memo by number. Return 1 if the memo was found, else 0. */
|
|
|
|
static int delmemo(MemoInfo * mi, int num)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < mi->memocount; i++) {
|
|
if (mi->memos[i].number == num)
|
|
break;
|
|
}
|
|
if (i < mi->memocount) {
|
|
free(mi->memos[i].text); /* Deallocate memo text memory */
|
|
mi->memocount--; /* One less memo now */
|
|
if (i < mi->memocount) /* Move remaining memos down a slot */
|
|
memmove(mi->memos + i, mi->memos + i + 1,
|
|
sizeof(Memo) * (mi->memocount - i));
|
|
if (mi->memocount == 0) { /* If no more memos, free array */
|
|
free(mi->memos);
|
|
mi->memos = NULL;
|
|
}
|
|
return 1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/*************************************************************************/
|
|
/*********************** MemoServ command routines ***********************/
|
|
/*************************************************************************/
|
|
|
|
/* Return a help message. */
|
|
|
|
static int do_help(User * u)
|
|
{
|
|
char *cmd = strtok(NULL, "");
|
|
|
|
if (!cmd) {
|
|
notice_help(s_MemoServ, u, MEMO_HELP);
|
|
if (is_services_oper(u)) {
|
|
notice_help(s_MemoServ, u, MEMO_HELP_OPER);
|
|
}
|
|
if (is_services_admin(u)) {
|
|
notice_help(s_MemoServ, u, MEMO_HELP_ADMIN);
|
|
}
|
|
moduleDisplayHelp(3, u);
|
|
notice_help(s_MemoServ, u, MEMO_HELP_FOOTER, s_ChanServ);
|
|
} else {
|
|
mod_help_cmd(s_MemoServ, u, MEMOSERV, cmd);
|
|
}
|
|
return MOD_CONT;
|
|
}
|
|
|
|
/*************************************************************************/
|
|
|
|
/* Send a memo to a nick/channel. */
|
|
|
|
static int do_send(User * u)
|
|
{
|
|
char *name = strtok(NULL, " ");
|
|
char *text = strtok(NULL, "");
|
|
int z = 0;
|
|
memo_send(u, name, text, z);
|
|
return MOD_CONT;
|
|
}
|
|
|
|
/**
|
|
* Split from do_send, this way we can easily send a memo from any point :)
|
|
* u - sender User
|
|
* name - target name
|
|
* text - memo Text
|
|
* z - output level,
|
|
* 0 - reply to user
|
|
* 1 - silent
|
|
* 2 - silent with no delay timer
|
|
**/
|
|
void memo_send(User * u, char *name, char *text, int z)
|
|
{
|
|
int ischan;
|
|
Memo *m;
|
|
MemoInfo *mi;
|
|
time_t now = time(NULL);
|
|
char *source = u->na->nc->display;
|
|
int is_servadmin = is_services_admin(u);
|
|
|
|
if (readonly) {
|
|
notice_lang(s_MemoServ, u, MEMO_SEND_DISABLED);
|
|
} else if (checkDefCon(DEFCON_NO_NEW_MEMOS)) {
|
|
notice_lang(s_MemoServ, u, OPER_DEFCON_DENIED);
|
|
return;
|
|
} else if (!text) {
|
|
if (z == 0)
|
|
syntax_error(s_MemoServ, u, "SEND", MEMO_SEND_SYNTAX);
|
|
|
|
} else if (!nick_recognized(u)) {
|
|
if (z == 0)
|
|
notice_lang(s_MemoServ, u, NICK_IDENTIFY_REQUIRED, s_NickServ);
|
|
|
|
} else if (!(mi = getmemoinfo(name, &ischan))) {
|
|
if (z == 0)
|
|
notice_lang(s_MemoServ, u,
|
|
ischan ? CHAN_X_NOT_REGISTERED :
|
|
NICK_X_NOT_REGISTERED, name);
|
|
|
|
} else if (z != 2 && MSSendDelay > 0 &&
|
|
u && u->lastmemosend + MSSendDelay > now && !is_servadmin) {
|
|
u->lastmemosend = now;
|
|
if (z == 0)
|
|
notice_lang(s_MemoServ, u, MEMO_SEND_PLEASE_WAIT, MSSendDelay);
|
|
|
|
} else if (mi->memomax == 0 && !is_servadmin) {
|
|
if (z == 0)
|
|
notice_lang(s_MemoServ, u, MEMO_X_GETS_NO_MEMOS, name);
|
|
|
|
} else if (mi->memomax > 0 && mi->memocount >= mi->memomax
|
|
&& !is_servadmin) {
|
|
if (z == 0)
|
|
notice_lang(s_MemoServ, u, MEMO_X_HAS_TOO_MANY_MEMOS, name);
|
|
|
|
} else {
|
|
u->lastmemosend = now;
|
|
mi->memocount++;
|
|
mi->memos = srealloc(mi->memos, sizeof(Memo) * mi->memocount);
|
|
m = &mi->memos[mi->memocount - 1];
|
|
strscpy(m->sender, source, NICKMAX);
|
|
if (mi->memocount > 1) {
|
|
m->number = m[-1].number + 1;
|
|
if (m->number < 1) {
|
|
int i;
|
|
for (i = 0; i < mi->memocount; i++)
|
|
mi->memos[i].number = i + 1;
|
|
}
|
|
} else {
|
|
m->number = 1;
|
|
}
|
|
m->time = time(NULL);
|
|
m->text = sstrdup(text);
|
|
m->flags = MF_UNREAD;
|
|
if (z == 0)
|
|
notice_lang(s_MemoServ, u, MEMO_SENT, name);
|
|
if (!ischan) {
|
|
NickAlias *na;
|
|
NickCore *nc = (findnick(name))->nc;
|
|
|
|
if (MSNotifyAll) {
|
|
if ((nc->flags & NI_MEMO_RECEIVE)
|
|
&& get_ignore(name) == NULL) {
|
|
int i;
|
|
|
|
for (i = 0; i < nc->aliases.count; i++) {
|
|
na = nc->aliases.list[i];
|
|
if (na->u && nick_identified(na->u))
|
|
notice_lang(s_MemoServ, na->u,
|
|
MEMO_NEW_MEMO_ARRIVED, source,
|
|
s_MemoServ, m->number);
|
|
}
|
|
} else {
|
|
if ((u = finduser(name)) && nick_identified(u))
|
|
notice_lang(s_MemoServ, u, MEMO_NEW_MEMO_ARRIVED,
|
|
source, s_MemoServ, m->number);
|
|
} /* if (flags & MEMO_RECEIVE) */
|
|
} /* if (MSNotifyAll) */
|
|
} else {
|
|
struct c_userlist *cu, *next;
|
|
Channel *c;
|
|
|
|
if (MSNotifyAll && (c = findchan(name))) {
|
|
for (cu = c->users; cu; cu = next) {
|
|
next = cu->next;
|
|
if (check_access(cu->user, c->ci, CA_MEMO)) {
|
|
if (cu->user->na
|
|
&& (cu->user->na->nc->flags & NI_MEMO_RECEIVE)
|
|
&& get_ignore(cu->user->nick) == NULL) {
|
|
notice_lang(s_MemoServ, cu->user,
|
|
MEMO_NEW_X_MEMO_ARRIVED,
|
|
c->ci->name, s_MemoServ,
|
|
c->ci->name, m->number);
|
|
}
|
|
}
|
|
}
|
|
} /* MSNotifyAll */
|
|
} /* if (!ischan) */
|
|
} /* if command is valid */
|
|
}
|
|
|
|
/*************************************************************************/
|
|
|
|
static int do_cancel(User * u)
|
|
{
|
|
int ischan;
|
|
char *name = strtok(NULL, " ");
|
|
MemoInfo *mi;
|
|
|
|
if (!name) {
|
|
syntax_error(s_MemoServ, u, "CANCEL", MEMO_CANCEL_SYNTAX);
|
|
|
|
} else if (!nick_recognized(u)) {
|
|
notice_lang(s_MemoServ, u, NICK_IDENTIFY_REQUIRED, s_NickServ);
|
|
|
|
} else if (!(mi = getmemoinfo(name, &ischan))) {
|
|
notice_lang(s_MemoServ, u,
|
|
ischan ? CHAN_X_NOT_REGISTERED : NICK_X_NOT_REGISTERED,
|
|
name);
|
|
} else {
|
|
int i;
|
|
|
|
for (i = mi->memocount - 1; i >= 0; i--) {
|
|
if ((mi->memos[i].flags & MF_UNREAD)
|
|
&& !stricmp(mi->memos[i].sender, u->na->nc->display)) {
|
|
delmemo(mi, mi->memos[i].number);
|
|
notice_lang(s_MemoServ, u, MEMO_CANCELLED, name);
|
|
return MOD_CONT;
|
|
}
|
|
}
|
|
|
|
notice_lang(s_MemoServ, u, MEMO_CANCEL_NONE);
|
|
}
|
|
return MOD_CONT;
|
|
}
|
|
|
|
/*************************************************************************/
|
|
|
|
/* Display a single memo entry, possibly printing the header first. */
|
|
|
|
static int list_memo(User * u, int index, MemoInfo * mi, int *sent_header,
|
|
int new, const char *chan)
|
|
{
|
|
Memo *m;
|
|
char timebuf[64];
|
|
struct tm tm;
|
|
|
|
if (index < 0 || index >= mi->memocount)
|
|
return 0;
|
|
if (!*sent_header) {
|
|
if (chan) {
|
|
notice_lang(s_MemoServ, u,
|
|
new ? MEMO_LIST_CHAN_NEW_MEMOS :
|
|
MEMO_LIST_CHAN_MEMOS, chan, s_MemoServ, chan);
|
|
} else {
|
|
notice_lang(s_MemoServ, u,
|
|
new ? MEMO_LIST_NEW_MEMOS : MEMO_LIST_MEMOS,
|
|
u->nick, s_MemoServ);
|
|
}
|
|
notice_lang(s_MemoServ, u, MEMO_LIST_HEADER);
|
|
*sent_header = 1;
|
|
}
|
|
m = &mi->memos[index];
|
|
tm = *localtime(&m->time);
|
|
strftime_lang(timebuf, sizeof(timebuf),
|
|
u, STRFTIME_DATE_TIME_FORMAT, &tm);
|
|
timebuf[sizeof(timebuf) - 1] = 0; /* just in case */
|
|
notice_lang(s_MemoServ, u, MEMO_LIST_FORMAT,
|
|
(m->flags & MF_UNREAD) ? '*' : ' ',
|
|
m->number, m->sender, timebuf);
|
|
return 1;
|
|
}
|
|
|
|
static int list_memo_callback(User * u, int num, va_list args)
|
|
{
|
|
MemoInfo *mi = va_arg(args, MemoInfo *);
|
|
int *sent_header = va_arg(args, int *);
|
|
const char *chan = va_arg(args, const char *);
|
|
int i;
|
|
|
|
for (i = 0; i < mi->memocount; i++) {
|
|
if (mi->memos[i].number == num)
|
|
break;
|
|
}
|
|
/* Range checking done by list_memo() */
|
|
return list_memo(u, i, mi, sent_header, 0, chan);
|
|
}
|
|
|
|
|
|
/* List the memos (if any) for the source nick or given channel. */
|
|
|
|
static int do_list(User * u)
|
|
{
|
|
char *param = strtok(NULL, " "), *chan = NULL;
|
|
ChannelInfo *ci;
|
|
MemoInfo *mi;
|
|
Memo *m;
|
|
int i;
|
|
|
|
if (param && *param == '#') {
|
|
chan = param;
|
|
param = strtok(NULL, " ");
|
|
if (!(ci = cs_findchan(chan))) {
|
|
notice_lang(s_MemoServ, u, CHAN_X_NOT_REGISTERED, chan);
|
|
return MOD_CONT;
|
|
} else if (ci->flags & CI_VERBOTEN) {
|
|
notice_lang(s_MemoServ, u, CHAN_X_FORBIDDEN, chan);
|
|
return MOD_CONT;
|
|
} else if (!check_access(u, ci, CA_MEMO)) {
|
|
notice_lang(s_MemoServ, u, ACCESS_DENIED);
|
|
return MOD_CONT;
|
|
}
|
|
mi = &ci->memos;
|
|
} else {
|
|
if (!nick_identified(u)) {
|
|
notice_lang(s_MemoServ, u, NICK_IDENTIFY_REQUIRED, s_NickServ);
|
|
return MOD_CONT;
|
|
}
|
|
mi = &u->na->nc->memos;
|
|
}
|
|
if (param && !isdigit(*param) && stricmp(param, "NEW") != 0) {
|
|
syntax_error(s_MemoServ, u, "LIST", MEMO_LIST_SYNTAX);
|
|
} else if (mi->memocount == 0) {
|
|
if (chan)
|
|
notice_lang(s_MemoServ, u, MEMO_X_HAS_NO_MEMOS, chan);
|
|
else
|
|
notice_lang(s_MemoServ, u, MEMO_HAVE_NO_MEMOS);
|
|
} else {
|
|
int sent_header = 0;
|
|
if (param && isdigit(*param)) {
|
|
process_numlist(param, NULL, list_memo_callback, u,
|
|
mi, &sent_header, chan);
|
|
} else {
|
|
if (param) {
|
|
for (i = 0, m = mi->memos; i < mi->memocount; i++, m++) {
|
|
if (m->flags & MF_UNREAD)
|
|
break;
|
|
}
|
|
if (i == mi->memocount) {
|
|
if (chan)
|
|
notice_lang(s_MemoServ, u, MEMO_X_HAS_NO_NEW_MEMOS,
|
|
chan);
|
|
else
|
|
notice_lang(s_MemoServ, u, MEMO_HAVE_NO_NEW_MEMOS);
|
|
return MOD_CONT;
|
|
}
|
|
}
|
|
for (i = 0, m = mi->memos; i < mi->memocount; i++, m++) {
|
|
if (param && !(m->flags & MF_UNREAD))
|
|
continue;
|
|
list_memo(u, i, mi, &sent_header, param != NULL, chan);
|
|
}
|
|
}
|
|
}
|
|
return MOD_CONT;
|
|
}
|
|
|
|
/*************************************************************************/
|
|
|
|
/* Send a single memo to the given user. */
|
|
|
|
static int read_memo(User * u, int index, MemoInfo * mi, const char *chan)
|
|
{
|
|
Memo *m;
|
|
char timebuf[64];
|
|
struct tm tm;
|
|
|
|
if (index < 0 || index >= mi->memocount)
|
|
return 0;
|
|
m = &mi->memos[index];
|
|
tm = *localtime(&m->time);
|
|
strftime_lang(timebuf, sizeof(timebuf),
|
|
u, STRFTIME_DATE_TIME_FORMAT, &tm);
|
|
timebuf[sizeof(timebuf) - 1] = 0;
|
|
if (chan)
|
|
notice_lang(s_MemoServ, u, MEMO_CHAN_HEADER, m->number,
|
|
m->sender, timebuf, s_MemoServ, chan, m->number);
|
|
else
|
|
notice_lang(s_MemoServ, u, MEMO_HEADER, m->number,
|
|
m->sender, timebuf, s_MemoServ, m->number);
|
|
notice_lang(s_MemoServ, u, MEMO_TEXT, m->text);
|
|
m->flags &= ~MF_UNREAD;
|
|
return 1;
|
|
}
|
|
|
|
static int read_memo_callback(User * u, int num, va_list args)
|
|
{
|
|
MemoInfo *mi = va_arg(args, MemoInfo *);
|
|
const char *chan = va_arg(args, const char *);
|
|
int i;
|
|
|
|
for (i = 0; i < mi->memocount; i++) {
|
|
if (mi->memos[i].number == num)
|
|
break;
|
|
}
|
|
/* Range check done in read_memo */
|
|
return read_memo(u, i, mi, chan);
|
|
}
|
|
|
|
|
|
/* Read memos. */
|
|
|
|
static int do_read(User * u)
|
|
{
|
|
MemoInfo *mi;
|
|
ChannelInfo *ci;
|
|
char *numstr = strtok(NULL, " "), *chan = NULL;
|
|
int num, count;
|
|
|
|
if (numstr && *numstr == '#') {
|
|
chan = numstr;
|
|
numstr = strtok(NULL, " ");
|
|
if (!(ci = cs_findchan(chan))) {
|
|
notice_lang(s_MemoServ, u, CHAN_X_NOT_REGISTERED, chan);
|
|
return MOD_CONT;
|
|
} else if (ci->flags & CI_VERBOTEN) {
|
|
notice_lang(s_MemoServ, u, CHAN_X_FORBIDDEN, chan);
|
|
return MOD_CONT;
|
|
} else if (!check_access(u, ci, CA_MEMO)) {
|
|
notice_lang(s_MemoServ, u, ACCESS_DENIED);
|
|
return MOD_CONT;
|
|
}
|
|
mi = &ci->memos;
|
|
} else {
|
|
if (!nick_identified(u)) {
|
|
notice_lang(s_MemoServ, u, NICK_IDENTIFY_REQUIRED, s_NickServ);
|
|
return MOD_CONT;
|
|
}
|
|
mi = &u->na->nc->memos;
|
|
}
|
|
num = numstr ? atoi(numstr) : -1;
|
|
if (!numstr
|
|
|| (stricmp(numstr, "LAST") != 0 && stricmp(numstr, "NEW") != 0
|
|
&& num <= 0)) {
|
|
syntax_error(s_MemoServ, u, "READ", MEMO_READ_SYNTAX);
|
|
|
|
} else if (mi->memocount == 0) {
|
|
if (chan)
|
|
notice_lang(s_MemoServ, u, MEMO_X_HAS_NO_MEMOS, chan);
|
|
else
|
|
notice_lang(s_MemoServ, u, MEMO_HAVE_NO_MEMOS);
|
|
|
|
} else {
|
|
int i;
|
|
|
|
if (stricmp(numstr, "NEW") == 0) {
|
|
int readcount = 0;
|
|
for (i = 0; i < mi->memocount; i++) {
|
|
if (mi->memos[i].flags & MF_UNREAD) {
|
|
read_memo(u, i, mi, chan);
|
|
readcount++;
|
|
}
|
|
}
|
|
if (!readcount) {
|
|
if (chan)
|
|
notice_lang(s_MemoServ, u, MEMO_X_HAS_NO_NEW_MEMOS,
|
|
chan);
|
|
else
|
|
notice_lang(s_MemoServ, u, MEMO_HAVE_NO_NEW_MEMOS);
|
|
}
|
|
} else if (stricmp(numstr, "LAST") == 0) {
|
|
for (i = 0; i < mi->memocount - 1; i++);
|
|
read_memo(u, i, mi, chan);
|
|
} else { /* number[s] */
|
|
if (!process_numlist(numstr, &count, read_memo_callback, u,
|
|
mi, chan)) {
|
|
if (count == 1)
|
|
notice_lang(s_MemoServ, u, MEMO_DOES_NOT_EXIST, num);
|
|
else
|
|
notice_lang(s_MemoServ, u, MEMO_LIST_NOT_FOUND,
|
|
numstr);
|
|
}
|
|
}
|
|
|
|
}
|
|
return MOD_CONT;
|
|
}
|
|
|
|
/*************************************************************************/
|
|
|
|
/* Delete a single memo from a MemoInfo. */
|
|
|
|
static int del_memo_callback(User * u, int num, va_list args)
|
|
{
|
|
MemoInfo *mi = va_arg(args, MemoInfo *);
|
|
int *last = va_arg(args, int *);
|
|
int *last0 = va_arg(args, int *);
|
|
char **end = va_arg(args, char **);
|
|
int *left = va_arg(args, int *);
|
|
|
|
if (delmemo(mi, num)) {
|
|
if (num != (*last) + 1) {
|
|
if (*last != -1) {
|
|
int len;
|
|
if (*last0 != *last)
|
|
len = snprintf(*end, *left, ",%d-%d", *last0, *last);
|
|
else
|
|
len = snprintf(*end, *left, ",%d", *last);
|
|
*end += len;
|
|
*left -= len;
|
|
}
|
|
*last0 = num;
|
|
}
|
|
*last = num;
|
|
return 1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
/* Delete memos. */
|
|
|
|
static int do_del(User * u)
|
|
{
|
|
MemoInfo *mi;
|
|
ChannelInfo *ci;
|
|
char *numstr = strtok(NULL, ""), *chan = NULL;
|
|
int last, last0, i;
|
|
char buf[BUFSIZE], *end;
|
|
int delcount, count, left;
|
|
|
|
if (numstr && *numstr == '#') {
|
|
chan = strtok(numstr, " ");
|
|
numstr = strtok(NULL, "");
|
|
if (!(ci = cs_findchan(chan))) {
|
|
notice_lang(s_MemoServ, u, CHAN_X_NOT_REGISTERED, chan);
|
|
return MOD_CONT;
|
|
} else if (ci->flags & CI_VERBOTEN) {
|
|
notice_lang(s_MemoServ, u, CHAN_X_FORBIDDEN, chan);
|
|
return MOD_CONT;
|
|
} else if (!check_access(u, ci, CA_MEMO)) {
|
|
notice_lang(s_MemoServ, u, ACCESS_DENIED);
|
|
return MOD_CONT;
|
|
}
|
|
mi = &ci->memos;
|
|
} else {
|
|
if (!nick_identified(u)) {
|
|
notice_lang(s_MemoServ, u, NICK_IDENTIFY_REQUIRED, s_NickServ);
|
|
return MOD_CONT;
|
|
}
|
|
mi = &u->na->nc->memos;
|
|
}
|
|
if (!numstr
|
|
|| (!isdigit(*numstr) && stricmp(numstr, "ALL") != 0
|
|
&& stricmp(numstr, "LAST") != 0)) {
|
|
syntax_error(s_MemoServ, u, "DEL", MEMO_DEL_SYNTAX);
|
|
} else if (mi->memocount == 0) {
|
|
if (chan)
|
|
notice_lang(s_MemoServ, u, MEMO_X_HAS_NO_MEMOS, chan);
|
|
else
|
|
notice_lang(s_MemoServ, u, MEMO_HAVE_NO_MEMOS);
|
|
} else {
|
|
if (isdigit(*numstr)) {
|
|
/* Delete a specific memo or memos. */
|
|
last = -1; /* Last memo deleted */
|
|
last0 = -1; /* Beginning of range of last memos deleted */
|
|
end = buf;
|
|
left = sizeof(buf);
|
|
delcount =
|
|
process_numlist(numstr, &count, del_memo_callback, u, mi,
|
|
&last, &last0, &end, &left);
|
|
if (last != -1) {
|
|
/* Some memos got deleted; tell them which ones. */
|
|
if (delcount > 1) {
|
|
if (last0 != last)
|
|
end += snprintf(end, sizeof(buf) - (end - buf),
|
|
",%d-%d", last0, last);
|
|
else
|
|
end += snprintf(end, sizeof(buf) - (end - buf),
|
|
",%d", last);
|
|
/* "buf+1" here because *buf == ',' */
|
|
notice_lang(s_MemoServ, u, MEMO_DELETED_SEVERAL,
|
|
buf + 1);
|
|
} else {
|
|
notice_lang(s_MemoServ, u, MEMO_DELETED_ONE, last);
|
|
}
|
|
} else {
|
|
/* No memos were deleted. Tell them so. */
|
|
if (count == 1)
|
|
notice_lang(s_MemoServ, u, MEMO_DOES_NOT_EXIST,
|
|
atoi(numstr));
|
|
else
|
|
notice_lang(s_MemoServ, u, MEMO_DELETED_NONE);
|
|
}
|
|
} else if (stricmp(numstr, "LAST") == 0) {
|
|
/* Delete last memo. */
|
|
for (i = 0; i < mi->memocount; i++)
|
|
last = mi->memos[i].number;
|
|
delmemo(mi, last);
|
|
notice_lang(s_MemoServ, u, MEMO_DELETED_ONE, last);
|
|
} else {
|
|
/* Delete all memos. */
|
|
for (i = 0; i < mi->memocount; i++)
|
|
free(mi->memos[i].text);
|
|
free(mi->memos);
|
|
mi->memos = NULL;
|
|
mi->memocount = 0;
|
|
if (chan)
|
|
notice_lang(s_MemoServ, u, MEMO_CHAN_DELETED_ALL, chan);
|
|
else
|
|
notice_lang(s_MemoServ, u, MEMO_DELETED_ALL);
|
|
}
|
|
|
|
/* Reset the order */
|
|
for (i = 0; i < mi->memocount; i++)
|
|
mi->memos[i].number = i + 1;
|
|
}
|
|
return MOD_CONT;
|
|
}
|
|
|
|
/*************************************************************************/
|
|
|
|
static int do_set(User * u)
|
|
{
|
|
char *cmd = strtok(NULL, " ");
|
|
char *param = strtok(NULL, "");
|
|
MemoInfo *mi = &u->na->nc->memos;
|
|
|
|
if (readonly) {
|
|
notice_lang(s_MemoServ, u, MEMO_SET_DISABLED);
|
|
return MOD_CONT;
|
|
}
|
|
if (!param) {
|
|
syntax_error(s_MemoServ, u, "SET", MEMO_SET_SYNTAX);
|
|
} else if (!nick_identified(u)) {
|
|
notice_lang(s_MemoServ, u, NICK_IDENTIFY_REQUIRED, s_NickServ);
|
|
return MOD_CONT;
|
|
} else if (stricmp(cmd, "NOTIFY") == 0) {
|
|
do_set_notify(u, mi, param);
|
|
} else if (stricmp(cmd, "LIMIT") == 0) {
|
|
do_set_limit(u, mi, param);
|
|
} else {
|
|
notice_lang(s_MemoServ, u, MEMO_SET_UNKNOWN_OPTION, cmd);
|
|
notice_lang(s_MemoServ, u, MORE_INFO, s_MemoServ, "SET");
|
|
}
|
|
return MOD_CONT;
|
|
}
|
|
|
|
/*************************************************************************/
|
|
|
|
static int do_set_notify(User * u, MemoInfo * mi, char *param)
|
|
{
|
|
if (stricmp(param, "ON") == 0) {
|
|
u->na->nc->flags |= NI_MEMO_SIGNON | NI_MEMO_RECEIVE;
|
|
notice_lang(s_MemoServ, u, MEMO_SET_NOTIFY_ON, s_MemoServ);
|
|
} else if (stricmp(param, "LOGON") == 0) {
|
|
u->na->nc->flags |= NI_MEMO_SIGNON;
|
|
u->na->nc->flags &= ~NI_MEMO_RECEIVE;
|
|
notice_lang(s_MemoServ, u, MEMO_SET_NOTIFY_LOGON, s_MemoServ);
|
|
} else if (stricmp(param, "NEW") == 0) {
|
|
u->na->nc->flags &= ~NI_MEMO_SIGNON;
|
|
u->na->nc->flags |= NI_MEMO_RECEIVE;
|
|
notice_lang(s_MemoServ, u, MEMO_SET_NOTIFY_NEW, s_MemoServ);
|
|
} else if (stricmp(param, "OFF") == 0) {
|
|
u->na->nc->flags &= ~(NI_MEMO_SIGNON | NI_MEMO_RECEIVE);
|
|
notice_lang(s_MemoServ, u, MEMO_SET_NOTIFY_OFF, s_MemoServ);
|
|
} else {
|
|
syntax_error(s_MemoServ, u, "SET NOTIFY", MEMO_SET_NOTIFY_SYNTAX);
|
|
}
|
|
return MOD_CONT;
|
|
}
|
|
|
|
/*************************************************************************/
|
|
|
|
static int do_set_limit(User * u, MemoInfo * mi, char *param)
|
|
{
|
|
char *p1 = strtok(param, " ");
|
|
char *p2 = strtok(NULL, " ");
|
|
char *p3 = strtok(NULL, " ");
|
|
char *user = NULL, *chan = NULL;
|
|
int32 limit;
|
|
NickAlias *na = u->na;
|
|
ChannelInfo *ci = NULL;
|
|
int is_servadmin = is_services_admin(u);
|
|
|
|
if (p1 && *p1 == '#') {
|
|
chan = p1;
|
|
p1 = p2;
|
|
p2 = p3;
|
|
p3 = strtok(NULL, " ");
|
|
if (!(ci = cs_findchan(chan))) {
|
|
notice_lang(s_MemoServ, u, CHAN_X_NOT_REGISTERED, chan);
|
|
return MOD_CONT;
|
|
} else if (ci->flags & CI_VERBOTEN) {
|
|
notice_lang(s_MemoServ, u, CHAN_X_FORBIDDEN, chan);
|
|
return MOD_CONT;
|
|
} else if (!is_servadmin && !check_access(u, ci, CA_MEMO)) {
|
|
notice_lang(s_MemoServ, u, ACCESS_DENIED);
|
|
return MOD_CONT;
|
|
}
|
|
mi = &ci->memos;
|
|
}
|
|
if (is_servadmin) {
|
|
if (p2 && stricmp(p2, "HARD") != 0 && !chan) {
|
|
if (!(na = findnick(p1))) {
|
|
notice_lang(s_MemoServ, u, NICK_X_NOT_REGISTERED, p1);
|
|
return MOD_CONT;
|
|
}
|
|
user = p1;
|
|
mi = &na->nc->memos;
|
|
p1 = p2;
|
|
p2 = p3;
|
|
} else if (!p1) {
|
|
syntax_error(s_MemoServ, u, "SET LIMIT",
|
|
MEMO_SET_LIMIT_SERVADMIN_SYNTAX);
|
|
return MOD_CONT;
|
|
}
|
|
if ((!isdigit(*p1) && stricmp(p1, "NONE") != 0) ||
|
|
(p2 && stricmp(p2, "HARD") != 0)) {
|
|
syntax_error(s_MemoServ, u, "SET LIMIT",
|
|
MEMO_SET_LIMIT_SERVADMIN_SYNTAX);
|
|
return MOD_CONT;
|
|
}
|
|
if (chan) {
|
|
if (p2)
|
|
ci->flags |= CI_MEMO_HARDMAX;
|
|
else
|
|
ci->flags &= ~CI_MEMO_HARDMAX;
|
|
} else {
|
|
if (p2)
|
|
na->nc->flags |= NI_MEMO_HARDMAX;
|
|
else
|
|
na->nc->flags &= ~NI_MEMO_HARDMAX;
|
|
}
|
|
limit = atoi(p1);
|
|
if (limit < 0 || limit > 32767) {
|
|
notice_lang(s_MemoServ, u, MEMO_SET_LIMIT_OVERFLOW, 32767);
|
|
limit = 32767;
|
|
}
|
|
if (stricmp(p1, "NONE") == 0)
|
|
limit = -1;
|
|
} else {
|
|
if (!p1 || p2 || !isdigit(*p1)) {
|
|
syntax_error(s_MemoServ, u, "SET LIMIT",
|
|
MEMO_SET_LIMIT_SYNTAX);
|
|
return MOD_CONT;
|
|
}
|
|
if (chan && (ci->flags & CI_MEMO_HARDMAX)) {
|
|
notice_lang(s_MemoServ, u, MEMO_SET_LIMIT_FORBIDDEN, chan);
|
|
return MOD_CONT;
|
|
} else if (!chan && (na->nc->flags & NI_MEMO_HARDMAX)) {
|
|
notice_lang(s_MemoServ, u, MEMO_SET_YOUR_LIMIT_FORBIDDEN);
|
|
return MOD_CONT;
|
|
}
|
|
limit = atoi(p1);
|
|
/* The first character is a digit, but we could still go negative
|
|
* from overflow... watch out! */
|
|
if (limit < 0 || (MSMaxMemos > 0 && limit > MSMaxMemos)) {
|
|
if (chan) {
|
|
notice_lang(s_MemoServ, u, MEMO_SET_LIMIT_TOO_HIGH,
|
|
chan, MSMaxMemos);
|
|
} else {
|
|
notice_lang(s_MemoServ, u, MEMO_SET_YOUR_LIMIT_TOO_HIGH,
|
|
MSMaxMemos);
|
|
}
|
|
return MOD_CONT;
|
|
} else if (limit > 32767) {
|
|
notice_lang(s_MemoServ, u, MEMO_SET_LIMIT_OVERFLOW, 32767);
|
|
limit = 32767;
|
|
}
|
|
}
|
|
mi->memomax = limit;
|
|
if (limit > 0) {
|
|
if (!chan && na->nc == u->na->nc)
|
|
notice_lang(s_MemoServ, u, MEMO_SET_YOUR_LIMIT, limit);
|
|
else
|
|
notice_lang(s_MemoServ, u, MEMO_SET_LIMIT,
|
|
chan ? chan : user, limit);
|
|
} else if (limit == 0) {
|
|
if (!chan && na->nc == u->na->nc)
|
|
notice_lang(s_MemoServ, u, MEMO_SET_YOUR_LIMIT_ZERO);
|
|
else
|
|
notice_lang(s_MemoServ, u, MEMO_SET_LIMIT_ZERO,
|
|
chan ? chan : user);
|
|
} else {
|
|
if (!chan && na->nc == u->na->nc)
|
|
notice_lang(s_MemoServ, u, MEMO_UNSET_YOUR_LIMIT);
|
|
else
|
|
notice_lang(s_MemoServ, u, MEMO_UNSET_LIMIT,
|
|
chan ? chan : user);
|
|
}
|
|
return MOD_CONT;
|
|
}
|
|
|
|
/*************************************************************************/
|
|
|
|
static int do_info(User * u)
|
|
{
|
|
MemoInfo *mi;
|
|
NickAlias *na = NULL;
|
|
ChannelInfo *ci = NULL;
|
|
char *name = strtok(NULL, " ");
|
|
int is_servadmin = is_services_admin(u);
|
|
int hardmax = 0;
|
|
|
|
if (is_servadmin && name && *name != '#') {
|
|
na = findnick(name);
|
|
if (!na) {
|
|
notice_lang(s_MemoServ, u, NICK_X_NOT_REGISTERED, name);
|
|
return MOD_CONT;
|
|
}
|
|
mi = &na->nc->memos;
|
|
hardmax = na->nc->flags & NI_MEMO_HARDMAX ? 1 : 0;
|
|
} else if (name && *name == '#') {
|
|
ci = cs_findchan(name);
|
|
if (!ci) {
|
|
notice_lang(s_MemoServ, u, CHAN_X_NOT_REGISTERED, name);
|
|
return MOD_CONT;
|
|
} else if (ci->flags & CI_VERBOTEN) {
|
|
notice_lang(s_MemoServ, u, CHAN_X_FORBIDDEN, name);
|
|
return MOD_CONT;
|
|
} else if (!check_access(u, ci, CA_MEMO)) {
|
|
notice_lang(s_MemoServ, u, ACCESS_DENIED);
|
|
return MOD_CONT;
|
|
}
|
|
mi = &ci->memos;
|
|
hardmax = ci->flags & CI_MEMO_HARDMAX ? 1 : 0;
|
|
} else if (name) { /* It's not a chan and we aren't services admin */
|
|
notice_lang(s_MemoServ, u, ACCESS_DENIED);
|
|
return MOD_CONT;
|
|
} else { /* !name */
|
|
if (!nick_identified(u)) {
|
|
notice_lang(s_MemoServ, u, NICK_IDENTIFY_REQUIRED, s_NickServ);
|
|
return MOD_CONT;
|
|
}
|
|
mi = &u->na->nc->memos;
|
|
hardmax = u->na->nc->flags & NI_MEMO_HARDMAX ? 1 : 0;
|
|
}
|
|
|
|
if (name && (ci || na->nc != u->na->nc)) {
|
|
|
|
if (!mi->memocount) {
|
|
notice_lang(s_MemoServ, u, MEMO_INFO_X_NO_MEMOS, name);
|
|
} else if (mi->memocount == 1) {
|
|
if (mi->memos[0].flags & MF_UNREAD)
|
|
notice_lang(s_MemoServ, u, MEMO_INFO_X_MEMO_UNREAD, name);
|
|
else
|
|
notice_lang(s_MemoServ, u, MEMO_INFO_X_MEMO, name);
|
|
} else {
|
|
int count = 0, i;
|
|
for (i = 0; i < mi->memocount; i++) {
|
|
if (mi->memos[i].flags & MF_UNREAD)
|
|
count++;
|
|
}
|
|
if (count == mi->memocount)
|
|
notice_lang(s_MemoServ, u, MEMO_INFO_X_MEMOS_ALL_UNREAD,
|
|
name, count);
|
|
else if (count == 0)
|
|
notice_lang(s_MemoServ, u, MEMO_INFO_X_MEMOS, name,
|
|
mi->memocount);
|
|
else if (count == 0)
|
|
notice_lang(s_MemoServ, u, MEMO_INFO_X_MEMOS_ONE_UNREAD,
|
|
name, mi->memocount);
|
|
else
|
|
notice_lang(s_MemoServ, u, MEMO_INFO_X_MEMOS_SOME_UNREAD,
|
|
name, mi->memocount, count);
|
|
}
|
|
if (mi->memomax >= 0) {
|
|
if (hardmax)
|
|
notice_lang(s_MemoServ, u, MEMO_INFO_X_HARD_LIMIT, name,
|
|
mi->memomax);
|
|
else
|
|
notice_lang(s_MemoServ, u, MEMO_INFO_X_LIMIT, name,
|
|
mi->memomax);
|
|
} else {
|
|
notice_lang(s_MemoServ, u, MEMO_INFO_X_NO_LIMIT, name);
|
|
}
|
|
|
|
/* I ripped this code out of ircservices 4.4.5, since I didn't want
|
|
to rewrite the whole thing (it pisses me off). */
|
|
if (na) {
|
|
if ((na->nc->flags & NI_MEMO_RECEIVE)
|
|
&& (na->nc->flags & NI_MEMO_SIGNON)) {
|
|
notice_lang(s_MemoServ, u, MEMO_INFO_X_NOTIFY_ON, name);
|
|
} else if (na->nc->flags & NI_MEMO_RECEIVE) {
|
|
notice_lang(s_MemoServ, u, MEMO_INFO_X_NOTIFY_RECEIVE,
|
|
name);
|
|
} else if (na->nc->flags & NI_MEMO_SIGNON) {
|
|
notice_lang(s_MemoServ, u, MEMO_INFO_X_NOTIFY_SIGNON,
|
|
name);
|
|
} else {
|
|
notice_lang(s_MemoServ, u, MEMO_INFO_X_NOTIFY_OFF, name);
|
|
}
|
|
}
|
|
|
|
} else { /* !name || (!ci || na->nc == u->na->nc) */
|
|
|
|
if (!mi->memocount) {
|
|
notice_lang(s_MemoServ, u, MEMO_INFO_NO_MEMOS);
|
|
} else if (mi->memocount == 1) {
|
|
if (mi->memos[0].flags & MF_UNREAD)
|
|
notice_lang(s_MemoServ, u, MEMO_INFO_MEMO_UNREAD);
|
|
else
|
|
notice_lang(s_MemoServ, u, MEMO_INFO_MEMO);
|
|
} else {
|
|
int count = 0, i;
|
|
for (i = 0; i < mi->memocount; i++) {
|
|
if (mi->memos[i].flags & MF_UNREAD)
|
|
count++;
|
|
}
|
|
if (count == mi->memocount)
|
|
notice_lang(s_MemoServ, u, MEMO_INFO_MEMOS_ALL_UNREAD,
|
|
count);
|
|
else if (count == 0)
|
|
notice_lang(s_MemoServ, u, MEMO_INFO_MEMOS, mi->memocount);
|
|
else if (count == 1)
|
|
notice_lang(s_MemoServ, u, MEMO_INFO_MEMOS_ONE_UNREAD,
|
|
mi->memocount);
|
|
else
|
|
notice_lang(s_MemoServ, u, MEMO_INFO_MEMOS_SOME_UNREAD,
|
|
mi->memocount, count);
|
|
}
|
|
|
|
if (mi->memomax == 0) {
|
|
if (!is_servadmin && hardmax)
|
|
notice_lang(s_MemoServ, u, MEMO_INFO_HARD_LIMIT_ZERO);
|
|
else
|
|
notice_lang(s_MemoServ, u, MEMO_INFO_LIMIT_ZERO);
|
|
} else if (mi->memomax > 0) {
|
|
if (!is_servadmin && hardmax)
|
|
notice_lang(s_MemoServ, u, MEMO_INFO_HARD_LIMIT,
|
|
mi->memomax);
|
|
else
|
|
notice_lang(s_MemoServ, u, MEMO_INFO_LIMIT, mi->memomax);
|
|
} else {
|
|
notice_lang(s_MemoServ, u, MEMO_INFO_NO_LIMIT);
|
|
}
|
|
|
|
/* Ripped too. But differently because of a seg fault (loughs) */
|
|
if ((u->na->nc->flags & NI_MEMO_RECEIVE)
|
|
&& (u->na->nc->flags & NI_MEMO_SIGNON)) {
|
|
notice_lang(s_MemoServ, u, MEMO_INFO_NOTIFY_ON);
|
|
} else if (u->na->nc->flags & NI_MEMO_RECEIVE) {
|
|
notice_lang(s_MemoServ, u, MEMO_INFO_NOTIFY_RECEIVE);
|
|
} else if (u->na->nc->flags & NI_MEMO_SIGNON) {
|
|
notice_lang(s_MemoServ, u, MEMO_INFO_NOTIFY_SIGNON);
|
|
} else {
|
|
notice_lang(s_MemoServ, u, MEMO_INFO_NOTIFY_OFF);
|
|
}
|
|
}
|
|
return MOD_CONT; /* if (name && (ci || na->nc != u->na->nc)) */
|
|
}
|
|
|
|
/*************************************************************************/
|
|
/**
|
|
* Allow the easy sending of memo's to all user's on the oper/admin/root lists
|
|
* - Rob
|
|
* Opers in several lists won't get the memo twice from now on
|
|
* - Certus
|
|
**/
|
|
|
|
static int do_staff(User * u)
|
|
{
|
|
NickCore *nc;
|
|
int i, z = 0;
|
|
char *text = strtok(NULL, "");
|
|
|
|
if (readonly) {
|
|
notice_lang(s_MemoServ, u, MEMO_SEND_DISABLED);
|
|
return MOD_CONT;
|
|
} else if (checkDefCon(DEFCON_NO_NEW_MEMOS)) {
|
|
notice_lang(s_MemoServ, u, OPER_DEFCON_DENIED);
|
|
return MOD_CONT;
|
|
} else if (text == NULL) {
|
|
syntax_error(s_MemoServ, u, "SEND", MEMO_SEND_SYNTAX);
|
|
return MOD_CONT;
|
|
}
|
|
|
|
for (i = 0; i < 1024; i++) {
|
|
for (nc = nclists[i]; nc; nc = nc->next) {
|
|
if (nick_is_services_oper(nc))
|
|
memo_send(u, nc->display, text, z);
|
|
}
|
|
}
|
|
return MOD_CONT;
|
|
}
|
|
|
|
/*************************************************************************/
|
|
/**
|
|
* Send a memo to all registered nicks
|
|
* - Certus - 06/06/2003
|
|
**/
|
|
static int do_sendall(User * u)
|
|
{
|
|
int i, z = 1;
|
|
NickCore *nc;
|
|
char *text = strtok(NULL, "");
|
|
|
|
|
|
|
|
if (readonly) {
|
|
notice_lang(s_MemoServ, u, MEMO_SEND_DISABLED);
|
|
return MOD_CONT;
|
|
} else if (checkDefCon(DEFCON_NO_NEW_MEMOS)) {
|
|
notice_lang(s_MemoServ, u, OPER_DEFCON_DENIED);
|
|
return MOD_CONT;
|
|
} else if (!text) {
|
|
syntax_error(s_MemoServ, u, "SENDALL", MEMO_SEND_SYNTAX);
|
|
return MOD_CONT;
|
|
}
|
|
|
|
|
|
for (i = 0; i < 1024; i++) {
|
|
for (nc = nclists[i]; nc; nc = nc->next) {
|
|
if (stricmp(u->nick, nc->display) != 0)
|
|
memo_send(u, nc->display, text, z);
|
|
} /* /nc */
|
|
} /* /i */
|
|
|
|
notice_lang(s_MemoServ, u, MEMO_MASS_SENT);
|
|
return MOD_CONT;
|
|
}
|
|
|
|
/*************************************************************************/
|