// who-auth für unix/linux. 25.05.2002
// Thomas Schreiner
// Kontaktdetails: http://www.tschreiner.org/

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h> /* close */

#include "base64.c"

#define SERVER_PORT 80

#define MAX_MSG 100
#define ERROR   1
#define END_LINE 0x0A


int main (int argc, char *argv[])
{

	int sd, rc, i, debug = 0;
	struct sockaddr_in localAddr, servAddr;
	struct hostent *h;
	char code[100] = "GET / HTTP/1.1\r\nAuthorization: Basic ";
	char host[100] = "www.eoad.de";
	char userpass[50];

	char line[MAX_MSG];
	FILE* config;

	config = fopen (".who-auth.config", "r");
	if (config == NULL)
	{
		config = fopen (".who-auth.config", "a+");

		printf ("Please enter account data, (syntax: username:password): ");
		fgets (userpass, 50, stdin);
		fputs (userpass, config);
		fclose (config);
	}
	else fgets (userpass, 50, config);

	strcat (code, base64Encode (userpass, strlen (userpass)));
	strcat (code, "\r\nHost: www.eoad.de\r\n\r\n");

	if (argc > 1)
	{
		if (!strcmp (argv[1], "-d")) debug = 1;
	}
	
	h = gethostbyname(host);

	if(h==NULL)
	{
		printf("%s: unknown host '%s'\n",argv[0],host);
		exit(1);
	}

	while (1)
	{
	servAddr.sin_family = h->h_addrtype;
	memcpy((char *) &servAddr.sin_addr.s_addr, h->h_addr_list[0], h->h_length);
	servAddr.sin_port = htons(SERVER_PORT);

	/* create socket */

	sd = socket(AF_INET, SOCK_STREAM, 0);
	if(sd < 0)
	{
		perror("cannot open socket ");
		exit(1);
	}

	/* bind any port number */
	localAddr.sin_family = AF_INET;
	localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
	localAddr.sin_port = htons(0);

	rc = bind(sd, (struct sockaddr *) &localAddr, sizeof(localAddr));
	if(rc < 0)
	{
		printf("%s: cannot bind port TCP %u\n", argv[0], SERVER_PORT);
		perror("error ");
		exit(1);
	}

	/* connect to server */
	rc = connect(sd, (struct sockaddr *) &servAddr, sizeof(servAddr));

	if (rc < 0)
	{
		perror("cannot connect ");
		exit(1);
	}

	rc = send(sd, code, strlen(code), 0);

	if (rc < 0)
	{
		perror("cannot send data ");
		close(sd);
		exit(1);
	}
	else
	{
		if (debug) printf ("sent: %s\n", code);
	}

	memset(line, 0x0, MAX_MSG);
	rc = read_line (sd, line);

	if (rc == ERROR)
	{
		printf ("Error reading from socket!");
		exit (1);
	}

	if (debug) printf ("received: %s\n", line);

	if (strcmp (line, "HTTP/1.1 401 Unauthorized\r\n"))
		printf ("Authorization successful.\n");
	else
	{
		printf ("Authorization failed. Wrong password string in .who-auth.config?\n");
		exit (1);
	}
	
	while (read_line(sd, line) != ERROR)
		if (debug) printf ("%s", line);
	close (sd);
	sleep (10);
	}
	
	return 0;
}



///////////////////////////////////////
//             read_line             //
///////////////////////////////////////


int read_line(int newSd, char *line_to_return)
{
	static int rcv_ptr=0;
	static char rcv_msg[MAX_MSG];
	static int n;
	int offset;

	offset=0;

	while(1)
	{
		if(rcv_ptr==0)
		{
			/* read data from socket */
			memset(rcv_msg,0x0,MAX_MSG); /* init buffer */
			n = recv(newSd, rcv_msg, MAX_MSG, 0); /* wait for data */
			if (n<0)
			{
				perror(" cannot receive data ");
				return ERROR;
			}
			else if (n==0)
			{
				printf(" connection closed by client\n");
				close(newSd);
				return ERROR;
			}
		}

		/* if new data read on socket */
		/* OR */
		/* if another line is still in buffer */

		/* copy line into 'line_to_return' */
		while(*(rcv_msg+rcv_ptr)!=END_LINE && rcv_ptr<n)
		{
			memcpy(line_to_return+offset,rcv_msg+rcv_ptr,1);
			offset++;
			rcv_ptr++;
		}

		/* end of line + end of buffer => return line */
		if(rcv_ptr==n-1)
		{
			/* set last byte to END_LINE */
			*(line_to_return+offset)=END_LINE;
			rcv_ptr=0;
			return ++offset;
		}

		/* end of line but still some data in buffer => return line */
		if(rcv_ptr <n-1)
		{
			/* set last byte to END_LINE */
			*(line_to_return+offset)=END_LINE;
			rcv_ptr++;
			return ++offset;
		}

		/* end of buffer but line is not ended => */
		/*  wait for more data to arrive on socket */
		if(rcv_ptr == n)
		{
			rcv_ptr = 0;
		}
	} /* while */
}

