Blame src/microhttpd/test_postprocessor.c

Packit 875988
/*
Packit 875988
     This file is part of libmicrohttpd
Packit 875988
     Copyright (C) 2007,2013 Christian Grothoff
Packit 875988
Packit 875988
     libmicrohttpd is free software; you can redistribute it and/or modify
Packit 875988
     it under the terms of the GNU General Public License as published
Packit 875988
     by the Free Software Foundation; either version 3, or (at your
Packit 875988
     option) any later version.
Packit 875988
Packit 875988
     libmicrohttpd is distributed in the hope that it will be useful, but
Packit 875988
     WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 875988
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 875988
     General Public License for more details.
Packit 875988
Packit 875988
     You should have received a copy of the GNU General Public License
Packit 875988
     along with libmicrohttpd; see the file COPYING.  If not, write to the
Packit 875988
     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Packit 875988
     Boston, MA 02110-1301, USA.
Packit 875988
*/
Packit 875988
Packit 875988
/**
Packit 875988
 * @file test_postprocessor.c
Packit 875988
 * @brief  Testcase for postprocessor
Packit 875988
 * @author Christian Grothoff
Packit 875988
 */
Packit 875988
Packit 875988
#include "platform.h"
Packit 875988
#include "microhttpd.h"
Packit 875988
#include "internal.h"
Packit 875988
#include <stdlib.h>
Packit 875988
#include <string.h>
Packit 875988
#include <stdio.h>
Packit 875988
#include "mhd_compat.h"
Packit 875988
Packit 875988
#ifndef WINDOWS
Packit 875988
#include <unistd.h>
Packit 875988
#endif
Packit 875988
Packit 875988
/**
Packit 875988
 * Array of values that the value checker "wants".
Packit 875988
 * Each series of checks should be terminated by
Packit 875988
 * five NULL-entries.
Packit 875988
 */
Packit 875988
const char *want[] = {
Packit 875988
#define URL_DATA "abc=def&x=5"
Packit 875988
#define URL_START 0
Packit 875988
  "abc", NULL, NULL, NULL, "def",
Packit 875988
  "x", NULL, NULL, NULL, "5",
Packit 875988
#define URL_END (URL_START + 10)
Packit 875988
  NULL, NULL, NULL, NULL, NULL,
Packit 875988
#define FORM_DATA "--AaB03x\r\ncontent-disposition: form-data; name=\"field1\"\r\n\r\nJoe Blow\r\n--AaB03x\r\ncontent-disposition: form-data; name=\"pics\"; filename=\"file1.txt\"\r\nContent-Type: text/plain\r\nContent-Transfer-Encoding: binary\r\n\r\nfiledata\r\n--AaB03x--\r\n"
Packit 875988
#define FORM_START (URL_END + 5)
Packit 875988
  "field1", NULL, NULL, NULL, "Joe Blow",
Packit 875988
  "pics", "file1.txt", "text/plain", "binary", "filedata",
Packit 875988
#define FORM_END (FORM_START + 10)
Packit 875988
  NULL, NULL, NULL, NULL, NULL,
Packit 875988
#define FORM_NESTED_DATA "--AaB03x\r\ncontent-disposition: form-data; name=\"field1\"\r\n\r\nJane Blow\r\n--AaB03x\r\ncontent-disposition: form-data; name=\"pics\"\r\nContent-type: multipart/mixed, boundary=BbC04y\r\n\r\n--BbC04y\r\nContent-disposition: attachment; filename=\"file1.txt\"\r\nContent-Type: text/plain\r\n\r\nfiledata1\r\n--BbC04y\r\nContent-disposition: attachment; filename=\"file2.gif\"\r\nContent-type: image/gif\r\nContent-Transfer-Encoding: binary\r\n\r\nfiledata2\r\n--BbC04y--\r\n--AaB03x--"
Packit 875988
#define FORM_NESTED_START (FORM_END + 5)
Packit 875988
  "field1", NULL, NULL, NULL, "Jane Blow",
Packit 875988
  "pics", "file1.txt", "text/plain", NULL, "filedata1",
Packit 875988
  "pics", "file2.gif", "image/gif", "binary", "filedata2",
Packit 875988
#define FORM_NESTED_END (FORM_NESTED_START + 15)
Packit 875988
  NULL, NULL, NULL, NULL, NULL,
Packit 875988
#define URL_EMPTY_VALUE_DATA "key1=value1&key2=&key3="
Packit 875988
#define URL_EMPTY_VALUE_START (FORM_NESTED_END + 5)
Packit 875988
  "key1", NULL, NULL, NULL, "value1",
Packit 875988
  "key2", NULL, NULL, NULL, "",
Packit 875988
  "key3", NULL, NULL, NULL, "",
Packit 875988
#define URL_EMPTY_VALUE_END (URL_EMPTY_VALUE_START + 15)
Packit 875988
  NULL, NULL, NULL, NULL, NULL
Packit 875988
};
Packit 875988
Packit 875988
static int
Packit 875988
mismatch (const char *a, const char *b)
Packit 875988
{
Packit 875988
  if (a == b)
Packit 875988
    return 0;
Packit 875988
  if ((a == NULL) || (b == NULL))
Packit 875988
    return 1;
Packit 875988
  return 0 != strcmp (a, b);
Packit 875988
}
Packit 875988
Packit 875988
static int
Packit 875988
value_checker (void *cls,
Packit 875988
               enum MHD_ValueKind kind,
Packit 875988
               const char *key,
Packit 875988
               const char *filename,
Packit 875988
               const char *content_type,
Packit 875988
               const char *transfer_encoding,
Packit 875988
               const char *data, uint64_t off, size_t size)
Packit 875988
{
Packit 875988
  int *want_off = cls;
Packit 875988
  int idx = *want_off;
Packit 875988
  (void)kind;  /* Unused. Silent compiler warning. */
Packit 875988
Packit 875988
Packit 875988
#if 0
Packit 875988
  fprintf (stderr,
Packit 875988
           "VC: `%s' `%s' `%s' `%s' `%.*s'\n",
Packit 875988
           key, filename, content_type, transfer_encoding,
Packit 875988
           (int) size,
Packit 875988
           data);
Packit 875988
#endif
Packit 875988
  if ( (0 != off) && (0 == size) )
Packit 875988
    return MHD_YES;
Packit 875988
  if ((idx < 0) ||
Packit 875988
      (want[idx] == NULL) ||
Packit 875988
      (0 != strcmp (key, want[idx])) ||
Packit 875988
      (mismatch (filename, want[idx + 1])) ||
Packit 875988
      (mismatch (content_type, want[idx + 2])) ||
Packit 875988
      (mismatch (transfer_encoding, want[idx + 3])) ||
Packit 875988
      (0 != memcmp (data, &want[idx + 4][off], size)))
Packit 875988
    {
Packit 875988
      *want_off = -1;
Packit 875988
      return MHD_NO;
Packit 875988
    }
Packit 875988
  if (off + size == strlen (want[idx + 4]))
Packit 875988
    *want_off = idx + 5;
Packit 875988
  return MHD_YES;
Packit 875988
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
static int
Packit 875988
test_urlencoding (void)
Packit 875988
{
Packit 875988
  struct MHD_Connection connection;
Packit 875988
  struct MHD_HTTP_Header header;
Packit 875988
  struct MHD_PostProcessor *pp;
Packit 875988
  unsigned int want_off = URL_START;
Packit 875988
  size_t i;
Packit 875988
  size_t delta;
Packit 875988
  size_t size;
Packit 875988
Packit 875988
  memset (&connection, 0, sizeof (struct MHD_Connection));
Packit 875988
  memset (&header, 0, sizeof (struct MHD_HTTP_Header));
Packit 875988
  connection.headers_received = &header;
Packit 875988
  header.header = MHD_HTTP_HEADER_CONTENT_TYPE;
Packit 875988
  header.value = MHD_HTTP_POST_ENCODING_FORM_URLENCODED;
Packit 875988
  header.kind = MHD_HEADER_KIND;
Packit 875988
  pp = MHD_create_post_processor (&connection,
Packit 875988
                                  1024, &value_checker, &want_off);
Packit 875988
  i = 0;
Packit 875988
  size = strlen (URL_DATA);
Packit 875988
  while (i < size)
Packit 875988
    {
Packit 875988
      delta = 1 + MHD_random_ () % (size - i);
Packit 875988
      MHD_post_process (pp, &URL_DATA[i], delta);
Packit 875988
      i += delta;
Packit 875988
    }
Packit 875988
  MHD_destroy_post_processor (pp);
Packit 875988
  if (want_off != URL_END)
Packit 875988
    return 1;
Packit 875988
  return 0;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
static int
Packit 875988
test_multipart_garbage (void)
Packit 875988
{
Packit 875988
  struct MHD_Connection connection;
Packit 875988
  struct MHD_HTTP_Header header;
Packit 875988
  struct MHD_PostProcessor *pp;
Packit 875988
  unsigned int want_off;
Packit 875988
  size_t size = strlen (FORM_DATA);
Packit 875988
  size_t splitpoint;
Packit 875988
  char xdata[size + 3];
Packit 875988
Packit 875988
  /* fill in evil garbage at the beginning */
Packit 875988
  xdata[0] = '-';
Packit 875988
  xdata[1] = 'x';
Packit 875988
  xdata[2] = '\r';
Packit 875988
  memcpy (&xdata[3], FORM_DATA, size);
Packit 875988
Packit 875988
  size = strlen (FORM_DATA);
Packit 875988
  size += 3;
Packit 875988
  for (splitpoint = 1; splitpoint < size; splitpoint++)
Packit 875988
  {
Packit 875988
    want_off = FORM_START;
Packit 875988
    memset (&connection, 0, sizeof (struct MHD_Connection));
Packit 875988
    memset (&header, 0, sizeof (struct MHD_HTTP_Header));
Packit 875988
    connection.headers_received = &header;
Packit 875988
    header.header = MHD_HTTP_HEADER_CONTENT_TYPE;
Packit 875988
    header.value =
Packit 875988
      MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA ", boundary=AaB03x";
Packit 875988
    header.kind = MHD_HEADER_KIND;
Packit 875988
    pp = MHD_create_post_processor (&connection,
Packit 875988
                                    1024, &value_checker, &want_off);
Packit 875988
    MHD_post_process (pp, xdata, splitpoint);
Packit 875988
    MHD_post_process (pp, &xdata[splitpoint], size - splitpoint);
Packit 875988
    MHD_destroy_post_processor (pp);
Packit 875988
    if (want_off != FORM_END)
Packit 875988
      return (int) splitpoint;
Packit 875988
  }
Packit 875988
  return 0;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
static int
Packit 875988
test_multipart_splits (void)
Packit 875988
{
Packit 875988
  struct MHD_Connection connection;
Packit 875988
  struct MHD_HTTP_Header header;
Packit 875988
  struct MHD_PostProcessor *pp;
Packit 875988
  unsigned int want_off;
Packit 875988
  size_t size;
Packit 875988
  size_t splitpoint;
Packit 875988
Packit 875988
  size = strlen (FORM_DATA);
Packit 875988
  for (splitpoint = 1; splitpoint < size; splitpoint++)
Packit 875988
  {
Packit 875988
    want_off = FORM_START;
Packit 875988
    memset (&connection, 0, sizeof (struct MHD_Connection));
Packit 875988
    memset (&header, 0, sizeof (struct MHD_HTTP_Header));
Packit 875988
    connection.headers_received = &header;
Packit 875988
    header.header = MHD_HTTP_HEADER_CONTENT_TYPE;
Packit 875988
    header.value =
Packit 875988
      MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA ", boundary=AaB03x";
Packit 875988
    header.kind = MHD_HEADER_KIND;
Packit 875988
    pp = MHD_create_post_processor (&connection,
Packit 875988
                                    1024, &value_checker, &want_off);
Packit 875988
    MHD_post_process (pp, FORM_DATA, splitpoint);
Packit 875988
    MHD_post_process (pp, &FORM_DATA[splitpoint], size - splitpoint);
Packit 875988
    MHD_destroy_post_processor (pp);
Packit 875988
    if (want_off != FORM_END)
Packit 875988
      return (int) splitpoint;
Packit 875988
  }
Packit 875988
  return 0;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
static int
Packit 875988
test_multipart (void)
Packit 875988
{
Packit 875988
  struct MHD_Connection connection;
Packit 875988
  struct MHD_HTTP_Header header;
Packit 875988
  struct MHD_PostProcessor *pp;
Packit 875988
  unsigned int want_off = FORM_START;
Packit 875988
  size_t i;
Packit 875988
  size_t delta;
Packit 875988
  size_t size;
Packit 875988
Packit 875988
  memset (&connection, 0, sizeof (struct MHD_Connection));
Packit 875988
  memset (&header, 0, sizeof (struct MHD_HTTP_Header));
Packit 875988
  connection.headers_received = &header;
Packit 875988
  header.header = MHD_HTTP_HEADER_CONTENT_TYPE;
Packit 875988
  header.value =
Packit 875988
    MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA ", boundary=AaB03x";
Packit 875988
  header.kind = MHD_HEADER_KIND;
Packit 875988
  pp = MHD_create_post_processor (&connection,
Packit 875988
                                  1024, &value_checker, &want_off);
Packit 875988
  i = 0;
Packit 875988
  size = strlen (FORM_DATA);
Packit 875988
  while (i < size)
Packit 875988
    {
Packit 875988
      delta = 1 + MHD_random_ () % (size - i);
Packit 875988
      MHD_post_process (pp, &FORM_DATA[i], delta);
Packit 875988
      i += delta;
Packit 875988
    }
Packit 875988
  MHD_destroy_post_processor (pp);
Packit 875988
  if (want_off != FORM_END)
Packit 875988
    return 2;
Packit 875988
  return 0;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
static int
Packit 875988
test_nested_multipart (void)
Packit 875988
{
Packit 875988
  struct MHD_Connection connection;
Packit 875988
  struct MHD_HTTP_Header header;
Packit 875988
  struct MHD_PostProcessor *pp;
Packit 875988
  unsigned int want_off = FORM_NESTED_START;
Packit 875988
  size_t i;
Packit 875988
  size_t delta;
Packit 875988
  size_t size;
Packit 875988
Packit 875988
  memset (&connection, 0, sizeof (struct MHD_Connection));
Packit 875988
  memset (&header, 0, sizeof (struct MHD_HTTP_Header));
Packit 875988
  connection.headers_received = &header;
Packit 875988
  header.header = MHD_HTTP_HEADER_CONTENT_TYPE;
Packit 875988
  header.value =
Packit 875988
    MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA ", boundary=AaB03x";
Packit 875988
  header.kind = MHD_HEADER_KIND;
Packit 875988
  pp = MHD_create_post_processor (&connection,
Packit 875988
                                  1024, &value_checker, &want_off);
Packit 875988
  i = 0;
Packit 875988
  size = strlen (FORM_NESTED_DATA);
Packit 875988
  while (i < size)
Packit 875988
    {
Packit 875988
      delta = 1 + MHD_random_ () % (size - i);
Packit 875988
      MHD_post_process (pp, &FORM_NESTED_DATA[i], delta);
Packit 875988
      i += delta;
Packit 875988
    }
Packit 875988
  MHD_destroy_post_processor (pp);
Packit 875988
  if (want_off != FORM_NESTED_END)
Packit 875988
    return 4;
Packit 875988
  return 0;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
static int
Packit 875988
test_empty_value (void)
Packit 875988
{
Packit 875988
  struct MHD_Connection connection;
Packit 875988
  struct MHD_HTTP_Header header;
Packit 875988
  struct MHD_PostProcessor *pp;
Packit 875988
  unsigned int want_off = URL_EMPTY_VALUE_START;
Packit 875988
  size_t i;
Packit 875988
  size_t delta;
Packit 875988
  size_t size;
Packit 875988
Packit 875988
  memset (&connection, 0, sizeof (struct MHD_Connection));
Packit 875988
  memset (&header, 0, sizeof (struct MHD_HTTP_Header));
Packit 875988
  connection.headers_received = &header;
Packit 875988
  header.header = MHD_HTTP_HEADER_CONTENT_TYPE;
Packit 875988
  header.value = MHD_HTTP_POST_ENCODING_FORM_URLENCODED;
Packit 875988
  header.kind = MHD_HEADER_KIND;
Packit 875988
  pp = MHD_create_post_processor (&connection,
Packit 875988
                                  1024, &value_checker, &want_off);
Packit 875988
  i = 0;
Packit 875988
  size = strlen (URL_EMPTY_VALUE_DATA);
Packit 875988
  while (i < size)
Packit 875988
    {
Packit 875988
      delta = 1 + MHD_random_ () % (size - i);
Packit 875988
      MHD_post_process (pp, &URL_EMPTY_VALUE_DATA[i], delta);
Packit 875988
      i += delta;
Packit 875988
    }
Packit 875988
  MHD_destroy_post_processor (pp);
Packit 875988
  if (want_off != URL_EMPTY_VALUE_END)
Packit 875988
    return 8;
Packit 875988
  return 0;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
Packit 875988
Packit 875988
int
Packit 875988
main (int argc, char *const *argv)
Packit 875988
{
Packit 875988
  unsigned int errorCount = 0;
Packit 875988
  (void)argc; (void)argv;  /* Unused. Silent compiler warning. */
Packit 875988
Packit 875988
  errorCount += test_multipart_splits ();
Packit 875988
  errorCount += test_multipart_garbage ();
Packit 875988
  errorCount += test_urlencoding ();
Packit 875988
  errorCount += test_multipart ();
Packit 875988
  errorCount += test_nested_multipart ();
Packit 875988
  errorCount += test_empty_value ();
Packit 875988
  if (errorCount != 0)
Packit 875988
    fprintf (stderr, "Error (code: %u)\n", errorCount);
Packit 875988
  return errorCount != 0;       /* 0 == pass */
Packit 875988
}