aboutsummaryrefslogtreecommitdiff
path: root/wiki.c
diff options
context:
space:
mode:
Diffstat (limited to 'wiki.c')
-rw-r--r--wiki.c332
1 files changed, 0 insertions, 332 deletions
diff --git a/wiki.c b/wiki.c
deleted file mode 100644
index ba854a5..0000000
--- a/wiki.c
+++ /dev/null
@@ -1,332 +0,0 @@
-#define _POSIX_C_SOURCE 200809L
-#define _GNU_SOURCE
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <glob.h>
-#include <libgen.h>
-#include <time.h>
-#include <unistd.h>
-#include <sys/stat.h>
-
-#include <marxup.h>
-
-#include "config.h"
-
-static const char *badchars = "\\?%:|\"<> ";
-
-int writable(char *path) {
- struct stat s;
- if(!stat(path, &s)) {
- if(S_ISREG(s.st_mode))
- return !eaccess(path, W_OK);
- else if(S_ISDIR(s.st_mode))
- return 0;
- }
- char *dir = dirname(strdup(path));
- if(!stat(dir, &s)) {
- if(S_ISDIR(s.st_mode))
- return !eaccess(dir, W_OK);
- }
- return 0;
-}
-
-void head(char *page, char *link, char *what) {
- printf("Content-Type: text/html; charset=utf-8\n\n");
- printf("<!doctype html>\n");
- printf("<title>%s · %s</title>\n", title, page);
- printf("<link rel='stylesheet' type='text/css' href='%s/wiki.css'>\n", base);
- printf("<script src='%s/wiki.js'></script>\n", base);
- printf("<h1>");
- if(link && what && !strcmp(what, "rediger"))
- printf("<a data-text='%s' href='%s'>%s</a>", what, link, page);
- else if(link && what)
- printf("<a data-text='%s' href='%s/%s'>%s</a>", what, base, link, page);
- else
- printf("%s", page);
- printf("</h1>\n");
-}
-
-void foot(int file) {
- printf("<hr>\n");
- printf("<p>");
- for(int i = 0; *links[i]; i++) {
- if(*links[i][1] == '/' || strstr(links[i][1], "://"))
- printf("<a href='%s'>%s</a> ", links[i][1], links[i][0]);
- else
- printf("<a href='%s/%s'>%s</a> ", script, links[i][1], links[i][0]);
- }
- if(!file) return;
- printf("<span class='f'>%s <a href='?t'>text/plain</a></span>\n", id);
-}
-
-char *clean(char *p) {
- char *dup = strdup(basename(p));
- char *x = dup;
- while(*x) {
- if(*x == '-') *x = ' ';
- x++;
- }
- return dup;
-}
-
-int legit(char *page) {
- if(!page) return 0;
- if(!strcmp(page, "/")) return 0;
- if(strstr(page, "..")) return 0;
- if(strcspn(page, badchars) < strlen(page)) return 0;
- // strlen(page)
- return 1;
-}
-
-int problem(int status, char *message) {
- printf("Status: %d\n", status);
- printf("Content-Type: text/plain\n\n");
- printf("%s\n", message);
- return 1;
-}
-
-int redirect(char *path, char *prefix) {
- printf("Status: 303\n");
- switch(*path) {
- case '?': printf("Location: %s\n\n", path); break;
- case '#':
- printf("Location: %s/%s?m=", script, path);
- // skrive ut ++path
- printf("\n");
- default:
- if(prefix) {
- printf("Location: %s/%s/%s\n\n", script, prefix, path); break;
- } else {
- printf("Location: %s/%s\n\n", script, path); break;
- }
- }
- return 0;
-}
-
-int unauthorized(int status) {
- printf("Status: %d\n", status);
- if(status == 401)
- printf("WWW-Authenticate: Basic realm='%s'\n", realm);
- printf("Content-Type: text/plain; charset=utf-8\n\n");
- printf("No.\n");
- return 1;
-}
-
-int edit(char *path) {
- if(!writable(path)) return unauthorized(403);
- FILE *fp = fopen(path, "r");
- fp ? head(path, path, "vis") : head(path, NULL, NULL);
- char buffer[sysconf(_SC_PAGESIZE)];
- printf("<form method='post'>\n");
- printf("<p class='edit'>\n");
- if(orz)
- printf("<a id='orz' href='#'>@picto</a><br>\n");
- printf("<textarea name=t rows=24 cols=72>");
- if(fp)
- while(fgets(buffer, sizeof(buffer), fp))
- printf("%s", buffer);
- printf("</textarea>\n");
- printf("<p><input type=submit value=Update>");
- printf("</form>");
- foot(1);
- if(fp) fclose(fp);
- return 0;
-}
-
-// v fæl
-int store(char *raw, int len) {
- char *dir = dirname(strdup(raw));
- char *id = basename(strdup(raw));
- if(chdir(dir))
- return problem(404, "Not found");
- char path[strlen(loft) + strlen(id) + 256];
- int epoch = time(NULL);
- snprintf(path, strlen(loft) + strlen(id) + 256, "%s/%s.%d", loft, id, epoch);
- FILE *fp = fopen(path, "w");
- if(!fp) return redirect("fff", NULL);
- int pos = 0;
- unsigned int decoded;
- char buffer[3] = { 0 };
- for(int i = 0; i < len; i++) {
- buffer[pos] = getchar();
- if(buffer[pos] == '+') buffer[pos] = ' ';
- if(buffer[pos] == '&') { buffer[pos] = '\0'; break; }
- if(pos == 2) {
- if(buffer[0] == '%' && isxdigit(buffer[1]) && isxdigit(buffer[2])) {
- sscanf(buffer, "%%%2x", &decoded);
- fprintf(fp, "%c", decoded);
- memset(buffer, 0, 3);
- pos = 0;
- } else {
- fprintf(fp, "%c", buffer[0]);
- memmove(buffer, &buffer[1], 2);
- buffer[2] = 0;
- }
- }
- else pos++;
- }
- fprintf(fp, "%.3s", buffer);
- fputc('\0', fp);
- fclose(fp);
- unlink(id);
- symlink(path, id);
- return 0;
-}
-
-int post(char *path) {
- char *header;
- int clen;
- header = getenv("CONTENT_LENGTH");
- if(!header) return redirect(path, NULL);
- clen = atoi(header);
- while(clen > 1)
- if(clen--, getchar() == 't')
- if(clen--, getchar() == '=')
- store(path, clen);
- return redirect(path, NULL);
-}
-
-// gjør denne penere!
-int list(char *raw, int dir, int inc) {
- int len = strlen(raw);
- char *pattern = malloc(len + 3);
- if(len > 0 && raw[len - 1] == '/')
- raw[len - 1] = '\0';
- if(dir)
- snprintf(pattern, len + 3, "%s/*", raw);
- else
- snprintf(pattern, len + 1, "%s", raw);
- glob_t res;
- if(glob(pattern, GLOB_MARK, NULL, &res)) {
- if(!inc) {
- head("ingen treff", NULL, NULL);
- foot(0);
- }
- return 0;
- }
- if(!inc)
- head("treff", NULL, NULL);
- char *path;
- printf("<ul class='glob'>");
- for(int i = 0; i < res.gl_pathc; i++) {
- path = res.gl_pathv[i];
- if(*path == '.' && *path + 1 == '/') path += 2;
- printf("<li><a href='%s/%s'>%s</a>", script, path, path);
- }
- printf("</ul>");
- if(!inc)
- foot(0);
- free(pattern);
- return 0;
-}
-
-int text(char *path, char *type) {
- FILE *fp = fopen(path, "r");
- if(fp) {
- char buffer[sysconf(_SC_PAGESIZE)];
- printf("Content-Type: %s; charset=utf-8\n\n", type);
- while(fgets(buffer, sizeof(buffer), fp))
- printf("%s", buffer);
- }
- fclose(fp);
- return 0;
-}
-
-void include(FILE *out, char *path) {
- struct stat s;
- int plain = 0;
- if(*path == 't')
- plain = 1, path++;
- while(isspace(*path)) path++;
- if(!legit(path)) return;
- if(*path == '/') return;
- stat(path, &s);
- if(S_ISDIR(s.st_mode)) {
- list(path, 1, 1);
- return;
- }
- FILE *fp = fopen(path, "r");
- if(!fp) return;
- if(plain) {
- printf("<pre>");
- int c;
- while((c = fgetc(fp)) != EOF) {
- switch(c) {
- case '&': printf("&amp;"); break;
- case '<': printf("&lt;"); break;
- case '>': printf("&gt;"); break;
- default: putc(c, stdout);
- }
- }
- printf("</pre>");
- } else {
- marxup(fp, out, NULL);
- }
- fclose(fp);
-}
-
-void magic(FILE *out, char *line) {
- switch(*line++) {
- case 'i': include(out, line); break;
- default: fprintf(out, "WHAT: %s\n", line); return;
- }
-}
-
-int view(char *path) {
- struct stat s;
- stat(path, &s);
- if(S_ISDIR(s.st_mode)) {
- if(dirlist)
- return list(path, 1, 0);
- return redirect(home, path);
- }
- FILE *fp = fopen(path, "r");
- if(!fp) return redirect("?e", NULL);
- writable(path) ? head(path, "?e", "rediger") : head(path, NULL, NULL);
- marxup(fp, stdout, magic);
- foot(1);
- return 0;
-}
-
-int main(int argc, char **argv) {
- char *page = getenv("PATH_INFO");
- char *qstr = getenv("QUERY_STRING");
- char *verb = getenv("REQUEST_METHOD");
-
- if(!page && argc > 1) page = argv[1];
- if(!qstr && argc > 2) qstr = argv[2];
-
- if(!verb) verb = "GET";
-
- if(!script) script = getenv("SCRIPT_NAME");
- if(!script) script = "";
- if(!base) base = strdup(dirname(strdup(script)));
-
- if(authenticate && !(id = authenticate())) return unauthorized(401);
- if(!legit(page++)) return redirect(home, NULL);
-
- setenv("MARXUP_HEADER", "2", 1);
- setenv("MARXUP_PREFIX", base, 1);
- setenv("MARXUP_WIKI", "1", 1);
-
- if(chdir(pages))
- return problem(503, "Service unavailable");
-
- if(!strncmp(verb, "POST", 4)) return post(page);
- if(strchr(page, '*'))
- return list(page, 0, 0);
-
- while(qstr && *qstr) {
- switch(*qstr) {
- case 'e': return edit(page);
- case 't': return text(page, "text/plain");
- case 'c': return text(page, "text/css");
- }
- qstr++;
- }
- return view(page);
-}
-