simplefiles

A lightweight C CGI web application for managing files.
git clone https://scm.kuandu.systems/git-raw/simplefiles.git
Log | Files | Refs | README | LICENSE

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 }