summaryrefslogblamecommitdiffstats
path: root/web/args.c
blob: 02e0fad0822a5a155d2402b0f1ed0819a60caba2 (plain) (tree)



































































































































































































































                                                                                     
/*  使用方法: 自己先用 r->method_number 判斷是 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: 我重寫拿掉mygetchar 並加上fileupload的功能 
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:截掉不需要吧 因為不是用字串處理方式
 (*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;

          // 檢查是不是file 若是就給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;
    }
  }
}