This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
magicka/src/www.c

1068 lines
27 KiB
C
Raw Normal View History

#if defined(ENABLE_WWW)
#include <microhttpd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
2016-08-17 10:55:03 +10:00
#include <fcntl.h>
2016-08-17 19:26:01 +10:00
#include <b64/cdecode.h>
2016-08-21 08:01:23 +10:00
#include <sys/socket.h>
#include <arpa/inet.h>
2018-01-23 21:47:34 +10:00
#include <libgen.h>
2018-01-19 17:13:06 +10:00
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
2017-03-17 19:50:37 +10:00
#include <netinet/in.h>
#endif
#include "bbs.h"
2016-08-19 15:23:04 +10:00
#define GET 1
#define POST 2
2016-08-20 19:22:40 +10:00
#define POSTBUFFERSIZE 65536
2016-08-19 15:23:04 +10:00
extern struct bbs_config conf;
2016-08-21 08:01:23 +10:00
extern char *ipaddress;
2016-08-17 10:55:03 +10:00
struct mime_type {
char *ext;
char *mime;
};
static struct mime_type **mime_types;
static int mime_types_count;
2016-08-19 15:23:04 +10:00
struct connection_info_s {
int connection_type;
struct user_record *user;
char *url;
struct ptr_vector keys;
struct ptr_vector values;
2016-08-19 15:23:04 +10:00
int count;
struct MHD_PostProcessor *pp;
};
void *www_logger(void *cls, const char *uri, struct MHD_Connection *con) {
2018-01-21 15:02:21 +10:00
struct sockaddr *so = (struct sockaddr *)MHD_get_connection_info(con, MHD_CONNECTION_INFO_CLIENT_ADDRESS)->client_addr;
2018-01-21 19:05:01 +10:00
char *ipaddr;
2018-01-21 15:02:21 +10:00
if (so->sa_family == AF_INET) {
ipaddr = (char *)malloz(INET_ADDRSTRLEN + 1);
2018-01-21 19:05:01 +10:00
inet_ntop(AF_INET, &((struct sockaddr_in *)so)->sin_addr, ipaddr, INET_ADDRSTRLEN);
2018-01-21 15:02:21 +10:00
} else if (so->sa_family == AF_INET6) {
ipaddr = (char *)malloz(INET6_ADDRSTRLEN + 1);
2018-01-21 19:05:01 +10:00
inet_ntop(AF_INET6, &((struct sockaddr_in6 *)so)->sin6_addr, ipaddr, INET6_ADDRSTRLEN);
2018-01-21 15:02:21 +10:00
}
2018-01-21 19:05:01 +10:00
dolog_www(ipaddr, "%s", uri);
free(ipaddr);
2016-08-21 08:01:23 +10:00
return NULL;
}
2016-08-19 15:23:04 +10:00
void www_request_completed(void *cls, struct MHD_Connection *connection, void **con_cls, enum MHD_RequestTerminationCode toe) {
struct connection_info_s *con_info = *con_cls;
int i;
if (con_info == NULL) {
return;
}
2016-08-19 15:23:04 +10:00
if (con_info->connection_type == POST) {
if (con_info->count > 0) {
ptr_vector_apply(&con_info->values, free);
ptr_vector_apply(&con_info->keys, free);
destroy_ptr_vector(&con_info->values);
destroy_ptr_vector(&con_info->keys);
2016-08-19 15:23:04 +10:00
}
if (con_info->pp != NULL) {
MHD_destroy_post_processor(con_info->pp);
}
2016-08-19 15:23:04 +10:00
}
2016-08-19 17:37:07 +10:00
if (con_info->user != NULL) {
free(con_info->user->loginname);
free(con_info->user->password);
free(con_info->user->firstname);
free(con_info->user->lastname);
free(con_info->user->email);
free(con_info->user->location);
free(con_info->user->sec_info);
2018-01-21 15:02:21 +10:00
free(con_info->user->signature);
2016-08-19 17:37:07 +10:00
free(con_info->user);
}
2016-08-19 15:23:04 +10:00
free(con_info->url);
free(con_info);
}
static int iterate_post(void *coninfo_cls, enum MHD_ValueKind kind,
const char *key, const char *filename,
const char *content_type, const char *transfer_encoding,
const char *data, uint64_t off, size_t size) {
2016-08-19 15:23:04 +10:00
struct connection_info_s *con_info = coninfo_cls;
if (size == 0)
return MHD_NO;
2018-10-15 10:46:49 +10:00
if (con_info == NULL)
return MHD_NO;
if (con_info->connection_type != POST)
return MHD_NO;
for (int i = 0; i < con_info->count; i++) {
if (strcmp(ptr_vector_get(&con_info->keys, i), key) == 0) {
char *value = ptr_vector_get(&con_info->values, i);
size_t newsize = strlen(value) + size + 1;
char *newvalue = realloc(value, newsize);
strlcat(newvalue, data, newsize);
ptr_vector_put(&con_info->values, newvalue, i);
2016-08-19 15:23:04 +10:00
return MHD_YES;
}
}
ptr_vector_append(&con_info->keys, strdup(key));
ptr_vector_append(&con_info->values, strdup(data));
con_info->count++;
return MHD_YES;
2016-08-19 15:23:04 +10:00
}
2016-08-17 10:55:03 +10:00
void www_init() {
FILE *fptr;
2018-01-21 19:05:01 +10:00
char buffer[PATH_MAX];
struct ptr_vector vec = EMPTY_PTR_VECTOR;
snprintf(buffer, sizeof buffer, "%s/mime.types", conf.www_path);
2016-08-17 10:55:03 +10:00
fptr = fopen(buffer, "r");
if (!fptr) {
return;
}
fgets(buffer, sizeof buffer, fptr);
2016-08-17 10:55:03 +10:00
while (!feof(fptr)) {
chomp(buffer);
for (char *p = buffer; *p != '\0'; ++p) {
if (*p == ' ') {
*p = '\0';
struct mime_type *atype = (struct mime_type *)malloz(sizeof(struct mime_type));
atype->mime = strdup(buffer);
atype->ext = strdup(p + 1);
ptr_vector_append(&vec, atype);
2016-08-17 10:55:03 +10:00
break;
}
}
fgets(buffer, sizeof buffer, fptr);
2016-08-17 10:55:03 +10:00
}
fclose(fptr);
mime_types_count = ptr_vector_len(&vec);
mime_types = (struct mime_type **)consume_ptr_vector(&vec);
2016-08-17 10:55:03 +10:00
}
char *www_get_mime_type(const char *extension) {
static char default_mime_type[] = "application/octet-stream";
if (extension != NULL)
for (int i = 0; i < mime_types_count; i++)
if (strcasecmp(extension, mime_types[i]->ext) == 0)
return mime_types[i]->mime;
2016-08-17 10:55:03 +10:00
return default_mime_type;
}
int www_401(char *header, char *footer, struct MHD_Connection *connection) {
2018-01-21 19:05:01 +10:00
char buffer[PATH_MAX];
2018-01-21 15:02:21 +10:00
char *page, *page_tmp;
2016-08-17 19:26:01 +10:00
char *whole_page;
struct MHD_Response *response;
int ret;
FILE *fptr;
2018-01-21 19:05:01 +10:00
snprintf(buffer, PATH_MAX, "%s/401.tpl", conf.www_path);
page_tmp = file2str(buffer);
2018-01-21 15:02:21 +10:00
if (page_tmp == NULL) {
page_tmp = strdup("Missing Content");
2018-01-21 15:02:21 +10:00
if (page_tmp == NULL) {
2016-08-17 19:26:01 +10:00
return -1;
}
}
2018-01-21 15:02:21 +10:00
page = str_replace(page_tmp, "@@WWW_URL@@", conf.www_url);
free(page_tmp);
whole_page = str3dup(header, page, footer);
2016-08-17 19:26:01 +10:00
response = MHD_create_response_from_buffer(strlen(whole_page), (void *)whole_page, MHD_RESPMEM_MUST_FREE);
2016-08-17 19:26:01 +10:00
MHD_add_response_header(response, "WWW-Authenticate", "Basic realm=\"BBS Area\"");
ret = MHD_queue_response(connection, 401, response);
MHD_destroy_response(response);
2016-08-17 19:26:01 +10:00
free(page);
2016-08-17 19:26:01 +10:00
return 0;
}
int www_404(char *header, char *footer, struct MHD_Connection *connection) {
2018-01-21 19:05:01 +10:00
char buffer[PATH_MAX];
2018-01-21 15:02:21 +10:00
char *page, *page_tmp;
2016-08-17 10:55:03 +10:00
struct stat s;
char *whole_page;
struct MHD_Response *response;
int ret;
FILE *fptr;
2018-01-21 19:05:01 +10:00
snprintf(buffer, PATH_MAX, "%s/404.tpl", conf.www_path);
page_tmp = file2str(buffer);
2018-01-21 15:02:21 +10:00
if (page_tmp == NULL) {
page_tmp = (char *)strdup("Missing Content");
2018-01-21 15:02:21 +10:00
if (page_tmp == NULL) {
2016-08-17 10:55:03 +10:00
return -1;
}
}
2018-01-21 15:02:21 +10:00
page = str_replace(page_tmp, "@@WWW_URL@@", conf.www_url);
free(page_tmp);
whole_page = str3dup(header, page, footer);
2016-08-17 10:55:03 +10:00
response = MHD_create_response_from_buffer(strlen(whole_page), (void *)whole_page, MHD_RESPMEM_MUST_FREE);
ret = MHD_queue_response(connection, MHD_HTTP_NOT_FOUND, response);
MHD_destroy_response(response);
2016-08-17 10:55:03 +10:00
free(page);
2016-08-17 10:55:03 +10:00
return 0;
}
int www_403(char *header, char *footer, struct MHD_Connection *connection) {
2018-01-21 19:05:01 +10:00
char buffer[PATH_MAX];
2018-01-21 15:02:21 +10:00
char *page, *page_tmp;
2016-08-17 10:55:03 +10:00
struct stat s;
char *whole_page;
struct MHD_Response *response;
int ret;
FILE *fptr;
char *endptr;
2018-01-21 19:05:01 +10:00
snprintf(buffer, PATH_MAX, "%s/403.tpl", conf.www_path);
page_tmp = file2str(buffer);
2018-01-21 15:02:21 +10:00
if (page_tmp == NULL) {
page_tmp = strdup("Missing Content");
2018-01-21 15:02:21 +10:00
if (page_tmp == NULL) {
2016-08-17 10:55:03 +10:00
return -1;
}
}
2018-01-21 15:02:21 +10:00
page = str_replace(page_tmp, "@@WWW_URL@@", conf.www_url);
free(page_tmp);
whole_page = str3dup(header, page, footer);
2016-08-17 10:55:03 +10:00
response = MHD_create_response_from_buffer(strlen(whole_page), (void *)whole_page, MHD_RESPMEM_MUST_FREE);
ret = MHD_queue_response(connection, MHD_HTTP_NOT_FOUND, response);
MHD_destroy_response(response);
2016-08-17 10:55:03 +10:00
free(page);
2016-08-17 10:55:03 +10:00
return 0;
}
2016-08-17 19:26:01 +10:00
struct user_record *www_auth_ok(struct MHD_Connection *connection, const char *url) {
const char *ptr = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Authorization");
2017-10-02 19:31:42 +10:00
char *user_password;
2016-08-17 19:26:01 +10:00
base64_decodestate state;
char decoded_pass[34];
int len;
char *username;
char *password;
int i;
2017-10-02 19:31:42 +10:00
struct user_record *u;
2017-10-02 19:31:42 +10:00
if (ptr == NULL) {
2016-08-17 19:26:01 +10:00
return NULL;
}
2017-10-02 19:31:42 +10:00
user_password = strdup(ptr);
2016-08-17 19:26:01 +10:00
if (strncasecmp(user_password, "basic ", 6) == 0) {
if (strlen(&user_password[6]) <= 48) {
base64_init_decodestate(&state);
len = base64_decode_block(&user_password[6], strlen(&user_password[6]), decoded_pass, &state);
decoded_pass[len] = '\0';
2016-08-17 19:26:01 +10:00
username = decoded_pass;
for (i = 0; i < strlen(decoded_pass); i++) {
2016-08-17 19:26:01 +10:00
if (decoded_pass[i] == ':') {
decoded_pass[i] = '\0';
password = &decoded_pass[i + 1];
2016-08-17 19:26:01 +10:00
break;
}
}
2017-10-02 19:31:42 +10:00
u = check_user_pass(username, password);
free(user_password);
2017-10-02 19:31:42 +10:00
return u;
2016-08-17 19:26:01 +10:00
}
}
2017-10-02 19:31:42 +10:00
free(user_password);
2016-08-17 19:26:01 +10:00
return NULL;
}
int www_handler(void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **ptr) {
struct MHD_Response *response;
int ret;
2018-01-21 15:02:21 +10:00
char *page, *page_tmp;
2018-01-21 19:05:01 +10:00
char buffer[PATH_MAX];
struct stat s;
2018-01-21 15:02:21 +10:00
char *header, *header_tmp;
char *footer, *footer_tmp;
char *whole_page;
FILE *fptr;
2016-08-17 10:55:03 +10:00
char *mime;
int i;
int fno;
2016-08-17 19:26:01 +10:00
const char *url_ = url;
2016-08-19 15:23:04 +10:00
char *subj, *to, *body;
struct connection_info_s *con_inf;
2016-08-20 13:52:02 +10:00
int conference, area, msg;
char *url_copy;
char *aptr;
const char *val;
int skip;
char *replyid;
2018-01-23 20:57:58 +10:00
char *filename;
int email;
char *endptr;
2018-02-15 14:43:37 +10:00
int file_dir;
int file_sub;
char *filen;
// char *static_buffer;
2018-01-21 19:05:01 +10:00
2018-01-25 20:34:26 +10:00
page = NULL;
2016-08-19 15:23:04 +10:00
if (strcmp(method, "GET") == 0) {
if (*ptr == NULL) {
con_inf = (struct connection_info_s *)malloz(sizeof(struct connection_info_s));
2016-08-19 15:23:04 +10:00
if (!con_inf) {
return MHD_NO;
}
con_inf->connection_type = GET;
con_inf->user = NULL;
con_inf->count = 0;
con_inf->url = strdup(url);
con_inf->pp = NULL;
init_ptr_vector(&con_inf->values);
init_ptr_vector(&con_inf->keys);
2016-08-19 15:23:04 +10:00
*ptr = con_inf;
return MHD_YES;
}
} else if (strcmp(method, "POST") == 0) {
if (*ptr == NULL) {
con_inf = (struct connection_info_s *)malloz(sizeof(struct connection_info_s));
2016-08-19 15:23:04 +10:00
if (!con_inf) {
return MHD_NO;
}
con_inf->connection_type = POST;
con_inf->user = NULL;
con_inf->count = 0;
con_inf->url = strdup(url);
con_inf->pp = NULL;
init_ptr_vector(&con_inf->values);
init_ptr_vector(&con_inf->keys);
2016-08-19 15:23:04 +10:00
*ptr = con_inf;
return MHD_YES;
}
2016-08-21 12:41:50 +10:00
} else {
return MHD_NO;
2016-08-17 19:26:01 +10:00
}
2016-08-19 15:23:04 +10:00
con_inf = *ptr;
2018-01-21 19:05:01 +10:00
snprintf(buffer, PATH_MAX, "%s/header.tpl", conf.www_path);
header_tmp = file2str(buffer);
2018-01-21 15:02:21 +10:00
if (header_tmp == NULL) {
header_tmp = str5dup("<HTML>\n<HEAD>\n<TITLE>", conf.bbs_name, "</TITLE>\n</HEAD>\n<BODY>\n<H1>", conf.bbs_name, "</H1><HR />");
2018-01-21 15:02:21 +10:00
if (header_tmp == NULL) {
return MHD_NO;
}
}
2018-01-21 15:02:21 +10:00
header = str_replace(header_tmp, "@@WWW_URL@@", conf.www_url);
free(header_tmp);
2018-01-21 19:05:01 +10:00
snprintf(buffer, PATH_MAX, "%s/footer.tpl", conf.www_path);
footer_tmp = file2str(buffer);
2018-01-21 15:02:21 +10:00
if (footer_tmp == NULL) {
footer_tmp = strdup("<HR />Powered by Magicka BBS</BODY></HTML>");
2018-01-21 15:02:21 +10:00
if (footer_tmp == NULL) {
free(header);
return MHD_NO;
}
}
2018-01-21 15:02:21 +10:00
footer = str_replace(footer_tmp, "@@WWW_URL@@", conf.www_url);
free(footer_tmp);
if (strcmp(method, "GET") == 0) {
if (strcasecmp(url, "/") == 0) {
2018-01-21 19:05:01 +10:00
snprintf(buffer, PATH_MAX, "%s/index.tpl", conf.www_path);
page_tmp = file2str(buffer);
2018-01-21 15:02:21 +10:00
if (page_tmp == NULL) {
page_tmp = strdup("Missing Content");
2018-01-21 15:02:21 +10:00
if (page_tmp == NULL) {
free(header);
free(footer);
return MHD_NO;
}
}
2018-01-21 15:02:21 +10:00
page = str_replace(page_tmp, "@@WWW_URL@@", conf.www_url);
free(page_tmp);
whole_page = str3dup(header, page, footer);
2016-08-21 15:02:18 +10:00
} else if (strcasecmp(url, "/last10/") == 0 || strcasecmp(url, "/last10") == 0) {
page = www_last10();
if (page == NULL) {
free(header);
free(footer);
return MHD_NO;
2016-08-21 15:02:18 +10:00
}
whole_page = str3dup(header, page, footer);
2018-02-27 18:26:32 +10:00
} else if (strcasecmp(url, "/blog") == 0 || strcasecmp(url, "/blog/") == 0) {
page = www_blog();
if (page == NULL) {
free(header);
free(footer);
return MHD_NO;
2018-02-27 18:26:32 +10:00
}
whole_page = str3dup(header, page, footer);
2016-08-19 12:32:04 +10:00
} else if (strcasecmp(url, "/email/") == 0 || strcasecmp(url, "/email") == 0) {
2016-08-19 17:37:07 +10:00
con_inf->user = www_auth_ok(connection, url_);
2016-08-19 17:37:07 +10:00
if (con_inf->user == NULL) {
2016-08-17 19:26:01 +10:00
www_401(header, footer, connection);
free(header);
free(footer);
return MHD_YES;
2016-08-17 19:26:01 +10:00
}
2016-08-19 17:37:07 +10:00
page = www_email_summary(con_inf->user);
2016-08-17 19:26:01 +10:00
if (page == NULL) {
free(header);
free(footer);
return MHD_NO;
2016-08-17 19:26:01 +10:00
}
whole_page = str3dup(header, page, footer);
} else if (strcasecmp(url, "/email/new") == 0) {
2016-08-19 17:37:07 +10:00
con_inf->user = www_auth_ok(connection, url_);
2016-08-19 17:37:07 +10:00
if (con_inf->user == NULL) {
2016-08-19 15:23:04 +10:00
www_401(header, footer, connection);
free(header);
free(footer);
return MHD_YES;
2016-08-19 15:23:04 +10:00
}
page = www_new_email();
if (page == NULL) {
free(header);
free(footer);
return MHD_NO;
2016-08-19 15:23:04 +10:00
}
whole_page = str3dup(header, page, footer);
2016-08-19 17:37:07 +10:00
} else if (strncasecmp(url, "/email/delete/", 14) == 0) {
con_inf->user = www_auth_ok(connection, url_);
2016-08-19 17:37:07 +10:00
if (con_inf->user == NULL) {
www_401(header, footer, connection);
free(header);
free(footer);
return MHD_YES;
2016-08-19 17:37:07 +10:00
}
email = strtol(&url[14], &endptr, 10);
if (email == -1 || !www_email_delete(con_inf->user, email)) {
page = strdup("<h1>Error Deleting Email.</h1>");
2016-08-19 17:37:07 +10:00
if (page == NULL) {
free(header);
free(footer);
2016-08-19 17:37:07 +10:00
return MHD_NO;
}
} else {
page = strdup("<h1>Email Deleted!</h1>");
2016-08-19 17:37:07 +10:00
if (page == NULL) {
free(header);
free(footer);
2016-08-19 17:37:07 +10:00
return MHD_NO;
}
}
if (page == NULL) {
free(header);
free(footer);
return MHD_NO;
2016-08-19 17:37:07 +10:00
}
whole_page = str3dup(header, page, footer);
2016-08-19 12:32:04 +10:00
} else if (strncasecmp(url, "/email/", 7) == 0) {
2016-08-19 17:37:07 +10:00
con_inf->user = www_auth_ok(connection, url_);
2016-08-19 17:37:07 +10:00
if (con_inf->user == NULL) {
2016-08-19 12:32:04 +10:00
www_401(header, footer, connection);
free(header);
free(footer);
return MHD_YES;
2016-08-19 12:32:04 +10:00
}
email = strtol(&url[7], &endptr, 10);
if (email == -1) {
free(header);
free(footer);
return MHD_NO;
}
page = www_email_display(con_inf->user, email);
2016-08-19 12:32:04 +10:00
if (page == NULL) {
free(header);
free(footer);
return MHD_NO;
2016-08-19 12:32:04 +10:00
}
whole_page = str3dup(header, page, footer);
2016-08-20 13:52:02 +10:00
} else if (strcasecmp(url, "/msgs/") == 0 || strcasecmp(url, "/msgs") == 0) {
con_inf->user = www_auth_ok(connection, url_);
2016-08-20 13:52:02 +10:00
if (con_inf->user == NULL) {
www_401(header, footer, connection);
free(header);
free(footer);
return MHD_YES;
2016-08-20 13:52:02 +10:00
}
page = www_msgs_arealist(con_inf->user);
if (page == NULL) {
free(header);
free(footer);
return MHD_NO;
2016-08-20 13:52:02 +10:00
}
whole_page = str3dup(header, page, footer);
2018-05-22 12:20:38 +10:00
} else if (strncasecmp(url, "/msgs/flag/", 11) == 0) {
con_inf->user = www_auth_ok(connection, url_);
2018-05-22 12:20:38 +10:00
if (con_inf->user == NULL) {
www_401(header, footer, connection);
free(header);
free(footer);
return MHD_YES;
2018-05-22 12:20:38 +10:00
}
conference = -1;
area = -1;
msg = -1;
url_copy = strdup(&url[11]);
2018-05-22 12:20:38 +10:00
aptr = strtok(url_copy, "/");
if (aptr != NULL) {
conference = strtol(aptr, &endptr, 10);
if (endptr == aptr) {
conference = -1;
}
aptr = strtok(NULL, "/");
if (aptr != NULL) {
area = strtol(aptr, &endptr, 10);
if (endptr == aptr) {
area = -1;
}
aptr = strtok(NULL, "/");
if (aptr != NULL) {
msg = strtol(aptr, &endptr, 10);
if (endptr == aptr) {
msg = -1;
}
2018-05-22 12:20:38 +10:00
}
}
}
free(url_copy);
2018-05-22 12:20:38 +10:00
if (conference != -1 && area != -1 && msg != -1) {
msgbase_flag_unflag(con_inf->user, conference, area, msg);
response = MHD_create_response_from_buffer(0, (void *)"", MHD_RESPMEM_PERSISTENT);
2018-05-22 12:20:38 +10:00
snprintf(buffer, PATH_MAX, "%smsgs/%d/%d/%d", conf.www_url, conference, area, msg);
MHD_add_response_header(response, "Location", buffer);
MHD_queue_response(connection, MHD_HTTP_FOUND, response);
2018-05-22 12:20:38 +10:00
MHD_destroy_response(response);
free(header);
free(footer);
return MHD_YES;
}
www_404(header, footer, connection);
free(header);
free(footer);
return MHD_YES;
2016-08-20 13:52:02 +10:00
} else if (strncasecmp(url, "/msgs/new/", 10) == 0) {
con_inf->user = www_auth_ok(connection, url_);
2016-08-20 13:52:02 +10:00
if (con_inf->user == NULL) {
www_401(header, footer, connection);
free(header);
free(footer);
return MHD_YES;
}
2016-08-20 13:52:02 +10:00
conference = -1;
area = -1;
url_copy = strdup(&url[10]);
2016-08-20 13:52:02 +10:00
aptr = strtok(url_copy, "/");
if (aptr != NULL) {
conference = strtol(aptr, &endptr, 10);
if (endptr == aptr) {
conference = -1;
}
2016-08-20 13:52:02 +10:00
aptr = strtok(NULL, "/");
if (aptr != NULL) {
area = strtol(aptr, &endptr, 10);
if (endptr == aptr) {
area = -1;
}
2016-08-20 13:52:02 +10:00
}
}
free(url_copy);
2016-08-20 13:52:02 +10:00
if (area != -1 && conference != -1) {
page = www_new_msg(con_inf->user, conference, area);
} else {
free(header);
free(footer);
return MHD_NO;
2016-08-20 13:52:02 +10:00
}
whole_page = str3dup(header, page, footer);
2016-08-20 13:52:02 +10:00
} else if (strncasecmp(url, "/msgs/", 6) == 0) {
con_inf->user = www_auth_ok(connection, url_);
2016-08-20 13:52:02 +10:00
if (con_inf->user == NULL) {
www_401(header, footer, connection);
free(header);
free(footer);
return MHD_YES;
}
2016-08-20 13:52:02 +10:00
conference = -1;
area = -1;
msg = -1;
url_copy = strdup(&url[6]);
2016-08-20 13:52:02 +10:00
aptr = strtok(url_copy, "/");
if (aptr != NULL) {
conference = strtol(aptr, &endptr, 10);
if (endptr == aptr) {
conference = -1;
}
2016-08-20 13:52:02 +10:00
aptr = strtok(NULL, "/");
if (aptr != NULL) {
area = strtol(aptr, &endptr, 10);
if (endptr == aptr) {
area = -1;
}
2016-08-20 13:52:02 +10:00
aptr = strtok(NULL, "/");
if (aptr != NULL) {
msg = strtol(aptr, &endptr, 10);
if (endptr == aptr) {
msg = -1;
}
2016-08-20 13:52:02 +10:00
}
}
}
free(url_copy);
val = MHD_lookup_connection_value(connection, MHD_GET_ARGUMENT_KIND, "skip");
2016-08-20 13:52:02 +10:00
if (val != NULL) {
skip = atoi(val);
2016-08-20 13:52:02 +10:00
} else {
skip = 0;
}
if (conference != -1 && area != -1 && msg == -1) {
page = www_msgs_messagelist(con_inf->user, conference, area, skip);
} else if (conference != -1 && area != -1 && msg != -1) {
page = www_msgs_messageview(con_inf->user, conference, area, msg);
}
2016-08-20 13:52:02 +10:00
if (page == NULL) {
2016-08-21 13:54:31 +10:00
if (www_403(header, footer, connection) != 0) {
free(header);
free(footer);
return MHD_NO;
2016-08-21 13:54:31 +10:00
}
2016-08-20 13:52:02 +10:00
free(header);
free(footer);
return MHD_YES;
2016-08-20 13:52:02 +10:00
}
whole_page = str3dup(header, page, footer);
} else if (strncasecmp(url, "/static/", 8) == 0) {
// sanatize path
2016-08-17 10:55:03 +10:00
if (strstr(url, "/..") != NULL) {
2018-01-21 19:05:01 +10:00
free(header);
free(footer);
2016-08-17 10:55:03 +10:00
return MHD_NO;
}
2018-01-21 19:05:01 +10:00
mime = NULL;
2016-08-17 10:55:03 +10:00
// get mimetype
for (i = strlen(url); i > 0; --i) {
2016-08-17 10:55:03 +10:00
if (url[i] == '.') {
mime = www_get_mime_type(&url[i + 1]);
2016-08-17 10:55:03 +10:00
break;
}
2018-01-21 19:05:01 +10:00
if (url[i] == '/') {
mime = www_get_mime_type(NULL);
break;
}
}
if (mime = NULL) {
mime = www_get_mime_type(NULL);
2016-08-17 10:55:03 +10:00
}
2018-01-21 19:05:01 +10:00
// load file
snprintf(buffer, sizeof buffer, "%s%s", conf.www_path, url);
2016-08-17 10:55:03 +10:00
if (stat(buffer, &s) == 0 && S_ISREG(s.st_mode)) {
fno = open(buffer, O_RDONLY);
if (fno != -1) {
//static_buffer = (char *)malloz(s.st_size + 1);
2018-01-21 19:05:01 +10:00
//read(fno, static_buffer, s.st_size);
2016-08-17 10:55:03 +10:00
response = MHD_create_response_from_fd(s.st_size, fno);
2018-01-21 19:05:01 +10:00
//response = MHD_create_response_from_buffer (s.st_size, (void*) static_buffer, MHD_RESPMEM_MUST_FREE);
2016-08-17 10:55:03 +10:00
MHD_add_response_header(response, MHD_HTTP_HEADER_CONTENT_TYPE, mime);
ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
MHD_destroy_response(response);
2016-08-17 10:55:03 +10:00
free(header);
free(footer);
return ret;
2016-08-17 10:55:03 +10:00
} else {
if (www_403(header, footer, connection) != 0) {
free(header);
free(footer);
return MHD_NO;
2016-08-17 10:55:03 +10:00
}
free(header);
free(footer);
return MHD_YES;
2016-08-17 10:55:03 +10:00
}
} else {
if (www_404(header, footer, connection) != 0) {
free(header);
free(footer);
return MHD_NO;
2016-08-17 10:55:03 +10:00
}
free(header);
free(footer);
return MHD_YES;
2016-08-17 10:55:03 +10:00
}
} else if (strcasecmp(url, "/files/areas/") == 0 || strcasecmp(url, "/files/areas") == 0) {
2018-02-15 14:43:37 +10:00
page = www_files_areas();
whole_page = str3dup(header, page, footer);
2018-02-15 14:43:37 +10:00
} else if (strncasecmp(url, "/files/areas/", 13) == 0) {
file_dir = -1;
file_sub = -1;
filen = NULL;
url_copy = strdup(&url[13]);
2018-02-15 14:43:37 +10:00
aptr = strtok(url_copy, "/");
if (aptr != NULL) {
file_dir = strtol(aptr, &endptr, 10);
if (endptr == aptr) {
file_dir = -1;
}
aptr = strtok(NULL, "/");
if (aptr != NULL) {
file_sub = strtol(aptr, &endptr, 10);
if (endptr == aptr) {
file_sub = -1;
}
aptr = strtok(NULL, "/");
if (aptr != NULL) {
filen = strdup(aptr);
2018-02-15 14:43:37 +10:00
}
}
}
free(url_copy);
if (file_dir != -1 && file_sub != -1 && filen == NULL) {
if (file_dir >= 0 && file_dir < ptr_vector_len(&conf.file_directories)) {
struct file_directory *dir = ptr_vector_get(&conf.file_directories, file_dir);
assert(dir != NULL);
if (dir->display_on_web && file_sub >= 0 && file_sub < ptr_vector_len(&dir->file_subs)) {
2018-02-20 12:18:22 +10:00
page = www_files_display_listing(file_dir, file_sub);
}
2018-02-15 14:43:37 +10:00
}
} else if (file_dir != -1 && file_sub != -1 && filen != NULL) {
if (file_dir >= 0 && file_dir < ptr_vector_len(&conf.file_directories)) {
struct file_directory *dir = ptr_vector_get(&conf.file_directories, file_dir);
if (dir->display_on_web && file_sub >= 0 && file_sub < ptr_vector_len(&dir->file_subs)) {
2018-02-20 12:18:22 +10:00
// send file
filename = www_files_get_from_area(file_dir, file_sub, filen);
free(filen);
if (filename != NULL) {
2018-02-22 21:27:50 +10:00
mime = NULL;
// get mimetype
for (i = strlen(filename); i > 0; --i) {
2018-02-22 21:27:50 +10:00
if (filename[i] == '.') {
mime = www_get_mime_type(&filename[i + 1]);
2018-02-22 21:27:50 +10:00
break;
}
if (filename[i] == '/') {
mime = www_get_mime_type(NULL);
break;
}
}
if (mime = NULL) {
mime = www_get_mime_type(NULL);
}
2018-02-20 12:18:22 +10:00
if (stat(filename, &s) == 0 && S_ISREG(s.st_mode)) {
fno = open(filename, O_RDONLY);
if (fno != -1) {
response = MHD_create_response_from_fd(s.st_size, fno);
MHD_add_response_header(response, MHD_HTTP_HEADER_CONTENT_TYPE, mime);
snprintf(buffer, sizeof buffer, "%ld", s.st_size);
2018-02-20 12:18:22 +10:00
MHD_add_response_header(response, MHD_HTTP_HEADER_CONTENT_LENGTH, buffer);
2018-02-20 12:18:22 +10:00
snprintf(buffer, PATH_MAX, "attachment; filename=\"%s\"", basename(filename));
MHD_add_response_header(response, MHD_HTTP_HEADER_CONTENT_DISPOSITION, buffer);
ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
MHD_destroy_response(response);
2018-02-20 12:18:22 +10:00
free(header);
free(footer);
free(filename);
return ret;
}
2018-02-15 14:43:37 +10:00
}
2018-02-20 12:18:22 +10:00
free(filename);
}
if (www_404(header, footer, connection) != 0) {
free(header);
free(footer);
return MHD_NO;
2018-02-15 14:43:37 +10:00
}
free(header);
free(footer);
return MHD_YES;
2018-02-21 09:59:26 +10:00
} else {
free(filen);
2018-02-15 14:43:37 +10:00
}
2018-02-21 09:59:26 +10:00
} else {
2018-02-20 12:18:22 +10:00
free(filen);
2018-02-15 14:43:37 +10:00
}
}
if (page == NULL) {
if (www_403(header, footer, connection) != 0) {
free(header);
free(footer);
return MHD_NO;
2018-02-15 14:43:37 +10:00
}
free(header);
free(footer);
return MHD_YES;
2018-02-15 14:43:37 +10:00
}
whole_page = str3dup(header, page, footer);
2018-01-23 20:57:58 +10:00
} else if (strncasecmp(url, "/files/", 7) == 0) {
filename = www_decode_hash(&url[7]);
if (filename != NULL) {
2018-01-23 21:37:23 +10:00
mime = NULL;
// get mimetype
for (i = strlen(filename); i > 0; --i) {
2018-01-23 21:37:23 +10:00
if (filename[i] == '.') {
mime = www_get_mime_type(&filename[i + 1]);
2018-01-23 21:37:23 +10:00
break;
}
if (filename[i] == '/') {
mime = www_get_mime_type(NULL);
break;
}
}
if (mime = NULL) {
mime = www_get_mime_type(NULL);
}
2018-01-23 20:57:58 +10:00
if (stat(filename, &s) == 0 && S_ISREG(s.st_mode)) {
2018-01-23 21:16:36 +10:00
fno = open(filename, O_RDONLY);
2018-01-23 20:57:58 +10:00
if (fno != -1) {
2018-01-23 20:57:58 +10:00
response = MHD_create_response_from_fd(s.st_size, fno);
MHD_add_response_header(response, MHD_HTTP_HEADER_CONTENT_TYPE, mime);
snprintf(buffer, sizeof buffer, "%ld", s.st_size);
2018-01-23 20:57:58 +10:00
MHD_add_response_header(response, MHD_HTTP_HEADER_CONTENT_LENGTH, buffer);
2018-01-23 20:57:58 +10:00
snprintf(buffer, PATH_MAX, "attachment; filename=\"%s\"", basename(filename));
MHD_add_response_header(response, MHD_HTTP_HEADER_CONTENT_DISPOSITION, buffer);
ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
MHD_destroy_response(response);
2018-01-23 20:57:58 +10:00
free(header);
free(footer);
2018-01-23 21:16:36 +10:00
free(filename);
2018-01-23 20:57:58 +10:00
return ret;
}
}
free(filename);
}
if (www_404(header, footer, connection) != 0) {
free(header);
free(footer);
return MHD_NO;
2018-01-23 20:57:58 +10:00
}
free(header);
free(footer);
return MHD_YES;
} else {
2016-08-17 10:55:03 +10:00
if (www_404(header, footer, connection) != 0) {
free(header);
free(footer);
return MHD_NO;
2016-08-17 10:55:03 +10:00
}
free(header);
free(footer);
return MHD_YES;
}
} else if (strcmp(method, "POST") == 0) {
2016-08-19 15:23:04 +10:00
if (strcasecmp(url, "/email/") == 0 || strcasecmp(url, "/email") == 0) {
con_inf->user = www_auth_ok(connection, url_);
2016-08-19 17:37:07 +10:00
if (con_inf->user == NULL) {
2016-08-19 15:23:04 +10:00
www_401(header, footer, connection);
free(header);
free(footer);
return MHD_YES;
}
if (con_inf->pp == NULL) {
con_inf->pp = MHD_create_post_processor(connection, POSTBUFFERSIZE, iterate_post, (void *)con_inf);
2016-08-19 15:23:04 +10:00
}
if (*upload_data_size != 0) {
MHD_post_process(con_inf->pp, upload_data, *upload_data_size);
2016-08-19 15:23:04 +10:00
*upload_data_size = 0;
2016-08-19 15:23:04 +10:00
return MHD_YES;
}
subj = NULL;
to = NULL;
body = NULL;
for (i = 0; i < con_inf->count; i++) {
const char *key = ptr_vector_get(&con_inf->keys, i);
char *value = ptr_vector_get(&con_inf->values, i);
if (strcmp(key, "recipient") == 0) {
to = value;
} else if (strcmp(key, "subject") == 0) {
subj = value;
} else if (strcmp(key, "body") == 0) {
body = value;
2016-08-19 15:23:04 +10:00
}
}
if (!www_send_email(con_inf->user, to, subj, body)) {
page = strdup("<h1>Error Sending Email (Check User Exists?)</h1>");
2016-08-19 15:23:04 +10:00
if (page == NULL) {
free(header);
free(footer);
2016-08-19 15:23:04 +10:00
return MHD_NO;
}
} else {
page = strdup("<h1>Email Sent!</h1>");
2016-08-19 15:23:04 +10:00
if (page == NULL) {
free(header);
free(footer);
2016-08-19 15:23:04 +10:00
return MHD_NO;
}
}
whole_page = str3dup(header, page, footer);
2016-08-20 13:52:02 +10:00
} else if (strcasecmp(url, "/msgs/") == 0 || strcasecmp(url, "/msgs") == 0) {
con_inf->user = www_auth_ok(connection, url_);
if (con_inf->user == NULL) {
www_401(header, footer, connection);
free(header);
free(footer);
return MHD_YES;
2016-08-20 13:52:02 +10:00
}
if (con_inf->pp == NULL) {
con_inf->pp = MHD_create_post_processor(connection, POSTBUFFERSIZE, iterate_post, (void *)con_inf);
}
2016-08-20 13:52:02 +10:00
if (*upload_data_size != 0) {
MHD_post_process(con_inf->pp, upload_data, *upload_data_size);
2016-08-20 13:52:02 +10:00
*upload_data_size = 0;
2016-08-20 13:52:02 +10:00
return MHD_YES;
}
subj = NULL;
to = NULL;
body = NULL;
replyid = NULL;
2018-01-21 15:02:21 +10:00
conference = -1;
area = -1;
for (i = 0; i < con_inf->count; i++) {
const char *key = ptr_vector_get(&con_inf->keys, i);
char *value = ptr_vector_get(&con_inf->values, i);
if (strcmp(key, "recipient") == 0) {
to = value;
} else if (strcmp(key, "subject") == 0) {
subj = value;
} else if (strcmp(key, "body") == 0) {
body = value;
} else if (strcmp(key, "conference") == 0) {
conference = strtol(value, &endptr, 10);
if (endptr == value) {
conference = -1;
}
} else if (strcmp(key, "area") == 0) {
area = strtol(value, &endptr, 10);
if (endptr == value) {
area = -1;
}
} else if (strcmp(key, "replyid") == 0) {
replyid = value;
2016-08-20 13:52:02 +10:00
}
}
2018-01-21 15:02:21 +10:00
2016-08-20 13:52:02 +10:00
if (!www_send_msg(con_inf->user, to, subj, conference, area, replyid, body)) {
page = strdup("<h1>Error Sending Message</h1>");
2016-08-20 13:52:02 +10:00
if (page == NULL) {
free(header);
free(footer);
2016-08-20 13:52:02 +10:00
return MHD_NO;
}
} else {
page = strdup("<h1>Message Sent!</h1>");
2016-08-20 13:52:02 +10:00
if (page == NULL) {
free(header);
free(footer);
2016-08-20 13:52:02 +10:00
return MHD_NO;
}
}
whole_page = str3dup(header, page, footer);
2016-08-19 15:23:04 +10:00
} else {
free(header);
free(footer);
2016-08-19 15:23:04 +10:00
return MHD_NO;
}
2016-08-21 09:45:38 +10:00
} else {
free(header);
free(footer);
return MHD_NO;
}
response = MHD_create_response_from_buffer(strlen(whole_page), (void *)whole_page, MHD_RESPMEM_MUST_FREE);
2016-08-19 12:32:04 +10:00
MHD_add_response_header(response, MHD_HTTP_HEADER_CONTENT_TYPE, "text/html");
ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
MHD_destroy_response(response);
free(page);
free(header);
free(footer);
return ret;
}
#endif