delete.c (3673B)
1 #include <errno.h> 2 #include <limits.h> 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <string.h> 6 #include <sys/stat.h> 7 #include <unistd.h> 8 9 #include "common.h" 10 #include "config.h" 11 #include "html.h" 12 #include "http.h" 13 #include "request.h" 14 #include "url.h" 15 16 static int do_get(void); 17 static int do_post(void); 18 19 static int 20 do_get(void) 21 { 22 char filename[NAME_MAX + 1]; 23 char path[PATH_MAX]; 24 struct stat st; 25 char template[PATH_MAX]; 26 27 if (!config_write_allowed()) { 28 reply("403 Forbidden", "Repository is read-only"); 29 return 0; 30 } 31 if (get_filename(getenv("QUERY_STRING"), filename, sizeof(filename)) == -1) 32 return 0; 33 34 if (build_storage_path(path, 35 sizeof(path), 36 storage_root(), 37 repository(), 38 filename) == -1) { 39 reply("500 Internal Server Error", 40 "Path too long"); 41 return 1; 42 } 43 if (stat(path, &st) == -1 || !S_ISREG(st.st_mode)) { 44 reply("404 Not Found", "File not found"); 45 return 0; 46 } 47 struct html_var vars[] = { 48 {"FILENAME", filename}, 49 {"CANCEL_URI", DEFAULT_REDIRECT_URI}, 50 }; 51 52 if (snprintf(template, sizeof(template), 53 "%s/%s", 54 simplefiles_root(), 55 DELETE_TEMPLATE_NAME) >= (int) sizeof(template)) { 56 reply("500 Internal Server Error", "Template path too long"); 57 return 0; 58 } 59 if (render_template_response(template, 60 vars, sizeof(vars) / sizeof(vars[0]), 61 NULL, 0) == -1) { 62 fprintf(stderr, "render_template failed: %s\n", template); 63 reply("500 Internal Server Error", "Template error"); 64 return 0; 65 } 66 return 0; 67 } 68 69 static int 70 do_post(void) 71 { 72 const char *p; 73 char *body; 74 char filename[NAME_MAX + 1]; 75 char path[PATH_MAX]; 76 char *end; 77 long len; 78 int rc; 79 int lock_fd; 80 81 if (!config_write_allowed()) { 82 reply("403 Forbidden", "Repository is read-only"); 83 return 0; 84 } 85 rc = check_csrf_origin(); 86 87 if (rc == -2) { 88 reply("500 Internal Server Error", 89 "CSRF origin is not configured"); 90 return 0; 91 } 92 if (rc == -1) { 93 reply("403 Forbidden", "Forbidden"); 94 return 0; 95 } 96 p = getenv("CONTENT_LENGTH"); 97 if (p == NULL) { 98 reply("400 Bad Request", 99 "Missing content length"); 100 return 0; 101 } 102 errno = 0; 103 len = strtol(p, &end, 10); 104 105 if (errno != 0 || 106 end == p || 107 *end != '\0' || 108 len <= 0 || 109 len > 1024) { 110 reply("400 Bad Request", 111 "Invalid content length"); 112 return 0; 113 } 114 body = malloc((size_t) len + 1); 115 if (body == NULL) { 116 reply("500 Internal Server Error", 117 "Out of memory"); 118 return 0; 119 } 120 if (fread(body, 1, (size_t) len, stdin) != (size_t) len) { 121 free(body); 122 reply("400 Bad Request", 123 "Could not read request"); 124 return 0; 125 } 126 body[len] = '\0'; 127 128 if (get_filename(body, filename, sizeof(filename)) == -1) { 129 free(body); 130 return 0; 131 } 132 free(body); 133 body = NULL; 134 135 if (build_storage_path(path, 136 sizeof(path), 137 storage_root(), 138 repository(), 139 filename) == -1) { 140 141 reply("500 Internal Server Error", 142 "Path too long"); 143 144 return 0; 145 } 146 lock_fd = repository_lock(repository()); 147 148 if (lock_fd == -1) { 149 reply("500 Internal Server Error", 150 "Could not lock repository"); 151 return 0; 152 } 153 if (unlink(path) == -1) { 154 if (errno == ENOENT) { 155 reply("404 Not Found", 156 "File not found"); 157 } else { 158 reply("500 Internal Server Error", 159 "Could not delete file"); 160 } 161 repository_unlock(lock_fd); 162 return 0; 163 } 164 repository_unlock(lock_fd); 165 redirect(DEFAULT_REDIRECT_URI); 166 167 return 0; 168 } 169 170 int 171 main(void) 172 { 173 const char *method; 174 175 method = getenv("REQUEST_METHOD"); 176 177 if (method == NULL) { 178 reply("400 Bad Request", "Missing request method"); 179 return 0; 180 } 181 if (strcmp(method, "GET") == 0) 182 return do_get(); 183 184 if (strcmp(method, "POST") == 0) 185 return do_post(); 186 187 reply("405 Method Not Allowed", 188 "GET or POST required"); 189 190 return 0; 191 }