2010-07-14 10 views
1

잠재적으로 엄청난 양의 CGI 제공 POST 데이터를 파헤치는 방법이 절실히 필요합니다.CGI POST 데이터를 가장 효율적으로 읽는 방법

내가 원하는대로 자주 QUERY_STRING 환경 변수를 다시 요청할 수 있지만 stdin을 통해 제공되는 POST 데이터를 사용하여 GET 데이터를 읽는 것은별로 중요하지 않습니다. 한 번에 읽을 수만 있고 어딘가에 보관해야합니다.

현재의 방법은 프로그램이 종료 될 때 제거 될 임시 파일 내에서 POST 데이터 전체를 읽는 것으로 구성되어 있습니다.이 프로그램을 통해 스캔하여 원하는 데이터를 찾습니다. GET 파싱 접근법에서는 GET 데이터가 매우 낮으므로 QUERY_STRING을 통해 strtok() 할 수 있습니다. 따라서 RAM 내부로 가져 오는 것이 안전하지만 POST 데이터는 "name = Bob"에서 4 Gigabye로 비워 둘 수 있습니다 영화 파일. > 0

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; 
} 

이 작품, 내가 = 오류 (반환 값 < 0을 확인 get_post_data("user_password", pass, sizeof(pass));를 호출 할 수 = 값이 NULL을 제외한 0 = 키가 않습니다

그래서, 여기 내 현재의 접근 방식 = 데이터 길이), 너무 비만 해 보입니다. 내 말은 .. 모든 단일 POST 매개 변수에 대한 엄청난 IO 오버 헤드로 잠재적으로 큰 파일을 업로드하기 위해 내 RAM에 전체 문자열이 포함되지 않도록 검색하고 싶습니까?

Stackoverflow는 어떻게 생각합니까?

답변

1

큰 파일을 RAM에로드하지 않으려면 휴대용 파일이 아닌 메모리 매핑 파일을 사용할 수 있지만 올바른 방법입니다. 플랫폼이 POSIX 인 경우 mmap()을 사용할 수 있습니다.

그런데 완전히 읽지 않았거나 코드를 테스트하지는 못했지만 strtok()을 사용하는 것이 올바른지 데이터를 파괴하기 때문에 해야할지 궁금합니다. 또한 데이터가 이진 파일 일 경우 str...() 함수를 사용하는 것에 대해 궁금해 하겠지만 CGI 파트가 어떻게 작동하는지 잘 모릅니다.

+0

데이터는 "key = value"로 도착하고 키와 값을 분리하려면'strtok() '을 사용합니다. 값은 실제로는 바이너리이며 호출자에게 수정되지 않은 채로 전달됩니다 :) – LukeN

+0

@LukeN :이 도움이 되었습니까? –

0

2MB와 같이 설정 제한보다 큰 POST 요청을 거부하는 것이 더 쉽다고 생각합니다.

그 방법 :

  • 당신은 작업 할 데이터의 관리 크기의 블록을 가지고있다.
  • 악의적 인 4GB POST 요청을 방지합니다.
+1

내 프로그램에서 허용 할 수있는 것을 제한하지 않으려 고합니다. 이 특별한 경우 (텍스트 기사)에는 2MB 정도면 충분하지만, 파일 업로드와 같이 어떤 경우에도 2MB를 버킷으로 사용하는 것과 같은 방식으로 모듈을 작성합니다. :) – LukeN

관련 문제