LTP GCOV extension - code coverage report
Current view: directory - and-httpd/src - httpd_conf_req.c
Test: And-httpd coverage
Date: 2006-09-11 Instrumented lines: 603
Code covered: 61.7 % Executed lines: 372

       1                 : 
       2                 : #include "httpd.h"
       3                 : #include "httpd_policy.h"
       4                 : 
       5                 : #include <err.h>
       6                 : 
       7                 : #define EX_UTILS_NO_USE_INIT  1
       8                 : #define EX_UTILS_NO_USE_EXIT  1
       9                 : #define EX_UTILS_NO_USE_LIMIT 1
      10                 : #define EX_UTILS_NO_USE_INPUT 1
      11                 : #define EX_UTILS_NO_USE_BLOCK 1
      12                 : #define EX_UTILS_NO_USE_PUT   1
      13                 : #define EX_UTILS_NO_USE_BLOCKING_OPEN 1
      14                 : #define EX_UTILS_RET_FAIL     1
      15                 : #include "ex_utils.h"
      16                 : 
      17                 : #define HTTPD_CONF_REQ__X_CONTENT_SINGLE_VSTR(x) do {                   \
      18                 :       if (!httpd__conf_req_single_str(req, conf, token,                 \
      19                 :                                       &req-> x ## _vs1,                 \
      20                 :                                       &req-> x ## _pos,                 \
      21                 :                                       &req-> x ## _len))                \
      22                 :         return (FALSE);                                                 \
      23                 :     } while (FALSE)
      24                 : 
      25                 : #define HTTPD_CONF_REQ__X_CONTENT_VSTR(x) do {                          \
      26                 :       if (!httpd__conf_req_make_str(req, conf, token,                   \
      27                 :                                     &req-> x ## _vs1,                   \
      28                 :                                     &req-> x ## _pos,                   \
      29                 :                                     &req-> x ## _len))                  \
      30                 :         return (FALSE);                                                 \
      31                 :     } while (FALSE)
      32                 : 
      33                 : 
      34                 : 
      35                 : #define HTTPD_CONF_REQ__TYPE_BUILD_PATH_SKIP   0
      36                 : #define HTTPD_CONF_REQ__TYPE_BUILD_PATH_ASSIGN 1
      37                 : #define HTTPD_CONF_REQ__TYPE_BUILD_PATH_APPEND 2
      38                 : 
      39                 : static int httpd__conf_req_single_str(Httpd_req_data *req,
      40                 :                                       Conf_parse *conf, Conf_token *token,
      41                 :                                       const Vstr_base **s1,
      42                 :                                       size_t *pos, size_t *len)
      43           16512 : {
      44           16512 :   Vstr_base *xs1 = req->xtra_content;
      45                 :   
      46            8256 :   ASSERT(s1 && pos && len);
      47            8256 :   ASSERT((*s1 == xs1) || !*s1);
      48                 : 
      49                 :   /* always delete, so don't call http_req_xtra_content() as it might do a
      50                 :      copy */
      51           16512 :   if (!req->xtra_content && !(req->xtra_content = vstr_make_base(NULL)))
      52               0 :     return (FALSE);
      53           16512 :   xs1 = req->xtra_content;
      54                 : 
      55           16512 :   if (*len && (vstr_sc_poslast(*pos, *len) == xs1->len))
      56              32 :     vstr_del(req->xtra_content, *pos, *len);
      57                 :   
      58           16512 :   *pos = xs1->len;
      59           16512 :   *len = 0;
      60           16512 :   if (conf_sc_token_app_vstr(conf, token, xs1, s1, pos, len))
      61               0 :     return (FALSE);
      62                 : 
      63           16512 :   if ((token->type == CONF_TOKEN_TYPE_QUOTE_ESC_D) ||
      64                 :       (token->type == CONF_TOKEN_TYPE_QUOTE_ESC_DDD) ||
      65                 :       (token->type == CONF_TOKEN_TYPE_QUOTE_ESC_S) ||
      66                 :       (token->type == CONF_TOKEN_TYPE_QUOTE_ESC_SSS) ||
      67                 :       FALSE)
      68            1152 :     if (!*s1 || !conf_sc_conv_unesc(xs1, *pos, *len, len))
      69               0 :       return (FALSE);
      70                 :   
      71           16512 :   return (TRUE);
      72                 : }
      73                 : 
      74                 : /* if we aren't the last string in the XTRA_CONTENT, copy to the last bit
      75                 :  * Then pass the last bit to make_str */
      76                 : static int httpd__conf_req_make_str(Httpd_req_data *req,
      77                 :                                     Conf_parse *conf, Conf_token *token,
      78                 :                                     const Vstr_base **s1,
      79                 :                                     size_t *pos, size_t *len)
      80           12032 : {
      81           12032 :   Opt_serv_opts *opts = req->policy->s->beg;
      82           12032 :   size_t xpos = 0;
      83                 : 
      84           12032 :   if (!(xpos = http_req_xtra_content(req, *s1, *pos, len)))
      85               0 :     return (FALSE);
      86                 :   
      87           12032 :   if (!opt_serv_sc_make_str(opts, conf, token, req->xtra_content, xpos, *len))
      88               0 :     return (FALSE);
      89                 :   
      90           12032 :   *s1  = req->xtra_content;
      91           12032 :   *pos = xpos;
      92           12032 :   *len = (req->xtra_content->len - xpos) + 1;
      93                 : 
      94           12032 :   return (TRUE);
      95                 : }
      96                 : 
      97                 : 
      98                 : static void httpd__conf_req_reset_expires(struct Httpd_req_data *req,
      99                 :                                           unsigned int off)
     100               0 : {
     101               0 :   Vstr_base *s1 = req->xtra_content;
     102               0 :   size_t pos = req->expires_pos;
     103               0 :   size_t len = req->expires_len;
     104               0 :   Opt_serv_opts *opts = req->policy->s->beg;
     105               0 :   Date_store *date = ((Httpd_opts *)opts)->date;
     106                 :   
     107               0 :   ASSERT(vstr_sc_poslast(pos, len) == s1->len);
     108                 : 
     109               0 :   if (off > (60 * 60 * 24 * 365))
     110               0 :     off = (60 * 60 * 24 * 365);
     111                 :   
     112               0 :   if (vstr_sub_cstr_buf(s1, pos, len, date_rfc1123(date, req->now + off)))
     113               0 :     req->expires_len = vstr_sc_posdiff(pos, s1->len);
     114               0 : }
     115                 : 
     116                 : static void httpd__conf_req_reset_cache_control(struct Httpd_req_data *req,
     117                 :                                                 unsigned int val)
     118               0 : {
     119               0 :   Vstr_base *s1 = req->xtra_content;
     120               0 :   size_t pos = req->cache_control_pos;
     121               0 :   size_t len = req->cache_control_len;
     122                 :   
     123               0 :   ASSERT(pos && len);
     124               0 :   ASSERT(vstr_sc_poslast(pos, len) == s1->len);
     125                 :   
     126               0 :   if (val > (60 * 60 * 24 * 365))
     127               0 :     val = (60 * 60 * 24 * 365);
     128                 :   
     129               0 :   if (vstr_add_fmt(s1, pos - 1, "max-age=%u", val))
     130                 :   {
     131               0 :     vstr_sc_reduce(s1, 1, s1->len, len);
     132               0 :     req->cache_control_len = vstr_sc_posdiff(pos, s1->len);
     133                 :   }
     134               0 : }
     135                 : 
     136                 : static int httpd__build_path(struct Con *con, Httpd_req_data *req,
     137                 :                              const Conf_parse *conf, Conf_token *token,
     138                 :                              Vstr_base *s1, size_t pos, size_t len,
     139                 :                              unsigned int lim, int full, Vstr_ref *ref,
     140                 :                              int uri_fname, int *type)
     141           11968 : {
     142                 :   int dummy_type;
     143           11968 :   int clist = FALSE;
     144                 : 
     145           11968 :   if (!type) type = &dummy_type;
     146           11968 :   *type = HTTPD_CONF_REQ__TYPE_BUILD_PATH_SKIP;
     147                 :   
     148           11968 :   if (uri_fname)
     149                 :   {
     150            4864 :     int slash_dot_safe = FALSE;
     151                 : 
     152            4864 :     if (req->chk_encoded_slash && req->chk_encoded_dot)
     153            4288 :       slash_dot_safe = TRUE;
     154            4864 :     if (!httpd_policy_uri_lim_eq(s1, &pos, &len, lim, slash_dot_safe, ref))
     155                 :     {
     156               0 :       int ret = conf_parse_end_token(conf, token, conf_token_at_depth(token));
     157               0 :       ASSERT(ret);
     158               0 :       return (TRUE);
     159                 :     }
     160                 :   }
     161                 :   else
     162                 :   {
     163            7104 :     size_t vhost_len = req->vhost_prefix_len;
     164                 :   
     165            7104 :     if (!httpd_policy_path_lim_eq(s1, &pos, &len, lim, vhost_len, ref))
     166                 :     {
     167             960 :       int ret = conf_parse_end_token(conf, token, conf_token_at_depth(token));
     168             480 :       ASSERT(ret);
     169             960 :       return (TRUE);
     170                 :     }
     171                 :     
     172            6144 :     if (full && vhost_len)
     173                 :     { /* don't want to keep the vhost data */
     174              32 :       if (lim != HTTPD_POLICY_PATH_LIM_NONE)
     175               0 :         pos -= vhost_len;
     176                 :       else
     177              32 :         len -= vhost_len;
     178                 :       
     179              16 :       ASSERT(req->fname == s1);
     180              32 :       vstr_del(req->fname, 1, vhost_len);
     181              32 :       req->vhost_prefix_len = 0;
     182                 :     }
     183                 :   }
     184           11008 :   *type = HTTPD_CONF_REQ__TYPE_BUILD_PATH_ASSIGN;
     185                 :   
     186           11008 :   CONF_SC_TOGGLE_CLIST_VAR(clist);
     187                 :   
     188                 :   if (0) { }
     189                 :   
     190           13312 :   else if (OPT_SERV_SYM_EQ("assign") || OPT_SERV_SYM_EQ("="))
     191                 :   {
     192            4608 :     if (!httpd_policy_build_path(con, req, conf, token, NULL, NULL))
     193               0 :       return (FALSE);
     194                 : 
     195            4608 :     if (!vstr_sub_vstr(s1, pos, len,
     196                 :                        conf->tmp, 1, conf->tmp->len, VSTR_TYPE_SUB_BUF_REF))
     197               0 :       return (FALSE);
     198                 :   }
     199            6400 :   else if (OPT_SERV_SYM_EQ("append") || OPT_SERV_SYM_EQ("+=") ||
     200                 :            OPT_SERV_SYM_EQ(".=") || OPT_SERV_SYM_EQ(">>="))
     201                 :   {
     202             288 :     *type = HTTPD_CONF_REQ__TYPE_BUILD_PATH_APPEND;
     203                 :   
     204             288 :     if (!httpd_policy_build_path(con, req, conf, token, NULL, NULL))
     205               0 :       return (FALSE);
     206                 : 
     207             288 :     return (vstr_add_vstr(s1, vstr_sc_poslast(pos, len),
     208                 :                           conf->tmp, 1, conf->tmp->len, VSTR_TYPE_ADD_BUF_REF));
     209                 :   }
     210            6112 :   else if (OPT_SERV_SYM_EQ("prepend") || OPT_SERV_SYM_EQ("<<="))
     211                 :   {
     212             768 :     *type = HTTPD_CONF_REQ__TYPE_BUILD_PATH_APPEND;
     213                 :   
     214             768 :     if (!httpd_policy_build_path(con, req, conf, token, NULL, NULL))
     215               0 :       return (FALSE);
     216                 : 
     217             768 :     return (vstr_add_vstr(s1, pos - 1,
     218                 :                           conf->tmp, 1, conf->tmp->len, VSTR_TYPE_ADD_BUF_REF));
     219                 :   }
     220            5344 :   else if (!clist)
     221                 :   {
     222            5344 :     const Vstr_sect_node *pv = conf_token_value(token);
     223                 :       
     224            5344 :     if (!pv || !vstr_sub_vstr(s1, pos, len, conf->data, pv->pos, pv->len,
     225                 :                               VSTR_TYPE_SUB_BUF_REF))
     226               0 :       return (FALSE);
     227            5344 :     OPT_SERV_X__ESC_VSTR(s1, pos, pv->len);
     228                 : 
     229            2672 :     goto fin_overwrite;
     230                 :   }    
     231                 :   else
     232               0 :     return (FALSE);
     233                 : 
     234            9952 :  fin_overwrite:
     235            9952 :   if (lim == HTTPD_POLICY_PATH_LIM_NONE)
     236            1056 :     req->vhost_prefix_len = 0; /* replaced everything */
     237                 : 
     238            9952 :   return (TRUE);
     239                 : }
     240                 : 
     241                 : static int httpd__meta_build_path(struct Con *con, Httpd_req_data *req,
     242                 :                                   Conf_parse *conf, Conf_token *token,
     243                 :                                   int *full, int *canon,
     244                 :                                   unsigned int *lim, Vstr_ref **ret_ref)
     245           11968 : {
     246           11968 :   unsigned int depth = token->depth_num;
     247                 : 
     248            5984 :   ASSERT(ret_ref && !*ret_ref);
     249                 :   
     250           11968 :   if (token->type != CONF_TOKEN_TYPE_SLIST)
     251            2624 :     return (TRUE);
     252                 : 
     253           24320 :   while (conf_token_list_num(token, depth))
     254                 :   {
     255           10304 :     int clist = FALSE;
     256                 :     
     257           10304 :     CONF_SC_PARSE_DEPTH_TOKEN_RET(conf, token, depth, TRUE);
     258           10304 :     CONF_SC_TOGGLE_CLIST_VAR(clist);
     259                 : 
     260                 :     if (0) { }
     261           10336 :     else if (full && (OPT_SERV_SYM_EQ("skip-virtual-hosts") ||
     262                 :                       OPT_SERV_SYM_EQ("skip-vhosts")))
     263              32 :       OPT_SERV_X_TOGGLE(*full);
     264           11296 :     else if (canon && (OPT_SERV_SYM_EQ("make-abs-url") ||
     265                 :                        OPT_SERV_SYM_EQ("make-absolute-url")))
     266            1024 :       OPT_SERV_X_TOGGLE(*canon);
     267            9312 :     else if (full && OPT_SERV_SYM_EQ("skip-document-root"))
     268              64 :       OPT_SERV_X_TOGGLE(req->skip_document_root);
     269            9184 :     else if (OPT_SERV_SYM_EQ("limit"))
     270                 :     {
     271            9184 :       CONF_SC_PARSE_TOP_TOKEN_RET(conf, token, FALSE);
     272                 : 
     273            9184 :       vstr_ref_del(*ret_ref); *ret_ref = NULL;
     274            9184 :       if (token->type >= CONF_TOKEN_TYPE_USER_BEG)
     275                 :       {
     276            4172 :         unsigned int type = token->type - CONF_TOKEN_TYPE_USER_BEG;
     277            4172 :         unsigned int nxt = 0;
     278            4172 :         Vstr_ref *ref = conf_token_get_user_value(conf, token, &nxt);
     279                 :     
     280            4172 :         switch (type)
     281                 :         {
     282                 :           case HTTPD_POLICY_REQ_PATH_BEG:
     283                 :           case HTTPD_POLICY_REQ_PATH_END:
     284                 :           case HTTPD_POLICY_REQ_PATH_EQ:
     285                 : 
     286                 :           case HTTPD_POLICY_REQ_NAME_BEG:
     287                 :           case HTTPD_POLICY_REQ_NAME_END:
     288                 :           case HTTPD_POLICY_REQ_NAME_EQ:
     289                 :             
     290                 :           case HTTPD_POLICY_REQ_BWEN_BEG:
     291                 :           case HTTPD_POLICY_REQ_BWEN_END:
     292                 :           case HTTPD_POLICY_REQ_BWEN_EQ:
     293                 :             
     294                 :           case HTTPD_POLICY_REQ_BWES_BEG:
     295                 :           case HTTPD_POLICY_REQ_BWES_END:
     296                 :           case HTTPD_POLICY_REQ_BWES_EQ:
     297                 :             
     298                 :           case HTTPD_POLICY_REQ_EXTN_BEG:
     299                 :           case HTTPD_POLICY_REQ_EXTN_END:
     300                 :           case HTTPD_POLICY_REQ_EXTN_EQ:
     301                 :             
     302                 :           case HTTPD_POLICY_REQ_EXTS_BEG:
     303                 :           case HTTPD_POLICY_REQ_EXTS_END:
     304                 :           case HTTPD_POLICY_REQ_EXTS_EQ:
     305            4172 :             *lim = httpd_policy_path_req2lim(type);
     306                 :             break;
     307                 : 
     308                 :           default:
     309               0 :             vstr_ref_del(ref);
     310               0 :             return (FALSE);
     311                 :         }
     312            4172 :         *ret_ref = ref;
     313            8344 :         if (nxt && !conf_parse_num_token(conf, token, nxt))
     314               0 :           return (FALSE);
     315                 :       }
     316                 :   
     317            5108 :       else if (OPT_SERV_SYM_EQ("<none>") || OPT_SERV_SYM_EQ("none"))
     318              96 :         *lim = HTTPD_POLICY_PATH_LIM_NONE;
     319            5876 :       else if (OPT_SERV_SYM_EQ("<path>") || OPT_SERV_SYM_EQ("path"))
     320             960 :         *lim = HTTPD_POLICY_PATH_LIM_PATH_FULL;
     321            3956 :       else if (OPT_SERV_SYM_EQ("<basename>") || OPT_SERV_SYM_EQ("basename"))
     322               0 :         *lim = HTTPD_POLICY_PATH_LIM_NAME_FULL;
     323            4212 :       else if (OPT_SERV_SYM_EQ("<extension>") || OPT_SERV_SYM_EQ("extension"))
     324             256 :         *lim = HTTPD_POLICY_PATH_LIM_EXTN_FULL;
     325            3956 :       else if (OPT_SERV_SYM_EQ("<extensions>") || OPT_SERV_SYM_EQ("extensions"))
     326             256 :         *lim = HTTPD_POLICY_PATH_LIM_EXTS_FULL;
     327            3444 :       else if (OPT_SERV_SYM_EQ("<basename-without-extension>") ||
     328                 :                OPT_SERV_SYM_EQ("basename-without-extension"))
     329               0 :         *lim = HTTPD_POLICY_PATH_LIM_BWEN_FULL;
     330            3444 :       else if (OPT_SERV_SYM_EQ("<basename-without-extensions>") ||
     331                 :                OPT_SERV_SYM_EQ("basename-without-extensions"))
     332               0 :         *lim = HTTPD_POLICY_PATH_LIM_BWES_FULL;
     333                 :       else
     334                 :       {
     335            3444 :         unsigned int type = HTTPD_POLICY_REQ_PATH_BEG;
     336                 :         
     337                 :         if (0) { }
     338            3484 :         else if (OPT_SERV_SYM_EQ("<path>-beg") || OPT_SERV_SYM_EQ("path-beg"))
     339              40 :           type = HTTPD_POLICY_REQ_PATH_BEG;
     340            6808 :         else if (OPT_SERV_SYM_EQ("<path>-end") || OPT_SERV_SYM_EQ("path-end"))
     341            3404 :           type = HTTPD_POLICY_REQ_PATH_END;
     342               0 :         else if (OPT_SERV_SYM_EQ("<path>-eq") || OPT_SERV_SYM_EQ("path-eq") ||
     343                 :                  OPT_SERV_SYM_EQ("<path>==") || OPT_SERV_SYM_EQ("path=="))
     344               0 :           type = HTTPD_POLICY_REQ_PATH_EQ;
     345               0 :         else if (OPT_SERV_SYM_EQ("<basename>-beg") ||
     346                 :                  OPT_SERV_SYM_EQ("basename-beg") ||
     347                 :                  OPT_SERV_SYM_EQ("<basename>==") ||
     348                 :                  OPT_SERV_SYM_EQ("basename=="))
     349               0 :           type = HTTPD_POLICY_REQ_NAME_BEG;
     350               0 :         else if (OPT_SERV_SYM_EQ("<basename>-end") ||
     351                 :                  OPT_SERV_SYM_EQ("basename-end"))
     352               0 :           type = HTTPD_POLICY_REQ_NAME_END;
     353               0 :         else if (OPT_SERV_SYM_EQ("<basename>-eq") ||
     354                 :                  OPT_SERV_SYM_EQ("basename-eq") ||
     355                 :                  OPT_SERV_SYM_EQ("<basename>==") ||
     356                 :                  OPT_SERV_SYM_EQ("basename=="))
     357               0 :           type = HTTPD_POLICY_REQ_NAME_EQ;
     358               0 :         else if (OPT_SERV_SYM_EQ("<extension>-beg") ||
     359                 :                  OPT_SERV_SYM_EQ("extension-beg"))
     360               0 :           type = HTTPD_POLICY_REQ_EXTN_BEG;
     361               0 :         else if (OPT_SERV_SYM_EQ("<extension>-end") ||
     362                 :                  OPT_SERV_SYM_EQ("extension-end"))
     363               0 :           type = HTTPD_POLICY_REQ_EXTN_END;
     364               0 :         else if (OPT_SERV_SYM_EQ("<extension>-eq") ||
     365                 :                  OPT_SERV_SYM_EQ("extension-eq") ||
     366                 :                  OPT_SERV_SYM_EQ("<extension>==") ||
     367                 :                  OPT_SERV_SYM_EQ("extension=="))
     368               0 :           type = HTTPD_POLICY_REQ_EXTN_EQ;
     369               0 :         else if (OPT_SERV_SYM_EQ("<extensions>-beg") ||
     370                 :                  OPT_SERV_SYM_EQ("extensions-beg"))
     371               0 :           type = HTTPD_POLICY_REQ_EXTS_BEG;
     372               0 :         else if (OPT_SERV_SYM_EQ("<extensions>-end") ||
     373                 :                  OPT_SERV_SYM_EQ("extensions-end"))
     374               0 :           type = HTTPD_POLICY_REQ_EXTS_END;
     375               0 :         else if (OPT_SERV_SYM_EQ("<extensions>-eq") ||
     376                 :                  OPT_SERV_SYM_EQ("extensions-eq") ||
     377                 :                  OPT_SERV_SYM_EQ("<extensions>==") ||
     378                 :                  OPT_SERV_SYM_EQ("extensions=="))
     379               0 :           type = HTTPD_POLICY_REQ_EXTS_EQ;
     380               0 :         else if (OPT_SERV_SYM_EQ("<basename-without-extension>-beg") ||
     381                 :                  OPT_SERV_SYM_EQ("basename-without-extension-beg"))
     382               0 :           type = HTTPD_POLICY_REQ_BWEN_BEG;
     383               0 :         else if (OPT_SERV_SYM_EQ("<basename-without-extension>-end") ||
     384                 :                  OPT_SERV_SYM_EQ("basename-without-extension-end"))
     385               0 :           type = HTTPD_POLICY_REQ_BWEN_END;
     386               0 :         else if (OPT_SERV_SYM_EQ("<basename-without-extension>-eq") ||
     387                 :                  OPT_SERV_SYM_EQ("basename-without-extension-eq") ||
     388                 :                  OPT_SERV_SYM_EQ("<basename-without-extension>==") ||
     389                 :                  OPT_SERV_SYM_EQ("basename-without-extension=="))
     390               0 :           type = HTTPD_POLICY_REQ_BWEN_EQ;
     391               0 :         else if (OPT_SERV_SYM_EQ("<basename-without-extensions>-beg") ||
     392                 :                  OPT_SERV_SYM_EQ("basename-without-extensions-beg"))
     393               0 :           type = HTTPD_POLICY_REQ_BWES_BEG;
     394               0 :         else if (OPT_SERV_SYM_EQ("<basename-without-extensions>-end") ||
     395                 :                  OPT_SERV_SYM_EQ("basename-without-extensions-end"))
     396               0 :           type = HTTPD_POLICY_REQ_BWES_END;
     397               0 :         else if (OPT_SERV_SYM_EQ("<basename-without-extensions>-eq") ||
     398                 :                  OPT_SERV_SYM_EQ("basename-without-extensions-eq") ||
     399                 :                  OPT_SERV_SYM_EQ("<basename-without-extensions>==") ||
     400                 :                  OPT_SERV_SYM_EQ("basename-without-extensions=="))
     401               0 :           type = HTTPD_POLICY_REQ_BWES_EQ;
     402                 :         else
     403               0 :           return (FALSE);
     404                 :         
     405            3444 :         if (!httpd_policy_path_make(con, req, conf, token, type, ret_ref))
     406               0 :            return (FALSE);
     407                 :         
     408            3444 :         *lim = httpd_policy_path_req2lim(type);
     409                 :       }
     410                 :     }
     411                 :     else
     412               0 :       return (FALSE);
     413                 :   }
     414                 :   
     415            9344 :   CONF_SC_PARSE_DEPTH_TOKEN_RET(conf, token, depth - 1, FALSE);
     416            9344 :   return (TRUE);
     417                 : }
     418                 : 
     419                 : static int httpd__content_location_valid(Httpd_req_data *req,
     420                 :                                          size_t *ret_pos, size_t *ret_len)
     421               0 : {
     422               0 :   *ret_pos = req->content_location_pos;
     423               0 :   *ret_len = req->content_location_len;
     424                 :   
     425               0 :   *ret_pos = http_req_xtra_content(req, req->xtra_content, *ret_pos, ret_len);
     426                 : 
     427               0 :   return (!!*ret_pos);
     428                 : }
     429                 : 
     430                 : /* we negotiate a few items, and this is the loop for all of them... */
     431                 : #define HTTPD__NEG_BEG(x)                                               \
     432                 :     unsigned int depth = token->depth_num;                              \
     433                 :     unsigned int max_qual  = 0;                                         \
     434                 :     unsigned int qual_num  = 0;                                         \
     435                 :     unsigned int neg_count = 0;                                         \
     436                 :     Conf_token save;                                                    \
     437                 :                                                                         \
     438                 :     save = *token;                                                      \
     439                 :     while (conf_token_list_num(token, depth) &&                         \
     440                 :            (!(x) || (++neg_count <= (x))))                              \
     441                 :     {                                                                   \
     442                 :       unsigned int qual = 0;                                            \
     443                 :       const Vstr_sect_node *val = NULL;                                 \
     444                 :                                                                         \
     445                 :       CONF_SC_PARSE_DEPTH_TOKEN_RET(conf, token, depth, TRUE);          \
     446                 :       CONF_SC_TOGGLE_CLIST_VAR(clist);                                  \
     447                 :                                                                         \
     448                 :       if (!((token->type == CONF_TOKEN_TYPE_QUOTE_D) ||                 \
     449                 :             (token->type == CONF_TOKEN_TYPE_QUOTE_DDD) ||               \
     450                 :             (token->type == CONF_TOKEN_TYPE_QUOTE_S) ||                 \
     451                 :             (token->type == CONF_TOKEN_TYPE_QUOTE_SSS) ||               \
     452                 :             (token->type == CONF_TOKEN_TYPE_SYMBOL)))                   \
     453                 :         return (FALSE);                                                 \
     454                 :                                                                         \
     455                 :       val = conf_token_value(token)
     456                 : 
     457                 : 
     458                 : #define HTTPD__NEG_END()                        \
     459                 :       if (qual > max_qual)                      \
     460                 :       {                                         \
     461                 :         max_qual = qual;                        \
     462                 :         qual_num = token->num - 1;              \
     463                 :       }                                         \
     464                 :                                                                         \
     465                 :       CONF_SC_PARSE_TOP_TOKEN_RET(conf, token, FALSE);                  \
     466                 :     }                                                                   \
     467                 :     if (neg_count)                                                      \
     468                 :     {                                                                   \
     469                 :       int ret = conf_parse_end_token(conf, token, depth);               \
     470                 :       ASSERT(ret);                                                      \
     471                 :     }                                                                   \
     472                 :     do { } while (FALSE)
     473                 : 
     474                 : 
     475                 : /* match with an 's' is it's > 1, otherwise without ... zero special cased */
     476                 : #define HTTPD__EXPIRES_CMP(x, y)                                        \
     477                 :     (((num == 1) &&                                                     \
     478                 :       vstr_cmp_cstr_eq(HTTP_REQ__CONT_PARAMS(req, x), "<" y ">")) ||     \
     479                 :      ((num > 1) &&                                                      \
     480                 :       vstr_cmp_cstr_eq(HTTP_REQ__CONT_PARAMS(req, x), "<" y "s>")))
     481                 : 
     482                 : #define HTTPD__CONF_REDIR(req, code) do {                               \
     483                 :       if ((req)->direct_uri) {                                          \
     484                 :         httpd_req_absolute_uri(con, req,                                \
     485                 :                                (req)->fname, 1, (req)->fname->len);     \
     486                 :         HTTPD_REDIR_MSG(req, code, "Req conf");                         \
     487                 :         return (FALSE);                                                 \
     488                 :       }                                                                 \
     489                 :     } while (FALSE)
     490                 : 
     491                 : static int httpd__conf_req_d1(struct Con *con, struct Httpd_req_data *req,
     492                 :                               time_t file_timestamp,
     493                 :                               Conf_parse *conf, Conf_token *token, int clist)
     494           41024 : {
     495                 :   if (0) { }
     496                 : 
     497           41024 :   else if (OPT_SERV_SYM_EQ("match-init"))
     498               0 :     OPT_SERV_SC_MATCH_INIT(req->policy->s->beg,
     499                 :                            httpd__conf_req_d1(con, req, file_timestamp,
     500                 :                                               conf, token, clist));
     501                 :   
     502           41024 :   else if (OPT_SERV_SYM_EQ("match-request"))
     503                 :   {
     504                 :     static unsigned int match_req_rec_depth = 0; /* no inf. recursion */
     505                 :     static int prev_match = TRUE;
     506             736 :     unsigned int depth = token->depth_num;
     507             736 :     int matches = TRUE;
     508                 : 
     509             736 :     if (match_req_rec_depth > 4) /* FIXME: conf */
     510               0 :       return (FALSE);
     511                 :     
     512             736 :     CONF_SC_PARSE_SLIST_DEPTH_TOKEN_RET(conf, token, depth, FALSE);
     513             736 :     ++depth;
     514            2208 :     while (conf_token_list_num(token, depth))
     515                 :     {
     516             736 :       CONF_SC_PARSE_DEPTH_TOKEN_RET(conf, token, depth, FALSE);
     517                 :       
     518             736 :       if (!httpd_match_request_sc_tst_d1(con, req, conf, token, &matches,
     519                 :                                          prev_match))
     520               0 :         return (FALSE);
     521                 :       
     522             736 :       if (!matches)
     523             352 :         conf_parse_end_token(conf, token, depth - 1);
     524                 :     }
     525             736 :     --depth;
     526                 : 
     527             736 :     prev_match = matches;
     528                 :     
     529            1856 :     while (conf_token_list_num(token, depth))
     530                 :     {
     531             512 :       int ret = FALSE;
     532                 :       
     533             512 :       CONF_SC_PARSE_DEPTH_TOKEN_RET(conf, token, depth, FALSE);
     534             512 :       CONF_SC_TOGGLE_CLIST_VAR(clist);
     535                 : 
     536             512 :       ++match_req_rec_depth;
     537             512 :       ret = httpd__conf_req_d1(con, req, file_timestamp, conf, token, clist);
     538             512 :       --match_req_rec_depth;
     539                 :       
     540             512 :       if (!ret)
     541             128 :         return (FALSE);
     542                 :     }
     543                 :   }
     544                 :   
     545           40288 :   else if (OPT_SERV_SYM_EQ("return"))
     546                 :   {
     547            4128 :     unsigned int code = 0;
     548                 :     
     549            4128 :     OPT_SERV_X_SYM_UINT_BEG(code);
     550                 : 
     551            4800 :     else if (OPT_SERV_SYM_EQ("<perm>") ||
     552                 :              OPT_SERV_SYM_EQ("<perm-redirect>") ||
     553                 :              OPT_SERV_SYM_EQ("<permanent>") || /* sp is permanent */
     554                 :              OPT_SERV_SYM_EQ("<permenant>") || /* allow bad sp */
     555                 :              OPT_SERV_SYM_EQ("<permanent-redirect>") ||
     556                 :              OPT_SERV_SYM_EQ("<permenant-redirect>"))
     557            1472 :       code = 301;
     558            1856 :     else if (OPT_SERV_SYM_EQ("<found>"))
     559             128 :       code = 302;
     560            1856 :     else if (OPT_SERV_SYM_EQ("<other>") || OPT_SERV_SYM_EQ("<see-other>"))
     561             128 :       code = 303;
     562            1856 :     else if (OPT_SERV_SYM_EQ("<tmp>") || OPT_SERV_SYM_EQ("<tmp-redirect>") ||
     563                 :              OPT_SERV_SYM_EQ("<temp>") ||
     564                 :              OPT_SERV_SYM_EQ("<temp-redirect>") ||
     565                 :              OPT_SERV_SYM_EQ("<temporary>") ||
     566                 :              OPT_SERV_SYM_EQ("<temporary-redirect>"))
     567             256 :       code = 307;
     568            1344 :     else if (OPT_SERV_SYM_EQ("<bad>") || OPT_SERV_SYM_EQ("<bad-request>"))
     569               0 :       code = 400;
     570            1344 :     else if (OPT_SERV_SYM_EQ("<forbidden>"))
     571             928 :       code = 403;
     572             416 :     else if (OPT_SERV_SYM_EQ("<not-found>"))
     573              64 :       code = 404;
     574             352 :     else if (OPT_SERV_SYM_EQ("<not-acceptable>"))
     575               0 :       code = 406;
     576             352 :     else if (OPT_SERV_SYM_EQ("<gone>"))
     577             352 :       code = 410;
     578               0 :     else if (OPT_SERV_SYM_EQ("<error>") ||
     579                 :              OPT_SERV_SYM_EQ("<internal-server-error>"))
     580               0 :       code = 500;
     581               0 :     else if (OPT_SERV_SYM_EQ("<service-unavailable>"))
     582               0 :       code = 503;
     583                 : 
     584               0 :     OPT_SERV_X_SYM_NUM_END();
     585                 :     
     586            4128 :     req->user_return_error_code = TRUE;
     587            2064 :     ASSERT(!req->error_code);
     588            4128 :     req->error_code = 0;
     589            4128 :     switch (code)
     590                 :     {
     591            1888 :       case 301: HTTPD__CONF_REDIR(req, 301);
     592             256 :       case 302: HTTPD__CONF_REDIR(req, 302);
     593             256 :       case 303: HTTPD__CONF_REDIR(req, 303);
     594             384 :       case 307: HTTPD__CONF_REDIR(req, 307);
     595                 :       default:
     596               0 :         req->user_return_error_code = FALSE;
     597               0 :         return (FALSE);
     598                 :         
     599               0 :       case 400: HTTPD_ERR_MSG_RET(req, 400, "Req conf", FALSE);
     600             928 :       case 403: HTTPD_ERR_MSG_RET(req, 403, "Req conf", FALSE);
     601              64 :       case 404: HTTPD_ERR_MSG_RET(req, 404, "Req conf", FALSE);
     602               0 :       case 406: HTTPD_ERR_MSG_RET(req, 406, "Req conf", FALSE);
     603             352 :       case 410: HTTPD_ERR_MSG_RET(req, 410, "Req conf", FALSE);
     604               0 :       case 500: HTTPD_ERR_MSG_RET(req, 500, "Req conf", FALSE);
     605               0 :       case 503: HTTPD_ERR_MSG_RET(req, 503, "Req conf", FALSE);
     606                 :     }
     607                 :   }
     608           36160 :   else if (OPT_SERV_SYM_EQ("Location:"))
     609                 :   {
     610            4864 :     unsigned int lim = HTTPD_POLICY_PATH_LIM_NONE;
     611            4864 :     Vstr_ref *ref = NULL;
     612            4864 :     size_t orig_len = 0;
     613            4864 :     int bp_type = HTTPD_CONF_REQ__TYPE_BUILD_PATH_SKIP;
     614            4864 :     int canon = FALSE;
     615                 :     
     616            4864 :     if (req->direct_filename)
     617               0 :       return (FALSE);
     618                 :     
     619            4864 :     CONF_SC_PARSE_TOP_TOKEN_RET(conf, token, FALSE);
     620            4864 :     if (!httpd__meta_build_path(con, req, conf, token,
     621                 :                                 NULL, &canon, &lim, &ref))
     622                 :     {
     623               0 :       vstr_ref_del(ref);
     624               0 :       return (FALSE);
     625                 :     }
     626            4864 :     if (!req->direct_uri)
     627                 :     {
     628            2784 :       if (lim == HTTPD_POLICY_PATH_LIM_NONE)
     629             160 :         orig_len = req->fname->len; /* don't do more than we need */
     630                 :       else
     631                 :       {
     632            2624 :         if (!vstr_sub_vstr(req->fname, 1, req->fname->len,
     633                 :                            con->evnt->io_r, req->path_pos, req->path_len, 0))
     634                 :         {
     635               0 :           vstr_ref_del(ref);
     636               0 :           return (FALSE);
     637                 :         }
     638            2624 :         req->vhost_prefix_len = 0;
     639                 :       }
     640                 :     }
     641            4864 :     if (!httpd__build_path(con, req, conf, token,
     642                 :                            req->fname, 1, req->fname->len,
     643                 :                            lim, FALSE, ref, TRUE, &bp_type))
     644               0 :       return (FALSE);
     645            4864 :     if (!req->direct_uri && (lim == HTTPD_POLICY_PATH_LIM_NONE) &&
     646                 :         (bp_type != HTTPD_CONF_REQ__TYPE_BUILD_PATH_ASSIGN))
     647                 :     { /* we needed to do the above sub */
     648               0 :       if (!vstr_sub_vstr(req->fname, 1, orig_len,
     649                 :                          con->evnt->io_r, req->path_pos, req->path_len, 0))
     650               0 :         return (FALSE);
     651                 :     }
     652            4864 :     req->vhost_prefix_len = 0;
     653                 :     
     654            4864 :     req->direct_uri = TRUE;
     655            4864 :     HTTP_REQ__X_HDR_CHK(req->fname, 1, req->fname->len);
     656                 : 
     657            4864 :     if (canon)
     658            1024 :       httpd_req_absolute_uri(con, req, req->fname, 1, req->fname->len);
     659                 :   }
     660           31296 :   else if (OPT_SERV_SYM_EQ("Cache-Control:"))
     661                 :   { 
     662               0 :     unsigned int num = 1;
     663               0 :     unsigned int tmp = 0;
     664               0 :     Conf_token save = *token;
     665               0 :     int ern = 0;
     666                 :     
     667               0 :     if ((ern = conf_sc_token_parse_uint(conf, token, &tmp)))
     668                 :     { /* reset, as though we didn't try */
     669               0 :       *token = save;
     670               0 :       HTTPD_CONF_REQ__X_CONTENT_VSTR(cache_control);
     671                 :     }
     672               0 :     else if (!(num = tmp))
     673               0 :       return (FALSE);
     674                 :     else
     675               0 :       HTTPD_CONF_REQ__X_CONTENT_SINGLE_VSTR(cache_control);
     676                 :     
     677                 :     if (0) { /* nothing */ }
     678               0 :     else if (HTTPD__EXPIRES_CMP(cache_control, "expire-minute"))
     679               0 :       httpd__conf_req_reset_cache_control(req, (num * 60 *  1));
     680               0 :     else if (HTTPD__EXPIRES_CMP(cache_control, "expire-hour"))
     681               0 :       httpd__conf_req_reset_cache_control(req, (num * 60 * 60));
     682               0 :     else if (HTTPD__EXPIRES_CMP(cache_control, "expire-day"))
     683               0 :       httpd__conf_req_reset_cache_control(req, (num * 60 * 60 * 24));
     684               0 :     else if (HTTPD__EXPIRES_CMP(cache_control, "expire-week"))
     685               0 :       httpd__conf_req_reset_cache_control(req, (num * 60 * 60 * 24 * 7));
     686               0 :     else if (!ern) /* must be one of the above symbols */
     687               0 :       return (FALSE);
     688               0 :     else if (vstr_cmp_cstr_eq(HTTP_REQ__CONT_PARAMS(req, cache_control),
     689                 :                               "<expires-now>"))
     690               0 :       httpd__conf_req_reset_cache_control(req, 0);
     691               0 :     else if (vstr_cmp_cstr_eq(HTTP_REQ__CONT_PARAMS(req, cache_control),
     692                 :                               "<expires-never>"))
     693               0 :       httpd__conf_req_reset_cache_control(req, (60 * 60 * 24 * 365));
     694                 :     else
     695               0 :       HTTP_REQ__X_CONTENT_HDR_CHK(cache_control);
     696                 :   }
     697           31296 :   else if (OPT_SERV_SYM_EQ("Content-Disposition:"))
     698                 :   {
     699               0 :     HTTPD_CONF_REQ__X_CONTENT_VSTR(content_disposition);
     700               0 :     HTTP_REQ__X_CONTENT_HDR_CHK(content_disposition);
     701                 :   }
     702           31296 :   else if (OPT_SERV_SYM_EQ("Content-Language:"))
     703                 :   {
     704               0 :     HTTPD_CONF_REQ__X_CONTENT_VSTR(content_language);
     705               0 :     HTTP_REQ__X_CONTENT_HDR_CHK(content_language);
     706                 :   }
     707           31296 :   else if (OPT_SERV_SYM_EQ("Content-Location:"))
     708                 :   {
     709               0 :     unsigned int lim = HTTPD_POLICY_PATH_LIM_NONE;
     710               0 :     size_t pos = 0;
     711               0 :     size_t len = 0;
     712               0 :     Vstr_ref *ref = NULL;
     713                 : 
     714               0 :     if (req->direct_uri || req->direct_filename)
     715               0 :       return (FALSE);
     716                 : 
     717               0 :     if (!httpd__content_location_valid(req, &pos, &len))
     718               0 :       return (FALSE);
     719                 :     
     720               0 :     CONF_SC_PARSE_TOP_TOKEN_RET(conf, token, FALSE);
     721               0 :     if (!httpd__meta_build_path(con, req, conf, token, NULL, NULL, &lim, &ref))
     722                 :     {
     723               0 :       vstr_ref_del(ref);
     724               0 :       return (FALSE);
     725                 :     }
     726               0 :     if (!httpd__build_path(con, req, conf, token, req->xtra_content, pos, len,
     727                 :                            lim, FALSE, ref, TRUE, NULL))
     728               0 :       return (FALSE);
     729                 :     
     730               0 :     len = vstr_sc_posdiff(pos, req->xtra_content->len);
     731                 :     
     732               0 :     req->content_location_vs1 = req->xtra_content;
     733               0 :     req->content_location_pos = pos;
     734               0 :     req->content_location_len = len;
     735               0 :     HTTP_REQ__X_CONTENT_HDR_CHK(content_location);
     736                 :   }
     737           31872 :   else if (OPT_SERV_SYM_EQ("Content-MD5:") ||
     738                 :            OPT_SERV_SYM_EQ("identity/Content-MD5:"))
     739                 :   {
     740            1152 :     req->content_md5_time = file_timestamp;
     741            1152 :     HTTPD_CONF_REQ__X_CONTENT_SINGLE_VSTR(content_md5);
     742            1152 :     HTTP_REQ__X_CONTENT_HDR_CHK(content_md5);
     743                 :   }
     744           30144 :   else if (OPT_SERV_SYM_EQ("gzip/Content-MD5:"))
     745                 :   { 
     746            1152 :     req->content_md5_time = file_timestamp;
     747            1152 :     HTTPD_CONF_REQ__X_CONTENT_SINGLE_VSTR(gzip_content_md5);
     748            1152 :     HTTP_REQ__X_CONTENT_HDR_CHK(gzip_content_md5);
     749                 :   }
     750           28992 :   else if (OPT_SERV_SYM_EQ("bzip2/Content-MD5:"))
     751                 :   { 
     752            1152 :     req->content_md5_time = file_timestamp;
     753            1152 :     HTTPD_CONF_REQ__X_CONTENT_SINGLE_VSTR(bzip2_content_md5);
     754            1152 :     HTTP_REQ__X_CONTENT_HDR_CHK(bzip2_content_md5);
     755                 :   }
     756           27840 :   else if (OPT_SERV_SYM_EQ("Content-Type:"))
     757                 :   {
     758            3296 :     HTTPD_CONF_REQ__X_CONTENT_VSTR(content_type);
     759            3296 :     HTTP_REQ__X_CONTENT_HDR_CHK(content_type);
     760                 :   }
     761           24544 :   else if (OPT_SERV_SYM_EQ("ETag:"))
     762                 :   {
     763            1696 :     req->etag_time = file_timestamp;
     764            1696 :     HTTPD_CONF_REQ__X_CONTENT_VSTR(etag);
     765            1696 :     HTTP_REQ__X_CONTENT_HDR_CHK(etag);
     766                 :   }
     767           22848 :   else if (OPT_SERV_SYM_EQ("Expires:"))
     768                 :   { /* note that rfc2616 says only go upto a year into the future */
     769               0 :     unsigned int num = 1;
     770               0 :     unsigned int tmp = 0;
     771               0 :     Conf_token save = *token;
     772               0 :     int ern = 0;
     773                 :     
     774               0 :     if ((ern = conf_sc_token_parse_uint(conf, token, &tmp)))
     775                 :     { /* reset, as though we didn't try */
     776               0 :       *token = save;
     777               0 :       HTTPD_CONF_REQ__X_CONTENT_VSTR(expires);
     778                 :     }
     779               0 :     else if (!(num = tmp))
     780               0 :       return (FALSE);
     781                 :     else
     782               0 :       HTTPD_CONF_REQ__X_CONTENT_SINGLE_VSTR(expires);
     783                 :     
     784                 :     /* if we dynamically generate use current timestamp, else filetimestamp */
     785               0 :     req->expires_time = req->now;
     786                 :     if (0) { /* nothing */ }
     787               0 :     else if (HTTPD__EXPIRES_CMP(expires, "minute"))
     788               0 :       httpd__conf_req_reset_expires(req, (num * 60 *  1));
     789               0 :     else if (HTTPD__EXPIRES_CMP(expires, "hour"))
     790               0 :       httpd__conf_req_reset_expires(req, (num * 60 * 60));
     791               0 :     else if (HTTPD__EXPIRES_CMP(expires, "day"))
     792               0 :       httpd__conf_req_reset_expires(req, (num * 60 * 60 * 24));
     793               0 :     else if (HTTPD__EXPIRES_CMP(expires, "week"))
     794               0 :       httpd__conf_req_reset_expires(req, (num * 60 * 60 * 24 * 7));
     795               0 :     else if (!ern) /* must be one of the above symbols */
     796               0 :       return (FALSE);
     797               0 :     else if (vstr_cmp_cstr_eq(HTTP_REQ__CONT_PARAMS(req, expires), "<now>"))
     798               0 :       httpd__conf_req_reset_expires(req, 0);
     799               0 :     else if (vstr_cmp_cstr_eq(HTTP_REQ__CONT_PARAMS(req, expires), "<never>"))
     800               0 :       httpd__conf_req_reset_expires(req, (60 * 60 * 24 * 365));
     801                 :     else
     802                 :     {
     803               0 :       req->expires_time = file_timestamp;
     804               0 :       HTTP_REQ__X_CONTENT_HDR_CHK(expires);
     805                 :     }
     806                 :   }
     807           22848 :   else if (OPT_SERV_SYM_EQ("Link:")) /* rfc2068 -- old, but still honored */
     808                 :   {
     809             640 :     HTTPD_CONF_REQ__X_CONTENT_VSTR(link);
     810             640 :     HTTP_REQ__X_CONTENT_HDR_CHK(link);
     811                 :   }
     812           22208 :   else if (OPT_SERV_SYM_EQ("P3P:")) /* http://www.w3.org/TR/P3P/ */
     813                 :   {
     814               0 :     HTTPD_CONF_REQ__X_CONTENT_VSTR(p3p);
     815               0 :     HTTP_REQ__X_CONTENT_HDR_CHK(p3p);
     816                 :   }
     817           22208 :   else if (OPT_SERV_SYM_EQ("filename"))
     818                 :   {
     819            7104 :     int full = req->skip_document_root;
     820            7104 :     unsigned int lim = HTTPD_POLICY_PATH_LIM_NAME_FULL;
     821            7104 :     Vstr_ref *ref = NULL;
     822                 :     
     823            7104 :     if (req->direct_uri)
     824               0 :       return (FALSE);
     825            7104 :     CONF_SC_PARSE_TOP_TOKEN_RET(conf, token, FALSE);
     826            7104 :     if (!httpd__meta_build_path(con, req, conf, token, &full, NULL, &lim, &ref))
     827                 :     {
     828               0 :       vstr_ref_del(ref);
     829               0 :       return (FALSE);
     830                 :     }
     831            7104 :     if (!httpd__build_path(con, req, conf, token,
     832                 :                            req->fname, 1, req->fname->len,
     833                 :                            lim, full, ref, FALSE, NULL))
     834               0 :       return (FALSE);
     835            7104 :     if (!req->skip_document_root &&
     836                 :         !(req->conf_flags & HTTPD_CONF_REQ_FLAGS_PARSE_FILE_DIRECT) &&
     837                 :         (!req->fname->len || !vstr_cmp_cstr_eq(req->fname, 1, 1, "/")))
     838              32 :       vstr_add_cstr_ptr(req->fname, 0, "/");
     839            7104 :     req->direct_filename = TRUE;
     840                 :   }
     841           15104 :   else if (OPT_SERV_SYM_EQ("parse-accept"))
     842               0 :     OPT_SERV_X_TOGGLE(req->parse_accept);
     843           15104 :   else if (OPT_SERV_SYM_EQ("parse-accept-language"))
     844               0 :     OPT_SERV_X_TOGGLE(req->parse_accept_language);
     845           15232 :   else if (OPT_SERV_SYM_EQ("allow-accept-encoding") ||
     846                 :            OPT_SERV_SYM_EQ("parse-accept-encoding"))
     847             128 :     OPT_SERV_X_TOGGLE(req->allow_accept_encoding);
     848           14976 :   else if (OPT_SERV_SYM_EQ("Vary:_*"))
     849               0 :     OPT_SERV_X_TOGGLE(req->vary_star);
     850           14976 :   else if (OPT_SERV_SYM_EQ("Vary:_Accept"))
     851              96 :     OPT_SERV_X_TOGGLE(req->vary_a);
     852           14880 :   else if (OPT_SERV_SYM_EQ("Vary:_Accept-Charset"))
     853              96 :     OPT_SERV_X_TOGGLE(req->vary_ac);
     854           14784 :   else if (OPT_SERV_SYM_EQ("Vary:_Accept-Encoding")) /* doesn't help */
     855              96 :     OPT_SERV_X_TOGGLE(req->vary_ae);
     856           14688 :   else if (OPT_SERV_SYM_EQ("Vary:_Accept-Language"))
     857              96 :     OPT_SERV_X_TOGGLE(req->vary_al);
     858           14688 :   else if (OPT_SERV_SYM_EQ("Vary:_Referer") ||
     859                 :            OPT_SERV_SYM_EQ("Vary:_Referrer"))
     860              96 :     OPT_SERV_X_TOGGLE(req->vary_rf);
     861           14496 :   else if (OPT_SERV_SYM_EQ("Vary:_User-Agent"))
     862              96 :     OPT_SERV_X_TOGGLE(req->vary_ua);
     863           14400 :   else if (OPT_SERV_SYM_EQ("Vary:_If-Modified-Since"))
     864              96 :     OPT_SERV_X_TOGGLE(req->vary_ims);
     865           14304 :   else if (OPT_SERV_SYM_EQ("Vary:_If-Unmodified-Since"))
     866              96 :     OPT_SERV_X_TOGGLE(req->vary_ius);
     867           14208 :   else if (OPT_SERV_SYM_EQ("Vary:_If-Range"))
     868              96 :     OPT_SERV_X_TOGGLE(req->vary_ir);
     869           14112 :   else if (OPT_SERV_SYM_EQ("Vary:_If-Match"))
     870              96 :     OPT_SERV_X_TOGGLE(req->vary_im);
     871           14016 :   else if (OPT_SERV_SYM_EQ("Vary:_If-None-Match"))
     872              96 :     OPT_SERV_X_TOGGLE(req->vary_inm);
     873           15520 :   else if (OPT_SERV_SYM_EQ("content-lang-ext") ||
     874                 :            OPT_SERV_SYM_EQ("content-language-ext") ||
     875                 :            OPT_SERV_SYM_EQ("content-language-extension"))
     876            3200 :     HTTPD_CONF_REQ__X_CONTENT_VSTR(ext_vary_al);
     877           12320 :   else if (OPT_SERV_SYM_EQ("content-type-ext") ||
     878                 :            OPT_SERV_SYM_EQ("content-type-extension"))
     879            3200 :     HTTPD_CONF_REQ__X_CONTENT_VSTR(ext_vary_a);
     880            9360 :   else if (OPT_SERV_SYM_EQ("content-type-neg") ||
     881                 :            OPT_SERV_SYM_EQ("content-type-negotiate") ||
     882                 :            OPT_SERV_SYM_EQ("negotiate-content-type"))
     883                 :   {
     884            3680 :     if (req->neg_content_type_done)
     885               0 :       return (FALSE);
     886           14720 :     HTTPD__NEG_BEG(req->policy->max_neg_A_nodes);
     887            7360 :     qual = http_parse_accept(req, conf->data, val->pos, val->len);
     888           11040 :     HTTPD__NEG_END();    
     889                 : 
     890            3680 :     req->neg_content_type_done = TRUE;
     891            3680 :     req->vary_a = TRUE;
     892            3680 :     if (qual_num)
     893                 :     {
     894            2848 :       unsigned int last = token->num;
     895                 : 
     896            2848 :       req->parse_accept = FALSE;
     897            2848 :       *token = save;
     898            2848 :       conf_parse_num_token(conf, token, qual_num);
     899            2848 :       HTTPD_CONF_REQ__X_CONTENT_SINGLE_VSTR(content_type);
     900            2848 :       HTTP_REQ__X_CONTENT_HDR_CHK(content_type);
     901            2848 :       HTTPD_CONF_REQ__X_CONTENT_SINGLE_VSTR(ext_vary_a);
     902            2848 :       conf_parse_num_token(conf, token, last);
     903                 :     }
     904                 :   }
     905                 :   /*  else if (OPT_SERV_SYM_EQ("negotiate-charset"))
     906                 :       return (FALSE); */
     907            5760 :   else if (OPT_SERV_SYM_EQ("content-lang-neg") ||
     908                 :            OPT_SERV_SYM_EQ("content-lang-negotiate") ||
     909                 :            OPT_SERV_SYM_EQ("content-language-negotiate") ||
     910                 :            OPT_SERV_SYM_EQ("negotiate-content-language"))
     911                 :   {
     912            3840 :     if (req->neg_content_lang_done)
     913               0 :       return (FALSE);
     914           29440 :     HTTPD__NEG_BEG(req->policy->max_neg_AL_nodes);
     915           21760 :     qual = http_parse_accept_language(req, conf->data, val->pos, val->len);
     916           25600 :     HTTPD__NEG_END();
     917                 : 
     918            3840 :     req->neg_content_lang_done = TRUE;
     919            3840 :     req->vary_al = TRUE;
     920            3840 :     if (qual_num)
     921                 :     {
     922            3680 :       unsigned int last = token->num;
     923                 : 
     924            3680 :       req->parse_accept_language = FALSE;
     925            3680 :       *token = save;
     926            3680 :       conf_parse_num_token(conf, token, qual_num);
     927            3680 :       HTTPD_CONF_REQ__X_CONTENT_SINGLE_VSTR(content_language);
     928            3680 :       HTTP_REQ__X_CONTENT_HDR_CHK(content_language);
     929            3680 :       HTTPD_CONF_REQ__X_CONTENT_SINGLE_VSTR(ext_vary_al);
     930            3680 :       conf_parse_num_token(conf, token, last);
     931                 :     }
     932                 :   }
     933                 :   else
     934               0 :     return (FALSE);
     935                 :   
     936           36768 :   return (TRUE);
     937                 : }
     938                 : #undef HTTPD__CONF_REDIR
     939                 : #undef HTTPD__EXPIRES_CMP
     940                 : #undef HTTPD__NEG_BEG
     941                 : #undef HTTPD__NEG_END
     942                 : 
     943                 : int httpd_conf_req_d0(struct Con *con, Httpd_req_data *req,
     944                 :                       time_t timestamp,
     945                 :                       Conf_parse *conf, Conf_token *token)
     946           13216 : {
     947           13216 :   unsigned int cur_depth = token->depth_num;
     948                 :   
     949           13216 :   if (!OPT_SERV_SYM_EQ("org.and.httpd-conf-req-1.0") &&
     950                 :       !OPT_SERV_SYM_EQ("org.and.jhttpd-conf-req-1.0"))
     951               0 :     return (FALSE);
     952                 :   
     953           56208 :   while (conf_token_list_num(token, cur_depth))
     954                 :   {
     955           40512 :     int clist = FALSE;
     956                 :     
     957           40512 :     CONF_SC_PARSE_DEPTH_TOKEN_RET(conf, token, cur_depth, FALSE);
     958           40512 :     CONF_SC_TOGGLE_CLIST_VAR(clist);
     959                 : 
     960           40512 :     if (!httpd__conf_req_d1(con, req, timestamp, conf, token, clist))
     961            4128 :       return (FALSE);
     962                 :   }
     963                 : 
     964            9088 :   if (req->content_location_vs1)
     965                 :   { /* absolute URI content-location header */
     966               0 :     size_t pos = 0;
     967               0 :     size_t len = 0;
     968                 : 
     969               0 :     if (!httpd__content_location_valid(req, &pos, &len))
     970               0 :       return (FALSE);
     971                 :     
     972               0 :     httpd_req_absolute_uri(con, req, req->xtra_content, pos, len);
     973               0 :     req->content_location_len = vstr_sc_posdiff(pos, req->xtra_content->len);
     974                 :   }
     975                 : 
     976            9088 :   return (TRUE);
     977                 : }
     978                 : 
     979                 : int httpd_conf_req_parse_file(Conf_parse *conf,
     980                 :                               struct Con *con, Httpd_req_data *req,
     981                 :                               size_t del_len)
     982           38777 : {
     983           38777 :   Conf_token token[1] = {CONF_TOKEN_INIT};
     984           38777 :   Vstr_base *fname = req->fname;
     985           38777 :   Vstr_base *s1 = NULL;
     986           38777 :   const char *fname_cstr = NULL;
     987           38777 :   int fd = -1;
     988                 :   struct stat64 cf_stat[1];
     989           38777 :   int open_flags = O_NONBLOCK;
     990                 : 
     991           19396 :   ASSERT(conf && con && req && fname && (del_len < fname->len));
     992                 :   
     993           38777 :   s1 = conf->tmp;
     994                 : 
     995           38777 :   if (req->conf_flags & HTTPD_CONF_REQ_FLAGS_PARSE_FILE_DIRECT)
     996           10904 :     HTTPD_APP_REF_VSTR(s1, fname, 1, fname->len - del_len);
     997                 :   else
     998                 :   {
     999           27873 :     Vstr_base *dir = req->policy->req_conf_dir;
    1000                 : 
    1001           13944 :     ASSERT(dir);
    1002                 : 
    1003           27873 :     if (!dir->len ||
    1004                 :         !req->policy->use_req_conf || req->skip_document_root)
    1005            6577 :       return (TRUE);
    1006                 :     
    1007           21296 :     HTTPD_APP_REF_ALLVSTR(s1, dir);
    1008           10648 :     ASSERT((dir->len   >= 1) && vstr_cmp_cstr_eq(dir,   dir->len, 1, "/"));
    1009           10648 :     ASSERT((fname->len >= 1) && vstr_cmp_cstr_eq(fname,        1, 1, "/"));
    1010           21296 :     HTTPD_APP_REF_VSTR(s1, fname, 2, fname->len - (1 + del_len));
    1011                 :   }
    1012                 :   
    1013           32200 :   if (s1->conf->malloc_bad ||
    1014                 :       !(fname_cstr = vstr_export_cstr_ptr(s1, 1, s1->len)))
    1015                 :     goto read_fail;
    1016                 :   
    1017           32200 :   if (req->policy->use_noatime)
    1018               0 :     open_flags |= O_NOATIME;
    1019                 :     
    1020           32200 :   fd = io__open(fname_cstr, open_flags);
    1021           32200 :   if ((fd == -1) && (errno == EISDIR))
    1022               0 :     goto fin_dir;
    1023                 : 
    1024           32200 :   if ((fd == -1) &&
    1025                 :       ((errno == ENOTDIR) || /* part of path was not a dir */
    1026                 :        (errno == ENAMETOOLONG)))
    1027               0 :     goto fin_file; /* ignore these errors, not local users fault */
    1028                 : 
    1029           32200 :   if ((fd == -1) && (errno == ENOENT))
    1030           27208 :     goto fin_ok; /* ignore these errors, not local users fault */
    1031                 : 
    1032            4992 :   if (fd == -1)
    1033               0 :     goto read_fail; /* this is "bad" */
    1034                 :   
    1035            4992 :   if (fstat64(fd, cf_stat) == -1)
    1036               0 :     goto close_read_fail; /* this is "bad" */
    1037                 :   
    1038            4992 :   if (S_ISDIR(cf_stat->st_mode))
    1039              32 :     goto fin_close_dir; /* ignore */
    1040                 :   
    1041            4960 :   if (!S_ISREG(cf_stat->st_mode))
    1042               0 :     goto close_read_fail; /* this is "bad" */
    1043                 : 
    1044            4960 :   if ((cf_stat->st_size < strlen("org.and.httpd-conf-req-1.0")) ||
    1045                 :       (cf_stat->st_size > req->policy->max_req_conf_sz))
    1046                 :     goto close_read_fail; /* this is "bad" */
    1047                 : 
    1048            4960 :   s1 = conf->data;
    1049            4960 :   vstr_del(conf->tmp,  1, conf->tmp->len); /* filename */
    1050                 : 
    1051           14880 :   while (cf_stat->st_size > s1->len)
    1052                 :   {
    1053            4960 :     size_t len = cf_stat->st_size - s1->len;
    1054                 :     
    1055            4960 :     if (!vstr_sc_read_len_fd(s1, s1->len, fd, len, NULL) ||
    1056                 :         (len == (cf_stat->st_size - s1->len)))
    1057                 :       goto close_read_fail;
    1058                 :   }
    1059                 :   
    1060            4960 :   close(fd);
    1061                 :     
    1062            4960 :   if (!conf_parse_lex(conf, 1, conf->data->len))
    1063               0 :     goto conf_fail;
    1064                 : 
    1065           12176 :   while (conf_parse_token(conf, token))
    1066                 :   {
    1067            4960 :     if ((token->type != CONF_TOKEN_TYPE_CLIST) || (token->depth_num != 1))
    1068                 :       goto conf_fail;
    1069                 : 
    1070            4960 :     if (!conf_parse_token(conf, token))
    1071               0 :       goto conf_fail;
    1072                 :     
    1073            4960 :     if (!conf_token_cmp_sym_cstr_eq(conf, token,
    1074                 :                                     "org.and.httpd-conf-req-1.0") &&
    1075                 :         !conf_token_cmp_sym_cstr_eq(conf, token,
    1076                 :                                     "org.and.jhttpd-conf-req-1.0"))
    1077               0 :       goto conf_fail;
    1078                 :   
    1079            4960 :     if (!httpd_conf_req_d0(con, req, cf_stat->st_mtime, conf, token))
    1080             224 :       goto conf_fail;
    1081                 :   }
    1082                 : 
    1083                 :   /* And they all live together ... dum dum */
    1084            4736 :   if (conf->data->conf->malloc_bad)
    1085               0 :     goto read_fail;
    1086                 : 
    1087            4736 :   return (TRUE);
    1088                 : 
    1089              32 :  fin_close_dir:
    1090              32 :   close(fd);
    1091              32 :  fin_dir:
    1092              32 :   req->conf_friendly_file = TRUE;
    1093              32 :   if (req->policy->use_secure_dirs &&
    1094                 :       !(req->conf_flags & HTTPD_CONF_REQ_FLAGS_PARSE_FILE_NONMAIN))
    1095                 :   { /* check if conf file exists inside the directory given,
    1096                 :      * so we can re-direct without leaking info. */
    1097                 :     struct stat64 d_stat[1];
    1098                 :     
    1099              32 :     vstr_add_cstr_buf(s1, s1->len, "/");
    1100              32 :     HTTPD_APP_REF_ALLVSTR(s1, req->policy->dir_filename);
    1101                 :     
    1102              32 :     fname_cstr = vstr_export_cstr_ptr(s1, 1, s1->len);
    1103              32 :     if (s1->conf->malloc_bad)
    1104               0 :       goto read_fail;
    1105              32 :     if ((stat64(fname_cstr, d_stat) != -1) && S_ISREG(d_stat->st_mode))
    1106              32 :       req->conf_secure_dirs = TRUE;
    1107                 :   }
    1108                 : 
    1109              16 :   ASSERT(s1 == conf->tmp);
    1110              32 :   vstr_del(s1, 1, s1->len);
    1111              32 :   return (TRUE);
    1112                 :   
    1113               0 :  fin_file:
    1114               0 :   if (req->policy->use_friendly_dirs &&
    1115                 :       !(req->conf_flags & HTTPD_CONF_REQ_FLAGS_PARSE_FILE_NONMAIN))
    1116                 :   { /* check if conf file exists as a file, so we can re-direct backwards */
    1117                 :     struct stat64 d_stat[1];
    1118               0 :     size_t len = vstr_cspn_cstr_chrs_rev(s1, 1, s1->len, "/") + 1;
    1119                 : 
    1120               0 :     if ((len > 1) && (len < (s1->len - req->vhost_prefix_len)))
    1121                 :     { /* must be a filename, can't be toplevel */
    1122               0 :       vstr_sc_reduce(s1, 1, s1->len, len);
    1123                 :     
    1124               0 :       fname_cstr = vstr_export_cstr_ptr(s1, 1, s1->len);
    1125               0 :       if (s1->conf->malloc_bad)
    1126               0 :         goto read_fail;
    1127               0 :       if ((stat64(fname_cstr, d_stat) != -1) && S_ISREG(d_stat->st_mode))
    1128               0 :         req->conf_friendly_dirs = TRUE;
    1129                 :     }
    1130                 :   }
    1131                 :   
    1132           27208 :  fin_ok:
    1133           13604 :   ASSERT(s1 == conf->tmp);
    1134           27208 :   vstr_del(s1, 1, s1->len);
    1135           27208 :   return (TRUE);
    1136                 : 
    1137               0 :  close_read_fail:
    1138               0 :   vstr_del(conf->data, 1, conf->data->len);
    1139               0 :   vstr_del(conf->tmp,  1, conf->tmp->len);
    1140               0 :   close(fd);
    1141               0 :   goto read_fail;
    1142                 :   
    1143             224 :  conf_fail:
    1144             224 :   vstr_del(conf->tmp,  1, conf->tmp->len);
    1145             224 :   if (!req->user_return_error_code &&
    1146                 :       !(req->conf_flags & HTTPD_CONF_REQ_FLAGS_PARSE_FILE_NONMAIN))
    1147               0 :     conf_parse_backtrace(conf->tmp, "<conf-request>", conf, token);
    1148             224 :  read_fail:
    1149             224 :   if (!req->user_return_error_code)
    1150               0 :     HTTPD_ERR_MSG(req, 503, "Req conf parse error");
    1151             224 :   conf->data->conf->malloc_bad = FALSE;
    1152             224 :   return (FALSE);
    1153                 : }

Generated by: LTP GCOV extension version 1.4