#include <stdio.h>
#include <string.h>
#include <process.h>
#include <windows.h>
#include "mem.h"
#include "network.h"
#include "struct.h"
#include "convert.h"
#include "auth.h"
#include "isip.h"
struct problemlist
{
unsigned long pageid;
struct problemlist *next;
};
struct neditargv
{
const char *id;
HTTP newtext;
const char *time;
};
int threadc[1024];
SRWLOCK rwcs;
CRITICAL_SECTION tcs;
CRITICAL_SECTION hcs;
int threadnumber=0;
unsigned char action=0;
int loadfromfile=0;
struct hashlist *hl=NULL;
struct problemlist *pbl=NULL;
FILE *fp,*fp1;
const char *username=NULL;
const char *passwd=NULL;
const char *searchstring=NULL;
const char *ns=NULL;
int maxthread=256;
int doallpage=0;
int output=0;
static void displayerr(unsigned int code)
{
if(!(code&0x1))
{
printf(
"\tNo username.\n"
"\t\tA valid username must be specified via \"-u\".\n"
);
}
if(code&0x2)
{
printf(
"\tUsername too long.\n"
"\t\tThe username should not be longer than 64 bytes.\n"
);
}
if(!(code&0x4))
{
printf(
"\tNo query.\n"
"\t\tEither a search string (via \"-s\") or \"-a\" should be set.\n"
);
}
if(code&0x8)
{
printf(
"\tPassword too long.\n"
"\t\tThe password should not be longer than 64 bytes.\n"
);
}
if(!(code&0x10))
{
printf(
"\tNo password.\n"
"\t\tA valid password must be specified via \"-p\".\n"
);
}
if(code&0x20)
{
printf(
"\tSearch string too long.\n"
"\t\tThe search string should not be longer than 128 bytes.\n"
);
}
if(code&0x40)
{
printf(
"\tns string too long.\n"
"\t\tThe ns string should not be longer than 32 bytes.\n"
);
}
if(code&0x80)
{
printf(
"\tInvalid input file.\n"
"\t\tCannot open the input file.\n"
);
}
if(code&0x100)
{
printf(
"\tInvalid output file.\n"
"\t\tCannot open the output file.\n"
);
}
return;
}
static int parsearg(int argc,const char *argv[])
{
int cur_arg=0;
unsigned int err=0;
doallpage=0;
for(cur_arg=1;cur_arg<argc;cur_arg++)
{
if(argv[cur_arg][0]=='-'&&((argv[cur_arg+1]&&argv[cur_arg+1][0]!='-')||argv[cur_arg][1]=='a'))
{
switch(argv[cur_arg][1])
{
case 'u':
username=G2U(argv[cur_arg+1]);
if(strlen(username)>64)
{
err|=0x2;
}
else
{
err|=0x1;
}
cur_arg++;
break;
case 'a':
err|=0x4;
doallpage=1;
break;
case 'p':
passwd=argv[cur_arg+1];
if(strlen(passwd)>64)
{
err|=0x8;
}
else
{
err|=0x10;
}
cur_arg++;
break;
case 's':
searchstring=G2U(argv[cur_arg+1]);
if(strlen(searchstring)>128)
{
err|=0x20;
}
else
{
err|=0x4;
}
cur_arg++;
break;
case 'n':
ns=argv[cur_arg+1];
if(strlen(ns)>32)
{
err|=0x40;
}
cur_arg++;
break;
case 'T':
maxthread=atoi(argv[cur_arg+1]);
if(maxthread<1||maxthread>1024) maxthread=32;
cur_arg++;
break;
case 'i':
fp=fopen(argv[cur_arg+1],"r+");
if(fp!=0) loadfromfile=1;
else
{
err|=0x80;
}
cur_arg++;
break;
case 'o':
fp1=fopen(argv[cur_arg+1],"w+");
if(fp1!=0) output=1;
else
{
err|=0x100;
}
cur_arg++;
break;
}
}
}
if(!ns) ns="0";
if(0x1+0x4+0x10==err) return 0;
else
{
printf("Error code 0x%x:\n",err);
displayerr(err);
return 1;
}
}
static int smartedit(struct neditargv *p,const char *reason, const char *tags)
{
HTTP res;
char line[2048],url[4096]={0};
char reason_e[512];
char tags_e[256];
char aft[1024],statusline[128];
char cur_token[128];
char err_type[8192];
char *erm[]={"code"};
char *erv[1];
int find=0;
int has_err=0,token_err=0,filtered=0;
int retry=0;
erv[0]=err_type;
if(reason) URLEncode(reason,strlen(reason),reason_e,510);
if(tags) URLEncode(tags,strlen(tags),tags_e,254);
sprintf(url,"/w/api.php?action=edit&pageid=%s&basetimestamp=%s",p->id,p->time);
find=sprintf(aft,"%s%s&summary=%s&bot=1&minor=1&nocreate=1&format=xml&token=",tags?"&tags=":"",tags?tags_e:"",reason_e);
if(find<0) return -4;
do
{
res=hopen();;
while(1)
{
AcquireSRWLockShared(&rwcs);
if(hastoken) break;
else ReleaseSRWLockShared(&rwcs);
Sleep(100);
}
aft[find]=0;
strcat(aft,token);
ReleaseSRWLockShared(&rwcs);
hrewind(p->newtext);
if(smartpost(url,p->newtext,aft,8888,1,res))
{
hclose(res);
return -1;
}
hgets(statusline,127,res);
if(!strstr(statusline," 200"))
{
hclose(res);
return -2;
}
skipresponseheader(res);
filtered=token_err=has_err=0;
while(!heof(res))
{
if(xmlparsetag(res,line)==XML_HAS_VALUE)
{
if(!strcmp(line,"error"))
{
has_err=1;
xmlparsearg(res,1,erm,erv);
if((!strcmp(err_type,"notoken"))||(!strcmp(err_type,"badtoken")))
{
token_err=1;
}
else if(!strcmp(err_type,"abusefilter-warning"))
{
filtered=1;
}
break;
}
}
}
if(token_err)
{
AcquireSRWLockExclusive(&rwcs);
if(!strcmp(aft+find,cur_token)) hastoken=0;
ReleaseSRWLockExclusive(&rwcs);
}
retry++;
hclose(res);
}while((token_err||filtered)&&(retry<3));
if(has_err) return -3;
else return 0;
}
struct hashlist *usernamelist;
struct hashlist *userrenamelist;
struct hashlist *dupuserlist;
struct hashlist *baduserlist;
static int userrenamed(const char *olduser,char **newuser)
{
void *p;
if(str_hashquery(baduserlist,olduser,&p)||str_hashquery(dupuserlist,olduser,&p)) return 0;
return str_hashquery(userrenamelist,olduser,newuser);
}
static int usernameexist(const char *username)
{
void *p;
return str_hashquery(usernamelist,username,&p);
}
static int isip(const char *username)
{
unsigned int username_u[1024];
utf8tounicode(username,username_u);
return regexIP(username_u);
}
const char *special;
const char *contrib_hans1,*contrib_hant1;
const char *contrib_hans2,*contrib_hant2;
const char *contrib_hans3,*contrib_hant3;
const char *delcontrib_hans;
const char *logs_hans;
const char *logs_hant;
const char *ul_hans1;
const char *ca_hans;
const char *ur_hans;
const char *af_hans;
const char *http_mark1,*http_mark2;
const char *domain_mark1,*domain_mark2;
const char *mail_hans,*mail_hant;
const char *upload_hans1,*upload_hant1;
const char *upload_hans2,*upload_hant2;
const char *upload_hant3;
struct hashlist *logtype;
struct hashlist *urltoken;
int urltokentype[4]={0,1,2,3};
static void ini_marks()
{
special=G2U("特殊:");
contrib_hans1=G2U("用户贡献/");
contrib_hant1=G2U("用戶貢獻/");
contrib_hans2=G2U("使用者贡献/");
contrib_hant2=G2U("使用者貢獻/");
contrib_hans3=G2U("贡献/");
contrib_hant3=G2U("貢獻/");
delcontrib_hans=G2U("删除的贡献/");
logs_hans=G2U("日志/");
logs_hant=G2U("日誌/");
ul_hans1=G2U("用户列表/");
ca_hans=G2U("中央认证/");
ur_hans=G2U("用户权限/");
af_hans=G2U("滥用日志/");
mail_hans=G2U("电邮联系/");
mail_hant=G2U("電郵聯絡/");
upload_hans1=G2U("文件列表/");
upload_hant1=G2U("檔案列表/");
upload_hans2=G2U("上传/");
upload_hant2=G2U("上載/");
upload_hant3=G2U("上傳/");
logtype=hashini();
str_hashadd(logtype,"timedmediahandler",NULL);
str_hashadd(logtype,"upload",NULL);
str_hashadd(logtype,"protect",NULL);
str_hashadd(logtype,"gblblock",NULL);
str_hashadd(logtype,"gblrights",NULL);
str_hashadd(logtype,"globalauth",NULL);
str_hashadd(logtype,"gblrename",NULL);
str_hashadd(logtype,"contentmodel",NULL);
str_hashadd(logtype,"delete",NULL);
str_hashadd(logtype,"merge",NULL);
str_hashadd(logtype,"spamblacklist",NULL);
str_hashadd(logtype,"massmessage",NULL);
str_hashadd(logtype,"import",NULL);
str_hashadd(logtype,"block",NULL);
str_hashadd(logtype,"patrol",NULL);
str_hashadd(logtype,"thanks",NULL);
str_hashadd(logtype,"tag",NULL);
str_hashadd(logtype,"managetags",NULL);
str_hashadd(logtype,"titleblacklist",NULL);
str_hashadd(logtype,"abusefilter",NULL);
str_hashadd(logtype,"newusers",NULL);
str_hashadd(logtype,"usermerge",NULL);
str_hashadd(logtype,"renameuser",NULL);
str_hashadd(logtype,"rights",NULL);
str_hashadd(logtype,"move",NULL);
str_hashadd(logtype,"create",NULL);
http_mark1="http";
http_mark2="HTTP";
domain_mark1="://zh.wikipedia.org/";
domain_mark2="://ZH.WIKIPEDIA.ORG/";
urltoken=hashini();
str_hashadd(urltoken,"title",urltokentype);
str_hashadd(urltoken,"user",urltokentype+1);
str_hashadd(urltoken,"target",urltokentype+2);
str_hashadd(urltoken,"wpSearchUser",urltokentype+3);
return ;
}
static int strncasecmp(const char *a,const char *b,const unsigned int k)
{
char c1=0,c2=0;
register unsigned int count=0;
do
{
c1=a[count];
c1=((c1>='A')&&(c1<='Z'))?c1+'a'-'A':c1;
c2=b[count];
c2=((c2>='A')&&(c2<='Z'))?c2+'a'-'A':c2;
if(c1>c2) return 1;
if(c1<c2) return -1;
count++;
}while(c1&&c2&&(count<k));
return 0;
}
static int checkusercontrib(const char *ori_link,char *fixedlink)
{
int linkpos=0,baselinkpos=0;
int todo=0;
int log=0;
char username[1024],link[2048];
char *newuser;
int usernamepos=0;
URLtryDecode(ori_link,strlen(ori_link),link,2046,0);
if(!strncasecmp(link,"Special:",8))
{
linkpos=8;
}
else if(!strncmp(link,special,7))
{
linkpos=7;
}
else goto nothingtodo;
if(!strncasecmp((link+linkpos),"Contributions/",14))
{
linkpos+=14;
}
else if(!strncasecmp((link+linkpos),"Contribs/",9))
{
linkpos+=9;
}
else if(!strncmp((link+linkpos),contrib_hans1,13)||!strncmp((link+linkpos),contrib_hant1,13))
{
linkpos+=13;
}
else if(!strncmp((link+linkpos),contrib_hans2,16)||!strncmp((link+linkpos),contrib_hant2,16))
{
linkpos+=16;
}
else if(!strncmp((link+linkpos),contrib_hans3,7)||!strncmp((link+linkpos),contrib_hant3,7))
{
linkpos+=7;
}
else if(!strncasecmp((link+linkpos),"Filelist/",9))
{
linkpos+=9;
}
else if(!strncasecmp((link+linkpos),"Uploads/",8))
{
linkpos+=8;
}
else if(!strncmp((link+linkpos),upload_hans1,13)||!strncmp((link+linkpos),upload_hant1,13))
{
linkpos+=13;
}
else if(!strncmp((link+linkpos),upload_hans2,7)||!strncmp((link+linkpos),upload_hant2,7)||!strncmp((link+linkpos),upload_hant3,7))
{
linkpos+=7;
}
else if(!strncasecmp((link+linkpos),"Email/",6))
{
linkpos+=6;
}
else if(!strncasecmp((link+linkpos),"EmailUser/",10))
{
linkpos+=10;
}
else if(!strncmp((link+linkpos),mail_hans,13)||!strncmp((link+linkpos),mail_hant,13))
{
linkpos+=13;
}
else if(!strncasecmp((link+linkpos),"DeletedContributions/",21))
{
linkpos+=21;
}
else if(!strncmp((link+linkpos),delcontrib_hans,16))
{
linkpos+=16;
}
else if(!strncasecmp((link+linkpos),"Log/",4))
{
linkpos+=4;
log=1;
}
else if(!strncasecmp((link+linkpos),"Logs/",5))
{
linkpos+=5;
log=1;
}
else if(!strncmp((link+linkpos),logs_hans,7)||!strncmp((link+linkpos),logs_hant,7))
{
linkpos+=7;
log=1;
}
/*
else if(!strncasecmp((link+linkpos),"Listusers/",10))
{
linkpos+=10;
}
else if(!strncmp((link+linkpos),ul_hans1,13))
{
linkpos+=13;
}*/
/*
else if(!strncasecmp((link+linkpos),"CentralAuth/",12))
{
linkpos+=12;
}
else if(!strncmp((link+linkpos),ca_hans,13))
{
linkpos+=13;
}*/
else if(!strncasecmp((link+linkpos),"UserRights/",11))
{
linkpos+=11;
}
else if(!strncmp((link+linkpos),ur_hans,13))
{
linkpos+=13;
}
else goto nothingtodo;
if(log)
{
int count;
int type=0;
for(count=linkpos;link[count];count++)
{
if(link[count]=='{'||link[count]=='}'
||link[count]=='<'||link[count]=='>'
||link[count]=='\\'
||link[count]=='#'
||link[count]=='$'
||link[count]=='['||link[count]==']') goto nothingtodo;
if(link[count]=='/')
{
type=1;
break;
}
}
if(type)
{
baselinkpos=linkpos=count+1;
while(link[linkpos]==' ') linkpos++;
while(link[linkpos])
{
if(link[linkpos]=='{'||link[linkpos]=='}'
||link[linkpos]=='<'||link[linkpos]=='>'
||link[linkpos]=='\\'
||link[linkpos]=='#'
||link[linkpos]=='$'
||link[linkpos]=='['||link[linkpos]==']') goto nothingtodo;
username[usernamepos]=(link[linkpos]=='_')?' ':link[linkpos];
usernamepos++;
linkpos++;
}
if(usernamepos==0) goto nothingtodo;
username[usernamepos]=0;
}
else
{
void *p;
baselinkpos=linkpos;
while(link[linkpos]==' ') linkpos++;
while(link[linkpos])
{
username[usernamepos]=(link[linkpos]=='_')?' ':link[linkpos];
usernamepos++;
linkpos++;
}
if(usernamepos==0) goto nothingtodo;
username[usernamepos]=0;
if(str_hashquery(logtype,username,&p)) goto nothingtodo;
}
}
else
{
baselinkpos=linkpos;
while(link[linkpos]==' ') linkpos++;
while(link[linkpos])
{
if(link[linkpos]=='{'||link[linkpos]=='}'
||link[linkpos]=='<'||link[linkpos]=='>'
||link[linkpos]=='\\'
||link[linkpos]=='#'
||link[linkpos]=='$'
||link[linkpos]=='['||link[linkpos]==']') goto nothingtodo;
username[usernamepos]=(link[linkpos]=='_')?' ':link[linkpos];
usernamepos++;
linkpos++;
}
if(usernamepos==0) goto nothingtodo;
username[usernamepos]=0;
}
while(usernamepos>0)
{
if(username[usernamepos-1]==' ') usernamepos--;
else break;
}
username[usernamepos]=0;
if(!strcmp(username,"newbies")) goto nothingtodo;
if(isip(username)) goto nothingtodo;
if(username[0]>='a'&&username[0]<='z') username[0]-='a'-'A';
if(usernameexist(username)) goto nothingtodo;
if(!userrenamed(username,&newuser))
{
goto nothingtodo;
}
todo=1;
strncpy(fixedlink,link,baselinkpos);
fixedlink[baselinkpos]=0;
strcat(fixedlink,newuser);
nothingtodo:
return todo;
}
static void format_url(char *url)
{
register int i;
for(i=0;url[i];i++)
{
if(url[i]==' ') url[i]='_';
}
return;
}
static void format_username(char *username)
{
register int i;
if((*username>='a')&&(*username<='z')) *username-='a'-'A';
for(i=0;username[i];i++)
{
if(username[i]=='_') username[i]=' ';
}
return;
}
struct _str
{
const char *s;
unsigned int len;
};
static int url_checkusercontrib(const char *url,char *fixed_url)
{
int i=0;
int urlpos=0;
int baseurlpos=0;
char name[1024];
char value_ori[8192],value_dec[8192],*fixed_value,fixed[8192];
char ch;
int namepos=0;
int valuepos=0,value_dec_len=0;
int exp=0,ext=0;
int status=0;
int log=0;
int todo=0;
struct _str *p;
struct _str var[10]={0};
void *q;
if(!strncmp(url,"wiki/",5))
{
urlpos=5;
exp=0;
}
else if(!strncmp(url,"w/index.php?",12))
{
urlpos=12;
exp=1;
}
else return 0;
if(!exp)
{
int query=0;
ch=url[urlpos+valuepos];
while(ch)
{
if(ch=='?')
{
query=1;
break;
}
else if(ch=='#'||ch=='|') return 0;
value_ori[valuepos]=ch;
valuepos++;
ch=url[urlpos+valuepos];
}
if(valuepos==0) return 0;
value_ori[valuepos]=0;
if(!query)
{
URLtryDecode(value_ori,strlen(value_ori),value_dec,2047,1);
if(checkusercontrib(value_dec,fixed))
{
strncpy(fixed_url,url,urlpos);
fixed_url[urlpos]=0;
strcat(fixed_url,fixed);
format_url(fixed_url);
return 1;
}
else return 0;
}
}
if(!exp)
{
var[0].s=url+urlpos;
var[0].len=valuepos;
urlpos+=valuepos+1;
valuepos=0;
}
ch=url[urlpos];
while(1)
{
switch(status)
{
case 0:
if(ch=='=')
{
name[namepos]=0;
baseurlpos=urlpos+1;
valuepos=0;
status=1;
}
else if(ch=='&'||ch==0)
{
namepos=0;
}
else
{
name[namepos]=ch;
namepos++;
}
break;
case 1:
if(ch=='&'||ch==0)
{
int *n;
while(namepos>0)
{
if(name[namepos-1]==' ') namepos--;
else break;
}
name[namepos]=0;
i=0;
while(name[i]==' ') i++;
if(str_hashquery(urltoken,name+i,&n))
{
if(var[*n].s) goto nothingtodo;
var[*n].len=valuepos;
var[*n].s=url+baseurlpos;
}
valuepos=0;
namepos=0;
status=0;
}
else
{
valuepos++;
}
break;
}
if(!ch) break;
ch=url[++urlpos];
}
if(!var[0].s) goto nothingtodo;
p=var;
strncpy(value_ori,p->s,p->len);
value_ori[p->len]=0;
valuepos=0;
value_dec_len=URLtryDecode(value_ori,p->len,value_dec,2047,1);
if(!strncasecmp(value_dec,"Special:",8))
{
valuepos=8;
}
else if(!strncmp(value_dec,special,7))
{
valuepos=7;
}
else goto nothingtodo;
if(!strncasecmp(value_dec+valuepos,"Log",3))
{
valuepos+=3;
if(valuepos==value_dec_len)
{
ext=2;
}
else if(value_dec_len==valuepos+1)
{
if(value_dec[valuepos]=='s'||value_dec[valuepos]=='S')
{
ext=2;
}
else goto nothingtodo;
}
else if(value_dec[valuepos]=='/')
{
valuepos++;
ext=1;
}
else if((value_dec[valuepos]=='S'||value_dec[valuepos]=='s')&&value_dec[valuepos+1]=='/')
{
valuepos+=2;
ext=1;
}
else goto nothingtodo;
log=1;
}
else if(!strncmp(value_dec+valuepos,logs_hans,6)||!strncmp(value_dec+valuepos,logs_hant,6))
{
valuepos+=6;
if(valuepos==value_dec_len)
{
ext=2;
}
else if(value_dec[valuepos]=='/')
{
valuepos++;
ext=1;
}
else goto nothingtodo;
log=1;
}
else if(!strncasecmp(value_dec+valuepos,"Contributions",13))
{
valuepos+=13;
if(valuepos==value_dec_len)
{
ext=3;
}
else if(value_dec[valuepos]=='/')
{
valuepos++;
ext=1;
}
else goto nothingtodo;
}
else if(!strncasecmp(value_dec+valuepos,"Contribs",8))
{
valuepos+=8;
if(valuepos==value_dec_len)
{
ext=3;
}
else if(value_dec[valuepos]=='/')
{
valuepos++;
ext=1;
}
else goto nothingtodo;
}
else if(!strncasecmp(value_dec+valuepos,"Filelist",8))
{
valuepos+=8;
if(valuepos==value_dec_len)
{
ext=2;
}
else if(value_dec[valuepos]=='/')
{
valuepos++;
ext=1;
}
else goto nothingtodo;
}
else if(!strncasecmp(value_dec+valuepos,"Uploads",7))
{
valuepos+=7;
if(valuepos==value_dec_len)
{
ext=2;
}
else if(value_dec[valuepos]=='/')
{
valuepos++;
ext=1;
}
else goto nothingtodo;
}
else if(!strncmp(value_dec+valuepos,upload_hans1,12)||!strncmp(value_dec+valuepos,upload_hant1,12))
{
valuepos+=12;
if(valuepos==value_dec_len)
{
ext=2;
}
else if(value_dec[valuepos]=='/')
{
valuepos++;
ext=1;
}
else goto nothingtodo;
}
else if(!strncmp(value_dec+valuepos,upload_hans2,6)||!strncmp(value_dec+valuepos,upload_hant2,6)||!strncmp(value_dec+valuepos,upload_hant3,6))
{
valuepos+=6;
if(valuepos==value_dec_len)
{
ext=2;
}
else if(value_dec[valuepos]=='/')
{
valuepos++;
ext=1;
}
else goto nothingtodo;
}
else if(!strncasecmp(value_dec+valuepos,"EmailUser",9))
{
valuepos+=9;
if(valuepos==value_dec_len)
{
ext=3;
}
else if(value_dec[valuepos]=='/')
{
valuepos++;
ext=1;
}
else goto nothingtodo;
}
else if(!strncasecmp(value_dec+valuepos,"Email",5))
{
valuepos+=5;
if(valuepos==value_dec_len)
{
ext=3;
}
else if(value_dec[valuepos]=='/')
{
valuepos++;
ext=1;
}
else goto nothingtodo;
}
else if(!strncmp(value_dec+valuepos,mail_hans,12)||!strncmp((value_dec+valuepos),mail_hant,12))
{
valuepos+=12;
if(valuepos==value_dec_len)
{
ext=3;
}
else if(value_dec[valuepos]=='/')
{
valuepos++;
ext=1;
}
else goto nothingtodo;
}
else if(!strncmp(value_dec+valuepos,contrib_hans3,6)||!strncmp(value_dec+valuepos,contrib_hant3,6))
{
valuepos+=6;
if(valuepos==value_dec_len)
{
ext=3;
}
else if(value_dec[valuepos]=='/')
{
valuepos++;
ext=1;
}
else goto nothingtodo;
}
else if(!strncmp(value_dec+valuepos,contrib_hans1,12)||!strncmp(value_dec+valuepos,contrib_hant1,12))
{
valuepos+=12;
if(valuepos==value_dec_len)
{
ext=3;
}
else if(value_dec[valuepos]=='/')
{
valuepos++;
ext=1;
}
else goto nothingtodo;
}
else if(!strncmp(value_dec+valuepos,contrib_hans2,15)
||!strncmp(value_dec+valuepos,contrib_hant2,15)
||!strncmp(value_dec+valuepos,delcontrib_hans,15))
{
valuepos+=15;
if(valuepos==value_dec_len)
{
ext=3;
}
else if(value_dec[valuepos]=='/')
{
valuepos++;
ext=1;
}
else goto nothingtodo;
}
else if(!strncasecmp(value_dec+valuepos,"DeletedContributions",20))
{
valuepos+=20;
if(valuepos==value_dec_len)
{
ext=3;
}
else if(value_dec[valuepos]=='/')
{
valuepos++;
ext=1;
}
else goto nothingtodo;
}
else if(!strncasecmp(value_dec+valuepos,"UserRights",10))
{
valuepos+=10;
if(valuepos==value_dec_len)
{
ext=2;
}
else if(value_dec[valuepos]=='/')
{
valuepos++;
ext=1;
}
else goto nothingtodo;
}
else if(!strncasecmp(value_dec+valuepos,ur_hans,12))
{
valuepos+=12;
if(valuepos==value_dec_len)
{
ext=2;
}
else if(value_dec[valuepos]=='/')
{
valuepos++;
ext=1;
}
else goto nothingtodo;
}
else if(!strncasecmp(value_dec+valuepos,"Abuselog",8))
{
valuepos+=8;
if(valuepos==value_dec_len)
{
ext=4;
}
else goto nothingtodo;
}
else if(!strncasecmp(value_dec+valuepos,af_hans,12))
{
valuepos+=12;
if(valuepos==value_dec_len)
{
ext=4;
}
else goto nothingtodo;
}
else goto nothingtodo;
if(log)
{
for(i=valuepos;value_dec[i];i++)
{
if(value_dec[i]=='/')
{
log=0;
break;
}
}
if(!log) valuepos=i+1;
}
switch(ext)
{
case 1:
baseurlpos=p->s-url;
strncpy(fixed_url,url,baseurlpos);
fixed_url[baseurlpos]=0;
strncat(fixed_url,value_dec,valuepos);
fixed_url[baseurlpos+valuepos]=0;
while(value_dec[valuepos]==' ') valuepos++;
i=value_dec_len;
while(i>0)
{
if(value_dec[i-1]==' ') i--;
else break;
}
value_dec[i]=0;
if(i<=valuepos) goto nothingtodo;
if(!log||!str_hashquery(logtype,value_dec+valuepos,&q))
{
if(isip(value_dec+valuepos)) goto nothingtodo;
if(!strcmp(value_dec+valuepos,"newbies")) goto nothingtodo;
format_username(value_dec+valuepos);
if(usernameexist(value_dec+valuepos)) goto nothingtodo;
if(!userrenamed(value_dec+valuepos,&fixed_value)) goto nothingtodo;
else
{
goto cleanup;
}
break;
}
case 2:
p=var+1;
if(!p->s) goto nothingtodo;
break;
case 3:
p=var+2;
if(!p->s) goto nothingtodo;
break;
case 4:
p=var+3;
if(!p->s) goto nothingtodo;
break;
}
baseurlpos=p->s-url;
strcpy(value_ori,p->s);
value_dec_len=URLtryDecode(value_ori,p->len,value_dec,2047,1);
while(value_dec_len>0)
{
if(value_dec[value_dec_len-1]==' ') value_dec_len--;
else break;
}
valuepos=0;
while(value_dec[valuepos]==' ') valuepos++;
if(valuepos>=value_dec_len) goto nothingtodo;
value_dec[value_dec_len]=0;
if(isip(value_dec+i)) goto nothingtodo;
if(!strcmp(value_dec+valuepos,"newbies")) goto nothingtodo;
format_username(value_dec+valuepos);
if(usernameexist(value_dec+valuepos)) goto nothingtodo;
if(!userrenamed(value_dec+valuepos,&fixed_value)) goto nothingtodo;
strncpy(fixed_url,url,baseurlpos);
fixed_url[baseurlpos]=0;
cleanup:
strcat(fixed_url,fixed_value);
strcat(fixed_url,p->s+p->len);
format_url(fixed_url);
todo=1;
nothingtodo:
return todo;
}
static int pagecheck(const char *pageid,const char *basetime,HTTP f)
{
HTTP newtext;
int status=0,error=0,todo=0;
int i=0,namepos=0,displaypos=0;
int protpos=0;
unsigned int domainpos=0;
int urlpos=0;
char ch=0,name[2048],fixed_name[2048],name_e[4096],display[2048],display_e[4096];
char url[2048],url_e[8192],fixed_url[2048];
newtext=hopen();
hputs("&text=",6,newtext);
while(xmlpulltext(f,&ch)==XML_TEXT_CONTINUE)
{
switch(status)
{
case 0:
if(ch=='[')
{
status=1;
}
smartURLEncode(ch,newtext);
break;
case 1:
if(ch=='[')
{
status=2;
namepos=0;
}
else if(ch=='h'||ch=='H')
{
status=4;
protpos=1;
}
else if(ch=='/')
{
status=6;
domainpos=2;
}
else status=0;
smartURLEncode(ch,newtext);
break;
case 2:
if(ch=='|')
{
name[namepos]=0;
status=3;
displaypos=0;
}
else if(ch==']')
{
name[namepos]=0;
if(checkusercontrib(name,fixed_name))
{
todo=1;
i=URLEncode(fixed_name,strlen(fixed_name),name_e,2048);
}
else
{
i=URLEncode(name,namepos,name_e,4095);
}
hputs(name_e,i,newtext);
smartURLEncode(']',newtext);
status=0;
}
else if((namepos>512)||ch=='{'||ch=='}'||ch=='<'||ch=='>'||ch=='['||ch=='\n'||ch=='\r')
{
name[namepos]=0;
i=URLEncode(name,namepos,name_e,4095);
hputs(name_e,i,newtext);
smartURLEncode(ch,newtext);
if(ch=='[')
{
status=1;
}
else status=0;
}
else
{
name[namepos++]=ch;
}
break;
case 3:
if(ch==']')
{
display[displaypos]=0;
if(checkusercontrib(name,fixed_name))
{
todo=1;
i=URLEncode(fixed_name,strlen(fixed_name),name_e,2048);
}
else
{
i=URLEncode(name,namepos,name_e,2048);
}
hputs(name_e,i,newtext);
smartURLEncode('|',newtext);
i=URLEncode(display,displaypos,display_e,2048);
hputs(display_e,i,newtext);
smartURLEncode(']',newtext);
status=0;
}
else if(ch=='[')
{
display[displaypos]=0;
if(checkusercontrib(name,fixed_name))
{
todo=1;
i=URLEncode(fixed_name,strlen(fixed_name),name_e,2048);
}
else
{
i=URLEncode(name,namepos,name_e,2048);
}
hputs(name_e,i,newtext);
smartURLEncode('|',newtext);
i=URLEncode(display,displaypos,display_e,2048);
hputs(display_e,i,newtext);
status=1;
smartURLEncode(ch,newtext);
}
else if(displaypos>512)
{
display[displaypos]=0;
if(checkusercontrib(name,fixed_name))
{
todo=1;
i=URLEncode(fixed_name,strlen(fixed_name),name_e,2048);
}
else
{
i=URLEncode(name,namepos,name_e,2048);
}
hputs(name_e,i,newtext);
smartURLEncode('|',newtext);
i=URLEncode(display,displaypos,display_e,2048);
hputs(display_e,i,newtext);
status=0;
smartURLEncode(ch,newtext);
}
else
{
display[displaypos++]=ch;
}
break;
case 4:
if((ch==http_mark1[protpos])||(ch==http_mark2[protpos]))
{
protpos++;
}
else if(ch=='[')
{
status=1;
protpos=0;
}
else
{
status=0;
protpos=0;
}
if(protpos==4)
{
status=5;
protpos=0;
}
smartURLEncode(ch,newtext);
break;
case 5:
if(ch==':')
{
status=6;
domainpos=1;
}
else if(ch=='s'||ch=='S')
{
status=6;
domainpos=0;
}
else if(ch=='[')
{
status=1;
}
else status=0;
smartURLEncode(ch,newtext);
break;
case 6:
if(ch==domain_mark1[domainpos]||ch==domain_mark2[domainpos])
{
domainpos++;
}
else if(ch=='[')
{
status=1;
domainpos=0;
}
else
{
status=0;
domainpos=0;
}
if(domainpos==strlen(domain_mark1))
{
status=7;
domainpos=0;
}
smartURLEncode(ch,newtext);
break;
case 7:
if(ch==']'||ch==' ')
{
url[urlpos]=0;
if(url_checkusercontrib(url,fixed_url))
{
i=URLEncode(fixed_url,strlen(fixed_url),url_e,8190);
todo=1;
}
else
{
i=URLEncode(url,urlpos,url_e,8190);
}
hputs(url_e,i,newtext);
urlpos=0;
status=0;
smartURLEncode(ch,newtext);
}
else if(ch=='|'||ch=='{'||ch=='}'||ch=='['||ch=='\n'||ch=='\r'||urlpos>1024)
{
url[urlpos]=0;
i=URLEncode(url,urlpos,url_e,8190);
hputs(url_e,i,newtext);
urlpos=0;
if(ch=='[')
{
status=1;
}
else status=0;
smartURLEncode(ch,newtext);
}
else
{
url[urlpos++]=ch;
}
break;
}
}
if(xmlpulltext(f,&ch)!=XML_TEXT_END) error=1;
if(todo&&!status&&!error)
{
struct neditargv point;
point.newtext=newtext;
point.id=pageid;
point.time=basetime;
smartedit(&point,"bot: cleanup after user rename",NULL);
}
hclose(newtext);
return 0;
}
static int proceedchild(const char *ids)
{
char url[4096];
char buf[8192];
char pageid[256];
char timestamp[256];
char contentmodel[64],contentformat[64];
const char *ttm[]={"pageid"};
const char *tmm[]={"timestamp"};
const char *cmm[]={"contentmodel","contentformat"};
char *ttv[1];
char *tmv[1];
char *cmv[2];
int result;
int status;
HTTP h;
ttv[0]=pageid;
tmv[0]=timestamp;
cmv[0]=contentmodel;
cmv[1]=contentformat;
if(!ids)
{
return -1;
}
sprintf(url,"/w/api.php?action=query&format=xml&prop=revisions&rvprop=content|timestamp&pageids=%s&rvslots=main",ids);
h=hopen();
if(get(url,8888,1,h))
{
hclose(h);
return -2;
}
hgets(buf,4096,h);
if(!strstr(buf," 200"))
{
hclose(h);
return -3;
}
if(skipresponseheader(h))
{
hclose(h);
return -3;
}
status=0;
while(!heof(h))
{
result=xmlparsetag(h,buf);
if(result==XML_HAS_VALUE)
{
switch(status)
{
case 0:
if(!strcmp(buf,"page")&&(xmlparsearg(h,1,ttm,ttv)==XML_HAS_VALUE))
{
if(atoi(pageid)>0) status=1;
}
break;
case 1:
if(!strcmp(buf,"rev"))
{
if(xmlparsearg(h,1,tmm,tmv)!=XML_HAS_VALUE)
{
status=3;
goto _cleanup;
}
status=2;
}
else goto _cleanup;
break;
case 2:
if(!strcmp(buf,"slot"))
{
if(xmlparsearg(h,2,cmm,cmv)!=XML_HAS_VALUE)
{
status=3;
goto _cleanup;
}
if(!strcmp(contentmodel,"wikitext")&&!strcmp(contentformat,"text/x-wiki"))
{
pagecheck(pageid,timestamp,h);
}
status=0;
}
else goto _cleanup;
break;
}
}
else if(result==XML_PARSE_ERROR)
{
status=3;
goto _cleanup;
}
}
_cleanup:
hclose(h);
return status?-4:0;
}
static void threadfunc(void *c)
{
int ext=0;
char pageid[10][64];
int count=0;
char ids[4096];
int result=0;
struct problemlist *temp;
while(!action) Sleep(1);
while(1)
{
EnterCriticalSection(&hcs);
for(count=0;count<10;count++)
{
if(pbl)
{
temp=pbl;
pbl=pbl->next;
sprintf(pageid[count],"%d",temp->pageid);
s_free(temp);
}
else
{
ext=2-(!count);
count++;
break;
}
}
count--;
if(count>=0)
{
strcpy(ids,pageid[count]);
count--;
while(count>=0)
{
strcat(ids,"|");
strcat(ids,pageid[count]);
count--;
}
}
LeaveCriticalSection(&hcs);
if(ext==1) break;
else
{
result=proceedchild(ids);
if(ext==2) break;
}
}
EnterCriticalSection(&tcs);
threadnumber--;
LeaveCriticalSection(&tcs);
return ;
}
static int threadini(int count)
{
int i=0;
int flag=0;
threadnumber=0;
for(i=0;i<count;i++)
{
threadc[i]=i;
flag=_beginthread(threadfunc,0,(void *)(threadc+i));
if(flag>0) threadnumber++;
}
return 0;
}
static int query(const char *target,const char *ns)
{
HTTP f;
char target_e[512],line[2048]={0},url[4096]={0},snd[4096]={0},id[512]={0},title[512]={0},sroffset[2048]={0},offseto[512]={0};
char statusline[128]={0};
int next=0,retry=0,pageid=0;
struct problemlist *temp=0;
char *ctm[]={"gsroffset"};
char *ctv[1];
char *idm[]={"pageid","title"};
char *idv[2];
ctv[0]=offseto;
idv[0]=id;
idv[1]=title;
if(strlen(target)>128)
{
printf("Search string too long!\n");
return -1;
}
URLEncode(target,strlen(target),target_e,511);
sprintf(url,"/w/api.php?action=query&format=xml&generator=search&prop=info&gsrlimit=500&gsrnamespace=%s&gsrsearch=%s",ns,target_e);
do
{
strcpy(snd,url);
if(next)
{
strcat(snd,"&gsroffset=");
strcat(snd,sroffset);
}
f=hopen();
retry=0;
do
{
if(get(snd,8888,1,f))
{
hclose(f);
f=hopen();
}
else
{
hgets(statusline,127,f);
if(strstr(statusline,"200")) break;
else
{
hclose(f);
f=hopen();
}
}
retry++;
}while(retry<20);
if(retry==20)
{
hclose(f);
return 1;
}
skipresponseheader(f);
next=0;
do
{
xmlparsetag(f,line);
if(!next)
{
if(!strcmp(line,"continue"))
{
xmlparsearg(f,1,ctm,ctv);
URLEncode(offseto,strlen(offseto),sroffset,2047);
next=1;
}
}
if(!strcmp(line,"page"))
{
xmlparsearg(f,2,idm,idv);
if((pageid=atoi(id))>0)
{
temp=(struct problemlist *)s_malloc(sizeof(struct problemlist));
temp->pageid=pageid;
temp->next=pbl;
pbl=temp;
}
}
}while(!heof(f));
hclose(f);
}while(next);
return 0;
}
static int allpagequery(const char *ns)
{
HTTP f;
char line[2048]={0},url[4096]={0},snd[4096]={0},id[512]={0},title[512]={0},sroffset[2048]={0},offseto[512]={0};
char statusline[128];
int next=0,retry=0,pageid=0;
struct problemlist *temp=0;
char *ctm[]={"apcontinue"};
char *ctv[1];
char *idm[]={"pageid","title"};
char *idv[2];
ctv[0]=offseto;
idv[0]=id;
idv[1]=title;
sprintf(url,"/w/api.php?action=query&format=xml&list=allpages&apnamespace=%s&aplimit=5000",ns);
do
{
strcpy(snd,url);
if(next)
{
strcat(snd,"&apcontinue=");
strcat(snd,sroffset);
}
f=hopen();
for(retry=0;retry<20;retry++)
{
if(get(snd,8888,1,f))
{
hclose(f);
f=hopen();
}
else
{
hgets(statusline,127,f);
if(strstr(statusline,"200")) break;
else
{
hclose(f);
f=hopen();
}
}
}
if(retry==20)
{
hclose(f);
return 1;
}
skipresponseheader(f);
next=0;
do
{
xmlparsetag(f,line);
if(!next)
{
if(!strcmp(line,"continue"))
{
xmlparsearg(f,1,ctm,ctv);
URLEncode(offseto,strlen(offseto),sroffset,2047);
next=1;
}
}
if(!strcmp(line,"p"))
{
xmlparsearg(f,2,idm,idv);
if((pageid=atoi(id))>0)
{
temp=(struct problemlist *)s_malloc(sizeof(struct problemlist));
temp->pageid=pageid;
temp->next=pbl;
pbl=temp;
}
}
}while(!heof(f));
hclose(f);
}while(next);
return 0;
}
static int loadusernametable()
{
HTTP f;
char line[2048]={0},url[4096]={0},snd[4096]={0},id[512]={0},name[512]={0},sroffset[2048]={0},offseto[512]={0};
char statusline[128];
int status=0,next=0,retry=0,count=0;
char *ctm[]={"aufrom"};
char *ctv[1];
char *idm[]={"userid","name"};
char *idv[2];
ctv[0]=offseto;
idv[0]=id;
idv[1]=name;
usernamelist=hashini();
sprintf(url,"/w/api.php?action=query&list=allusers&format=xml&aulimit=5000");
do
{
strcpy(snd,url);
if(next)
{
strcat(snd,"&aufrom=");
strcat(snd,sroffset);
}
f=hopen();
for(retry=0;retry<20;retry++)
{
if(get(snd,8888,1,f))
{
hclose(f);
f=hopen();
}
else
{
hgets(statusline,127,f);
if(!strstr(statusline,"200"))
{
hclose(f);
f=hopen();
}
else
{
skipresponseheader(f);
next=0;count=0;
do
{
if(xmlparsetag(f,line)==XML_PARSE_ERROR) break;
if(!next)
{
if(!strcmp(line,"continue"))
{
xmlparsearg(f,1,ctm,ctv);
URLEncode(offseto,strlen(offseto),sroffset,2047);
next=1;
}
}
if(!strcmp(line,"allusers"))
{
status=1;
}
if(!strcmp(line,"u"))
{
if(xmlparsearg(f,2,idm,idv)!=XML_HAS_VALUE) break;
count++;
if(!strstr(name,"~zhwiki"))
{
void *p;
if(!str_hashquery(usernamelist,name,&p))
{
if(output)
{
fprintf(fp1,"%s\n",name);
fflush(fp1);
}
str_hashadd(usernamelist,name,0);
}
}
}
}while(!heof(f));
hclose(f);
if(status&&((!next)||(count==5000))) break;
else
{
f=hopen();
}
}
}
}
if(retry==20)
{
hclose(f);
return 1;
}
}while(next);
if(output) fclose(fp1);
return !status;
}
static int loaduserfromlocalfile()
{
char line[1024];
int length;
usernamelist=hashini();
while(!feof(fp))
{
void *p;
fgets(line,1023,fp);
length=strlen(line);
if(line[length-1]=='\n')
{
line[length-1]=0;
length--;
}
if(!str_hashquery(usernamelist,line,&p))
{
str_hashadd(usernamelist,line,NULL);
}
}
fclose(fp);
return 0;
}
static int loadrenamelog()
{
HTTP f;
void *p;
char line[2048]={0},url[4096]={0},snd[4096]={0},olduser[512]={0},newuser[512]={0},sroffset[2048]={0},offseto[512]={0};
char statusline[128];
int next=0,retry=0,bad=0;
char *ctm[]={"lecontinue"};
char *ctv[1];
char *idm[]={"olduser","newuser"};
char *idv[2];
ctv[0]=offseto;
idv[0]=olduser;
idv[1]=newuser;
userrenamelist=hashini();
dupuserlist=hashini();
baduserlist=hashini();
sprintf(url,"/w/api.php?action=query&list=logevents&format=xml&leprop=details&letype=renameuser&lelimit=5000");
do
{
strcpy(snd,url);
if(next)
{
strcat(snd,"&lecontinue=");
strcat(snd,sroffset);
}
f=hopen();
for(retry=0;retry<20;retry++)
{
if(get(snd,8888,1,f))
{
hclose(f);
f=hopen();
}
else
{
hgets(statusline,127,f);
if(strstr(statusline,"200")) break;
else
{
hclose(f);
f=hopen();
}
}
}
if(retry==20)
{
hclose(f);
return 1;
}
skipresponseheader(f);
next=0;
do
{
xmlparsetag(f,line);
if(!next)
{
if(!strcmp(line,"continue"))
{
xmlparsearg(f,1,ctm,ctv);
URLEncode(offseto,strlen(offseto),sroffset,2047);
next=1;
}
}
if(!strcmp(line,"params"))
{
xmlparsearg(f,2,idm,idv);
bad=0;
if(!olduser[0]||!newuser[0]) continue;
else if(strstr(olduser,"~zhwiki")||strstr(newuser,"~zhwiki"))
{
bad=2;
}
else if(str_hashquery(baduserlist,newuser,&p))
{
bad=2;
}
else if(str_hashquery(userrenamelist,newuser,&p))
{
void *q;
if(str_hashquery(usernamelist,olduser,&q))
{
bad=1;
}
else
{
if(str_hashquery(userrenamelist,olduser,&q))
{
if(strcmp(q,p)) bad=1;
s_free(q);
}
q=s_calloc(strlen(p)+3,1);
strcpy(q,p);
str_hashadd(userrenamelist,olduser,q);
}
}
else if(str_hashquery(usernamelist,newuser,&p))
{
void *q;
if(str_hashquery(usernamelist,olduser,&q))
{
bad=1;
}
else
{
if(str_hashquery(userrenamelist,olduser,&q))
{
if(strcmp(q,newuser)) bad=1;
s_free(q);
}
p=s_calloc(strlen(newuser)+3,1);
strcpy(p,newuser);
str_hashadd(userrenamelist,olduser,p);
}
}
else bad=2;
switch(bad)
{
case 0:
break;
case 1:
if(!str_hashquery(dupuserlist,olduser,&p))
{
str_hashadd(dupuserlist,olduser,NULL);
}
break;
case 2:
if(!str_hashquery(baduserlist,olduser,&p))
{
str_hashadd(baduserlist,olduser,NULL);
}
break;
}
}
}while(!heof(f));
hclose(f);
}while(next);
return 0;
}
#ifdef _DEBUG
#include <crtdbg.h>
void dumpfunc(const char *name,void *p,void *q)
{
fprintf((FILE *)q,"%s\n",name);
return;
}
void dumpbadlog()
{
FILE *fp=fopen("debug.txt","w+");
str_hashdump(baduserlist,dumpfunc,fp);
fclose(fp);
return;
}
void dumpduplog()
{
FILE *fp=fopen("dup.txt","w+");
str_hashdump(dupuserlist,dumpfunc,fp);
fclose(fp);
return;
}
void dumprnfunc(const char *name,void *p,void *q)
{
fprintf((FILE *)q,"%s -> %s\n",name,(char *)p);
return;
}
void dumprenamelog()
{
FILE *fp=fopen("rename.txt","w+");
str_hashdump(userrenamelist,dumprnfunc,fp);
fclose(fp);
return;
}
int main(int argc,char **argv)
{
int count=0;
if(parsearg(argc,argv))
{
printf("usage: -u username -p passwd [-T concurrency -s searchstring -a allpagequery -n namespace -i inputfile -o outputfile]\n");
return -1;
}
InitializeSRWLock(&rwcs);
InitializeCriticalSection(&tcs);
InitializeCriticalSection(&hcs);
buckini(20);
if(login(username,passwd))
{
printf("Login error!\n");
return -2;
}
hastoken=0;
printf("Login complete.\n");
fflush(stdout);
if(loadfromfile)
{
loaduserfromlocalfile();
}
else loadusernametable();
loadrenamelog();
dumprenamelog();
dumpduplog();
dumpbadlog();
ini_marks();
printf("ready!\n");
proceedchild("5157328");
AcquireSRWLockExclusive(&rwcs);
hastoken=-1;
ReleaseSRWLockExclusive(&rwcs);
system("PAUSE");
buckdestroy();
str_hashdestroy(usernamelist);
str_hashdestroy_withfree(userrenamelist,s_free);
str_hashdestroy(baduserlist);
str_hashdestroy(dupuserlist);
str_hashdestroy(logtype);
str_hashdestroy(urltoken);
_CrtDumpMemoryLeaks();
return 0;
}
#else
int main(int argc,char *argv[])
{
int count=0,res=0;
HANDLE tk_thread;
if(parsearg(argc,argv))
{
printf("usage: -u username -p passwd [-T concurrency -s searchstring -a allpagequery -n namespace]\n");
return -1;
}
InitializeSRWLock(&rwcs);
InitializeCriticalSection(&tcs);
InitializeCriticalSection(&hcs);
buckini(20);
if(login(username,passwd))
{
printf("Login error!\n");
return -2;
}
hastoken=0;
printf("Login complete.\n");
fflush(stdout);
ini_marks();
tk_thread=(HANDLE)_beginthread(tokenmanage,0,0);
if(loadfromfile)
{
res=loaduserfromlocalfile();
}
else res=loadusernametable();
if(res)
{
printf("Load username list error!\n");
return -3;
}
if(loadrenamelog())
{
printf("Load user-rename list error!\n");
return -4;
}
if(doallpage)
{
allpagequery(ns);
}
else query(searchstring,ns);
if(pbl==NULL)
{
printf("No page!\n");
return -5;
}
printf("Query complete.\n");
action=0;
threadini(maxthread);
action=1;
while(1)
{
EnterCriticalSection(&hcs);
if(pbl!=NULL)
{
LeaveCriticalSection(&hcs);
Sleep(1000);
}
else
{
LeaveCriticalSection(&hcs);
break;
}
}
count=0;
while(count<150)
{
count++;
EnterCriticalSection(&tcs);
if(threadnumber>0)
{
printf("Waiting for all threads to exit. Current thread number: %d\n",threadnumber);
LeaveCriticalSection(&tcs);
}
else
{
LeaveCriticalSection(&tcs);
break;
}
fflush(stdout);
Sleep(1000);
}
if(!threadnumber)
{
printf("Cleanup...\n");
DeleteCriticalSection(&tcs);
DeleteCriticalSection(&hcs);
AcquireSRWLockExclusive(&rwcs);
hastoken=-1;
ReleaseSRWLockExclusive(&rwcs);
WaitForSingleObject(tk_thread,INFINITE);
buckdestroy();
str_hashdestroy(usernamelist);
str_hashdestroy_withfree(userrenamelist,s_free);
str_hashdestroy(dupuserlist);
str_hashdestroy(baduserlist);
str_hashdestroy(logtype);
str_hashdestroy(urltoken);
}
printf("---------------Ok done.---------------\n");
fflush(stdout);
system("PAUSE");
return 0;
}
#endif