tcluser.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. /*
  2. * tcluser.c -- handles:
  3. * Tcl stubs for the user-record-oriented commands
  4. *
  5. */
  6. #include "main.h"
  7. #include "users.h"
  8. #include "chan.h"
  9. #include "tandem.h"
  10. #include "modules.h"
  11. extern Tcl_Interp *interp;
  12. extern struct userrec *userlist;
  13. extern int default_flags, dcc_total, ignore_time;
  14. extern struct dcc_t *dcc;
  15. extern char origbotname[], botnetnick[];
  16. extern time_t now;
  17. static int tcl_chattr STDVAR
  18. {
  19. char *chan, *chg, work[100];
  20. struct flag_record pls, mns, user;
  21. struct userrec *u;
  22. BADARGS(2, 4, " handle ?changes? ?channel?");
  23. if ((argv[1][0] == '*') || !(u = get_user_by_handle(userlist, argv[1]))) {
  24. Tcl_AppendResult(irp, "*", NULL);
  25. return TCL_OK;
  26. }
  27. if (argc == 4) {
  28. user.match = FR_GLOBAL | FR_CHAN;
  29. chan = argv[3];
  30. chg = argv[2];
  31. } else if (argc == 3 && argv[2][0]) {
  32. int ischan = (findchan_by_dname(argv[2]) != NULL);
  33. if (strchr(CHANMETA, argv[2][0]) && !ischan && argv[2][0] != '+' && argv[2][0] != '-') {
  34. Tcl_AppendResult(irp, "no such channel", NULL);
  35. return TCL_ERROR;
  36. } else if (ischan) {
  37. /* Channel exists */
  38. user.match = FR_GLOBAL | FR_CHAN;
  39. chan = argv[2];
  40. chg = NULL;
  41. } else {
  42. /* 3rd possibility... channel doesnt exist, does start with a +.
  43. * In this case we assume the string is flags.
  44. */
  45. user.match = FR_GLOBAL;
  46. chan = NULL;
  47. chg = argv[2];
  48. }
  49. } else {
  50. user.match = FR_GLOBAL;
  51. chan = NULL;
  52. chg = NULL;
  53. }
  54. if (chan && !findchan_by_dname(chan)) {
  55. Tcl_AppendResult(irp, "no such channel", NULL);
  56. return TCL_ERROR;
  57. }
  58. get_user_flagrec(u, &user, chan);
  59. /* Make changes */
  60. if (chg) {
  61. pls.match = user.match;
  62. break_down_flags(chg, &pls, &mns);
  63. /* No-one can change these flags on-the-fly */
  64. pls.global &=~(USER_BOT);
  65. mns.global &=~(USER_BOT);
  66. if (chan) {
  67. pls.chan &= ~(BOT_SHARE);
  68. mns.chan &= ~(BOT_SHARE);
  69. }
  70. user.global = sanity_check((user.global |pls.global) &~mns.global);
  71. user.udef_global = (user.udef_global | pls.udef_global)
  72. & ~mns.udef_global;
  73. if (chan) {
  74. user.chan = chan_sanity_check((user.chan | pls.chan) & ~mns.chan,
  75. user.global);
  76. user.udef_chan = (user.udef_chan | pls.udef_chan) & ~mns.udef_chan;
  77. }
  78. set_user_flagrec(u, &user, chan);
  79. }
  80. /* Retrieve current flags and return them */
  81. build_flags(work, &user, NULL);
  82. Tcl_AppendResult(irp, work, NULL);
  83. return TCL_OK;
  84. }
  85. static int tcl_adduser STDVAR
  86. {
  87. BADARGS(2, 3, " handle ?hostmask?");
  88. if (strlen(argv[1]) > HANDLEN)
  89. argv[1][HANDLEN] = 0;
  90. if ((argv[1][0] == '*') || get_user_by_handle(userlist, argv[1]))
  91. Tcl_AppendResult(irp, "0", NULL);
  92. else {
  93. userlist = adduser(userlist, argv[1], argv[2], "-", default_flags);
  94. Tcl_AppendResult(irp, "1", NULL);
  95. }
  96. return TCL_OK;
  97. }
  98. static int tcl_deluser STDVAR
  99. {
  100. BADARGS(2, 2, " handle");
  101. Tcl_AppendResult(irp, (argv[1][0] == '*') ? "0" :
  102. int_to_base10(deluser(argv[1])), NULL);
  103. return TCL_OK;
  104. }
  105. static int tcl_delhost STDVAR
  106. {
  107. BADARGS(3, 3, " handle hostmask");
  108. if ((!get_user_by_handle(userlist, argv[1])) || (argv[1][0] == '*')) {
  109. Tcl_AppendResult(irp, "non-existent user", NULL);
  110. return TCL_ERROR;
  111. }
  112. Tcl_AppendResult(irp, delhost_by_handle(argv[1], argv[2]) ? "1" : "0",
  113. NULL);
  114. return TCL_OK;
  115. }
  116. static int tcl_userlist STDVAR
  117. {
  118. struct userrec *u;
  119. struct flag_record user, plus, minus;
  120. int ok = 1, f = 0;
  121. BADARGS(1, 3, " ?flags ?channel??");
  122. if (argc == 3 && !findchan_by_dname(argv[2])) {
  123. Tcl_AppendResult(irp, "Invalid channel: ", argv[2], NULL);
  124. return TCL_ERROR;
  125. }
  126. if (argc >= 2) {
  127. plus.match = FR_GLOBAL | FR_CHAN | FR_BOT;
  128. break_down_flags(argv[1], &plus, &minus);
  129. f = (minus.global || minus.udef_global || minus.chan ||
  130. minus.udef_chan || minus.bot);
  131. }
  132. minus.match = plus.match ^ (FR_AND | FR_OR);
  133. for (u = userlist; u; u = u->next) {
  134. if (argc >= 2) {
  135. user.match = FR_GLOBAL | FR_CHAN | FR_BOT | (argc == 3 ? 0 : FR_ANYWH);
  136. if (argc == 3)
  137. get_user_flagrec(u, &user, argv[2]);
  138. else
  139. get_user_flagrec(u, &user, NULL);
  140. if (flagrec_eq(&plus, &user) && !(f && flagrec_eq(&minus, &user)))
  141. ok = 1;
  142. else
  143. ok = 0;
  144. }
  145. if (ok)
  146. Tcl_AppendElement(interp, u->handle);
  147. }
  148. return TCL_OK;
  149. }
  150. #ifdef HUB
  151. static int tcl_save STDVAR
  152. {
  153. write_userfile(-1);
  154. return TCL_OK;
  155. }
  156. static int tcl_reload STDVAR
  157. {
  158. reload();
  159. return TCL_OK;
  160. }
  161. #endif /* HUB */
  162. static int tcl_chhandle STDVAR
  163. {
  164. struct userrec *u;
  165. char newhand[HANDLEN + 1];
  166. int x = 1, i;
  167. BADARGS(3, 3, " oldnick newnick");
  168. u = get_user_by_handle(userlist, argv[1]);
  169. if (!u)
  170. x = 0;
  171. else {
  172. strncpyz(newhand, argv[2], sizeof newhand);
  173. for (i = 0; i < strlen(newhand); i++)
  174. if ((newhand[i] <= 32) || (newhand[i] >= 127) || (newhand[i] == '@'))
  175. newhand[i] = '?';
  176. if (strchr(BADHANDCHARS, newhand[0]) != NULL)
  177. x = 0;
  178. else if (strlen(newhand) < 1)
  179. x = 0;
  180. else if (get_user_by_handle(userlist, newhand))
  181. x = 0;
  182. else if (!egg_strcasecmp(botnetnick, newhand) &&
  183. (!(u->flags & USER_BOT) || nextbot (argv [1]) != -1))
  184. x = 0;
  185. else if (newhand[0] == '*')
  186. x = 0;
  187. }
  188. if (x)
  189. x = change_handle(u, newhand);
  190. Tcl_AppendResult(irp, x ? "1" : "0", NULL);
  191. return TCL_OK;
  192. }
  193. static int tcl_getting_users STDVAR
  194. {
  195. int i;
  196. BADARGS(1, 1, "");
  197. for (i = 0; i < dcc_total; i++) {
  198. if (dcc[i].type == &DCC_BOT && dcc[i].status & STAT_GETTING) {
  199. Tcl_AppendResult(irp, "1", NULL);
  200. return TCL_OK;
  201. }
  202. }
  203. Tcl_AppendResult(irp, "0", NULL);
  204. return TCL_OK;
  205. }
  206. static int tcl_isignore STDVAR
  207. {
  208. BADARGS(2, 2, " nick!user@host");
  209. Tcl_AppendResult(irp, match_ignore(argv[1]) ? "1" : "0", NULL);
  210. return TCL_OK;
  211. }
  212. static int tcl_newignore STDVAR
  213. {
  214. time_t expire_time;
  215. char ign[UHOSTLEN], cmt[66], from[HANDLEN + 1];
  216. BADARGS(4, 5, " hostmask creator comment ?lifetime?");
  217. strncpyz(ign, argv[1], sizeof ign);
  218. strncpyz(from, argv[2], sizeof from);
  219. strncpyz(cmt, argv[3], sizeof cmt);
  220. if (argc == 4)
  221. expire_time = now + (60 * ignore_time);
  222. else {
  223. if (argc == 5 && atol(argv[4]) == 0)
  224. expire_time = 0L;
  225. else
  226. expire_time = now + (60 * atol(argv[4])); /* This is a potential crash. FIXME -poptix */
  227. }
  228. addignore(ign, from, cmt, expire_time);
  229. return TCL_OK;
  230. }
  231. static int tcl_killignore STDVAR
  232. {
  233. BADARGS(2, 2, " hostmask");
  234. Tcl_AppendResult(irp, delignore(argv[1]) ? "1" : "0", NULL);
  235. return TCL_OK;
  236. }
  237. /* { hostmask note expire-time create-time creator }
  238. */
  239. static int tcl_ignorelist STDVAR
  240. {
  241. struct igrec *i;
  242. char expire[11], added[11], *p;
  243. #if (((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4)) || (TCL_MAJOR_VERSION > 8))
  244. CONST char *list[5];
  245. #else
  246. char *list[5];
  247. #endif
  248. BADARGS(1, 1, "");
  249. for (i = global_ign; i; i = i->next) {
  250. list[0] = i->igmask;
  251. list[1] = i->msg;
  252. egg_snprintf(expire, sizeof expire, "%lu", i->expire);
  253. list[2] = expire;
  254. egg_snprintf(added, sizeof added, "%lu", i->added);
  255. list[3] = added;
  256. list[4] = i->user;
  257. p = Tcl_Merge(5, list);
  258. Tcl_AppendElement(irp, p);
  259. Tcl_Free((char *) p);
  260. }
  261. return TCL_OK;
  262. }
  263. static int tcl_getuser STDVAR
  264. {
  265. struct user_entry_type *et;
  266. struct userrec *u;
  267. struct user_entry *e;
  268. BADARGS(3, 999, " handle type");
  269. if (!(et = find_entry_type(argv[2])) && egg_strcasecmp(argv[2], "HANDLE")) {
  270. Tcl_AppendResult(irp, "No such info type: ", argv[2], NULL);
  271. return TCL_ERROR;
  272. }
  273. if (!(u = get_user_by_handle(userlist, argv[1]))) {
  274. if (argv[1][0] != '*') {
  275. Tcl_AppendResult(irp, "No such user.", NULL);
  276. return TCL_ERROR;
  277. } else
  278. return TCL_OK; /* silently ignore user * */
  279. }
  280. if (!egg_strcasecmp(argv[2], "HANDLE")) {
  281. Tcl_AppendResult(irp,u->handle, NULL);
  282. } else {
  283. e = find_user_entry(et, u);
  284. if (e)
  285. return et->tcl_get(irp, u, e, argc, argv);
  286. }
  287. return TCL_OK;
  288. }
  289. static int tcl_setuser STDVAR
  290. {
  291. struct user_entry_type *et;
  292. struct userrec *u;
  293. struct user_entry *e;
  294. int r;
  295. module_entry *me;
  296. BADARGS(3, 999, " handle type ?setting....?");
  297. if (!(et = find_entry_type(argv[2]))) {
  298. Tcl_AppendResult(irp, "No such info type: ", argv[2], NULL);
  299. return TCL_ERROR;
  300. }
  301. if (!(u = get_user_by_handle(userlist, argv[1]))) {
  302. if (argv[1][0] != '*') {
  303. Tcl_AppendResult(irp, "No such user.", NULL);
  304. return TCL_ERROR;
  305. } else
  306. return TCL_OK; /* Silently ignore user * */
  307. }
  308. me = module_find("irc", 0, 0);
  309. if (me && !strcmp(argv[2], "hosts") && argc == 3) {
  310. Function *func = me->funcs;
  311. (func[IRC_CHECK_THIS_USER]) (argv[1], 1, NULL);
  312. }
  313. if (!(e = find_user_entry(et, u))) {
  314. e = user_malloc(sizeof(struct user_entry));
  315. e->type = et;
  316. e->name = NULL;
  317. e->u.list = NULL;
  318. list_insert((&(u->entries)), e);
  319. }
  320. r = et->tcl_set(irp, u, e, argc, argv);
  321. /* Yeah... e is freed, and we read it... (tcl: setuser hand HOSTS none) */
  322. if (!e->u.list) {
  323. if (list_delete((struct list_type **) &(u->entries),
  324. (struct list_type *) e))
  325. nfree(e);
  326. /* else maybe already freed... (entry_type==HOSTS) <drummer> */
  327. }
  328. if (me && !strcmp(argv[2], "hosts") && argc == 4) {
  329. Function *func = me->funcs;
  330. (func[IRC_CHECK_THIS_USER]) (argv[1], 0, NULL);
  331. }
  332. return r;
  333. }
  334. tcl_cmds tcluser_cmds[] =
  335. {
  336. {"chattr", tcl_chattr},
  337. {"adduser", tcl_adduser},
  338. {"deluser", tcl_deluser},
  339. {"delhost", tcl_delhost},
  340. {"userlist", tcl_userlist},
  341. #ifdef HUB
  342. {"save", tcl_save},
  343. {"reload", tcl_reload},
  344. #endif /* HUB */
  345. {"chhandle", tcl_chhandle},
  346. {"chnick", tcl_chhandle},
  347. {"getting-users", tcl_getting_users},
  348. {"isignore", tcl_isignore},
  349. {"newignore", tcl_newignore},
  350. {"killignore", tcl_killignore},
  351. {"ignorelist", tcl_ignorelist},
  352. {"getuser", tcl_getuser},
  353. {"setuser", tcl_setuser},
  354. {NULL, NULL}
  355. };