/*  �ϥΤ�k: �ۤv���� r->method_number �P�_�O M_GET �� M_POST
 */
#include "mod_ptt.h"

unsigned char xtoc(char ch1, char ch2) {
  unsigned char d, up1, up2;

  if (!isxdigit(ch1) || !isxdigit(ch2)) return ' ';

  up1 = toupper(ch1);
  up2 = toupper(ch2);

  if (up1>='0' && up1<='9') d = up1-'0';
  else d = up1-'A'+10;
  d <<= 4;
  if (up2>='0' && up2<='9') d += up2-'0';
  else d += up2-'A'+10;

  return d;
}

char * cstoxs(pool *p, char *str)
{
  char * newstr = pstrdup(p,""), *po = str;

  for(po = str; *po; po++)
    {
	if(isprint(*po) && *po!=' ') newstr=psprintf(p, "%s%c", newstr,*po);
	else newstr=psprintf(p, "%s%%%X", newstr, *po& 0xFF);
    }
  return newstr;
}

int  // Ptt: �ڭ��g����mygetchar �å[�Wfileupload���\�� 
inital_postdata(request_rec *r, int *fileupload, char *boundary, 
        char **data)
{ 
  char *buf, *mb;
  int  size, off = 0, len_read; 
  void (*handler)();
 
  buf = table_get(r->subprocess_env,"CONTENT_TYPE"); 
  if(!buf || 
     (strncasecmp(buf,"application/x-www-form-urlencoded",33) && 
             strncasecmp(buf,"multipart/form-data",19)))
                return -1; 

  if(!strncasecmp(buf,"multipart/form-data",19)) { 
		if(!fileupload) return -1;
                *fileupload=1; 
                mb = strchr(buf,'='); 
                if(mb) {
			strcpy(boundary,mb+1);  
			strtok(boundary, " ;\n");
		       }
                else return -1; 
        } 
 
  buf = table_get(r->subprocess_env,"CONTENT_LENGTH"); 
  if(buf==NULL) return -1; 
 
  size = atoi(buf); 
  mb = (char *)palloc(r->pool,(size+1)*sizeof(char)); 
 
  if(!mb || 
     (setup_client_block(r ,REQUEST_CHUNKED_ERROR) != 0) ||               
     (should_client_block(r) == 0)) 
     return -1; 
                 
  hard_timeout("args.c copy script args", r);              
  handler = signal(SIGPIPE, SIG_IGN);

  while(size-off > 0 && (len_read = get_client_block 
                (r, mb + off, size - off)) > 0) { 
                        off += len_read; 
        } 

  signal(SIGPIPE, handler);
  kill_timeout(r);

  if(len_read < 0) return -1; // Ū�����~�����_
  mb[size]=0; // Ptt:�I�����ݭn�a �]�����O�Φr��B�z�覡
 (*data) = mb; 
  return size; 
} 

#define ENCODED_NAME     " name=\""
#define ENCODED_FILENAME " filename=\"" 
#define ENCODED_CONTENT  "Content-Type: "

//#define FILEDATAFILE DATABASEDIR "/" FDATA

int 
unescape(request_rec *r, char** name, char** value) {
  static char *sp=NULL,  boundary[150]; 
  static int fileupload,  boundarylen, dsize; 
  pool *p = r->pool;
  char   ch, ch1, *dp, *p0, *p1, *temp_sp, *ftype;
  int type;

  if (sp==NULL) {
    fileupload=0;
    switch (r->method_number) { 
	    case M_GET: 
	       if (r->args) sp = pstrdup(p, r->args);
	       else {sp=NULL; return -1;}
	       break;
	    case M_POST:
	       if ((dsize = 
		 inital_postdata(r, &fileupload, boundary,&sp))<0) 
	           {sp=NULL; return -1; }
	       if(fileupload) boundarylen = strlen(boundary);
	       break;
	    default: 
	       sp=NULL;
 	       return -1; 
	}
   }

  if(fileupload) 
   {	
	if(dsize >0 && (temp_sp = memstr(sp, boundary, dsize)))
         { 
	   temp_sp += boundarylen; 
           p0 = strstr(temp_sp, "\r\n\r\n"); 
           p1 = strstr(temp_sp, "\n\n"); 

           if(!((*name) = strstr(temp_sp, ENCODED_NAME))) 
		        {sp=NULL; return -1; }
	   (*name) += strlen(ENCODED_NAME);
	   strtok((*name) + 1 , "\"");
	   if( (!p0 && p1) || (p0 && p1 && p1<p0)) 
		{
			(*value) = sp = p1 + 2;
			type = 2;
		}
	   else if(p0)  
		{
                        (*value) = sp = p0 + 4; 
			type = 4;
		}
	   else 
		{
	          sp=NULL; 
 	 	  return -1;
	        }

          if((p1 = memstr(temp_sp, boundary, dsize - boundarylen))) 
		  temp_sp = p1;
	  else
		  temp_sp = sp + dsize;

	  *(temp_sp - type) = 0;

          // �ˬd�O���Ofile �Y�O�N��fileinfo
          if((dp=memstr(
  	      (*name) + strlen(*name) +1, ENCODED_FILENAME, dsize)) && 
	      dp < *value)
            {
		dp += strlen(ENCODED_FILENAME);
		p0 = strchr(dp,'"');
                *p0 = 0;
                if(p0 - dp>3)
		{
                 fileheader_t *file=(fileheader_t *)pcalloc(p, sizeof(fileheader_t));
                 if((ftype = strstr(p0 + 1, ENCODED_CONTENT)))
		  {
 		   ftype +=  strlen(ENCODED_CONTENT);
		   strtok(ftype, "\r\n");
		  }
                 while(p0 > dp && *p0 !='/' && *p0 !='\\') p0--;
                 strcpy(file->name, p0+1);    
		 strcpy(file->content_type, ftype);
		 file->icontent_type = filetype(ftype);
	//	 if(file->icontent_type & (FILE_TXT | FILE_HTML))
         //          file->size = strlen(sp);
          //       else
		   file->size = temp_sp - sp - type;
		 file->uploadtime = time(NULL); 
		 file->data = (*value);
                 (*value) = (char *)file;
		}
               else
                {
                 (*value) = NULL;
                }      
            }     

	  dsize -= (temp_sp - sp);
	  sp = temp_sp;
	  return 1;
         } 
        else 
         { 
          sp=NULL; 
          return -1; 
         }   
  }

  dp = (*name) = sp;  
  while(1) {
    ch = *sp++;
    switch(ch) {
      case '+':
        *dp++ = ' ';
        break;
      case '=':
        *dp++ = '\0';
	(*value) = dp;
	break;
      case '&': case '|':
        *dp++ = '\0';
        return 1;
      case '\0': case EOF:
        *dp = '\0'; 
	sp=NULL;
        return 0;
      case '%':
        ch = *sp++; ch1 = *sp++;
        *dp++ = xtoc(ch, ch1);
        break;
      default:
	*dp++=ch;
        break;
    }
  }
}