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

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 }