00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "klone_conf.h"
00012 #include <stdlib.h>
00013 #include <string.h>
00014 #include <ctype.h>
00015 #include <sys/types.h>
00016 #include <sys/stat.h>
00017 #include <u/libu.h>
00018 #include <klone/request.h>
00019 #include <klone/utils.h>
00020 #include <klone/io.h>
00021 #include <klone/ioprv.h>
00022 #include <klone/http.h>
00023 #include <klone/addr.h>
00024 #include <klone/vars.h>
00025 #include <klone/timer.h>
00026
00027
00028 struct request_s
00029 {
00030 http_t *http;
00031 header_t *header;
00032 io_t *io;
00033 int method;
00034 char *cli_rq;
00035 char *uri;
00036 char *protocol;
00037 char *path_info;
00038 char *query;
00039 char *filename;
00040 char *resolved_path_info;
00041 char *resolved_filename;
00042 vars_t *args;
00043 vars_t *cookies;
00044 vars_t *uploads;
00045 char *content_type;
00046 char *content_encoding;
00047 size_t content_length;
00048 time_t if_modified_since;
00049 addr_t local_addr, peer_addr;
00050 int cgi;
00051 size_t idle_timeout;
00052 size_t post_timeout;
00053 size_t post_maxsize;
00054 };
00055
00056 typedef struct upload_info_s
00057 {
00058 char mime_type[MIME_TYPE_BUFSZ];
00059 char filename[U_FILENAME_MAX];
00060 size_t size;
00061 } upload_info_t;
00062
00063 enum {
00064 REQUEST_DEFAULT_IDLE_TIMEOUT = 10,
00065 REQUEST_DEFAULT_POST_TIMEOUT = 600,
00066 REQUEST_DEFAULT_POST_MAXSIZE = 5*1024000,
00067 };
00068
00069
00070 #define REQUEST_SET_STRING_FIELD(lval, rval) \
00071 do { \
00072 U_FREE(lval); \
00073 if(rval) \
00074 { \
00075 lval = u_strdup(rval); \
00076 dbg_err_if(lval == NULL); \
00077 } \
00078 } while(0)
00079
00080
00081 int request_is_encoding_accepted(request_t *rq, const char *encoding)
00082 {
00083 char *pp, *tok, *src, *buf = NULL;
00084 const char *accept_encoding;
00085 int rc = 0;
00086
00087 dbg_err_if (rq == NULL);
00088 dbg_err_if (encoding == NULL);
00089
00090 accept_encoding = header_get_field_value(rq->header, "Accept-Encoding");
00091 if(accept_encoding)
00092 {
00093
00094 buf = u_strdup(accept_encoding);
00095 dbg_err_if(buf == NULL);
00096
00097
00098 for(src = buf; (tok = strtok_r(src, " ,", &pp)) != NULL; src = NULL)
00099 {
00100 if(strcasecmp(tok, encoding) == 0)
00101 {
00102 rc++;
00103 break;
00104 }
00105 }
00106
00107 U_FREE(buf);
00108 }
00109
00110 return rc;
00111 err:
00112 U_FREE(buf);
00113 return 0;
00114 }
00115
00131 io_t *request_io(request_t *rq)
00132 {
00133 dbg_return_if (rq == NULL, NULL);
00134
00135 return rq->io;
00136 }
00137
00149 vars_t *request_get_cookies(request_t *rq)
00150 {
00151 dbg_return_if (rq == NULL, NULL);
00152
00153 return rq->cookies;
00154 }
00155
00167 const char *request_get_cookie(request_t *rq, const char *name)
00168 {
00169 var_t *v;
00170
00171 dbg_return_if (rq == NULL, NULL);
00172 dbg_return_if (name == NULL, NULL);
00173
00174 v = vars_get(rq->cookies, name);
00175
00176 return v ? var_get_value(v): NULL;
00177 }
00178
00189 vars_t *request_get_args(request_t *rq)
00190 {
00191 dbg_return_if (rq == NULL, NULL);
00192
00193 return rq->args;
00194 }
00195
00209 const char *request_get_arg(request_t *rq, const char *name)
00210 {
00211 var_t *v;
00212
00213 dbg_return_if (rq == NULL, NULL);
00214 dbg_return_if (name == NULL, NULL);
00215
00216 v = vars_get(rq->args, name);
00217
00218 return v ? var_get_value(v): NULL;
00219 }
00220
00221 int request_set_field(request_t *rq, const char *name, const char *value)
00222 {
00223 dbg_return_if (rq == NULL, ~0);
00224 dbg_return_if (name == NULL, ~0);
00225 dbg_return_if (value == NULL, ~0);
00226
00227 return header_set_field(rq->header, name, value);
00228 }
00229
00240 const char *request_get_uri(request_t *rq)
00241 {
00242 dbg_return_if (rq == NULL, NULL);
00243
00244 return rq->uri;
00245 }
00246
00257 const char *request_get_filename(request_t *rq)
00258 {
00259 dbg_return_if (rq == NULL, NULL);
00260
00261 return rq->filename;
00262 }
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275 int request_set_filename(request_t *rq, const char *filename)
00276 {
00277 dbg_err_if (rq == NULL);
00278 dbg_err_if (filename == NULL);
00279
00280 REQUEST_SET_STRING_FIELD(rq->filename, filename);
00281
00282 return 0;
00283 err:
00284 return ~0;
00285 }
00286
00297 const char *request_get_query_string(request_t *rq)
00298 {
00299 dbg_return_if (rq == NULL, NULL);
00300
00301 return rq->query;
00302 }
00303
00314 const char *request_get_path_info(request_t *rq)
00315 {
00316 dbg_return_if (rq == NULL, NULL);
00317
00318 return rq->path_info;
00319 }
00320
00321
00322 static int request_parse_ims(request_t *rq)
00323 {
00324 const char *ims;
00325
00326 dbg_err_if (rq == NULL);
00327
00328 rq->if_modified_since = 0;
00329
00330 ims = header_get_field_value(rq->header, "If-Modified-Since");
00331 if(ims)
00332 dbg_err_if(u_httpdate_to_tt(ims, &rq->if_modified_since));
00333
00334 err:
00335 return 0;
00336 }
00337
00348 time_t request_get_if_modified_since(request_t *rq)
00349 {
00350 dbg_return_if (rq == NULL, (time_t) -1);
00351
00352 return rq->if_modified_since;
00353 }
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366 int request_set_resolved_filename(request_t *rq, const char *resolved_fn)
00367 {
00368 dbg_err_if (rq == NULL);
00369 dbg_err_if (resolved_fn == NULL);
00370
00371 REQUEST_SET_STRING_FIELD(rq->resolved_filename, resolved_fn);
00372
00373 return 0;
00374 err:
00375 return ~0;
00376 }
00377
00388 http_t* request_get_http(request_t *rq)
00389 {
00390 dbg_return_if (rq == NULL, NULL);
00391
00392 return rq->http;
00393 }
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406 int request_bind(request_t *rq, io_t *in)
00407 {
00408 dbg_return_if (rq == NULL, ~0);
00409 dbg_return_if (in == NULL, ~0);
00410
00411 rq->io = in;
00412
00413 return 0;
00414 }
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427 int request_set_query_string(request_t *rq, const char *query)
00428 {
00429 dbg_err_if (rq == NULL);
00430 dbg_err_if (query == NULL);
00431
00432 REQUEST_SET_STRING_FIELD(rq->query, query);
00433
00434 return 0;
00435 err:
00436 return ~0;
00437 }
00438
00439 void request_clear_uri(request_t *rq)
00440 {
00441 U_FREE(rq->uri);
00442 U_FREE(rq->protocol);
00443 U_FREE(rq->path_info);
00444 U_FREE(rq->query);
00445 U_FREE(rq->filename);
00446 U_FREE(rq->resolved_path_info);
00447 U_FREE(rq->resolved_filename);
00448 U_FREE(rq->content_type);
00449 U_FREE(rq->content_encoding);
00450 }
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463 int request_set_path_info(request_t *rq, const char *path_info)
00464 {
00465 dbg_err_if (rq == NULL);
00466 dbg_err_if (path_info == NULL);
00467
00468 REQUEST_SET_STRING_FIELD(rq->path_info, path_info);
00469
00470 return 0;
00471 err:
00472 return ~0;
00473 }
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486 int request_set_resolved_path_info(request_t *rq, const char *resolved_pi)
00487 {
00488 dbg_err_if (rq == NULL);
00489 dbg_err_if (resolved_pi == NULL);
00490
00491 REQUEST_SET_STRING_FIELD(rq->resolved_path_info, resolved_pi);
00492
00493 return 0;
00494 err:
00495 return ~0;
00496 }
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511 int request_set_uri(request_t *rq, const char *uri,
00512 int (*is_valid_uri)(void*, const char *, size_t),
00513 void* arg)
00514 {
00515 enum { REQUEST_URI_MAX_LENGTH = 4095 };
00516 char *p, *fn, *pi, *cp = NULL;
00517 size_t uri_len = strlen(uri);
00518
00519 dbg_err_if (rq == NULL);
00520 dbg_err_if (uri == NULL);
00521
00522
00523
00524 request_clear_uri(rq);
00525
00526
00527
00528 warn_err_ifm(uri_len > REQUEST_URI_MAX_LENGTH, "Request URI too long");
00529
00530 REQUEST_SET_STRING_FIELD(rq->uri, uri);
00531
00532
00533 if((p = strchr(uri, '?')) != NULL)
00534 dbg_err_if(request_set_query_string(rq, ++p));
00535
00536 cp = (char*)u_malloc(uri_len + 1);
00537 dbg_err_if(cp == NULL);
00538
00539
00540 dbg_err_if(u_urlncpy(cp, rq->uri, uri_len, URLCPY_DECODE) <= 0);
00541
00542 if((p = strchr(cp, '?')) != NULL)
00543 *p++ = 0;
00544
00545
00546 dbg_err_if(u_uri_normalize(cp));
00547
00548
00549 dbg_err_if(request_set_filename(rq, cp));
00550
00551
00552 fn = cp;
00553 pi = fn + strlen(fn);
00554 for(;;)
00555 {
00556 if(is_valid_uri == NULL || is_valid_uri(arg, fn, pi - fn))
00557 {
00558 dbg_err_if(request_set_filename(rq, fn));
00559 rq->filename[pi-fn] = 0;
00560 if(strlen(pi))
00561 dbg_err_if(request_set_path_info(rq, pi));
00562 break;
00563 } else {
00564 if((p = u_strnrchr(fn, '/', pi - fn)) == NULL)
00565 break;
00566 pi = p;
00567 }
00568 }
00569
00570 U_FREE(cp);
00571
00572 return 0;
00573 err:
00574 U_FREE(cp);
00575 return ~0;
00576 }
00577
00578 static int request_set_proto(request_t *rq, const char *proto)
00579 {
00580 dbg_err_if (rq == NULL);
00581 dbg_err_if (proto == NULL);
00582
00583
00584 if(strncasecmp(proto, "http", 4))
00585 return ~0;
00586
00587 REQUEST_SET_STRING_FIELD(rq->protocol, proto);
00588
00589 return 0;
00590 err:
00591 return ~0;
00592 }
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605 int request_set_client_request(request_t *rq, const char *ln)
00606 {
00607 char *p;
00608 dbg_err_if(rq == NULL);
00609 dbg_err_if(ln == NULL);
00610
00611 rq->cli_rq = u_strdup(ln);
00612 dbg_err_if(rq->cli_rq == NULL);
00613
00614
00615 for(p = rq->cli_rq; *p && (*p != '\r' && *p != '\n'); ++p)
00616 continue;
00617 *p = 0;
00618
00619 return 0;
00620 err:
00621 return ~0;
00622 }
00623
00634 const char *request_get_client_request(request_t *rq)
00635 {
00636 return rq->cli_rq;
00637 }
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647 int request_set_method(request_t *rq, const char *method)
00648 {
00649 dbg_return_if (rq == NULL, ~0);
00650 dbg_return_if (method == NULL, ~0);
00651
00652 if(!strcasecmp(method, "get"))
00653 rq->method = HM_GET;
00654 else if(!strcasecmp(method, "head"))
00655 rq->method = HM_HEAD;
00656 else if(!strcasecmp(method, "post"))
00657 rq->method = HM_POST;
00658 else {
00659
00660 rq->method = HM_UNKNOWN;
00661 return ~0;
00662 }
00663
00664 return 0;
00665 }
00666
00667 static int request_set_content_length(request_t *rq)
00668 {
00669 const char *clen;
00670 size_t len;
00671
00672 dbg_err_if (rq == NULL);
00673
00674 clen = header_get_field_value(rq->header, "Content-Length");
00675 dbg_err_if(clen == NULL || (len = atoi(clen)) < 0);
00676
00677 rq->content_length = len;
00678
00679 return 0;
00680 err:
00681 return ~0;
00682 }
00683
00684 static int request_parse_cookie(request_t *rq, field_t *field)
00685 {
00686 enum { BUFSZ = 4096 };
00687 char *pp, *tok, *src, buf[BUFSZ];
00688
00689 dbg_err_if (rq == NULL);
00690 dbg_err_if (field == NULL);
00691
00692 dbg_err_if(field_get_value(field) == NULL);
00693
00694
00695 strncpy(buf, field_get_value(field), BUFSZ);
00696
00697
00698 for(src = buf; (tok = strtok_r(src, " ;", &pp)) != NULL; src = NULL)
00699 dbg_if(vars_add_urlvar(rq->cookies, tok, NULL));
00700
00701 return 0;
00702 err:
00703 return ~0;
00704 }
00705
00706 static int request_parse_cookies(request_t *rq)
00707 {
00708 field_t *f;
00709 size_t i, count;
00710
00711 dbg_err_if (rq == NULL);
00712
00713 count = header_field_count(rq->header);
00714 for(i = 0; i < count; ++i)
00715 {
00716 f = header_get_fieldn(rq->header, i);
00717 dbg_err_if(f == NULL);
00718 if(strcasecmp(field_get_name(f), "cookie") == 0)
00719 dbg_err_if(request_parse_cookie(rq, f));
00720 }
00721
00722 return 0;
00723 err:
00724 return ~0;
00725 }
00726
00727 static int request_parse_query_args(request_t *rq)
00728 {
00729 char *pp, *tok, *src, *query = NULL;
00730
00731 dbg_err_if (rq == NULL);
00732
00733 if(!rq->query)
00734 return 0;
00735
00736
00737 query = u_strdup(rq->query);
00738 dbg_err_if(query == NULL);
00739
00740
00741 for(src = query; (tok = strtok_r(src, "&", &pp)) != NULL; src = NULL)
00742 {
00743
00744 dbg_if(vars_add_urlvar(rq->args, tok, NULL));
00745 }
00746
00747 U_FREE(query);
00748
00749 return 0;
00750 err:
00751 U_FREE(query);
00752 return ~0;
00753 }
00754
00755
00756 void request_set_cgi(request_t *rq, int cgi)
00757 {
00758 rq->cgi = cgi;
00759 return;
00760 }
00761
00773 ssize_t request_get_content_length(request_t *rq)
00774 {
00775 dbg_return_if (rq == NULL, -1);
00776
00777 return (ssize_t) rq->content_length;
00778 }
00779
00780 static int match_content_type(header_t *h, const char *mime_type)
00781 {
00782 const char *ct;
00783
00784 dbg_return_if (h == NULL, 0);
00785 dbg_return_if (mime_type == NULL, 0);
00786
00787 ct = header_get_field_value(h, "Content-Type");
00788 if(ct == NULL || strncasecmp(ct, mime_type, strlen(mime_type)))
00789 return 0;
00790
00791 return 1;
00792 }
00793
00794 static int request_is_multipart_formdata(request_t *rq)
00795 {
00796 return match_content_type(rq->header, "multipart/form-data");
00797 }
00798
00799 static int request_parse_urlencoded_data(request_t *rq)
00800 {
00801 ssize_t qsz, len;
00802
00803 dbg_err_if (rq == NULL);
00804
00805 len = rq->content_length;
00806
00807 qsz = (rq->query ? strlen(rq->query) : 0);
00808
00809
00810 rq->query = u_realloc(rq->query, len + qsz + 2);
00811 dbg_err_if(rq->query == NULL);
00812
00813
00814
00815 rq->query[qsz] = 0;
00816 if(qsz)
00817 {
00818 strcat(rq->query, "&");
00819 ++qsz;
00820 }
00821
00822
00823 dbg_err_if(io_read(rq->io, rq->query + qsz, len) != len);
00824
00825
00826 rq->query[qsz + len] = 0;
00827
00828
00829 dbg_err_if(request_parse_query_args(rq));
00830
00831 return 0;
00832 err:
00833 return ~0;
00834 }
00835
00836
00837
00838 static int request_get_fieldparam(request_t *rq, const char *field_name,
00839 const char *param_name, char *buf, size_t size)
00840 {
00841 const char *param_value, *field_value, *p;
00842 size_t pv_len;
00843
00844 dbg_err_if (rq == NULL);
00845 dbg_err_if (field_name == NULL);
00846 dbg_err_if (param_name == NULL);
00847 dbg_err_if (buf == NULL);
00848 dbg_err_if (size == 0);
00849
00850 field_value = header_get_field_value(rq->header, field_name);
00851 dbg_err_if(field_value == NULL);
00852
00853
00854 param_value = u_stristr(field_value, param_name);
00855 dbg_err_if(param_value == NULL);
00856
00857
00858 param_value += strlen(param_name);
00859
00860
00861 dbg_err_if(*param_value++ != '=');
00862
00863
00864 for(p = param_value; ;++p)
00865 if(*p == '\0' || *p == ';' || isspace(*p))
00866 break;
00867
00868
00869 pv_len = p - param_value;
00870
00871
00872 dbg_err_if(pv_len > size - 1);
00873
00874
00875 strncpy(buf, param_value, pv_len);
00876 buf[MIN(pv_len, size - 1)] = 0;
00877
00878 return 0;
00879 err:
00880 return ~0;
00881 }
00882
00883 static int is_multipart_mixed(header_t *h)
00884 {
00885 return match_content_type(h, "multipart/mixed");
00886 }
00887
00888 static int is_encoded(header_t *h)
00889 {
00890 const char *cte;
00891
00892 dbg_return_if (h == NULL, 0);
00893
00894 if((cte = header_get_field_value(h, "Content-Transfer-Encoding")) == NULL)
00895 return 0;
00896
00897 if(strcasecmp(cte, "binary") == 0)
00898 return 0;
00899
00900 return 1;
00901 }
00902
00903 static inline int is_nl(char c)
00904 {
00905 return (c == '\n' || c == '\r' ? c : 0);
00906 }
00907
00908 static inline int is_quote(char c)
00909 {
00910 return (c == '"' || c == '\'' ? c : 0);
00911 }
00912
00913 static int parse_content_disposition(header_t *h, char *name, char *filename,
00914 size_t prmsz)
00915 {
00916 enum { BUFSZ = 512 };
00917 char *pp, *tok, *src, buf[BUFSZ];
00918 size_t n_len, fn_len;
00919 const char *cd;
00920 int q;
00921
00922 dbg_err_if (h == NULL);
00923 dbg_err_if (name == NULL);
00924 dbg_err_if (filename == NULL);
00925 dbg_err_if (prmsz == 0);
00926
00927 cd = header_get_field_value(h, "Content-Disposition");
00928 dbg_err_if(cd == NULL);
00929
00930 dbg_err_if(strlen(cd) >= BUFSZ);
00931
00932
00933 dbg_err_if(strncmp(cd, "form-data", strlen("form-data")));
00934
00935 name[0] = filename[0] = 0;
00936
00937
00938 strncpy(buf, cd, BUFSZ);
00939
00940
00941 n_len = strlen("name=");
00942 fn_len = strlen("filename=");
00943
00944
00945 for(src = buf; (tok = strtok_r(src, " ;", &pp)) != NULL; src = NULL)
00946 {
00947 if(strncmp(tok, "form-data", strlen("form-data")) == 0)
00948 continue;
00949 else if(strncmp(tok, "name=", n_len) == 0) {
00950
00951 tok += n_len;
00952
00953
00954 if((q = is_quote(tok[0])) != 0)
00955 ++tok;
00956 if(strlen(tok) && tok[strlen(tok) - 1] == q)
00957 tok[strlen(tok) - 1] = 0;
00958
00959 strncpy(name, tok, prmsz);
00960 } else if(strncmp(tok, "filename=", fn_len) == 0) {
00961
00962 tok += fn_len;
00963
00964
00965 if((q = is_quote(tok[0])) != 0)
00966 ++tok;
00967 if(strlen(tok) && tok[strlen(tok) - 1] == q)
00968 tok[strlen(tok) - 1] = 0;
00969
00970 strncpy(filename, tok, prmsz);
00971 }
00972
00973 }
00974
00975 return 0;
00976 err:
00977 return ~0;
00978 }
00979
00980
00981
00982
00983
00984
00985
00986
00987 static ssize_t read_until(io_t *io, const char *stop_at, char *obuf,
00988 size_t size, int *found)
00989 {
00990
00991
00992
00993 #define SETUP_BUF_ACCESS_AT(idx) \
00994 if(idx >= wtot) { \
00995 if(idx >= size) \
00996 return wtot; \
00997 \
00998 \
00999 dbg_err_if((rc = io_read(io, wbuf, idx + 1 - wtot)) < 0); \
01000 if(rc == 0 || rc < idx + 1 - wtot) \
01001 return wtot + rc; \
01002 wbuf += rc; \
01003 wtot += rc; \
01004 }
01005
01006 int sa_len = strlen(stop_at);
01007 int i, t, shift[256], rc;
01008 unsigned char c;
01009 size_t wtot = 0;
01010 char *wbuf = obuf;
01011
01012 dbg_err_if (io == NULL);
01013 dbg_err_if (stop_at == NULL);
01014 dbg_err_if (obuf == NULL);
01015
01016 dbg_err_if (found == NULL);
01017
01018 for(i = 0; i < 256; ++i)
01019 shift[i] = sa_len;
01020
01021 for(i = 0; i < sa_len; ++i)
01022 shift[ stop_at[i] ] = sa_len - i - 1;
01023
01024 *found = 0;
01025
01026 for(i = t = sa_len-1; t >= 0; --i, --t)
01027 {
01028 SETUP_BUF_ACCESS_AT(i);
01029
01030 while((c = obuf[i]) != stop_at[t])
01031 {
01032 i += MAX(sa_len - t, shift[c]);
01033
01034 SETUP_BUF_ACCESS_AT(i);
01035
01036 t = sa_len - 1;
01037 }
01038 }
01039
01040 *found = 1;
01041
01042
01043 return wtot;
01044 err:
01045 return -1;
01046 }
01047
01048
01067 vars_t *request_get_uploads(request_t *rq)
01068 {
01069 return rq->uploads;
01070 }
01071
01072
01073
01074
01075
01076
01077
01078
01079 static int request_add_uploaded_file(request_t *rq, const char *name,
01080 const char *filename, const char *tmp_filename, const char *mime_type)
01081 {
01082 struct stat st;
01083 var_t *v = NULL;
01084 upload_info_t *info = NULL;
01085
01086 dbg_err_if (rq == NULL);
01087 dbg_err_if (name == NULL);
01088
01089 dbg_err_if (tmp_filename == NULL);
01090
01091
01092 dbg_err_sif (stat(tmp_filename, &st) < 0);
01093
01094
01095 dbg_err_if(var_create(name, tmp_filename, &v));
01096
01097
01098 dbg_err_if((info = u_zalloc(sizeof(upload_info_t))) == NULL);
01099
01100
01101 info->size = st.st_size;
01102 if(mime_type)
01103 snprintf(info->mime_type, MIME_TYPE_BUFSZ, "%s", mime_type);
01104 else
01105 info->mime_type[0] = 0;
01106
01107 if(filename)
01108 snprintf(info->filename, U_FILENAME_MAX, "%s", filename);
01109
01110
01111 var_set_opaque(v, info);
01112 info = NULL;
01113
01114
01115 dbg_err_if(vars_add(rq->uploads, v));
01116
01117 return 0;
01118 err:
01119 if(info)
01120 U_FREE(info);
01121 if(v)
01122 var_free(v);
01123 return ~0;
01124 }
01125
01126 static int request_get_uploaded_filev(request_t *rq, var_t *v,
01127 char local_filename[U_FILENAME_MAX], char client_filename[U_FILENAME_MAX],
01128 char mime_type[MIME_TYPE_BUFSZ], size_t *file_size)
01129 {
01130 upload_info_t *info;
01131 const char *tmp_fqn;
01132
01133 dbg_err_if (rq == NULL);
01134 dbg_err_if (v == NULL);
01135 dbg_err_if (local_filename == NULL);
01136 dbg_err_if (client_filename == NULL);
01137 dbg_err_if (mime_type == NULL);
01138 dbg_err_if (file_size == NULL);
01139
01140 info = var_get_opaque(v);
01141 dbg_err_if(info == NULL);
01142
01143 tmp_fqn = var_get_value(v);
01144 dbg_err_if(tmp_fqn == NULL);
01145
01146
01147 strncpy(local_filename, tmp_fqn, U_FILENAME_MAX);
01148 strncpy(mime_type, info->mime_type, MIME_TYPE_BUFSZ);
01149 strncpy(client_filename, info->filename, U_FILENAME_MAX);
01150 *file_size = info->size;
01151
01152 return 0;
01153 err:
01154 return ~0;
01155 }
01156
01179 int request_get_uploaded_file(request_t *rq, const char *name, size_t idx,
01180 char local_filename[U_FILENAME_MAX], char client_filename[U_FILENAME_MAX],
01181 char mime_type[MIME_TYPE_BUFSZ], size_t *file_size)
01182 {
01183 var_t *v;
01184 upload_info_t *info;
01185 const char *tmp_fqn;
01186
01187 dbg_err_if (rq == NULL);
01188 dbg_err_if (name == NULL);
01189 dbg_err_if (idx >= vars_count(rq->uploads));
01190 dbg_err_if (local_filename == NULL);
01191 dbg_err_if (client_filename == NULL);
01192 dbg_err_if (mime_type == NULL);
01193 dbg_err_if (file_size == NULL);
01194
01195 v = vars_geti(rq->uploads, name, idx);
01196 dbg_err_if(v == NULL);
01197
01198 return request_get_uploaded_filev(rq, v, local_filename, client_filename,
01199 mime_type, file_size);
01200 err:
01201 return ~0;
01202 }
01203
01204 static int request_parse_multipart_chunk(request_t *rq, io_t *io,
01205 const char *boundary, int *eof)
01206 {
01207 enum { PRMSZ = 512, BUFSZ = 4096 };
01208 header_t *h = NULL;
01209 io_t *tmpio = NULL;
01210 var_t *v = NULL;
01211 char name[PRMSZ], filename[PRMSZ], buf[BUFSZ];
01212 size_t bound_len, len;
01213 int found;
01214 ssize_t rc;
01215
01216
01217 dbg_err_if(header_create(&h));
01218
01219
01220 dbg_err_if(header_load(h, io));
01221
01222 warn_err_ifm(is_multipart_mixed(h),
01223 "multipart/mixed content is not supported yet");
01224
01225
01226 warn_err_ifm(is_encoded(h),
01227 "encoded file upload is not supported");
01228
01229 dbg_err_if(parse_content_disposition(h, name, filename, PRMSZ));
01230
01231
01232 bound_len = strlen(boundary);
01233
01234 if(filename[0] != '\0')
01235 {
01236 dbg_err_if(BUFSZ <= bound_len);
01237
01238
01239 dbg_err_if(u_tmpfile_open(&tmpio));
01240
01241 for(found = 0; !found; )
01242 {
01243 rc = read_until(io, boundary, buf, BUFSZ, &found);
01244 dbg_err_if(rc <= 0);
01245
01246
01247 if(found)
01248 {
01249 rc -= (bound_len + 2);
01250 dbg_err_if(rc < 0);
01251 }
01252
01253
01254 dbg_err_if(io_write(tmpio, buf, rc) < 0);
01255 }
01256
01257
01258 dbg_err_if(io_name_get(tmpio, buf, BUFSZ));
01259
01260
01261 io_free(tmpio); tmpio = NULL;
01262
01263
01264 dbg_err_if(request_add_uploaded_file(rq, name, filename, buf,
01265 header_get_field_value(h, "Content-Type")));
01266
01267
01268 dbg_err_if(io_gets(io, buf, BUFSZ) <= 0);
01269
01270 if(strncmp(buf, "--", 2) == 0)
01271 *eof = 1;
01272
01273 } else {
01274
01275 rc = read_until(io, boundary, buf, BUFSZ, &found);
01276 dbg_err_if(rc <= 0);
01277
01278
01279 warn_err_ifm(!found, "malformed request or BUFSZ too small");
01280
01281 rc -= (bound_len + 2);
01282 dbg_err_if(rc < 0);
01283
01284
01285 buf[rc] = 0;
01286
01287
01288 dbg_err_if(var_bin_create(name, buf, rc, &v));
01289 dbg_if(vars_add(rq->args, v));
01290
01291
01292 dbg_err_if(io_gets(io, buf, BUFSZ) <= 0);
01293
01294 if(strncmp(buf, "--", 2) == 0)
01295 *eof = 1;
01296 }
01297
01298 header_free(h);
01299
01300 return 0;
01301 err:
01302 if(tmpio)
01303 io_free(tmpio);
01304 if(h)
01305 header_free(h);
01306 return ~0;
01307 }
01308
01309 static int request_parse_multipart_data(request_t *rq)
01310 {
01311 enum { BOUNDARY_BUFSZ = 128, BUFSZ = 1024 };
01312 char boundary[BOUNDARY_BUFSZ], buf[BUFSZ];
01313 int eof;
01314
01315
01316 strcpy(boundary, "--");
01317
01318 dbg_err_if(request_get_fieldparam(rq, "Content-Type", "boundary",
01319 boundary + 2, BOUNDARY_BUFSZ - 2));
01320
01321 dbg_err_if(strlen(boundary) == 0);
01322
01323
01324 for(;;)
01325 {
01326 dbg_err_if(io_gets(rq->io, buf, BUFSZ) <= 0);
01327 if(!strncmp(buf, boundary, strlen(boundary)))
01328 break;
01329 }
01330
01331
01332 for(eof = 0; eof == 0; )
01333 dbg_err_if(request_parse_multipart_chunk(rq, rq->io, boundary, &eof));
01334
01335 return 0;
01336 err:
01337 return ~0;
01338 }
01339
01340 static int request_cb_close_socket(talarm_t *al, void *arg)
01341 {
01342 io_t *io = (io_t*)arg;
01343
01344 u_unused_args(al);
01345
01346 warn("[%x] connection timed out, closing", io);
01347
01348
01349 io_close(io);
01350
01351 return 0;
01352 }
01353
01354 int request_parse_data(request_t *rq)
01355 {
01356 talarm_t *al = NULL;
01357 int rc = HTTP_STATUS_BAD_REQUEST;
01358
01359 if(rq->method == HM_POST)
01360 {
01361
01362 dbg_err_if(timerm_add(rq->post_timeout, request_cb_close_socket,
01363 (void*)rq->io, &al));
01364
01365
01366 dbg_err_if(request_set_content_length(rq) &&
01367 (rc = HTTP_STATUS_LENGTH_REQUIRED));
01368
01369 if(rq->content_length == 0)
01370 return 0;
01371
01372
01373 dbg_err_if(rq->content_length > rq->post_maxsize &&
01374 (rc = HTTP_STATUS_REQUEST_TOO_LARGE));
01375
01376 if(request_is_multipart_formdata(rq))
01377 {
01378
01379 dbg_err_if(request_parse_query_args(rq));
01380
01381
01382 dbg_err_if(request_parse_multipart_data(rq));
01383 } else {
01384
01385 dbg_err_if(request_parse_urlencoded_data(rq));
01386 }
01387
01388
01389 dbg_if(timerm_del(al)); al = NULL;
01390 } else {
01391
01392 dbg_err_if(request_parse_query_args(rq));
01393 }
01394
01395 return 0;
01396 err:
01397 return rc;
01398 }
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409 int request_parse_header(request_t *rq,
01410 int (*is_valid_uri)(void*, const char *, size_t),
01411 void* arg)
01412 {
01413 enum { BUFSZ = 4096 };
01414 const char WP[] = " \t\r\n";
01415 char ln[BUFSZ], *pp, *method, *uri, *proto;
01416 talarm_t *al = NULL;
01417 int rc = HTTP_STATUS_BAD_REQUEST;
01418
01419 dbg_err_if (rq == NULL);
01420 dbg_err_if (rq->io == NULL);
01421
01422
01423 dbg_err_if(timerm_add(rq->idle_timeout, request_cb_close_socket,
01424 (void*)rq->io, &al));
01425
01426 if(!rq->cgi)
01427 {
01428
01429 dbg_err_if(io_gets(rq->io, ln, BUFSZ) <= 0);
01430
01431
01432 dbg_err_if(request_set_client_request(rq, ln));
01433
01434 method = strtok_r(ln, WP, &pp);
01435 dbg_err_if(!method || request_set_method(rq, method));
01436
01437 uri = strtok_r(NULL, WP, &pp);
01438 dbg_err_if(!uri || request_set_uri(rq, uri, is_valid_uri, arg));
01439
01440
01441 proto = strtok_r(NULL, WP, &pp);
01442 dbg_err_if(!proto || request_set_proto(rq, proto));
01443
01444 dbg_err_if(header_load(rq->header, rq->io));
01445 } else
01446 dbg_err_if(header_load_from_cgienv(rq->header));
01447
01448
01449 dbg_err_if(request_parse_ims(rq));
01450
01451
01452 dbg_err_if(request_parse_cookies(rq));
01453
01454
01455 if(request_get_method(rq) == HM_POST)
01456 dbg_err_if(request_set_content_length(rq));
01457
01458
01459 dbg_if(timerm_del(al)); al = NULL;
01460
01461
01462
01463
01464 return 0;
01465 err:
01466 if(al)
01467 timerm_del(al);
01468 return rc;
01469 }
01470
01482 int request_get_method(request_t *rq)
01483 {
01484 dbg_return_if (rq == NULL, HM_UNKNOWN);
01485
01486 return rq->method;
01487 }
01488
01500 const char* request_get_protocol(request_t *rq)
01501 {
01502 dbg_return_if (rq == NULL, "unknown");
01503
01504 return rq->protocol;
01505 }
01506
01517 const char *request_get_resolved_filename(request_t *rq)
01518 {
01519 dbg_return_if (rq == NULL, NULL);
01520
01521 return rq->resolved_filename;
01522 }
01523
01534 const char *request_get_resolved_path_info(request_t *rq)
01535 {
01536 dbg_return_if (rq == NULL, NULL);
01537
01538 return rq->resolved_path_info;
01539 }
01540
01541 int request_print(request_t *rq)
01542 {
01543 dbg_return_if (rq == NULL, ~0);
01544
01545 dbg("method: %u", rq->method);
01546 dbg("uri: %s", rq->uri);
01547 dbg("proto: %s", rq->protocol);
01548 dbg("filename: %s", rq->filename);
01549 dbg("resolved filename: %s", rq->resolved_filename);
01550 dbg("path_info: %s", rq->path_info);
01551 dbg("resolved path_info: %s", rq->resolved_path_info);
01552 dbg("query: %s", rq->query);
01553
01554 return 0;
01555 }
01556
01557 static int request_load_config(request_t *rq)
01558 {
01559 u_config_t *c;
01560 const char *v;
01561
01562 dbg_err_if (rq == NULL);
01563 dbg_err_if (rq->http == NULL);
01564 dbg_err_if (http_get_config(rq->http) == NULL);
01565
01566 c = http_get_config(rq->http);
01567
01568
01569 rq->idle_timeout = REQUEST_DEFAULT_IDLE_TIMEOUT;
01570 rq->post_timeout = REQUEST_DEFAULT_POST_TIMEOUT;
01571 rq->post_maxsize = REQUEST_DEFAULT_POST_MAXSIZE;
01572
01573
01574 if((v = u_config_get_subkey_value(c, "idle_timeout")) != NULL)
01575 rq->idle_timeout = MAX(1, atoi(v));
01576
01577
01578 if((v = u_config_get_subkey_value(c, "post_timeout")) != NULL)
01579 rq->post_timeout = MAX(5, atoi(v));
01580
01581
01582 if((v = u_config_get_subkey_value(c, "post_maxsize")) != NULL)
01583 rq->post_maxsize = MAX(1024, atoi(v));
01584
01585 return 0;
01586 err:
01587 return ~0;
01588 }
01589
01590 int request_create(http_t *http, request_t **prq)
01591 {
01592 request_t *rq = NULL;
01593
01594 dbg_return_if (prq == NULL, ~0);
01595 dbg_return_if (http == NULL, ~0);
01596
01597 rq = u_zalloc(sizeof(request_t));
01598 dbg_err_if(rq == NULL);
01599
01600 dbg_err_if(header_create(&rq->header));
01601
01602 dbg_err_if(vars_create(&rq->args));
01603 dbg_err_if(vars_create(&rq->cookies));
01604 dbg_err_if(vars_create(&rq->uploads));
01605
01606 rq->http = http;
01607
01608 dbg_err_if(request_load_config(rq));
01609
01610 *prq = rq;
01611
01612 return 0;
01613 err:
01614 if(rq)
01615 request_free(rq);
01616 return ~0;
01617 }
01618
01619 static int request_unlink_uploads(var_t *v, void * arg)
01620 {
01621 dbg_err_if (v == NULL);
01622
01623 u_unused_args(arg);
01624
01625 if(var_get_opaque(v) && var_get_value(v))
01626 {
01627 unlink(var_get_value(v));
01628 }
01629
01630 err:
01631 return 0;
01632 }
01633
01634 int request_free(request_t *rq)
01635 {
01636 if (rq)
01637 {
01638
01639 request_clear_uri(rq);
01640
01641 if(rq->header)
01642 header_free(rq->header);
01643
01644 if(rq->io)
01645 io_free(rq->io);
01646
01647 if(rq->uploads)
01648 {
01649
01650 vars_foreach(rq->uploads, request_unlink_uploads, NULL);
01651 vars_free(rq->uploads);
01652 }
01653
01654 if(rq->cookies)
01655 vars_free(rq->cookies);
01656
01657 if(rq->args)
01658 vars_free(rq->args);
01659
01660 U_FREE(rq);
01661 }
01662
01663 return 0;
01664 }
01665
01666
01667 int request_set_addr(request_t *rq, addr_t *addr)
01668 {
01669 dbg_return_if (rq == NULL, ~0);
01670 dbg_return_if (addr == NULL, ~0);
01671
01672 memcpy(&rq->local_addr, addr, sizeof(addr_t));
01673
01674 return 0;
01675 }
01676
01677
01678 int request_set_peer_addr(request_t *rq, addr_t *addr)
01679 {
01680 dbg_return_if (rq == NULL, ~0);
01681 dbg_return_if (addr == NULL, ~0);
01682
01683 memcpy(&rq->peer_addr, addr, sizeof(addr_t));
01684
01685 return 0;
01686 }
01687
01698 addr_t* request_get_addr(request_t *rq)
01699 {
01700 dbg_return_if (rq == NULL, NULL);
01701
01702 return &rq->local_addr;
01703 }
01704
01715 addr_t* request_get_peer_addr(request_t *rq)
01716 {
01717 dbg_return_if (rq == NULL, NULL);
01718
01719 return &rq->peer_addr;
01720 }
01721
01733 header_t* request_get_header(request_t *rq)
01734 {
01735 dbg_return_if (rq == NULL, NULL);
01736
01737 return rq->header;
01738 }
01739
01751 field_t* request_get_field(request_t *rq, const char *name)
01752 {
01753 dbg_return_if (rq == NULL, NULL);
01754 dbg_return_if (name == NULL, NULL);
01755
01756 return header_get_field(rq->header, name);
01757 }
01758
01770 const char* request_get_field_value(request_t *rq, const char *name)
01771 {
01772 dbg_return_if (rq == NULL, NULL);
01773 dbg_return_if (name == NULL, NULL);
01774
01775 return header_get_field_value(rq->header, name);
01776 }
01777