在C

时间:2016-04-05 03:05:58

标签: c string http http-post

我有以下代码来处理microhttp服务器中的POST数据:

#include <microhttpd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>

#define PAGE "<html><head><title>libmicrohttpd demo</title>"\
             "</head><body>libmicrohttpd demo!!</body></html>"

struct postStatus {
    bool status;
    char *buff;
};


static int ahc_echo(void * cls,
            struct MHD_Connection * connection,
            const char * url,
            const char * method,
                    const char * version,
            const char * upload_data,
            size_t * upload_data_size,
                    void ** ptr) {
  const char * page = cls;
  struct MHD_Response * response;
  int ret;

  struct postStatus *post = NULL;
  post = (struct postStatus*)*ptr;

  if(post == NULL) {
    post = malloc(sizeof(struct postStatus));
    post->status = false;
    *ptr = post;
  }

  if(!post->status) {
    post->status = true;
    return MHD_YES;
  } else {
    if(*upload_data_size != 0) {
        post->buff = malloc(*upload_data_size + 1);
        snprintf(post->buff, *upload_data_size,"%s",upload_data);
        *upload_data_size = 0;
        return MHD_YES;
    } else {
        printf("Post data: %s\n",post->buff);
        free(post->buff);
    }
  } 

  if(post != NULL)
    free(post);

  response = MHD_create_response_from_buffer (strlen(page),
                                              (void*) page,
                          MHD_RESPMEM_PERSISTENT);
  ret = MHD_queue_response(connection,
               MHD_HTTP_OK,
               response);
  MHD_destroy_response(response);
  return ret;
}

int main(int argc,
     char ** argv) {
  struct MHD_Daemon * d;

  d = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY,
               9000,
               NULL,
               NULL,
               &ahc_echo,
               PAGE,
               MHD_OPTION_END);
  if (d == NULL)
    return 1;
  sleep(10000);
  MHD_stop_daemon(d);
  return 0;
}

我尝试以下CURL命令来测试POST数据处理:

curl -XPOST -d '{"email":"test@gmail.com","password":"test"}' 'http://192.168.1.17:9000'

但是我得到了输出{"email":"test@gmail.com","password":"test"。我没有得到最后一个}。我也尝试了更长的json输入。还是一样。无法获得最后一个大括号。有人可以帮忙吗?

由于

编辑:我搞定了。我使用strncpy(post->buff, upload_data, *upload_data_size)代替snprintf

有人可以解释为什么没有snprintf工作?

1 个答案:

答案 0 :(得分:1)

对于请求,

ahc_echo()将被调用至少两次。请求数据可能被拆分为多个调用,并且此碎片非常随机(取决于缓冲区的请求,以及套接字上的每个read()调用返回的内容)。因此,您当前的代码仅适用于较小的请求,但仍然不安全。

MHD_create_post_processor()是解析此部分缓冲区的助手。

https://www.gnu.org/software/libmicrohttpd/tutorial.html#Processing-POST-data完成了这个

原因

 snprintf(post->buff, *upload_data_size,"%s",upload_data);

不起作用,应该是

 snprintf(post->buff, *upload_data_size + 1,"%s",upload_data);

以匹配malloc()中使用的内存大小,该内存具有\ 0终止的空间。

strncpy(post->buff, upload_data, *upload_data_size);

实际上是危险的,因为它应该是

strncpy(post->buff, upload_data, *upload_data_size);
post->buff[*upload_data_size] = 0;

由于你需要确保结果为零终止(幸运的是,内存现在已经包含零,这是使用malloc()时的随机行为,而不是calloc()),并且增加复制大小为*upload_data_size + 1是错误的,因为这会使源溢出一个字节,其中也包含随机数据,甚至可能包含无效的内存。