Мне очень нужен способ копаться в потенциально огромных объемах данных POST, предоставленных CGI.
С чтением данных GET это не составляет большого труда, так как я могу просто повторно запрашивать переменную окружения QUERY_STRING
так часто, как я хочу, но с данными POST, которые передаются через stdin
. Я могу прочитать его только один раз и хранить где-то.
Мой текущий метод состоит в том, чтобы прочитать всю кучу данных POST во временном файле, который будет удален при выходе из программы, и просканировать его, чтобы найти ключи, которые я хочу найти.
В подходе разбора GET я мог бы просто использовать strtok () над QUERY_STRING, потому что данные GET имеют довольно низкие пределы, поэтому их можно извлекать из оперативной памяти, но данные POST могут быть любыми, от пустых до «name = Bob» и до фильма 4 Гигабайта файл.
Итак, вот мой текущий подход:
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, который я хочу найти, просто чтобы в моей оперативной памяти не было всей строки для загружаемых потенциально больших файлов?
Что думает Stackoverflow?