#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>

#include "html-util.h"
#include "ndb_misclib.h"

char HT_CGI_PATH[HT_ENV_MAX_NAME_LEN];
char HT_SERVER_NAME[HT_ENV_MAX_NAME_LEN];
char HT_SERVER_PATH[HT_ENV_MAX_NAME_LEN];
char HT_SESSION_ROOT_PATH[HT_ENV_MAX_NAME_LEN];

void ht_set_httpd_environment()
{
       char server[HT_ENV_MAX_NAME_LEN], port[HT_ENV_MAX_NAME_LEN];
       char *server_env = NULL, *port_env = NULL;         
    
       server_env = getenv("SERVER_NAME");
       memset(server, '\0', HT_ENV_MAX_NAME_LEN);
       if (server_env) strcpy(server, server_env);
       port_env  = getenv("SERVER_PORT");
       memset(port, '\0', HT_ENV_MAX_NAME_LEN);
       if (port_env) strcpy(port, port_env);

       strcpy(HT_CGI_PATH,   "/cgi-bin/");             

       strcpy(HT_SERVER_NAME, "http://");
       strcat(HT_SERVER_NAME, server);
       strcat(HT_SERVER_NAME, ":"); 
       strcat(HT_SERVER_NAME, port); 

       strcpy(HT_SERVER_PATH,  "/WWWligand/");  
       strcpy(HT_SESSION_ROOT_PATH, "/WWWligand/sessions/");
}

void print_error_message(FILE *out, const char *message)
{
       fprintf(out, "Content-type: text/html\n\n");
       fprintf(out, "<html>\n<body bgcolor=\"#C6EFF7\">\n");
       fprintf(out, "<center>\n");
       fprintf(out, "<br><br>\n");
       fprintf(out, "<H1>%s.</H1>\n", message);
       fprintf(out, "<br><br>\n");
       fprintf(out, "</center>\n");
       fprintf(out, "</body>\n</html>\n");
}

int html_decode_multipart_form_data(entry *entries, const char *path)
{
       int  c, i, j, ibeg, lenCT, lenData = 0, numEntries = 0, bufLen;
       int isCompressed;
       char *contentType = NULL, *sp, boundary[256], tfile[HT_MAX_NAME_LENGTH];
       char *bufp, *buf, *cp0, *cp1, *cp2, *cpN, *datap = NULL;
       char contDisp[HT_MAX_LINE_LENGTH], contType[HT_MAX_LINE_LENGTH];
       char name[HT_MAX_NAME_LENGTH],  fileName[HT_MAX_NAME_LENGTH];
       FILE *fp = NULL;

       sleep(3);

       ht_check_post_request();
       if (strncmp(getenv("CONTENT_TYPE"), "multipart/form-data", 19)) {
            ndb_log_message_text(NDB_MSG_ERR,"html_decode_multipart_form_data: Wrong CONTENT_TYPE %s",
                       getenv("CONTENT_TYPE"));
            return (0);
       }

       isCompressed = 0;
       lenCT = strlen(getenv("CONTENT_TYPE"));
       contentType = (char *) calloc(lenCT+1,sizeof(char));
       strcpy(contentType, getenv("CONTENT_TYPE"));

       for (i = 0, sp = &contentType[0], ibeg = -1; i < lenCT; i++) {
            if (!strncmp(sp, "boundary=", 9)) {
                 ibeg = i; break;
            }
            sp++;
       }

       if (ibeg > 0 && ibeg < ((int) strlen(contentType) - 9)) {
            sp+=9;
            memset(boundary, 0, 256);
            strcpy(boundary, "--");  /* prefix boundary string with "--"  */
            strncat(boundary, sp, 244);
       } else {
            ndb_log_message_text(NDB_MSG_ERR,"html_decode_multipart_form_data: no boundary string");
            return(0);
       }

       bufLen = atoi(getenv("CONTENT_LENGTH"));
       if (bufLen > HT_MAX_UPLOAD_BYTES) {
            ndb_log_message_text(NDB_MSG_DEBUG,"html_decode_multipart_form_data: Upload %d exceeds %d byte limit",
                          bufLen, HT_MAX_UPLOAD_BYTES); 
            return(0);
       }

       i = 0;
       buf = (char *) calloc(bufLen+1, sizeof(char));
       while ((c = fgetc(stdin)) != EOF && i < bufLen) {
            buf[i] = c; i++;
       }
       if (i != bufLen) ndb_log_message_text(NDB_MSG_ERR,"html_decode_multipart_form_data: Uploaded failed.");

       numEntries = -1;
       for (bufp = &buf[0]; bufp; bufp++) {
            if (!strncmp(bufp, boundary, strlen(boundary))) {
                 if (numEntries != -1 && lenData) {
                      if (entries[numEntries].isFile) { 
                           i = strlen(fileName);
                           isCompressed = 0;
                           if (i > 0) { 
                                if (((i > 2 && fileName[i-2] == '.' && fileName[i-1] == 'Z')) ||
                                    ((i > 3 && fileName[i-3] == '.' && fileName[i-2] == 'g' &&
                                               fileName[i-1] == 'z') )) isCompressed = 1;
                                cp0 = ht_strip_leading_path(fileName);
                                strcpy(tfile, path);
                                strcat(tfile, cp0);
                                ndb_log_message_text(NDB_MSG_DEBUG,"html_decode_multipart_form_data: copying file to %s",tfile);
                                fp = fopen(tfile, "w");
                                if (fp == NULL) {
                                     ndb_log_message_text(NDB_MSG_ERR,"html_decode_multipart_form_data: Unable to open upload file %s",tfile);
                                }
                                if (isCompressed) {
                                     for (cp1 = datap, i = 0; i < lenData - 2; i++) {
                                          fputc(*cp1, fp);  cp1++;
                                     }
                                } else { 
                                     for (cp1 = datap, i = 0; i < lenData - 2; i++) {
                                          cpN = cp1; cpN++; 
                                          if ((*cp1 == 13) && (*cpN != 10)) *cp1 = 10;  // convert isolated cr to nl.
                                          if ((*cp1 > 31 && *cp1 <= 126) || *cp1 == 10 ) { // filter ascii control characters.
                                               fputc(*cp1, fp);  
                                          } else if (*cp1 == 9 || *cp1 > 126) {// filter ascii control characters.
                                               fputc(' ', fp);  
                                          }
                                          cp1++;
                                     }
                                }
                                fclose(fp);
                           }
                      } else {
                           entries[numEntries].val = (char *)calloc(lenData+2,sizeof(char));
                           strncpy(entries[numEntries].val, datap,lenData-2);
                           ndb_log_message_text(NDB_MSG_DEBUG,"html_decode_multipart_form_data: entry=%d name=%s value=%s\n",
                                  numEntries, entries[numEntries].name, entries[numEntries].val); 
                      }
                 }
                 lenData = 0;
                 numEntries++;
                 entries[numEntries].isFile = 0;
                 entries[numEntries].name   = (char *)NULL;
                 entries[numEntries].val    = (char *)NULL;
                 entries[numEntries].file   = (char *)NULL;

                 bufp += strlen(boundary); bufp++; bufp++;
                 
                 for (i = 0, cp1 = bufp; *cp1 && (*cp1 != '\r'); cp1++) {
                      contDisp[i] = *cp1; i++;
                 }
                 contDisp[i] = '\0';
                 if (strlen(contDisp) == 0) break;

                 for (i = 0, cp1 = contDisp; *cp1; cp1++) {
                      if (!strncmp(cp1, "name=", 5)) {
                           cp1 += 6;
                           for (j = 0, cp2 = cp1; cp2 && *cp2 != '"'; cp2++) {
                             name[j] = *cp2; j++;
                           }
                           name[j] = '\0';
                           entries[numEntries].name = (char *)calloc(strlen(name)+1, sizeof(char));
                           strcpy(entries[numEntries].name, name);
                      }
                      if (!strncmp(cp1, "filename=", 9) ) {
                           cp1 += 10;
                           for (j = 0, cp2 = cp1; cp2 && *cp2 != '"'; cp2++) {
                                fileName[j] = *cp2; j++;
                           }
                           fileName[j] = '\0';
                           if (strlen(fileName) > 0) {
                                cp1 = ht_strip_leading_path(fileName);
                                entries[numEntries].file = (char *) calloc(strlen(cp1)+1, sizeof(char));
                                strcpy(entries[numEntries].file, cp1);
/*
                                entries[numEntries].file = (char *)calloc(strlen(cp1)+strlen(path)+1, sizeof(char));
                                strcat(entries[numEntries].file,path);
                                strcat(entries[numEntries].file,cp1);
*/
                           } else entries[numEntries].file = NULL;
                           entries[numEntries].isFile = 1;
                      }
                 }
                 bufp += strlen(contDisp) + 2;
                 for (i = 0, cp1 = bufp; *cp1 && (*cp1 != '\r') ; cp1++) {
                      contType[i] = *cp1; i++;
                 }
                 contType[i] = '\0';
                 if (strlen(contType)) bufp += 2;
                 bufp += strlen(contType) + 2;
                 datap = bufp;
            }
            lenData++;
       }
       for (i = 0; i < numEntries; i++) {
            if (entries[i].isFile && entries[i].file != NULL) {
                 entries[i].val = (char *) calloc(strlen(entries[i].file)+1, sizeof(char));
                 strcpy(entries[i].val, entries[i].file);
            } else if (!entries[i].isFile && entries[i].val != NULL) {
                 entries[i].file = (char *) calloc(strlen(entries[i].val)+1,sizeof(char));
                 strcpy(entries[i].file,entries[i].val);
            }
       }
       if (buf) free(buf);
       if (contentType) free(contentType);
       return (numEntries);
}  
