use fast string formatting routines
[cwebfiles.git] / listdir.c
1 #include <stdlib.h>
2 #include <sys/types.h>
3 #include <unistd.h>
4 #include "cwebfiles.h"
5 #include <sys/types.h>
6 #include <dirent.h>
7 #include <unistd.h>
8 #include <sys/fsuid.h>
9 #include <string.h>
10 #include <stdio.h>
11 #include <errno.h>
12 #include <sys/stat.h>
13 #include <fmt.h>
14
15 int main() {
16   FASTOUTPUT
17   
18   char *encpath = getenv("QUERY_STRING");
19   login_and_setup(); // will clear the environment
20   if (encpath == NULL) senderr("no query string received", NOTMYFAULT);
21   
22   // OK, we're authenticated. Drop our fsuid to the user's.
23   // Yes, there's no error indication apart from this kludge. Sucks.
24   setfsuid(session.uid);
25   if (setfsuid(session.uid) != session.uid) senderr("setfsuid failed", MYFAULT);
26   
27   // Do what the user wants us to do.
28   char path[strlen(encpath)/2+1];
29   unhex((unsigned char *)path, encpath, strlen(encpath));
30   path[strlen(encpath)/2] = 0;
31   if (chdir(path)) {
32     char errstr[128];
33     snprintf(errstr, 128, "can't access that path: %s", strerror(errno));
34     senderr(errstr, NOTMYFAULT);
35   }
36   DIR *dir = opendir(".");
37   if (dir == NULL) {
38     char errstr[128];
39     snprintf(errstr, 128, "can't open that path for reading: %s", strerror(errno));
40     senderr(errstr, NOTMYFAULT);
41   }
42   
43   // The directory was opened successfully - send our success header.
44   puts("Status: 200 here's your listing");
45   puts("X-Frame-Options: DENY");
46   puts("Content-Type: text/plain;charset=utf8");
47   puts("");
48   
49   // send one line per file
50   struct dirent *dent;
51   char linedata[NAME_MAX*2+1+FMT_ULONG+1+FMT_ULONG+1];
52   while ((dent = readdir(dir)) != NULL) {
53     struct stat st;
54     // if we can't really see the file anyway, skip it
55     if (lstat(dent->d_name, &st)) continue;
56     //printf("%s %lu %u\n", encfilename, (unsigned long)st.st_size, (unsigned int)st.st_mode);
57     size_t name_len = strlen(dent->d_name);
58     hex(linedata, (unsigned char *)dent->d_name, name_len);
59     char *p = linedata+name_len*2;
60     *(p++) = ' ';
61     p += fmt_ulong(p, (unsigned long)st.st_size);
62     *(p++) = ' ';
63     p += fmt_ulong(p, (unsigned int)st.st_mode);
64     *(p++) = '\n';
65     *p = 0;
66     fputs(linedata, stdout);
67   }
68 }