/*      Get and Resume Elite EDition source code


Get and Resume Elite EDition (GREED)
Copyright (C) 1999  Anoakie Turner

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program 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 General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

For more information on the GPL, please go to:
http://www.gnu.org/copyleft/gpl.html


        Contact:  Anoakie Turner
                  Anoakie.Turner@asu.edu

                  13240 N. 94th Pl.
                  Scottsdale, AZ 85260
*/

#include "main.h"
#ifdef __riscos__
#include "riscos.h"
#endif /* __riscos__ */


bool ReadHTTPHeader(URLp URL)
/*************************************
**	bool ReadHTTPHeader(URLp URL)
**
**	URL->protcol == HTTP, HTTP header read.
**
** Pre:  Assigned(URL->size) && Assigned(URL->filename) && Assigned(URL->sockfd)
** Post: URL->fp, URL->lsize, URL->left, and URL->lleft set. Returns 1
**	 if successful
*************************************/
{	int bsize = 0;
	char *temp, *fin, *statusptr;
	char buffer[4096];
	char code[5];
	int i;
#ifdef __riscos__
        char *ext;
#endif /* __riscos__ */
	URL->done = 0;
	URL->size = malloc(15);

#ifdef __riscos__
        if (!riscos_style)
            temp = __riscosify(URL->filename, 0, __RISCOSIFY_DONT_TRUNCATE,
                               buffer, sizeof(buffer), NULL);
        else
            temp = gs_trans(URL->filename, buffer, sizeof(buffer));
        if (!temp) {
            printf("Error during filename conversion!\n");
            exit (100);
        }
        free(URL->filename);
        URL->filename = malloc(strlen(buffer)+1);
        strcpy(URL->filename, buffer);
        if (!riscos_style)
	    ext = strrchr(URL->filename, '/');
	else
            ext = strrchr(URL->name, '.');
        if (ext)
            filetype = mimemap_translate_ext2type(ext+1);
        else
            filetype = 0xfaf;
#endif /* __riscos__ */
	URL->fp = fopen (URL->filename, "a+b");
        if (URL->fp == NULL)
        {       printf("Error opening file!\n");
                exit(69);
        }

	fseek (URL->fp,0,SEEK_END);
	URL->lsize = ftell(URL->fp);

	if (URL->lsize >=ROLLBACK)
		URL->lsize -= ROLLBACK;
	else
		URL->lsize = 0;

/*	if ((URL->lsize >= URL->ltotal) && URL->ltotal != 0)
	{	if (OUTPUT_LEVEL > 0)
			printf("Error... File already downloaded!\n");
		URL->retry = 0;
		return(0);
	} else
*/
	if (URL->fp == NULL)
	{	if (OUTPUT_LEVEL > 0)
#ifdef USE_GTK
			fprintf(out, "%d:mb:Error#Error opening file %s!\n",
				URL->pid, URL->filename);
#else
			printf("Error opening file %s!\n", URL->filename);
#endif
		URL->retry = 0;
		return(0);
	} else
	if (URL->lsize == -1)
		URL->lsize = 0;
	sprintf(URL->size, "%ld", URL->lsize);
	write(URL->sockfd, URL->size, strlen(URL->size));
	write(URL->sockfd, "-\r\n\r\n", 5);

	dldots = URL->lsize / ROLLBACK;

	bsize = 0;
/*	while(strstr(buffer, "\r\n\r\n") == NULL &&
		strstr(buffer, "ength: ") == NULL)
*/		bsize = read(URL->sockfd, buffer + bsize, 4096);

	if (OUTPUT_LEVEL > 8)
		printf("\n\n%s\n\n",buffer);

	temp = strstr (buffer, "ength: ");

	if (temp != NULL && strstr(temp,"\r\n\r\n") != NULL)
		fin = strstr(temp,"\r\n\r\n");
	else
	{	if (strstr(buffer, "HTTP/1.0") != NULL)
		{	fin = strstr(buffer, "\n\n");
			if (OUTPUT_LEVEL > 2)
#ifdef USE_GTK
				fprintf(out, "%d:lb:Server wants to use HTTP/1.0...\n",
						URL->pid);
#else
				printf("Server wants to use HTTP/1.0...\n");
#endif
			URL->protocol = 10;
			if (fin == NULL)
				fin = strstr(buffer,"\r\n\r\n");
		}
		else
			fin = strstr(buffer,"\r\n\r\n");
	}

	if (fin == NULL)
	{	if (OUTPUT_LEVEL > 0)
#ifdef USE_GTK
			fprintf(out, "%d:mb:Error#Error - Webserver header too large OR server busy!\n",
				URL->pid);
#else
			printf("Error - Webserver header too large OR server busy!\n");
#endif
		URL->retry = 0;
		return(0);
	}

	*fin='\0'; fin+=4;

	if (strstr(buffer,"Transfer-Encoding: chunked"))
		if (OUTPUT_LEVEL > 0)
#ifdef USE_GTK
			fprintf(out, "%d:lb:Error - \"chunked\" Transfer-Encoding not HTTP/1.1 compliant!\n",
					URL->pid);
#else
			printf("Error - \"chunked\" Transfer-Encoding not HTTP/1.1 compliant!\n");
#endif
/*	if (URL->lsize)
	{	if (OUTPUT_LEVEL > 0)
			printf("Error - Server says file already retrieved!\n");
		URL->retry = 0;
		return(0);
	} else
*/

	if (URL->protocol == 10)
	{	URL->protocol = HTTP;
		statusptr = strstr(buffer,"HTTP/1.0 ");
		fin-=2;
	} else
		statusptr = strstr(buffer,"HTTP/1.1 ");

	if (statusptr != NULL)
		for(i = 0; i < 4 && isdigit(statusptr[i + 9]); i++)
			code[i] = statusptr[i + 9];
	else
		i = 0;

	code[i] = '\0';

	switch(atoi(code))
	{	case 100:
		case 101:
		case 200:
		case 202:
		case 203:
			break;
		case 204:
			if (OUTPUT_LEVEL > 0)
				printf("No Content!!!\n");
			URL->retry = 0;
			return(0);
			break;
		case 205:
		case 206:
			break;
		case 300:
		case 301:
		case 302:
		case 303:
		case 304:
		case 305:
			if (strstr(buffer, "ocation:") != NULL)
			{	URL->name = ReadString2(strstr(buffer, "ocation:") + 9, '\r');
				if (Parse(URL))
				{	if(OUTPUT_LEVEL > 0)
						printf("URL points to %s... Will Retry...\n", URL->name);
					URL->retry = 1;
				} else
				{	if(OUTPUT_LEVEL > 0)
						printf("URL points to %s, but it's not valid :(\n", URL->name);
					URL->retry = 0;
				}
				return(0);
			}
		    	break;
		case 400:
		case 401:
		case 402:
		case 403:
		case 404:
		case 405:
		case 406:
		case 407:
		case 408:
		case 409:
		case 410:
		case 411:
		case 412:
		case 413:
		case 414:
		case 415:
			if (OUTPUT_LEVEL > 0)
				printf("Got a %s, skipping file!", code);
			URL->retry = 0;
			return(0);
			break;
		case 500:
			URL->retry = 1;
			if (OUTPUT_LEVEL > 0)
				printf("Error - Server busy!\n");
			return(0);
			break;
		case 501:
		case 502:
		case 503:
		case 504:
		case 505:
			URL->retry = 0;
			if (OUTPUT_LEVEL > 0)
				printf("Error, server returned [%s]!\n", code);
			return(0);
			break;
		default:
			if (OUTPUT_LEVEL > 0)
				printf("Server Code [%s] unrecognized!\n", code);
			break;
	}

/*	if (strstr(buffer, "tion: close") != NULL)
	{	URL->retry = 1;
		if (OUTPUT_LEVEL > 0)
			printf("Error - Server busy!\n");
		return(0);
	}
*/
	if (strstr(buffer,"ange") == NULL)
	{	if (URL->lsize != 0)
		{	fclose(URL->fp);
			URL->fp = fopen (URL->filename, "r+b");
			fseek (URL->fp,0,SEEK_SET);
			URL->lsize = 0;
			dldots = 0;
			ftruncate(fileno(URL->fp), 0);
		}
		if (OUTPUT_LEVEL > 0)
			printf("Non Fatal Error - Cannot resume!\n");
	} else
	{	if (OUTPUT_LEVEL > 1)
			printf("# File: %s\n",URL->filename);
		ftruncate(fileno(URL->fp), URL->lsize);
	}

	if (temp != NULL)
	{	for (i = 0; temp[i + 7] != '\r'; i++);
		URL->left = malloc(i);
		for (i = 0; temp[i + 7] != '\r'; i++)
			URL->left[i] = temp[i + 7];
		URL->left [i] = '\0';
		URL->lleft = atol(URL->left);
		if (URL->lsize == URL->lleft || URL->lleft < 2)
		{	if (OUTPUT_LEVEL > 0)
				printf("Error, file already downloaded!\n");
			URL->retry = 0;
			return 0;
		}
		URL->ltotal = URL->lleft + URL->lsize;
		if (OUTPUT_LEVEL > 1)
			printf("# File size: %ld kbytes (%ld bytes)\n", (long int)((URL->ltotal)/1024+.5), URL->ltotal);

		URL->resume = 1;
		URL->lleft -= (bsize-(fin-buffer));
	} else
	{	if (OUTPUT_LEVEL > 0)
			printf("Error in web site file size estimation, or unknown server type!\n\n");
		URL->resume = 0;
		URL->lleft = 2000000000;
		NOSIZE = 1;
	}

	if (OUTPUT_LEVEL > 0)
		printf("# Found %ld kbytes : resuming from byte %ld.\n\n", URL->lsize/1024, URL->lsize);

	if (STDOUT == 1)
	{	buffer[bsize + 1] = '\0';
		printf("%s", buffer);
	} else
	fwrite(fin,bsize-(fin-buffer),1,URL->fp);

	if (OUTPUT_LEVEL > 1 && STDOUT == 0)
		printf("[.");
	fflush(NULL);

	return 1;
}
