1 /* $NetBSD: dir-index-bozo.c,v 1.7 2009/11/04 18:32:27 joerg Exp $ */ 2 3 /* $eterna: dir-index-bozo.c,v 1.14 2009/04/18 01:48:18 mrg Exp $ */ 4 5 /* 6 * Copyright (c) 1997-2009 Matthew R. Green 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer and 16 * dedication in the documentation and/or other materials provided 17 * with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 */ 32 33 /* this code implements directory index generation for bozohttpd */ 34 35 #ifndef NO_DIRINDEX_SUPPORT 36 37 #include <sys/param.h> 38 39 #include <dirent.h> 40 #include <errno.h> 41 #include <string.h> 42 #include <stdlib.h> 43 #include <time.h> 44 #include <assert.h> 45 46 #include "bozohttpd.h" 47 48 int Xflag; /* do directory indexing */ 49 int Hflag; /* hide .* */ 50 51 static void 52 directory_hr(void) 53 { 54 55 bozoprintf("<hr noshade align=\"left\" width=\"80%%\">\r\n\r\n"); 56 } 57 58 /* 59 * output a directory index. return 1 if it actually did something.. 60 */ 61 int 62 directory_index(http_req *request, const char *dirname, int isindex) 63 { 64 struct stat sb; 65 struct dirent *de; 66 struct tm *tm; 67 DIR *dp; 68 char buf[MAXPATHLEN]; 69 char spacebuf[48]; 70 char *file = NULL; 71 int l, i; 72 73 if (!isindex || !Xflag) 74 return 0; 75 76 if (strlen(dirname) <= strlen(index_html)) 77 dirname = "."; 78 else { 79 file = bozostrdup(dirname); 80 81 file[strlen(file) - strlen(index_html)] = '\0'; 82 dirname = file; 83 } 84 debug((DEBUG_FAT, "directory_index: dirname ``%s''", dirname)); 85 if (stat(dirname, &sb) < 0 || 86 (dp = opendir(dirname)) == NULL) { 87 if (errno == EPERM) 88 (void)http_error(403, request, 89 "no permission to open directory"); 90 else if (errno == ENOENT) 91 (void)http_error(404, request, "no file"); 92 else 93 (void)http_error(500, request, "open directory"); 94 goto done; 95 /* NOTREACHED */ 96 } 97 98 bozoprintf("%s 200 OK\r\n", request->hr_proto); 99 100 if (request->hr_proto != http_09) { 101 print_header(request, NULL, "text/html", ""); 102 bozoprintf("\r\n"); 103 } 104 bozoflush(stdout); 105 106 if (request->hr_method == HTTP_HEAD) { 107 closedir(dp); 108 goto done; 109 } 110 111 bozoprintf("<html><head><title>Index of %s</title></head>\r\n", 112 request->hr_file); 113 bozoprintf("<body><h1>Index of %s</h1>\r\n", request->hr_file); 114 bozoprintf("<pre>\r\n"); 115 #define NAMELEN 40 116 #define LMODLEN 19 117 bozoprintf("Name " 118 "Last modified " 119 "Size\n"); 120 bozoprintf("</pre>"); 121 directory_hr(); 122 bozoprintf("<pre>"); 123 124 while ((de = readdir(dp)) != NULL) { 125 int nostat = 0; 126 char *name = de->d_name; 127 128 if (strcmp(name, ".") == 0 || 129 (strcmp(name, "..") != 0 && Hflag && name[0] == '.')) 130 continue; 131 132 snprintf(buf, sizeof buf, "%s/%s", dirname, name); 133 if (stat(buf, &sb)) 134 nostat = 1; 135 136 l = 0; 137 138 if (strcmp(name, "..") == 0) { 139 bozoprintf("<a href=\"../\">"); 140 l += bozoprintf("Parent Directory"); 141 } else if (S_ISDIR(sb.st_mode)) { 142 bozoprintf("<a href=\"%s/\">", name); 143 l += bozoprintf("%s/", name); 144 } else { 145 bozoprintf("<a href=\"%s\">", name); 146 l += bozoprintf("%s", name); 147 } 148 bozoprintf("</a>"); 149 150 /* NAMELEN spaces */ 151 assert(sizeof(spacebuf) > NAMELEN); 152 i = (l < NAMELEN) ? (NAMELEN - l) : 0; 153 i++; 154 memset(spacebuf, ' ', i); 155 spacebuf[i] = '\0'; 156 bozoprintf(spacebuf); 157 l += i; 158 159 if (nostat) 160 bozoprintf("? ?"); 161 else { 162 tm = gmtime(&sb.st_mtime); 163 strftime(buf, sizeof buf, "%d-%b-%Y %R", tm); 164 l += bozoprintf("%s", buf); 165 166 /* LMODLEN spaces */ 167 assert(sizeof(spacebuf) > LMODLEN); 168 i = (l < (LMODLEN+NAMELEN+1)) ? ((LMODLEN+NAMELEN+1) - l) : 0; 169 i++; 170 memset(spacebuf, ' ', i); 171 spacebuf[i] = '\0'; 172 bozoprintf(spacebuf); 173 174 bozoprintf("%7ukB", 175 ((unsigned int)(sb.st_size >> 10))); 176 } 177 bozoprintf("\r\n"); 178 } 179 180 closedir(dp); 181 bozoprintf("</pre>"); 182 directory_hr(); 183 bozoprintf("</body></html>\r\n\r\n"); 184 bozoflush(stdout); 185 186 done: 187 if (file) 188 free(file); 189 return 1; 190 } 191 #endif /* NO_DIRINDEX_SUPPORT */ 192