#include "mongoose.h" #include "index.h" #include "gsl.h" #include "agsl.h" #include "lgsl.h" #include "clauses.h" #include #include #include #include #include #include #include char *port = "33368"; // sneed, backwards, in phone number, with the last number changed to 8 cuz sneedmc.org is already on 33367 void trim(char *str) { char *_str = str; int len = strlen(_str); while(*_str && *_str == '/') ++_str, --len; memmove(str, _str, len + 1); } // I stole this directly from stack overflow. char** str_split(char* a_str, const char a_delim) { char** result = 0; size_t count = 0; char* tmp = a_str; char* last_comma = 0; char delim[2]; delim[0] = a_delim; delim[1] = 0; /* Count how many elements will be extracted. */ while (*tmp) { if (a_delim == *tmp) { count++; last_comma = tmp; } tmp++; } /* Add space for trailing token. */ count += last_comma < (a_str + strlen(a_str) - 1); /* Add space for terminating null string so caller knows where the list of returned strings ends. */ count++; result = malloc(sizeof(char*) * count); if (result) { size_t idx = 0; char* token = strtok(a_str, delim); while (token) { assert(idx < count); *(result + idx++) = strdup(token); token = strtok(0, delim); } assert(idx == count - 1); *(result + idx) = 0; } return result; } int arrlen(char **a_arr) { int count = 0; while (a_arr[count] != NULL) count++; return count; } // compare N chars of s1 to s2 bool eq(const char *s1, const char *s2, int n) { return strncmp(s1, s2, n) == 0; } void handle_url_req(struct mg_connection *nc, char *host, char *link) { char *a_host = strdup(host); char **host_elements = str_split(a_host, '.'); free(a_host); if (arrlen(host_elements) == 3) { // FIXME: index.html goes here. return mg_http_reply(nc, 200, "Content-Type: text/html\r\n", "%s\r\n", INDEX_HTML); } char *b_host = strdup(host_elements[0]); char **host_clauses = str_split(b_host, '-'); free(b_host); size_t startclause = 18; char *license; if (eq(host_elements[0], "gsl", 3)) { license = strdup(GSL); } else if (eq(host_elements[0], "agsl", 4)) { license = strdup(AGSL); } else if (eq(host_elements[0], "lgsl", 4)) { license = strdup(LGSL); startclause = 7; } else { mg_http_reply(nc, 404, "", "Not Found"); } int clausenum = startclause; char *jogger = malloc(strlen(JOGGER_NOTICE) + 2); char *farmer = malloc(strlen(FARMER_NOTICE) + 2); char *dwarf = malloc(strlen(DWARF_NOTICE) + 2); char *output_clauses[3] = {"", "", ""}; bool jogger_shown = false; bool farmer_shown = false; bool dwarf_shown = false; if (arrlen(host_clauses) > 1) { for (size_t i = 0; i < strlen(host_clauses[1]); i++) { if (host_clauses[1][i] == 'n' && !jogger_shown) { snprintf(jogger, strlen(JOGGER_NOTICE) + 2, JOGGER_NOTICE, clausenum); output_clauses[clausenum - startclause] = jogger; clausenum++; jogger_shown = true; } else if (host_clauses[1][i] == 'd' && !dwarf_shown) { snprintf(dwarf, strlen(DWARF_NOTICE) + 2, DWARF_NOTICE, clausenum); output_clauses[clausenum - startclause] = dwarf; clausenum++; dwarf_shown = true; } else if (host_clauses[1][i] == 'f' && !farmer_shown) { snprintf(farmer, strlen(FARMER_NOTICE) + 2, FARMER_NOTICE, clausenum); output_clauses[clausenum - startclause] = farmer; clausenum++; farmer_shown = true; } else { continue; } } } mg_http_reply(nc, 200, "Content-Type: text/plain; charset=utf-8\r\n", license, output_clauses[0], output_clauses[1], output_clauses[2], host); free(host_elements); free(host_clauses); free(jogger); free(dwarf); free(farmer); } static void ev_handler(struct mg_connection *nc, int ev, void *p, void *f) { if (ev == MG_EV_HTTP_MSG) { struct mg_http_message *hm = (struct mg_http_message *) p; char *uri = malloc(hm->uri.len + 1); snprintf(uri, hm->uri.len + 1, "%s", hm->uri.ptr); trim(uri); // Host parsing here. struct mg_str *pmhost = mg_http_get_header(hm, "Host"); struct mg_str mhost; if (pmhost == NULL) { fprintf(stderr, "request sent with no Host header"); free(uri); mg_http_reply(nc, 400, "", "Please include a Host header."); return; } mhost = *pmhost; char *host = malloc(mhost.len + 1); snprintf(host, mhost.len + 1, "%s", mhost.ptr); if (strncmp(hm->method.ptr, "GET", hm->method.len) == 0){ if (eq(uri, "favicon.ico", 12) || eq(uri, "sneedcube.png", 14)) { struct mg_http_serve_opts opts = {.root_dir = "/srv/gsl"}; // Serve local dir if (ev == MG_EV_HTTP_MSG) mg_http_serve_dir(nc, p, &opts); return; } handle_url_req(nc, host, uri); } else { mg_http_reply(nc, 405, "Allow: GET\r\n", ""); } free(uri); free(host); } } int main(int argc, char *argv[]) { setlocale(LC_CTYPE, ""); int index; int c; opterr = 0; setvbuf(stdout, NULL, _IONBF, 0); while ((c = getopt (argc, argv, "p:h")) != -1) { switch (c) { case 'p': port = optarg; break; case 'h': printf("gsl: host the GSL licenses\n"); printf("usage: %s [-p port]\n\n", argv[0]); printf("options:\n"); printf("-p \t\tport to use (default 33368)\n"); printf("source: https://git.sneedmc.org/sneederix/gsl"); return 0; case '?': if (optopt == 'p') { fprintf(stderr, "Option -%c requires an argument.\n", optopt); } else if (isprint (optopt)) { fprintf(stderr, "Unknown option `-%c'.\n", optopt); } else { fprintf(stderr, "Unknown option character `\\x%x'.\n", optopt); } return 1; default: abort(); } } for (index = optind; index < argc; index++) { printf ("Non-option argument %s\n", argv[index]); } struct mg_mgr mgr; struct mg_connection *nc; mg_mgr_init(&mgr); printf("Starting web server on port %s\n", port); char *str_port = malloc(20); sprintf(str_port, "http://0.0.0.0:%s", port); nc = mg_http_listen(&mgr, str_port, ev_handler, &mgr); if (nc == NULL) { printf("Failed to create listener\n"); return 1; } for (;;) { mg_mgr_poll(&mgr, 1000); } mg_mgr_free(&mgr); return 0; }