storage_file.c
上传用户:tany51
上传日期:2013-06-12
资源大小:1397k
文件大小:23k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*
  2.  * Copyright (C) 1998,1999,2000,2001  Ross Combs (rocombs@cs.nmsu.edu)
  3.  * Copyright (C) 2000,2001  Marco Ziech (mmz@gmx.net)
  4.  * Copyright (C) 2002,2003 Mihai RUSU (dizzy@rdsnet.ro)
  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. #include "common/setup_before.h"
  21. #include <stdio.h>
  22. #ifdef HAVE_STDDEF_H
  23. # include <stddef.h>
  24. #else
  25. # ifndef NULL
  26. #  define NULL ((void *)0)
  27. # endif
  28. #endif
  29. #ifdef STDC_HEADERS
  30. # include <stdlib.h>
  31. #else
  32. # ifdef HAVE_MALLOC_H
  33. #  include <malloc.h>
  34. # endif
  35. #endif
  36. #ifdef HAVE_STRING_H
  37. # include <string.h>
  38. #else
  39. # ifdef HAVE_STRINGS_H
  40. #  include <strings.h>
  41. # endif
  42. #endif
  43. #include "compat/strchr.h"
  44. #include "compat/strdup.h"
  45. #include "compat/strcasecmp.h"
  46. #include "compat/strncasecmp.h"
  47. #include <ctype.h>
  48. #ifdef HAVE_LIMITS_H
  49. # include <limits.h>
  50. #endif
  51. #include "compat/char_bit.h"
  52. #ifdef TIME_WITH_SYS_TIME
  53. # include <sys/time.h>
  54. # include <time.h>
  55. #else
  56. # ifdef HAVE_SYS_TIME_H
  57. #  include <sys/time.h>
  58. # else
  59. #  include <time.h>
  60. # endif
  61. #endif
  62. #include <errno.h>
  63. #include "compat/strerror.h"
  64. #ifdef HAVE_SYS_TYPES_H
  65. # include <sys/types.h>
  66. #endif
  67. #ifdef HAVE_UNISTD_H
  68. # include <unistd.h>
  69. #else
  70. # ifdef WIN32
  71. #  include <io.h>
  72. # endif
  73. #endif
  74. #include "compat/pdir.h"
  75. #include "common/eventlog.h"
  76. #include "prefs.h"
  77. #include "common/util.h"
  78. #include "common/field_sizes.h"
  79. #include "common/bnethash.h"
  80. #define CLAN_INTERNAL_ACCESS
  81. #define ACCOUNT_INTERNAL_ACCESS
  82. #include "common/introtate.h"
  83. #include "account.h"
  84. #include "common/hashtable.h"
  85. #include "storage.h"
  86. #include "common/list.h"
  87. #include "connection.h"
  88. #include "watch.h"
  89. #include "clan.h"
  90. #undef ACCOUNT_INTERNAL_ACCESS
  91. #undef CLAN_INTERNAL_ACCESS
  92. #include "common/tag.h"
  93. #include "common/setup_after.h"
  94. /* file storage API functions */
  95. static int file_init(const char *);
  96. static int file_close(void);
  97. static t_storage_info *file_create_account(char const *);
  98. static t_storage_info *file_get_defacct(void);
  99. static int file_free_info(t_storage_info *);
  100. static int file_read_attrs(t_storage_info *, t_read_attr_func, void *);
  101. static void *file_read_attr(t_storage_info *, const char *);
  102. static int file_write_attrs(t_storage_info *, void *);
  103. static int file_read_accounts(t_read_accounts_func, void *);
  104. static void *file_read_account(t_read_account_func, const char *);
  105. static int file_cmp_info(t_storage_info *, t_storage_info *);
  106. static const char *file_escape_key(const char *);
  107. static int file_load_clans(t_load_clans_func);
  108. static int file_write_clan(void *);
  109. static int file_remove_clan(int);
  110. static int file_remove_clanmember(int);
  111. /* storage struct populated with the functions above */
  112. t_storage storage_file = {
  113.     file_init,
  114.     file_close,
  115.     file_create_account,
  116.     file_get_defacct,
  117.     file_free_info,
  118.     file_read_attrs,
  119.     file_write_attrs,
  120.     file_read_attr,
  121.     file_read_accounts,
  122.     file_read_account,
  123.     file_cmp_info,
  124.     file_escape_key,
  125.     file_load_clans,
  126.     file_write_clan,
  127.     file_remove_clan,
  128.     file_remove_clanmember
  129. };
  130. /* start of actual file storage code */
  131. static const char *accountsdir = NULL;
  132. static const char *clansdir = NULL;
  133. static const char *defacct = NULL;
  134. static int file_init(const char *path)
  135. {
  136.     char *tok, *copy, *tmp, *p;
  137.     const char *dir = NULL;
  138.     const char *clan = NULL;
  139.     const char *def = NULL;
  140.     if (path == NULL || path[0] == '')
  141.     {
  142. eventlog(eventlog_level_error, __FUNCTION__, "got NULL or empty path");
  143. return -1;
  144.     }
  145.     if ((copy = strdup(path)) == NULL)
  146.     {
  147. eventlog(eventlog_level_error, __FUNCTION__, "could not duplicate path");
  148. return -1;
  149.     }
  150.     tmp = copy;
  151.     while ((tok = strtok(tmp, ";")) != NULL)
  152.     {
  153. tmp = NULL;
  154. if ((p = strchr(tok, '=')) == NULL)
  155. {
  156.     eventlog(eventlog_level_error, __FUNCTION__, "invalid storage_path, no '=' present in token");
  157.     free((void *) copy);
  158.     return -1;
  159. }
  160. *p = '';
  161. if (strcasecmp(tok, "dir") == 0)
  162.     dir = p + 1;
  163. else if (strcasecmp(tok, "clan") == 0)
  164.     clan = p + 1;
  165. else if (strcasecmp(tok, "default") == 0)
  166.     def = p + 1;
  167. else
  168.     eventlog(eventlog_level_warn, __FUNCTION__, "unknown token in storage_path : '%s'", tok);
  169.     }
  170.     if (def == NULL || clan == NULL || dir == NULL)
  171.     {
  172. eventlog(eventlog_level_error, __FUNCTION__, "invalid storage_path line for file module (doesnt have a 'dir', a 'clan' and a 'default' token)");
  173. free((void *) copy);
  174. return -1;
  175.     }
  176.     if (accountsdir)
  177. file_close();
  178.     if ((accountsdir = strdup(dir)) == NULL)
  179.     {
  180. eventlog(eventlog_level_error, __FUNCTION__, "not enough memory to store accounts dir");
  181. free((void *) copy);
  182. return -1;
  183.     }
  184.     if ((clansdir = strdup(clan)) == NULL)
  185.     {
  186. eventlog(eventlog_level_error, __FUNCTION__, "not enough memory to store clans dir");
  187. free((void *) copy);
  188. return -1;
  189.     }
  190.     if ((defacct = strdup(def)) == NULL)
  191.     {
  192. eventlog(eventlog_level_error, __FUNCTION__, "not enough memory to store default account path");
  193. free((void *) accountsdir);
  194. accountsdir = NULL;
  195. free((void *) copy);
  196. return -1;
  197.     }
  198.     free((void *) copy);
  199.     return 0;
  200. }
  201. static int file_close(void)
  202. {
  203.     if (accountsdir)
  204. free((void *) accountsdir);
  205.     accountsdir = NULL;
  206.     if (clansdir)
  207. free((void *) clansdir);
  208.     clansdir = NULL;
  209.     if (defacct)
  210. free((void *) defacct);
  211.     defacct = NULL;
  212.     return 0;
  213. }
  214. static t_storage_info *file_create_account(const char *username)
  215. {
  216.     char *temp;
  217.     if (accountsdir == NULL)
  218.     {
  219. eventlog(eventlog_level_error, __FUNCTION__, "file storage not initilized");
  220. return NULL;
  221.     }
  222.     if (prefs_get_savebyname())
  223.     {
  224. char const *safename;
  225. if (!(safename = escape_fs_chars(username, strlen(username))))
  226. {
  227.     eventlog(eventlog_level_error, __FUNCTION__, "could not escape username");
  228.     return NULL;
  229. }
  230. if (!(temp = malloc(strlen(accountsdir) + 1 + strlen(safename) + 1))) /* dir + / + name + NUL */
  231. {
  232.     eventlog(eventlog_level_error, __FUNCTION__, "could not allocate memory for temp");
  233.     free((void *) safename);
  234.     return NULL;
  235. }
  236. sprintf(temp, "%s/%s", accountsdir, safename);
  237. free((void *) safename); /* avoid warning */
  238.     } else
  239.     {
  240. if (!(temp = malloc(strlen(accountsdir) + 1 + 8 + 1))) /* dir + / + uid + NUL */
  241. {
  242.     eventlog(eventlog_level_error, __FUNCTION__, "could not allocate memory for temp");
  243.     return NULL;
  244. }
  245. sprintf(temp, "%s/%06u", accountsdir, maxuserid + 1); /* FIXME: hmm, maybe up the %06 to %08... */
  246.     }
  247.     return temp;
  248. }
  249. static int file_write_attrs(t_storage_info * info, void *attributes)
  250. {
  251.     FILE *accountfile;
  252.     t_attribute *attr;
  253.     char const *key;
  254.     char const *val;
  255.     char *tempname;
  256.     if (accountsdir == NULL)
  257.     {
  258. eventlog(eventlog_level_error, __FUNCTION__, "file storage not initilized");
  259. return -1;
  260.     }
  261.     if (info == NULL)
  262.     {
  263. eventlog(eventlog_level_error, __FUNCTION__, "got NULL info storage");
  264. return -1;
  265.     }
  266.     if (attributes == NULL)
  267.     {
  268. eventlog(eventlog_level_error, __FUNCTION__, "got NULL attributes");
  269. return -1;
  270.     }
  271.     if (!(tempname = malloc(strlen(accountsdir) + 1 + strlen(BNETD_ACCOUNT_TMP) + 1)))
  272.     {
  273. eventlog(eventlog_level_error, __FUNCTION__, "unable to allocate memory for tempname");
  274. return -1;
  275.     }
  276.     sprintf(tempname, "%s/%s", accountsdir, BNETD_ACCOUNT_TMP);
  277.     if (!(accountfile = fopen(tempname, "w")))
  278.     {
  279. eventlog(eventlog_level_error, __FUNCTION__, "unable to open file "%s" for writing (fopen: %s)", tempname, strerror(errno));
  280. free(tempname);
  281. return -1;
  282.     }
  283.     for (attr = (t_attribute *) attributes; attr; attr = attr->next)
  284.     {
  285. if (attr->key)
  286.     key = escape_chars(attr->key, strlen(attr->key));
  287. else
  288. {
  289.     eventlog(eventlog_level_error, __FUNCTION__, "attribute with NULL key in list");
  290.     key = NULL;
  291. }
  292. if (attr->val)
  293.     val = escape_chars(attr->val, strlen(attr->val));
  294. else
  295. {
  296.     eventlog(eventlog_level_error, __FUNCTION__, "attribute with NULL val in list");
  297.     val = NULL;
  298. }
  299. if (key && val)
  300. {
  301.     if (strncmp("BNET\CharacterDefault\", key, 20) == 0)
  302.     {
  303. eventlog(eventlog_level_debug, __FUNCTION__, "skipping attribute key="%s"", attr->key);
  304.     } else
  305.     {
  306. eventlog(eventlog_level_debug, __FUNCTION__, "saving attribute key="%s" val="%s"", attr->key, attr->val);
  307. fprintf(accountfile, ""%s"="%s"n", key, val);
  308.     }
  309. } else
  310.     eventlog(eventlog_level_error, __FUNCTION__, "could not save attribute key="%s"", attr->key);
  311. if (key)
  312.     free((void *) key); /* avoid warning */
  313. if (val)
  314.     free((void *) val); /* avoid warning */
  315.     }
  316.     if (fclose(accountfile) < 0)
  317.     {
  318. eventlog(eventlog_level_error, __FUNCTION__, "could not close account file "%s" after writing (fclose: %s)", tempname, strerror(errno));
  319. free(tempname);
  320. return -1;
  321.     }
  322. #ifdef WIN32
  323.     /* We are about to rename the temporary file
  324.      * to replace the existing account.  In Windows,
  325.      * we have to remove the previous file or the
  326.      * rename function will fail saying the file
  327.      * already exists.  This defeats the purpose of
  328.      * the rename which was to make this an atomic
  329.      * operation.  At least the race window is small.
  330.      */
  331.     if (access((const char *) info, 0) == 0)
  332.     {
  333. if (remove((const char *) info) < 0)
  334. {
  335.     eventlog(eventlog_level_error, __FUNCTION__, "could not delete account file "%s" (remove: %s)", (char *) info, strerror(errno));
  336.     free(tempname);
  337.     return -1;
  338. }
  339.     }
  340. #endif
  341.     if (rename(tempname, (const char *) info) < 0)
  342.     {
  343. eventlog(eventlog_level_error, __FUNCTION__, "could not rename account file to "%s" (rename: %s)", (char *) info, strerror(errno));
  344. free(tempname);
  345. return -1;
  346.     }
  347.     free(tempname);
  348.     return 0;
  349. }
  350. static int file_read_attrs(t_storage_info * info, t_read_attr_func cb, void *data)
  351. {
  352.     FILE *accountfile;
  353.     unsigned int line;
  354.     char const *buff;
  355.     unsigned int len;
  356.     char *esckey;
  357.     char *escval;
  358.     char *key;
  359.     char *val;
  360.     if (accountsdir == NULL)
  361.     {
  362. eventlog(eventlog_level_error, __FUNCTION__, "file storage not initilized");
  363. return -1;
  364.     }
  365.     if (info == NULL)
  366.     {
  367. eventlog(eventlog_level_error, __FUNCTION__, "got NULL info storage");
  368. return -1;
  369.     }
  370.     if (cb == NULL)
  371.     {
  372. eventlog(eventlog_level_error, __FUNCTION__, "got NULL callback");
  373. return -1;
  374.     }
  375.     eventlog(eventlog_level_debug, __FUNCTION__, "loading "%s"", (char *) info);
  376.     if (!(accountfile = fopen((const char *) info, "r")))
  377.     {
  378. eventlog(eventlog_level_error, __FUNCTION__, "could not open account file "%s" for reading (fopen: %s)", (char *) info, strerror(errno));
  379. return -1;
  380.     }
  381.     for (line = 1; (buff = file_get_line(accountfile)); line++)
  382.     {
  383. if (buff[0] == '#' || buff[0] == '')
  384. {
  385.     free((void *) buff); /* avoid warning */
  386.     continue;
  387. }
  388. if (strlen(buff) < 6) /* "?"="" */
  389. {
  390.     eventlog(eventlog_level_error, __FUNCTION__, "malformed line %d of account file "%s"", line, (char *) info);
  391.     free((void *) buff); /* avoid warning */
  392.     continue;
  393. }
  394. len = strlen(buff) - 5 + 1; /* - ""="" + NUL */
  395. if (!(esckey = malloc(len)))
  396. {
  397.     eventlog(eventlog_level_error, __FUNCTION__, "could not allocate memory for esckey on line %d of account file "%s"", line, (char *) info);
  398.     free((void *) buff); /* avoid warning */
  399.     continue;
  400. }
  401. if (!(escval = malloc(len)))
  402. {
  403.     eventlog(eventlog_level_error, __FUNCTION__, "could not allocate memory for escval on line %d of account file "%s"", line, (char *) info);
  404.     free((void *) buff); /* avoid warning */
  405.     free(esckey);
  406.     continue;
  407. }
  408. if (sscanf(buff, ""%[^"]" = "%[^"]"", esckey, escval) != 2)
  409. {
  410.     if (sscanf(buff, ""%[^"]" = """, esckey) != 1) /* hack for an empty value field */
  411.     {
  412. eventlog(eventlog_level_error, __FUNCTION__, "malformed entry on line %d of account file "%s"", line, (char *) info);
  413. free(escval);
  414. free(esckey);
  415. free((void *) buff); /* avoid warning */
  416. continue;
  417.     }
  418.     escval[0] = '';
  419. }
  420. free((void *) buff); /* avoid warning */
  421. key = unescape_chars(esckey);
  422. val = unescape_chars(escval);
  423. /* eventlog(eventlog_level_debug,"account_load_attrs","strlen(esckey)=%u (%c), len=%u",strlen(esckey),esckey[0],len);*/
  424. free(esckey);
  425. free(escval);
  426. if (cb(key, val, data))
  427.     eventlog(eventlog_level_error, __FUNCTION__, "got error from callback (key: '%s' val:'%s')", key, val);
  428. if (key)
  429.     free((void *) key); /* avoid warning */
  430. if (val)
  431.     free((void *) val); /* avoid warning */
  432.     }
  433.     if (fclose(accountfile) < 0)
  434. eventlog(eventlog_level_error, __FUNCTION__, "could not close account file "%s" after reading (fclose: %s)", (char *) info, strerror(errno));
  435.     return 0;
  436. }
  437. static void *file_read_attr(t_storage_info * info, const char *key)
  438. {
  439.     /* flat file storage doesnt know to read selective attributes */
  440.     return NULL;
  441. }
  442. static int file_free_info(t_storage_info * info)
  443. {
  444.     if (info)
  445. free((void *) info);
  446.     return 0;
  447. }
  448. static t_storage_info *file_get_defacct(void)
  449. {
  450.     t_storage_info *info;
  451.     if (defacct == NULL)
  452.     {
  453. eventlog(eventlog_level_error, __FUNCTION__, "file storage not initilized");
  454. return NULL;
  455.     }
  456.     if ((info = strdup(defacct)) == NULL)
  457.     {
  458. eventlog(eventlog_level_error, __FUNCTION__, "could not duplicate default account filename");
  459. return NULL;
  460.     }
  461.     return info;
  462. }
  463. static int file_read_accounts(t_read_accounts_func cb, void *data)
  464. {
  465.     char const *dentry;
  466.     char *pathname;
  467.     t_pdir *accountdir;
  468.     if (accountsdir == NULL)
  469.     {
  470. eventlog(eventlog_level_error, __FUNCTION__, "file storage not initilized");
  471. return -1;
  472.     }
  473.     if (cb == NULL)
  474.     {
  475. eventlog(eventlog_level_error, __FUNCTION__, "got NULL callback");
  476. return -1;
  477.     }
  478.     if (!(accountdir = p_opendir(accountsdir)))
  479.     {
  480. eventlog(eventlog_level_error, __FUNCTION__, "unable to open user directory "%s" for reading (p_opendir: %s)", accountsdir, strerror(errno));
  481. return -1;
  482.     }
  483.     while ((dentry = p_readdir(accountdir)))
  484.     {
  485. if (dentry[0] == '.')
  486.     continue;
  487. if (!(pathname = malloc(strlen(accountsdir) + 1 + strlen(dentry) + 1))) /* dir + / + file + NUL */
  488. {
  489.     eventlog(eventlog_level_error, __FUNCTION__, "could not allocate memory for pathname");
  490.     continue;
  491. }
  492. sprintf(pathname, "%s/%s", accountsdir, dentry);
  493. cb(pathname, data);
  494.     }
  495.     if (p_closedir(accountdir) < 0)
  496. eventlog(eventlog_level_error, __FUNCTION__, "unable to close user directory "%s" (p_closedir: %s)", accountsdir, strerror(errno));
  497.     return 0;
  498. }
  499. static void *file_read_account(t_read_account_func cb, const char *accname)
  500. {
  501.     char *pathname;
  502.     if (accountsdir == NULL)
  503.     {
  504. eventlog(eventlog_level_error, __FUNCTION__, "file storage not initilized");
  505. return NULL;
  506.     }
  507.     if (cb == NULL)
  508.     {
  509. eventlog(eventlog_level_error, __FUNCTION__, "got NULL callback");
  510. return NULL;
  511.     }
  512.     if (!(pathname = malloc(strlen(accountsdir) + 1 + strlen(accname) + 1))) /* dir + / + file + NUL */
  513.     {
  514. eventlog(eventlog_level_error, __FUNCTION__, "could not allocate memory for pathname");
  515. return NULL;
  516.     }
  517.     sprintf(pathname, "%s/%s", accountsdir, accname);
  518.     if (access(pathname, 0)) /* if it doesn't exist */
  519.     {
  520. free((void *) pathname);
  521. return NULL;
  522.     }
  523.     return cb(pathname);
  524. }
  525. static int file_cmp_info(t_storage_info * info1, t_storage_info * info2)
  526. {
  527.     return strcmp((const char *) info1, (const char *) info2);
  528. }
  529. static const char *file_escape_key(const char *key)
  530. {
  531.     return key;
  532. }
  533. static int file_load_clans(t_load_clans_func cb)
  534. {
  535.     char const *dentry;
  536.     t_pdir *clandir;
  537.     char *pathname;
  538.     int clantag;
  539.     t_clan *clan;
  540.     FILE *fp;
  541.     char *clanname, *motd, *p;
  542.     char line[1024];
  543.     int cid, creation_time;
  544.     int member_uid, member_join_time;
  545.     char member_status;
  546.     t_clanmember *member;
  547.     if (cb == NULL)
  548.     {
  549. eventlog(eventlog_level_error, __FUNCTION__, "get NULL callback");
  550. return -1;
  551.     }
  552.     if (!(clandir = p_opendir(clansdir)))
  553.     {
  554. eventlog(eventlog_level_error, __FUNCTION__, "unable to open clan directory "%s" for reading (p_opendir: %s)", clansdir, strerror(errno));
  555. return -1;
  556.     }
  557.     eventlog(eventlog_level_trace, __FUNCTION__, "start reading clans");
  558.     if (!(pathname = malloc(strlen(clansdir) + 1 + 4 + 1)))
  559.     {
  560. eventlog(eventlog_level_error, __FUNCTION__, "could not allocate memory for pathname");
  561. return -1;
  562.     }
  563.     while ((dentry = p_readdir(clandir)) != NULL)
  564.     {
  565. if (dentry[0] == '.')
  566.     continue;
  567. if (strlen(dentry) > 4)
  568. {
  569.     eventlog(eventlog_level_error, __FUNCTION__, "found too long clan filename in clandir "%s"", dentry);
  570.     continue;
  571. }
  572. sprintf(pathname, "%s/%s", clansdir, dentry);
  573. clantag = str_to_clantag(dentry);
  574. if ((fp = fopen(pathname, "r")) == NULL)
  575. {
  576.     eventlog(eventlog_level_error, __FUNCTION__, "can't open clanfile "%s"", pathname);
  577.     continue;
  578. }
  579. if (!(clan = malloc(sizeof(t_clan))))
  580. {
  581.     eventlog(eventlog_level_error, __FUNCTION__, "could not allocate memory for clan");
  582.     free((void *) pathname);
  583.     p_closedir(clandir);
  584.     return -1;
  585. }
  586. clan->clantag = clantag;
  587. if (!fgets(line, 1024, fp))
  588. {
  589.     eventlog(eventlog_level_error, __FUNCTION__, "invalid clan file: no first line");
  590.     free((void*)clan);
  591.     continue;
  592. }
  593. clanname = line;
  594. if (*clanname != '"')
  595. {
  596.     eventlog(eventlog_level_error, __FUNCTION__, "invalid clan file: invalid first line");
  597.     free((void*)clan);
  598.     continue;
  599. }
  600. clanname++;
  601. p = strchr(clanname, '"');
  602. if (!p)
  603. {
  604.     eventlog(eventlog_level_error, __FUNCTION__, "invalid clan file: invalid first line");
  605.     free((void*)clan);
  606.     continue;
  607. }
  608. *p = '';
  609. if (strlen(clanname) >= CLAN_NAME_MAX)
  610. {
  611.     eventlog(eventlog_level_error, __FUNCTION__, "invalid clan file: invalid first line");
  612.     free((void*)clan);
  613.     continue;
  614. }
  615. p++;
  616. if (*p != ',')
  617. {
  618.     eventlog(eventlog_level_error, __FUNCTION__, "invalid clan file: invalid first line");
  619.     free((void*)clan);
  620.     continue;
  621. }
  622. p++;
  623. if (*p != '"')
  624. {
  625.     eventlog(eventlog_level_error, __FUNCTION__, "invalid clan file: invalid first line");
  626.     free((void*)clan);
  627.     continue;
  628. }
  629. motd = p + 1;
  630. p = strchr(motd, '"');
  631. if (!p)
  632. {
  633.     eventlog(eventlog_level_error, __FUNCTION__, "invalid clan file: invalid first line");
  634.     free((void*)clan);
  635.     continue;
  636. }
  637. *p = '';
  638. if (sscanf(p + 1, ",%d,%dn", &cid, &creation_time) != 2)
  639. {
  640.     eventlog(eventlog_level_error, __FUNCTION__, "invalid first line in clanfile");
  641.     free((void*)clan);
  642.     continue;
  643. }
  644. if ((clan->clanname = strdup(clanname)) == NULL)
  645. {
  646.     eventlog(eventlog_level_error, __FUNCTION__, "not enough memory to store clanname");
  647.     free((void*)clan);
  648.     continue;
  649. }
  650. if ((clan->clan_motd = strdup(motd)) == NULL)
  651. {
  652.     eventlog(eventlog_level_error, __FUNCTION__, "not enough memory to store motd");
  653.     free((void*)clan);
  654.     continue;
  655. }
  656. clan->clanid = cid;
  657. clan->creation_time = (time_t) creation_time;
  658. clan->created = 1;
  659. clan->modified = 0;
  660. clan->channel_type = prefs_get_clan_channel_default_private();
  661. eventlog(eventlog_level_trace, __FUNCTION__, "name: %s motd: %s clanid: %i time: %i", clanname, motd, cid, creation_time);
  662. if ((clan->members = list_create()) == NULL)
  663. {
  664.     eventlog(eventlog_level_error, __FUNCTION__, "could not allocate memory for clan members");
  665.     free((void*)clan);
  666.     free((void *) pathname);
  667.     p_closedir(clandir);
  668.     return -1;
  669. }
  670. while (fscanf(fp, "%i,%c,%in", &member_uid, &member_status, &member_join_time) == 3)
  671. {
  672.     if (!(member = malloc(sizeof(t_clanmember))))
  673.     {
  674. eventlog(eventlog_level_error, __FUNCTION__, "cannot allocate memory for clan member");
  675. clan_remove_all_members(clan);
  676. free((void *) clan->clanname);
  677. free((void *) clan->clan_motd);
  678. free((void *) clan);
  679. fclose(fp);
  680. free((void *) pathname);
  681. p_closedir(clandir);
  682. return -1;
  683.     }
  684.     if (!(member->memberacc = accountlist_find_account_by_uid(member_uid)))
  685.     {
  686. eventlog(eventlog_level_error, __FUNCTION__, "cannot find uid %u", member_uid);
  687. free((void *) member);
  688. continue;
  689.     }
  690.     member->memberconn = NULL;
  691.     member->status = member_status - '0';
  692.     member->join_time = member_join_time;
  693.     member->clan = clan;
  694.     if ((member->status == CLAN_NEW) && (time(NULL) - member->join_time > prefs_get_clan_newer_time() * 3600))
  695.     {
  696. member->status = CLAN_PEON;
  697. clan->modified = 1;
  698.     }
  699.     if (list_append_data(clan->members, member) < 0)
  700.     {
  701. eventlog(eventlog_level_error, __FUNCTION__, "could not append item");
  702. free((void *) member);
  703. clan_remove_all_members(clan);
  704. free((void *) clan->clanname);
  705. free((void *) clan->clan_motd);
  706. free((void *) clan);
  707. fclose(fp);
  708. free((void *) pathname);
  709. p_closedir(clandir);
  710. return -1;
  711.     }
  712.     account_set_clanmember(member->memberacc, member);
  713.     eventlog(eventlog_level_trace, __FUNCTION__, "added member: uid: %i status: %c join_time: %i", member_uid, member_status + '0', member_join_time);
  714. }
  715. fclose(fp);
  716. cb(clan);
  717.     }
  718.     free((void *) pathname);
  719.     if (p_closedir(clandir) < 0)
  720.     {
  721. eventlog(eventlog_level_error, __FUNCTION__, "unable to close clan directory "%s" (p_closedir: %s)", clansdir, strerror(errno));
  722.     }
  723.     eventlog(eventlog_level_trace, __FUNCTION__, "finished reading clans");
  724.     return 0;
  725. }
  726. static int file_write_clan(void *data)
  727. {
  728.     FILE *fp;
  729.     t_elem *curr;
  730.     t_clanmember *member;
  731.     char *clanfile;
  732.     t_clan *clan = (t_clan *) data;
  733.     if (!(clanfile = malloc(strlen(clansdir) + 1 + 4 + 1)))
  734.     {
  735. eventlog(eventlog_level_error, __FUNCTION__, "could not allocate memory for filename");
  736. return -1;
  737.     }
  738.     sprintf(clanfile, "%s/%c%c%c%c", clansdir, clan->clantag >> 24, (clan->clantag >> 16) & 0xff, (clan->clantag >> 8) & 0xff, clan->clantag & 0xff);
  739.     if ((fp = fopen(clanfile, "w")) == NULL)
  740.     {
  741. eventlog(eventlog_level_error, __FUNCTION__, "can't open clanfile "%s"", clanfile);
  742. free((void *) clanfile);
  743. return -1;
  744.     }
  745.     fprintf(fp, ""%s","%s",%i,%in", clan->clanname, clan->clan_motd, clan->clanid, (int) clan->creation_time);
  746.     LIST_TRAVERSE(clan->members, curr)
  747.     {
  748. if (!(member = elem_get_data(curr)))
  749. {
  750.     eventlog(eventlog_level_error, __FUNCTION__, "got NULL elem in list");
  751.     continue;
  752. }
  753. if ((member->status == CLAN_NEW) && (time(NULL) - member->join_time > prefs_get_clan_newer_time() * 3600))
  754.     member->status = CLAN_PEON;
  755. fprintf(fp, "%i,%c,%un", account_get_uid(member->memberacc), member->status + '0', (unsigned) member->join_time);
  756.     }
  757.     fclose(fp);
  758.     free((void *) clanfile);
  759.     return 0;
  760. }
  761. static int file_remove_clan(int clantag)
  762. {
  763.     char *tempname;
  764.     if (!(tempname = malloc(strlen(clansdir) + 1 + 4 + 1)))
  765.     {
  766. eventlog(eventlog_level_error, __FUNCTION__, "could not allocate memory for pathname");
  767. return -1;
  768.     }
  769.     sprintf(tempname, "%s/%c%c%c%c", clansdir, clantag >> 24, (clantag >> 16) & 0xff, (clantag >> 8) & 0xff, clantag & 0xff);
  770.     if (remove((const char *) tempname) < 0)
  771.     {
  772. eventlog(eventlog_level_error, __FUNCTION__, "could not delete clan file "%s" (remove: %s)", (char *) tempname, strerror(errno));
  773. free(tempname);
  774. return -1;
  775.     }
  776.     free(tempname);
  777.     return 0;
  778. }
  779. static int file_remove_clanmember(int uid)
  780. {
  781.     return 0;
  782. }