download.c (1369B)
1 #include <limits.h> 2 #include <sys/stat.h> 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <string.h> 6 #include <unistd.h> 7 8 #include "common.h" 9 #include "config.h" 10 #include "http.h" 11 #include "request.h" 12 #include "url.h" 13 14 int 15 main(void) 16 { 17 const char *method; 18 char filename[NAME_MAX + 1]; 19 char path[PATH_MAX]; 20 struct stat st; 21 FILE *fp; 22 char buffer[8192]; 23 size_t n; 24 25 method = getenv("REQUEST_METHOD"); 26 if (method == NULL || strcmp(method, "GET") != 0) { 27 reply("405 Method Not Allowed", "GET required"); 28 return 0; 29 } 30 31 if (!config_access_allowed()) { 32 reply("403 Forbidden", "Forbidden"); 33 return 0; 34 } 35 36 if (get_filename(getenv("QUERY_STRING"), filename, sizeof(filename)) == -1) 37 return 0; 38 if (build_storage_path(path, 39 sizeof(path), 40 storage_root(), 41 repository(), 42 filename) == -1) { 43 reply("500 Internal Server Error", "Path too long"); 44 return 0; 45 } 46 if (lstat(path, &st) == -1 || !S_ISREG(st.st_mode)) { 47 reply("404 Not Found", "File not found"); 48 return 0; 49 } 50 if (download_headers(filename, st.st_size) == -1) { 51 reply("400 Bad Request", "Invalid filename"); 52 return 0; 53 } 54 55 fp = fopen(path, "rb"); 56 if (fp == NULL) { 57 reply("500 Internal Server Error", "Could not open file"); 58 return 0; 59 } 60 while ((n = fread(buffer, 1, sizeof(buffer), fp)) > 0) { 61 if (fwrite(buffer, 1, n, stdout) != n) { 62 break; 63 } 64 } 65 66 fclose(fp); 67 return 0; 68 }