// Http.c : Defines the entry point for the DLL application.
// Sébastien Métrot et Sylvain Huet - avril 99
//
// Modification History
//
//$ LB (17/07/2001) : add SCINETIsConnected and INETIsConnected functions
//
//$ LB (23/08/2001) : implements proxy http authentication in INETGetUrlEx


#include <windows.h>
#include <wininet.h>
#include <winreg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <io.h>
#include <direct.h>

#include "common/kernel.h"
#include "mainscol.h"
#include "OS_specific/windows/winscol.h"
#include "scolMacros.h"
//$ LB (24/08/2001) : add proxy http management
#include "common/proxyhttp.h"
#include "OS_specific/windows/http.h"

HINTERNET session=0;
int WM_HTTP;
int HTTPobj;




//cbmachine ww;                

//$ LB (24/08/2001) : transfert type declaration now in http.h

//$LB (06/10/2003) : correction added





/*************************************************************************************************************/
/*                                                                                                           */
/*      C O N T E N T                                                                                        */
/*                                                                                                           */
/*                                                                                                           */
/*                                                                                                           */
/*    TRANSFERT TAB MANAGEMENT                                                                               */
/*                                                                                                           */
/* void HTTPtransfert_Add (transfert* t)                                                                     */
/*                                                                                                           */
/* transfert* HTTPtransfert_Extract (DWORD threadid)                                                         */
/*                                                                                                           */
/*                                                                                                           */
/*                                                                                                           */
/*    BODY                                                                                                   */
/*                                                                                                           */
/* int HTTPdestroy (mmachine m,int handsys,int objm)                                                         */
/*                                                                                                           */
/* int GetData (mmachine m,transfert*t,int size)                                                             */
/*                                                                                                           */
/* int HTTPEvent(mmachine m,HWND hwnd, unsigned msg,UINT wParam,LONG lParam,int *ret)                        */
/*                                                                                                           */
/* DWORD HTTPThreadQueryData (transfert* t)                                                                  */
/*                                                                                                           */
/* DWORD HTTPThreadSetOptions (transfert* t)                                                                 */
/*                                                                                                           */
/* DWORD HTTPThreadAuthorization (DWORD threadid, int processState)                                          */
/*                                                                                                           */
/* char* findslash(char *dst,char *src)                                                                      */
/*                                                                                                           */
/* DWORD WINAPI HTTPThread(LPVOID p)                                                                         */
/*                                                                                                           */
/* int INETdumpURL (mmachine m)                                                                              */
/*                                                                                                           */
/* int INETStopURL (mmachine m)                                                                              */
/*                                                                                                           */
/* int iniSessionUrl()                                                                                       */
/*                                                                                                           */
/* DWORD WINAPI HTTPThreadEasy(LPVOID p)                                                                     */
/*                                                                                                           */
/* int INETGetURL (mmachine m)                                                                               */
/*                                                                                                           */
/* int INETGetURLengine (mmachine m, int nbArgs,                                                             */
/*                       int mchn, int mverb, int murl, int mheaderAdds, int mopt, int mflag)                */
/*                                                                                                           */
/* int INETGetURLex2 (mmachine m)                                                                            */
/*                                                                                                           */
/* int INETGetURLex (mmachine m)                                                                             */
/*                                                                                                           */
/* int INETdisableProxy(mmachine m)                                                                          */
/*                                                                                                           */
/*                                                                                                           */
/*************************************************************************************************************/










/****************************************************************************************************************/
/*                                                                                                              */
/*      T R A N S F E R T    T A B      M A N A G E M E N T                                                     */
/*                                                                                                              */
/****************************************************************************************************************/


transfert*** transfertTab;    // dyn. tab of transfert struct pointers
int transfertTabSize = 0;     // dyn. size of tab
int transfertTabLock = 0;



/**************************************************/
/* scol v 4                                       */
/*                                                */
/* void HTTPtransfert_Add (transfert* t)          */
/*                                                */
/* add a transfert struct to the tab.             */
/* deals with proxy authentication.               */
/*                                                */
/**************************************************/
void HTTPtransfert_Add (transfert* t)
{
	// wait for another thread to free the access
	while (transfertTabLock)
		Sleep (100);

	// lock the access
	transfertTabLock = 1;

	// create a new element
	if (transfertTabSize == 0)
		transfertTab = (transfert***) malloc (sizeof (transfert**));
	else 
		transfertTab = (transfert***) realloc (transfertTab, (transfertTabSize + 1) * sizeof(transfert**));
	transfertTab[transfertTabSize] = (transfert**) malloc (sizeof(transfert*));

	// store the transfert struct
	*(transfertTab[transfertTabSize]) = t;
	transfertTabSize++;

	// free access
	transfertTabLock = 0;
}





/*****************************************************/
/* scol v 4                                          */
/*                                                   */
/* transfert* HTTPtransfert_Extract (DWORD threadid) */
/*                                                   */
/* extract a transfert struct from the tab, by the   */
/* ID of the thread in which the transfert struct is */
/* managed.                                          */
/* deals with proxy authentication.                  */
/*                                                   */
/*****************************************************/
transfert* HTTPtransfert_Extract (DWORD threadid)
{
int i,j;
transfert* t;

	// wait for another thread to free the access
	while (transfertTabLock)
		Sleep(100);

	// lock access
	transfertTabLock = 1;

	// search for the expected element
	for (i=0; i < transfertTabSize; i++)
	{
		t = *(transfertTab [i]);

		// this is it!
		if (t->threadid == threadid)
		{
			transfertTabSize--;

			// shift the elements
			for (j=i; j < transfertTabSize; j++)
				*(transfertTab[j]) = *(transfertTab[j+1]);
			if (transfertTab[transfertTabSize]) free (transfertTab[transfertTabSize]);
			if ((transfertTabSize == 0) && (transfertTab)) free (transfertTab);

			// free access and return the element
			transfertTabLock = 0;
			return t;
		}
	}

	// no element found by this thread id
	transfertTabLock = 0;
	return NULL;
}











/****************************************************************************************************************/
/*                                                                                                              */
/*      B O D Y                                                                                                 */
/*                                                                                                              */
/****************************************************************************************************************/




/********************************************************/
/*                                                      */
/* int HTTPdestroy (mmachine m,int handsys,int objm)    */
/*                                                      */
/********************************************************/
int HTTPdestroy (mmachine m,int handsys,int objm)
{
	transfert*t=(transfert*)handsys;

	if (!t)	return 0;

	if (!t->handle)	return 0;
//	MMechostr(1,"kill HTTP %x %x\n",t,t->handle);

	if (t->dead)
	{
		*(t->dead)=1;
		t->dead=NULL;
	}
	if (t->handle)
	{
		InternetCloseHandle(t->handle);
		t->handle=NULL;
	}
	if (t->handlebis)
	{
		InternetCloseHandle(t->handlebis);
		t->handlebis=NULL;
	}

	if (t->thread)
	{
		MMechostr(1,"kill HTTP thread\n");
		TerminateThread(t->thread,0);
		MMechostr(1,"kill HTTP thread Ok\n");
		t->thread=NULL;
	}

	if (t->opt)
	{
		free(t->opt);
		t->opt=NULL;
	}
	if (t->url)
	{
		free(t->url);
		t->url=NULL;
	}
	free(t);
	return 0;
}










/********************************************************/
/*                                                      */
/* int GetData (mmachine m,transfert*t,int size)        */
/*                                                      */
/********************************************************/
int GetData (mmachine m,transfert*t,int size)
{
	DWORD dwDownloaded;
	int s;
	char *c;

//	MMechostr(MSKDEBUG,">>>GetData %d %x\n",size,t);
	s=MMmalloc(m,(size>>2)+2,TYPEBUF);
	if (s==NIL) return MERRMEM;
						
	dwDownloaded=0;
	c=MMstartstr(m,s);
	if(!InternetReadFile(t->handle,(LPVOID)c,size,&dwDownloaded))
	{
		MMechostr(MSKDEBUG,">>>HTTP error on read\n");
		return -1;
	}
	c[size]=0;
	MMsetsizestr(m,s,size);
	MMpush(m,s+s+1);
	return 0;
}







/********************************************************/
/*                                                      */
/* int HTTPEvent                                        */
/*                                                      */
/********************************************************/
int HTTPEvent(mmachine m,HWND hwnd, unsigned msg,UINT wParam,LONG lParam,int *ret)
{
	transfert * t=(transfert*)lParam;
	int k=0;
	
//	MMechostr(MSKDEBUG,"HTTPEvent %x %d\n",t,wParam);

	
	k=OBJbeginreflex(m,HTTPobj,lParam,0);
	if (k==0)
	{
		if (wParam<0)
		{
			if (MMpush(m,NIL)) return MERRMEM;
			if (MMpush(m, (wParam<<1))) return MERRMEM;
			OBJdelTH(m,HTTPobj,lParam);
		}
		else if (wParam==0)
		{
			if (MMpush(m,NIL)) return MERRMEM;
			if (MMpush(m,2)) return MERRMEM; // 1<<1 <=> 2
			OBJdelTH(m,HTTPobj,lParam);
		}
		else
		{
			if (GetData(m,t,wParam))
			{
				if (MMpush(m,NIL)) return MERRMEM;
				if (MMpush(m,(-1<<1))) return MERRMEM;
				OBJdelTH(m,HTTPobj,lParam);
			}
			else
			{
				if (MMpush(m,0)) return MERRMEM;
//			MMechostr(MSKDEBUG,">>>HTTP free wait %x\n",t);
				t->wait=FALSE;
			}
		}

		if (k=OBJcallreflex(m,2)) return k;
		return 0;
	}
	else
	{

		MMechostr(MSKDEBUG,"HTTP : No reflex ...\n");
	}

	return 0;
}















/********************************************************/
/* scol v 4                                             */
/*                                                      */
/* DWORD HTTPThreadQueryData (transfert* t)             */
/*                                                      */
/* determines the amount of data available to download. */
/*                                                      */
/********************************************************/
DWORD HTTPThreadQueryData (transfert* t)
{
int result;
unsigned long size=-1;


	while (1)
	{
		// The call to InternetQueryDataAvailable determines the amount of 
		// data available to download.
//		MMechostr(MSKDEBUG,">>>query data %x\n",t);
		result = InternetQueryDataAvailable(t->handle, &size, 0, 0);
		if (*(t->dead)){free(t->dead);return 1;}
		if (!result)
		{
			MMechostr(MSKDEBUG,"Error : data failed %d  %x\n",GetLastError(),GetLastError());
			free(t->dead);
			t->dead=NULL;
			PostMessage(hscol,WM_HTTP,-1,(DWORD)t);
			return 1;
		}
		else
		{
//		MMechostr(MSKDEBUG,">>>res query data %x ->%d \n",t,size);
			if (size)
			{
				t->wait=TRUE;
				PostMessage(hscol,WM_HTTP,size,(DWORD)t);
				while (t->wait);
			}
			else
			{
				free(t->dead);
				t->dead=NULL;
				PostMessage(hscol,WM_HTTP,0,(DWORD)t);
				return 1;
			}
		}
	}
}






/****************************************************************/
/* scol v 4                                                     */
/*                                                              */
/* DWORD HTTPThreadSetOptions (transfert* t)                    */
/*                                                              */
/* set proxy authentication infos in wininet lib and            */
/* resend the request.                                          */
/*                                                              */
/****************************************************************/
DWORD HTTPThreadSetOptions (transfert* t)
{
char* uname = PROXYHTTP_GetUname();
char* pword = PROXYHTTP_GetPword();
int i;
DWORD dwStatus;
DWORD dwStatusSize = sizeof(dwStatus);
int headerAddsSize;


	// set the username and password
	InternetSetOption (t->handle, INTERNET_OPTION_USERNAME, uname, strlen(uname)+1);
	InternetSetOption (t->handle, INTERNET_OPTION_PASSWORD, pword, strlen(pword)+1);

	if (t->headerAdds) headerAddsSize = strlen (t->headerAdds);
	else headerAddsSize = 0;

	// re-send the request
	i = HttpSendRequest(t->handle, t->headerAdds, headerAddsSize, t->opt, t->sizeopt);

	if (*(t->dead)) {free(t->dead); return 1;}

	if (!i)
	{
		MMechostr(MSKDEBUG,"Error : HttpSendRequest failed on %s (%d)\n",t->url,GetLastError());
		PostMessage(hscol, WM_HTTP, -2, (DWORD)t);
		free(t->dead);
		t->dead = NULL;
		return 1;
	}

	// check errors
	HttpQueryInfo (t->handle, HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_STATUS_CODE, &dwStatus, &dwStatusSize, NULL);

	// authentication infos rejected
	if (dwStatus == HTTP_STATUS_PROXY_AUTH_REQ)
	{
		HTTPtransfert_Add (t);
		PROXYHTTP_AskAuthInfos (t->m, PROXYHTTP_WININET_NETWORK_API, (int)t->threadid, PROXYHTTP_FORCED_MODE);
		SuspendThread(t->thread);
		if (PROXYHTTP_IsAuthorized())
			return HTTPThreadSetOptions (t);

		// get data
		return HTTPThreadQueryData (t);

	}

	// get data
	return HTTPThreadQueryData (t);
}






/********************************************************************/
/* scol v 4                                                         */
/*                                                                  */
/* DWORD HTTPThreadAuthorization (DWORD threadid, int processState) */
/*                                                                  */
/* check if the user gave the authentication infos. If he did so,   */
/* call HTTPThreadSetOptions to resend the request. If he didn't,   */
/* the request is rejected.                                         */
/*                                                                  */
/********************************************************************/
DWORD HTTPThreadAuthorization (DWORD threadid, int processState)
{
transfert* t;

	// get the transfert struct from threadid
	t = HTTPtransfert_Extract (threadid);

	if (!t)
	{
		MMechostr (MSKDEBUG, "HTTPThreadAuthorization ERROR : no transfert struct is corresponding to the thread ID %d\n", threadid);
		return 1;
	}

	
	// wake up the thread in order to authenticate
	if (ResumeThread (t->thread) == -1)
	{
	LPVOID lpMsgBuf;

		FormatMessage( 
			FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
			NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL);
		MMechostr (MSKDEBUG, "HTTPThreadAuthorization ERROR : ResumeThread threadid %d : GetLastError : %s\n", t->threadid, (LPCTSTR)lpMsgBuf);

		LocalFree( lpMsgBuf );
	}

	return 0;
}










/********************************************************/
/*                                                      */
/* char* findslash(char *dst,char *src)                 */
/*                                                      */
/********************************************************/
char* findslash(char *dst,char *src)
{
	while(*src)
	{
		if ((*src)=='/')
		{
			*dst=0;
			return src;
		}
		*(dst++)=*(src++);
	}
	*src='/';
	src[1]=0;
	*dst=0;
	return src;
}










int cutaddr(char *addr, char *buf);


/***********************************************************/
/*                                                         */
/* DWORD WINAPI HTTPThread(LPVOID p)                       */
/*                                                         */
/* thread callback to manage INETGetURLex and ex2 requests */
/*                                                         */
/***********************************************************/
DWORD WINAPI HTTPThread(LPVOID p)
{
	transfert * t=(transfert*)p;
	int flag,serv;
	char bufname[128];
    char buf[256];
	char *doc;
	char* bufaccept[2];
	int port,defport;
	char *verb;
	HINTERNET k;
	int i;
	int *dead;
	char* header;
	char* pragmaHeader = "Pragma: no-cache\n";


	dead=(int*)malloc(sizeof(int));
	*dead=0;
	t->dead=dead;


	flag=INTERNET_FLAG_RELOAD;
	
	if (!strnicmp(t->url,"http://",7))
	{
		doc=findslash(bufname,t->url+7);
		serv=INTERNET_SERVICE_HTTP;
		defport=INTERNET_DEFAULT_HTTP_PORT;
	}
	else if (!strnicmp(t->url,"https://",8))
	{
		doc=findslash(bufname,t->url+8);
		serv=INTERNET_SERVICE_HTTP;
		defport=INTERNET_DEFAULT_HTTPS_PORT;
	}
	else
	{
		MMechostr(MSKDEBUG,"Bad adress %s\n",t->url);

		//$LB (06/10/2003)
		/*
		PostMessage(hscol,WM_HTTP,-2,(DWORD)t);
		free(dead);
		t->dead=NULL;
		*/
		free(dead);
        t->dead=NULL;
        PostMessage(hscol,WM_HTTP,-2,(DWORD)t);
		//


		return 1;
	}

	port=cutaddr(bufname,buf);
	if (port==-1)
	{
		port=defport;
	}
	
	bufaccept[0]="*/*";
	bufaccept[1]=NULL;

//	MMechostr(MSKDEBUG,">>> HttpSendRequest %s %s %d %s %d\n",t->url,buf,port,doc,t->sizeopt);

	k=InternetConnect(session,buf,(unsigned short)port,NULL,NULL,(unsigned long)serv,0,0);

	if (*dead){free(dead);return 1;}
	t->handlebis=k;
	if (!t->handlebis) 
	{
		MMechostr(MSKDEBUG,"Error : InternetConnect failed on %s (%d)\n",t->url,GetLastError());
		//$LB (06/10/2003)
		/*
		PostMessage(hscol,WM_HTTP,-2,(DWORD)t);
		free(dead);
		t->dead=NULL;
		*/
		free(dead);
        t->dead=NULL;
        PostMessage(hscol,WM_HTTP,-2,(DWORD)t);
		//
		return 1;
	}



	//$ LB (24/08/2001) : add KEEP_CONNECTION flag in order to manage authentication
	flag=INTERNET_FLAG_RELOAD|INTERNET_FLAG_KEEP_CONNECTION;

	verb=NULL;
	if (t->verb[0]) verb=t->verb;


	k=HttpOpenRequest(t->handlebis,verb,doc,NULL,NULL,bufaccept,flag,0);

	if (*dead){free(dead);return 1;}
	t->handle=k;
	if (!t->handle) 
	{
		MMechostr(MSKDEBUG,"Error : HttpOpenRequest failed on %s (%d)\n",t->url,GetLastError());
		//$LB (06/10/2003)
		/*
		PostMessage(hscol,WM_HTTP,-2,(DWORD)t);
		free(dead);
		t->dead=NULL;
		*/
		free(dead);
        t->dead=NULL;
        PostMessage(hscol,WM_HTTP,-2,(DWORD)t);
		//
		return 1;
	}
//	MMechostr(MSKDEBUG,"createhttp %x t->handle=%x url=%s\n",t,t->handle,t->url);


	//$ LB (24/08/2001) : add proxy http authentication check
	if (PROXYHTTP_IsAuthorized ())
		return HTTPThreadSetOptions (t);

	if (t->headerAdds)
	{
		header = (char*) malloc ((strlen (pragmaHeader) + strlen (t->headerAdds) + 1) * sizeof(char));
		sprintf (header, "%s%s", t->headerAdds, pragmaHeader);
	}
	else
	{
		header = (char*) malloc ((strlen (pragmaHeader) + 1) * sizeof(char));
		sprintf (header, "%s", pragmaHeader);
	}

	i=HttpSendRequest(t->handle, header, strlen (header), t->opt, t->sizeopt);

	if (*dead){free(dead); if (header) free (header); return 1;}

	if (!i)
	{
		MMechostr(MSKDEBUG,"Error : HttpSendRequest failed on %s (%d)\n",t->url,GetLastError());
		//$LB (06/10/2003)
		/*
		PostMessage(hscol,WM_HTTP,-2,(DWORD)t);
		free(dead);
		t->dead=NULL;
		*/
		free(dead);
        t->dead=NULL;
        PostMessage(hscol,WM_HTTP,-2,(DWORD)t);
		//
		if (header) free (header);
		return 1;
	}

	if (header) free (header);

	//$ LB (24/08/2001) : check if authentication is needed
	if (PROXYHTTP_WININET_IsAuthenticated (t->handle))
	{
		// authentication has already been given
		if (PROXYHTTP_IsAuthorized())
			return HTTPThreadSetOptions (t);

		// ask for authentication
		else 
		{
			// store the struct
			HTTPtransfert_Add (t);
			// ask for authentication to scol engine
			PROXYHTTP_AskAuthInfos (t->m, PROXYHTTP_WININET_NETWORK_API, (int)t->threadid, PROXYHTTP_NORMAL_MODE);
			// sleep a while, 'til the authentication infos are returned
			SuspendThread(t->thread);


			// wake up, go authenticate
			if (PROXYHTTP_IsAuthorized())
				return HTTPThreadSetOptions (t);

			return HTTPThreadQueryData (t);

		}
	}
	// no authentication needed
	else return HTTPThreadQueryData (t);



}









/********************************************************/
/*                                                      */
/* int INETdumpURL (mmachine m)                         */
/*                                                      */
/********************************************************/
int INETdumpURL (mmachine m)
{
	int url,i;
	transfert * t;
	
	url=MMget(m,0)>>1;
	if (url==NIL) return 0;
	
	t=(transfert*)MMfetch(m,url,0);
	
	if (!t) return 0;
  MMechostr(1,"Dump %x\n",t->opt);
  if (t->opt) for(i=0;i<t->sizeopt;i++) MMechostr(1,"%d-%x\n",i,t->opt[i]);
	
	return 0;
}






/********************************************************/
/*                                                      */
/* int INETStopURL (mmachine m)                         */
/*                                                      */
/********************************************************/
int INETStopURL (mmachine m)
{
	int url;
	transfert * t;
	
	if (!session) return 0;

	url=MMget(m,0)>>1;
	MMset(m,0,NIL);
	
	if (url==NIL) return 0;
	
	t=(transfert*)MMfetch(m,url,0);
	
	if (!t) 
		return 0;
	
	MMstore(m,url,0,0);
	OBJdelTH(m,HTTPobj,(int)t);
	return 0;
}






/********************************************************/
/*                                                      */
/* int iniSessionUrl()                                  */
/*                                                      */
/********************************************************/
int iniSessionUrl()
{

	if (!session)
	{
		MMechostr(MSKDEBUG,">>>start session via %s\n",HTTPproxy);
		if (HTTPproxy[0]==0) session=InternetOpen("SCOL",INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,0);
		else if (!strcmp(HTTPproxy,"no")) session=InternetOpen("SCOL",INTERNET_OPEN_TYPE_DIRECT,NULL,NULL,0);
		else session=InternetOpen("SCOL",INTERNET_OPEN_TYPE_PROXY,HTTPproxy,NULL,0);
		if (!session)
		{
			MMechostr(MSKDEBUG,"cannot open HTTP session\n");
			return MERRTYP;
		}
/*		n=100;
		k=sizeof(int);
		InternetQueryOption(session,INTERNET_OPTION_CONNECT_RETRIES,&n,&k);
		MMechostr(1,"test=%d\n",n);
*/
	}
	return 0;
}










/********************************************************/
/*                                                      */
/* DWORD WINAPI HTTPThreadEasy(LPVOID p)                */
/*                                                      */
/* thread callback to manage INETGetURL requests        */
/*                                                      */
/********************************************************/
DWORD WINAPI HTTPThreadEasy(LPVOID p)
{
	transfert * t=(transfert*)p;
	unsigned long size=-1;
	int flag;
	HINTERNET k;
	int *dead;
	int errcod,sizeerrbuf,lerr;
	char buf[1024];

	dead=(int*)malloc(sizeof(int));
	*dead=0;
	t->dead=dead;


	
	flag=INTERNET_FLAG_RELOAD|INTERNET_FLAG_KEEP_CONNECTION;

	//$ LB (27/08/2001) : test authorization
	// authentication has already been given
	if (PROXYHTTP_IsAuthorized())
	{
	char* uname = PROXYHTTP_GetUname();
	char* pword = PROXYHTTP_GetPword();

		InternetSetOption (t->handle, INTERNET_OPTION_USERNAME, uname, strlen(uname)+1);
		InternetSetOption (t->handle, INTERNET_OPTION_PASSWORD, pword, strlen(pword)+1);
		k = InternetOpenUrl(session, t->url, NULL, 0, flag , 0);
	}
	else k=InternetOpenUrl(session, t->url, "Pragma: no-cache\n", -1, flag , 0);

	

	if (*dead){free(dead);return 1;}
	t->handle=k;
//	MMechostr(MSKDEBUG,"createhttp %x t->handle=%x url=%s\n",t,t->handle,t->url);
	if (!t->handle) 
	{
			lerr=GetLastError();
	sizeerrbuf=1024;
	buf[0]=0;
	InternetGetLastResponseInfo(&errcod,buf,&sizeerrbuf);
		MMechostr(MSKDEBUG,"Error : InternetOpenUrl failed on %s\n%d %d\n%s\n",t->url,lerr,errcod,buf);
		//$LB (06/10/2003)
		/*
		PostMessage(hscol,WM_HTTP,-2,(DWORD)t);
		free(dead);
		t->dead=NULL;
		*/
		free(dead);
        t->dead=NULL;
        PostMessage(hscol,WM_HTTP,-2,(DWORD)t);
		//
		return 1;
	}



	//$ LB (24/08/2001) : check if authentication is needed
	if (PROXYHTTP_WININET_IsAuthenticated (t->handle))
	{
		// authentication has already been given
		if (PROXYHTTP_IsAuthorized())
			return HTTPThreadSetOptions (t);

		// ask for authentication
		else 
		{
			// store the struct
			HTTPtransfert_Add (t);
			// ask for authentication to scol engine
			PROXYHTTP_AskAuthInfos (t->m, PROXYHTTP_WININET_NETWORK_API, (int)t->threadid, PROXYHTTP_NORMAL_MODE);
			// sleep a while, 'til the authentication infos are returned
			SuspendThread(t->thread);


			// wake up, go authenticate
			if (PROXYHTTP_IsAuthorized())
				return HTTPThreadSetOptions (t);

			return HTTPThreadQueryData (t);

		}
	}
	// no authentication needed
	else return HTTPThreadQueryData (t);


}








/********************************************************/
/*                                                      */
/* int INETGetURL (mmachine m)                          */
/*                                                      */
/********************************************************/
int INETGetURL (mmachine m)
{
	int url,flag,tr,k;
	transfert* t;

	//MMechostr(MSKDEBUG,">>>INETGetURL\n");

	if (k=iniSessionUrl()) return k;
	
	flag=MMget(m,2)>>1;
	url=MMget(m,3)>>1;
	
	if (url==NIL || flag==NIL)
	{
		SEDROP(m, 4);
		MMset(m,0,NIL);
		MMechostr(MSKDEBUG,"Error : url  or flag NIL\n");
		return 0;
	}
	
	tr=MMmalloc(m,1,TYPEBUF);
	if (tr==NIL) return MERRMEM;
	
	t=(transfert*)malloc(sizeof(struct transfert));
//	MMechostr(MSKDEBUG,"create t: %x\n",t);
	
	if (!t) 
	{
		SEDROP(m, 4);
		MMset(m,0,NIL);
		MMechostr(MSKDEBUG,"HTTP Error : not enougth memory\n");
		return 0;
	}
	url=MMget(m,3)>>1;
	t->url=(char*)malloc(strlen(MMstartstr(m,url))+2);
//	MMechostr(MSKDEBUG,"create t: %x\n",t);
	
	if (!t->url) 
	{
		SEDROP(m, 4);
		MMset(m,0,NIL);
		free(t);
		MMechostr(MSKDEBUG,"HTTP Error : not enougth memory\n");
		return 0;
	}

	strcpy(t->url,MMstartstr(m,url));
	//  MMechostr(MSKDEBUG,"URL: %s\n",t->url);
	
	MMstore(m,tr,0,(int)t);
	
	t->thread=NULL;
	t->threadid=0;
	t->handle=NULL;
	t->handlebis=NULL;
	t->wait=FALSE;
	t->opt=NULL;
	t->sizeopt=0;
	t->verb[0]=0;
	t->dead=NULL;

	//$ LB (27/08/2001) : add mmachine to transfert
	t->m = m;
	t->headerAdds = NULL;

//	MMechostr(MSKDEBUG,">>>>create %x url=%s\n",t,t->url);
	(t->thread)=CreateThread(
		NULL, // pointer to security attributes
		0,    // initial thread stack size
		HTTPThreadEasy, // pointer to thread function
		t,   // argument for new thread
		0,    // creation flags
		&(t->threadid)  // pointer to receive thread ID
		);
	
	if (t->thread==NULL)
	{
		free(t->url);
		free(t);
		SEDROP(m, 4);
		MMset(m,0,NIL);
		MMechostr(MSKDEBUG,"HTTP Error : could not create thread\n");
		return 0;
	}
//	while(!t->dead);
	SetThreadPriority(t->thread,THREAD_PRIORITY_LOWEST);
	if (MMpushNoGC(m,MMget(m,4))) return MERRMEM;
	if (MMpush(m,(tr*2)+1)) return MERRMEM;
//	MMechostr(MSKDEBUG,">>>>chn %x obj=%x\n",MMget(m,1),MMget(m,0));
	if (OBJcreate(m,HTTPobj,(int)t,-1,0)) return MERRMEM;
//	MMechostr(MSKDEBUG,">>>>createHTTP %x %x\n",t,MMget(m,0));
	
	if (MMpush(m,MMget(m,2))) return MERRMEM;
	if (MMpush(m,MMget(m,2))) return MERRMEM;
	if (OBJaddreflex(m,HTTPobj,0)) return MERRMEM;
	
	tr=MMpull(m);
	SEDROP(m, 5);
	return MMpush(m,tr);
}








/********************************************************/
/*                                                      */
/* int INETGetURLengine                                 */
/*                                                      */
/* process INETGetURLex and INETGetURLex2 functions     */
/*                                                      */
/********************************************************/
int INETGetURLengine (mmachine m, int nbArgs, int mchn, int mverb, int murl, int mheaderAdds, int mopt, int mflag)
{
	int nbDrops = nbArgs-1;
	int tr;
	transfert* t;

	
	if ((mchn == NIL)||(murl == NIL) || (mflag == NIL))
	{
		SEDROP(m, nbDrops); MMset(m,0,NIL);
		MMechostr(MSKDEBUG,"Error : url  or flag NIL\n");
		return 0;
	}
	


	tr = MMmalloc(m,1,TYPEBUF);
	if (tr==NIL) return MERRMEM;
	
	t=(transfert*)malloc(sizeof(struct transfert));
//	MMechostr(MSKDEBUG,"create t: %x\n",t);
	
	if (!t) 
	{
		SEDROP(m, nbDrops);	MMset(m,0,NIL);
		MMechostr(MSKDEBUG,"HTTP Error : not enougth memory\n");
		return 0;
	}



	// verb
	if (mverb==NIL) t->verb[0]=0;
	else if (MMsizestr(m,mverb)<16) strcpy(t->verb,MMstartstr(m,mverb));
	else
	{
		SEDROP(m, nbDrops);	MMset(m,0,NIL);
		free(t);
		MMechostr(MSKDEBUG,"HTTP Error : verb too long\n");
		return 0;
	}


	// url
	t->url=(char*)malloc(strlen(MMstartstr(m,murl))+2);
	if (!t->url) 
	{
		SEDROP(m, nbDrops);	MMset(m,0,NIL);
		free(t);
		MMechostr(MSKDEBUG,"HTTP Error : not enougth memory\n");
		return 0;
	}
	strcpy(t->url,MMstartstr(m,murl));


	// headerAdds
	if (mheaderAdds == NIL) t->headerAdds = NULL;
	else
	{
	char* headerAdds = MMstartstr (m, mheaderAdds);

		t->headerAdds = (char*) malloc (strlen(headerAdds)+2);
		if (!t->headerAdds)
		{
			SEDROP (m, nbDrops); MMset(m,0,NIL);
			free(t->url); free(t);
			MMechostr (MSKDEBUG, "HTTP Error : not enough memory\n");
			return 0;
		}
		strcpy (t->headerAdds, headerAdds);
	}



	//opt
	t->sizeopt=0;
	if (mopt==NIL) t->opt=NULL;
	else
	{
		t->sizeopt=MMsizestr(m,mopt);
		t->opt=(char*)malloc(t->sizeopt);	
		if (!t->opt) 
		{
			SEDROP(m, nbDrops);	MMset(m,0,NIL);
			free(t->url); if (t->headerAdds) free (t->headerAdds); free(t);
			MMechostr(MSKDEBUG,"HTTP Error : not enougth memory\n");
			return 0;
		}
		memcpy(t->opt,MMstartstr(m,mopt),t->sizeopt);

	}

	//  MMechostr(MSKDEBUG,"URL: %s\n",t->url);
	
	MMstore(m,tr,0,(int)t);
	
	t->thread=NULL;
	t->threadid=0;
	t->handle=NULL;
	t->handlebis=NULL;
	t->wait=FALSE;
	t->dead=NULL;
	//$ LB (24/08/2001) : add mmachine to transfert
	t->m = m;


//	MMechostr(MSKDEBUG,">>>>createEx %x url=%s\n",t,t->url);
	(t->thread)=CreateThread(
		NULL, // pointer to security attributes
		0,    // initial thread stack size
		HTTPThread, // pointer to thread function
		t,   // argument for new thread
		0,    // creation flags
		&(t->threadid)  // pointer to receive thread ID
		);
	
	if (t->thread==NULL)
	{
		if (t->opt) free(t->opt);
		free(t->url); if (t->headerAdds) free (t->headerAdds); free(t);
		SEDROP(m, nbDrops);	MMset(m,0,NIL);
		MMechostr(MSKDEBUG,"HTTP Error : could not create thread\n");
		return 0;
	}

	SetThreadPriority(t->thread,THREAD_PRIORITY_LOWEST);
/*	while(!t->dead);*/
	if (MMpushNoGC(m, mchn)) return MERRMEM;
	if (MMpush(m,(tr*2)+1)) return MERRMEM;
	if (OBJcreate(m,HTTPobj,(int)t,-1,0)) return MERRMEM;
//	MMechostr(MSKDEBUG,">>>>createHTTP %x %x\n",t,MMget(m,0));
	
	if (MMpush(m,MMget(m,2))) return MERRMEM;
	if (MMpush(m,MMget(m,2))) return MERRMEM;
	if (OBJaddreflex(m,HTTPobj,0)) return MERRMEM;
	
	tr=MMpull(m);
	SEDROP(m, nbArgs);
	return MMpush(m,tr);
}





/********************************************************/
/*                                                      */
/* int INETGetURLex2 (mmachine m)                       */
/*                                                      */
/* same as INETGetURLex, but the supplementary fourth   */
/* parameter (S) allow to adds field(s) in the request  */
/* header.                                              */
/*                                                      */
/* fun [Chn S S S S I fun [INET u0 S I] u1 u0] INET     */
/********************************************************/
int INETGetURLex2 (mmachine m)
{
int mchn, mverb, murl, mheaderAdds, mopt, mflag, k;

	//MMechostr(MSKDEBUG,"\n>>>INETGetURLex2\n");

	if (k=iniSessionUrl()) return k;
	
	mflag = MMget(m,2)>>1;
	mopt  = MMget(m,3)>>1;
	mheaderAdds = MMget(m,4)>>1;
	murl  = MMget(m,5)>>1;
	mverb = MMget(m,6)>>1;
	mchn  = MMget(m,7)>>1;

	return INETGetURLengine (m, 8, mchn, mverb, murl, mheaderAdds, mopt, mflag);
}




/********************************************************/
/*                                                      */
/* int INETGetURLex (mmachine m)                        */
/*                                                      */
/* fun [Chn S S S I fun [INET u0 S I] u1 u0] INET       */
/********************************************************/
int INETGetURLex (mmachine m)
{
int mchn, mverb, murl, mopt, mflag, k;


	//MMechostr(MSKDEBUG,"\n>>>INETGetURLex\n");

	if (k=iniSessionUrl()) return k;
	
	mflag = MMget(m,2)>>1;
	mopt  = MMget(m,3)>>1;
	murl  = MMget(m,4)>>1;
	mverb = MMget(m,5)>>1;
	mchn  = MMget(m,6)>>1;


	return INETGetURLengine (m, 7, mchn, mverb, murl, NIL, mopt, mflag);
}






/********************************************************/
/*                                                      */
/* int INETdisableProxy(mmachine m)                     */
/*                                                      */
/********************************************************/
/* fun [] I*/
int INETdisableProxy(mmachine m)
{
	strcpy(HTTPproxy,"no");
	if (session) InternetCloseHandle(session);
	session=0;
	return MMpush(m,NIL);
}









//$ LB (17/07/2001) : add INETisConnected function 
//$ LB (28/08/2001) : add INETGetURLex2 function
//$LB (05/03/2002) : suppr INETisConnected from here : it's now managed in inetconnect.cpp
#define NHTTPPKG 6

char * HTTPname [ NHTTPPKG ] = 
{
	"INET",
	"INETGetURL",
	"INETGetURLex",
	"INETGetURLex2", //$ LB (27/08/2001) : allow to add field(s) in the header of the request
	"INETStopURL",
	"INETdisableProxy"
} ; 

char * HTTPtype [ NHTTPPKG ] = 
{
	NULL,
	"fun [Chn S I fun [INET u0 S I] u1 u0] INET",
	"fun [Chn S S S I fun [INET u0 S I] u1 u0] INET",
	"fun [Chn S S S S I fun [INET u0 S I] u1 u0] INET",
	"fun [INET] INET",
	"fun [] I"
} ;

int HTTPnarg [ NHTTPPKG ] = 
{
	TYPTYPE,
	5,
	7,
	8,
	1,
	0
} ;

int (*HTTPfun[NHTTPPKG])(mmachine m)= 
{
	NULL,
	INETGetURL,
	INETGetURLex,
	INETGetURLex2,
	INETStopURL,
	INETdisableProxy
} ;                                                                   


int SCOLloadHTTPbis(mmachine m)
{
	int k;

	k=PKhardpak(m,"INETie.pkg",NHTTPPKG,HTTPname,HTTPfun,HTTPnarg,HTTPtype);
	HTTPobj=OBJregister(1,0,HTTPdestroy,"OBJHTTP");
	WM_HTTP=OBJgetUserEvent();
	OBJdefEvent(WM_HTTP,HTTPEvent);

	session=0;

	return k;
}

int SCOLfreeHTTP()
{
	MMechostr(1,"close HTTP session\n");
	if (session) InternetCloseHandle(session);
	session=0;
	return 0;
}
