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