/* -------------------------------------------------------------------- */
/* SMS Client, send messages to mobile phones and pagers		*/
/*									*/
/* url.c								*/
/*									*/
/*  Copyright (C) 1997,1998,1999 Angelo Masci				*/
/*									*/
/*  This library is free software; you can redistribute it and/or	*/
/*  modify it under the terms of the GNU Library General Public		*/
/*  License as published by the Free Software Foundation; either	*/
/*  version 2 of the License, or (at your option) any later version.	*/
/*									*/
/*  This library is distributed in the hope that it will be useful,	*/
/*  but WITHOUT ANY WARRANTY; without even the implied warranty of	*/
/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU	*/
/*  Library General Public License for more details.			*/
/*									*/
/*  You should have received a copy of the GNU Library General Public	*/
/*  License along with this library; if not, write to the Free		*/
/*  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.	*/
/*									*/
/*  You can contact the author at this e-mail address:			*/
/*									*/
/*  angelo@styx.demon.co.uk						*/
/*									*/
/* -------------------------------------------------------------------- */
/* $Id$
   -------------------------------------------------------------------- */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "url.h"
#include "common/common.h"
#include "logfile/logfile.h"
#include "error.h"

/* -------------------------------------------------------------------- */

#define PARSING_PROTOCOL	 0
#define PARSING_HOST		 1
#define PARSING_PORT		 2
#define PARSING_DIRECTORY	 3
#define PARSING_FILENAME	 4
#define PARSING_COMPLETE	 5
#define PARSING_ERROR		-1
#define PARSING_ALLOC_ERROR	-1

/* -------------------------------------------------------------------- */
/* -------------------------------------------------------------------- */
int parse_url(char *str, URL *url)
{
	char 	*ptr,
		*buf;
	int 	state;
	



	if ((str == NULL) || (*str == '\0'))
	{	return -1;
	}


	buf = (char *)malloc(sizeof(char) * (strlen(str) +1));
	if (buf == NULL)
	{
		lprintf(LOG_ERROR, "malloc() failed\n");
		exit(EMALLOC);
	}


	state = PARSING_PROTOCOL;
	ptr   = str;
	while ((state != PARSING_ERROR) && 
	       (state != PARSING_COMPLETE) &&
	       (state != PARSING_ALLOC_ERROR))

	{
		switch (state)
		{
			case PARSING_PROTOCOL:		/* Gobble 'http://' */
			{
				if (strncasecmp(ptr, "http://", strlen("http://")) == 0)
				{
					ptr  += strlen("http://");
					state = PARSING_HOST;
				}
				else
				{	state = PARSING_ERROR;
				}

				break;
			}
			case PARSING_HOST:			/* Gobble 'host' */
			{
				char 	*host_ptr;


				host_ptr = buf;
				while ((*host_ptr = *ptr))
				{
					if (*ptr == '/')
					{	
						state = PARSING_DIRECTORY;

						url->port = strdup("80");
						if (url->port == NULL)
						{	state = PARSING_ALLOC_ERROR;
						}

						break;
					}
					else
					if (*ptr == ':')
					{	
						state = PARSING_PORT;
						ptr++;
						break;
					}

					host_ptr++;
					ptr++;
				}

				*host_ptr = '\0';

				if (strlen(buf) == 0)
				{	state = PARSING_ERROR;
				}

				url->host = strdup(buf);
				if (url->host == NULL)
				{	state = PARSING_ALLOC_ERROR;
				}

				break;
			}
			case PARSING_PORT:			/* Gobble 'port' */
			{
				char 	*port_ptr;


				port_ptr = buf;
				while ((*port_ptr = *ptr))
				{
					if (*ptr == '/')
					{	
						state = PARSING_DIRECTORY;
						break;
					}

					port_ptr++;
					ptr++;
				}

				*port_ptr = '\0';

				if (strlen(buf) == 0)
				{	state = PARSING_ERROR;
				}

				url->port = strdup(buf);
				if (url->port == NULL)
				{	state = PARSING_ALLOC_ERROR;
				}

				break;
			}
			case PARSING_DIRECTORY:			/* Gobble 'directory' */
			{
				char 	*last_seperator,
					*last_directory,
					*directory_ptr;


				last_seperator = NULL;
				last_directory = NULL;
				directory_ptr  = buf;

				if (*ptr == '/')
				{
					while ((*directory_ptr = *ptr))
					{
						if (*ptr == '/')
						{	last_seperator = directory_ptr;
							last_directory = ptr;
						}

						directory_ptr++;
						ptr++;
					}

					*directory_ptr  = '\0';

					if (last_seperator == NULL)
					{	state = PARSING_ERROR;
					}
					else
					{	*last_seperator = '\0';

						if (strlen(buf) == 0)
						{	strcpy(buf, "/");
						}


						url->directory = strdup(buf);
						if (url->directory == NULL)
						{	state = PARSING_ALLOC_ERROR;
						}

						ptr = last_directory+1;
						state = PARSING_FILENAME;
					}
				}
				else
				{	state = PARSING_ERROR;
				}
			
				break;
			}
			case PARSING_FILENAME:			/* Gobble 'filename' */
			{
				char 	*filename_ptr;


				filename_ptr = buf;
				while ((*filename_ptr = *ptr))
				{
					filename_ptr++;
					ptr++;
				}

				*filename_ptr = '\0';

				url->filename = strdup(buf);
				if (url->filename == NULL)
				{	state = PARSING_ALLOC_ERROR;
				}

				state = PARSING_COMPLETE;
				break;

			}
			default:		/* Failure */
			{
				;
			}
		}
	}


	if (state == PARSING_COMPLETE)
	{
		strcpy(buf, url->directory);
		if (buf[strlen(buf) -1] != '/')
		{	strcat(buf, "/");
		}

		strcat(buf, url->filename);

		url->document = strdup(buf);
		if (url->document == NULL)
		{
			state = PARSING_ALLOC_ERROR;
		}
		else
		{	if (buf != NULL)
			{	free(buf);
			}

			return 0;
		}
	}


	if (buf != NULL)
	{	free(buf);
	}

	if (url->host != NULL)
	{	free(url->host);
	}

	if (url->port != NULL)
	{	free(url->port);
	}

	if (url->document != NULL)
	{	free(url->document);
	}

	if (url->directory != NULL)
	{	free(url->directory);
	}

	if (url->filename != NULL)
	{	free(url->filename);
	}

	return -1;
}


/* -------------------------------------------------------------------- */
/* -------------------------------------------------------------------- */
void free_url(URL *url)
{
	if (url->host != NULL)
	{	free(url->host);
	}

	if (url->port != NULL)
	{	free(url->port);
	}

	if (url->document != NULL)
	{	free(url->document);
	}

	if (url->directory != NULL)
	{	free(url->directory);
	}

	if (url->filename != NULL)
	{	free(url->filename);
	}
}
