chanmisc.c 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217
  1. /*
  2. * Copyright (C) 1997 Robey Pointer
  3. * Copyright (C) 1999 - 2002 Eggheads Development Team
  4. * Copyright (C) 2002 - 2014 Bryan Drewery
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version 2
  9. * of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  19. */
  20. /*
  21. * tclchan.c -- part of channels.mod
  22. *
  23. */
  24. static int FindElement(char *resultBuf, const char *list, size_t listLength,
  25. const char **elementPtr, const char **nextPtr,
  26. size_t *sizePtr, int *bracePtr)
  27. {
  28. const char *p = list;
  29. const char *elemStart = NULL; /* Points to first byte of first element. */
  30. const char *limit = (list + listLength); /* Points just after list's last byte. */
  31. int openBraces = 0; /* Brace nesting level during parse. */
  32. int inQuotes = 0;
  33. size_t size = 0; /* lint. */
  34. const char *p2 = NULL;
  35. /*
  36. * Skim off leading white space and check for an opening brace or
  37. * quote. We treat embedded NULLs in the list as bytes belonging to
  38. * a list element.
  39. */
  40. while ((p < limit) && egg_isspace(*p)) { /* INTL: ISO space. */
  41. p++;
  42. }
  43. if (p == limit) { /* no element found */
  44. elemStart = limit;
  45. goto done;
  46. }
  47. if (*p == '{') {
  48. openBraces = 1;
  49. p++;
  50. } else if (*p == '"') {
  51. inQuotes = 1;
  52. p++;
  53. }
  54. elemStart = p;
  55. if (bracePtr != 0) {
  56. *bracePtr = openBraces;
  57. }
  58. /*
  59. * Find element's end (a space, close brace, or the end of the string).
  60. */
  61. while (p < limit) {
  62. switch (*p) {
  63. /*
  64. * Open brace: don't treat specially unless the element is in
  65. * braces. In this case, keep a nesting count.
  66. */
  67. case '{':
  68. if (openBraces != 0) {
  69. openBraces++;
  70. }
  71. break;
  72. /*
  73. * Close brace: if element is in braces, keep nesting count and
  74. * quit when the last close brace is seen.
  75. */
  76. case '}':
  77. if (openBraces > 1) {
  78. openBraces--;
  79. } else if (openBraces == 1) {
  80. size = (p - elemStart);
  81. p++;
  82. if ((p >= limit) || egg_isspace(*p)) { /* INTL: ISO space. */
  83. goto done;
  84. }
  85. /*
  86. * Garbage after the closing brace; return an error.
  87. */
  88. if (resultBuf) {
  89. p2 = p;
  90. while ((p2 < limit)
  91. && (!egg_isspace(*p2)) /* INTL: ISO space. */
  92. && (p2 < p+20)) {
  93. p2++;
  94. }
  95. // snprintf(resultBuf, RESULT_LEN, "list element in braces followed by \"%.*s\" instead of space", (int) (p2-p), p);
  96. }
  97. return ERROR;
  98. }
  99. break;
  100. /*
  101. * Backslash: skip over everything up to the end of the
  102. * backslash sequence.
  103. */
  104. /* case '\\': {
  105. Tcl_UtfBackslash(p, &numChars, NULL);
  106. p += (numChars - 1);
  107. break;
  108. }
  109. */
  110. /*
  111. * Space: ignore if element is in braces or quotes; otherwise
  112. * terminate element.
  113. */
  114. case ' ':
  115. case '\f':
  116. case '\n':
  117. case '\r':
  118. case '\t':
  119. case '\v':
  120. if ((openBraces == 0) && !inQuotes) {
  121. size = (p - elemStart);
  122. goto done;
  123. }
  124. break;
  125. /*
  126. * Double-quote: if element is in quotes then terminate it.
  127. */
  128. case '"':
  129. if (inQuotes) {
  130. size = (p - elemStart);
  131. p++;
  132. if ((p >= limit) || egg_isspace(*p)) { /* INTL: ISO space */
  133. goto done;
  134. }
  135. /*
  136. * Garbage after the closing quote; return an error.
  137. */
  138. if (resultBuf) {
  139. p2 = p;
  140. while ((p2 < limit)
  141. && (!egg_isspace(*p2)) /* INTL: ISO space */
  142. && (p2 < p+20)) {
  143. p2++;
  144. }
  145. // sprintf(resultBuf, "list element in quotes followed by \"%.*s\" %s", (int) (p2-p), p, "instead of space");
  146. }
  147. return ERROR;
  148. }
  149. break;
  150. }
  151. p++;
  152. }
  153. /*
  154. * End of list: terminate element.
  155. */
  156. if (p == limit) {
  157. if (openBraces != 0) {
  158. if (resultBuf) {
  159. simple_snprintf(resultBuf, RESULT_LEN, "unmatched open brace in list");
  160. }
  161. return ERROR;
  162. } else if (inQuotes) {
  163. if (resultBuf) {
  164. simple_snprintf(resultBuf, RESULT_LEN, "unmatched open quote in list");
  165. }
  166. return ERROR;
  167. }
  168. size = (p - elemStart);
  169. }
  170. done:
  171. while ((p < limit) && (egg_isspace(*p))) { /* INTL: ISO space. */
  172. p++;
  173. }
  174. *elementPtr = elemStart;
  175. *nextPtr = p;
  176. if (sizePtr != 0) {
  177. *sizePtr = size;
  178. }
  179. return OK;
  180. }
  181. /* unneeded?
  182. int CopyAndCollapse(int count, const char *src, char *dst)
  183. {
  184. register char c;
  185. int numRead;
  186. int newCount = 0;
  187. int backslashCount;
  188. for (c = *src; count > 0; src++, c = *src, count--) {
  189. if (c == '\\') {
  190. backslashCount = Tcl_UtfBackslash(src, &numRead, dst);
  191. dst += backslashCount;
  192. newCount += backslashCount;
  193. src += numRead-1;
  194. count -= numRead-1;
  195. } else {
  196. *dst = c;
  197. dst++;
  198. newCount++;
  199. }
  200. }
  201. *dst = 0;
  202. return newCount;
  203. }
  204. */
  205. int SplitList(char *resultBuf, const char *list, int *argcPtr, const char ***argvPtr)
  206. {
  207. const char **argv = NULL;
  208. const char *l = NULL;
  209. const char *element = NULL;
  210. char *p = NULL;
  211. int result, brace = 0;
  212. size_t size = 2; /* initialized to 1 for NULL pointer */
  213. size_t length, elSize, i = 0;
  214. /*
  215. * Figure out how much space to allocate. There must be enough
  216. * space for both the array of pointers and also for a copy of
  217. * the list. To estimate the number of pointers needed, count
  218. * the number of space characters in the list.
  219. */
  220. for (l = list; *l != 0; l++) {
  221. if (egg_isspace(*l)) { /* INTL: ISO space. */
  222. size++;
  223. }
  224. }
  225. argv = (const char **) my_calloc(1, (unsigned) ((size * sizeof(char *)) + (l - list) + 1 + 15)); /* 15 cuz the tcl src is hard to follow */
  226. length = strlen(list);
  227. for (p = ((char *) argv) + size*sizeof(char *); *list != 0; i++) {
  228. const char *prevList = list;
  229. result = FindElement(resultBuf, list, length, &element, &list, &elSize, &brace);
  230. length -= (list - prevList);
  231. if (result != OK) {
  232. free((char *) argv);
  233. return result;
  234. }
  235. if (*element == 0) {
  236. break;
  237. }
  238. if (i >= size) {
  239. free((char *) argv);
  240. if (resultBuf)
  241. strlcpy(resultBuf, "internal error in SplitList", RESULT_LEN);
  242. return ERROR;
  243. }
  244. argv[i] = p;
  245. if (brace) {
  246. memcpy(p, element, elSize);
  247. p += elSize;
  248. *p = 0;
  249. p++;
  250. } else {
  251. /* CopyAndCollapse(elSize, element, p); */
  252. memcpy(p, element, elSize);
  253. p += elSize + 1;
  254. }
  255. }
  256. argv[i] = NULL;
  257. *argvPtr = argv;
  258. *argcPtr = i;
  259. return OK;
  260. }
  261. /* Parse options for a channel.
  262. */
  263. int channel_modify(char *result, struct chanset_t *chan, int items, char **item, bool cmd)
  264. {
  265. bool error = 0, changed_groups = false;
  266. int old_status = chan->status,
  267. old_mode_mns_prot = chan->mode_mns_prot,
  268. old_mode_pls_prot = chan->mode_pls_prot;
  269. char s[121] = "", result_extra[RESULT_LEN / 2] = "";
  270. if (result)
  271. result[0] = 0;
  272. for (register int i = 0; i < items; i++) {
  273. /* Chanchar template
  274. } else if (!strcmp(item[i], "temp")) {
  275. i++;
  276. if (i >= items) {
  277. if (result)
  278. strlcpy(result, "channel temp needs argument", RESULT_LEN);
  279. return ERROR;
  280. }
  281. strlcpy(chan->temp, item[i], sizeof(chan->temp));
  282. check_temp(chan);
  283. */
  284. if (!strcmp(item[i], "chanmode")) {
  285. i++;
  286. if (i >= items) {
  287. if (result)
  288. strlcpy(result, "channel chanmode needs argument", RESULT_LEN);
  289. return ERROR;
  290. }
  291. strlcpy(s, item[i], sizeof(s));
  292. set_mode_protect(chan, s);
  293. } else if (!strcmp(item[i], "groups")) {
  294. i++;
  295. if (i >= items) {
  296. if (result)
  297. strlcpy(result, "channel groups needs argument", RESULT_LEN);
  298. return ERROR;
  299. }
  300. // Get string into right format
  301. bd::String changroups(item[i]);
  302. // Replace commas with spaces to be in proper format
  303. changroups = changroups.sub(",", " ");
  304. changroups.trim();
  305. *(chan->groups) = changroups.split(" ");
  306. changed_groups = true;
  307. } else if (!strcmp(item[i], "topic")) {
  308. char *p = NULL;
  309. i++;
  310. if (i >= items) {
  311. if (result)
  312. strlcpy(result, "topic needs argument", RESULT_LEN);
  313. return ERROR;
  314. }
  315. p = replace(item[i], "{", "[");
  316. p = replace(p, "}", "]");
  317. strlcpy(chan->topic, p, sizeof(chan->topic));
  318. } else if (!cmd && !strcmp(item[i], "addedby")) {
  319. i++;
  320. if (i >= items) {
  321. if (result)
  322. strlcpy(result, "addedby needs argument", RESULT_LEN);
  323. return ERROR;
  324. }
  325. strlcpy(chan->added_by, item[i], sizeof(chan->added_by));
  326. } else if (!cmd && !strcmp(item[i], "addedts")) {
  327. i++;
  328. if (i >= items) {
  329. if (result)
  330. strlcpy(result, "addedts needs argument", RESULT_LEN);
  331. return ERROR;
  332. }
  333. chan->added_ts = atoi(item[i]);
  334. } else if (!strcmp(item[i], "limit")) {
  335. i++;
  336. if (i >= items) {
  337. if (result)
  338. strlcpy(result, "channel limit needs argument", RESULT_LEN);
  339. return ERROR;
  340. }
  341. if (chan->limitraise && !atoi(item[i]) && dolimit(chan)) //limitraise was disabled by the user
  342. add_mode(chan, '-', 'l', "");
  343. chan->limitraise = atoi(item[i]);
  344. chan->limit_prot = 0;
  345. } else if (!strcmp(item[i], "fish-key")) {
  346. i++;
  347. if (i >= items) {
  348. if (result)
  349. strlcpy(result, "channel fish-key needs argument", RESULT_LEN);
  350. return ERROR;
  351. }
  352. bd::String key(item[i]);
  353. key.trim();
  354. set_fish_key(chan->dname, key);
  355. strlcpy(chan->fish_key, key.c_str(), sizeof(chan->fish_key));
  356. } else if (!strcmp(item[i], "ban-time")) {
  357. i++;
  358. if (i >= items) {
  359. if (result)
  360. strlcpy(result, "channel ban-time needs argument", RESULT_LEN);
  361. return ERROR;
  362. }
  363. chan->ban_time = atoi(item[i]);
  364. } else if (!strcmp(item[i], "exempt-time")) {
  365. i++;
  366. if (i >= items) {
  367. if (result)
  368. strlcpy(result, "channel exempt-time needs argument", RESULT_LEN);
  369. return ERROR;
  370. }
  371. chan->exempt_time = atoi(item[i]);
  372. } else if (!strcmp(item[i], "invite-time")) {
  373. i++;
  374. if (i >= items) {
  375. if (result)
  376. strlcpy(result, "channel invite-time needs argument", RESULT_LEN);
  377. return ERROR;
  378. }
  379. chan->invite_time = atoi(item[i]);
  380. } else if (!strcmp(item[i], "capslimit") || !strcmp(item[i], "caps-limit")) {
  381. i++;
  382. if (i >= items) {
  383. if (result)
  384. strlcpy(result, "channel caps-limit needs argument", RESULT_LEN);
  385. return ERROR;
  386. }
  387. int capslimit = atoi(item[i]);
  388. if (capslimit > 100 || capslimit < 0 || item[i][0] == '-') {
  389. if (result)
  390. strlcpy(result, "channel caps-limit out of range (0-100)", RESULT_LEN);
  391. return ERROR;
  392. }
  393. chan->capslimit = capslimit;
  394. } else if (!strcmp(item[i], "colorlimit") || !strcmp(item[i], "color-limit")) {
  395. i++;
  396. if (i >= items) {
  397. if (result)
  398. strlcpy(result, "channel color-limit needs argument", RESULT_LEN);
  399. return ERROR;
  400. }
  401. chan->colorlimit = atoi(item[i]);
  402. } else if (!strcmp(item[i], "closed-ban")) {
  403. i++;
  404. if (i >= items) {
  405. if (result)
  406. strlcpy(result, "channel closed-ban needs argument", RESULT_LEN);
  407. return ERROR;
  408. }
  409. chan->closed_ban = atoi(item[i]);
  410. } else if (!strcmp(item[i], "voice-moderate")) {
  411. i++;
  412. if (i >= items) {
  413. if (result)
  414. strlcpy(result, "channel voice-moderate needs argument", RESULT_LEN);
  415. return ERROR;
  416. }
  417. chan->voice_moderate = atoi(item[i]);
  418. if (chan->mode_mns_prot & CHANMODER && chan->voice_moderate)
  419. chan->voice_moderate = 0;
  420. } else if (!strcmp(item[i], "closed-invite")) {
  421. i++;
  422. if (i >= items) {
  423. if (result)
  424. strlcpy(result, "channel closed-invite needs argument", RESULT_LEN);
  425. return ERROR;
  426. }
  427. chan->closed_invite = atoi(item[i]);
  428. if (chan->mode_mns_prot & CHANINV && chan->closed_invite)
  429. chan->closed_invite = 0;
  430. } else if (!strcmp(item[i], "closed-private")) {
  431. i++;
  432. if (i >= items) {
  433. if (result)
  434. strlcpy(result, "channel closed-private needs argument", RESULT_LEN);
  435. return ERROR;
  436. }
  437. chan->closed_private = atoi(item[i]);
  438. if (chan->mode_mns_prot & CHANPRIV && chan->closed_private)
  439. chan->closed_private = 0;
  440. } else if (!strcmp(item[i], "voice-non-ident")) {
  441. i++;
  442. if (i >= items) {
  443. if (result)
  444. strlcpy(result, "channel voice-ident needs argument", RESULT_LEN);
  445. return ERROR;
  446. }
  447. chan->voice_non_ident = atoi(item[i]);
  448. } else if (!strcmp(item[i], "bad-cookie")) {
  449. i++;
  450. if (i >= items) {
  451. if (result)
  452. strlcpy(result, "channel bad-cookie needs argument", RESULT_LEN);
  453. return ERROR;
  454. }
  455. chan->bad_cookie = deflag_translate(item[i]);
  456. } else if (!strcmp(item[i], "manop")) {
  457. i++;
  458. if (i >= items) {
  459. if (result)
  460. strlcpy(result, "channel manop needs argument", RESULT_LEN);
  461. return ERROR;
  462. }
  463. chan->manop = deflag_translate(item[i]);
  464. } else if (!strcmp(item[i], "mdop")) {
  465. i++;
  466. if (i >= items) {
  467. if (result)
  468. strlcpy(result, "channel mdop needs argument", RESULT_LEN);
  469. return ERROR;
  470. }
  471. chan->mdop = deflag_translate(item[i]);
  472. } else if (!strcmp(item[i], "mop")) {
  473. i++;
  474. if (i >= items) {
  475. if (result)
  476. strlcpy(result, "channel mop needs argument", RESULT_LEN);
  477. return ERROR;
  478. }
  479. chan->mop = deflag_translate(item[i]);
  480. } else if (!strcmp(item[i], "revenge")) {
  481. i++;
  482. if (i >= items) {
  483. if (result)
  484. strlcpy(result, "channel revenge needs argument", RESULT_LEN);
  485. return ERROR;
  486. }
  487. chan->revenge = deflag_translate(item[i]);
  488. } else if (!strcmp(item[i], "knock")) {
  489. i++;
  490. if (i >= items) {
  491. if (result)
  492. strlcpy(result, "channel knock needs argument", RESULT_LEN);
  493. return ERROR;
  494. }
  495. if (!str_isdigit(item[i])) {
  496. if (!strcasecmp("Op", item[i]))
  497. chan->knock_flags = CHAN_FLAG_OP;
  498. else if (!strcasecmp("Voice", item[i]))
  499. chan->knock_flags = CHAN_FLAG_VOICE;
  500. else if (!strcasecmp("User", item[i]))
  501. chan->knock_flags = CHAN_FLAG_USER;
  502. else if (!strcasecmp("None", item[i]))
  503. chan->knock_flags = 0;
  504. else {
  505. if (result)
  506. strlcpy(result, "channel knock only accepts Op|Voice|User|None", RESULT_LEN);
  507. return ERROR;
  508. }
  509. } else
  510. chan->knock_flags = atoi(item[i]);
  511. } else if (!strcmp(item[i], "flood-exempt")) {
  512. i++;
  513. if (i >= items) {
  514. if (result)
  515. strlcpy(result, "channel flood-exempt needs argument", RESULT_LEN);
  516. return ERROR;
  517. }
  518. if (!str_isdigit(item[i])) {
  519. if (!strcasecmp("Op", item[i]))
  520. chan->flood_exempt_mode = CHAN_FLAG_OP;
  521. else if (!strcasecmp("Voice", item[i]))
  522. chan->flood_exempt_mode = CHAN_FLAG_VOICE;
  523. else if (!strcasecmp("None", item[i]))
  524. chan->flood_exempt_mode = 0;
  525. else {
  526. if (result)
  527. strlcpy(result, "channel flood-exempt only accepts Op|Voice|None", RESULT_LEN);
  528. return ERROR;
  529. }
  530. } else
  531. chan->flood_exempt_mode = atoi(item[i]);
  532. } else if (!strcmp(item[i], "closed-exempt")) {
  533. i++;
  534. if (i >= items) {
  535. if (result)
  536. strlcpy(result, "channel closed-exempt needs argument", RESULT_LEN);
  537. return ERROR;
  538. }
  539. if (!str_isdigit(item[i])) {
  540. if (!strcasecmp("Op", item[i]))
  541. chan->closed_exempt_mode = CHAN_FLAG_OP;
  542. else if (!strcasecmp("Voice", item[i]))
  543. chan->closed_exempt_mode = CHAN_FLAG_VOICE;
  544. else if (!strcasecmp("None", item[i]))
  545. chan->closed_exempt_mode = 0;
  546. else {
  547. if (result)
  548. strlcpy(result, "channel closed-exempt only accepts Op|Voice|None", RESULT_LEN);
  549. return ERROR;
  550. }
  551. } else
  552. chan->closed_exempt_mode = atoi(item[i]);
  553. } else if (!strcmp(item[i], "flood-lock-time")) {
  554. i++;
  555. if (i >= items) {
  556. if (result)
  557. strlcpy(result, "channel flood-lock-time needs argument", RESULT_LEN);
  558. return ERROR;
  559. }
  560. chan->flood_lock_time = atoi(item[i]);
  561. } else if (!strcmp(item[i], "auto-delay")) {
  562. i++;
  563. if (i >= items) {
  564. if (result)
  565. strlcpy(result, "channel auto-delay needs argument", RESULT_LEN);
  566. return ERROR;
  567. }
  568. chan->auto_delay = atoi(item[i]);
  569. } else if (!strcmp(item[i], "ban-type")) {
  570. i++;
  571. if (i >= items) {
  572. if (result)
  573. strlcpy(result, "channel ban-type needs argument", RESULT_LEN);
  574. return ERROR;
  575. }
  576. chan->ban_type = atoi(item[i]);
  577. } else if (!strcmp(item[i], "protect-backup")) {
  578. i++;
  579. if (i >= items) {
  580. if (result)
  581. strlcpy(result, "channel protect-backup needs argument", RESULT_LEN);
  582. return ERROR;
  583. }
  584. chan->protect_backup = atoi(item[i]);
  585. }
  586. /* Chanint template
  587. * } else if (!strcmp(item[i], "temp")) {
  588. * i++;
  589. * if (i >= items) {
  590. * if (result)
  591. * strlcpy(result, "channel temp needs argument", RESULT_LEN);
  592. * return ERROR;
  593. * }
  594. * chan->temp = atoi(item[i]);
  595. */
  596. else if (!strcmp(item[i], "+floodban"))
  597. chan->status |= CHAN_FLOODBAN;
  598. else if (!strcmp(item[i], "-floodban"))
  599. chan->status &= ~CHAN_FLOODBAN;
  600. else if (!strcmp(item[i], "+enforcebans"))
  601. chan->status |= CHAN_ENFORCEBANS;
  602. else if (!strcmp(item[i], "-enforcebans"))
  603. chan->status &= ~CHAN_ENFORCEBANS;
  604. else if (!strcmp(item[i], "+dynamicbans"))
  605. chan->status |= CHAN_DYNAMICBANS;
  606. else if (!strcmp(item[i], "-dynamicbans"))
  607. chan->status &= ~CHAN_DYNAMICBANS;
  608. else if (!strcmp(item[i], "-userbans"))
  609. chan->status |= CHAN_NOUSERBANS;
  610. else if (!strcmp(item[i], "+userbans"))
  611. chan->status &= ~CHAN_NOUSERBANS;
  612. else if (!strcmp(item[i], "+bitch"))
  613. chan->status |= CHAN_BITCH;
  614. else if (!strcmp(item[i], "-bitch"))
  615. chan->status &= ~CHAN_BITCH;
  616. else if (!strcmp(item[i], "+nodesynch"))
  617. chan->status |= CHAN_NODESYNCH;
  618. else if (!strcmp(item[i], "-nodesynch"))
  619. chan->status &= ~CHAN_NODESYNCH;
  620. else if (!strcmp(item[i], "+inactive"))
  621. chan->status |= CHAN_INACTIVE;
  622. else if (!strcmp(item[i], "-inactive"))
  623. chan->status&= ~CHAN_INACTIVE;
  624. else if (!strcmp(item[i], "+secret"))
  625. chan->status |= CHAN_SECRET;
  626. else if (!strcmp(item[i], "-secret"))
  627. chan->status &= ~CHAN_SECRET;
  628. else if (!strcmp(item[i], "+cycle"))
  629. chan->status |= CHAN_CYCLE;
  630. else if (!strcmp(item[i], "-cycle"))
  631. chan->status &= ~CHAN_CYCLE;
  632. else if (!strcmp(item[i], "+dynamicexempts"))
  633. chan->status |= CHAN_DYNAMICEXEMPTS;
  634. else if (!strcmp(item[i], "-dynamicexempts"))
  635. chan->status &= ~CHAN_DYNAMICEXEMPTS;
  636. else if (!strcmp(item[i], "-userexempts"))
  637. chan->status |= CHAN_NOUSEREXEMPTS;
  638. else if (!strcmp(item[i], "+userexempts"))
  639. chan->status &= ~CHAN_NOUSEREXEMPTS;
  640. else if (!strcmp(item[i], "+dynamicinvites"))
  641. chan->status |= CHAN_DYNAMICINVITES;
  642. else if (!strcmp(item[i], "-dynamicinvites"))
  643. chan->status &= ~CHAN_DYNAMICINVITES;
  644. else if (!strcmp(item[i], "-userinvites"))
  645. chan->status |= CHAN_NOUSERINVITES;
  646. else if (!strcmp(item[i], "+userinvites"))
  647. chan->status &= ~CHAN_NOUSERINVITES;
  648. else if (!strcmp(item[i], "+closed"))
  649. chan->status |= CHAN_CLOSED;
  650. else if (!strcmp(item[i], "-closed"))
  651. chan->status &= ~CHAN_CLOSED;
  652. else if (HAVE_TAKE && !strcmp(item[i], "+take"))
  653. chan->status |= CHAN_TAKE;
  654. else if (HAVE_TAKE && !strcmp(item[i], "-take"))
  655. chan->status &= ~CHAN_TAKE;
  656. else if (!HAVE_TAKE && !strcmp(item[i], "+take"))
  657. chan->status |= CHAN_BITCH;
  658. else if (!HAVE_TAKE && !strcmp(item[i], "-take"))
  659. chan->status &= ~CHAN_BITCH;
  660. else if (!strcmp(item[i], "+voice"))
  661. chan->status |= CHAN_VOICE;
  662. else if (!strcmp(item[i], "-voice"))
  663. chan->status &= ~CHAN_VOICE;
  664. else if (!strcmp(item[i], "+autoop"))
  665. chan->status |= CHAN_AUTOOP;
  666. else if (!strcmp(item[i], "-autoop"))
  667. chan->status &= ~CHAN_AUTOOP;
  668. else if (!strcmp(item[i], "+botbitch"))
  669. chan->status |= CHAN_BOTBITCH;
  670. else if (!strcmp(item[i], "-botbitch"))
  671. chan->status &= ~CHAN_BOTBITCH;
  672. else if (!strcmp(item[i], "+rbl"))
  673. chan->status |= CHAN_RBL;
  674. else if (!strcmp(item[i], "-rbl"))
  675. chan->status &= ~CHAN_RBL;
  676. else if (!strcmp(item[i], "+voicebitch"))
  677. chan->status |= CHAN_VOICEBITCH;
  678. else if (!strcmp(item[i], "-voicebitch"))
  679. chan->status &= ~CHAN_VOICEBITCH;
  680. else if (!strcmp(item[i], "+protect"))
  681. chan->status |= CHAN_PROTECT;
  682. else if (!strcmp(item[i], "-protect"))
  683. chan->status &= ~CHAN_PROTECT;
  684. /* Chanflag template
  685. * else if (!strcmp(item[i], "+temp"))
  686. * chan->status |= CHAN_TEMP;
  687. * else if (!strcmp(item[i], "-temp"))
  688. * chan->status &= ~CHAN_TEMP;
  689. */
  690. else if (!strcmp(item[i], "+fastop"))
  691. chan->status |= CHAN_FASTOP;
  692. else if (!strcmp(item[i], "-fastop"))
  693. chan->status &= ~CHAN_FASTOP;
  694. else if (!strcmp(item[i], "+private"))
  695. chan->status |= CHAN_PRIVATE;
  696. else if (!strcmp(item[i], "-private"))
  697. chan->status &= ~CHAN_PRIVATE;
  698. else if (!strcmp(item[i], "+backup"))
  699. chan->status |= CHAN_BACKUP;
  700. else if (!strcmp(item[i], "-backup"))
  701. chan->status &= ~CHAN_BACKUP;
  702. /* ignore wasoptest, stopnethack and clearbans in chanfile, remove
  703. this later */
  704. else if (!cmd && !HAVE_TAKE && !strcmp(item[i], "+take")) ;
  705. else if (!cmd && !HAVE_TAKE && !strcmp(item[i], "-take")) ;
  706. else if (!cmd && !strcmp(item[i], "stopnethack-mode")) ;
  707. else if (!cmd && !strcmp(item[i], "revenge-mode")) ;
  708. else if (!cmd && !strcmp(item[i], "+meankicks")) ;
  709. else if (!cmd && !strcmp(item[i], "-meankicks")) ;
  710. else if (!cmd && !strcmp(item[i], "+nomassjoin")) ;
  711. else if (!cmd && !strcmp(item[i], "-nomassjoin")) ;
  712. else if (!cmd && !strcmp(item[i], "+revenge")) ;
  713. else if (!cmd && !strcmp(item[i], "-revenge")) ;
  714. else if (!cmd && !strcmp(item[i], "+revengebot")) ;
  715. else if (!cmd && !strcmp(item[i], "-revengebot")) ;
  716. else if (!cmd && !strcmp(item[i], "+manop")) ;
  717. else if (!cmd && !strcmp(item[i], "-manop")) ;
  718. else if (!cmd && !strcmp(item[i], "+dontkickops")) ;
  719. else if (!cmd && !strcmp(item[i], "-dontkickops")) ;
  720. else if (!cmd && !strcmp(item[i], "+nomdop")) ;
  721. else if (!cmd && !strcmp(item[i], "-nomdop")) ;
  722. else if (!cmd && !strcmp(item[i], "+protectfriends")) ;
  723. else if (!cmd && !strcmp(item[i], "-protectfriends")) ;
  724. else if (!cmd && !strcmp(item[i], "+protectops")) ;
  725. else if (!cmd && !strcmp(item[i], "-protectops")) ;
  726. else if (!cmd && !strcmp(item[i], "+punish")) ;
  727. else if (!cmd && !strcmp(item[i], "-punish")) ;
  728. else if (!cmd && !strcmp(item[i], "+seen")) ;
  729. else if (!cmd && !strcmp(item[i], "-seen")) ;
  730. else if (!cmd && !strcmp(item[i], "+secret")) ;
  731. else if (!cmd && !strcmp(item[i], "-secret")) ;
  732. else if (!cmd && !strcmp(item[i], "-stopnethack")) ;
  733. else if (!cmd && !strcmp(item[i], "+stopnethack")) ;
  734. else if (!cmd && !strcmp(item[i], "-wasoptest")) ;
  735. else if (!cmd && !strcmp(item[i], "+wasoptest")) ; /* Eule 01.2000 */
  736. else if (!cmd && !strcmp(item[i], "+clearbans")) ;
  737. else if (!cmd && !strcmp(item[i], "-clearbans")) ;
  738. else if (!cmd && !strncmp(item[i], "need-", 5)) ;
  739. else if (!strncmp(item[i], "flood-", 6)) {
  740. int *pthr = NULL;
  741. interval_t *ptime = NULL;
  742. char *p = NULL;
  743. if (!strcmp(item[i] + 6, "*")) {
  744. i++;
  745. if (i >= items) {
  746. if (result)
  747. simple_snprintf(result, RESULT_LEN, "%s needs argument", item[i - 1]);
  748. return ERROR;
  749. }
  750. p = strchr(item[i], ':');
  751. int thr = 0;
  752. interval_t time = 0;
  753. if (p) {
  754. *p++ = 0;
  755. thr = atoi(item[i]);
  756. time = atoi(p);
  757. *--p = ':';
  758. } else {
  759. thr = atoi(item[i]);
  760. time = 1;
  761. }
  762. chan->flood_pub_thr = thr;
  763. chan->flood_pub_time = time;
  764. chan->flood_mpub_thr = thr;
  765. chan->flood_mpub_time = time;
  766. chan->flood_bytes_thr = thr;
  767. chan->flood_bytes_time = time;
  768. chan->flood_mbytes_thr = thr;
  769. chan->flood_mbytes_time = time;
  770. chan->flood_join_thr = thr;
  771. chan->flood_join_time = time;
  772. chan->flood_ctcp_thr = thr;
  773. chan->flood_ctcp_time = time;
  774. chan->flood_mctcp_thr = thr;
  775. chan->flood_mctcp_time = time;
  776. chan->flood_kick_thr = thr;
  777. chan->flood_kick_time = time;
  778. chan->flood_deop_thr = thr;
  779. chan->flood_deop_time = time;
  780. chan->flood_nick_thr = thr;
  781. chan->flood_nick_time = time;
  782. chan->flood_mjoin_thr = thr;
  783. chan->flood_mjoin_time = time;
  784. } else if (!strcmp(item[i] + 6, "chan")) {
  785. pthr = &chan->flood_pub_thr;
  786. ptime = &chan->flood_pub_time;
  787. } else if (!strcmp(item[i] + 6, "bytes")) {
  788. pthr = &chan->flood_bytes_thr;
  789. ptime = &chan->flood_bytes_time;
  790. } else if (!strcmp(item[i] + 6, "join")) {
  791. pthr = &chan->flood_join_thr;
  792. ptime = &chan->flood_join_time;
  793. } else if (!strcmp(item[i] + 6, "ctcp")) {
  794. pthr = &chan->flood_ctcp_thr;
  795. ptime = &chan->flood_ctcp_time;
  796. } else if (!strcmp(item[i] + 6, "kick")) {
  797. pthr = &chan->flood_kick_thr;
  798. ptime = &chan->flood_kick_time;
  799. } else if (!strcmp(item[i] + 6, "deop")) {
  800. pthr = &chan->flood_deop_thr;
  801. ptime = &chan->flood_deop_time;
  802. } else if (!strcmp(item[i] + 6, "nick")) {
  803. pthr = &chan->flood_nick_thr;
  804. ptime = &chan->flood_nick_time;
  805. } else if (!strcmp(item[i] + 6, "mjoin")) {
  806. pthr = &chan->flood_mjoin_thr;
  807. ptime = &chan->flood_mjoin_time;
  808. } else if (!strcmp(item[i] + 6, "mpub")) {
  809. pthr = &chan->flood_mpub_thr;
  810. ptime = &chan->flood_mpub_time;
  811. } else if (!strcmp(item[i] + 6, "mbytes")) {
  812. pthr = &chan->flood_mbytes_thr;
  813. ptime = &chan->flood_mbytes_time;
  814. } else if (!strcmp(item[i] + 6, "mctcp")) {
  815. pthr = &chan->flood_mctcp_thr;
  816. ptime = &chan->flood_mctcp_time;
  817. } else { /* Ignore for optimal forward compatibility */
  818. i++;
  819. continue;
  820. }
  821. if (pthr && ptime) { //Ignore flood-*
  822. i++;
  823. if (i >= items) {
  824. if (result)
  825. simple_snprintf(result, RESULT_LEN, "%s needs argument", item[i - 1]);
  826. return ERROR;
  827. }
  828. p = strchr(item[i], ':');
  829. if (p) {
  830. *p++ = 0;
  831. *pthr = atoi(item[i]);
  832. *ptime = atoi(p);
  833. *--p = ':';
  834. } else {
  835. *pthr = atoi(item[i]);
  836. *ptime = 1;
  837. }
  838. }
  839. } else {
  840. if (result && item[i][0]) { /* ignore "" */
  841. if (!result[0])
  842. strlcpy(result, "illegal channel option: ", RESULT_LEN);
  843. if (result_extra[0])
  844. strlcat(result_extra, " ", sizeof(result_extra));
  845. strlcat(result_extra, item[i], sizeof(result_extra));
  846. }
  847. error = 1;
  848. }
  849. }
  850. if ((chan->status ^ old_status) & CHAN_TAKE)
  851. chan->status |= CHAN_BITCH; // to avoid bots still mass opping from +take from not using cookies
  852. if (!conf.bot->hub && (chan != chanset_default)) {
  853. // Check if groups changed or +/-backup set
  854. if (!restarting && !loading && (changed_groups || ((old_status ^ chan->status) & (CHAN_INACTIVE | CHAN_BACKUP)))) {
  855. check_shouldjoin(chan);
  856. }
  857. if (me_op(chan)) {
  858. if ((old_status ^ chan->status) & (CHAN_ENFORCEBANS|CHAN_NOUSERBANS|CHAN_DYNAMICBANS|CHAN_NOUSEREXEMPTS|CHAN_NOUSERINVITES|CHAN_DYNAMICEXEMPTS|CHAN_DYNAMICINVITES)) {
  859. recheck_channel(chan, 1);
  860. /* Does a change in channel flag affect client status in the channel? */
  861. } else if ((chan->status ^ old_status) & (CHAN_BITCH | CHAN_BOTBITCH | CHAN_PRIVATE | CHAN_CLOSED | CHAN_VOICE | CHAN_VOICEBITCH )) {
  862. recheck_channel(chan, 0);
  863. } else if ((old_status & CHAN_TAKE) && !(chan->status & CHAN_TAKE)) {
  864. //Set -take, fetch bans/exempts/invites
  865. recheck_channel(chan, 2);
  866. } else if (old_mode_pls_prot != chan->mode_pls_prot || old_mode_mns_prot != chan->mode_mns_prot) {
  867. recheck_channel_modes(chan);
  868. }
  869. }
  870. }
  871. if (result && result[0] && result_extra[0])
  872. strlcat(result, result_extra, RESULT_LEN);
  873. if (error)
  874. return ERROR;
  875. return OK;
  876. }
  877. static void init_masklist(masklist *m)
  878. {
  879. m->mask = (char *) my_calloc(1, 1);
  880. m->who = NULL;
  881. m->next = NULL;
  882. }
  883. /* Initialize out the channel record.
  884. */
  885. static void init_channel(struct chanset_t *chan, bool reset)
  886. {
  887. chan->channel.maxmembers = 0;
  888. chan->channel.mode = 0;
  889. chan->channel.members = 0;
  890. chan->channel.splitmembers = 0;
  891. if (!reset)
  892. my_setkey(chan, NULL);
  893. chan->channel.ban = (masklist *) my_calloc(1, sizeof(masklist));
  894. init_masklist(chan->channel.ban);
  895. chan->channel.exempt = (masklist *) my_calloc(1, sizeof(masklist));
  896. init_masklist(chan->channel.exempt);
  897. chan->channel.invite = (masklist *) my_calloc(1, sizeof(masklist));
  898. init_masklist(chan->channel.invite);
  899. chan->channel.member = (memberlist *) my_calloc(1, sizeof(memberlist));
  900. chan->channel.member->nick[0] = 0;
  901. chan->channel.member->next = NULL;
  902. chan->channel.topic = NULL;
  903. chan->channel.floodtime = new bd::HashTable<bd::String, bd::HashTable<flood_t, time_t> >;
  904. chan->channel.floodnum = new bd::HashTable<bd::String, bd::HashTable<flood_t, int> >;
  905. chan->channel.cached_members = new bd::HashTable<bd::String, memberlist*>;
  906. /* Don't clear out existing roles, keep them until rebalancing
  907. * to not create a window of missing roles. */
  908. if (!chan->bot_roles) {
  909. chan->bot_roles = new bd::HashTable<bd::String, int>;
  910. chan->role_bots = new bd::HashTable<short, bd::Array<bd::String> >;
  911. chan->role = 0;
  912. }
  913. chan->needs_role_rebalance = 1;
  914. }
  915. static void clear_masklist(masklist *m)
  916. {
  917. masklist *temp = NULL;
  918. for (; m; m = temp) {
  919. temp = m->next;
  920. if (m->mask)
  921. free(m->mask);
  922. if (m->who)
  923. free(m->who);
  924. free(m);
  925. }
  926. }
  927. /* Clear out channel data from memory.
  928. */
  929. void clear_channel(struct chanset_t *chan, bool reset)
  930. {
  931. memberlist *m = NULL, *m1 = NULL;
  932. if (chan->channel.topic)
  933. free(chan->channel.topic);
  934. for (m = chan->channel.member; m; m = m1) {
  935. m1 = m->next;
  936. delete_member(m);
  937. }
  938. clear_masklist(chan->channel.ban);
  939. chan->channel.ban = NULL;
  940. clear_masklist(chan->channel.exempt);
  941. chan->channel.exempt = NULL;
  942. clear_masklist(chan->channel.invite);
  943. chan->channel.invite = NULL;
  944. chan->channel.last_eI = 0;
  945. chan->ircnet_status = 0;
  946. // chan->ircnet_status &= ~CHAN_HAVEBANS;
  947. delete chan->channel.floodtime;
  948. chan->channel.floodtime = NULL;
  949. delete chan->channel.floodnum;
  950. chan->channel.floodnum = NULL;
  951. /* Don't clear out existing roles if resetting, keep them until rebalancing
  952. * to not create a window of missing roles. */
  953. if (!reset) {
  954. delete chan->bot_roles;
  955. chan->bot_roles = NULL;
  956. delete chan->role_bots;
  957. chan->role_bots = NULL;
  958. }
  959. if (chan->channel.cached_members) {
  960. if (chan->channel.cached_members->size()) {
  961. bd::Array<bd::String> member_uhosts(chan->channel.cached_members->keys());
  962. for (size_t i = 0; i < member_uhosts.length(); ++i) {
  963. const bd::String uhost(member_uhosts[i]);
  964. // Delete the cached member
  965. m = (*chan->channel.cached_members)[uhost];
  966. delete_member(m);
  967. // Remove the cached member (not technically needed as it is deleted below, but for completeness.)
  968. chan->channel.cached_members->remove(uhost);
  969. }
  970. }
  971. delete chan->channel.cached_members;
  972. chan->channel.cached_members = NULL;
  973. }
  974. if (reset)
  975. init_channel(chan, 1);
  976. for (size_t i = 0; i < MODES_PER_LINE_MAX; ++i) {
  977. if (chan->cmode[i].op) {
  978. free(chan->cmode[i].op);
  979. chan->cmode[i].op = NULL;
  980. }
  981. if (chan->ccmode[i].op) {
  982. free(chan->ccmode[i].op);
  983. chan->ccmode[i].op = NULL;
  984. }
  985. }
  986. }
  987. /* Create new channel and parse commands.
  988. */
  989. int channel_add(char *result, const char *newname, char *options, bool isdefault)
  990. {
  991. /* When loading userfile */
  992. if (newname && newname[0] && loading && !strcmp(newname, "default"))
  993. isdefault = 1;
  994. if (!newname || !newname[0] || (!isdefault && !strchr(CHANMETA, newname[0]))) {
  995. if (result)
  996. strlcpy(result, "invalid channel prefix", RESULT_LEN);
  997. return ERROR;
  998. }
  999. if (strchr(newname, ',') != NULL) {
  1000. if (result)
  1001. strlcpy(result, "invalid channel name", RESULT_LEN);
  1002. return ERROR;
  1003. }
  1004. const char **item = NULL;
  1005. int items = 0;
  1006. char buf[3001] = "";
  1007. simple_snprintf(buf, sizeof(buf), "chanmode { %s }", glob_chanmode);
  1008. if (!isdefault) { // These are passed in in 'options'
  1009. strlcat(buf, " ", sizeof(buf));
  1010. strlcat(buf, def_chanset, sizeof(buf));
  1011. }
  1012. // Add in 'default' channel options
  1013. if (!isdefault && chanset_default) {
  1014. bd::String default_chan_options = channel_to_string(chanset_default);
  1015. strlcat(buf, " ", sizeof(buf));
  1016. strlcat(buf, default_chan_options.c_str(), sizeof(buf));
  1017. }
  1018. if (options && options[0]) {
  1019. strlcat(buf, " ", sizeof(buf));
  1020. strlcat(buf, options, sizeof(buf));
  1021. }
  1022. if (SplitList(result, buf, &items, &item) != OK)
  1023. return ERROR;
  1024. bool join = 0;
  1025. struct chanset_t *chan = NULL;
  1026. int ret = OK;
  1027. if ((chan = findchan_by_dname(newname))) {
  1028. /* Already existing channel, maybe a reload of the channel file */
  1029. chan->status &= ~CHAN_FLAGGED; /* don't delete me! :) */
  1030. } else {
  1031. chan = (struct chanset_t *) my_calloc(1, sizeof(struct chanset_t));
  1032. /* These are defaults, bzero already set them 0, but we set them for future reference */
  1033. chan->limit_prot = 0;
  1034. chan->limit = 0;
  1035. chan->closed_ban = 0;
  1036. chan->closed_private = 1;
  1037. chan->closed_invite = 1;
  1038. chan->voice_moderate = 1;
  1039. chan->voice_non_ident = 1;
  1040. chan->auto_delay = 5;
  1041. chan->ban_type = 3;
  1042. chan->revenge = DEFLAG_REACT;
  1043. /* Chanint template
  1044. * chan->temp = 0;
  1045. */
  1046. chan->groups = new bd::Array<bd::String>;
  1047. *(chan->groups) << "main";
  1048. chan->protect_backup = 1;
  1049. chan->fish_key[0] = 0;
  1050. chan->knock_flags = 0;
  1051. chan->flood_lock_time = 120;
  1052. chan->flood_exempt_mode = 0;
  1053. chan->flood_pub_thr = 0;
  1054. chan->flood_pub_time = 0;
  1055. chan->flood_bytes_thr = 0;
  1056. chan->flood_bytes_time = 0;
  1057. chan->flood_ctcp_thr = 5;
  1058. chan->flood_ctcp_time = 30;
  1059. chan->flood_join_thr = 0;
  1060. chan->flood_join_time = 0;
  1061. chan->flood_deop_thr = 8;
  1062. chan->flood_deop_time = 10;
  1063. chan->flood_kick_thr = 0;
  1064. chan->flood_kick_time = 0;
  1065. chan->flood_nick_thr = 0;
  1066. chan->flood_nick_time = 0;
  1067. chan->flood_mjoin_thr = 6;
  1068. chan->flood_mjoin_time = 1;
  1069. chan->capslimit = 0;
  1070. chan->colorlimit = 0;
  1071. chan->flood_mpub_thr = 20;
  1072. chan->flood_mpub_time = 1;
  1073. chan->flood_mbytes_thr = 1000;
  1074. chan->flood_mbytes_time = 1;
  1075. chan->flood_mctcp_thr = 7;
  1076. chan->flood_mctcp_time = 1;
  1077. chan->limitraise = 20;
  1078. chan->ban_time = global_ban_time;
  1079. chan->exempt_time = global_exempt_time;
  1080. chan->invite_time = global_invite_time;
  1081. chan->channel.jointime = 0;
  1082. chan->channel.parttime = 0;
  1083. chan->channel.fighting = 0;
  1084. chan->channel.drone_set_mode = 0;
  1085. chan->channel.drone_jointime = 0;
  1086. chan->channel.drone_joins = 0;
  1087. chan->channel.last_eI = 0;
  1088. chan->channel.floodtime = NULL;
  1089. chan->channel.floodnum = NULL;
  1090. /* We _only_ put the dname (display name) in here so as not to confuse
  1091. * any code later on. chan->name gets updated with the channel name as
  1092. * the server knows it, when we join the channel. <cybah>
  1093. */
  1094. strlcpy(chan->dname, newname, sizeof(chan->dname));
  1095. /* Initialize chan->channel info */
  1096. if (isdefault) {
  1097. if (chanset_default)
  1098. remove_channel(chanset_default);
  1099. chanset_default = chan;
  1100. } else {
  1101. init_channel(chan, 0);
  1102. list_append((struct list_type **) &chanset, (struct list_type *) chan);
  1103. /* Channel name is stored in xtra field for sharebot stuff */
  1104. if (!conf.bot->hub && !isdefault)
  1105. join = 1;
  1106. }
  1107. }
  1108. /* If loading is set, we're loading the userfile. Ignore errors while
  1109. * reading userfile and just return OK. This is for compatability
  1110. * if a user goes back to an eggdrop that no-longer supports certain
  1111. * (channel) options.
  1112. */
  1113. if ((channel_modify(result, chan, items, (char **) item, 0) != OK)) {
  1114. putlog(LOG_ERROR, "*", "Error parsing channel options for %s: %s", chan->dname, result);
  1115. if (!loading)
  1116. ret = ERROR;
  1117. }
  1118. free(item);
  1119. if (join && shouldjoin(chan))
  1120. join_chan(chan);
  1121. return ret;
  1122. }
  1123. /* vim: set sts=2 sw=2 ts=8 et: */