#define CHUNK 16384
//---------------------------------------------------------------------------

#include <assert.h>
#include <vcl.h>
#pragma hdrstop

#include "THTTPdownloader.h"
#include "TZlib\GZipHelper.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
THTTPdownloader *HTTPdownloader;

//---------------------------------------------------------------------------
__fastcall THTTPdownloader::THTTPdownloader(TComponent* Owner)
        : TForm(Owner)
{
  headers = new TList();
}
//---------------------------------------------------------------------------
int __fastcall THTTPdownloader::descargarHTML(char *host, char *request, TStream *out)
{
    TMemoryStream* in  = new TMemoryStream();
    char buffer[4096];

    int pos,readed;
    int currSize,lastSize;

    AnsiString line, Location;
    HTTPheaders_list HeaderStruct;
    httpResult->Clear();

    for (int i = 0; i < headers->Count; i++)
    {
     HeaderStruct = (HTTPheaders_list) headers->Items[i];
     delete HeaderStruct;
    }
    headers->Clear();


    TcpClient1->RemoteHost = AnsiString( host );
    TcpClient1->RemotePort = 80;
    TcpClient1->Open();


    if ( TcpClient1->Connected )
    {
            statusBar->SelAttributes->Color = clGreen;statusBar->Lines->Add(AnsiString(Now())+AnsiString(" > ")+AnsiString("Conectado a: ")+AnsiString(host));

/* ¿ver que se envia?
            if ( Visible && debug->Checked ) ShowMessage("Cierre esta ventana para continuar");
*/

            TcpClient1->SendBuf(request,StrLen(request));


            bool R,W,T;
            bool atStart = true;
            bool inHeaders = true;

            while (TcpClient1->Connected)
            {
              R=TcpClient1->WaitForData(20000);
              if (!TcpClient1->Connected || !R) break;

              if ( inHeaders )
                      line = TcpClient1->Receiveln();
              else {
                      readed = TcpClient1->ReceiveBuf(buffer,4096);
                      if(readed<=0) break;
              }


              if ( atStart )
              {
		atStart = false;  //if (!preg_match('/HTTP\/(\\d\\.\\d)\\s*(\\d+)\\s*(.*)/', line, m))  return false;
                httpResult->SelAttributes->Color = clGreen;
                httpResult->Paragraph->Numbering = nsBullet;
                httpResult->Lines->Add(line);
                if ( line.SubString(1,4)!="HTTP" )  return -1;
                continue;
              }

              if (inHeaders)
              {
	      	if ( line.Trim() == "" )
                {
                  inHeaders = false;
		  continue;
		}

                pos = line.AnsiPos(":");
		if (pos==0)
		{
			// Skip to the next header
			continue;
		}

                HeaderStruct = new THTTP_headers;
                HeaderStruct->key = line.SubString(1,pos-1).Trim().LowerCase();
                HeaderStruct->value = line.SubString(pos+1,line.Length()).Trim();
                headers->Add(HeaderStruct);

                httpResult->SelAttributes->Color = clRed;
                httpResult->Paragraph->Numbering = nsBullet;
                httpResult->Lines->Add(line);

		continue;
              }

              in->Write(buffer,readed);
            }
            TcpClient1->Close();

            statusBar->Lines->Add(AnsiString(Now())+AnsiString(" > ")+AnsiString("Leidos: ")+AnsiString(readed)+"/"+AnsiString(in->Size));

            bool gziped=false;
            for ( pos=0;pos<headers->Count; pos++ )
            {
               HeaderStruct = (HTTPheaders_list)headers->Items[pos];
               if ( HeaderStruct->key=="content-encoding" )
               {
                  gziped= (HeaderStruct->value=="gzip");
                  break;
               } else
               if ( HeaderStruct->key=="location" )
               {
                  Location = HeaderStruct->value;
               }


            }

            httpResult->Paragraph->Numbering = nsNone;
            if ( gziped )
            {
               in->Position=0;
               CGZIP2A plain((unsigned char *)in->Memory,(int)in->Size);
               out->Write(plain.psz,plain.Length);out->Write("",1);
               httpResult->Lines->Add(plain.psz);
            } else {
               in->Write("",1);in->Position = 0;
               out->Write(in->Memory,in->Size);
               httpResult->Lines->Add((char *)in->Memory);
            }

            if ( debug->Checked )
            {
                  DateSeparator	= '-';
                  TimeSeparator	= ';';
             statusBar->Clear();
             statusBar->SelAttributes->Color = clRed;statusBar->Lines->Add("RX: ------------------------------------------------------------------");
             statusBar->Lines->Assign(httpResult->Lines);
             statusBar->SelAttributes->Color = clRed;statusBar->Lines->Add("TX: ------------------------------------------------------------------");
             statusBar->Lines->Add(request);
             statusBar->Lines->SaveToFile( ExtractFilePath(Application->ExeName)+"log\\"+DateTimeToStr(Now())+".http.rtf" );
             statusBar->SelAttributes->Color = clRed;statusBar->Lines->Add("EOT ------------------------------------------------------------------");
            }

            delete in;
    } else {
     statusBar->SelAttributes->Color = clRed;statusBar->Lines->Add(AnsiString(Now())+AnsiString(" > ")+AnsiString("ERROR CONECTANDO a: ")+AnsiString(host));
     return -1;
    }

    if ( !Location.IsEmpty() ) {
        AnsiString lrequest;
        lrequest = "GET "+Location;
        lrequest+=" HTTP/1.1\r\n";
        lrequest+= "Host: "+AnsiString(host)+"\r\n";
        lrequest+= "Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n";
        lrequest+= "Accept-Language: es-es,es;q=0.8\r\n";
        lrequest+= "Accept-Encoding: gzip,deflate\r\n";
        lrequest+= "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n";
        lrequest+= "Keep-Alive: 300\r\n";
        lrequest+= "Connection: keep-alive\r\n";
        lrequest+= "\r\n";

        return descargarHTML(host, lrequest.c_str(), out);
    } else
        return 0;
}
//---------------------------------------------------------------------------
void __fastcall THTTPdownloader::FormDestroy(TObject *Sender)
{
  HTTPheaders_list HeaderStruct;

  // Clean up – must free memory for the items as well as the list
  for (int i = 0; i < headers->Count; i++)
  {
    HeaderStruct = (HTTPheaders_list) headers->Items[i];
    delete HeaderStruct;
  }
  delete headers;
}
//---------------------------------------------------------------------------




