2010-07-14 49 views
1

我非常需要挖掘潜在的大量CGI提供的POST数据的方法。阅读CGI POST数据是最有效的方式

通过读取GET数据,没有什么大不了的,因为我可以根据需要重新请求QUERY_STRING环境变量,但使用的是通过stdin提供的POST数据。我只能一次读取它,并且必须将其存储在某个地方。

我目前的方法包括读取临时文件中的大量POST数据,当程序退出并通过扫描找到我想查找的键时将被删除。 在GET解析方法中,我可以在QUERY_STRING上使用strtok(),因为GET数据具有相当低的限制,因此可以安全地在RAM中读取数据,但POST数据可以是从空到“name = Bob”到4 Gigabye电影文件。

所以,这是我目前的做法:

int get_post_data(const char *s_key, char *target, size_t target_size) 
{ 
    FILE *tmp; 
    int ret_val = -1; 

    /* postdata_temp = global variable containing the temporary file name */ 
    if ((tmp = fopen(postdata_tempfile, "r")) == NULL) 
     return -1; 
    else 
    { 
     char *buffer = NULL; 
     char *temp_buffer = NULL; 
     int buffer_size; 
     int i; 

     if ((buffer = malloc(BUFFER_SIZE)) == NULL) 
     return -1; 

     memset(buffer, 0, sizeof(BUFFER_SIZE)); 
     buffer_size = BUFFER_SIZE; 

     for (i = 0;; i++) 
     { 
     int c = fgetc(tmp); 

     if ((c == '&') || feof(tmp)) 
     { 
      char *key = strtok(buffer, "="); 
      char *val = strtok(NULL, "");    

      if (key) 
      { 
       if (strcmp(s_key, key) == 0) 
       { 
        if (val) 
        { 
        strncpy(target, val, target_size); 
        ret_val = strlen(val); 
        } 
        else 
        { 
        target = NULL; 
        ret_val = 0; 
        } 

        break; 
       } 
      } 

      if (feof(tmp)) 
       break; 

      memset(buffer, 0, buffer_size); 
      i = -1; /* because it will be 0 when the fgetc() is called the 
        * next time */ 
     } 
     else 
     { 
      if (!(i < buffer_size)) 
      { 
       buffer_size += BUFFER_SIZE; 

       if ((temp_buffer = realloc(buffer, buffer_size)) == NULL) 
       { 
        free(temp_buffer); 
        free(buffer); 
        target = NULL; 

        return -1; 
       } 
       else 
        buffer = temp_buffer; 
      } 

      buffer[i] = c; 
     } 

     } 

     free(buffer); 

     // printf("Final buffer size: %d<br />\n", buffer_size); 
    } 

    fclose(tmp); 

    return ret_val; 
} 

这不工作,我可以叫get_post_data("user_password", pass, sizeof(pass));,检查返回值(< 0 =错误=存在0 =键,但值为NULL,> 0 =数据长度),但它看起来太肥胖了。我的意思是......对于每一个POST参数而言,我想要搜索的庞大IO开销只是为了让我的RAM中的整个字符串不会被上传潜在的大文件?

Stackoverflow认为什么?

回答

1

如果您想要避免将大文件加载到RAM中,可以使用内存映射文件 - 不是便携式的,但是这是正确的方法。如果你的平台是POSIX,你可以使用mmap()

顺便说一句,我没有完全读或测试你的代码,但我想知道使用strtok()是否正确,因为它破坏了数据。如果你的数据可能是二进制文件,我也想知道如何使用str...()函数,但我不知道CGI部分是如何工作的,所以你可能就在那里。

+0

数据以“key = value”的形式到达,我使用'strtok()'分割键和值。只有价值是在实践中的二进制,并将交给调用者未经修改:) – LukeN 2010-07-14 02:36:24

+0

@LukeN:这有帮助吗? – 2010-09-02 04:36:29

0

我认为只要拒绝超过设定限制的POST请求比较容易,比如2MB。

这样:

  • 你有数据的可管理的大小的块的工作。
  • 您可以防止恶意的4GB POST请求。
+1

我尽量不限制我的程序可以接受的内容。在这种特殊情况下(文章文章)2 MB是足够的,但我写了我的模块,使我可以在任何情况下使用它们,例如文件上传,其中2 MB是一个桶中的下降。 :) – LukeN 2010-07-14 02:50:33

相关问题