2010-07-14 52 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

相關問題