用户:Antigng-bot/auth

#include <stdio.h>
#include <string.h>
#include <process.h> 
#include <windows.h>
#include "mem.h"
#include "network.h"
#include "convert.h"
#include "auth.h"

/*Cookies & session*/

struct _cookie
{
	char name[512];
	char value[512];
	struct _cookie *next;
};
struct _cookie *cookielist=NULL;
char session[4096]={0};
int sessionlength=0;

static int destroycookielist()
{
	struct _cookie *pre,*temp;
	temp=pre=cookielist;
	while(temp)
	{
		pre=temp;
		temp=temp->next;
		s_free(pre);
	}
	cookielist=NULL;
	return 0;
}
static int addtocookielist(const char *name,const char *value)
{
	struct _cookie *head=cookielist,*pre=NULL;
	while(head)
	{
		if(!strcmp(head->name,name)) break;
		pre=head;
		head=head->next;
	}
	if(!head)
	{
		head=(struct _cookie *)s_malloc(sizeof(struct _cookie));
		if(pre)
		{
			pre->next=head;
		}
		else cookielist=head;
		strcpy(head->name,name);
		strcpy(head->value,value);
		head->next=0;
		return 1;
	}
	else
	{
		strcpy(head->value,value);
		return 0;
	}
}
static int deletefromcookielist(const char *name)
{
	struct _cookie *pre,*cur;
	pre=cur=cookielist;
	while(cur)
	{
		if(!strcmp(cur->name,name))
		{
			if(cur==cookielist)
			{
				cookielist=cookielist->next;
				s_free(cur);
			}
			else
			{
				pre->next=cur->next;
				s_free(cur);
			}
			return 1;
		}
		pre=cur;
		cur=cur->next;
	}
	return 0;
}
static void generatesessionfromcookies()
{
	struct _cookie *head;
	char *ptosession=session;
	head=cookielist;
	*ptosession=0;
	sessionlength=0;
	while(head)
	{
		int length=sprintf(ptosession,"%s=%s;",head->name,head->value);
		ptosession+=length;
		sessionlength+=length;
		head=head->next;
	}
	return ;
}
static int cookieexist(const char *name)
{
	struct _cookie *cur;
	cur=cookielist;
	while(cur)
	{
		if(!strcmp(cur->name,name))
		{
			return 1;
		}
		cur=cur->next;
	}
	return 0;
}
static int splitcookie(const char *cookie,char *name,char *value)
{
	int counter=0;
	const char *val;
	*name=*value=0;
	while(cookie[counter]==' ')
	{
		counter++;
	}
	val=strchr(cookie+counter,'=');
	if(val)
	{
		strncpy(name,cookie+counter,val-cookie-counter);
		name[val-cookie-counter]=0;
		strcpy(value,val+1);
		return 1;
	}
	return 0;
}
static int validatecookie(const char *value,const char *attr)
{
	if(!strcmp(value,"deleted"))
	{
		return 0;
	}
	else
	{
		const char *start=strstr(attr,"Max-Age=");
		if(start)
		{
			const char *end=strstr(start+8,";");
			char time[32];
			if(end)
			{
				strncpy(time,start+8,end-start-7);
				time[end-start-8]=0;
			}
			else
			{
				strncpy(time,start+8,30);
				time[30]=0;
			}
			if(atoi(time)<20) return 0;
		}
	}
	return 1;
}
static int deletesession(const char *name)
{
	deletefromcookielist(name);
	generatesessionfromcookies();
	return !(*session);
}
static int updatesession(const char *name,const char *value)
{
	if(sessionlength+strlen(name)+strlen(value)<2048)
	{
		addtocookielist(name,value);
		generatesessionfromcookies();
	}
	return !(*session);
}
void sessionmanage(const char *cookie,const char *attr)
{
	char name[512],value[512];
	if(splitcookie(cookie,name,value))
	{
		if(validatecookie(value,attr))
		{
			AcquireSRWLockExclusive(&rwcs);
			updatesession(name,value);
			ReleaseSRWLockExclusive(&rwcs);
		}
		else
		{
			AcquireSRWLockShared(&rwcs);
			if(cookieexist(name))
			{
				ReleaseSRWLockShared(&rwcs);
				AcquireSRWLockExclusive(&rwcs);
				deletesession(name);
				ReleaseSRWLockExclusive(&rwcs);
			}
			else
			{
				ReleaseSRWLockShared(&rwcs);
			}
		}
	}
	return ;
}

/*Login & logout*/

static int checkloginsucceed(HTTP h)
{
	char line[2048];
	int suc=0;
	while(!heof(h))
	{
		hgets(line,2047,h);
		if(strstr(line,"Success"))
		{
			suc=1;
			break;
		}
	}
	return suc;
}
int login(const char *username,const char *password)
{
	HTTP f;
	int tokenfound=0;
	char buf[1024];
	char postbody[1024],logintoken[128],raw_logintoken[128];
	char *lgm[]={"logintoken"};
	char *lgv[1];
	lgv[0]=raw_logintoken;
	f=hopen();
	if(get("/w/api.php?action=query&format=xml&meta=tokens&type=login",8888,0,f))
	{
		hclose(f);
		return 1;
	}
	skipresponseheader(f,1);
	while(!heof(f))
	{
		xmlparsetag(f,buf);
		if(!strcmp(buf,"tokens"))
		{
			xmlparsearg(f,1,lgm,lgv);
			URLEncode(raw_logintoken,strlen(raw_logintoken),logintoken,127);
			tokenfound=1;
			break;
		}
	}
	hclose(f);
	if(!tokenfound) return 1;
	sprintf(postbody,"&lgname=%s&lgpassword=%s&lgtoken=%s",username,password,logintoken);
	f=hopen();
	if(post("/w/api.php?action=login&format=xml",postbody,8888,1,f))
	{
		hclose(f);
		return 1;
	}
	skipresponseheader(f,1);
	if(!checkloginsucceed(f))
	{
		hclose(f);
		return 1;
	}
	hclose(f);
	printf("Auth complete.\n");
	return 0;
}
static int do_logout()
{
	HTTP res;
	char content[512],statusline[128];
	sprintf(content,"&token=%s",token);
	res=hopen();
	if(post("/w/api.php?action=logout&format=xml",content,8888,1,res))
	{
		hclose(res);
		return -1;
	}
	hgets(statusline,126,res);
	if(!strstr(statusline,"200"))
	{
		hclose(res);
		return -2;
	}
	if(skipresponseheader(res,1))
	{
		hclose(res);
		return -3;
	}
	hclose(res);
	return 0;
}
void logout()
{
	if(token[0])
	{
		if(!do_logout())
		{
			printf("Sucessfully logged out.\n");
		}
	}
	token[0]=0;
	session[0]=0;
	sessionlength=0;
	destroycookielist();
	return ;
}

/*Tokens*/

char token[128]={0};
int hastoken=0;

static int gettoken()
{
	HTTP f;
	int flag=0;
	char buf[1024];
	char raw_token[128];
	char *tkm[]={"csrftoken"};
	char *tkv[1];
	tkv[0]=raw_token;
	f=hopen();
	if(get("/w/api.php?action=query&format=xml&meta=tokens",8888,1,f))
	{
		hclose(f);
		goto TOKEN_NOT_FOUND;
	}
	if(skipresponseheader(f,1))
	{
		hclose(f);
		goto TOKEN_NOT_FOUND;
	}
	while(!heof(f))
	{
		xmlparsetag(f,buf);
		if(!strcmp(buf,"tokens"))
		{
			xmlparsearg(f,1,tkm,tkv);
			flag=1;
			break;
		}
	}
	hclose(f);
	if(flag)
	{
		if(!strcmp(raw_token,"+\\"))
		{
			fprintf(stderr,"Warning! Logout.\n");
			exit(-1);
		}
		AcquireSRWLockExclusive(&rwcs);
		URLEncode(raw_token,strlen(raw_token),token,127);
		if(!hastoken) hastoken=1;
		ReleaseSRWLockExclusive(&rwcs);
		return 0;
	}
TOKEN_NOT_FOUND:
	printf("Token not found.\n");
	return -1;
}
void tokenmanage(void *p)
{
	p=NULL;
	for(;;)
	{
		AcquireSRWLockShared(&rwcs);
		if(!hastoken)
		{
			ReleaseSRWLockShared(&rwcs);
			printf("Change token.\n");
			gettoken();
		}
		else if(hastoken==-1)
		{
			ReleaseSRWLockShared(&rwcs);
			break;
		}
		else ReleaseSRWLockShared(&rwcs);
		Sleep(1);
	}
	return;
}