2022-09-05 02:48:41 +00:00
|
|
|
#include "mongoose.h"
|
|
|
|
#include "index.h"
|
2022-09-05 04:05:16 +00:00
|
|
|
#include "gsl.h"
|
|
|
|
#include "agsl.h"
|
|
|
|
#include "lgsl.h"
|
|
|
|
#include "clauses.h"
|
2022-09-05 02:48:41 +00:00
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
2022-09-05 04:05:16 +00:00
|
|
|
#include <assert.h>
|
|
|
|
#include <locale.h>
|
2022-09-05 02:48:41 +00:00
|
|
|
|
|
|
|
char *port = "33368"; // sneed, backwards, in phone number, with the last number changed to 8 cuz sneedmc.org is already on 33367
|
|
|
|
|
|
|
|
static struct mg_http_serve_opts s_http_server_opts;
|
|
|
|
|
|
|
|
void trim(char *str) {
|
|
|
|
char *_str = str;
|
|
|
|
int len = strlen(_str);
|
|
|
|
|
|
|
|
while(*_str && *_str == '/') ++_str, --len;
|
|
|
|
|
|
|
|
memmove(str, _str, len + 1);
|
|
|
|
}
|
|
|
|
|
2022-09-05 04:05:16 +00:00
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
2022-09-05 02:48:41 +00:00
|
|
|
void handle_url_req(struct mg_connection *nc, char *host, char *link) {
|
2022-09-05 04:05:16 +00:00
|
|
|
if (strncmp(link, "favicon.ico", 12) == 0) {
|
|
|
|
mg_http_reply(nc, 404, "", "Not Found"); // FIXME: sneed cube.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
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", "Sneed\r\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2022-09-05 02:48:41 +00:00
|
|
|
} else {
|
2022-09-05 04:05:16 +00:00
|
|
|
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;
|
|
|
|
}
|
2022-09-05 02:48:41 +00:00
|
|
|
}
|
|
|
|
}
|
2022-09-05 04:05:16 +00:00
|
|
|
|
|
|
|
mg_http_reply(nc, 200, "", license, output_clauses[0], output_clauses[1], output_clauses[2], host);
|
|
|
|
|
|
|
|
free(host_elements);
|
|
|
|
free(host_clauses);
|
|
|
|
|
|
|
|
free(jogger);
|
|
|
|
free(dwarf);
|
|
|
|
free(farmer);
|
2022-09-05 02:48:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
2022-09-05 04:05:16 +00:00
|
|
|
mg_http_reply(nc, 400, "", "Please include a Host header.");
|
2022-09-05 02:48:41 +00:00
|
|
|
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){
|
|
|
|
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[]) {
|
2022-09-05 04:05:16 +00:00
|
|
|
setlocale(LC_CTYPE, "");
|
2022-09-05 02:48:41 +00:00
|
|
|
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 <port>\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;
|
|
|
|
}
|
|
|
|
|