Anope IRC Services  Version 1.8
os_sgline.c
Go to the documentation of this file.
1 /* OperServ core functions
2  *
3  * (C) 2003-2014 Anope Team
4  * Contact us at team@anope.org
5  *
6  * Please read COPYING and README for further details.
7  *
8  * Based on the original code of Epona by Lara.
9  * Based on the original code of Services by Andy Church.
10  *
11  *
12  */
13 /*************************************************************************/
14 
15 #include "module.h"
16 
17 static int sgline_view_callback(SList * slist, int number, void *item,
18  va_list args);
19 static int sgline_view(int number, SXLine * sx, User * u, int *sent_header);
20 static int sgline_list_callback(SList * slist, int number, void *item,
21  va_list args);
22 static int sgline_list(int number, SXLine * sx, User * u, int *sent_header);
23 static int do_sgline(User * u);
24 
25 static void myOperServHelp(User * u);
26 
33 int AnopeInit(int argc, char **argv)
34 {
35  Command *c;
36 
37  moduleAddAuthor("Anope");
38  moduleAddVersion(VERSION_STRING);
40 
42  OPER_HELP_SGLINE, -1, -1, -1, -1);
44 
46 
47  if (!ircd->sgline) {
48  return MOD_STOP;
49  }
50  return MOD_CONT;
51 }
52 
56 void AnopeFini(void)
57 {
58 
59 }
60 
61 
66 static void myOperServHelp(User * u)
67 {
68  if (is_services_oper(u)) {
69  notice_lang(s_OperServ, u, OPER_HELP_CMD_SGLINE);
70  }
71 }
72 
78 static int do_sgline(User * u)
79 {
80  char *cmd = strtok(NULL, " ");
81 
82  if (!cmd)
83  cmd = "";
84 
85  if (!stricmp(cmd, "ADD")) {
86  int deleted = 0;
87  char *expiry, *mask, *reason;
88  time_t expires, now = time(NULL);
89 
90  mask = strtok(NULL, ":");
91  if (mask && *mask == '+') {
92  expiry = mask;
93  mask = strchr(expiry, ' ');
94  if (mask) {
95  *mask = 0;
96  mask++;
97  }
98  } else {
99  expiry = NULL;
100  }
101 
102  expires = expiry ? dotime(expiry) : SGLineExpiry;
103  /* If the expiry given does not contain a final letter, it's in days,
104  * said the doc. Ah well.
105  */
106  if (expiry && isdigit(expiry[strlen(expiry) - 1]))
107  expires *= 86400;
108  /* Do not allow less than a minute expiry time */
109  if (expires != 0 && expires < 60) {
110  notice_lang(s_OperServ, u, BAD_EXPIRY_TIME);
111  return MOD_CONT;
112  } else if (expires > 0) {
113  expires += now;
114  }
115 
116  if (mask && (reason = strtok(NULL, ""))) {
117  /* Clean up the last character of the mask if it is a space
118  * See bug #761
119  */
120  size_t masklen = strlen(mask);
121  if (mask[masklen - 1] == ' ')
122  mask[masklen - 1] = '\0';
123 
124  /* We first do some sanity check on the proposed mask. */
125 
126  if (mask && strspn(mask, "*?") == strlen(mask)) {
127  notice_lang(s_OperServ, u, USERHOST_MASK_TOO_WIDE, mask);
128  return MOD_CONT;
129  }
130 
131  deleted = add_sgline(u, mask, u->nick, expires, reason);
132  if (deleted < 0)
133  return MOD_CONT;
134  else if (deleted)
135  notice_lang(s_OperServ, u, OPER_SGLINE_DELETED_SEVERAL,
136  deleted);
137  notice_lang(s_OperServ, u, OPER_SGLINE_ADDED, mask);
138 
139  if (WallOSSGLine) {
140  char buf[128];
141 
142  if (!expires) {
143  strcpy(buf, "does not expire");
144  } else {
145  int wall_expiry = expires - now;
146  char *s = NULL;
147 
148  if (wall_expiry >= 86400) {
149  wall_expiry /= 86400;
150  s = "day";
151  } else if (wall_expiry >= 3600) {
152  wall_expiry /= 3600;
153  s = "hour";
154  } else if (wall_expiry >= 60) {
155  wall_expiry /= 60;
156  s = "minute";
157  }
158 
159  snprintf(buf, sizeof(buf), "expires in %d %s%s",
160  wall_expiry, s,
161  (wall_expiry == 1) ? "" : "s");
162  }
163 
165  "%s added an SGLINE for %s (%s)", u->nick,
166  mask, buf);
167  }
168 
169  if (readonly)
170  notice_lang(s_OperServ, u, READ_ONLY_MODE);
171 
172  } else {
173  syntax_error(s_OperServ, u, "SGLINE", OPER_SGLINE_SYNTAX);
174  }
175 
176  } else if (!stricmp(cmd, "DEL")) {
177 
178  char *mask;
179  int res = 0;
180 
181  mask = strtok(NULL, "");
182 
183  if (!mask) {
184  syntax_error(s_OperServ, u, "SGLINE", OPER_SGLINE_SYNTAX);
185  return MOD_CONT;
186  }
187 
188  if (sglines.count == 0) {
189  notice_lang(s_OperServ, u, OPER_SGLINE_LIST_EMPTY);
190  return MOD_CONT;
191  }
192 
193  if (isdigit(*mask) && strspn(mask, "1234567890,-") == strlen(mask)) {
194  /* Deleting a range */
195  res = slist_delete_range(&sglines, mask, NULL);
196  if (res == 0) {
197  notice_lang(s_OperServ, u, OPER_SGLINE_NO_MATCH);
198  return MOD_CONT;
199  } else if (res == 1) {
200  notice_lang(s_OperServ, u, OPER_SGLINE_DELETED_ONE);
201  } else {
202  notice_lang(s_OperServ, u, OPER_SGLINE_DELETED_SEVERAL,
203  res);
204  }
205  } else {
206  if ((res = slist_indexof(&sglines, mask)) == -1) {
207  notice_lang(s_OperServ, u, OPER_SGLINE_NOT_FOUND, mask);
208  return MOD_CONT;
209  }
210 
211  slist_delete(&sglines, res);
212  notice_lang(s_OperServ, u, OPER_SGLINE_DELETED, mask);
213  }
214 
215  if (readonly)
216  notice_lang(s_OperServ, u, READ_ONLY_MODE);
217 
218  } else if (!stricmp(cmd, "LIST")) {
219  char *mask;
220  int res, sent_header = 0;
221 
222  if (sglines.count == 0) {
223  notice_lang(s_OperServ, u, OPER_SGLINE_LIST_EMPTY);
224  return MOD_CONT;
225  }
226 
227  mask = strtok(NULL, "");
228 
229  if (!mask || (isdigit(*mask)
230  && strspn(mask, "1234567890,-") == strlen(mask))) {
231  res =
233  &sent_header);
234  if (res == 0) {
235  notice_lang(s_OperServ, u, OPER_SGLINE_NO_MATCH);
236  return MOD_CONT;
237  }
238  } else {
239  int i;
240  char *amask;
241 
242  for (i = 0; i < sglines.count; i++) {
243  amask = ((SXLine *) sglines.list[i])->mask;
244  if (!stricmp(mask, amask)
245  || match_wild_nocase(mask, amask))
246  sgline_list(i + 1, sglines.list[i], u, &sent_header);
247  }
248 
249  if (!sent_header)
250  notice_lang(s_OperServ, u, OPER_SGLINE_NO_MATCH);
251  else {
252  notice_lang(s_OperServ, u, END_OF_ANY_LIST, "SGLine");
253  }
254  }
255  } else if (!stricmp(cmd, "VIEW")) {
256  char *mask;
257  int res, sent_header = 0;
258 
259  if (sglines.count == 0) {
260  notice_lang(s_OperServ, u, OPER_SGLINE_LIST_EMPTY);
261  return MOD_CONT;
262  }
263 
264  mask = strtok(NULL, "");
265 
266  if (!mask || (isdigit(*mask)
267  && strspn(mask, "1234567890,-") == strlen(mask))) {
268  res =
270  &sent_header);
271  if (res == 0) {
272  notice_lang(s_OperServ, u, OPER_SGLINE_NO_MATCH);
273  return MOD_CONT;
274  }
275  } else {
276  int i;
277  char *amask;
278 
279  for (i = 0; i < sglines.count; i++) {
280  amask = ((SXLine *) sglines.list[i])->mask;
281  if (!stricmp(mask, amask)
282  || match_wild_nocase(mask, amask))
283  sgline_view(i + 1, sglines.list[i], u, &sent_header);
284  }
285 
286  if (!sent_header)
287  notice_lang(s_OperServ, u, OPER_SGLINE_NO_MATCH);
288  }
289  } else if (!stricmp(cmd, "CLEAR")) {
290  slist_clear(&sglines, 1);
291  notice_lang(s_OperServ, u, OPER_SGLINE_CLEAR);
292  } else {
293  syntax_error(s_OperServ, u, "SGLINE", OPER_SGLINE_SYNTAX);
294  }
295  return MOD_CONT;
296 }
297 
298 /* Lists an SGLINE entry, prefixing it with the header if needed */
299 
300 static int sgline_view(int number, SXLine * sx, User * u, int *sent_header)
301 {
302  char timebuf[32], expirebuf[256];
303  struct tm tm;
304 
305  if (!sx)
306  return 0;
307 
308  if (!*sent_header) {
309  notice_lang(s_OperServ, u, OPER_SGLINE_VIEW_HEADER);
310  *sent_header = 1;
311  }
312 
313  tm = *localtime(&sx->seton);
314  strftime_lang(timebuf, sizeof(timebuf), u, STRFTIME_SHORT_DATE_FORMAT,
315  &tm);
316  expire_left(u->na, expirebuf, sizeof(expirebuf), sx->expires);
317  notice_lang(s_OperServ, u, OPER_SGLINE_VIEW_FORMAT, number, sx->mask,
318  sx->by, timebuf, expirebuf, sx->reason);
319 
320  return 1;
321 }
322 
323 /* Callback for enumeration purposes */
324 
325 static int sgline_view_callback(SList * slist, int number, void *item,
326  va_list args)
327 {
328  User *u = va_arg(args, User *);
329  int *sent_header = va_arg(args, int *);
330 
331  return sgline_view(number, item, u, sent_header);
332 }
333 
334 /* Lists an SGLINE entry, prefixing it with the header if needed */
335 
336 static int sgline_list(int number, SXLine * sx, User * u, int *sent_header)
337 {
338  if (!sx)
339  return 0;
340 
341  if (!*sent_header) {
342  notice_lang(s_OperServ, u, OPER_SGLINE_LIST_HEADER);
343  *sent_header = 1;
344  }
345 
346  notice_lang(s_OperServ, u, OPER_SGLINE_LIST_FORMAT, number, sx->mask,
347  sx->reason);
348 
349  return 1;
350 }
351 
352 /* Callback for enumeration purposes */
353 
354 static int sgline_list_callback(SList * slist, int number, void *item,
355  va_list args)
356 {
357  User *u = va_arg(args, User *);
358  int *sent_header = va_arg(args, int *);
359 
360  return sgline_list(number, item, u, sent_header);
361 }
E int add_sgline(User *u, char *mask, const char *by, const time_t expires, const char *reason)
Definition: operserv.c:973
E size_t strspn(const char *s, const char *accept)
Definition: compat.c:106
static int sgline_view(int number, SXLine *sx, User *u, int *sent_header)
Definition: os_sgline.c:300
E int readonly
Definition: extern.h:776
E int match_wild_nocase(const char *pattern, const char *str)
Definition: misc.c:268
char nick[NICKMAX]
Definition: services.h:875
E int snprintf(char *buf, size_t size, const char *fmt,...)
Definition: compat.c:37
time_t expires
Definition: services.h:1099
E int slist_delete_range(SList *slist, char *range, slist_delcheckcb_t cb,...)
Definition: slist.c:129
char * by
Definition: services.h:1096
E IRCDVar * ircd
Definition: extern.h:39
char * mask
Definition: services.h:1095
static int do_sgline(User *u)
Definition: os_sgline.c:78
E int dotime(const char *s)
Definition: misc.c:364
E int stricmp(const char *s1, const char *s2)
Definition: compat.c:58
E int slist_enum(SList *slist, char *range, slist_enumcb_t cb,...)
Definition: slist.c:203
static void myOperServHelp(User *u)
Definition: os_sgline.c:66
E char * expire_left(NickAlias *na, char *buf, int len, time_t expires)
Definition: misc.c:470
E SList sglines
Definition: extern.h:970
MDE void moduleAddAuthor(const char *author)
Definition: modules.c:1772
E int WallOSSGLine
Definition: extern.h:455
E void syntax_error(char *service, User *u, const char *command, int msgnum)
Definition: language.c:295
E void notice_lang(char *source, User *dest, int message,...)
Definition: send.c:169
MDE void moduleSetType(MODType type)
Definition: modules.c:818
E void slist_clear(SList *slist, int free)
Definition: slist.c:70
#define OPERSERV
Definition: modules.h:62
int AnopeInit(int argc, char **argv)
Definition: os_sgline.c:33
void ** list
Definition: slist.h:21
E char * s_OperServ
Definition: extern.h:289
time_t seton
Definition: services.h:1098
E int slist_delete(SList *slist, int index)
Definition: slist.c:97
#define MOD_STOP
Definition: modules.h:53
int16 count
Definition: slist.h:23
static int sgline_list(int number, SXLine *sx, User *u, int *sent_header)
Definition: os_sgline.c:336
MDE void moduleAddVersion(const char *version)
Definition: modules.c:1760
Command * c
Definition: ns_recover.c:17
E int slist_indexof(SList *slist, void *item)
Definition: slist.c:317
MDE void moduleSetOperHelp(void(*func)(User *u))
Definition: modules.c:2126
#define MOD_CONT
Definition: modules.h:54
static int sgline_list_callback(SList *slist, int number, void *item, va_list args)
Definition: os_sgline.c:354
static int sgline_view_callback(SList *slist, int number, void *item, va_list args)
Definition: os_sgline.c:325
Definition: modules.h:99
Definition: slist.h:20
MDE Command * createCommand(const char *name, int(*func)(User *u), int(*has_priv)(User *u), int help_all, int help_reg, int help_oper, int help_admin, int help_root)
Definition: modules.c:987
E int is_services_oper(User *u)
Definition: operserv.c:606
void AnopeFini(void)
Definition: os_sgline.c:56
E int strftime_lang(char *buf, int size, User *u, int format, struct tm *tm)
Definition: language.c:240
int sgline
Definition: services.h:313
MDE int moduleAddCommand(CommandHash *cmdTable[], Command *c, int pos)
Definition: modules.c:1082
char * reason
Definition: services.h:1097
E int SGLineExpiry
Definition: extern.h:441
NickAlias * na
Definition: services.h:892
#define MOD_UNIQUE
Definition: module.h:11
E void anope_cmd_global(char *source, const char *fmt,...)
Definition: ircd.c:506