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

Web服务器

开发平台:

Unix_Linux

  1. /*
  2. ** dir.c
  3. **
  4. ** Copyright (c) 1994-1995 Peter Eriksson <pen@signum.se>
  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 <alloca.h>
  21. #include <string.h>
  22. #include <time.h>
  23. #include <fcntl.h>
  24. #include <stdlib.h>
  25. #include <sys/types.h>
  26. #include <sys/stat.h>
  27. #include <dirent.h>
  28. #include <limits.h>
  29. #include <errno.h>
  30. #include "phttpd.h"
  31. #define DEFAULT_INDEX_PATH "index.html:Welcome.html"
  32. #define DEFAULT_ICON_UNKNOWN 
  33. "<IMG SRC="/icons/unknown.xbm" ALT=" " BORDER=0 HSPACE=5>"
  34. #define DEFAULT_ICON_BACK 
  35. "<IMG SRC="/icons/back.xbm" ALT=" " BORDER=0 HSPACE=5>"
  36. #define DEFAULT_ICON_MENU 
  37. "<IMG SRC="/icons/menu.xbm" ALT=" " BORDER=0 HSPACE=5>"
  38. #define DEFAULT_ICON_BINARY 
  39. "<IMG SRC="/icons/binary.xbm" ALT=" " BORDER=0 HSPACE=5>"
  40. static hashtable_t *directory_icons_table = NULL;
  41. static hashtable_t *add_href_table = NULL;
  42. static char *index_file_path = NULL;
  43. static int check_index_file = 1;
  44. static int allow_dir_listing = 0;
  45. static struct options dir_cfg_table[] =
  46. {
  47.     { "directory-icons",   T_HTABLE, &directory_icons_table, NULL },
  48.     { "add-href",          T_HTABLE, &add_href_table,         NULL },
  49.     { "index-file-path",   T_STRING, &index_file_path, NULL },
  50.     { "check-index-file",  T_BOOL,   &check_index_file, NULL },
  51.     
  52.     { "allow-dir-listing", T_BOOL,   &allow_dir_listing, NULL },
  53.     
  54.     { NULL,                -1,       NULL, NULL }
  55. };
  56. int pm_init(const char **argv)
  57. {
  58.     char *cfg_path, *cp;
  59.     const char *name;
  60.     int clen;
  61.     
  62.     
  63.     name = argv[0];
  64.     
  65.     if (debug > 1)
  66. fprintf(stderr, "*** libdir/pm_init("%s") called ***n", name);  
  67.     clen = strlen(name)+6;
  68.     cfg_path = s_malloc(clen);
  69.     s_strcpy(cfg_path, clen, name);
  70.     
  71.     cp = strrchr(cfg_path, '.');
  72.     if (cp && strcmp(cp, ".so") == 0)
  73. *cp = '';
  74.     
  75.     s_strcat(cfg_path, clen, ".conf");
  76.     if (config_parse_file(cfg_path, dir_cfg_table, 0) < 0)
  77. return -1;
  78.     
  79.     if (config_parse_argv(argv+1, dir_cfg_table) < 0)
  80. return -1;
  81.     if (index_file_path == NULL)
  82. index_file_path = s_strdup(DEFAULT_INDEX_PATH);
  83.     return 0;
  84. }
  85. void pm_exit(void)
  86. {
  87.     if (debug > 1)
  88. fprintf(stderr, "*** libdir/pm_exit() called ***n");
  89.     if (directory_icons_table)
  90.     {
  91. ht_destroy(directory_icons_table);
  92. s_free(directory_icons_table);
  93.     }
  94.     if (add_href_table)
  95.     {
  96. ht_destroy(add_href_table);
  97. s_free(add_href_table);
  98.     }
  99.     
  100.     if (index_file_path)
  101. s_free(index_file_path);
  102.     
  103.     if (debug > 1)
  104. fprintf(stderr, "*** libdir/pm_exit() done ***n");
  105. }
  106. static  int dircompare(a, b)
  107.     char **a, **b;
  108. {
  109.     struct fsc_dirent *fdp1, *fdp2;
  110.     struct dirent *dp1, *dp2;
  111.     fdp1 = *(struct fsc_dirent **) a;
  112.     fdp2 = *(struct fsc_dirent **) b;
  113.     dp1 = fdp1->dbp;
  114.     dp2 = fdp2->dbp;
  115.     return strcmp(dp1->d_name, dp2->d_name);
  116. }
  117. static int do_dirlisting(int fd,
  118.  struct connectioninfo *cip,
  119.  struct httpinfo *hip,
  120.  int browse_flag)
  121. {
  122.     char buf[1024],qbuf[2048];
  123.     int result, len, i, j, k, maxlen, n_cols;
  124.     fscentry_t *fep;
  125.     fsinfo_t *fip;
  126.     struct fsc_dirent *fdp, **fdpl;
  127.     unsigned int fsc_flags = 0;
  128.     
  129.     if (debug > 4)
  130. fprintf(stderr, "do_dirlisting()n");
  131.     
  132.     if (hip && hip->mip && (hip->mip->pragma_flags & MPF_NOCACHE))
  133. fsc_flags = FSCF_RELOAD;
  134.     fep = fscache_lookup(hip->url, FSCF_GETDATA+fsc_flags);
  135.     if (fep == NULL)
  136. return -1;
  137.     if (debug > 4)
  138. fprintf(stderr, "  doing listing, step 1n");
  139.     
  140.     fip = fep->fip;
  141.     if (fip == NULL)
  142.     {
  143. fscache_release(fep);
  144. return -1;
  145.     }
  146.     
  147.     if (!S_ISDIR(fip->sb.st_mode))
  148.     {
  149. fscache_release(fep);
  150. return -1;
  151.     }
  152.     
  153.     result = 200;
  154.     if (hip->mip != NULL)
  155.     {
  156. char *s_since;
  157. if ((s_since = mime_getheader(hip->mip, "IF-MODIFIED-SINCE", 1)) != NULL)
  158. {
  159.     struct tm tm_since;
  160.     int t_since;
  161.     
  162.     
  163.     if (debug > 2)
  164. fprintf(stderr, "Got If-Modified-Since: %sn", s_since);
  165.     
  166.     t_since = atotm(s_since, &tm_since);
  167.     if (t_since != -1)
  168.     {
  169. if (fip->sb.st_mtime <= (time_t) t_since)
  170. {
  171.     fscache_release(fep);
  172.     return http_not_modified(cip);
  173. }
  174.     }
  175.     else
  176.     {
  177. /* Could not parse the date format - do a string compare */
  178. http_time_r(&fip->sb.st_mtime, buf, sizeof(buf));
  179. i = strlen(buf);
  180. buf[i-1] = '';
  181. if (strcmp(s_since, buf) == 0)
  182. {
  183.     fscache_release(fep);
  184.     return http_not_modified(cip);
  185. }
  186.     }
  187. }
  188. http_sendheaders(fd, cip, result, NULL);
  189. http_sendlastmodified(fd, fip->sb.st_mtime);
  190. if (browse_flag)
  191.     fd_puts("Content-Type: application/x-navibrowsen", fd);
  192. else
  193.     fd_puts("Content-Type: text/htmln", fd);
  194.     }
  195.     if (hip->mip != NULL)
  196. fd_putc('n', fd);
  197.     if (strcasecmp(hip->method, "HEAD") == 0)
  198.     {
  199. fscache_release(fep);
  200. return result;
  201.     }
  202.     len = fd_written(fd);
  203.     if (!browse_flag)
  204. html_sysheader(fd, "H2", "Index of %s%s", make_sip_url(cip,qbuf,2048), hip->url+hip->prelen);
  205.     if (browse_flag)
  206. fd_puts("application/x-navidir .n", fd);
  207.     
  208.     if (strcmp(hip->url, "/") != 0)
  209.     {
  210. if (browse_flag)
  211.     fd_puts("application/x-navidir ..n", fd);
  212. else
  213.     fd_printf(fd, "%s <A HREF="%s">Up to previous directory</A>n",
  214.       DEFAULT_ICON_BACK,
  215. /* rkmultimode hip->prelen */
  216.   url_quote(url_getparent(hip->url+hip->prelen, buf, sizeof(buf)),
  217.                             qbuf,2048,NULL,1) );
  218.     }
  219.     if (fip->data.dir.size > 0)
  220.     {
  221. fdpl = (struct fsc_dirent **)
  222.     alloca(fip->data.dir.size * sizeof(struct fsc_dirent *));
  223. i = 0;
  224. maxlen = 0;
  225. for (fdp = fip->data.dir.head; fdp; fdp = fdp->next)
  226. {
  227.     struct dirent *dp;
  228.     
  229.     dp = fdp->dbp;
  230.     
  231.     if (dp->d_name[0] == '.')
  232. continue;
  233.     
  234.     if (fdp->fep == NULL)
  235.     {
  236. if (debug)
  237.     fprintf(stderr, "dir: fdp->fep == NULL, name=%sn", dp->d_name);
  238. continue;
  239.     }
  240.     
  241.     if (fdp->fep->fip == NULL)
  242.     {
  243. if (debug)
  244.     fprintf(stderr, "dir: fdp->fep->fip == NULL, name=%sn", dp->d_name);
  245. continue;
  246.     }
  247.     
  248.     if (!S_ISDIR(fdp->fep->fip->sb.st_mode))
  249. continue;
  250.     
  251.     len = strlen(dp->d_name);
  252.     if (len > maxlen)
  253. maxlen = len;
  254.     
  255.     fdpl[i++] = fdp;
  256. }
  257. if (i > 0)
  258. {
  259.     if (!browse_flag)
  260.     {
  261. if (i == 1)
  262.     fd_printf(fd, "<H3>1 Directory:</H3>n");
  263. else
  264.     fd_printf(fd, "<H3>%d Directories:</H3>n", i);
  265.     
  266. fd_puts("<PRE>n", fd);
  267.     }
  268.     
  269.     qsort((char **)fdpl, i, sizeof(struct fsc_dirent *),
  270.   (int (*)(const void *, const void *)) dircompare);
  271.     
  272.     n_cols = 80/(maxlen+10);
  273.     
  274.     for (j = k = 0; j < i; j++)
  275.     {
  276. if (browse_flag)
  277. {
  278.     fd_puts("application/x-navidir ", fd);
  279.     fd_puts(fdpl[j]->dbp->d_name, fd);
  280.     fd_puts("n", fd);
  281. }
  282. else
  283. {
  284.     fd_puts(DEFAULT_ICON_MENU, fd);
  285.     fd_printf(fd, " <A HREF="%s/">%s</A>",
  286.       url_quote(fdpl[j]->dbp->d_name,qbuf,2048,NULL,1),
  287.       fdpl[j]->dbp->d_name);
  288.     
  289.     if (++k < n_cols)
  290. fd_printf(fd, "%*s    ",
  291.   maxlen-strlen(fdpl[j]->dbp->d_name), "");
  292.     else
  293.     {
  294. fd_putc('n', fd);
  295. k = 0;
  296.     }
  297. }
  298.     }
  299.     if (!browse_flag)
  300. fd_puts("</PRE>n", fd);
  301. }
  302. i = 0;
  303. maxlen = 0;
  304. for (fdp = fip->data.dir.head; fdp; fdp = fdp->next)
  305. {
  306.     struct dirent *dp;
  307.     
  308.     
  309.     dp = fdp->dbp;
  310.     
  311.     if (dp->d_name[0] == '.')
  312. continue;
  313.     
  314.     if (fdp->fep == NULL)
  315.     {
  316. if (debug)
  317.     fprintf(stderr, "dir: fdp->fep == NULL, name=%sn", dp->d_name);
  318. continue;
  319.     }
  320.     
  321.     if (fdp->fep->fip == NULL)
  322.     {
  323. if (debug)
  324.     fprintf(stderr, "dir: fdp->fep->fip == NULL, name=%sn", dp->d_name);
  325. continue;
  326.     }
  327.     
  328.     if (S_ISDIR(fdp->fep->fip->sb.st_mode))
  329. continue;
  330.     
  331.     len = strlen(dp->d_name);
  332.     if (len > maxlen)
  333. maxlen = len;
  334.     
  335.     fdpl[i++] = fdp;
  336. }
  337. if (i > 0)
  338. {
  339.     char buf[128];
  340.     
  341.     if (!browse_flag)
  342.     {
  343. if (i == 1)
  344.     fd_printf(fd, "<H3>1 File:</H3>n");
  345. else
  346.     fd_printf(fd, "<H3>%d Files:</H3>n", i);
  347.     
  348. fd_puts("<PRE>n", fd);
  349.     }
  350.     
  351.     qsort((char **)fdpl, i, sizeof(struct fsc_dirent *),
  352.   (int (*)(const void *, const void *)) dircompare);
  353.     
  354.     for (j = 0; j < i; j++)
  355.     {
  356. hashentry_t *hep_i, *hep_h;
  357. char *cp;
  358. struct stat *sp;
  359. cp = strrchr(fdpl[j]->dbp->d_name, '.');
  360. if (browse_flag)
  361. {
  362. /* XXX move the .html -> text/html to a separate module, callable
  363.    from both file.so and dir.so... */
  364.    
  365.     if (cp && strcmp(cp, ".html") == 0)
  366. fd_puts("text/html ", fd);
  367.     else
  368. fd_puts("image/gif ", fd);
  369.     
  370.     fd_puts(fdpl[j]->dbp->d_name, fd);
  371.     fd_puts("n", fd);
  372. }
  373. else
  374. {
  375.     cp = strrchr(fdpl[j]->dbp->d_name, '.');
  376.     
  377.     if (cp)
  378. hep_h = ht_lookup(add_href_table, cp, 0);
  379.     else
  380. hep_h = NULL;
  381.     
  382.     if (hep_h)
  383. fd_printf(fd, "<A HREF="%s%s%s">",
  384.   hep_h->data,
  385.   hip->url+hip->prelen,
  386.   url_quote(fdpl[j]->dbp->d_name,qbuf,2048,NULL,1) );
  387.     
  388.     if (cp)
  389.     {
  390. hep_i = ht_lookup(directory_icons_table, cp, 0);
  391. if (hep_i)
  392. {
  393.     fd_puts(hep_i->data, fd);
  394.     ht_release(hep_i);
  395. }
  396. else
  397.     fd_puts(DEFAULT_ICON_UNKNOWN, fd);
  398.     }
  399.     else
  400. fd_puts(DEFAULT_ICON_UNKNOWN, fd);
  401.     
  402.     if (hep_h)
  403. fd_puts("</A>", fd);
  404.     
  405.     sp = &fdpl[j]->fep->fip->sb;
  406.     fd_printf(fd, " <A HREF="%s">%s</A>   %*s %10d     %s",
  407.       url_quote(fdpl[j]->dbp->d_name,qbuf,2048,NULL,1),
  408.       fdpl[j]->dbp->d_name,
  409.       maxlen-strlen(fdpl[j]->dbp->d_name),
  410.       "",
  411.       sp->st_size,
  412.       ctime_r(&sp->st_mtime, buf, sizeof(buf)));
  413.     if (hep_h)
  414. ht_release(hep_h);
  415. }
  416.     }
  417.     if (!browse_flag)
  418. fd_puts("</PRE>n", fd);
  419. }
  420.     }
  421.     if (!browse_flag)
  422. html_sysfooter(fd);
  423.     fscache_release(fep);
  424.     
  425.     return result;
  426. }
  427. static int http_get_head(struct connectioninfo *cip)
  428. {
  429.     int len, status;
  430.     char url[2048];
  431.     char url2[2048]; /* added rk 9.4.98 try */
  432.     char *orig_url;
  433.     struct stat sb;
  434.     int fd = cip->fd;
  435.     struct httpinfo *hip = cip->hip;
  436.     
  437.     if (debug > 1)
  438. fprintf(stderr, "*** libdir/http_get_head() called ***n");
  439.     len = strlen(hip->url);
  440.     
  441.     if (len == 0 || hip->url[len-1] != '/')
  442.     {
  443. s_strcpy(url, sizeof(url), cip->sip->url);
  444. s_strcat(url, sizeof(url), hip->url);
  445. s_strcat(url, sizeof(url), "/");
  446. return http_redirect(cip, url, hip->request, NULL, 301);
  447.     }
  448.     orig_url = hip->url;
  449.     {
  450. char *if_path, *c_index_file, *cfp;
  451. int ilen = strlen(index_file_path)+1;
  452. if_path = (char *) alloca(ilen);
  453. s_strcpy(if_path, ilen, index_file_path);
  454. cfp = if_path;
  455. c_index_file = strtok_r(if_path, ":", &cfp);
  456. while (c_index_file)
  457. {
  458.     s_strcpy(url, sizeof(url), orig_url);
  459.     s_strcat(url, sizeof(url), c_index_file);
  460. /* Hack RK -- we do need this ? or not ?*/
  461. /* check-index-file ?? */
  462.     if ( check_index_file )
  463. /* { if ( stat(url+1,&sb) != 0 ) goto nextfile; } */
  464. { if ( url_expand(url,url2,sizeof(url2),&sb,NULL,NULL) == NULL ) goto nextfile; }
  465.     if ( url_getrewrite(url,url2,2048) != NULL ) 
  466. hip->url = url2;
  467.     else
  468.      hip->url = url;
  469. /* end of HACK */
  470.     
  471.     if (debug > 2)
  472. fprintf(stderr, "Dir: Trying Indexfile '%s'...n", hip->url);
  473.     
  474.     /* Try the index.html-file in the directory */
  475.     status = phttpd_request(cip);
  476.     if (status > 0 || status < -100 )
  477.     {
  478. hip->url = orig_url;
  479. return status;
  480.     }
  481. nextfile:    
  482.     c_index_file = strtok_r(NULL, ":", &cfp);
  483. }
  484.     }
  485.     hip->url = orig_url;
  486.     if (allow_dir_listing)
  487. return do_dirlisting(fd, cip, hip, 0);
  488.     else
  489. return -1;
  490.     
  491. }
  492. static int http_browse(struct connectioninfo *cip)
  493. {
  494.     int fd = cip->fd;
  495.     struct httpinfo *hip = cip->hip;
  496.     if ( allow_dir_listing == 1 ) /* RK */
  497. return do_dirlisting(fd, cip, hip, 1);
  498.     else
  499. return -1;
  500. }
  501. int pm_request(struct connectioninfo *cip)
  502. {
  503.     struct httpinfo *hip = cip->hip;
  504.     
  505.     if (strcasecmp(hip->method, "GET") == 0 ||
  506. strcasecmp(hip->method, "HEAD") == 0)
  507. return http_get_head(cip);
  508.     else if (strcasecmp(hip->method, "BROWSE") == 0)
  509. return http_browse(cip);
  510.     else
  511. return -2;
  512. }