/***************************************************************************
                          http.cpp  -  description
                             -------------------
    begin                : Mon Dec 8 2003
    copyright            : (C) 2003 by Wei Zheng
    email                : v_zheng@yahoo.com
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

#include "http.h"

http::http(){
  memset(sendmesgbuf,0,sizeof(sendmesgbuf));
  memset(recimesgbuf,0,sizeof(recimesgbuf));
  memset(proxyaddr,0,sizeof(proxyaddr));
  memset(tmpline,0,sizeof(tmpline));
  memset(finline,0,sizeof(finline));
  memset(&tmpresp,0,sizeof(response));
  sendmesgrea = sendmesglen = recimesglen = counter = proxyport = 0;
  memset(&prp,0,sizeof(post_request_parameters));
  if(sem_init(&bin_sem_finline_isfull, 0, 0)!= 0)
    perror("Semaphore initialization failed");
}
http::~http(){
}

/** No descriptions */
int http::reci_mesg() {
  int length;
  memset(recimesgbuf,0,sizeof(recimesgbuf));
  while((length = reci_mesg_head())==-1);
  if(length > 0)
    return reci_mesg_body(length);
  else
    return 0;
}

/** No descriptions */
int http::reci_mesg_head(){
  int length,result;
  char * start;
  length = -1;
  while(1)
  {
    tmpresp.flush();
    result = get_line(fd,tmpresp.line,sizeof(tmpresp.line));
    if(result==0)
    {
      tmpresp.makearray();
      if(tmpresp.point[0]!=NULL)
      {
        if(strcmp(tmpresp.point[0],"X-MSN-Messenger:")==0)
        {
          start = strstr(tmpresp.point[1],"SessionID=");
          if(start!=NULL)
          {
            start += 10;
            memset(prp.sessionid,0,strlen(prp.sessionid));
            strncat(prp.sessionid,start,strstr(tmpresp.point[1],";")-start);
          }
          if(strstr(tmpresp.point[2],"GW-IP=")!=NULL)
          {
            memset(prp.ip,0,strlen(prp.ip));
            strcat(prp.ip,tmpresp.point[2]+sizeof(char)*6);
          }
        }
        else if(strcmp(tmpresp.point[0],"Content-Length:")==0)
        {
          length = atoi(tmpresp.point[1]);
        }
      }
      else
      {
        break;
      }
    }
  }
  return length;
}

/** No descriptions */
int http::reci_mesg_body(int length){
  int result;
  memset(recimesgbuf,0,sizeof(recimesgbuf));
  result = full_read(recimesgbuf,length);
  if(length == result)
    linep = recimesgbuf;
  debug("%s",recimesgbuf);
  return result;
}

/** No descriptions */
int http::send_mesg()
{
  char mime[128],mesghead[256],postrequest[512];

  if(sendmesglen!=0 && sendmesgrea==1)
  {
    memset(mime,0,sizeof(mime));
    strcat(mime,"MIME-Version: 1.0\r\nContent-Type: text/plain; charset=UTF-8\r\nX-MMS-IM-Format:FN=Clean;EF=;CO=000000;CS=0;PF=22\r\n\r\n");
    memset(mesghead,0,sizeof(mesghead));
    sprintf(mesghead,"MSG %d A %d\r\n",counter++,strlen(mime)+sendmesglen);
    strcat(mesghead,mime);
    makeurl();
    memset(postrequest,0,sizeof(postrequest));
    sprintf(postrequest,"POST %s HTTP/1.1\r\nAccept: */*\r\nAccept-Language: en-us\r\nAccept-Encoding: gzip, deflate\r\nUser-Agent: MSMSGS\r\nHost: %s\r\nProxy-Connection: Keep-Alive\r\nConnection: Keep-Alive\r\nPragma: no-cache\r\nContent-Type: application/x-msn-messenger\r\n",prp.url,prp.ip);
    sprintf(postrequest+strlen(postrequest),"Content-Length: %d\r\n\r\n",strlen(mesghead)+sendmesglen);
    memset(&prp,0,sizeof(post_request_parameters));
    full_write(postrequest,strlen(postrequest));
    debug("postrequest:\n%s",postrequest);
    full_write(mesghead,strlen(mesghead));
    debug("mesghead:\n%s",mesghead);
    full_write(sendmesgbuf,sendmesglen);
    debug("sendmesgbuf:\n%s",sendmesgbuf);
    memset(sendmesgbuf,0,sizeof(sendmesgbuf));
    sendmesglen = 0;
    sendmesgrea = 0;
  }
  else
  {
    memset(prp.action,0,sizeof(prp.action));
    strcat(prp.action,"poll");
    makeurl();
    memset(postrequest,0,sizeof(postrequest));
    sprintf(postrequest,"POST %s HTTP/1.1\r\nAccept: */*\r\nAccept-Language: en-us\r\nAccept-Encoding: gzip, deflate\r\nUser-Agent: MSMSGS\r\nHost: %s\r\nProxy-Connection: Keep-Alive\r\nConnection: Keep-Alive\r\nPragma: no-cache\r\nContent-Type: application/x-msn-messenger\r\n",prp.url,prp.ip);
    sprintf(postrequest+strlen(postrequest),"Content-Length: 0\r\n\r\n");
    memset(&prp,0,sizeof(post_request_parameters));
    full_write(postrequest,strlen(postrequest));
    debug("%s",postrequest);
  }
  return 0;
}

/** No descriptions */
int http::send_comm(int flag, char * comm, char * argu,...){

  char line[32];
  char postrequest[512];
  int n, size = 560;
  char *p;
  va_list ap;

  memset(line,0,sizeof(line));
  if(strlen(comm) != 0)
  {
    sprintf(line,"%s %d ",comm,counter++);
    strcat(sendmesgbuf,line);

    p=(char *)malloc(size);
    if((p=(char *)malloc(size))==NULL)
    {
      p=NULL;
      return 1;
    }
    while(1)
    {
      va_start(ap, argu);
      n = vsnprintf (p, size, argu, ap);
      va_end(ap);
      if (n > -1 && n < size)
        break;
      if (n > -1)
        size = n+1;
      else
        size *= 2;
      if ((p = (char *)realloc(p, size)) == NULL)
      {
        p=NULL;
        return 1;
      }
    }
    strcat(sendmesgbuf,p);
  }
  else
  {
    if(strcmp(prp.action,"open")!=0)
    {
      memset(prp.action,0,sizeof(prp.action));
      strcat(prp.action,"poll");
    }
  }

  if(flag == 1)
  {
    if(strlen(sendmesgbuf)!=0 && strlen(prp.action)!=0)
      memset(prp.action,0,sizeof(prp.action));
    makeurl();
    memset(postrequest,0,sizeof(postrequest));
    sprintf(postrequest,"POST %s HTTP/1.1\r\nAccept: */*\r\nAccept-Language: en-us\r\nAccept-Encoding: gzip, deflate\r\nUser-Agent: MSMSGS\r\nHost: %s\r\nProxy-Connection: Keep-Alive\r\nConnection: Keep-Alive\r\nPragma: no-cache\r\nContent-Type: application/x-msn-messenger\r\n",prp.url,prp.ip);
    sprintf(postrequest+strlen(postrequest),"Content-Length: %d\r\n\r\n",strlen(sendmesgbuf));

    if(proxyport == 0)
    {
      if(strcmp(prp.action,"open")==0)
      {
        if(make_connect(NOTIFICATIONHTTPPROXY,80)==-1)
        {
          debug("ERR ADDR:%s PORT:80 unable to connect\n",NOTIFICATIONHTTPPROXY);
          return 1;
        }
        else
        {
          debug("OK ADDR:%s PORT:80 able to connect\n",NOTIFICATIONHTTPPROXY);
        }
      }
      else if(strcmp(proxyaddr,prp.ip)!=0 && strlen(prp.ip)!=0)
      {
        make_close();
        memset(proxyaddr,0,sizeof(proxyaddr));
        strcat(proxyaddr,prp.ip);
        if(make_connect(proxyaddr,80)==-1)
        {
          debug("ERR ADDR:%s PORT:80 unable to connect\n",proxyaddr);
          return 1;
        }
        else
        {
          debug("OK ADDR:%s PORT:80 able to connect\n",proxyaddr);
        }
      }
    }

    memset(&prp,0,sizeof(post_request_parameters));
    full_write(postrequest,strlen(postrequest));
    debug("%s",postrequest);
    full_write(sendmesgbuf,strlen(sendmesgbuf));
    debug("%s",sendmesgbuf);
    memset(sendmesgbuf,0,sizeof(sendmesgbuf));
  }
  return 0;
}

/** No descriptions */
void http::makeurl()
{
  int para=0;
  memset(prp.url,0,strlen(prp.url));
  if(strcmp(prp.action,"open")==0)
  {
    sprintf(prp.url,"http://%s/gateway/gateway.dll?",NOTIFICATIONHTTPPROXY);
    strcat(prp.url,"Action=");strcat(prp.url,prp.action);
    strcat(prp.url,"&Server=");strcat(prp.url,prp.server);
    strcat(prp.url,"&IP=");strcat(prp.url,prp.ip);
    para =1;
  }
  else if(strlen(prp.action)!=0)
  {
    sprintf(prp.url,"http://%s/gateway/gateway.dll?",prp.ip);
    strcat(prp.url,"Action=");strcat(prp.url,prp.action);
    para=1;
  }
  else
  {
    sprintf(prp.url,"http://%s/gateway/gateway.dll?",prp.ip);
  }
  if(strlen(prp.sessionid)!=0)
  {
    if(para==1)
      strcat(prp.url,"&");
    strcat(prp.url,"SessionID="); strcat(prp.url,prp.sessionid);
  }
}

/** No descriptions */
int http::get_resp()
{
  char * tmpchar;
  if((tmpchar = strstr(linep,"\r\n")) == NULL)
  {
    linep = NULL;
    return 1;
  }
  else
  {
    tmpresp.flush();
    strncat(tmpresp.line,linep,tmpchar-linep);
    linep = tmpchar + 2;
    tmpresp.makearray();
    return 0;
  }
}

/** No descriptions */
int http::get_mesg(int len)
{
  int ismesg;
  char * start;
  char * end;

  start = linep;
  ismesg = 0;
  while(1)
  {
    end = strstr(start,"\r\n");
    if(start == end)
    {
      start = end + 2;
      break;
    }
    else
    {
      memset(tmpline,0,sizeof(tmpline));
      strncat(tmpline,start,end-start);
      if(strstr(tmpline,"Content-Type: text/plain;")!=NULL)
        ismesg = 1;
    }
    start = end + 2;
  }
  if(ismesg==1)
  {
    if(strlen(finline)==0)
    {
      memset(finline,0,sizeof(tmpline));
      strncat(finline,start,len-(start-linep));
        debug("COM:%s\n",finline);
    }
  }
  linep = linep + len;
  return ismesg;
}
