📄 versioncheck.c
字号:
/* * Copyright (C) 2000 Onlyer (onlyer@263.net) * Copyright (C) 2001 Ross Combs (ross@bnetd.org) * Copyright (C) 2002 Gianluigi Tiesi (sherpya@netfarm.it) * Copyright (C) 2004 CreepLord (creeplord@pvpgn.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#define VERSIONCHECK_INTERNAL_ACCESS#include "common/setup_before.h"#include <stdio.h>#ifdef HAVE_STDDEF_H# include <stddef.h>#else# ifndef NULL# define NULL ((void *)0)# endif#endif#ifdef STDC_HEADERS# include <stdlib.h>#else# ifdef HAVE_MALLOC_H# include <malloc.h># endif#endif#include "compat/strtoul.h"#ifdef HAVE_STRING_H# include <string.h>#else# ifdef HAVE_STRINGS_H# include <strings.h># endif#endif#ifdef HAVE_MKTIME# ifdef TIME_WITH_SYS_TIME# include <sys/time.h># include <time.h># else# ifdef HAVE_SYS_TIME_H# include <sys/time.h># else# include <time.h># endif# endif#endif#ifdef HAVE_ASSERT_H# include <assert.h>#endif#include "compat/strchr.h"#include "compat/strdup.h"#include "compat/strcasecmp.h"#include <ctype.h>#include <errno.h>#include "compat/strerror.h"#include "common/eventlog.h"#include "common/list.h"#include "common/util.h"#include "common/proginfo.h"#include "common/token.h"#include "common/field_sizes.h"#include "prefs.h"#include "versioncheck.h"#include "common/tag.h"#include "common/xalloc.h"#include "common/setup_after.h"static t_list * versioninfo_head=NULL;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" };static int versioncheck_compare_exeinfo(t_parsed_exeinfo * pattern, t_parsed_exeinfo * match);extern t_versioncheck * versioncheck_create(t_tag archtag, t_tag clienttag){ t_elem const * curr; t_versioninfo * vi; t_versioncheck * vc; char archtag_str[5]; char clienttag_str[5]; LIST_TRAVERSE_CONST(versioninfo_head,curr) { if (!(vi = elem_get_data(curr))) /* should not happen */ { eventlog(eventlog_level_error,__FUNCTION__,"version list contains NULL item"); continue; } eventlog(eventlog_level_debug,__FUNCTION__,"version check entry archtag=%s, clienttag=%s", tag_uint_to_str(archtag_str,vi->archtag), tag_uint_to_str(clienttag_str,vi->clienttag)); if (vi->archtag != archtag) continue; if (vi->clienttag != clienttag) continue; /* FIXME: randomize the selection if more than one match */ vc = xmalloc(sizeof(t_versioncheck)); vc->eqn = xstrdup(vi->eqn); vc->mpqfile = xstrdup(vi->mpqfile); vc->versiontag = xstrdup(tag_uint_to_str(clienttag_str,clienttag)); return vc; } /* * No entries in the file that match, return the dummy because we have to send * some equation and auth mpq to the client. The client is not going to pass the * validation later unless skip_versioncheck or allow_unknown_version is enabled. */ return &dummyvc;}extern int versioncheck_destroy(t_versioncheck * vc){ if (!vc) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL vc"); return -1; } if (vc==&dummyvc) return 0; xfree((void *)vc->versiontag); xfree((void *)vc->mpqfile); xfree((void *)vc->eqn); xfree(vc); return 0;}extern int versioncheck_set_versiontag(t_versioncheck * vc, char const * versiontag){ if (!vc) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL vc"); return -1; } if (!versiontag) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL versiontag"); return -1; } if (vc->versiontag!=NULL) xfree((void *)vc->versiontag); vc->versiontag = xstrdup(versiontag); return 0;}extern char const * versioncheck_get_versiontag(t_versioncheck const * vc){ if (!vc) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL vc"); return NULL; } return vc->versiontag;}extern char const * versioncheck_get_mpqfile(t_versioncheck const * vc){ if (!vc) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL vc"); return NULL; } return vc->mpqfile;}extern char const * versioncheck_get_eqn(t_versioncheck const * vc){ if (!vc) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL vc"); return NULL; } return vc->eqn;}t_parsed_exeinfo * parse_exeinfo(char const * exeinfo){ t_parsed_exeinfo * parsed_exeinfo; if (!exeinfo) { return NULL; } parsed_exeinfo = xmalloc(sizeof(t_parsed_exeinfo)); parsed_exeinfo->exe = xstrdup(exeinfo); parsed_exeinfo->time = 0; parsed_exeinfo->size = 0; if (strcmp(prefs_get_version_exeinfo_match(),"parse")==0) {#ifdef HAVE_MKTIME struct tm t1; char *exe; char mask[MAX_EXEINFO_STR+1]; char * marker; int size; char time_invalid = 0; if ((exeinfo[0]=='\0') || //happens when using war3-noCD and having deleted war3.org (strcmp(exeinfo,"badexe")==0)) //happens when AUTHREQ had no owner/exeinfo entry { xfree((void *)parsed_exeinfo->exe); xfree((void *)parsed_exeinfo); eventlog(eventlog_level_error,__FUNCTION__,"found empty exeinfo"); return NULL; } memset(&t1,0,sizeof(t1)); t1.tm_isdst = -1; exeinfo = strreverse((char *)exeinfo); if (!(marker = strchr(exeinfo,' '))) { xfree((void *)parsed_exeinfo->exe); xfree((void *)parsed_exeinfo); return NULL; } for (; marker[0]==' ';marker++); if (!(marker = strchr(marker,' '))) { xfree((void *)parsed_exeinfo->exe); xfree((void *)parsed_exeinfo); return NULL; } for (; marker[0]==' ';marker++); if (!(marker = strchr(marker,' '))) { xfree((void *)parsed_exeinfo->exe); xfree((void *)parsed_exeinfo); return NULL; } for (; marker[0]==' ';marker++); marker--; marker[0] = '\0'; marker++; exe = xstrdup(marker); xfree((void *)parsed_exeinfo->exe); parsed_exeinfo->exe = strreverse((char *)exe); exeinfo = strreverse((char *)exeinfo); sprintf(mask,"%%02u/%%02u/%%u %%02u:%%02u:%%02u %%u"); if (sscanf(exeinfo,mask,&t1.tm_mon,&t1.tm_mday,&t1.tm_year,&t1.tm_hour,&t1.tm_min,&t1.tm_sec,&size)!=7) { if (sscanf(exeinfo,"%*s %*s %u",&size) != 1) { eventlog(eventlog_level_warn,__FUNCTION__,"parser error while parsing pattern \"%s\"",exeinfo); xfree((void *)parsed_exeinfo->exe); xfree((void *)parsed_exeinfo); return NULL; /* neq */ } time_invalid=1; } /* Now we have a Y2K problem :) Thanks for using a 2 digit decimal years, Blizzard. */ /* 00-79 -> 2000-2079 * * 80-99 -> 1980-1999 * * 100+ unchanged */ if (t1.tm_year<80) t1.tm_year = t1.tm_year + 100; if (time_invalid) parsed_exeinfo->time = -1; else parsed_exeinfo->time = mktime(&t1); parsed_exeinfo->size = size;#else eventlog(eventlog_level_error,__FUNCTION__,"Your system does not support mktime(). Please select another exeinfo matching method."); return NULL;#endif } return parsed_exeinfo;}#define safe_toupper(X) (islower((int)X)?toupper((int)X):(X))/* This implements some dumb kind of pattern matching. Any '?' * signs in the pattern are treated as "don't care" signs. This * means that it doesn't matter what's on this place in the match. *///static int versioncheck_compare_exeinfo(char const * pattern, char const * match)static int versioncheck_compare_exeinfo(t_parsed_exeinfo * pattern, t_parsed_exeinfo * match){ assert(pattern); assert(match); if (!strcasecmp(prefs_get_version_exeinfo_match(),"none")) return 0; /* ignore exeinfo */ if (strlen(pattern->exe)!=strlen(match->exe)) return 1; /* neq */ if (strcmp(prefs_get_version_exeinfo_match(),"exact")==0) { return strcasecmp(pattern->exe,match->exe); } else if (strcmp(prefs_get_version_exeinfo_match(),"exactcase")==0) { return strcmp(pattern->exe,match->exe); } else if (strcmp(prefs_get_version_exeinfo_match(),"wildcard")==0) { unsigned int i; for (i=0;i<strlen(pattern->exe);i++) if ((pattern->exe[i]!='?')&& /* out "don't care" sign */ (safe_toupper(pattern->exe[i])!=safe_toupper(match->exe[i]))) return 1; /* neq */ return 0; /* ok */ } else if (strcmp(prefs_get_version_exeinfo_match(),"parse")==0) { if (strcasecmp(pattern->exe,match->exe)!=0) { eventlog(eventlog_level_trace,__FUNCTION__,"filename differs"); return 1; /* neq */ } if (pattern->size!=match->size) { eventlog(eventlog_level_trace,__FUNCTION__,"size differs"); return 1; /* neq */ }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -