Anope IRC Services  Version 1.8
os_szline.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 do_szline(User * u);
18 static void myOperServHelp(User * u);
19 static int szline_view_callback(SList * slist, int number, void *item,
20  va_list args);
21 static int szline_list_callback(SList * slist, int number, void *item,
22  va_list args);
23 static int szline_view(int number, SXLine * sx, User * u, int *sent_header);
24 static int szline_list(int number, SXLine * sx, User * u, int *sent_header);
25 
32 int AnopeInit(int argc, char **argv)
33 {
34  Command *c;
35 
36  moduleAddAuthor("Anope");
37  moduleAddVersion(VERSION_STRING);
39 
41  OPER_HELP_SZLINE, -1, -1, -1, -1);
43 
45  if (!ircd->szline) {
46  return MOD_STOP;
47  }
48  return MOD_CONT;
49 }
50 
54 void AnopeFini(void)
55 {
56 
57 }
58 
59 
64 static void myOperServHelp(User * u)
65 {
66  if (is_services_oper(u)) {
67  notice_lang(s_OperServ, u, OPER_HELP_CMD_SZLINE);
68  }
69 }
70 
76 static int do_szline(User * u)
77 {
78  char *cmd = strtok(NULL, " ");
79 
80  if (!cmd)
81  cmd = "";
82 
83  if (!stricmp(cmd, "ADD")) {
84  int deleted = 0;
85  char *expiry, *mask, *reason;
86  time_t expires, now = time(NULL);
87 
88  mask = strtok(NULL, " ");
89  if (mask && *mask == '+') {
90  expiry = mask;
91  mask = strtok(NULL, " ");
92  } else {
93  expiry = NULL;
94  }
95 
96  expires = expiry ? dotime(expiry) : SZLineExpiry;
97  /* If the expiry given does not contain a final letter, it's in days,
98  * said the doc. Ah well.
99  */
100  if (expiry && isdigit(expiry[strlen(expiry) - 1]))
101  expires *= 86400;
102  /* Do not allow less than a minute expiry time */
103  if (expires != 0 && expires < 60) {
104  notice_lang(s_OperServ, u, BAD_EXPIRY_TIME);
105  return MOD_CONT;
106  } else if (expires > 0) {
107  expires += time(NULL);
108  }
109 
110  if (mask && (reason = strtok(NULL, ""))) {
111  /* We first do some sanity check on the proposed mask. */
112 
113  if (strchr(mask, '!') || strchr(mask, '@')) {
114  notice_lang(s_OperServ, u, OPER_SZLINE_ONLY_IPS);
115  return MOD_CONT;
116  }
117 
118  if (strspn(mask, "*?") == strlen(mask)) {
119  notice_lang(s_OperServ, u, USERHOST_MASK_TOO_WIDE, mask);
120  return MOD_CONT;
121  }
122 
123  deleted = add_szline(u, mask, u->nick, expires, reason);
124  if (deleted < 0)
125  return MOD_CONT;
126  else if (deleted)
127  notice_lang(s_OperServ, u, OPER_SZLINE_DELETED_SEVERAL,
128  deleted);
129  notice_lang(s_OperServ, u, OPER_SZLINE_ADDED, mask);
130 
131  if (WallOSSZLine) {
132  char buf[128];
133 
134  if (!expires) {
135  strcpy(buf, "does not expire");
136  } else {
137  int wall_expiry = expires - now;
138  char *s = NULL;
139 
140  if (wall_expiry >= 86400) {
141  wall_expiry /= 86400;
142  s = "day";
143  } else if (wall_expiry >= 3600) {
144  wall_expiry /= 3600;
145  s = "hour";
146  } else if (wall_expiry >= 60) {
147  wall_expiry /= 60;
148  s = "minute";
149  }
150 
151  snprintf(buf, sizeof(buf), "expires in %d %s%s",
152  wall_expiry, s,
153  (wall_expiry == 1) ? "" : "s");
154  }
155 
157  "%s added an SZLINE for %s (%s)", u->nick,
158  mask, buf);
159  }
160 
161  if (readonly)
162  notice_lang(s_OperServ, u, READ_ONLY_MODE);
163 
164  } else {
165  syntax_error(s_OperServ, u, "SZLINE", OPER_SZLINE_SYNTAX);
166  }
167 
168  } else if (!stricmp(cmd, "DEL")) {
169 
170  char *mask;
171  int res = 0;
172 
173  mask = strtok(NULL, " ");
174 
175  if (!mask) {
176  syntax_error(s_OperServ, u, "SZLINE", OPER_SZLINE_SYNTAX);
177  return MOD_CONT;
178  }
179 
180  if (szlines.count == 0) {
181  notice_lang(s_OperServ, u, OPER_SZLINE_LIST_EMPTY);
182  return MOD_CONT;
183  }
184 
185  if (isdigit(*mask) && strspn(mask, "1234567890,-") == strlen(mask)) {
186  /* Deleting a range */
187  res = slist_delete_range(&szlines, mask, NULL);
188  if (res == 0) {
189  notice_lang(s_OperServ, u, OPER_SZLINE_NO_MATCH);
190  return MOD_CONT;
191  } else if (res == 1) {
192  notice_lang(s_OperServ, u, OPER_SZLINE_DELETED_ONE);
193  } else {
194  notice_lang(s_OperServ, u, OPER_SZLINE_DELETED_SEVERAL,
195  res);
196  }
197  } else {
198  if ((res = slist_indexof(&szlines, mask)) == -1) {
199  notice_lang(s_OperServ, u, OPER_SZLINE_NOT_FOUND, mask);
200  return MOD_CONT;
201  }
202 
203  slist_delete(&szlines, res);
204  notice_lang(s_OperServ, u, OPER_SZLINE_DELETED, mask);
205  }
206 
207  if (readonly)
208  notice_lang(s_OperServ, u, READ_ONLY_MODE);
209 
210  } else if (!stricmp(cmd, "LIST")) {
211  char *mask;
212  int res, sent_header = 0;
213 
214  if (szlines.count == 0) {
215  notice_lang(s_OperServ, u, OPER_SZLINE_LIST_EMPTY);
216  return MOD_CONT;
217  }
218 
219  mask = strtok(NULL, " ");
220 
221  if (!mask || (isdigit(*mask)
222  && strspn(mask, "1234567890,-") == strlen(mask))) {
223  res =
225  &sent_header);
226  if (res == 0) {
227  notice_lang(s_OperServ, u, OPER_SZLINE_NO_MATCH);
228  return MOD_CONT;
229  }
230  } else {
231  int i;
232  char *amask;
233 
234  for (i = 0; i < szlines.count; i++) {
235  amask = ((SXLine *) szlines.list[i])->mask;
236  if (!stricmp(mask, amask)
237  || match_wild_nocase(mask, amask))
238  szline_list(i + 1, szlines.list[i], u, &sent_header);
239  }
240 
241  if (!sent_header)
242  notice_lang(s_OperServ, u, OPER_SZLINE_NO_MATCH);
243  }
244  } else if (!stricmp(cmd, "VIEW")) {
245  char *mask;
246  int res, sent_header = 0;
247 
248  if (szlines.count == 0) {
249  notice_lang(s_OperServ, u, OPER_SZLINE_LIST_EMPTY);
250  return MOD_CONT;
251  }
252 
253  mask = strtok(NULL, " ");
254 
255  if (!mask || (isdigit(*mask)
256  && strspn(mask, "1234567890,-") == strlen(mask))) {
257  res =
259  &sent_header);
260  if (res == 0) {
261  notice_lang(s_OperServ, u, OPER_SZLINE_NO_MATCH);
262  return MOD_CONT;
263  }
264  } else {
265  int i;
266  char *amask;
267 
268  for (i = 0; i < szlines.count; i++) {
269  amask = ((SXLine *) szlines.list[i])->mask;
270  if (!stricmp(mask, amask)
271  || match_wild_nocase(mask, amask))
272  szline_view(i + 1, szlines.list[i], u, &sent_header);
273  }
274 
275  if (!sent_header)
276  notice_lang(s_OperServ, u, OPER_SZLINE_NO_MATCH);
277  }
278  } else if (!stricmp(cmd, "CLEAR")) {
279  slist_clear(&szlines, 1);
280  notice_lang(s_OperServ, u, OPER_SZLINE_CLEAR);
281  } else {
282  syntax_error(s_OperServ, u, "SZLINE", OPER_SZLINE_SYNTAX);
283  }
284  return MOD_CONT;
285 }
286 
287 
288 static int szline_view(int number, SXLine * sx, User * u, int *sent_header)
289 {
290  char timebuf[32], expirebuf[256];
291  struct tm tm;
292 
293  if (!sx)
294  return 0;
295 
296  if (!*sent_header) {
297  notice_lang(s_OperServ, u, OPER_SZLINE_VIEW_HEADER);
298  *sent_header = 1;
299  }
300 
301  tm = *localtime(&sx->seton);
302  strftime_lang(timebuf, sizeof(timebuf), u, STRFTIME_SHORT_DATE_FORMAT,
303  &tm);
304  expire_left(u->na, expirebuf, sizeof(expirebuf), sx->expires);
305  notice_lang(s_OperServ, u, OPER_SZLINE_VIEW_FORMAT, number, sx->mask,
306  sx->by, timebuf, expirebuf, sx->reason);
307 
308  return 1;
309 }
310 
311 /* Callback for enumeration purposes */
312 
313 static int szline_view_callback(SList * slist, int number, void *item,
314  va_list args)
315 {
316  User *u = va_arg(args, User *);
317  int *sent_header = va_arg(args, int *);
318 
319  return szline_view(number, item, u, sent_header);
320 }
321 
322 /* Callback for enumeration purposes */
323 
324 static int szline_list_callback(SList * slist, int number, void *item,
325  va_list args)
326 {
327  User *u = va_arg(args, User *);
328  int *sent_header = va_arg(args, int *);
329 
330  return szline_list(number, item, u, sent_header);
331 }
332 
333 /* Lists an SZLINE entry, prefixing it with the header if needed */
334 
335 static int szline_list(int number, SXLine * sx, User * u, int *sent_header)
336 {
337  if (!sx)
338  return 0;
339 
340  if (!*sent_header) {
341  notice_lang(s_OperServ, u, OPER_SZLINE_LIST_HEADER);
342  *sent_header = 1;
343  }
344 
345  notice_lang(s_OperServ, u, OPER_SZLINE_LIST_FORMAT, number, sx->mask,
346  sx->reason);
347 
348  return 1;
349 }
E size_t strspn(const char *s, const char *accept)
Definition: compat.c:106
static int do_szline(User *u)
Definition: os_szline.c:76
E int readonly
Definition: extern.h:776
E int match_wild_nocase(const char *pattern, const char *str)
Definition: misc.c:268
static int szline_list_callback(SList *slist, int number, void *item, va_list args)
Definition: os_szline.c:324
char nick[NICKMAX]
Definition: services.h:875
E int snprintf(char *buf, size_t size, const char *fmt,...)
Definition: compat.c:37
E int SZLineExpiry
Definition: extern.h:443
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
E int dotime(const char *s)
Definition: misc.c:364
E int stricmp(const char *s1, const char *s2)
Definition: compat.c:58
static int szline_list(int number, SXLine *sx, User *u, int *sent_header)
Definition: os_szline.c:335
E int slist_enum(SList *slist, char *range, slist_enumcb_t cb,...)
Definition: slist.c:203
E char * expire_left(NickAlias *na, char *buf, int len, time_t expires)
Definition: misc.c:470
int szline
Definition: services.h:315
void AnopeFini(void)
Definition: os_szline.c:54
MDE void moduleAddAuthor(const char *author)
Definition: modules.c:1772
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
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
int AnopeInit(int argc, char **argv)
Definition: os_szline.c:32
MDE void moduleAddVersion(const char *version)
Definition: modules.c:1760
E int add_szline(User *u, char *mask, const char *by, const time_t expires, const char *reason)
Definition: operserv.c:1380
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 void myOperServHelp(User *u)
Definition: os_szline.c:64
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
static int szline_view(int number, SXLine *sx, User *u, int *sent_header)
Definition: os_szline.c:288
E SList szlines
Definition: extern.h:970
E int is_services_oper(User *u)
Definition: operserv.c:606
E int strftime_lang(char *buf, int size, User *u, int format, struct tm *tm)
Definition: language.c:240
MDE int moduleAddCommand(CommandHash *cmdTable[], Command *c, int pos)
Definition: modules.c:1082
static int szline_view_callback(SList *slist, int number, void *item, va_list args)
Definition: os_szline.c:313
char * reason
Definition: services.h:1097
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
E int WallOSSZLine
Definition: extern.h:457