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

MySQL数据库

开发平台:

Visual C++

  1. /*
  2.  * Copyright (C) 2000 Onlyer (onlyer@263.net)
  3.  * Copyright (C) 2001 Ross Combs (ross@bnetd.org)
  4.  * Copyright (C) 2002 Gianluigi Tiesi (sherpya@netfarm.it)
  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. #define VERSIONCHECK_INTERNAL_ACCESS
  21. #include "common/setup_before.h"
  22. #include <stdio.h>
  23. #ifdef HAVE_STDDEF_H
  24. # include <stddef.h>
  25. #else
  26. # ifndef NULL
  27. #  define NULL ((void *)0)
  28. # endif
  29. #endif
  30. #ifdef STDC_HEADERS
  31. # include <stdlib.h>
  32. #else
  33. # ifdef HAVE_MALLOC_H
  34. #  include <malloc.h>
  35. # endif
  36. #endif
  37. #include "compat/strtoul.h"
  38. #ifdef HAVE_STRING_H
  39. # include <string.h>
  40. #else
  41. # ifdef HAVE_STRINGS_H
  42. #  include <strings.h>
  43. # endif
  44. #endif
  45. #ifdef HAVE_MKTIME
  46. # ifdef TIME_WITH_SYS_TIME
  47. #  include <sys/time.h>
  48. #  include <time.h>
  49. # else
  50. #  ifdef HAVE_SYS_TIME_H
  51. #   include <sys/time.h>
  52. #  else
  53. #   include <time.h>
  54. #  endif
  55. # endif
  56. #endif
  57. #include "compat/strchr.h"
  58. #include "compat/strdup.h"
  59. #include "compat/strcasecmp.h"
  60. #include <ctype.h>
  61. #include <errno.h>
  62. #include "compat/strerror.h"
  63. #include "common/eventlog.h"
  64. #include "common/list.h"
  65. #include "common/util.h"
  66. #include "common/proginfo.h"
  67. #include "common/token.h"
  68. #include "common/field_sizes.h"
  69. #include "prefs.h"
  70. #include "versioncheck.h"
  71. #include "common/setup_after.h"
  72. static t_list * versioninfo_head=NULL;
  73. static t_versioncheck dummyvc={ "A=42 B=42 C=42 4 A=A^S B=B^B C=C^C A=A^S", "IX86ver1.mpq", "NoVC" };
  74. static int versioncheck_compare_exeinfo(t_parsed_exeinfo * pattern, t_parsed_exeinfo * match);
  75. extern t_versioncheck * versioncheck_create(char const * archtag, char const * clienttag)
  76. {
  77.     t_elem const *   curr;
  78.     t_versioninfo *  vi;
  79.     t_versioncheck * vc;
  80.     
  81.     LIST_TRAVERSE_CONST(versioninfo_head,curr)
  82.     {
  83.         if (!(vi = elem_get_data(curr))) /* should not happen */
  84.         {
  85.             eventlog(eventlog_level_error,"versioncheck_create","version list contains NULL item");
  86.             continue;
  87.         }
  88. eventlog(eventlog_level_debug,"versioncheck_create","version check entry archtag=%s, clienttag=%s",vi->archtag,vi->clienttag);
  89. if (strcmp(vi->archtag,archtag)!=0)
  90.     continue;
  91. if (strcmp(vi->clienttag,clienttag)!=0)
  92.     continue;
  93. /* FIXME: randomize the selection if more than one match */
  94. if (!(vc = malloc(sizeof(t_versioncheck))))
  95. {
  96.     eventlog(eventlog_level_error,"versioncheck_create","unable to allocate memory for vc");
  97.     return &dummyvc;
  98. }
  99. if (!(vc->eqn = strdup(vi->eqn)))
  100. {
  101.     eventlog(eventlog_level_error,"versioncheck_create","unable to allocate memory for eqn");
  102.     free(vc);
  103.     return &dummyvc;
  104. }
  105. if (!(vc->mpqfile = strdup(vi->mpqfile)))
  106. {
  107.     eventlog(eventlog_level_error,"versioncheck_create","unable to allocate memory for mpqfile");
  108.     free((void *)vc->eqn); /* avoid warning */
  109.     free(vc);
  110.     return &dummyvc;
  111. }
  112. vc->versiontag = strdup(clienttag);
  113. return vc;
  114.     }
  115.     
  116.     /*
  117.      * No entries in the file that match, return the dummy because we have to send
  118.      * some equation and auth mpq to the client.  The client is not going to pass the
  119.      * validation later unless skip_versioncheck or allow_unknown_version is enabled.
  120.      */
  121.     return &dummyvc;
  122. }
  123. extern int versioncheck_destroy(t_versioncheck * vc)
  124. {
  125.     if (!vc)
  126.     {
  127. eventlog(eventlog_level_error,"versioncheck_destroy","got NULL vc");
  128. return -1;
  129.     }
  130.     
  131.     if (vc==&dummyvc)
  132. return 0;
  133.     
  134.     free((void *)vc->versiontag);
  135.     free((void *)vc->mpqfile);
  136.     free((void *)vc->eqn);
  137.     free(vc);
  138.     
  139.     return 0;
  140. }
  141. extern int versioncheck_set_versiontag(t_versioncheck * vc, char const * versiontag)
  142. {
  143.     if (!vc) {
  144. eventlog(eventlog_level_error,"versioncheck_set_versiontag","got NULL vc");
  145. return -1;
  146.     }
  147.     if (!versiontag) {
  148. eventlog(eventlog_level_error,"versioncheck_set_versiontag","got NULL versiontag");
  149. return -1;
  150.     }
  151.     
  152.     if (vc->versiontag!=NULL) free((void *)vc->versiontag);
  153.     vc->versiontag = strdup(versiontag);
  154.     return 0;
  155. }
  156. extern char const * versioncheck_get_versiontag(t_versioncheck const * vc)
  157. {
  158.     if (!vc) {
  159. eventlog(eventlog_level_error,"versioncheck_get_versiontag","got NULL vc");
  160. return NULL;
  161.     }
  162.     
  163.     return vc->versiontag;
  164. }
  165. extern char const * versioncheck_get_mpqfile(t_versioncheck const * vc)
  166. {
  167.     if (!vc)
  168.     {
  169. eventlog(eventlog_level_error,"versioncheck_get_mpqfile","got NULL vc");
  170. return NULL;
  171.     }
  172.     
  173.     return vc->mpqfile;
  174. }
  175. extern char const * versioncheck_get_eqn(t_versioncheck const * vc)
  176. {
  177.     if (!vc)
  178.     {
  179. eventlog(eventlog_level_error,"versioncheck_get_mpqfile","got NULL vc");
  180. return NULL;
  181.     }
  182.     
  183.     return vc->eqn;
  184. }
  185. t_parsed_exeinfo * parse_exeinfo(char const * exeinfo)
  186. {
  187.   t_parsed_exeinfo * parsed_exeinfo;
  188.     if (!exeinfo) {
  189. return NULL;
  190.     }
  191.     if (!(parsed_exeinfo = malloc(sizeof(t_parsed_exeinfo))))
  192.     {
  193.       eventlog(eventlog_level_error,__FUNCTION__,"could not allocate memory for parsed exeinfo");
  194.       return NULL;
  195.     }
  196.     if (!(parsed_exeinfo->exe = strdup(exeinfo)))
  197.     {
  198.       free((void *)parsed_exeinfo);
  199.       eventlog(eventlog_level_error,__FUNCTION__,"could not duplicate exeinfo");
  200.       return NULL;
  201.     }
  202.     parsed_exeinfo->time = 0;
  203.     parsed_exeinfo->size = 0;
  204.     
  205.     if (strcmp(prefs_get_version_exeinfo_match(),"parse")==0) 
  206.     {
  207. #ifdef HAVE_MKTIME
  208. struct tm t1;
  209. char *exe;
  210. char mask[MAX_EXEINFO_STR+1];
  211. char * marker;
  212. int size;
  213.         char time_invalid = 0;
  214. if ((exeinfo[0]=='') ||    //happens when using war3-noCD and having deleted war3.org
  215.     (strcmp(exeinfo,"badexe")==0)) //happens when AUTHREQ had no owner/exeinfo entry
  216. {
  217.           free((void *)parsed_exeinfo->exe);
  218.           free((void *)parsed_exeinfo);
  219.           eventlog(eventlog_level_error,__FUNCTION__,"found empty exeinfo");
  220.           return NULL;
  221. }
  222.         memset(&t1,0,sizeof(t1));
  223.         t1.tm_isdst = -1;
  224.         exeinfo    = strreverse((char *)exeinfo);
  225.         if (!(marker     = strchr(exeinfo,' ')))
  226.         {
  227.   free((void *)parsed_exeinfo->exe);
  228.   free((void *)parsed_exeinfo);
  229.   return NULL;
  230.         }
  231. for (; marker[0]==' ';marker++); 
  232.         if (!(marker     = strchr(marker,' ')))
  233.         {
  234.   free((void *)parsed_exeinfo->exe);
  235.   free((void *)parsed_exeinfo);
  236.   return NULL;
  237. for (; marker[0]==' ';marker++);
  238.         if (!(marker     = strchr(marker,' ')))
  239.         {
  240.   free((void *)parsed_exeinfo->exe);
  241.   free((void *)parsed_exeinfo);
  242.   return NULL;
  243. }
  244.         for (; marker[0]==' ';marker++);
  245.         marker--;
  246.         marker[0]  = '';
  247.         marker++; 
  248.         
  249.         if (!(exe = strdup(marker)))
  250.         {
  251.           free((void *)parsed_exeinfo->exe);
  252.           free((void *)parsed_exeinfo);
  253.           eventlog(eventlog_level_error,__FUNCTION__,"could not duplicate exe");
  254.           return NULL;
  255.         }
  256.         free((void *)parsed_exeinfo->exe);
  257.         parsed_exeinfo->exe = strreverse((char *)exe);
  258.         exeinfo    = strreverse((char *)exeinfo);
  259. sprintf(mask,"%%02u/%%02u/%%u %%02u:%%02u:%%02u %%u");
  260. if (sscanf(exeinfo,mask,&t1.tm_mon,&t1.tm_mday,&t1.tm_year,&t1.tm_hour,&t1.tm_min,&t1.tm_sec,&size)!=7) {
  261.             if (sscanf(exeinfo,"%*s %*s %u",&size) != 1)
  262.             {
  263.       eventlog(eventlog_level_warn,__FUNCTION__,"parser error while parsing pattern "%s"",exeinfo);
  264.       free((void *)parsed_exeinfo->exe);
  265.       free((void *)parsed_exeinfo);
  266.       return NULL; /* neq */
  267.             }
  268.             time_invalid=1;
  269. }
  270.        /* Now we have a Y2K problem :)  Thanks for using a 2 digit decimal years, Blizzard. */ 
  271.        /* 00-79 -> 2000-2079 
  272. *             * 80-99 -> 1980-1999 
  273. *             * 100+ unchanged */ 
  274.        if (t1.tm_year<80) 
  275.  t1.tm_year = t1.tm_year + 100; 
  276.        if (time_invalid)
  277.          parsed_exeinfo->time = -1;
  278.        else 
  279.          parsed_exeinfo->time = mktime(&t1);
  280.        parsed_exeinfo->size = size;
  281. #else
  282. eventlog(eventlog_level_error,__FUNCTION__,"Your system does not support mktime(). Please select another exeinfo matching method.");
  283. return NULL;
  284. #endif
  285.   }
  286.   return parsed_exeinfo;
  287. }
  288. #define safe_toupper(X) (islower((int)X)?toupper((int)X):(X))
  289. /* This implements some dumb kind of pattern matching. Any '?'
  290.  * signs in the pattern are treated as "don't care" signs. This
  291.  * means that it doesn't matter what's on this place in the match.
  292.  */
  293. //static int versioncheck_compare_exeinfo(char const * pattern, char const * match)
  294. static int versioncheck_compare_exeinfo(t_parsed_exeinfo * pattern, t_parsed_exeinfo * match)
  295. {
  296.     if (!pattern) {
  297. eventlog(eventlog_level_error,"versioncheck_compare_exeinfo","got NULL pattern");
  298. return -1; /* neq/fail */
  299.     }
  300.     if (!match) {
  301. eventlog(eventlog_level_error,"versioncheck_compare_exeinfo","got NULL match");
  302. return -1; /* neq/fail */
  303.     }
  304.     if (strlen(pattern->exe)!=strlen(match->exe))
  305.      return 1; /* neq */
  306.     
  307.     if (strcmp(prefs_get_version_exeinfo_match(),"exact")==0) {
  308. return strcasecmp(pattern->exe,match->exe);
  309.     } else if (strcmp(prefs_get_version_exeinfo_match(),"exactcase")==0) {
  310. return strcmp(pattern->exe,match->exe);
  311.     } else if (strcmp(prefs_get_version_exeinfo_match(),"wildcard")==0) {
  312.      unsigned int i;
  313.     
  314.      for (i=0;i<strlen(pattern->exe);i++)
  315.          if ((pattern->exe[i]!='?')&& /* out "don't care" sign */
  316.           (safe_toupper(pattern->exe[i])!=safe_toupper(match->exe[i])))
  317.           return 1; /* neq */
  318.      return 0; /* ok */
  319.     } else if (strcmp(prefs_get_version_exeinfo_match(),"parse")==0) {
  320.        
  321.        if (strcasecmp(pattern->exe,match->exe)!=0)
  322.             {
  323.             eventlog(eventlog_level_trace,__FUNCTION__,"filename differs");
  324.     return 1; /* neq */
  325.             }
  326. if (pattern->size!=match->size)
  327.             {
  328.             eventlog(eventlog_level_trace,__FUNCTION__,"size differs");
  329.     return 1; /* neq */
  330.             }
  331. if ((pattern->time!=-1) && prefs_get_version_exeinfo_maxdiff() && (abs(pattern->time-match->time)>(signed)prefs_get_version_exeinfo_maxdiff()))
  332.             {
  333.             eventlog(eventlog_level_trace,__FUNCTION__,"time differs by %i",abs(pattern->time-match->time));
  334.     return 1;
  335.             }
  336. return 0; /* ok */
  337.     } else {
  338. eventlog(eventlog_level_error,"versioncheck_compare_exeinfo","unknown version exeinfo match method "%s"",prefs_get_version_exeinfo_match());
  339. return -1; /* neq/fail */
  340.     }
  341. }
  342. void free_parsed_exeinfo(t_parsed_exeinfo * parsed_exeinfo)
  343. {
  344.   if (parsed_exeinfo)
  345.   {
  346.     if (parsed_exeinfo->exe) 
  347.       free((void *)parsed_exeinfo->exe);
  348.     free((void *)parsed_exeinfo);
  349.   }
  350. }
  351. extern int versioncheck_validate(t_versioncheck * vc, char const * archtag, char const * clienttag, char const * exeinfo, unsigned long versionid, unsigned long gameversion, unsigned long checksum)
  352. {
  353.     t_elem const     * curr;
  354.     t_versioninfo    * vi;
  355.     int                badexe,badcs;
  356.     t_parsed_exeinfo * parsed_exeinfo;
  357.     
  358.     if (!vc)
  359.     {
  360. eventlog(eventlog_level_error,"versioncheck_validate","got NULL vc");
  361. return -1;
  362.     }
  363.     
  364.     badexe=badcs = 0;
  365.     parsed_exeinfo = parse_exeinfo(exeinfo);
  366.     LIST_TRAVERSE_CONST(versioninfo_head,curr)
  367.     {
  368.         if (!(vi = elem_get_data(curr))) /* should not happen */
  369.         {
  370.     eventlog(eventlog_level_error,"versioncheck_validate","version list contains NULL item");
  371.     continue;
  372.         }
  373. if (strcmp(vi->eqn,vc->eqn)!=0)
  374.     continue;
  375. if (strcmp(vi->mpqfile,vc->mpqfile)!=0)
  376.     continue;
  377. if (strcmp(vi->archtag,archtag)!=0)
  378.     continue;
  379. if (strcmp(vi->clienttag,clienttag)!=0)
  380.     continue;
  381. if (vi->versionid && vi->versionid != versionid)
  382.     continue;
  383. if (vi->gameversion && vi->gameversion != gameversion)
  384.     continue;
  385. if ((!(parsed_exeinfo)) || (vi->parsed_exeinfo && (versioncheck_compare_exeinfo(vi->parsed_exeinfo,parsed_exeinfo) != 0)))
  386. {
  387.     /*
  388.      * Found an entry matching but the exeinfo doesn't match.
  389.      * We need to rember this because if no other matching versions are found
  390.      * we will return badversion.
  391.      */
  392.     badexe = 1;
  393. }
  394. else
  395.     badexe = 0;
  396. if (vi->checksum && vi->checksum != checksum)
  397. {
  398.     /*
  399.      * Found an entry matching but the checksum doesn't match.
  400.      * We need to rember this because if no other matching versions are found
  401.      * we will return badversion.
  402.      */
  403.     badcs = 1;
  404. }
  405. else
  406.     badcs = 0;
  407. if (vc->versiontag)
  408.     free((void *)vc->versiontag);
  409. vc->versiontag = strdup(vi->versiontag);
  410. if (badexe || badcs)
  411.     continue;
  412. /* Ok, version and checksum matches or exeinfo/checksum are disabled
  413.  * anyway we have found a complete match */
  414. eventlog(eventlog_level_info,"versioncheck_validate","got a matching entry: %s",vc->versiontag);
  415.         free_parsed_exeinfo(parsed_exeinfo);
  416. return 1;
  417.     }
  418.     
  419.     if (badcs) /* A match was found but the checksum was different */
  420.     {
  421. eventlog(eventlog_level_info,"versioncheck_validate","bad checksum, closest match is: %s",vc->versiontag);
  422.         free_parsed_exeinfo(parsed_exeinfo);
  423. return -1;
  424.     }
  425.     if (badexe) /* A match was found but the exeinfo string was different */
  426.     {
  427. eventlog(eventlog_level_info,"versioncheck_validate","bad exeinfo, closest match is: %s",vc->versiontag);
  428.         free_parsed_exeinfo(parsed_exeinfo);
  429. return -1;
  430.     }
  431.     
  432.     /* No match in list */
  433.     eventlog(eventlog_level_info,"versioncheck_validate","no match in list, setting to: %s",vc->versiontag);
  434.     free_parsed_exeinfo(parsed_exeinfo);
  435.     return 0;
  436. }
  437. extern int versioncheck_load(char const * filename)
  438. {
  439.     FILE *     fp;
  440.     unsigned int    line;
  441.     unsigned int    pos;
  442.     char *     buff;
  443.     char *     temp;
  444.     char const *    eqn;
  445.     char const *    mpqfile;
  446.     char const *    archtag;
  447.     char const *    clienttag;
  448.     char const *    exeinfo;
  449.     char const *    versionid;
  450.     char const *    gameversion;
  451.     char const *    checksum;
  452.     char const *    versiontag;
  453.     t_versioninfo * vi;
  454.     
  455.     if (!filename)
  456.     {
  457. eventlog(eventlog_level_error,"versioncheck_load","got NULL filename");
  458. return -1;
  459.     }
  460.     
  461.     if (!(versioninfo_head = list_create()))
  462.     {
  463. eventlog(eventlog_level_error,"versioncheck_load","could create list");
  464. return -1;
  465.     }
  466.     if (!(fp = fopen(filename,"r")))
  467.     {
  468. eventlog(eventlog_level_error,"versioncheck_load","could not open file "%s" for reading (fopen: %s)",filename,strerror(errno));
  469. list_destroy(versioninfo_head);
  470. versioninfo_head = NULL;
  471. return -1;
  472.     }
  473.     line = 1;
  474.     for (; (buff = file_get_line(fp)); line++)
  475.     {
  476. for (pos=0; buff[pos]=='t' || buff[pos]==' '; pos++);
  477. if (buff[pos]=='' || buff[pos]=='#')
  478. {
  479.     free(buff);
  480.     continue;
  481. }
  482. if ((temp = strrchr(buff,'#')))
  483. {
  484.     unsigned int len;
  485.     unsigned int endpos;
  486.     
  487.     *temp = '';
  488.     len = strlen(buff)+1;
  489.     for (endpos=len-1;  buff[endpos]=='t' || buff[endpos]==' '; endpos--);
  490.     buff[endpos+1] = '';
  491. }
  492. if (!(eqn = next_token(buff,&pos)))
  493. {
  494.     eventlog(eventlog_level_error,"versioncheck_load","missing eqn near line %u of file "%s"",line,filename);
  495.     free(buff);
  496.     continue;
  497. }
  498. line++;
  499. if (!(mpqfile = next_token(buff,&pos)))
  500. {
  501.     eventlog(eventlog_level_error,"versioncheck_load","missing mpqfile near line %u of file "%s"",line,filename);
  502.     free(buff);
  503.     continue;
  504. }
  505. line++;
  506. if (!(archtag = next_token(buff,&pos)))
  507. {
  508.     eventlog(eventlog_level_error,"versioncheck_load","missing archtag near line %u of file "%s"",line,filename);
  509.     free(buff);
  510.     continue;
  511. }
  512. line++;
  513. if (!(clienttag = next_token(buff,&pos)))
  514. {
  515.     eventlog(eventlog_level_error,"versioncheck_load","missing clienttag near line %u of file "%s"",line,filename);
  516.     free(buff);
  517.     continue;
  518. }
  519. line++;
  520. if (!(exeinfo = next_token(buff,&pos)))
  521. {
  522.     eventlog(eventlog_level_error,"versioncheck_load","missing exeinfo near line %u of file "%s"",line,filename);
  523.     free(buff);
  524.     continue;
  525. }
  526. line++;
  527. if (!(versionid = next_token(buff,&pos)))
  528. {
  529.     eventlog(eventlog_level_error,"versioncheck_load","missing versionid near line %u of file "%s"",line,filename);
  530.     free(buff);
  531.     continue;
  532. }
  533. line++;
  534. if (!(gameversion = next_token(buff,&pos)))
  535. {
  536.     eventlog(eventlog_level_error,"versioncheck_load","missing gameversion near line %u of file "%s"",line,filename);
  537.     free(buff);
  538.     continue;
  539. }
  540. line++;
  541. if (!(checksum = next_token(buff,&pos)))
  542. {
  543.     eventlog(eventlog_level_error,"versioncheck_load","missing checksum near line %u of file "%s"",line,filename);
  544.     free(buff);
  545.     continue;
  546. }
  547. line++;
  548. if (!(versiontag = next_token(buff,&pos)))
  549. {
  550.     versiontag = NULL;
  551. }
  552. if (!(vi = malloc(sizeof(t_versioninfo))))
  553. {
  554.     eventlog(eventlog_level_error,"versioncheck_load","could not allocate memory for vi");
  555.     free(buff);
  556.     continue;
  557. }
  558. if (!(vi->eqn = strdup(eqn)))
  559. {
  560.     eventlog(eventlog_level_error,"versioncheck_load","could not allocate memory for eqn");
  561.     free(vi);
  562.     free(buff);
  563.     continue;
  564. }
  565. if (!(vi->mpqfile = strdup(mpqfile)))
  566. {
  567.     eventlog(eventlog_level_error,"versioncheck_load","could not allocate memory for mpqfile");
  568.     free((void *)vi->eqn); /* avoid warning */
  569.     free(vi);
  570.     free(buff);
  571.     continue;
  572. }
  573. if (strlen(archtag)!=4)
  574. {
  575.     eventlog(eventlog_level_error,"versioncheck_load","invalid arch tag on line %u of file "%s"",line,filename);
  576.     free((void *)vi->mpqfile); /* avoid warning */
  577.     free((void *)vi->eqn); /* avoid warning */
  578.     free(vi);
  579.     free(buff);
  580.     continue;
  581. }
  582. if (!(vi->archtag = strdup(archtag)))
  583. {
  584.     eventlog(eventlog_level_error,"versioncheck_load","could not allocate memory for archtag");
  585.     free((void *)vi->mpqfile); /* avoid warning */
  586.     free((void *)vi->eqn); /* avoid warning */
  587.     free(vi);
  588.     free(buff);
  589.     continue;
  590. }
  591. if (strlen(clienttag)!=4)
  592. {
  593.     eventlog(eventlog_level_error,"versioncheck_load","invalid client tag on line %u of file "%s"",line,filename);
  594.     free((void *)vi->archtag); /* avoid warning */
  595.     free((void *)vi->mpqfile); /* avoid warning */
  596.     free((void *)vi->eqn); /* avoid warning */
  597.     free(vi);
  598.     free(buff);
  599.     continue;
  600. }
  601. if (!(vi->clienttag = strdup(clienttag)))
  602. {
  603.     eventlog(eventlog_level_error,"versioncheck_load","could not allocate memory for clienttag");
  604.     free((void *)vi->archtag); /* avoid warning */
  605.     free((void *)vi->mpqfile); /* avoid warning */
  606.     free((void *)vi->eqn); /* avoid warning */
  607.     free(vi);
  608.     free(buff);
  609.     continue;
  610. }
  611. if (strcmp(exeinfo, "NULL") == 0)
  612.     vi->parsed_exeinfo = NULL;
  613. else
  614. {
  615.     if (!(vi->parsed_exeinfo = parse_exeinfo(exeinfo)))
  616.     {
  617. eventlog(eventlog_level_error,"versioncheck_load","encountered an error while parsing exeinfo");
  618. free((void *)vi->clienttag); /* avoid warning */
  619. free((void *)vi->archtag); /* avoid warning */
  620. free((void *)vi->mpqfile); /* avoid warning */
  621. free((void *)vi->eqn); /* avoid warning */
  622. free(vi);
  623. free(buff);
  624. continue;
  625.     }
  626. }
  627. vi->versionid = strtoul(versionid,NULL,0);
  628. if (verstr_to_vernum(gameversion,&vi->gameversion)<0)
  629. {
  630.     eventlog(eventlog_level_error,"versioncheck_load","malformed version on line %u of file "%s"",line,filename);
  631.     free((void *)vi->parsed_exeinfo); /* avoid warning */
  632.     free((void *)vi->clienttag); /* avoid warning */
  633.     free((void *)vi->archtag); /* avoid warning */
  634.     free((void *)vi->mpqfile); /* avoid warning */
  635.     free((void *)vi->eqn); /* avoid warning */
  636.     free(vi);
  637.     free(buff);
  638.     continue;
  639.         }
  640. vi->checksum = strtoul(checksum,NULL,0);
  641. if (versiontag)
  642. {
  643.     if (!(vi->versiontag = strdup(versiontag)))
  644.     {
  645. eventlog(eventlog_level_error,"versioncheck_load","could not allocate memory for versiontag");
  646. free((void *)vi->parsed_exeinfo); /* avoid warning */
  647. free((void *)vi->clienttag); /* avoid warning */
  648. free((void *)vi->archtag); /* avoid warning */
  649. free((void *)vi->mpqfile); /* avoid warning */
  650. free((void *)vi->eqn); /* avoid warning */
  651. free(vi);
  652. free(buff);
  653. continue;
  654.     }
  655. }
  656. else
  657.     vi->versiontag = NULL;
  658. free(buff);
  659. if (list_append_data(versioninfo_head,vi)<0)
  660. {
  661.     eventlog(eventlog_level_error,"versioncheck_load","could not append item");
  662.     if (vi->versiontag)
  663.       free((void *)vi->versiontag); /* avoid warning */
  664.     free((void *)vi->parsed_exeinfo); /* avoid warning */
  665.     free((void *)vi->clienttag); /* avoid warning */
  666.     free((void *)vi->archtag); /* avoid warning */
  667.     free((void *)vi->mpqfile); /* avoid warning */
  668.     free((void *)vi->eqn); /* avoid warning */
  669.     free(vi);
  670.     continue;
  671. }
  672.     }
  673.     
  674.     if (fclose(fp)<0)
  675. eventlog(eventlog_level_error,"versioncheck_load","could not close versioncheck file "%s" after reading (fclose: %s)",filename,strerror(errno));
  676.     
  677.     return 0;
  678. }
  679. extern int versioncheck_unload(void)
  680. {
  681.     t_elem *     curr;
  682.     t_versioninfo * vi;
  683.     
  684.     if (versioninfo_head)
  685.     {
  686. LIST_TRAVERSE(versioninfo_head,curr)
  687. {
  688.     if (!(vi = elem_get_data(curr))) /* should not happen */
  689.     {
  690. eventlog(eventlog_level_error,"versioncheck_unload","version list contains NULL item");
  691. continue;
  692.     }
  693.     
  694.     if (list_remove_elem(versioninfo_head,curr)<0)
  695. eventlog(eventlog_level_error,"versioncheck_unload","could not remove item from list");
  696.     if (vi->parsed_exeinfo)
  697.             {
  698.                 if (vi->parsed_exeinfo->exe)
  699.                     free((void *)vi->parsed_exeinfo->exe);
  700. free((void *)vi->parsed_exeinfo); /* avoid warning */
  701.             }
  702.     free((void *)vi->clienttag); /* avoid warning */
  703.     free((void *)vi->archtag); /* avoid warning */
  704.     free((void *)vi->mpqfile); /* avoid warning */
  705.     free((void *)vi->eqn); /* avoid warning */
  706.     if (vi->versiontag)
  707. free((void *)vi->versiontag); /* avoid warning */
  708.     free(vi);
  709. }
  710. if (list_destroy(versioninfo_head)<0)
  711.     return -1;
  712. versioninfo_head = NULL;
  713.     }
  714.     
  715.     return 0;
  716. }