用户:Antigng-bot2/highrisktemp

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <process.h>
#include "mem.h"
#include "network.h"
#include "auth.h"
#include "convert.h"
struct problemlist
{
	int pageid;
	struct problemlist *next;
};
int threadc[1024];
char *threads[1024];
SRWLOCK rwcs;
CRITICAL_SECTION tcs;
CRITICAL_SECTION fcs;
CRITICAL_SECTION hcs;
int threadnumber=0;
int action=0;
struct problemlist *pbl=NULL;

int hideredirect=0;
int pagenum=0;
int hasquerytimeslimit=0;
int maxquerytimes=500;
int maxthread=256;
int logerr=0;
int test_mode=0;
const char *username;
const char *passwd;
FILE *debug;
FILE *err_log;

#define FULL_PROTECT 2
#define FULL_LIMIT 5000
#define SEMI_PROTECT 1
#define SEMI_LIMIT 500
#define NO_PROTECT 0

static int checkprotect(int pageid,int checklevel)
{
	HTTP res;
	char line[2048]={0},url[4096]={0},pttype[16],ptlevel[16],pttime[64];
	char statusline[128];
	int retry=0;
	int haseditprot=0;
	char *ptm[]={"type","level","expiry"};
	char *ptv[3];
	ptv[0]=pttype;
	ptv[1]=ptlevel;
	ptv[2]=pttime;
	sprintf(url,"/w/api.php?action=query&format=xml&pageids=%d&prop=info&inprop=protection",pageid);
	res=hopen();
	for(retry=0;retry<20;retry++)
	{
		if(get(url,8888,1,res))
		{
			hclose(res);
			res=hopen();
		}
		else
		{
			hgets(statusline,127,res);
			if(strstr(statusline,"200")) break;
			else
			{
				hclose(res);
				res=hopen();
			}
		}
	}
	if(retry==20)
	{
		hclose(res);
		return -1;
	}
	skipresponseheader(res);
	do
	{
		if(xmlparsetag(res,line)==XML_PARSE_ERROR)
		{
			hclose(res);
			return -1;
		}
		if(!strcmp(line,"pr"))
		{
			if(xmlparsearg(res,3,ptm,ptv)!=XML_HAS_VALUE)
			{
				hclose(res);
				return -1;
			}
			if(!strcmp(pttime,"infinity"))
			{
				switch(checklevel)
				{
				case 1:
					if(!strcmp(pttype,"edit")) haseditprot=1;
					break;
				case 2:
					if(!strcmp(ptlevel,"sysop")||!strcmp(ptlevel,"templateeditor"))
					{
						if(!strcmp(pttype,"edit")) haseditprot=1;
					}
					break;
				}
			}
		}
	}while(!heof(res));
	hclose(res);
	return !haseditprot;
}

static int transcludesitu(int pageid)
{
	HTTP res;
	char line[2048]={0},url[4096]={0},snd[4096]={0},sroffset[2048]={0},offseto[512]={0},ids[16]={0};
	char statusline[128];
	int next=0,retry=0;
	int count=0;
	char *ctm[]={"ticontinue"};
	char *ctv[1];
	char *ttm[]={"pageid"};
	char *ttv[1];
	ctv[0]=offseto;
	ttv[0]=ids;
	sprintf(url,"/w/api.php?action=query&format=xml&prop=transcludedin&pageids=%d&tilimit=5000&tiprop=pageid",pageid);
	do
	{
		strcpy(snd,url);
		if(next)
		{
			strcat(snd,"&ticontinue=");
			strcat(snd,sroffset);
		}
		res=hopen();
		for(retry=0;retry<20;retry++)
		{
			if(get(snd,8888,1,res))
			{
				hclose(res);
				res=hopen();
			}
			else
			{
				hgets(statusline,127,res);
				if(strstr(statusline,"200")) break;
				else
				{
					hclose(res);
					res=hopen();
				}
			}
		}
		if(retry==20)
		{
			hclose(res);
			return -1;
		}
		skipresponseheader(res);
		next=0;
		do
		{
			if(xmlparsetag(res,line)==XML_PARSE_ERROR) break;
			if(!next)
			{
				if(!strcmp(line,"continue"))
				{
					if(xmlparsearg(res,1,ctm,ctv)==XML_HAS_VALUE)
					{
						URLEncode(offseto,strlen(offseto),sroffset,2047);
						next=1;
					}
					else break;
				}
			}
			if(!strcmp(line,"ti"))
			{
				if(xmlparsearg(res,1,ttm,ttv)==XML_HAS_VALUE) count++;
				else break;
			}
		}while(!heof(res));
		hclose(res);
		if(next==1)
		{
			if(count>=FULL_LIMIT) return FULL_PROTECT;
		}
		else 
		{
			if(count>FULL_LIMIT) return FULL_PROTECT;
			else if(count>SEMI_LIMIT) return SEMI_PROTECT;
		}
	}while(next);
	return NO_PROTECT;
}
static int fake_protect(int pageid,const char *type,const char *reason,const char *expiry)
{
	EnterCriticalSection(&fcs);
	fprintf(debug,"#pageid=%d type=%s reason=%s expiry=%s\n",pageid,type,reason,expiry);
	fflush(debug);
	LeaveCriticalSection(&fcs);
	return 0;
}
static int protect(int pageid,const char *type,const char *reason,const char *expiry)
{
	HTTP res;
	char line[2048]={0},url[4096]={0};
	char tp_enc[1024],rs_enc[1024],exp_enc[512];
	char postbody[256],statusline[128];
	char cur_token[128];
	char err_type[8192];
	char err_info[8192];
	char *erm[]={"code","info"};
	char *erv[2];
	int has_err=0,token_err=0;
	int retry=0;
	erv[0]=err_type;
	erv[1]=err_info;
	URLEncode(type,strlen(type),tp_enc,1023);
	URLEncode(reason,strlen(reason),rs_enc,1023);
	URLEncode(expiry,strlen(expiry),exp_enc,511);
	sprintf(url,"/w/api.php?action=protect&format=xml&pageid=%d&protections=%s&reason=%s&expiry=%s",pageid,tp_enc,rs_enc,exp_enc);
	do
	{
		res=hopen();
		while(1)
		{
			AcquireSRWLockShared(&rwcs);
			if(hastoken) break;
			else ReleaseSRWLockShared(&rwcs);
			Sleep(100);
		}
		strcpy(cur_token,token);
		ReleaseSRWLockShared(&rwcs);
		sprintf(postbody,"&token=%s",cur_token);
		if(post(url,postbody,8888,1,res))
		{
			hclose(res);
			return -1;
		}
		hgets(statusline,127,res);
		if(!strstr(statusline," 200"))
		{
			hclose(res);
			return -2;
		}
		skipresponseheader(res);
		token_err=has_err=0;
		while(!heof(res))
		{
			if(xmlparsetag(res,line)==XML_HAS_VALUE)
			{
				if(!strcmp(line,"error"))
				{
					has_err=1;
					xmlparsearg(res,2,erm,erv);
					if((!strcmp(err_type,"notoken"))||(!strcmp(err_type,"badtoken")))
					{
						token_err=1;
					}
					break;
				}
			}
		}
		if(token_err)
		{
			AcquireSRWLockExclusive(&rwcs);
			if(!strcmp(token,cur_token)) hastoken=0;
			ReleaseSRWLockExclusive(&rwcs);
		}
		retry++;
		hclose(res);
	}while((token_err==1)&&(retry<3));
	if(has_err==1)
	{
		if(logerr)
		{
			EnterCriticalSection(&fcs);
			fprintf(err_log,"Error protecting page %d: type=%s reason=%s expiry=%s error=%s\nerror info=%s\n\n",pageid,type,reason,expiry,err_type,err_info);
			fflush(err_log);
			LeaveCriticalSection(&fcs);
		}
		return -3;
	}
	else return 0;
}

const char *reason_HRT=NULL;
static int proceedchild(int pageid)
{
	switch(transcludesitu(pageid))
	{
	case SEMI_PROTECT:
		if(checkprotect(pageid,SEMI_PROTECT)==1)
		{
			return test_mode==1?fake_protect(pageid,"edit=autoconfirmed",reason_HRT,"never"):protect(pageid,"edit=autoconfirmed",reason_HRT,"never");
		}
		break;
	case FULL_PROTECT:
		if(checkprotect(pageid,FULL_PROTECT)==1)
		{
			return test_mode==1?fake_protect(pageid,"edit=templateeditor|move=sysop",reason_HRT,"never"):protect(pageid,"edit=templateeditor|move=sysop",reason_HRT,"never");
		}
		break;
	}
	return 0;
}
void threadfunc(void *c)
{
	int i=*(int *)c;
	int ext=0;
	int result=0;
	int id=0;
	struct problemlist *p;
	while(!action) Sleep(1);
	while(1)
	{
		EnterCriticalSection(&hcs);
		if(p=pbl)
		{
			id=pbl->pageid;
			pbl=pbl->next;
		}
		else ext=1;
		LeaveCriticalSection(&hcs);
		if(ext) break;
		else
		{
			result=proceedchild(id);
			s_free(p);
		}
	}             
	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 allpagequery(const char *ns)
{
	HTTP f;
	char line[2048]={0},url[4096]={0},id[512]={0},title[512]={0},sroffset[2048]={0},offseto[512]={0};
	char statusline[128];
	int status=0,next=0,retry=0,pageid=0;
	struct problemlist *temp=0;
	char *ctm[]={"apcontinue"};
	char *ctv[1];
	char *idm[]={"pageid","title"};
	char *idv[2];
	char *ptourl=url;
	ctv[0]=offseto;
	idv[0]=id;
	idv[1]=title;
	ptourl+=sprintf(url,"/w/api.php?action=query&format=xml&list=allpages&apnamespace=%s&aplimit=5000&apfilterredir=%s",ns,hideredirect?"nonredirects":"all");
	do
	{
		if(next)
		{
			sprintf(ptourl,"&apcontinue=%s",sroffset);
		}
		else *ptourl=0;
		f=hopen();
		for(retry=0;retry<20;retry++)
		{
			if(get(url,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;status=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;
					pagenum++;
				}
			}
		}while(!heof(f));
		hclose(f);
		if(hasquerytimeslimit)
		{
			if(--maxquerytimes<=0) break;
		}
	}while(next);
	return 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&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&0x80)
	{
		printf(
			"\tInvalid debug file.\n"
			"\t\tCannot open the specified debug file.\n"
			);
	}
	if(code&0x100)
	{
		printf(
			"\tInvalid log file.\n"
			"\t\tCannot open the specified log file.\n"
			);
	}
	return;
}
static int parsearg(int argc,const char *argv[])
{
	int cur_arg=0;
	unsigned int err=0;
	for(cur_arg=1;cur_arg<argc;cur_arg++)
	{
		if(argv[cur_arg][0]=='-'&&(argv[cur_arg+1]&&argv[cur_arg+1][0]!='-'))
		{
			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 'p':
				passwd=argv[cur_arg+1];
				if(strlen(passwd)>64)
				{
					err|=0x8;
				}
				else
				{
					err|=0x10;
				}
				cur_arg++;
				break;
			case 'T':
				maxthread=atoi(argv[cur_arg+1]);
				if(maxthread<1||maxthread>1024) maxthread=32;
				cur_arg++;
				break;
			case 'm':
				maxquerytimes=atoi(argv[cur_arg+1]);
				if(maxquerytimes>0) hasquerytimeslimit=1;
				break;
			case 'd':
				if((debug=fopen(argv[cur_arg+1],"w+"))!=NULL)
				{
					test_mode=1;
				}
				else
				{
					err|=0x80;
				}
				break;
			case 'l':
				if((err_log=fopen(argv[cur_arg+1],"a+"))!=NULL)
				{
					fprintf(err_log,"--------- Logging... ---------\n");
					logerr=1;
				}
				else
				{
					err|=0x100;
				}
				break;
			}
		}
	}
	if(0x1+0x10==err) return 0;
	else
	{
		displayerr(err);
		return err;
	}
}
static void ini_marks()
{
	reason_HRT=G2U("bot: [[WP:HRT|high-risk templates/高风险模板/高風險模板]]");
	return;
}
static void printusage()
{
	printf("usage: -u username -p passwd [-T concurrency -d debug_file -l err_log -m maxquery]\n");
	return ;
}
#ifndef _DEBUG
int main(int argc,char **argv)
{
	int count=0;
	HANDLE tk_thread=0;
	buckini(20);
	InitializeSRWLock(&rwcs);
	InitializeCriticalSection(&tcs);
	InitializeCriticalSection(&hcs);
	InitializeCriticalSection(&fcs);
	if(parsearg(argc,argv))
	{
		printusage();
		return -1;
	}
	if(login(username,passwd))
	{
		printf("Login error!\n");
		return -2;
	}
	ini_marks();
	if(!test_mode)
	{
		tk_thread=(HANDLE)_beginthread(tokenmanage,0,0);
	}
	allpagequery("10");
	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);
		if(!test_mode) WaitForSingleObject(tk_thread,INFINITE);
		buckdestroy();
	}
	else printf("%d threads left.\n",threadnumber);
	printf("---------------Ok done.---------------\n");	 
	fflush(stdout);
	if(logerr) fclose(err_log);
	if(test_mode) fclose(debug);
	return 0;
}
#else
int main(void)
{
	buckini(20);
	InitializeSRWLock(&rwcs);
	InitializeCriticalSection(&tcs);
	InitializeCriticalSection(&hcs);
	InitializeCriticalSection(&fcs);
	login("Antigng@Antigng","");
	ini_marks();
	_beginthread(tokenmanage,0,0);
	Sleep(5000);
	logerr=1;
	err_log=stdout;
	proceedchild(557733);
	return 0;
}
#endif