var.c
上传用户:ladybrid91
上传日期:2007-01-04
资源大小:287k
文件大小:20k
源码类别:

Web服务器

开发平台:

Unix_Linux

  1. /*
  2. ** var.c
  3. **
  4. ** Copyright (c) 1995 Marcus E. Hennecke <marcush@leland.stanford.edu>
  5. **
  6. ** This program is free software; you can redistribute it and/or modify
  7. ** it under the terms of the GNU General Public License as published by
  8. ** the Free Software Foundation; either version 2 of the License, or
  9. ** (at your option) any later version.
  10. **
  11. ** This program is distributed in the hope that it will be useful,
  12. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. ** GNU General Public License for more details.
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program; if not, write to the Free Software
  17. ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <time.h>
  22. #include <string.h>
  23. #include <fcntl.h>
  24. #include <unistd.h>
  25. #include <errno.h>
  26. #include <math.h>
  27. #include <alloca.h>
  28. #include <sys/types.h>
  29. #include <sys/stat.h>
  30. #include "phttpd.h"
  31. /***********************************************************************/
  32. /* The code below should probably go in table.c.        */
  33. /* Deletes and at the same time frees entries pos1 to pos2 (inclusive) */
  34. /* of a table. */
  35. int tbl_remove(struct table *tp, int pos1, int pos2,
  36.        void (*val_free)(void *val))
  37. {
  38.     int i;
  39.     if (pos2 < pos1)
  40. return tp->length;
  41.     mutex_lock(&tp->lock);
  42.     for (i = pos1; i <= pos2; i++)
  43. (*val_free)(tp->value[i]);
  44.     for (pos2++; pos2 < tp->length; pos1++, pos2++)
  45. tp->value[pos1] = tp->value[pos2];
  46.     tp->length = pos1;
  47.     for (; pos1 < pos2; pos1++)
  48. tp->value[pos1] = NULL;
  49.     
  50.     mutex_unlock(&tp->lock);
  51.     
  52.     return tp->length;
  53. }
  54. /* The code above should probably go in table.c.        */
  55. /***********************************************************************/
  56. /***********************************************************************/
  57. /* These type definitions and the following functions should probably */
  58. /* go in mime.h and mime.c since they are general and they could be */
  59. /* useful to other modules. */
  60. /* mimetype holds MIME information */
  61. struct mimetype
  62. {
  63.     char *content_type;
  64.     float q;
  65.     float mxb;
  66.     float version;
  67. };
  68. /* This is to hold all necessary information for a variant */
  69. struct variantinfo
  70. {
  71.     char *url;
  72.     struct mimetype mt;
  73.     char *content_charset;
  74.     char *content_language;
  75.     char *content_encoding;
  76.     int   content_length;
  77. };
  78. void mime_free(void *p)
  79. {
  80.     struct mimetype *mtp = (struct mimetype *)p;
  81.     if (!mtp) return;
  82.     if (mtp->content_type)
  83. s_free(mtp->content_type);
  84.     s_free(mtp);
  85. }
  86. /* This is just for debugging purposes. */
  87. void print_variant(struct variantinfo *vip)
  88. {
  89.     fprintf(stderr, "Variant URL: %sn", vip->url);
  90.     if (vip->mt.content_type)
  91. fprintf(stderr, "t%s; q=%3.1f; mxb=%3.1f; version=%3.1fn",
  92. vip->mt.content_type, vip->mt.q, vip->mt.mxb,
  93. vip->mt.version);
  94.     if (vip->content_charset)
  95. fprintf(stderr, "t%sn", vip->content_charset);
  96.     if (vip->content_language)
  97. fprintf(stderr, "t%sn", vip->content_language);
  98.     if (vip->content_encoding)
  99. fprintf(stderr, "t%sn", vip->content_encoding);
  100.     if (vip->content_length)
  101. fprintf(stderr, "t%dn", vip->content_length);
  102. }
  103. void variant_free(void *p)
  104. {
  105.     struct variantinfo *vip = (struct variantinfo *)p;
  106.     if (!vip) return;
  107.     if (vip->url)
  108. s_free(vip->url);
  109.     if (vip->mt.content_type)
  110. s_free(vip->mt.content_type);
  111.     if (vip->content_charset)
  112. s_free(vip->content_charset);
  113.     if (vip->content_language)
  114. s_free(vip->content_language);
  115.     if (vip->content_encoding)
  116. s_free(vip->content_encoding);
  117.     s_free(vip);
  118. }
  119. /* Compares two mime types. Takes care of * wild cards. */
  120. int mime_typecmp(void *p1, void *p2)
  121. {
  122.     char *cp1 = (char*)p1;
  123.     char *cp2 = (char*)p2;
  124.     char *cp;
  125.     int len;
  126.     if (cp1[0] == '*' || cp2[0] == '*')
  127. return 1;
  128.     cp = strchr(cp1, '/');
  129.     if (!cp)
  130. return 0;
  131.     len = cp+1 - cp1;
  132.     if (strncasecmp(cp1, cp2, len))
  133. return 0;
  134.     cp1 += len;
  135.     cp2 += len;
  136.     if (cp1[0] == '*' || cp2[0] == '*')
  137. return 1;
  138.     return (strcasecmp(cp1, cp2) == 0);
  139. }
  140. /* The following are all just wrapper functions to be used for the */
  141. /* tbl_foreach function. */
  142. /* Compare the encoding. */
  143. static int encodingcmp(void *cp1, void *cp2)
  144. {
  145.     return(cp1 && cp2 && strcasecmp((char*)cp1, (char*)cp2) == 0);
  146. }
  147. /* Compare the languages. */
  148. static int languagecmp(void *lang1, void *lang2)
  149. {
  150.     return(lang1 && lang2 && strcasecmp((char*)lang1, (char*)lang2) == 0);
  151. }
  152. static int check_languages(void *vip, void *al)
  153. {
  154.     return(tbl_foreach((struct table *)al, languagecmp,
  155.        ((struct variantinfo *)vip)->content_language));
  156. }
  157. /* Reads mime type and evaluates parameters. Fills a mimtype structure. */
  158. void mime_gettype(char *buf, struct mimetype *mtp)
  159. {
  160.     char ch, *cp, *val;
  161.     int equals;
  162.     mtp->q = 1.0;
  163.     mtp->mxb = 0.0;
  164.     mtp->version = 0.0;
  165.     for (ch = *(cp = buf);
  166.  ch && !s_isspace(ch) && ch != ';';
  167.  ch = *++cp )
  168. ;
  169.     *cp = '';
  170.     mtp->content_type = s_strdup(buf);
  171.     if (debug > 5)
  172. fprintf(stderr, "tmime_gettype: content_type %sn", buf);
  173.     while (ch)
  174.     {
  175. for ( ; ch && (s_isspace(ch) || ch == ';'); ch = *++cp )
  176.     ;
  177. if (!ch)
  178.     break;
  179. buf = cp;
  180. for ( ; ch && !s_isspace(ch) && ch != '='; ch = *++cp )
  181.     ;
  182. if (!ch)
  183.     break;
  184. *cp = '';
  185. for ( equals = 0; ch && (s_isspace(ch) || ch == '='); ch = *++cp )
  186.     if (ch == '=')
  187. equals = 1;
  188. if (!equals)
  189.     break;
  190. val = cp;
  191. for ( ; ch && !s_isspace(ch) && ch != '='; ch = *++cp )
  192.     ;
  193. *cp = '';
  194. if (s_tolower(buf[0]) == 'q' &&
  195.     ( buf[1] == '' ||
  196.      (s_tolower(buf[1]) == 's' && buf[2] == '') ) )
  197. {
  198.     mtp->q = atof(val);
  199.     if (mtp->q < 0.0)
  200. mtp->q = 0.0;
  201.     if (mtp->q > 1.0)
  202. mtp->q = 1.0;
  203.     if (debug > 5)
  204. fprintf(stderr, "tmime_gettype: q=%3.1fn", mtp->q);
  205. }
  206. else
  207. if (s_tolower(buf[0]) == 'm' && buf[1] == 'x' &&
  208.     s_tolower(buf[2]) == 'b' && buf[3] == '')
  209. {
  210.     mtp->mxb = atof(val);
  211.     sscanf(val,"%f",&(mtp->mxb));
  212.     if (mtp->mxb < 0.0)
  213. mtp->mxb = 0.0;
  214.     if (debug > 5)
  215. fprintf(stderr, "tmime_gettype: mxb=%3.1fn", mtp->mxb);
  216. }
  217. else
  218. if (!strcasecmp(buf, "version") || !strcasecmp(buf, "level"))
  219. {
  220.     mtp->version = atof(val);
  221.     if (mtp->version < 0.0)
  222. mtp->version = 0.0;
  223.     if (debug > 5)
  224. fprintf(stderr, "tmime_gettype: version=%3.1fn", mtp->version);
  225. }
  226.     }
  227.     /* Assumes that every browser understand at least 2.0 */
  228.     if (mtp->version == 0.0 &&
  229. (!strcmp("text/html", mtp->content_type) ||
  230.  !strcmp("*/*", mtp->content_type)))
  231. mtp->version = 2.0;
  232. }
  233. /* Fills in the missing file sizes in the variants table. */
  234. static void fill_mxb(struct table *vtp, const char *base)
  235. {
  236.     struct variantinfo *vip;
  237.     int i;
  238.     struct stat sb;
  239.     char *url, *baseend, buf[1025], path[1025];
  240.     baseend = NULL;
  241.     for (i = 0; i < vtp->length; i++)
  242.     {
  243. vip = vtp->value[i];
  244. if (vip->mt.mxb <= 0.0)
  245. {
  246.     url = vip->url;
  247.     if (url[0] != '/')
  248.     {
  249. if (!baseend)
  250. {
  251.     s_strcpy(buf, sizeof(buf), base);
  252.     baseend = strrchr(buf, '/') + 1;
  253. }
  254. s_strcpy(baseend, sizeof(buf)-(baseend-buf), url);
  255. url = buf;
  256.     }
  257.     if (url_expand(url, path, sizeof(path), &sb, NULL,
  258.    NULL))
  259. vip->mt.mxb = (float)sb.st_size;
  260. }
  261.     }
  262. }
  263. /* Try to find the best match between a mime type and the variant */
  264. /* entries in the variants table. Return the quality of the best */
  265. /* match. This is used to eliminate Accept headers. */
  266. static float mime_variant_match(struct mimetype *mip, struct table *vtp)
  267. {
  268.     struct variantinfo *vip;
  269.     float q, maxq = 0.0;
  270.     int i;
  271.     if (debug > 7)
  272. fprintf(stderr,"mime_variant_matchn");
  273.     for ( i = 0; i < vtp->length; i++ )
  274.     {
  275. vip = vtp->value[i];
  276. if (mime_typecmp(mip->content_type, vip->mt.content_type))
  277. {
  278.     q = mip->q * vip->mt.q;
  279.     if ( q > maxq)
  280. maxq = q;
  281. }
  282.     }
  283.     if (debug > 7)
  284. fprintf(stderr,"mime_variant_match returning %3.1fn", maxq);
  285.     return maxq;
  286. }
  287. /* Convert the accept table into a table with mime type entries. This */
  288. /* makes it easier to handle mime parameters such as quality factor, */
  289. /* version, and mxb. */
  290. static struct table *convert_accept(struct table *tp, struct table *vtp,
  291.     int *sflag)
  292. {
  293.     struct table *atp;
  294.     int i, sizeflag = 0;
  295.     struct mimetype *mtp;
  296.     if (debug > 6)
  297. fprintf(stderr, "Converting %d accept headersn", tp->length);
  298.     atp = tbl_create(tp->length);
  299.     for ( i = 0; i < tp->length; i++ )
  300.     {
  301. mtp = s_malloc(sizeof(struct mimetype));
  302. if (!mtp)
  303. {
  304.     tbl_free(atp, mime_free);
  305.     return NULL;
  306. }
  307. mime_gettype((char*)(tp->value[i]), mtp);
  308. if ( mime_variant_match(mtp, vtp) > 0.0 )
  309. {
  310.     tbl_append(atp, mtp);
  311.     if ( mtp->mxb > 0.0 )
  312. sizeflag = 1;
  313. }
  314. else
  315.     mime_free(mtp);
  316.     }
  317.     if (debug > 6)
  318. fprintf(stderr, "Returning %d accept headersn", atp->length);
  319.     *sflag = sizeflag;
  320.     return atp;
  321. }
  322. /* The following functions evaluate matches between the various Accept */
  323. /* headers and the variants. */
  324. /* Try to find the best match between a mime type and the mime type */
  325. /* entries in the accept table. Return the quality of the best */
  326. /* match. This is used to eliminate variants. */
  327. static float mime_match(struct mimetype *mip1, struct table *atp)
  328. {
  329.     struct mimetype *mip2;
  330.     float q, maxq = 0.0;
  331.     int i;
  332.     if (debug > 7)
  333. fprintf(stderr,"mime_matchn");
  334.     for ( i = 0; i < atp->length; i++ )
  335.     {
  336. mip2 = atp->value[i];
  337. if (debug > 8)
  338. {
  339.     fprintf(stderr,"Comparing %s; q=%3.1f; mxb=%3.1f; version=%3.1fn",
  340.     mip1->content_type, mip1->q, mip1->mxb, mip1->version);
  341.     fprintf(stderr,"     with %s; q=%3.1f; mxb=%3.1f; version=%3.1fn",
  342.     mip2->content_type, mip2->q, mip2->mxb, mip2->version);
  343. }
  344. if (mime_typecmp(mip1->content_type, mip2->content_type))
  345. {
  346.     q = mip1->q * mip2->q;
  347.     if (mip2->mxb > 0.0 && mip2->mxb < mip1->mxb)
  348. q = 0.0;
  349.     if (mip2->version < mip1->version)
  350. q = 0.0;
  351.     if ( q > maxq)
  352. maxq = q;
  353. }
  354.     }
  355.     if (debug > 7)
  356. fprintf(stderr,"mime_match returning %3.1fn", maxq);
  357.     return maxq;
  358. }
  359. /* Returns the index of the language (languages are listed in the */
  360. /* order they are prefered; the first language is the favorite). */
  361. static int find_language(char *lang, struct table *atp)
  362. {
  363.     int i;
  364.     for (i = 0; i < atp->length; i++)
  365. if (languagecmp(lang, atp->value[i]))
  366.     return i;
  367.     return atp->length;
  368. }
  369. /* Returns the size of the variant. If necessary, fills in the */
  370. /* information by looking up the file itself. */
  371. static float get_mxb(struct variantinfo *vip, const char *base)
  372. {
  373.     struct stat sb;
  374.     char *url, *baseend, buf[1025], path[1025];
  375.     if (vip->mt.mxb <= 0.0)
  376.     {
  377. url = vip->url;
  378. if (url[0] != '/')
  379. {
  380.     s_strcpy(buf, sizeof(buf), base);
  381.     baseend = strrchr(buf, '/') + 1;
  382.     s_strcpy(baseend, sizeof(buf)-(baseend-buf), url);
  383.     url = buf;
  384. }
  385. if (url_expand(url, path, sizeof(path), &sb, NULL,
  386.        NULL))
  387.     vip->mt.mxb = (float)sb.st_size;
  388.     }
  389.     return vip->mt.mxb;
  390. }
  391. /* This is the core function for content negotiation. */
  392. char *mime_negotiate(struct table *variants, struct mimeinfo *mip,
  393.      const char *base)
  394. {
  395.     struct variantinfo *vip;
  396.     struct mimetype *mtp;
  397.     int i;
  398.     float q, maxq = 0.0;
  399.     float v, maxv = 0.0;
  400.     int l, minl = 10000000;
  401.     float s, mins = 1e23;
  402.     struct table *atp;
  403.     /* Create empty mime info if none given. */
  404.     if (!mip)
  405.     {
  406. mip = (struct mimeinfo *) alloca(sizeof(struct mimeinfo));
  407. mip->version = 1;
  408.     }
  409.     /* Get rid of invalid encodings */
  410.     for ( i = 0; i < variants->length; i++ )
  411.     {
  412.         vip = (struct variantinfo *)(variants->value[i]);
  413. if (vip->content_encoding)
  414. {
  415.     if (!mip->accept_encoding)
  416.     {
  417. variant_free(vip);
  418. tbl_delete(variants,i--);
  419.     }
  420.     else
  421.     {
  422. if (!tbl_foreach(mip->accept_encoding,
  423.  encodingcmp, vip->content_encoding))
  424. {
  425.     variant_free(vip);
  426.     tbl_delete(variants,i--);
  427. }
  428.     }
  429. }
  430.     }
  431.     /* Get rid of invalid languages */
  432.     if (mip->accept_language)
  433.     {
  434. /* Before we eliminate anything, check if we can even offer */
  435. /* one of those languages. Otherwise, just skip this step. */
  436. if (tbl_foreach(variants, check_languages, mip->accept_language))
  437. {
  438.     for ( i = 0; i < variants->length; i++ )
  439.     {
  440. vip = (struct variantinfo *)(variants->value[i]);
  441. if (!check_languages(vip, mip->accept_language))
  442. {
  443.     variant_free(vip);
  444.     tbl_delete(variants,i--);
  445. }
  446.     }
  447. }
  448.     }
  449.     /* Anything left? */
  450.     if (!variants->length)
  451. return NULL;
  452.     /* Ok, it's time to convert the accept headers into something more */
  453.     /* useful. At the same time, eliminate those headers that we don't */
  454.     /* need. */
  455.     if (mip->accept)
  456.     {
  457. atp = convert_accept(mip->accept, variants, &i);
  458. if (!atp)
  459.     return NULL;
  460. if (i)
  461.     fill_mxb(variants, base);
  462.     }
  463.     else
  464.     {
  465. /* Come up with some defaults if no accept headers given. */
  466. atp = tbl_create(1);
  467. mtp = s_malloc(sizeof(struct mimetype));
  468. mtp->content_type = s_strdup("*/*");
  469. mtp->q = 1.0;
  470. mtp->mxb = 0.0;
  471. mtp->version = 2.0;
  472. tbl_append(atp, mtp);
  473.     }
  474.     if (!atp || atp->length == 0)
  475. return NULL;
  476.     if (debug > 7)
  477. fprintf(stderr, "Variants: %dn", variants->length);
  478.     /* Now go through the variants and eliminate all except for the */
  479.     /* best matches. */
  480.     maxq = 0.0;
  481.     for ( i = 0; i < variants->length; i++ )
  482.     {
  483. vip = (struct variantinfo *)(variants->value[i]);
  484. q = mime_match(&(vip->mt), atp);
  485. if (q < maxq || q == 0.0) /* Not good enough */
  486. {
  487.     variant_free(vip);
  488.     tbl_delete(variants, i--);
  489. }
  490. else
  491. if (q > maxq ) /* Best so far */
  492. {
  493.     maxq = q;
  494.     tbl_remove(variants, 0, i-1, variant_free);
  495.     i = 0;
  496. }
  497.     }
  498.     if (debug > 7)
  499. fprintf(stderr, "Variants: %dn", variants->length);
  500.     /* More than one variant left? Ok, pick highest version. */
  501.     if (variants->length > 1)
  502.     {
  503. vip = (struct variantinfo *)(variants->value[0]);
  504. maxv = vip->mt.version;
  505. for ( i = 1; i < variants->length; i++ )
  506. {
  507.     vip = (struct variantinfo *)(variants->value[i]);
  508.     v = vip->mt.version;
  509.     if (v < maxv)
  510.     {
  511. variant_free(vip);
  512. tbl_delete(variants, i--);
  513.     }
  514.     else
  515.     if (v > maxv )
  516.     {
  517. maxv = v;
  518. tbl_remove(variants, 0, i-1, variant_free);
  519. i = 0;
  520.     }
  521. }
  522.     }
  523.     if (debug > 7)
  524. fprintf(stderr, "Variants: %dn", variants->length);
  525.     /* Still more than one variant? Ok, pick favorite language. */
  526.     if (variants->length > 1 && mip->accept_language)
  527.     {
  528. vip = (struct variantinfo *)(variants->value[0]);
  529. minl = find_language(vip->content_language, mip->accept_language);
  530. for ( i = 1; i < variants->length; i++ )
  531. {
  532.     vip = (struct variantinfo *)(variants->value[i]);
  533.     l = find_language(vip->content_language, mip->accept_language);
  534.     if (l > minl)
  535.     {
  536. variant_free(vip);
  537. tbl_delete(variants, i--);
  538.     }
  539.     else
  540.     if (l < minl )
  541.     {
  542. minl = l;
  543. tbl_remove(variants, 0, i-1, variant_free);
  544. i = 0;
  545.     }
  546. }
  547.     }
  548.     if (debug > 7)
  549. fprintf(stderr, "Variants: %dn", variants->length);
  550.     /* Still more than one variant? Use smallest file. */
  551.     if (variants->length > 1)
  552.     {
  553. vip = (struct variantinfo *)(variants->value[0]);
  554. mins = get_mxb(vip, base);
  555. for ( i = 1; i < variants->length; i++ )
  556. {
  557.     vip = (struct variantinfo *)(variants->value[i]);
  558.     s = get_mxb(vip, base);
  559.     if (s > mins)
  560.     {
  561. variant_free(vip);
  562. tbl_delete(variants, i--);
  563.     }
  564.     else
  565.     if (s < mins )
  566.     {
  567. mins = s;
  568. tbl_remove(variants, 0, i-1, variant_free);
  569. i = 0;
  570.     }
  571. }
  572.     }
  573.     tbl_free(atp, mime_free);
  574.     /* Anything left? */
  575.     if (!variants->length)
  576. return NULL;
  577.     vip = (struct variantinfo *)(variants->value[0]);
  578.     return(vip->url);
  579. }
  580. /* The code above should probably go in mime.c        */
  581. /***********************************************************************/
  582. int pm_init(const char **argv)
  583. {
  584.     char *name = argv[0];
  585.     
  586.     if (debug > 1)
  587. fprintf(stderr, "*** libvar/pm_init("%s") called ***n", name);
  588.     return 0;
  589. }
  590. void pm_exit(void)
  591. {
  592.     if (debug > 1)
  593. fprintf(stderr, "*** libvar/pm_exit() called ***n");
  594. }
  595. static int http_get_head(struct connectioninfo *cip)
  596. {
  597.     struct stat sb;
  598.     int fd_var;
  599.     char buf[2048];
  600.     int status, i;
  601.     
  602.     char *header;
  603.     char *rest;
  604.     char *cp, *url, *orig_url;
  605.     struct table *tp = NULL;
  606.     int redirect;
  607.     struct httpinfo *hip = cip->hip;
  608.     
  609.     url = NULL;
  610.     
  611.     if (debug > 1)
  612. fprintf(stderr, "*** libvar/http_get_head() called ***n");
  613.     if (url_expand(hip->url, buf, sizeof(buf), &sb, NULL, NULL) == NULL)
  614. return -1;
  615.     
  616.     fd_var = fd_open(buf, O_RDONLY);
  617.     if (fd_var < 0)
  618.     {
  619. if (debug)
  620.     perror("open()");
  621. return -1;
  622.     }
  623.     do
  624.     {
  625. struct variantinfo *vip;
  626. vip = s_malloc(sizeof(struct variantinfo));
  627. if (vip == NULL)
  628.     break;
  629. vip->mt.q = 1.0;
  630. do
  631. {
  632.     status = mime_getline(buf, sizeof(buf), fd_var);
  633.     if (debug > 4)
  634. fprintf(stderr, "libvar: Got VARFILE line: %sn", buf);
  635.     
  636.     i = strlen(buf) - 1;
  637.     while (i >= 0 && s_isspace(buf[i]))
  638. i--;
  639.     buf[i+1] = '';     
  640.     for (cp = buf; *cp && s_isspace(*cp); cp++)
  641. ;
  642.     if (*cp == '')
  643.     {
  644. if (status > 0)
  645.     status = 0;
  646. break;
  647.     }
  648.     header = cp;
  649.     cp = strchr(cp, ':');
  650.     if (cp == NULL)
  651. continue;
  652.     *cp = '';
  653.     while ( *++cp && isspace(*cp) )
  654. ;
  655.     rest = cp;
  656.     if (!strcasecmp(header, "URI"))
  657.     {
  658. if (vip->url)
  659.     continue;
  660. vip->url = s_strdup(rest);
  661.     }
  662.     else if (!strcasecmp(header, "CONTENT-TYPE"))
  663.     {
  664. if (vip->mt.content_type)
  665.     continue;
  666. mime_gettype(rest, &(vip->mt));
  667.     }
  668.     else if (!strcasecmp(header, "CONTENT-CHARSET"))
  669.     {
  670. if (vip->content_charset)
  671.     continue;
  672. vip->content_charset = s_strdup(rest);
  673.     }
  674.     else if (!strcasecmp(header, "CONTENT-LANGUAGE"))
  675.     {
  676. if (vip->content_language)
  677.     continue;
  678. vip->content_language = s_strdup(rest);
  679.     }
  680.     else if (!strcasecmp(header, "CONTENT-ENCODING"))
  681.     {
  682. if (vip->content_encoding)
  683.     continue;
  684. vip->content_encoding = s_strdup(rest);
  685.     }
  686.     else if (!strcasecmp(header, "CONTENT-LENGTH"))
  687.     {
  688. if (vip->content_length)
  689.     continue;
  690. vip->content_length = atoi(rest);
  691.     }
  692.     else
  693.       if (debug)
  694. fprintf(stderr, "Illegal header in VAR file: %sn",
  695. header);
  696. }
  697. while (status > 0);
  698. if (!vip->url ||
  699.     (!vip->mt.content_type && !vip->content_language &&
  700.      !vip->content_encoding && !vip->content_length))
  701. {
  702.     variant_free(vip);
  703.     continue;
  704. }
  705. if (!vip->mt.content_type)
  706.     vip->mt.content_type = s_strdup("*/*");
  707. if (!tp)
  708.     tp = tbl_create(0);
  709. tbl_append(tp, vip);
  710. if (debug > 4)
  711. {
  712.   print_variant(vip);
  713. }
  714.     }
  715.     while (status >= 0);
  716.     fd_close(fd_var);
  717.     if (!tp)
  718. return -1;
  719.     url = mime_negotiate(tp, hip->mip, hip->url);
  720.     if (!url)
  721.     {
  722. status = 406;
  723. http_sendheaders(cip->fd, cip, status, NULL);
  724. fd_putc('n', cip->fd);
  725. tbl_free(tp, variant_free);
  726. return status;
  727.     }
  728.     cp = strchr(url, '/');
  729.     redirect = (cp != NULL);
  730.     if (url[0] != '/')
  731.     {
  732. s_strcpy(buf, sizeof(buf), hip->url);
  733. cp = strrchr(buf, '/');
  734. s_strcpy(cp+1, sizeof(buf)-((cp+1)-buf), buurl);
  735. url = buf;
  736.     }
  737.     if (redirect)
  738.     {
  739. status = http_redirect(cip, url, hip->request, NULL, 302);
  740.     }
  741.     else
  742.     {
  743. orig_url = hip->url;
  744. hip->url = url;
  745. status = phttpd_request(cip);
  746. hip->url = orig_url;
  747.     }
  748.     tbl_free(tp, variant_free);
  749.     if (debug > 2)
  750. fprintf(stderr, "libvar/http_get_head: Returningn");
  751.     return status;
  752. }
  753. int pm_request(struct connectioninfo *cip)
  754. {
  755.     struct httpinfo *hip = cip->hip;
  756.     
  757.     if (strcasecmp(hip->method, "GET") == 0 ||
  758. strcasecmp(hip->method, "HEAD") == 0)
  759. return http_get_head(cip);
  760.     else
  761. return -1;
  762. }