Home | History | Annotate | Download | only in testcurl
      1 
      2 /*
      3      This file is part of libmicrohttpd
      4      Copyright (C) 2007 Christian Grothoff
      5 
      6      libmicrohttpd is free software; you can redistribute it and/or modify
      7      it under the terms of the GNU General Public License as published
      8      by the Free Software Foundation; either version 3, or (at your
      9      option) any later version.
     10 
     11      libmicrohttpd is distributed in the hope that it will be useful, but
     12      WITHOUT ANY WARRANTY; without even the implied warranty of
     13      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14      General Public License for more details.
     15 
     16      You should have received a copy of the GNU General Public License
     17      along with libmicrohttpd; see the file COPYING.  If not, write to the
     18      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
     19      Boston, MA 02111-1307, USA.
     20 */
     21 
     22 /**
     23  * @file test_parse_cookies.c
     24  * @brief  Testcase for HTTP cookie parsing
     25  * @author Christian Grothoff
     26  */
     27 
     28 #include "MHD_config.h"
     29 #include "platform.h"
     30 #include <curl/curl.h>
     31 #include <microhttpd.h>
     32 #include <stdlib.h>
     33 #include <string.h>
     34 #include <time.h>
     35 
     36 #ifndef WINDOWS
     37 #include <unistd.h>
     38 #endif
     39 
     40 static int oneone;
     41 
     42 struct CBC
     43 {
     44   char *buf;
     45   size_t pos;
     46   size_t size;
     47 };
     48 
     49 static size_t
     50 copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
     51 {
     52   struct CBC *cbc = ctx;
     53 
     54   if (cbc->pos + size * nmemb > cbc->size)
     55     return 0;                   /* overflow */
     56   memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
     57   cbc->pos += size * nmemb;
     58   return size * nmemb;
     59 }
     60 
     61 static int
     62 ahc_echo (void *cls,
     63           struct MHD_Connection *connection,
     64           const char *url,
     65           const char *method,
     66           const char *version,
     67           const char *upload_data, size_t *upload_data_size,
     68           void **unused)
     69 {
     70   static int ptr;
     71   const char *me = cls;
     72   struct MHD_Response *response;
     73   int ret;
     74   const char *hdr;
     75 
     76   if (0 != strcmp (me, method))
     77     return MHD_NO;              /* unexpected method */
     78   if (&ptr != *unused)
     79     {
     80       *unused = &ptr;
     81       return MHD_YES;
     82     }
     83   *unused = NULL;
     84   ret = 0;
     85 
     86   hdr = MHD_lookup_connection_value (connection, MHD_COOKIE_KIND, "name1");
     87   if ((hdr == NULL) || (0 != strcmp (hdr, "var1")))
     88     abort ();
     89   hdr = MHD_lookup_connection_value (connection, MHD_COOKIE_KIND, "name2");
     90   if ((hdr == NULL) || (0 != strcmp (hdr, "var2")))
     91     abort ();
     92   hdr = MHD_lookup_connection_value (connection, MHD_COOKIE_KIND, "name3");
     93   if ((hdr == NULL) || (0 != strcmp (hdr, "")))
     94     abort ();
     95   hdr = MHD_lookup_connection_value (connection, MHD_COOKIE_KIND, "name4");
     96   if ((hdr == NULL) || (0 != strcmp (hdr, "var4 with spaces")))
     97     abort ();
     98   response = MHD_create_response_from_buffer (strlen (url),
     99 					      (void *) url,
    100 					      MHD_RESPMEM_PERSISTENT);
    101   ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
    102   MHD_destroy_response (response);
    103   if (ret == MHD_NO)
    104     abort ();
    105   return ret;
    106 }
    107 
    108 static int
    109 testExternalGet ()
    110 {
    111   struct MHD_Daemon *d;
    112   CURL *c;
    113   char buf[2048];
    114   struct CBC cbc;
    115   CURLM *multi;
    116   CURLMcode mret;
    117   fd_set rs;
    118   fd_set ws;
    119   fd_set es;
    120   MHD_socket max;
    121   int running;
    122   struct CURLMsg *msg;
    123   time_t start;
    124   struct timeval tv;
    125 
    126   multi = NULL;
    127   cbc.buf = buf;
    128   cbc.size = 2048;
    129   cbc.pos = 0;
    130   d = MHD_start_daemon (MHD_USE_DEBUG,
    131                         21080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
    132   if (d == NULL)
    133     return 256;
    134   c = curl_easy_init ();
    135   curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1:21080/hello_world");
    136   curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
    137   curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
    138   curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
    139   /* note that the string below intentionally uses the
    140      various ways cookies can be specified to exercise the
    141      parser! Do not change! */
    142   curl_easy_setopt (c, CURLOPT_COOKIE,
    143                     "name1=var1; name2=var2,name3 ;name4=\"var4 with spaces\";");
    144   if (oneone)
    145     curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
    146   else
    147     curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
    148   curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
    149   curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
    150   /* NOTE: use of CONNECTTIMEOUT without also
    151      setting NOSIGNAL results in really weird
    152      crashes on my system! */
    153   curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
    154 
    155 
    156   multi = curl_multi_init ();
    157   if (multi == NULL)
    158     {
    159       curl_easy_cleanup (c);
    160       MHD_stop_daemon (d);
    161       return 512;
    162     }
    163   mret = curl_multi_add_handle (multi, c);
    164   if (mret != CURLM_OK)
    165     {
    166       curl_multi_cleanup (multi);
    167       curl_easy_cleanup (c);
    168       MHD_stop_daemon (d);
    169       return 1024;
    170     }
    171   start = time (NULL);
    172   while ((time (NULL) - start < 5) && (multi != NULL))
    173     {
    174       max = 0;
    175       FD_ZERO (&rs);
    176       FD_ZERO (&ws);
    177       FD_ZERO (&es);
    178       curl_multi_perform (multi, &running);
    179       mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
    180       if (mret != CURLM_OK)
    181         {
    182           curl_multi_remove_handle (multi, c);
    183           curl_multi_cleanup (multi);
    184           curl_easy_cleanup (c);
    185           MHD_stop_daemon (d);
    186           return 2048;
    187         }
    188       if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
    189         {
    190           curl_multi_remove_handle (multi, c);
    191           curl_multi_cleanup (multi);
    192           curl_easy_cleanup (c);
    193           MHD_stop_daemon (d);
    194           return 4096;
    195         }
    196       tv.tv_sec = 0;
    197       tv.tv_usec = 1000;
    198       select (max + 1, &rs, &ws, &es, &tv);
    199       curl_multi_perform (multi, &running);
    200       if (running == 0)
    201         {
    202           msg = curl_multi_info_read (multi, &running);
    203           if (msg == NULL)
    204             break;
    205           if (msg->msg == CURLMSG_DONE)
    206             {
    207               if (msg->data.result != CURLE_OK)
    208                 printf ("%s failed at %s:%d: `%s'\n",
    209                         "curl_multi_perform",
    210                         __FILE__,
    211                         __LINE__, curl_easy_strerror (msg->data.result));
    212               curl_multi_remove_handle (multi, c);
    213               curl_multi_cleanup (multi);
    214               curl_easy_cleanup (c);
    215               c = NULL;
    216               multi = NULL;
    217             }
    218         }
    219       MHD_run (d);
    220     }
    221   if (multi != NULL)
    222     {
    223       curl_multi_remove_handle (multi, c);
    224       curl_easy_cleanup (c);
    225       curl_multi_cleanup (multi);
    226     }
    227   MHD_stop_daemon (d);
    228   if (cbc.pos != strlen ("/hello_world"))
    229     return 8192;
    230   if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
    231     return 16384;
    232   return 0;
    233 }
    234 
    235 
    236 int
    237 main (int argc, char *const *argv)
    238 {
    239   unsigned int errorCount = 0;
    240 
    241   oneone = (NULL != strrchr (argv[0], (int) '/')) ?
    242     (NULL != strstr (strrchr (argv[0], (int) '/'), "11")) : 0;
    243   if (0 != curl_global_init (CURL_GLOBAL_WIN32))
    244     return 2;
    245   errorCount += testExternalGet ();
    246   if (errorCount != 0)
    247     fprintf (stderr, "Error (code: %u)\n", errorCount);
    248   curl_global_cleanup ();
    249   return errorCount != 0;       /* 0 == pass */
    250 }
    251