From 6ac2e6f1254e55163ba82325e4f1717cfcaf8a8c Mon Sep 17 00:00:00 2001 From: Andrew Pamment Date: Sun, 21 Jan 2018 15:02:21 +1000 Subject: [PATCH 01/87] WWW improvements, fixes and a bug. --- .gitignore | 1 + dist/config/bbs.ini | 1 + dist/www/header.tpl | 12 +-- file_id.diz | 2 +- src/bbs.c | 46 +++++++++++ src/bbs.h | 5 +- src/main.c | 10 ++- src/www.c | 189 +++++++++++++++++++++++++------------------- src/www_email.c | 14 +++- src/www_msgs.c | 29 ++++--- 10 files changed, 202 insertions(+), 107 deletions(-) diff --git a/.gitignore b/.gitignore index 442798f..c076286 100644 --- a/.gitignore +++ b/.gitignore @@ -75,3 +75,4 @@ menus/file.mnu menus/logoff.mnu menus/mail.mnu menus/main.mnu +.vscode/settings.json diff --git a/dist/config/bbs.ini b/dist/config/bbs.ini index 3a2736a..22dd472 100644 --- a/dist/config/bbs.ini +++ b/dist/config/bbs.ini @@ -16,6 +16,7 @@ Automessage Write Level = 10 Fork = false Enable WWW = false WWW Port = 8080 +WWW URL = http://127.0.0.1:8080/ Enable SSH = false SSH Port = 2024 SSH DSA Key = /home/andrew/MagickaBBS/keys/ssh_host_dsa_key diff --git a/dist/www/header.tpl b/dist/www/header.tpl index 29bb8f5..7dd9a84 100644 --- a/dist/www/header.tpl +++ b/dist/www/header.tpl @@ -1,19 +1,19 @@ Magicka BBS - +
- Magicka BBS + Magicka BBS

diff --git a/file_id.diz b/file_id.diz index 110c861..95d964a 100644 --- a/file_id.diz +++ b/file_id.diz @@ -1,6 +1,6 @@ . . . .__ .__ __. |\/| _. _ * _.;_/ _. [__)[__)(__ -| |(_](_]|(_.| \(_] [__)[__).__) v0.8a +| |(_](_]|(_.| \(_] [__)[__).__) v0.9a -------._|---------------------------------- Magicka BBS is a Free BBS System for Linux, macOS, FreeBSD, NetBSD, OpenIndiana, diff --git a/src/bbs.c b/src/bbs.c index 04e4a2c..11802bd 100644 --- a/src/bbs.c +++ b/src/bbs.c @@ -1075,3 +1075,49 @@ int copy_file(char *src, char *dest) { fclose(dest_file); return 0; } + +char *str_replace(char *orig, char *rep, char *with) { + char *result; // the return string + char *ins; // the next insert point + char *tmp; // varies + int len_rep; // length of rep (the string to remove) + int len_with; // length of with (the string to replace rep with) + int len_front; // distance between rep and end of last rep + int count; // number of replacements + + // sanity checks and initialization + if (!orig || !rep) + return NULL; + len_rep = strlen(rep); + if (len_rep == 0) + return NULL; // empty rep causes infinite loop during count + if (!with) + with = ""; + len_with = strlen(with); + + // count the number of replacements needed + ins = orig; + for (count = 0; tmp = strstr(ins, rep); ++count) { + ins = tmp + len_rep; + } + + tmp = result = malloc(strlen(orig) + (len_with - len_rep) * count + 1); + + if (!result) + return NULL; + + // first time through the loop, all the variable are set correctly + // from here on, + // tmp points to the end of the result string + // ins points to the next occurrence of rep in orig + // orig points to the remainder of orig after "end of rep" + while (count--) { + ins = strstr(orig, rep); + len_front = ins - orig; + tmp = strncpy(tmp, orig, len_front) + len_front; + tmp = strcpy(tmp, with) + len_with; + orig += len_front + len_rep; // move to next "end of rep" + } + strcpy(tmp, orig); + return result; +} diff --git a/src/bbs.h b/src/bbs.h index efe4e7a..e745edf 100644 --- a/src/bbs.h +++ b/src/bbs.h @@ -12,7 +12,7 @@ #include "jamlib/jam.h" #define VERSION_MAJOR 0 -#define VERSION_MINOR 8 +#define VERSION_MINOR 9 #define VERSION_STR "alpha" #define NETWORK_FIDO 1 @@ -128,6 +128,7 @@ struct bbs_config { char *netmail_sem; char *default_tagline; int telnet_port; + char *www_url; int www_server; int www_port; char *www_path; @@ -227,6 +228,8 @@ struct msg_headers { struct jam_msg **msgs; int msg_count; }; + +extern char *str_replace(char *orig, char *rep, char *with); extern int copy_file(char *src, char *dest); extern int recursive_delete(const char *dir); extern void automessage_write(struct user_record *user); diff --git a/src/main.c b/src/main.c index 19a6cc2..43c0c1e 100644 --- a/src/main.c +++ b/src/main.c @@ -425,6 +425,13 @@ static int handler(void* user, const char* section, const char* name, } } else if (strcasecmp(name, "www port") == 0) { conf->www_port = atoi(value); + } else if (strcasecmp(name, "www url") == 0) { + if (value[strlen(value) - 1] == '/') { + conf->www_url = strdup(value); + } else { + conf->www_url = (char *)malloc(strlen(value) + 2); + sprintf(conf->www_url, "%s/", value); + } } else if (strcasecmp(name, "ssh port") == 0) { conf->ssh_port = atoi(value); } else if (strcasecmp(name, "ssh dsa key") == 0) { @@ -1065,7 +1072,7 @@ void server(int port, int ipv6) { } #if defined(ENABLE_WWW) - if (conf.www_server && conf.www_path != NULL) { + if (conf.www_server && conf.www_path != NULL && conf.www_url != NULL) { if (!conf.fork) { printf(" - HTTP Starting on Port %d (IPv%d)\n", conf.www_port, (ipv6 ? 6 : 4)); } @@ -1241,6 +1248,7 @@ int main(int argc, char **argv) { conf.telnet_port = 0; conf.string_file = NULL; conf.www_path = NULL; + conf.www_url = NULL; conf.archiver_count = 0; conf.broadcast_enable = 0; conf.broadcast_port = 0; diff --git a/src/www.c b/src/www.c index bbb1bd2..39c398e 100644 --- a/src/www.c +++ b/src/www.c @@ -40,8 +40,14 @@ struct connection_info_s { }; void *www_logger(void * cls, const char * uri, struct MHD_Connection *con) { - struct sockaddr_in *so = (struct sockaddr_in *)MHD_get_connection_info(con, MHD_CONNECTION_INFO_CLIENT_ADDRESS)->client_addr; - ipaddress = strdup(inet_ntoa(so->sin_addr)); + struct sockaddr *so = (struct sockaddr *)MHD_get_connection_info(con, MHD_CONNECTION_INFO_CLIENT_ADDRESS)->client_addr; + if (so->sa_family == AF_INET) { + ipaddress = (char *)malloc(INET_ADDRSTRLEN + 1); + inet_ntop(AF_INET, &((struct sockaddr_in *)so)->sin_addr, ipaddress, INET_ADDRSTRLEN); + } else if (so->sa_family == AF_INET6) { + ipaddress = (char *)malloc(INET6_ADDRSTRLEN + 1); + inet_ntop(AF_INET6, &((struct sockaddr_in6 *)so)->sin6_addr, ipaddress, INET6_ADDRSTRLEN); + } dolog("%s", uri); free(ipaddress); ipaddress = NULL; @@ -78,6 +84,7 @@ void www_request_completed(void *cls, struct MHD_Connection *connection, void ** free(con_info->user->email); free(con_info->user->location); free(con_info->user->sec_info); + free(con_info->user->signature); free(con_info->user); } @@ -181,7 +188,7 @@ char *www_get_mime_type(const char *extension) { int www_401(char *header, char *footer, struct MHD_Connection * connection) { char buffer[4096]; - char *page; + char *page, *page_tmp; struct stat s; char *whole_page; struct MHD_Response *response; @@ -190,32 +197,35 @@ int www_401(char *header, char *footer, struct MHD_Connection * connection) { snprintf(buffer, 4096, "%s/401.tpl", conf.www_path); - page = NULL; + page_tmp = NULL; if (stat(buffer, &s) == 0) { - page = (char *)malloc(s.st_size + 1); - if (page == NULL) { + page_tmp = (char *)malloc(s.st_size + 1); + if (page_tmp == NULL) { return -1; } - memset(page, 0, s.st_size + 1); + memset(page_tmp, 0, s.st_size + 1); fptr = fopen(buffer, "r"); if (fptr) { - fread(page, s.st_size, 1, fptr); + fread(page_tmp, s.st_size, 1, fptr); fclose(fptr); } else { - free(page); - page = NULL; + free(page_tmp); + page_tmp = NULL; } } - if (page == NULL) { - page = (char *)malloc(16); - if (page == NULL) { + if (page_tmp == NULL) { + page_tmp = (char *)malloc(16); + if (page_tmp == NULL) { return -1; } - sprintf(page, "Missing Content"); + sprintf(page_tmp, "Missing Content"); } - + + page = str_replace(page_tmp, "@@WWW_URL@@", conf.www_url); + free(page_tmp); + whole_page = (char *)malloc(strlen(header) + strlen(page) + strlen(footer) + 1); sprintf(whole_page, "%s%s%s", header, page, footer); @@ -233,7 +243,7 @@ int www_401(char *header, char *footer, struct MHD_Connection * connection) { int www_404(char *header, char *footer, struct MHD_Connection * connection) { char buffer[4096]; - char *page; + char *page, *page_tmp; struct stat s; char *whole_page; struct MHD_Response *response; @@ -242,32 +252,35 @@ int www_404(char *header, char *footer, struct MHD_Connection * connection) { snprintf(buffer, 4096, "%s/404.tpl", conf.www_path); - page = NULL; + page_tmp = NULL; if (stat(buffer, &s) == 0) { - page = (char *)malloc(s.st_size + 1); - if (page == NULL) { + page_tmp = (char *)malloc(s.st_size + 1); + if (page_tmp == NULL) { return -1; } - memset(page, 0, s.st_size + 1); + memset(page_tmp, 0, s.st_size + 1); fptr = fopen(buffer, "r"); if (fptr) { - fread(page, s.st_size, 1, fptr); + fread(page_tmp, s.st_size, 1, fptr); fclose(fptr); } else { - free(page); + free(page_tmp); page = NULL; } } - if (page == NULL) { - page = (char *)malloc(16); - if (page == NULL) { + if (page_tmp == NULL) { + page_tmp = (char *)malloc(16); + if (page_tmp == NULL) { return -1; } - sprintf(page, "Missing Content"); + sprintf(page_tmp, "Missing Content"); } - + + page = str_replace(page_tmp, "@@WWW_URL@@", conf.www_url); + free(page_tmp); + whole_page = (char *)malloc(strlen(header) + strlen(page) + strlen(footer) + 1); sprintf(whole_page, "%s%s%s", header, page, footer); @@ -283,7 +296,7 @@ int www_404(char *header, char *footer, struct MHD_Connection * connection) { int www_403(char *header, char *footer, struct MHD_Connection * connection) { char buffer[4096]; - char *page; + char *page, *page_tmp; struct stat s; char *whole_page; struct MHD_Response *response; @@ -292,32 +305,35 @@ int www_403(char *header, char *footer, struct MHD_Connection * connection) { snprintf(buffer, 4096, "%s/403.tpl", conf.www_path); - page = NULL; + page_tmp = NULL; if (stat(buffer, &s) == 0) { - page = (char *)malloc(s.st_size + 1); - if (page == NULL) { + page_tmp = (char *)malloc(s.st_size + 1); + if (page_tmp == NULL) { return -1; } - memset(page, 0, s.st_size + 1); + memset(page_tmp, 0, s.st_size + 1); fptr = fopen(buffer, "r"); if (fptr) { - fread(page, s.st_size, 1, fptr); + fread(page_tmp, s.st_size, 1, fptr); fclose(fptr); } else { - free(page); - page = NULL; + free(page_tmp); + page_tmp = NULL; } } - if (page == NULL) { - page = (char *)malloc(16); - if (page == NULL) { + if (page_tmp == NULL) { + page_tmp = (char *)malloc(16); + if (page_tmp == NULL) { return -1; } - sprintf(page, "Missing Content"); + sprintf(page_tmp, "Missing Content"); } - + + page = str_replace(page_tmp, "@@WWW_URL@@", conf.www_url); + free(page_tmp); + whole_page = (char *)malloc(strlen(header) + strlen(page) + strlen(footer) + 1); sprintf(whole_page, "%s%s%s", header, page, footer); @@ -376,11 +392,11 @@ int www_handler(void * cls, struct MHD_Connection * connection, const char * url struct MHD_Response *response; int ret; - char *page; + char *page, *page_tmp; char buffer[4096]; struct stat s; - char *header; - char *footer; + char *header, *header_tmp; + char *footer, *footer_tmp; char *whole_page; FILE *fptr; char *mime; @@ -432,97 +448,106 @@ int www_handler(void * cls, struct MHD_Connection * connection, const char * url snprintf(buffer, 4096, "%s/header.tpl", conf.www_path); - header = NULL; + header_tmp = NULL; if (stat(buffer, &s) == 0) { - header = (char *)malloc(s.st_size + 1); - if (header == NULL) { + header_tmp = (char *)malloc(s.st_size + 1); + if (header_tmp == NULL) { return MHD_NO; } - memset(header, 0, s.st_size + 1); + memset(header_tmp, 0, s.st_size + 1); fptr = fopen(buffer, "r"); if (fptr) { - fread(header, s.st_size, 1, fptr); + fread(header_tmp, s.st_size, 1, fptr); fclose(fptr); } else { - free(header); - header = NULL; + free(header_tmp); + header_tmp = NULL; } } - if (header == NULL) { - header = (char *)malloc(strlen(conf.bbs_name) * 2 + 61); - if (header == NULL) { + if (header_tmp == NULL) { + header_tmp = (char *)malloc(strlen(conf.bbs_name) * 2 + 61); + if (header_tmp == NULL) { return MHD_NO; } - sprintf(header, "\n\n%s\n\n\n

%s


", conf.bbs_name, conf.bbs_name); + sprintf(header_tmp, "\n\n%s\n\n\n

%s


", conf.bbs_name, conf.bbs_name); } + header = str_replace(header_tmp, "@@WWW_URL@@", conf.www_url); + free(header_tmp); + snprintf(buffer, 4096, "%s/footer.tpl", conf.www_path); footer = NULL; if (stat(buffer, &s) == 0) { - footer = (char *)malloc(s.st_size + 1); - if (footer == NULL) { + footer_tmp = (char *)malloc(s.st_size + 1); + if (footer_tmp == NULL) { free(header); return MHD_NO; } - memset(footer, 0, s.st_size + 1); + memset(footer_tmp, 0, s.st_size + 1); fptr = fopen(buffer, "r"); if (fptr) { - fread(footer, s.st_size, 1, fptr); + fread(footer_tmp, s.st_size, 1, fptr); fclose(fptr); } else { - free(footer); - footer = NULL; + free(footer_tmp); + footer_tmp = NULL; } } - if (footer == NULL) { - footer = (char *)malloc(43); - if (footer == NULL) { + if (footer_tmp == NULL) { + footer_tmp = (char *)malloc(43); + if (footer_tmp == NULL) { free(header); return MHD_NO; } - sprintf(footer, "
Powered by Magicka BBS"); + sprintf(footer_tmp, "
Powered by Magicka BBS"); } - + + footer = str_replace(footer_tmp, "@@WWW_URL@@", conf.www_url); + free(footer_tmp); + if (strcmp(method, "GET") == 0) { if (strcasecmp(url, "/") == 0) { snprintf(buffer, 4096, "%s/index.tpl", conf.www_path); - page = NULL; + page_tmp = NULL; if (stat(buffer, &s) == 0) { - page = (char *)malloc(s.st_size + 1); - if (page == NULL) { + page_tmp = (char *)malloc(s.st_size + 1); + if (page_tmp == NULL) { free(header); free(footer); return MHD_NO; } - memset(page, 0, s.st_size + 1); + memset(page_tmp, 0, s.st_size + 1); fptr = fopen(buffer, "r"); if (fptr) { - fread(page, s.st_size, 1, fptr); + fread(page_tmp, s.st_size, 1, fptr); fclose(fptr); } else { - free(page); - page = NULL; + free(page_tmp); + page_tmp = NULL; } } - if (page == NULL) { - page = (char *)malloc(16); - if (page == NULL) { + if (page_tmp == NULL) { + page_tmp = (char *)malloc(16); + if (page_tmp == NULL) { free(header); free(footer); return MHD_NO; } - sprintf(page, "Missing Content"); + sprintf(page_tmp, "Missing Content"); } - + + page = str_replace(page_tmp, "@@WWW_URL@@", conf.www_url); + free(page_tmp); + whole_page = (char *)malloc(strlen(header) + strlen(page) + strlen(footer) + 1); sprintf(whole_page, "%s%s%s", header, page, footer); @@ -756,7 +781,7 @@ int www_handler(void * cls, struct MHD_Connection * connection, const char * url MHD_destroy_response (response); free(header); free(footer); - return MHD_YES; + return ret; } else { if (www_403(header, footer, connection) != 0) { free(header); @@ -864,7 +889,8 @@ int www_handler(void * cls, struct MHD_Connection * connection, const char * url to = NULL; body = NULL; replyid = NULL; - + conference = -1; + area = -1; for (i=0;icount;i++) { if (strcmp(con_inf->keys[i], "recipient") == 0) { @@ -881,8 +907,9 @@ int www_handler(void * cls, struct MHD_Connection * connection, const char * url replyid = con_inf->values[i]; } } + if (!www_send_msg(con_inf->user, to, subj, conference, area, replyid, body)) { - page = (char *)malloc(50); + page = (char *)malloc(31); if (page == NULL) { free(header); free(footer); @@ -890,7 +917,7 @@ int www_handler(void * cls, struct MHD_Connection * connection, const char * url } sprintf(page, "

Error Sending Message

"); } else { - page = (char *)malloc(21); + page = (char *)malloc(23); if (page == NULL) { free(header); free(footer); diff --git a/src/www_email.c b/src/www_email.c index 6addda8..e0ba8d1 100644 --- a/src/www_email.c +++ b/src/www_email.c @@ -80,10 +80,16 @@ int www_send_email(struct user_record *user, char *recipient, char *subject, cha int i; int pos; + if (recipient == NULL || subject == NULL || ibody == NULL) { + return 0; + } + if (check_user(recipient)) { return 0; } + + uname(&name); snprintf(buffer, 256, "\r--- MagickaBBS v%d.%d%s (%s/%s)\r * Origin: %s \r", VERSION_MAJOR, VERSION_MINOR, VERSION_STR, name.sysname, name.machine, conf.default_tagline); @@ -159,7 +165,7 @@ char *www_new_email() { strcat(page, buffer); len += strlen(buffer); - sprintf(buffer, "
\n"); + sprintf(buffer, "\n", conf.www_url); if (len + strlen(buffer) > max_len - 1) { max_len += 4096; page = (char *)realloc(page, max_len); @@ -380,7 +386,7 @@ char *www_email_display(struct user_record *user, int email) { strcat(page, buffer); len += strlen(buffer); - sprintf(buffer, "\n"); + sprintf(buffer, "\n", conf.www_url); if (len + strlen(buffer) > max_len - 1) { max_len += 4096; page = (char *)realloc(page, max_len); @@ -612,7 +618,7 @@ sqlite3_busy_timeout(db, 5000); date = (time_t)sqlite3_column_int(res, 4); localtime_r(&date, &msg_date); if (seen == 0) { - sprintf(buffer, "
%d
%s
%.2d:%.2d %.2d-%.2d-%.2d
\"delete\"
\n", msgid + 1, msgid + 1, subject, from, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mday, msg_date.tm_mon + 1, msg_date.tm_year - 100, id); + sprintf(buffer, "
%d
%s
%.2d:%.2d %.2d-%.2d-%.2d
\"delete\"
\n", msgid + 1, conf.www_url, msgid + 1, subject, from, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mday, msg_date.tm_mon + 1, msg_date.tm_year - 100, conf.www_url, id, conf.www_url); if (len + strlen(buffer) > max_len - 1) { max_len += 4096; page = (char *)realloc(page, max_len); @@ -620,7 +626,7 @@ sqlite3_busy_timeout(db, 5000); strcat(page, buffer); len += strlen(buffer); } else { - sprintf(buffer, "
%d
%s
%.2d:%.2d %.2d-%.2d-%.2d
\"delete\"
\n", msgid + 1, msgid + 1, subject, from, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mday, msg_date.tm_mon + 1, msg_date.tm_year - 100, id); + sprintf(buffer, "
%d
%s
%.2d:%.2d %.2d-%.2d-%.2d
\"delete\"
\n", msgid + 1, conf.www_url, msgid + 1, subject, from, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mday, msg_date.tm_mon + 1, msg_date.tm_year - 100, conf.www_url, id, conf.www_url); if (len + strlen(buffer) > max_len - 1) { max_len += 4096; page = (char *)realloc(page, max_len); diff --git a/src/www_msgs.c b/src/www_msgs.c index 29fcc45..93dfac6 100644 --- a/src/www_msgs.c +++ b/src/www_msgs.c @@ -141,9 +141,9 @@ char *www_msgs_arealist(struct user_record *user) { if (conf.mail_conferences[i]->mail_areas[j]->read_sec_level <= user->sec_level) { if (new_messages(user, i, j) > 0) { - sprintf(buffer, "\n", i, j, conf.mail_conferences[i]->mail_areas[j]->name); + sprintf(buffer, "\n", conf.www_url, i, j, conf.mail_conferences[i]->mail_areas[j]->name); } else { - sprintf(buffer, "\n", i, j, conf.mail_conferences[i]->mail_areas[j]->name); + sprintf(buffer, "\n", conf.www_url, i, j, conf.mail_conferences[i]->mail_areas[j]->name); } if (len + strlen(buffer) > max_len - 1) { max_len += 4096; @@ -192,7 +192,7 @@ char *www_msgs_messagelist(struct user_record *user, int conference, int area, i len += strlen(buffer); if (conf.mail_conferences[conference]->mail_areas[area]->type != TYPE_NETMAIL_AREA) { - sprintf(buffer, "\n", conference, area); + sprintf(buffer, "\n", conf.www_url, conference, area); if (len + strlen(buffer) > max_len - 1) { max_len += 4096; page = (char *)realloc(page, max_len); @@ -246,15 +246,15 @@ char *www_msgs_messagelist(struct user_record *user, int conference, int area, i subject = www_sanitize(mhrs->msgs[i]->subject); if (mhrs->msgs[i]->msg_h->MsgNum > jlr.HighReadMsg) { if (conf.date_style == 1) { - sprintf(buffer, "
%d
%s
%s
%.2d:%.2d %.2d-%.2d-%.2d
\n", mhrs->msgs[i]->msg_no + 1, conference, area, mhrs->msgs[i]->msg_h->MsgNum, subject, from, to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mon + 1, msg_date.tm_mday, msg_date.tm_year - 100); + sprintf(buffer, "
%d
%s
%s
%.2d:%.2d %.2d-%.2d-%.2d
\n", mhrs->msgs[i]->msg_no + 1, conf.www_url, conference, area, mhrs->msgs[i]->msg_h->MsgNum, subject, from, to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mon + 1, msg_date.tm_mday, msg_date.tm_year - 100); } else { - sprintf(buffer, "
%d
%s
%s
%.2d:%.2d %.2d-%.2d-%.2d
\n", mhrs->msgs[i]->msg_no + 1, conference, area, mhrs->msgs[i]->msg_h->MsgNum, subject, from, to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mday, msg_date.tm_mon + 1, msg_date.tm_year - 100); + sprintf(buffer, "
%d
%s
%s
%.2d:%.2d %.2d-%.2d-%.2d
\n", mhrs->msgs[i]->msg_no + 1, conf.www_url, conference, area, mhrs->msgs[i]->msg_h->MsgNum, subject, from, to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mday, msg_date.tm_mon + 1, msg_date.tm_year - 100); } } else { if (conf.date_style == 1) { - sprintf(buffer, "
%d
%s
%s
%.2d:%.2d %.2d-%.2d-%.2d
\n", mhrs->msgs[i]->msg_no + 1, conference, area, mhrs->msgs[i]->msg_h->MsgNum, subject, from, to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mon + 1, msg_date.tm_mday, msg_date.tm_year - 100); + sprintf(buffer, "
%d
%s
%s
%.2d:%.2d %.2d-%.2d-%.2d
\n", mhrs->msgs[i]->msg_no + 1, conf.www_url, conference, area, mhrs->msgs[i]->msg_h->MsgNum, subject, from, to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mon + 1, msg_date.tm_mday, msg_date.tm_year - 100); } else { - sprintf(buffer, "
%d
%s
%s
%.2d:%.2d %.2d-%.2d-%.2d
\n", mhrs->msgs[i]->msg_no + 1, conference, area, mhrs->msgs[i]->msg_h->MsgNum, subject, from, to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mday, msg_date.tm_mon + 1, msg_date.tm_year - 100); + sprintf(buffer, "
%d
%s
%s
%.2d:%.2d %.2d-%.2d-%.2d
\n", mhrs->msgs[i]->msg_no + 1, conf.www_url, conference, area, mhrs->msgs[i]->msg_h->MsgNum, subject, from, to, msg_date.tm_hour, msg_date.tm_min, msg_date.tm_mday, msg_date.tm_mon + 1, msg_date.tm_year - 100); } } @@ -279,9 +279,9 @@ char *www_msgs_messagelist(struct user_record *user, int conference, int area, i if (skip > 0) { if (skip - 50 < 0) { - sprintf(buffer, "\n", conference, area); + sprintf(buffer, "\n", conf.www_url, conference, area); } else { - sprintf(buffer, "\n", conference, area, skip - 50); + sprintf(buffer, "\n", conf.www_url, conference, area, skip - 50); } if (len + strlen(buffer) > max_len - 1) { max_len += 4096; @@ -292,7 +292,7 @@ char *www_msgs_messagelist(struct user_record *user, int conference, int area, i } if (skip + 50 <= mhrs->msg_count) { - sprintf(buffer, "\n", conference, area, skip + 50); + sprintf(buffer, "\n", conf.www_url, conference, area, skip + 50); if (len + strlen(buffer) > max_len - 1) { max_len += 4096; page = (char *)realloc(page, max_len); @@ -458,7 +458,7 @@ char *www_msgs_messageview(struct user_record *user, int conference, int area, i len = 0; memset(page, 0, 4096); - sprintf(buffer, "\n", conference, area, conf.mail_conferences[conference]->name, conf.mail_conferences[conference]->mail_areas[area]->name); + sprintf(buffer, "\n", conf.www_url, conference, area, conf.mail_conferences[conference]->name, conf.mail_conferences[conference]->mail_areas[area]->name); if (len + strlen(buffer) > max_len - 1) { max_len += 4096; page = (char *)realloc(page, max_len); @@ -579,7 +579,7 @@ char *www_msgs_messageview(struct user_record *user, int conference, int area, i strcat(page, buffer); len += strlen(buffer); - sprintf(buffer, "\n"); + sprintf(buffer, "\n", conf.www_url); if (len + strlen(buffer) > max_len - 1) { max_len += 4096; page = (char *)realloc(page, max_len); @@ -757,6 +757,9 @@ int www_send_msg(struct user_record *user, char *to, char *subj, int conference, if (conference < 0 || conference >= conf.mail_conference_count || area < 0 || area >= conf.mail_conferences[conference]->mail_area_count) { return 0; } + if (subj == NULL || to == NULL || body == NULL) { + return 0; + } if (conf.mail_conferences[conference]->mail_areas[area]->write_sec_level <= user->sec_level && conf.mail_conferences[conference]->mail_areas[area]->type != TYPE_NETMAIL_AREA) { jb = open_jam_base(conf.mail_conferences[conference]->mail_areas[area]->path); if (!jb) { @@ -933,7 +936,7 @@ char *www_new_msg(struct user_record *user, int conference, int area) { strcat(page, buffer); len += strlen(buffer); - sprintf(buffer, "\n"); + sprintf(buffer, "\n", conf.www_url); if (len + strlen(buffer) > max_len - 1) { max_len += 4096; page = (char *)realloc(page, max_len); From aac4aaad00136c4efb56997662e7afec94f04341 Mon Sep 17 00:00:00 2001 From: Andrew Pamment Date: Sun, 21 Jan 2018 15:19:04 +1000 Subject: [PATCH 02/87] fix new email link --- src/www_email.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/www_email.c b/src/www_email.c index e0ba8d1..73d019d 100644 --- a/src/www_email.c +++ b/src/www_email.c @@ -566,7 +566,7 @@ char *www_email_summary(struct user_record *user) { strcat(page, buffer); len += strlen(buffer); - sprintf(buffer, "\n"); + sprintf(buffer, "\n", config.www_url); if (len + strlen(buffer) > max_len - 1) { max_len += 4096; page = (char *)realloc(page, max_len); From 69897e795538342a5ea1551d0d1a1448c2e4625b Mon Sep 17 00:00:00 2001 From: Andrew Pamment Date: Sun, 21 Jan 2018 19:05:01 +1000 Subject: [PATCH 03/87] Think I may have fixed it! --- .gitignore | 2 + src/Makefile.linux.WWW | 2 +- src/bbs.c | 148 +++++++++++++++++++++++++++++------------ src/bbs.h | 3 +- src/www.c | 71 +++++++++++++------- src/www_email.c | 2 +- 6 files changed, 157 insertions(+), 71 deletions(-) diff --git a/.gitignore b/.gitignore index c076286..d16aea4 100644 --- a/.gitignore +++ b/.gitignore @@ -76,3 +76,5 @@ menus/logoff.mnu menus/mail.mnu menus/main.mnu .vscode/settings.json +core +.vscode/launch.json diff --git a/src/Makefile.linux.WWW b/src/Makefile.linux.WWW index 16f0756..6ddadc0 100644 --- a/src/Makefile.linux.WWW +++ b/src/Makefile.linux.WWW @@ -5,7 +5,7 @@ JAMLIB = ../deps/jamlib/jamlib.a ZMODEM = ../deps/Xmodem/libzmodem.a LUA = ../deps/lua/liblua.a B64 = ../deps/libb64-1.2/src/libb64.a -MICROHTTPD=-lmicrohttpd +MICROHTTPD=-lmicrohttpd ODOORS = ../deps/odoors/libs-`uname -s`/libODoors.a JSMN = ../deps/jsmn/libjsmn.a CDK = ../deps/cdk-5-20161210/libcdk.a diff --git a/src/bbs.c b/src/bbs.c index 11802bd..9171a28 100644 --- a/src/bbs.c +++ b/src/bbs.c @@ -89,8 +89,8 @@ void broadcast(char *mess, ...) { } } -void dolog(char *fmt, ...) { - char buffer[512]; +void dolog_www(char *ipaddr, char *fmt, ...) { + char buffer[PATH_MAX]; struct tm time_now; time_t timen; FILE *logfptr; @@ -102,14 +102,42 @@ void dolog(char *fmt, ...) { localtime_r(&timen, &time_now); - snprintf(buffer, 512, "%s/%04d%02d%02d.log", conf.log_path, time_now.tm_year + 1900, time_now.tm_mon + 1, time_now.tm_mday); + snprintf(buffer, PATH_MAX, "%s/%04d%02d%02d.log", conf.log_path, time_now.tm_year + 1900, time_now.tm_mon + 1, time_now.tm_mday); logfptr = fopen(buffer, "a"); if (!logfptr) { return; } va_list ap; va_start(ap, fmt); - vsnprintf(buffer, 512, fmt, ap); + vsnprintf(buffer, PATH_MAX, fmt, ap); + va_end(ap); + + fprintf(logfptr, "%02d:%02d:%02d [%d][%s] %s\n", time_now.tm_hour, time_now.tm_min, time_now.tm_sec, mypid, ipaddr, buffer); + + fclose(logfptr); +} + +void dolog(char *fmt, ...) { + char buffer[PATH_MAX]; + struct tm time_now; + time_t timen; + FILE *logfptr; + int mypid = getpid(); + + if (conf.log_path == NULL) return; + + timen = time(NULL); + + localtime_r(&timen, &time_now); + + snprintf(buffer, PATH_MAX, "%s/%04d%02d%02d.log", conf.log_path, time_now.tm_year + 1900, time_now.tm_mon + 1, time_now.tm_mday); + logfptr = fopen(buffer, "a"); + if (!logfptr) { + return; + } + va_list ap; + va_start(ap, fmt); + vsnprintf(buffer, PATH_MAX, fmt, ap); va_end(ap); fprintf(logfptr, "%02d:%02d:%02d [%d][%s] %s\n", time_now.tm_hour, time_now.tm_min, time_now.tm_sec, mypid, ipaddress, buffer); @@ -1076,48 +1104,80 @@ int copy_file(char *src, char *dest) { return 0; } -char *str_replace(char *orig, char *rep, char *with) { - char *result; // the return string - char *ins; // the next insert point - char *tmp; // varies - int len_rep; // length of rep (the string to remove) - int len_with; // length of with (the string to replace rep with) - int len_front; // distance between rep and end of last rep - int count; // number of replacements +char *str_replace(const char *str, const char *from, const char *to) { + /* Adjust each of the below values to suit your needs. */ - // sanity checks and initialization - if (!orig || !rep) - return NULL; - len_rep = strlen(rep); - if (len_rep == 0) - return NULL; // empty rep causes infinite loop during count - if (!with) - with = ""; - len_with = strlen(with); + /* Increment positions cache size initially by this number. */ + size_t cache_sz_inc = 16; + /* Thereafter, each time capacity needs to be increased, + * multiply the increment by this factor. */ + const size_t cache_sz_inc_factor = 3; + /* But never increment capacity by more than this number. */ + const size_t cache_sz_inc_max = 1048576; - // count the number of replacements needed - ins = orig; - for (count = 0; tmp = strstr(ins, rep); ++count) { - ins = tmp + len_rep; - } + char *pret, *ret = NULL; + const char *pstr2, *pstr = str; + size_t i, count = 0; + uintptr_t *pos_cache_tmp, *pos_cache = NULL; + size_t cache_sz = 0; + size_t cpylen, orglen, retlen, tolen, fromlen = strlen(from); - tmp = result = malloc(strlen(orig) + (len_with - len_rep) * count + 1); + /* Find all matches and cache their positions. */ + while ((pstr2 = strstr(pstr, from)) != NULL) { + count++; - if (!result) - return NULL; + /* Increase the cache size when necessary. */ + if (cache_sz < count) { + cache_sz += cache_sz_inc; + pos_cache_tmp = realloc(pos_cache, sizeof(*pos_cache) * cache_sz); + if (pos_cache_tmp == NULL) { + goto end_repl_str; + } else pos_cache = pos_cache_tmp; + cache_sz_inc *= cache_sz_inc_factor; + if (cache_sz_inc > cache_sz_inc_max) { + cache_sz_inc = cache_sz_inc_max; + } + } - // first time through the loop, all the variable are set correctly - // from here on, - // tmp points to the end of the result string - // ins points to the next occurrence of rep in orig - // orig points to the remainder of orig after "end of rep" - while (count--) { - ins = strstr(orig, rep); - len_front = ins - orig; - tmp = strncpy(tmp, orig, len_front) + len_front; - tmp = strcpy(tmp, with) + len_with; - orig += len_front + len_rep; // move to next "end of rep" - } - strcpy(tmp, orig); - return result; -} + pos_cache[count-1] = pstr2 - str; + pstr = pstr2 + fromlen; + } + + orglen = pstr - str + strlen(pstr); + + /* Allocate memory for the post-replacement string. */ + if (count > 0) { + tolen = strlen(to); + retlen = orglen + (tolen - fromlen) * count; + } else retlen = orglen; + ret = malloc(retlen + 1); + if (ret == NULL) { + goto end_repl_str; + } + + if (count == 0) { + /* If no matches, then just duplicate the string. */ + strcpy(ret, str); + } else { + /* Otherwise, duplicate the string whilst performing + * the replacements using the position cache. */ + pret = ret; + memcpy(pret, str, pos_cache[0]); + pret += pos_cache[0]; + for (i = 0; i < count; i++) { + memcpy(pret, to, tolen); + pret += tolen; + pstr = str + pos_cache[i] + fromlen; + cpylen = (i == count-1 ? orglen : pos_cache[i+1]) - pos_cache[i] - fromlen; + memcpy(pret, pstr, cpylen); + pret += cpylen; + } + ret[retlen] = '\0'; + } + +end_repl_str: + /* Free the cache and return the post-replacement string, + * which will be NULL in the event of an error. */ + free(pos_cache); + return ret; +} \ No newline at end of file diff --git a/src/bbs.h b/src/bbs.h index e745edf..01758e9 100644 --- a/src/bbs.h +++ b/src/bbs.h @@ -229,12 +229,13 @@ struct msg_headers { int msg_count; }; -extern char *str_replace(char *orig, char *rep, char *with); +extern char *str_replace(const char *orig, const char *rep, const char *with); extern int copy_file(char *src, char *dest); extern int recursive_delete(const char *dir); extern void automessage_write(struct user_record *user); extern void automessage_display(); extern void dolog(char *fmt, ...); +extern void dolog_www(char *ipaddr, char *fmt, ...); extern void runbbs_ssh(char *ipaddress); extern void runbbs(int sock, char *ipaddress); extern struct fido_addr *parse_fido_addr(const char *str); diff --git a/src/www.c b/src/www.c index 39c398e..2acd743 100644 --- a/src/www.c +++ b/src/www.c @@ -41,16 +41,17 @@ struct connection_info_s { void *www_logger(void * cls, const char * uri, struct MHD_Connection *con) { struct sockaddr *so = (struct sockaddr *)MHD_get_connection_info(con, MHD_CONNECTION_INFO_CLIENT_ADDRESS)->client_addr; + char *ipaddr; if (so->sa_family == AF_INET) { - ipaddress = (char *)malloc(INET_ADDRSTRLEN + 1); - inet_ntop(AF_INET, &((struct sockaddr_in *)so)->sin_addr, ipaddress, INET_ADDRSTRLEN); + ipaddr = (char *)malloc(INET_ADDRSTRLEN + 1); + inet_ntop(AF_INET, &((struct sockaddr_in *)so)->sin_addr, ipaddr, INET_ADDRSTRLEN); } else if (so->sa_family == AF_INET6) { - ipaddress = (char *)malloc(INET6_ADDRSTRLEN + 1); - inet_ntop(AF_INET6, &((struct sockaddr_in6 *)so)->sin6_addr, ipaddress, INET6_ADDRSTRLEN); + ipaddr = (char *)malloc(INET6_ADDRSTRLEN + 1); + inet_ntop(AF_INET6, &((struct sockaddr_in6 *)so)->sin6_addr, ipaddr, INET6_ADDRSTRLEN); } - dolog("%s", uri); - free(ipaddress); - ipaddress = NULL; + dolog_www(ipaddr, "%s", uri); + free(ipaddr); + return NULL; } @@ -133,18 +134,18 @@ static int iterate_post (void *coninfo_cls, enum MHD_ValueKind kind, const char void www_init() { FILE *fptr; - char buffer[4096]; + char buffer[PATH_MAX]; int i; mime_types_count = 0; - sprintf(buffer, "%s/mime.types", conf.www_path); + snprintf(buffer, PATH_MAX, "%s/mime.types", conf.www_path); fptr = fopen(buffer, "r"); if (!fptr) { return; } - fgets(buffer, 4096, fptr); + fgets(buffer, 256, fptr); while (!feof(fptr)) { chomp(buffer); @@ -167,7 +168,7 @@ void www_init() { } } - fgets(buffer, 4096, fptr); + fgets(buffer, 256, fptr); } fclose(fptr); @@ -177,7 +178,10 @@ char *www_get_mime_type(const char *extension) { int i; static char default_mime_type[] = "application/octet-stream"; - + if (extension == NULL) { + return default_mime_type; + } + for (i=0;iext) == 0) { return mime_types[i]->mime; @@ -187,7 +191,7 @@ char *www_get_mime_type(const char *extension) { } int www_401(char *header, char *footer, struct MHD_Connection * connection) { - char buffer[4096]; + char buffer[PATH_MAX]; char *page, *page_tmp; struct stat s; char *whole_page; @@ -195,7 +199,7 @@ int www_401(char *header, char *footer, struct MHD_Connection * connection) { int ret; FILE *fptr; - snprintf(buffer, 4096, "%s/401.tpl", conf.www_path); + snprintf(buffer, PATH_MAX, "%s/401.tpl", conf.www_path); page_tmp = NULL; @@ -242,7 +246,7 @@ int www_401(char *header, char *footer, struct MHD_Connection * connection) { } int www_404(char *header, char *footer, struct MHD_Connection * connection) { - char buffer[4096]; + char buffer[PATH_MAX]; char *page, *page_tmp; struct stat s; char *whole_page; @@ -250,7 +254,7 @@ int www_404(char *header, char *footer, struct MHD_Connection * connection) { int ret; FILE *fptr; - snprintf(buffer, 4096, "%s/404.tpl", conf.www_path); + snprintf(buffer, PATH_MAX, "%s/404.tpl", conf.www_path); page_tmp = NULL; @@ -295,7 +299,7 @@ int www_404(char *header, char *footer, struct MHD_Connection * connection) { } int www_403(char *header, char *footer, struct MHD_Connection * connection) { - char buffer[4096]; + char buffer[PATH_MAX]; char *page, *page_tmp; struct stat s; char *whole_page; @@ -303,7 +307,7 @@ int www_403(char *header, char *footer, struct MHD_Connection * connection) { int ret; FILE *fptr; - snprintf(buffer, 4096, "%s/403.tpl", conf.www_path); + snprintf(buffer, PATH_MAX, "%s/403.tpl", conf.www_path); page_tmp = NULL; @@ -393,7 +397,7 @@ int www_handler(void * cls, struct MHD_Connection * connection, const char * url int ret; char *page, *page_tmp; - char buffer[4096]; + char buffer[PATH_MAX]; struct stat s; char *header, *header_tmp; char *footer, *footer_tmp; @@ -411,7 +415,8 @@ int www_handler(void * cls, struct MHD_Connection * connection, const char * url const char *val; int skip; char *replyid; - +// char *static_buffer; + if (strcmp(method, "GET") == 0) { if (*ptr == NULL) { con_inf = (struct connection_info_s *)malloc(sizeof(struct connection_info_s)); @@ -446,7 +451,7 @@ int www_handler(void * cls, struct MHD_Connection * connection, const char * url con_inf = *ptr; - snprintf(buffer, 4096, "%s/header.tpl", conf.www_path); + snprintf(buffer, PATH_MAX, "%s/header.tpl", conf.www_path); header_tmp = NULL; @@ -477,9 +482,9 @@ int www_handler(void * cls, struct MHD_Connection * connection, const char * url header = str_replace(header_tmp, "@@WWW_URL@@", conf.www_url); free(header_tmp); - snprintf(buffer, 4096, "%s/footer.tpl", conf.www_path); + snprintf(buffer, PATH_MAX, "%s/footer.tpl", conf.www_path); - footer = NULL; + footer_tmp = NULL; if (stat(buffer, &s) == 0) { footer_tmp = (char *)malloc(s.st_size + 1); @@ -513,7 +518,7 @@ int www_handler(void * cls, struct MHD_Connection * connection, const char * url if (strcmp(method, "GET") == 0) { if (strcasecmp(url, "/") == 0) { - snprintf(buffer, 4096, "%s/index.tpl", conf.www_path); + snprintf(buffer, PATH_MAX, "%s/index.tpl", conf.www_path); page_tmp = NULL; @@ -760,22 +765,40 @@ int www_handler(void * cls, struct MHD_Connection * connection, const char * url } else if (strncasecmp(url, "/static/", 8) == 0) { // sanatize path if (strstr(url, "/..") != NULL) { + free(header); + free(footer); return MHD_NO; } + + mime = NULL; // get mimetype for (i=strlen(url);i>0;--i) { if (url[i] == '.') { mime = www_get_mime_type(&url[i+1]); break; } + if (url[i] == '/') { + mime = www_get_mime_type(NULL); + break; + } } + + if (mime = NULL) { + mime = www_get_mime_type(NULL); + } + + // load file sprintf(buffer, "%s%s", conf.www_path, url); if (stat(buffer, &s) == 0 && S_ISREG(s.st_mode)) { fno = open(buffer, O_RDONLY); if (fno != -1) { + + //static_buffer = (char *)malloc(s.st_size + 1); + //read(fno, static_buffer, s.st_size); response = MHD_create_response_from_fd(s.st_size, fno); + //response = MHD_create_response_from_buffer (s.st_size, (void*) static_buffer, MHD_RESPMEM_MUST_FREE); MHD_add_response_header(response, MHD_HTTP_HEADER_CONTENT_TYPE, mime); ret = MHD_queue_response (connection, MHD_HTTP_OK, response); MHD_destroy_response (response); diff --git a/src/www_email.c b/src/www_email.c index 73d019d..28c00e9 100644 --- a/src/www_email.c +++ b/src/www_email.c @@ -566,7 +566,7 @@ char *www_email_summary(struct user_record *user) { strcat(page, buffer); len += strlen(buffer); - sprintf(buffer, "\n", config.www_url); + sprintf(buffer, "\n", conf.www_url); if (len + strlen(buffer) > max_len - 1) { max_len += 4096; page = (char *)realloc(page, max_len); From c5b754e13572599d4e7242bd777a53262befdfac Mon Sep 17 00:00:00 2001 From: Andrew Pamment Date: Mon, 22 Jan 2018 12:48:43 +1000 Subject: [PATCH 04/87] Fix for broken msgs? --- src/mail_menu.c | 7 ++++++- src/www_msgs.c | 10 +++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/mail_menu.c b/src/mail_menu.c index 1ea20ff..1fc5a0d 100644 --- a/src/mail_menu.c +++ b/src/mail_menu.c @@ -301,7 +301,12 @@ struct msg_headers *read_message_headers(int msgconf, int msgarea, struct user_r if (jamm->subject == NULL) { jamm->subject = strdup("(No Subject)"); } - + if (jamm->from == NULL) { + jamm->from = strdup("(No Sender)"); + } + if (jamm->to == NULL) { + jamm->to = strdup("(No Recipient)"); + } if (jmh.Attribute & JAM_MSG_PRIVATE) { if (!msg_is_to(user, jamm->to, jamm->daddress, conf.mail_conferences[msgconf]->nettype, conf.mail_conferences[msgconf]->realnames, msgconf) && !msg_is_from(user, jamm->from, jamm->oaddress, conf.mail_conferences[msgconf]->nettype, conf.mail_conferences[msgconf]->realnames, msgconf) && diff --git a/src/www_msgs.c b/src/www_msgs.c index 93dfac6..349c150 100644 --- a/src/www_msgs.c +++ b/src/www_msgs.c @@ -402,6 +402,14 @@ char *www_msgs_messageview(struct user_record *user, int conference, int area, i if (subject == NULL) { subject = strdup("(No Subject)"); } + + if (from == NULL) { + from = strdup("(No Sender)"); + } + + if (to == NULL) { + to = strdup("(No Recipient)"); + } if (jmh.Attribute & JAM_MSG_PRIVATE) { if (!msg_is_to(user, to, daddress, conf.mail_conferences[conference]->nettype, conf.mail_conferences[conference]->realnames, conference) && @@ -485,7 +493,7 @@ char *www_msgs_messageview(struct user_record *user, int conference, int area, i len += strlen(buffer); from_s = www_sanitize(from); - if (conf.mail_conferences[conference]->mail_areas[area]->type != TYPE_LOCAL_AREA) { + if (conf.mail_conferences[conference]->mail_areas[area]->type != TYPE_LOCAL_AREA && oaddress != NULL) { sprintf(buffer, "
From: %s (%s)
\n", from_s, oaddress); } else { sprintf(buffer, "
From: %s
\n", from_s); From 4e4fc0378479c9977ded485a3c292a7ee36679ad Mon Sep 17 00:00:00 2001 From: Andrew Pamment Date: Mon, 22 Jan 2018 19:21:57 +1000 Subject: [PATCH 05/87] Fix a few minor bugs --- src/www_msgs.c | 1 + utils/magiedit/main.c | 1 + utils/ticproc/ticproc.c | 1 + 3 files changed, 3 insertions(+) diff --git a/src/www_msgs.c b/src/www_msgs.c index 349c150..28de7bf 100644 --- a/src/www_msgs.c +++ b/src/www_msgs.c @@ -923,6 +923,7 @@ int www_send_msg(struct user_record *user, char *to, char *subj, int conference, return 1; } + return 0; } char *www_new_msg(struct user_record *user, int conference, int area) { diff --git a/utils/magiedit/main.c b/utils/magiedit/main.c index 569df27..1476315 100644 --- a/utils/magiedit/main.c +++ b/utils/magiedit/main.c @@ -767,6 +767,7 @@ char *message_editor() { } } } + return NULL; } #if _MSC_VER diff --git a/utils/ticproc/ticproc.c b/utils/ticproc/ticproc.c index d249935..c7b402d 100644 --- a/utils/ticproc/ticproc.c +++ b/utils/ticproc/ticproc.c @@ -88,6 +88,7 @@ static int handler(void* user, const char* section, const char* name, conf.filearea_count++; return 1; } + return 1; } void chomp(char *string) { From 1ebf8780b47585b6b663154a10cc853039af547e Mon Sep 17 00:00:00 2001 From: Andrew Pamment Date: Mon, 22 Jan 2018 19:59:31 +1000 Subject: [PATCH 06/87] fixes for file downloading --- src/files.c | 49 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/src/files.c b/src/files.c index 936498e..02a4a8d 100644 --- a/src/files.c +++ b/src/files.c @@ -36,7 +36,13 @@ struct file_entry { time_t uploaddate; }; -char **tagged_files; +struct tagged_file { + char *filename; + int dir; + int sub; +}; + +struct tagged_file **tagged_files; int tagged_count = 0; int ttySetRaw(int fd, struct termios *prevTermios) { @@ -803,9 +809,9 @@ void download(struct user_record *user) { for (i=0;ifilename); - sprintf(buffer, "%s/%s.sq3", conf.bbs_path, conf.file_directories[user->cur_file_dir]->file_subs[user->cur_file_sub]->database); + sprintf(buffer, "%s/%s.sq3", conf.bbs_path, conf.file_directories[tagged_files[i]->dir]->file_subs[tagged_files[i]->sub]->database); rc = sqlite3_open(buffer, &db); @@ -818,7 +824,7 @@ void download(struct user_record *user) { rc = sqlite3_prepare_v2(db, ssql, -1, &res, 0); if (rc == SQLITE_OK) { - sqlite3_bind_text(res, 1, tagged_files[i], -1, 0); + sqlite3_bind_text(res, 1, tagged_files[i]->filename, -1, 0); } else { dolog("Failed to execute statement: %s", sqlite3_errmsg(db)); } @@ -854,6 +860,7 @@ void download(struct user_record *user) { for (i=0;ifilename); free(tagged_files[i]); } free(tagged_files); @@ -920,18 +927,21 @@ void do_list_files(struct file_entry **files_e, int files_c) { if (conf.file_directories[files_e[z]->dir]->file_subs[files_e[z]->sub]->download_sec_level <= gUser->sec_level) { match = 0; for (k=0;kfilename) == 0) { + if (strcmp(tagged_files[k]->filename, files_e[z]->filename) == 0) { match = 1; break; } } if (match == 0) { if (tagged_count == 0) { - tagged_files = (char **)malloc(sizeof(char *)); + tagged_files = (struct tagged_file **)malloc(sizeof(struct tagged_file *)); } else { - tagged_files = (char **)realloc(tagged_files, sizeof(char *) * (tagged_count + 1)); + tagged_files = (struct tagged_file **)realloc(tagged_files, sizeof(struct tagged_file *) * (tagged_count + 1)); } - tagged_files[tagged_count] = strdup(files_e[z]->filename); + tagged_files[tagged_count] = (struct tagged_file *)malloc(sizeof(struct tagged_file)); + tagged_files[tagged_count]->filename = strdup(files_e[z]->filename); + tagged_files[tagged_count]->dir = files_e[z]->dir; + tagged_files[tagged_count]->sub = files_e[z]->sub; tagged_count++; s_printf(get_string(71), basename(files_e[z]->filename)); } else { @@ -974,18 +984,21 @@ void do_list_files(struct file_entry **files_e, int files_c) { if (conf.file_directories[files_e[z]->dir]->file_subs[files_e[z]->sub]->download_sec_level <= gUser->sec_level) { match = 0; for (k=0;kfilename) == 0) { + if (strcmp(tagged_files[k]->filename, files_e[z]->filename) == 0) { match = 1; break; } } if (match == 0) { if (tagged_count == 0) { - tagged_files = (char **)malloc(sizeof(char *)); + tagged_files = (struct tagged_file **)malloc(sizeof(struct tagged_file *)); } else { - tagged_files = (char **)realloc(tagged_files, sizeof(char *) * (tagged_count + 1)); + tagged_files = (struct tagged_file **)realloc(tagged_files, sizeof(struct tagged_file *) * (tagged_count + 1)); } - tagged_files[tagged_count] = strdup(files_e[z]->filename); + tagged_files[tagged_count] = (struct tagged_file *)malloc(sizeof(struct tagged_file)); + tagged_files[tagged_count]->filename = strdup(files_e[z]->filename); + tagged_files[tagged_count]->dir = files_e[z]->dir; + tagged_files[tagged_count]->sub = files_e[z]->sub; tagged_count++; s_printf(get_string(71), basename(files_e[z]->filename)); } else { @@ -1017,18 +1030,21 @@ void do_list_files(struct file_entry **files_e, int files_c) { if (conf.file_directories[files_e[z]->dir]->file_subs[files_e[z]->sub]->download_sec_level <= gUser->sec_level) { match = 0; for (k=0;kfilename) == 0) { + if (strcmp(tagged_files[k]->filename, files_e[z]->filename) == 0) { match = 1; break; } } if (match == 0) { if (tagged_count == 0) { - tagged_files = (char **)malloc(sizeof(char *)); + tagged_files = (struct tagged_file **)malloc(sizeof(struct tagged_file *)); } else { - tagged_files = (char **)realloc(tagged_files, sizeof(char *) * (tagged_count + 1)); + tagged_files = (struct tagged_file **)realloc(tagged_files, sizeof(struct tagged_file *) * (tagged_count + 1)); } - tagged_files[tagged_count] = strdup(files_e[z]->filename); + tagged_files[tagged_count] = (struct tagged_file *)malloc(sizeof(struct tagged_file)); + tagged_files[tagged_count]->filename = strdup(files_e[z]->filename); + tagged_files[tagged_count]->dir = files_e[z]->dir; + tagged_files[tagged_count]->sub = files_e[z]->sub; tagged_count++; s_printf(get_string(71), basename(files_e[z]->filename)); } else { @@ -1623,6 +1639,7 @@ void clear_tagged_files() { // Clear tagged files if (tagged_count > 0) { for (i=0;ifilename); free(tagged_files[i]); } free(tagged_files); From 9ee460ca51c2492724f3ecbec991003585f0ba45 Mon Sep 17 00:00:00 2001 From: Andrew Pamment Date: Mon, 22 Jan 2018 20:12:41 +1000 Subject: [PATCH 07/87] fix files again... --- src/files.c | 54 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/src/files.c b/src/files.c index 02a4a8d..7a6bd20 100644 --- a/src/files.c +++ b/src/files.c @@ -27,6 +27,7 @@ extern time_t userlaston; extern struct user_record *gUser; struct file_entry { + int fid; int dir; int sub; char *filename; @@ -40,6 +41,7 @@ struct tagged_file { char *filename; int dir; int sub; + int fid; }; struct tagged_file **tagged_files; @@ -846,7 +848,7 @@ void download(struct user_record *user) { if (rc == SQLITE_OK) { sqlite3_bind_int(res, 1, dloads); - sqlite3_bind_text(res, 2, tagged_files[i], -1, 0); + sqlite3_bind_text(res, 2, tagged_files[i]->filename, -1, 0); } else { dolog("Failed to execute statement: %s", sqlite3_errmsg(db)); } @@ -942,6 +944,7 @@ void do_list_files(struct file_entry **files_e, int files_c) { tagged_files[tagged_count]->filename = strdup(files_e[z]->filename); tagged_files[tagged_count]->dir = files_e[z]->dir; tagged_files[tagged_count]->sub = files_e[z]->sub; + tagged_files[tagged_count]->fid = files_e[z]->fid; tagged_count++; s_printf(get_string(71), basename(files_e[z]->filename)); } else { @@ -999,6 +1002,7 @@ void do_list_files(struct file_entry **files_e, int files_c) { tagged_files[tagged_count]->filename = strdup(files_e[z]->filename); tagged_files[tagged_count]->dir = files_e[z]->dir; tagged_files[tagged_count]->sub = files_e[z]->sub; + tagged_files[tagged_count]->fid = files_e[z]->fid; tagged_count++; s_printf(get_string(71), basename(files_e[z]->filename)); } else { @@ -1045,6 +1049,7 @@ void do_list_files(struct file_entry **files_e, int files_c) { tagged_files[tagged_count]->filename = strdup(files_e[z]->filename); tagged_files[tagged_count]->dir = files_e[z]->dir; tagged_files[tagged_count]->sub = files_e[z]->sub; + tagged_files[tagged_count]->fid = files_e[z]->fid; tagged_count++; s_printf(get_string(71), basename(files_e[z]->filename)); } else { @@ -1118,21 +1123,21 @@ void file_search() { ptr = strtok(NULL, " "); } if (stype == 0) { - snprintf(sqlbuffer, 1024, "select filename, description, size, dlcount, uploaddate from files where approved=1 AND (filename LIKE ?"); + snprintf(sqlbuffer, 1024, "select id, filename, description, size, dlcount, uploaddate from files where approved=1 AND (filename LIKE ?"); for (i=1; i < searchterm_count; i++) { strncat(sqlbuffer, " OR filename LIKE ?", 1024); } strncat(sqlbuffer, ")", 1024); } if (stype == 1) { - snprintf(sqlbuffer, 1024, "select filename, description, size, dlcount, uploaddate from files where approved=1 AND (description LIKE ?"); + snprintf(sqlbuffer, 1024, "select id, filename, description, size, dlcount, uploaddate from files where approved=1 AND (description LIKE ?"); for (i=1; i < searchterm_count; i++) { strncat(sqlbuffer, " OR description LIKE ?", 1024); } strncat(sqlbuffer, ")", 1024); } if (stype == 2) { - snprintf(sqlbuffer, 1024, "select filename, description, size, dlcount, uploaddate from files where approved=1 AND (filename LIKE ?"); + snprintf(sqlbuffer, 1024, "select id, filename, description, size, dlcount, uploaddate from files where approved=1 AND (filename LIKE ?"); for (i=1; i < searchterm_count; i++) { strncat(sqlbuffer, " OR filename LIKE ?", 1024); } @@ -1187,11 +1192,12 @@ void file_search() { files_e = (struct file_entry **)realloc(files_e, sizeof(struct file_entry *) * (files_c + 1)); } files_e[files_c] = (struct file_entry *)malloc(sizeof(struct file_entry)); - files_e[files_c]->filename = strdup((char *)sqlite3_column_text(res, 0)); - files_e[files_c]->description = strdup((char *)sqlite3_column_text(res, 1)); - files_e[files_c]->size = sqlite3_column_int(res, 2); - files_e[files_c]->dlcount = sqlite3_column_int(res, 3); - files_e[files_c]->uploaddate = sqlite3_column_int(res, 4); + files_e[files_c]->fid = sqlite3_column_int(res, 0); + files_e[files_c]->filename = strdup((char *)sqlite3_column_text(res, 1)); + files_e[files_c]->description = strdup((char *)sqlite3_column_text(res, 2)); + files_e[files_c]->size = sqlite3_column_int(res, 3); + files_e[files_c]->dlcount = sqlite3_column_int(res, 4); + files_e[files_c]->uploaddate = sqlite3_column_int(res, 5); files_e[files_c]->dir = gUser->cur_file_dir; files_e[files_c]->sub = gUser->cur_file_sub; files_c++; @@ -1248,11 +1254,12 @@ void file_search() { files_e = (struct file_entry **)realloc(files_e, sizeof(struct file_entry *) * (files_c + 1)); } files_e[files_c] = (struct file_entry *)malloc(sizeof(struct file_entry)); - files_e[files_c]->filename = strdup((char *)sqlite3_column_text(res, 0)); - files_e[files_c]->description = strdup((char *)sqlite3_column_text(res, 1)); - files_e[files_c]->size = sqlite3_column_int(res, 2); - files_e[files_c]->dlcount = sqlite3_column_int(res, 3); - files_e[files_c]->uploaddate = sqlite3_column_int(res, 4); + files_e[files_c]->fid = sqlite3_column_int(res, 0); + files_e[files_c]->filename = strdup((char *)sqlite3_column_text(res, 1)); + files_e[files_c]->description = strdup((char *)sqlite3_column_text(res, 2)); + files_e[files_c]->size = sqlite3_column_int(res, 3); + files_e[files_c]->dlcount = sqlite3_column_int(res, 4); + files_e[files_c]->uploaddate = sqlite3_column_int(res, 5); files_e[files_c]->dir = gUser->cur_file_dir; files_e[files_c]->sub = gUser->cur_file_sub; files_c++; @@ -1273,10 +1280,10 @@ void file_search() { } void list_files(struct user_record *user) { - char *dsql = "select filename, description, size, dlcount, uploaddate from files where approved=1 ORDER BY uploaddate DESC"; - char *fsql = "select filename, description, size, dlcount, uploaddate from files where approved=1 ORDER BY filename"; - char *psql = "select filename, description, size, dlcount, uploaddate from files where approved=1 ORDER BY dlcount DESC"; - char *nsql = "select filename, description, size, dlcount, uploaddate from files where approved=1 ORDER BY uploaddate DESC WHERE uploaddate > ?"; + char *dsql = "select id, filename, description, size, dlcount, uploaddate from files where approved=1 ORDER BY uploaddate DESC"; + char *fsql = "select id, filename, description, size, dlcount, uploaddate from files where approved=1 ORDER BY filename"; + char *psql = "select id, filename, description, size, dlcount, uploaddate from files where approved=1 ORDER BY dlcount DESC"; + char *nsql = "select id, filename, description, size, dlcount, uploaddate from files where approved=1 ORDER BY uploaddate DESC WHERE uploaddate > ?"; char *sql; char buffer[PATH_MAX]; sqlite3 *db; @@ -1337,11 +1344,12 @@ void list_files(struct user_record *user) { files_e = (struct file_entry **)realloc(files_e, sizeof(struct file_entry *) * (files_c + 1)); } files_e[files_c] = (struct file_entry *)malloc(sizeof(struct file_entry)); - files_e[files_c]->filename = strdup((char *)sqlite3_column_text(res, 0)); - files_e[files_c]->description = strdup((char *)sqlite3_column_text(res, 1)); - files_e[files_c]->size = sqlite3_column_int(res, 2); - files_e[files_c]->dlcount = sqlite3_column_int(res, 3); - files_e[files_c]->uploaddate = sqlite3_column_int(res, 4); + files_e[files_c]->fid = sqlite3_column_int(res, 0); + files_e[files_c]->filename = strdup((char *)sqlite3_column_text(res, 1)); + files_e[files_c]->description = strdup((char *)sqlite3_column_text(res, 2)); + files_e[files_c]->size = sqlite3_column_int(res, 3); + files_e[files_c]->dlcount = sqlite3_column_int(res, 4); + files_e[files_c]->uploaddate = sqlite3_column_int(res, 5); files_e[files_c]->dir = user->cur_file_dir; files_e[files_c]->sub = user->cur_file_sub; files_c++; From 84a3d271df3760cadaa2acb07b7d66397a251ec5 Mon Sep 17 00:00:00 2001 From: Andrew Pamment Date: Tue, 23 Jan 2018 20:57:58 +1000 Subject: [PATCH 08/87] first attempt at www downlods WIP --- STRINGS.CHANGES | 28 ++ deps/hashids/hashids.c | 831 +++++++++++++++++++++++++++++++++++++++ deps/hashids/hashids.h | 122 ++++++ dist/magicka.strings | 5 + dist/menus/file.mnu | 3 + src/Makefile.freebsd.WWW | 2 +- src/Makefile.linux.WWW | 2 +- src/Makefile.netbsd.WWW | 2 +- src/Makefile.openbsd.WWW | 2 +- src/Makefile.osx.WWW | 2 +- src/Makefile.sunos.WWW | 2 +- src/bbs.c | 3 + src/bbs.h | 3 + src/files.c | 45 ++- src/menus.c | 8 +- src/users.c | 2 +- src/www.c | 31 ++ src/www_files.c | 237 +++++++++++ 18 files changed, 1318 insertions(+), 12 deletions(-) create mode 100644 STRINGS.CHANGES create mode 100644 deps/hashids/hashids.c create mode 100644 deps/hashids/hashids.h create mode 100644 src/www_files.c diff --git a/STRINGS.CHANGES b/STRINGS.CHANGES new file mode 100644 index 0000000..ef53413 --- /dev/null +++ b/STRINGS.CHANGES @@ -0,0 +1,28 @@ +New / Changed Strings in dist/magicka.strings +-------------------------------------------------------------- +If you are using your own custom strings file, you will need +to add / modify the new string on the line specified. Be sure +to remove the start and end quotation marks. + + +Changes from v0.8-alpha -> v0.9-alpha +-------------------------------------------------------------- +LINE: 255 NEW +OLDSTRING: (NONE) +NEWSTRING: "\r\n\e[1;37mSending file %s...\r\n" + +LINE 256 NEW +OLDSTRING: (NONE) +NEWSTRING: "\r\n\e[1;34mFilename\e[1;30m: \e[1;37m%s\e[0m\r\n" + +LINE 257 NEW +OLDSTRING: (NONE) +NEWSTRING: " \e[1;34mURL\e[1;30m: \e[1;37m%s\e[0m\r\n" + +LINE 258 NEW +OLDSTRING: (NONE) +NEWSTRING: "\r\n\e[1;31mError creating URL!\e[0m\r\n" + +LINE 259 NEW +OLDSTRING: (NONE) +NEWSTRING: "\e[1;33mSorry this BBS does not have the webserver enabled.\e[0m\r\n" \ No newline at end of file diff --git a/deps/hashids/hashids.c b/deps/hashids/hashids.c new file mode 100644 index 0000000..dfbab26 --- /dev/null +++ b/deps/hashids/hashids.c @@ -0,0 +1,831 @@ +#include +#include +#include +#include +#include + +#include "hashids.h" + +/* branch prediction hinting */ +#ifndef __has_builtin +# define __has_builtin(x) (0) +#endif +#if defined(__builtin_expect) || __has_builtin(__builtin_expect) +# define HASHIDS_LIKELY(x) (__builtin_expect(!!(x), 1)) +# define HASHIDS_UNLIKELY(x) (__builtin_expect(!!(x), 0)) +#else +# define HASHIDS_LIKELY(x) (x) +# define HASHIDS_UNLIKELY(x) (x) +#endif + +/* thread-local storage */ +#ifndef TLS +#define TLS +#endif + +/* thread-safe hashids_errno indirection */ +TLS int __hashids_errno_val; +int * +__hashids_errno_addr() +{ + return &__hashids_errno_val; +} + +/* default alloc() implementation */ +static inline void * +hashids_alloc_f(size_t size) +{ + return calloc(size, 1); +} + +/* default free() implementation */ +static inline void +hashids_free_f(void *ptr) +{ + free(ptr); +} + +void *(*_hashids_alloc)(size_t size) = hashids_alloc_f; +void (*_hashids_free)(void *ptr) = hashids_free_f; + +/* fast ceil(x / y) for size_t arguments */ +static inline size_t +hashids_div_ceil_size_t(size_t x, size_t y) +{ + return x / y + !!(x % y); +} + +/* fast ceil(x / y) for unsigned short arguments */ +static inline unsigned short +hashids_div_ceil_unsigned_short(unsigned short x, unsigned short y) { + return x / y + !!(x % y); +} + +/* fast log2(x) for unsigned long long */ +const unsigned short hashids_log2_64_tab[64] = { + 63, 0, 58, 1, 59, 47, 53, 2, + 60, 39, 48, 27, 54, 33, 42, 3, + 61, 51, 37, 40, 49, 18, 28, 20, + 55, 30, 34, 11, 43, 14, 22, 4, + 62, 57, 46, 52, 38, 26, 32, 41, + 50, 36, 17, 19, 29, 10, 13, 21, + 56, 45, 25, 31, 35, 16, 9, 12, + 44, 24, 15, 8, 23, 7, 6, 5 +}; + +static inline unsigned short +hashids_log2_64(unsigned long long x) +{ + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + x |= x >> 32; + + /* pure evil : ieee abuse */ + return hashids_log2_64_tab[ + ((unsigned long long)((x - (x >> 1)) * 0x07EDD5E59A4E28C2)) >> 58]; +} + +/* shuffle loop step */ +#define hashids_shuffle_step(iter) \ + if (i == 0) { break; } \ + if (v == salt_length) { v = 0; } \ + p += salt[v]; j = (salt[v] + v + p) % (iter); \ + temp = str[(iter)]; str[(iter)] = str[j]; str[j] = temp; \ + --i; ++v; + +/* consistent shuffle */ +void +hashids_shuffle(char *str, size_t str_length, char *salt, size_t salt_length) +{ + ssize_t i; + size_t j, v, p; + char temp; + + /* meh, meh */ + if (!salt_length) { + return; + } + + /* pure evil : loop unroll */ + for (i = str_length - 1, v = 0, p = 0; i > 0; /* empty */) { + switch (i % 32) { + case 31: hashids_shuffle_step(i); + case 30: hashids_shuffle_step(i); + case 29: hashids_shuffle_step(i); + case 28: hashids_shuffle_step(i); + case 27: hashids_shuffle_step(i); + case 26: hashids_shuffle_step(i); + case 25: hashids_shuffle_step(i); + case 24: hashids_shuffle_step(i); + case 23: hashids_shuffle_step(i); + case 22: hashids_shuffle_step(i); + case 21: hashids_shuffle_step(i); + case 20: hashids_shuffle_step(i); + case 19: hashids_shuffle_step(i); + case 18: hashids_shuffle_step(i); + case 17: hashids_shuffle_step(i); + case 16: hashids_shuffle_step(i); + case 15: hashids_shuffle_step(i); + case 14: hashids_shuffle_step(i); + case 13: hashids_shuffle_step(i); + case 12: hashids_shuffle_step(i); + case 11: hashids_shuffle_step(i); + case 10: hashids_shuffle_step(i); + case 9: hashids_shuffle_step(i); + case 8: hashids_shuffle_step(i); + case 7: hashids_shuffle_step(i); + case 6: hashids_shuffle_step(i); + case 5: hashids_shuffle_step(i); + case 4: hashids_shuffle_step(i); + case 3: hashids_shuffle_step(i); + case 2: hashids_shuffle_step(i); + case 1: hashids_shuffle_step(i); + case 0: hashids_shuffle_step(i); + } + } +} + +/* "destructor" */ +void +hashids_free(hashids_t *hashids) +{ + if (hashids) { + if (hashids->alphabet) { + _hashids_free(hashids->alphabet); + } + if (hashids->alphabet_copy_1) { + _hashids_free(hashids->alphabet_copy_1); + } + if (hashids->alphabet_copy_2) { + _hashids_free(hashids->alphabet_copy_2); + } + if (hashids->salt) { + _hashids_free(hashids->salt); + } + if (hashids->separators) { + _hashids_free(hashids->separators); + } + if (hashids->guards) { + _hashids_free(hashids->guards); + } + + _hashids_free(hashids); + } +} + +/* common init */ +hashids_t * +hashids_init3(const char *salt, size_t min_hash_length, const char *alphabet) +{ + hashids_t *result; + size_t i, j, len; + char ch, *p; + + hashids_errno = HASHIDS_ERROR_OK; + + /* allocate the structure */ + result = _hashids_alloc(sizeof(hashids_t)); + if (HASHIDS_UNLIKELY(!result)) { + hashids_errno = HASHIDS_ERROR_ALLOC; + return NULL; + } + + /* allocate enough space for the alphabet */ + len = strlen(alphabet) + 1; + result->alphabet = _hashids_alloc(len); + + /* extract only the unique characters */ + result->alphabet[0] = '\0'; + for (i = 0, j = 0; i < len; ++i) { + ch = alphabet[i]; + if (!strchr(result->alphabet, ch)) { + result->alphabet[j++] = ch; + } + } + result->alphabet[j] = '\0'; + + /* store alphabet length */ + result->alphabet_length = j; + + /* check length and whitespace */ + if (result->alphabet_length < HASHIDS_MIN_ALPHABET_LENGTH) { + hashids_free(result); + hashids_errno = HASHIDS_ERROR_ALPHABET_LENGTH; + return NULL; + } + if (strchr(result->alphabet, 0x20) || strchr(result->alphabet, 0x09)) { + hashids_free(result); + hashids_errno = HASHIDS_ERROR_ALPHABET_SPACE; + return NULL; + } + + /* copy salt */ + result->salt_length = salt ? strlen(salt) : 0; + result->salt = _hashids_alloc(result->salt_length + 1); + if (HASHIDS_UNLIKELY(!result->salt)) { + hashids_free(result); + hashids_errno = HASHIDS_ERROR_ALLOC; + return NULL; + } + strncpy(result->salt, salt, result->salt_length); + + /* allocate enough space for separators */ + len = strlen(HASHIDS_DEFAULT_SEPARATORS); + j = (size_t) + (ceil((float)result->alphabet_length / HASHIDS_SEPARATOR_DIVISOR) + 1); + if (j < len + 1) { + j = len + 1; + } + + result->separators = _hashids_alloc(j); + if (HASHIDS_UNLIKELY(!result->separators)) { + hashids_free(result); + hashids_errno = HASHIDS_ERROR_ALLOC; + return NULL; + } + + /* take default separators out of the alphabet */ + for (i = 0, j = 0; i < strlen(HASHIDS_DEFAULT_SEPARATORS); ++i) { + ch = HASHIDS_DEFAULT_SEPARATORS[i]; + + /* check if separator is actually in the used alphabet */ + if ((p = strchr(result->alphabet, ch))) { + result->separators[j++] = ch; + + /* remove that separator */ + memmove(p, p + 1, + strlen(result->alphabet) - (p - result->alphabet)); + } + } + + /* store separators length */ + result->separators_count = j; + + /* subtract separators count from alphabet length */ + result->alphabet_length -= result->separators_count; + + /* shuffle the separators */ + if (result->separators_count) { + hashids_shuffle(result->separators, result->separators_count, + result->salt, result->salt_length); + } + + /* check if we have any/enough separators */ + if (!result->separators_count + || (((float)result->alphabet_length / (float)result->separators_count) + > HASHIDS_SEPARATOR_DIVISOR)) { + size_t separators_count = (size_t)ceil( + (float)result->alphabet_length / HASHIDS_SEPARATOR_DIVISOR); + + if (separators_count == 1) { + separators_count = 2; + } + + if (separators_count > result->separators_count) { + /* we need more separators - get some from alphabet */ + size_t diff = separators_count - result->separators_count; + strncat(result->separators, result->alphabet, diff); + memmove(result->alphabet, result->alphabet + diff, + result->alphabet_length - diff + 1); + + result->separators_count += diff; + result->alphabet_length -= diff; + } else { + /* we have more than enough - truncate */ + result->separators[separators_count] = '\0'; + result->separators_count = separators_count; + } + } + + /* shuffle alphabet */ + hashids_shuffle(result->alphabet, result->alphabet_length, + result->salt, result->salt_length); + + /* allocate guards */ + result->guards_count = hashids_div_ceil_size_t(result->alphabet_length, + HASHIDS_GUARD_DIVISOR); + result->guards = _hashids_alloc(result->guards_count + 1); + if (HASHIDS_UNLIKELY(!result->guards)) { + hashids_free(result); + hashids_errno = HASHIDS_ERROR_ALLOC; + return NULL; + } + + if (HASHIDS_UNLIKELY(result->alphabet_length < 3)) { + /* take some from separators */ + strncpy(result->guards, result->separators, result->guards_count); + memmove(result->separators, result->separators + result->guards_count, + result->separators_count - result->guards_count + 1); + + result->separators_count -= result->guards_count; + } else { + /* take them from alphabet */ + strncpy(result->guards, result->alphabet, result->guards_count); + memmove(result->alphabet, result->alphabet + result->guards_count, + result->alphabet_length - result->guards_count + 1); + + result->alphabet_length -= result->guards_count; + } + + /* allocate enough space for the alphabet copies */ + result->alphabet_copy_1 = _hashids_alloc(result->alphabet_length + 1); + result->alphabet_copy_2 = _hashids_alloc(result->alphabet_length + 1); + if (HASHIDS_UNLIKELY(!result->alphabet || !result->alphabet_copy_1 + || !result->alphabet_copy_2)) { + hashids_free(result); + hashids_errno = HASHIDS_ERROR_ALLOC; + return NULL; + } + + /* set min hash length */ + result->min_hash_length = min_hash_length; + + /* return result happily */ + return result; +} + +/* init with salt and minimum hash length */ +hashids_t * +hashids_init2(const char *salt, size_t min_hash_length) +{ + return hashids_init3(salt, min_hash_length, HASHIDS_DEFAULT_ALPHABET); +} + +/* init with hash only */ +hashids_t * +hashids_init(const char *salt) +{ + return hashids_init2(salt, HASHIDS_DEFAULT_MIN_HASH_LENGTH); +} + +/* estimate buffer size (generic) */ +size_t +hashids_estimate_encoded_size(hashids_t *hashids, + size_t numbers_count, unsigned long long *numbers) +{ + int i, result_len; + + for (i = 0, result_len = 1; i < numbers_count; ++i) { + if (numbers[i] == 0) { + result_len += 2; + } else if (numbers[i] == 0xFFFFFFFFFFFFFFFFull) { + result_len += hashids_div_ceil_unsigned_short( + hashids_log2_64(numbers[i]), + hashids_log2_64(hashids->alphabet_length)) - 1; + } else { + result_len += hashids_div_ceil_unsigned_short( + hashids_log2_64(numbers[i] + 1), + hashids_log2_64(hashids->alphabet_length)); + } + } + + if (numbers_count > 1) { + result_len += numbers_count - 1; + } + + if (result_len < hashids->min_hash_length) { + result_len = hashids->min_hash_length; + } + + return result_len + 2 /* fast log2 & ceil sometimes undershoot by 1 */; +} + +/* estimate buffer size (variadic) */ +size_t +hashids_estimate_encoded_size_v(hashids_t *hashids, + size_t numbers_count, ...) +{ + size_t i, result; + unsigned long long *numbers; + va_list ap; + + numbers = _hashids_alloc(numbers_count * sizeof(unsigned long long)); + + if (HASHIDS_UNLIKELY(!numbers)) { + hashids_errno = HASHIDS_ERROR_ALLOC; + return 0; + } + + va_start(ap, numbers_count); + for (i = 0; i < numbers_count; ++i) { + numbers[i] = va_arg(ap, unsigned long long); + } + va_end(ap); + + result = hashids_estimate_encoded_size(hashids, numbers_count, numbers); + _hashids_free(numbers); + + return result; +} + +/* encode many (generic) */ +size_t +hashids_encode(hashids_t *hashids, char *buffer, + size_t numbers_count, unsigned long long *numbers) +{ + /* bail out if no numbers */ + if (HASHIDS_UNLIKELY(!numbers_count)) { + buffer[0] = '\0'; + + return 0; + } + + size_t i, j, result_len, guard_index, half_length_ceil, half_length_floor; + unsigned long long number, number_copy, numbers_hash; + int p_max; + char lottery, ch, temp_ch, *p, *buffer_end, *buffer_temp; + + /* return an estimation if no buffer */ + if (HASHIDS_UNLIKELY(!buffer)) { + return hashids_estimate_encoded_size(hashids, numbers_count, numbers); + } + + /* copy the alphabet into internal buffer 1 */ + strncpy(hashids->alphabet_copy_1, hashids->alphabet, + hashids->alphabet_length); + + /* walk arguments once and generate a hash */ + for (i = 0, numbers_hash = 0; i < numbers_count; ++i) { + number = numbers[i]; + numbers_hash += number % (i + 100); + } + + /* lottery character */ + lottery = hashids->alphabet[numbers_hash % hashids->alphabet_length]; + + /* start output buffer with it (or don't) */ + buffer[0] = lottery; + buffer_end = buffer + 1; + + /* alphabet-like buffer used for salt at each iteration */ + hashids->alphabet_copy_2[0] = lottery; + hashids->alphabet_copy_2[1] = '\0'; + strncat(hashids->alphabet_copy_2, hashids->salt, + hashids->alphabet_length - 1); + p = hashids->alphabet_copy_2 + hashids->salt_length + 1; + p_max = hashids->alphabet_length - 1 - hashids->salt_length; + if (p_max > 0) { + strncat(hashids->alphabet_copy_2, hashids->alphabet, + p_max); + } else { + hashids->alphabet_copy_2[hashids->alphabet_length] = '\0'; + } + + for (i = 0; i < numbers_count; ++i) { + /* take number */ + number = number_copy = numbers[i]; + + /* create a salt for this iteration */ + if (p_max > 0) { + strncpy(p, hashids->alphabet_copy_1, p_max); + } + + /* shuffle the alphabet */ + hashids_shuffle(hashids->alphabet_copy_1, hashids->alphabet_length, + hashids->alphabet_copy_2, hashids->alphabet_length); + + /* hash the number */ + buffer_temp = buffer_end; + do { + ch = hashids->alphabet_copy_1[number % hashids->alphabet_length]; + *buffer_end++ = ch; + number /= hashids->alphabet_length; + } while (number); + + /* reverse the hash we got */ + for (j = 0; j < (buffer_end - buffer_temp) / 2; ++j) { + temp_ch = *(buffer_temp + j); + *(buffer_temp + j) = *(buffer_end - 1 - j); + *(buffer_end - 1 - j) = temp_ch; + } + + if (i + 1 < numbers_count) { + number_copy %= ch + i; + *buffer_end = hashids->separators[number_copy % + hashids->separators_count]; + ++buffer_end; + } + } + + /* intermediate string length */ + result_len = buffer_end - buffer; + + if (result_len < hashids->min_hash_length) { + /* add a guard before the encoded numbers */ + guard_index = (numbers_hash + buffer[0]) % hashids->guards_count; + memmove(buffer + 1, buffer, result_len); + buffer[0] = hashids->guards[guard_index]; + ++result_len; + + if (result_len < hashids->min_hash_length) { + /* add a guard after the encoded numbers */ + guard_index = (numbers_hash + buffer[2]) % hashids->guards_count; + buffer[result_len] = hashids->guards[guard_index]; + ++result_len; + + /* pad with half alphabet before and after */ + half_length_ceil = hashids_div_ceil_size_t( + hashids->alphabet_length, 2); + half_length_floor = floor((float)hashids->alphabet_length / 2); + + /* pad, pad, pad */ + while (result_len < hashids->min_hash_length) { + /* shuffle the alphabet */ + strncpy(hashids->alphabet_copy_2, hashids->alphabet_copy_1, + hashids->alphabet_length); + hashids_shuffle(hashids->alphabet_copy_1, + hashids->alphabet_length, hashids->alphabet_copy_2, + hashids->alphabet_length); + + /* left pad from the end of the alphabet */ + i = hashids_div_ceil_size_t( + hashids->min_hash_length - result_len, 2); + /* right pad from the beginning */ + j = floor((float)(hashids->min_hash_length - result_len) / 2); + + /* check bounds */ + if (i > half_length_ceil) { + i = half_length_ceil; + } + if (j > half_length_floor) { + j = half_length_floor; + } + + /* handle excessively excessive excess */ + if ((i + j) % 2 == 0 && hashids->alphabet_length % 2 == 1) { + ++i; --j; + } + + /* move the current result to "center" */ + memmove(buffer + i, buffer, result_len); + /* pad left */ + memmove(buffer, + hashids->alphabet_copy_1 + hashids->alphabet_length - i, i); + /* pad right */ + memmove(buffer + i + result_len, hashids->alphabet_copy_1, j); + + /* increment result_len */ + result_len += i + j; + } + } + } + + buffer[result_len] = '\0'; + return result_len; +} + +/* encode many (variadic) */ +size_t +hashids_encode_v(hashids_t *hashids, char *buffer, + size_t numbers_count, ...) +{ + int i; + size_t result; + unsigned long long *numbers; + va_list ap; + + numbers = _hashids_alloc(numbers_count * sizeof(unsigned long long)); + + if (HASHIDS_UNLIKELY(!numbers)) { + hashids_errno = HASHIDS_ERROR_ALLOC; + return 0; + } + + va_start(ap, numbers_count); + for (i = 0; i < numbers_count; ++i) { + numbers[i] = va_arg(ap, unsigned long long); + } + va_end(ap); + + result = hashids_encode(hashids, buffer, numbers_count, numbers); + _hashids_free(numbers); + + return result; +} + +/* encode one */ +size_t +hashids_encode_one(hashids_t *hashids, char *buffer, + unsigned long long number) +{ + return hashids_encode(hashids, buffer, 1, &number); +} + +/* numbers count */ +size_t +hashids_numbers_count(hashids_t *hashids, char *str) +{ + size_t numbers_count; + char ch, *p; + + /* skip characters until we find a guard */ + if (hashids->min_hash_length) { + p = str; + while ((ch = *p)) { + if (strchr(hashids->guards, ch)) { + str = p + 1; + break; + } + + p++; + } + } + + /* parse */ + numbers_count = 0; + while ((ch = *str)) { + if (strchr(hashids->guards, ch)) { + break; + } + if (strchr(hashids->separators, ch)) { + numbers_count++; + str++; + continue; + } + if (!strchr(hashids->alphabet, ch)) { + hashids_errno = HASHIDS_ERROR_INVALID_HASH; + return 0; + } + + str++; + } + + /* account for the last number */ + return numbers_count + 1; +} + +/* decode */ +size_t +hashids_decode(hashids_t *hashids, char *str, + unsigned long long *numbers) +{ + size_t numbers_count; + unsigned long long number; + char lottery, ch, *p, *c; + int p_max; + + numbers_count = hashids_numbers_count(hashids, str); + + if (!numbers) { + return numbers_count; + } + + /* skip characters until we find a guard */ + if (hashids->min_hash_length) { + p = str; + while ((ch = *p)) { + if (strchr(hashids->guards, ch)) { + str = p + 1; + break; + } + + p++; + } + } + + /* get the lottery character */ + lottery = *str++; + + /* copy the alphabet into internal buffer 1 */ + strncpy(hashids->alphabet_copy_1, hashids->alphabet, + hashids->alphabet_length); + + /* alphabet-like buffer used for salt at each iteration */ + hashids->alphabet_copy_2[0] = lottery; + hashids->alphabet_copy_2[1] = '\0'; + strncat(hashids->alphabet_copy_2, hashids->salt, + hashids->alphabet_length - 1); + p = hashids->alphabet_copy_2 + hashids->salt_length + 1; + p_max = hashids->alphabet_length - 1 - hashids->salt_length; + if (p_max > 0) { + strncat(hashids->alphabet_copy_2, hashids->alphabet, + p_max); + } else { + hashids->alphabet_copy_2[hashids->alphabet_length] = '\0'; + } + + /* first shuffle */ + hashids_shuffle(hashids->alphabet_copy_1, hashids->alphabet_length, + hashids->alphabet_copy_2, hashids->alphabet_length); + + /* parse */ + number = 0; + while ((ch = *str)) { + if (strchr(hashids->guards, ch)) { + break; + } + if (strchr(hashids->separators, ch)) { + *numbers++ = number; + number = 0; + + /* resalt the alphabet */ + if (p_max > 0) { + strncpy(p, hashids->alphabet_copy_1, p_max); + } + hashids_shuffle(hashids->alphabet_copy_1, hashids->alphabet_length, + hashids->alphabet_copy_2, hashids->alphabet_length); + + str++; + continue; + } + if (!(c = strchr(hashids->alphabet_copy_1, ch))) { + hashids_errno = HASHIDS_ERROR_INVALID_HASH; + return 0; + } + + number *= hashids->alphabet_length; + number += c - hashids->alphabet_copy_1; + + str++; + } + + /* store last number */ + *numbers = number; + + return numbers_count; +} + +/* encode hex */ +size_t +hashids_encode_hex(hashids_t *hashids, char *buffer, + const char *hex_str) +{ + int len; + char *temp, *p; + size_t result; + unsigned long long number; + + len = strlen(hex_str); + temp = _hashids_alloc(len + 2); + + if (!temp) { + hashids_errno = HASHIDS_ERROR_ALLOC; + return 0; + } + + temp[0] = '1'; + strncpy(temp + 1, hex_str, len); + + number = strtoull(temp, &p, 16); + + if (p == temp) { + _hashids_free(temp); + hashids_errno = HASHIDS_ERROR_INVALID_NUMBER; + return 0; + } + + result = hashids_encode(hashids, buffer, 1, &number); + _hashids_free(temp); + + return result; +} + +/* decode hex */ +size_t +hashids_decode_hex(hashids_t *hashids, char *str, char *output) +{ + size_t result, i; + unsigned long long number; + char ch, *temp; + + result = hashids_numbers_count(hashids, str); + + if (result != 1) { + return 0; + } + + result = hashids_decode(hashids, str, &number); + + if (result != 1) { + return 0; + } + + temp = output; + + do { + ch = number % 16; + if (ch > 9) { + ch += 'A' - 10; + } else { + ch += '0'; + } + + *temp++ = (char)ch; + + number /= 16; + } while (number); + + temp--; + *temp = 0; + + for (i = 0; i < (temp - output) / 2; ++i) { + ch = *(output + i); + *(output + i) = *(temp - 1 - i); + *(temp - 1 - i) = ch; + } + + return 1; +} diff --git a/deps/hashids/hashids.h b/deps/hashids/hashids.h new file mode 100644 index 0000000..dd9a575 --- /dev/null +++ b/deps/hashids/hashids.h @@ -0,0 +1,122 @@ +#ifndef HASHIDS_H +#define HASHIDS_H 1 + +#include + +/* version constants */ +#define HASHIDS_VERSION "1.1.5" +#define HASHIDS_VERSION_MAJOR 1 +#define HASHIDS_VERSION_MINOR 1 +#define HASHIDS_VERSION_PATCH 5 + +/* minimal alphabet length */ +#define HASHIDS_MIN_ALPHABET_LENGTH 16u + +/* separator divisor */ +#define HASHIDS_SEPARATOR_DIVISOR 3.5f + +/* guard divisor */ +#define HASHIDS_GUARD_DIVISOR 12u + +/* default salt */ +#define HASHIDS_DEFAULT_SALT "" + +/* default minimal hash length */ +#define HASHIDS_DEFAULT_MIN_HASH_LENGTH 0u + +/* default alphabet */ +#define HASHIDS_DEFAULT_ALPHABET "abcdefghijklmnopqrstuvwxyz" \ + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ + "1234567890" + +/* default separators */ +#define HASHIDS_DEFAULT_SEPARATORS "cfhistuCFHISTU" + +/* error codes */ +#define HASHIDS_ERROR_OK 0 +#define HASHIDS_ERROR_ALLOC -1 +#define HASHIDS_ERROR_ALPHABET_LENGTH -2 +#define HASHIDS_ERROR_ALPHABET_SPACE -3 +#define HASHIDS_ERROR_INVALID_HASH -4 +#define HASHIDS_ERROR_INVALID_NUMBER -5 + +/* thread-safe hashids_errno indirection */ +extern int *__hashids_errno_addr(); +#define hashids_errno (*__hashids_errno_addr()) + +/* alloc & free */ +extern void *(*_hashids_alloc)(size_t size); +extern void (*_hashids_free)(void *ptr); + +/* the hashids "object" */ +struct hashids_s { + char *alphabet; + char *alphabet_copy_1; + char *alphabet_copy_2; + size_t alphabet_length; + + char *salt; + size_t salt_length; + + char *separators; + size_t separators_count; + + char *guards; + size_t guards_count; + + size_t min_hash_length; +}; +typedef struct hashids_s hashids_t; + +/* exported function definitions */ +void +hashids_shuffle(char *str, size_t str_length, char *salt, size_t salt_length); + +void +hashids_free(hashids_t *hashids); + +hashids_t * +hashids_init3(const char *salt, size_t min_hash_length, + const char *alphabet); + +hashids_t * +hashids_init2(const char *salt, size_t min_hash_length); + +hashids_t * +hashids_init(const char *salt); + +size_t +hashids_estimate_encoded_size(hashids_t *hashids, + size_t numbers_count, unsigned long long *numbers); + +size_t +hashids_estimate_encoded_size_v(hashids_t *hashids, + size_t numbers_count, ...); + +size_t +hashids_encode(hashids_t *hashids, char *buffer, + size_t numbers_count, unsigned long long *numbers); + +size_t +hashids_encode_v(hashids_t *hashids, char *buffer, + size_t numbers_count, ...); + +size_t +hashids_encode_one(hashids_t *hashids, char *buffer, + unsigned long long number); + +size_t +hashids_numbers_count(hashids_t *hashids, char *str); + +size_t +hashids_decode(hashids_t *hashids, char *str, + unsigned long long *numbers); + +size_t +hashids_encode_hex(hashids_t *hashids, char *buffer, + const char *hex_str); + +size_t +hashids_decode_hex(hashids_t *hashids, char *str, char *output); + +#endif diff --git a/dist/magicka.strings b/dist/magicka.strings index 723d2bf..6415ebb 100644 --- a/dist/magicka.strings +++ b/dist/magicka.strings @@ -252,3 +252,8 @@ File exists!\r\n \e[1;37;44mChoose an Area in %s\e[K \e[1;37;44mChoose an Subdir in %s\e[K \e[1;37;44mChoose a Directory\e[K +\r\n\e[1;37mSending file %s...\r\n +\r\n\e[1;34mFilename\e[1;30m: \e[1;37m%s\e[0m\r\n + \e[1;34mURL\e[1;30m: \e[1;37m%s\e[0m\r\n +\r\n\e[1;31mError creating URL!\e[0m\r\n +\e[1;33mSorry this BBS does not have the webserver enabled.\e[0m\r\n \ No newline at end of file diff --git a/dist/menus/file.mnu b/dist/menus/file.mnu index 12c2c41..ffa9c02 100644 --- a/dist/menus/file.mnu +++ b/dist/menus/file.mnu @@ -16,6 +16,9 @@ COMMAND UPLOAD HOTKEY D COMMAND DOWNLOAD +HOTKEY W +COMMAND GENWWWURLS + HOTKEY C COMMAND CLEARTAGGED diff --git a/src/Makefile.freebsd.WWW b/src/Makefile.freebsd.WWW index 579c49b..648703c 100644 --- a/src/Makefile.freebsd.WWW +++ b/src/Makefile.freebsd.WWW @@ -34,7 +34,7 @@ $(CDK): cd ../deps/cdk-5.0-20161210/ && export CPPFLAGS=-I/usr/local/include && ./configure --with-ncurses cd ../deps/cdk-5.0-20161210/ && $(MAKE) -OBJ = ../deps/aha/aha.o inih/ini.o bbs.o main.o users.o main_menu.o mail_menu.o doors.o bbs_list.o chat_system.o email.o files.o settings.o lua_glue.o strings.o bluewave.o www.o www_email.o www_msgs.o www_last10.o hashmap/hashmap.o menus.o +OBJ = ../deps/aha/aha.o ../deps/hashids/hashids.o inih/ini.o bbs.o main.o users.o main_menu.o mail_menu.o doors.o bbs_list.o chat_system.o email.o files.o settings.o lua_glue.o strings.o bluewave.o www.o www_email.o www_msgs.o www_last10.o www_files.o hashmap/hashmap.o menus.o %.o: %.c $(DEPS) $(CC) -c -o $@ $< $(CFLAGS) diff --git a/src/Makefile.linux.WWW b/src/Makefile.linux.WWW index 6ddadc0..850ea3b 100644 --- a/src/Makefile.linux.WWW +++ b/src/Makefile.linux.WWW @@ -34,7 +34,7 @@ $(CDK): cd ../deps/cdk-5.0-20161210/ && ./configure cd ../deps/cdk-5.0-20161210/ && $(MAKE) -OBJ = ../deps/aha/aha.o inih/ini.o bbs.o main.o users.o main_menu.o mail_menu.o doors.o bbs_list.o chat_system.o email.o files.o settings.o lua_glue.o strings.o www.o www_email.o www_msgs.o www_last10.o bluewave.o hashmap/hashmap.o menus.o +OBJ = ../deps/aha/aha.o ../deps/hashids/hashids.o inih/ini.o bbs.o main.o users.o main_menu.o mail_menu.o doors.o bbs_list.o chat_system.o email.o files.o settings.o lua_glue.o strings.o www.o www_email.o www_msgs.o www_last10.o www_files.o bluewave.o hashmap/hashmap.o menus.o %.o: %.c $(DEPS) $(CC) -c -o $@ $< $(CFLAGS) diff --git a/src/Makefile.netbsd.WWW b/src/Makefile.netbsd.WWW index c6bf98b..f07c917 100644 --- a/src/Makefile.netbsd.WWW +++ b/src/Makefile.netbsd.WWW @@ -34,7 +34,7 @@ $(CDK): cd ../deps/cdk-5.0-20161210/ && export CPPFLAGS=-I/usr/pkg/include && ./configure --with-ncurses cd ../deps/cdk-5.0-20161210/ && $(MAKE) -OBJ = ../deps/aha/aha.o inih/ini.o bbs.o main.o users.o main_menu.o mail_menu.o doors.o bbs_list.o chat_system.o email.o files.o settings.o lua_glue.o strings.o bluewave.o www.o www_email.o www_msgs.o www_last10.o hashmap/hashmap.o menus.o +OBJ = ../deps/aha/aha.o ../deps/hashids/hashids.o inih/ini.o bbs.o main.o users.o main_menu.o mail_menu.o doors.o bbs_list.o chat_system.o email.o files.o settings.o lua_glue.o strings.o bluewave.o www.o www_email.o www_msgs.o www_last10.o www_files.o hashmap/hashmap.o menus.o %.o: %.c $(DEPS) $(CC) -c -o $@ $< $(CFLAGS) diff --git a/src/Makefile.openbsd.WWW b/src/Makefile.openbsd.WWW index abdb526..450250c 100644 --- a/src/Makefile.openbsd.WWW +++ b/src/Makefile.openbsd.WWW @@ -34,7 +34,7 @@ $(CDK): cd ../deps/cdk-5.0-20161210/ && export CPPFLAGS=-I/usr/pkg/include && ./configure --with-ncurses cd ../deps/cdk-5.0-20161210/ && $(MAKE) -OBJ = ../deps/aha/aha.o inih/ini.o bbs.o main.o users.o main_menu.o mail_menu.o doors.o bbs_list.o chat_system.o email.o files.o settings.o lua_glue.o strings.o bluewave.o www.o www_email.o www_msgs.o www_last10.o hashmap/hashmap.o menus.o +OBJ = ../deps/aha/aha.o ../deps/hashids/hashids.o inih/ini.o bbs.o main.o users.o main_menu.o mail_menu.o doors.o bbs_list.o chat_system.o email.o files.o settings.o lua_glue.o strings.o bluewave.o www.o www_email.o www_msgs.o www_last10.o www_files.o hashmap/hashmap.o menus.o %.o: %.c $(DEPS) $(CC) -c -o $@ $< $(CFLAGS) diff --git a/src/Makefile.osx.WWW b/src/Makefile.osx.WWW index ba540bc..f7aabfe 100644 --- a/src/Makefile.osx.WWW +++ b/src/Makefile.osx.WWW @@ -34,7 +34,7 @@ $(CDK): cd ../deps/cdk-5.0-20161210/ && ./configure cd ../deps/cdk-5.0-20161210/ && $(MAKE) -OBJ = ../deps/aha/aha.o inih/ini.o bbs.o main.o users.o main_menu.o mail_menu.o doors.o bbs_list.o chat_system.o email.o files.o settings.o lua_glue.o strings.o www.o www_email.o www_msgs.o www_last10.o bluewave.o hashmap/hashmap.o menus.o +OBJ = ../deps/aha/aha.o ../deps/hashids/hashids.o inih/ini.o bbs.o main.o users.o main_menu.o mail_menu.o doors.o bbs_list.o chat_system.o email.o files.o settings.o lua_glue.o strings.o www.o www_email.o www_msgs.o www_last10.o www_files.o bluewave.o hashmap/hashmap.o menus.o %.o: %.c $(DEPS) $(CC) -c -o $@ $< $(CFLAGS) diff --git a/src/Makefile.sunos.WWW b/src/Makefile.sunos.WWW index 09eb808..bcbdb2d 100644 --- a/src/Makefile.sunos.WWW +++ b/src/Makefile.sunos.WWW @@ -34,7 +34,7 @@ $(CDK): cd ../deps/cdk-5.0-20161210/ && ./configure cd ../deps/cdk-5.0-20161210/ && $(MAKE) -OBJ = ../deps/aha/aha.o inih/ini.o bbs.o main.o users.o main_menu.o mail_menu.o doors.o bbs_list.o chat_system.o email.o files.o settings.o lua_glue.o strings.o www.o www_email.o www_msgs.o www_last10.o bluewave.o hashmap/hashmap.o menus.o os/sunos.o +OBJ = ../deps/aha/aha.o ../deps/hashids/hashids.o inih/ini.o bbs.o main.o users.o main_menu.o mail_menu.o doors.o bbs_list.o chat_system.o email.o files.o settings.o lua_glue.o strings.o www.o www_email.o www_msgs.o www_last10.o bluewave.o www_files.o hashmap/hashmap.o menus.o os/sunos.o %.o: %.c $(DEPS) $(CC) -c -o $@ $< $(CFLAGS) diff --git a/src/bbs.c b/src/bbs.c index 9171a28..092d6c7 100644 --- a/src/bbs.c +++ b/src/bbs.c @@ -895,6 +895,9 @@ tryagain: unlink(buffer); } +#if defined(ENABLE_WWW) + www_expire_old_links(); +#endif // do post-login dolog("%s logged in, on node %d", user->loginname, mynode); broadcast("%s logged in, on node %d", user->loginname, mynode); diff --git a/src/bbs.h b/src/bbs.h index 01758e9..dc38da1 100644 --- a/src/bbs.h +++ b/src/bbs.h @@ -323,6 +323,7 @@ extern void next_file_sub(struct user_record *user); extern void prev_file_sub(struct user_record *user); extern void file_scan(); extern void file_search(); +extern void genurls(); extern void lua_push_cfunctions(lua_State *L); extern void do_lua_script(char *script); @@ -350,6 +351,8 @@ extern char *www_msgs_messageview(struct user_record *user, int conference, int extern int www_send_msg(struct user_record *user, char *to, char *subj, int conference, int area, char *replyid, char *body); extern char *www_new_msg(struct user_record *user, int conference, int area); extern char *www_last10(); +extern void www_expire_old_links(); +extern char *www_create_link(int dir, int sub, int fid); #endif extern int menu_system(char *menufile); #endif diff --git a/src/files.c b/src/files.c index 7a6bd20..bb643e4 100644 --- a/src/files.c +++ b/src/files.c @@ -798,6 +798,42 @@ void download_zmodem(struct user_record *user, char *filename) { } } + +void genurls() { +#if defined(ENABLE_WWW) + int i; + char *url; + for (i=0;idir, tagged_files[i]->sub, tagged_files[i]->fid); + + if (url != NULL) { + s_printf(get_string(255), basename(tagged_files[i]->filename)); + s_printf(get_string(256), url); + free(url); + } else { + s_printf(get_string(257)); + } + } + for (i=0;ifilename); + free(tagged_files[i]); + } + free(tagged_files); + tagged_count = 0; +#else + s_printf(get_string(258)); + s_printf(get_string(6)); + s_getc(); +#endif +} + + void download(struct user_record *user) { int i; char *ssql = "select dlcount from files where filename like ?"; @@ -810,6 +846,7 @@ void download(struct user_record *user) { for (i=0;ifilename)); do_download(user, tagged_files[i]->filename); @@ -1324,15 +1361,15 @@ void list_files(struct user_record *user) { } sqlite3_busy_timeout(db, 5000); rc = sqlite3_prepare_v2(db, sql, -1, &res, 0); - if (sql == nsql) { - sqlite3_bind_int(res, 1, userlaston); - } if (rc != SQLITE_OK) { - sqlite3_finalize(res); sqlite3_close(db); s_printf(get_string(68)); return; } + if (sql == nsql) { + sqlite3_bind_int(res, 1, userlaston); + } + files_c = 0; diff --git a/src/menus.c b/src/menus.c index 12e15a1..e0e8141 100644 --- a/src/menus.c +++ b/src/menus.c @@ -54,6 +54,7 @@ #define MENU_FILESEARCH 44 #define MENU_DISPTXTFILE 45 #define MENU_DISPTXTFILEPAUSE 46 +#define MENU_GENWWWURLS 47 extern struct bbs_config conf; extern struct user_record *gUser; @@ -212,7 +213,9 @@ int menu_system(char *menufile) { menu[menu_items-1]->command = MENU_DISPTXTFILE; } else if (strncasecmp(&buffer[8], "DISPLAYTXTPAUSE", 15) == 0) { menu[menu_items-1]->command = MENU_DISPTXTFILEPAUSE; - } + } else if (strncasecmp(&buffer[8], "GENWWWURLS", 10) == 0) { + menu[menu_items-1]->command = MENU_GENWWWURLS; + } } else if (strncasecmp(buffer, "SECLEVEL", 8) == 0) { menu[menu_items-1]->seclevel = atoi(&buffer[9]); } else if (strncasecmp(buffer, "DATA", 4) == 0) { @@ -531,6 +534,9 @@ int menu_system(char *menufile) { s_printf(get_string(6)); s_getc(); break; + case MENU_GENWWWURLS: + genurls(); + break; default: break; } diff --git a/src/users.c b/src/users.c index 3e716a2..1026d08 100644 --- a/src/users.c +++ b/src/users.c @@ -266,7 +266,7 @@ int inst_user(struct user_record *user) { "exteditor INTEGER," "bwavestyle INTEGER," "signature TEXT," - "autosig INT);"; + "autosig INTEGER);"; char *insert_sql = "INSERT INTO users (loginname, password, salt, firstname," "lastname, email, location, sec_level, last_on, time_left, cur_mail_conf, cur_mail_area, cur_file_dir, cur_file_sub, times_on, bwavepktno, archiver, protocol, nodemsgs, codepage, exteditor, bwavestyle, signature, autosig) VALUES(?,?, ?,?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; diff --git a/src/www.c b/src/www.c index 2acd743..214f34d 100644 --- a/src/www.c +++ b/src/www.c @@ -415,6 +415,7 @@ int www_handler(void * cls, struct MHD_Connection * connection, const char * url const char *val; int skip; char *replyid; + char *filename; // char *static_buffer; if (strcmp(method, "GET") == 0) { @@ -826,6 +827,36 @@ int www_handler(void * cls, struct MHD_Connection * connection, const char * url return MHD_YES; } + } else if (strncasecmp(url, "/files/", 7) == 0) { + filename = www_decode_hash(&url[7]); + if (filename != NULL) { + if (stat(filename, &s) == 0 && S_ISREG(s.st_mode)) { + fno = open(buffer, 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); + sprintf(buffer, "%ld", s.st_size); + MHD_add_response_header(response, MHD_HTTP_HEADER_CONTENT_LENGTH, buffer); + 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); + free(header); + free(footer); + return ret; + } + } + free(filename); + } + if (www_404(header, footer, connection) != 0) { + free(header); + free(footer); + return MHD_NO; + } + free(header); + free(footer); + return MHD_YES; } else { if (www_404(header, footer, connection) != 0) { free(header); diff --git a/src/www_files.c b/src/www_files.c new file mode 100644 index 0000000..cfad512 --- /dev/null +++ b/src/www_files.c @@ -0,0 +1,237 @@ +#if defined(ENABLE_WWW) + +#include +#include +#include +#include +#include "bbs.h" +#include "../deps/hashids/hashids.h" + +extern struct bbs_config conf; +extern struct user_record *gUser; + +void www_expire_old_links() { + char buffer[PATH_MAX]; + sqlite3 *db; + sqlite3_stmt *res; + int rc; + char sql[] = "delete from wwwhash where expire <= ?"; + char *ret; + time_t now = time(NULL); + + snprintf(buffer, PATH_MAX, "%s/www_file_hashes.sq3", conf.bbs_path); + + rc = sqlite3_open(buffer, &db); + if (rc != SQLITE_OK) { + dolog("Cannot open database: %s", sqlite3_errmsg(db)); + return; + } + sqlite3_busy_timeout(db, 5000); + rc = sqlite3_prepare_v2(db, sql, -1, &res, 0); + if (rc != SQLITE_OK) { + sqlite3_close(db); + return; + } + sqlite3_bind_int(res, 1, now); + sqlite3_step(res); + sqlite3_finalize(res); + sqlite3_close(db); +} + +int www_check_hash_expired(char *hash) { + char buffer[PATH_MAX]; + sqlite3 *db; + sqlite3_stmt *res; + int rc; + time_t now = time(NULL); + char sql[] = "select id from wwwhash where hash = ? and expire > ?"; + snprintf(buffer, PATH_MAX, "%s/www_file_hashes.sq3", conf.bbs_path); + rc = sqlite3_open(buffer, &db); + if (rc != SQLITE_OK) { + return 1; + } + sqlite3_busy_timeout(db, 5000); + rc = sqlite3_prepare_v2(db, sql, -1, &res, 0); + if (rc != SQLITE_OK) { + sqlite3_close(db); + return 0; + } + + sqlite3_bind_text(res, 1, hash, -1, 0); + sqlite3_bind_int(res, 2, now); + + if (sqlite3_step(res) == SQLITE_ROW) { + sqlite3_finalize(res); + sqlite3_close(db); + return 0; + } + sqlite3_finalize(res); + sqlite3_close(db); + return 1; +} + +void www_add_hash_to_db(char *hash, time_t expiry) { + char buffer[PATH_MAX]; + sqlite3 *db; + sqlite3_stmt *res; + int rc; + char csql[] = "create table if not exists wwwhash (id INTEGER PRIMARY KEY, hash TEXT, expiry INTEGER)"; + char chsql[] = "select id from wwwhash where hash = ?"; + char usql[] = "update wwwhash SET expiry = ? WHERE hash = ?"; + char isql[] = "insert into wwwhash (hash, expiry) values(?, ?)"; + + char *ret; + char *err_msg = 0; + + snprintf(buffer, PATH_MAX, "%s/www_file_hashes.sq3", conf.bbs_path); + + rc = sqlite3_open(buffer, &db); + if (rc != SQLITE_OK) { + return; + } + sqlite3_busy_timeout(db, 5000); + + rc = sqlite3_exec(db, csql, 0, 0, &err_msg); + if (rc != SQLITE_OK) { + + dolog("SQL error: %s", err_msg); + + sqlite3_free(err_msg); + sqlite3_close(db); + return; + } + + // first check if hash is in database + rc = sqlite3_prepare_v2(db, chsql, -1, &res, 0); + if (rc != SQLITE_OK) { + sqlite3_close(db); + return; + } + sqlite3_bind_text(res, 1, hash, -1, 0); + rc = sqlite3_step(res); + if (rc == SQLITE_ROW) { + // if so, update hash + sqlite3_finalize(res); + rc = sqlite3_prepare_v2(db, usql, -1, &res, 0); + if (rc != SQLITE_OK) { + sqlite3_close(db); + return; + } + sqlite3_bind_int(res, 1, expiry); + sqlite3_bind_text(res, 2, hash, -1, 0); + sqlite3_step(res); + sqlite3_finalize(res); + sqlite3_close(db); + + return; + } + // if not add hash + sqlite3_finalize(res); + rc = sqlite3_prepare_v2(db, isql, -1, &res, 0); + if (rc != SQLITE_OK) { + sqlite3_close(db); + return; + } + sqlite3_bind_text(res, 1, hash, -1, 0); + sqlite3_bind_int(res, 2, expiry); + sqlite3_step(res); + sqlite3_finalize(res); + sqlite3_close(db); +} + +char *www_decode_hash(char *hash) { + long long unsigned numbers[4]; + int dir, sub, fid, uid; + hashids_t *hashids = hashids_init(conf.bbs_name); + char buffer[PATH_MAX]; + sqlite3 *db; + sqlite3_stmt *res; + int rc; + char sql[] = "select filename from files where approved = 1 and id = ?"; + char *ret; + + if (www_check_hash_expired(hash)) { + return NULL; + } + + if (hashids_decode(hashids, hash, numbers) != 4) { + hashids_free(hashids); + return NULL; + } + hashids_free(hashids); + + uid = (int)numbers[0]; + dir = (int)numbers[1]; + sub = (int)numbers[2]; + fid = (int)numbers[3]; + + if (dir >= conf.file_directory_count || sub >= conf.file_directories[dir]->file_sub_count) { + return NULL; + } + +#if 0 + // TODO: check security level... + + if (conf.file_directories[dir]->sec_level < ) +#endif + // get filename from database + snprintf(buffer, PATH_MAX, "%s/%s.sq3", conf.bbs_path, conf.file_directories[dir]->file_subs[sub]->database); + rc = sqlite3_open(buffer, &db); + if (rc != SQLITE_OK) { + dolog("Cannot open database: %s", sqlite3_errmsg(db)); + return NULL; + } + sqlite3_busy_timeout(db, 5000); + rc = sqlite3_prepare_v2(db, sql, -1, &res, 0); + if (rc != SQLITE_OK) { + sqlite3_close(db); + return NULL; + } + sqlite3_bind_int(res, 1, fid); + if (sqlite3_step(res) == SQLITE_ROW) { + ret = strdup(sqlite3_column_text(res, 0)); + sqlite3_finalize(res); + sqlite3_close(db); + + return ret; + } + sqlite3_finalize(res); + sqlite3_close(db); + return NULL; +} + +char *www_create_link(int dir, int sub, int fid) { + char url[PATH_MAX]; + char *ret; + char *hashid; + int sizereq; + time_t expiry; + + hashids_t *hashids = hashids_init(conf.bbs_name); + + sizereq = hashids_estimate_encoded_size_v(hashids, 4, gUser->id, dir, sub, fid); + + hashid = (char *)malloc(sizereq); + + if (hashids_encode_v(hashids, hashid, 4, gUser->id, dir, sub, fid) == 0) { + hashids_free(hashids); + free(hashid); + return NULL; + } + + hashids_free(hashids); + + snprintf(url, PATH_MAX, "%sfiles/%s", conf.www_url, hashid); + + // add link into hash database + expiry = time(NULL) + 86400; + www_add_hash_to_db(hashid, expiry); + + free(hashid); + + ret = strdup(url); + + return ret; +} + +#endif From d694b22b8dfe39c5002aee0f42957d0048f64aa1 Mon Sep 17 00:00:00 2001 From: Andrew Pamment Date: Tue, 23 Jan 2018 21:16:36 +1000 Subject: [PATCH 09/87] misc fixes --- src/www.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/www.c b/src/www.c index 214f34d..91e221b 100644 --- a/src/www.c +++ b/src/www.c @@ -831,7 +831,7 @@ int www_handler(void * cls, struct MHD_Connection * connection, const char * url filename = www_decode_hash(&url[7]); if (filename != NULL) { if (stat(filename, &s) == 0 && S_ISREG(s.st_mode)) { - fno = open(buffer, O_RDONLY); + fno = open(filename, O_RDONLY); if (fno != -1) { response = MHD_create_response_from_fd(s.st_size, fno); @@ -844,6 +844,7 @@ int www_handler(void * cls, struct MHD_Connection * connection, const char * url MHD_destroy_response (response); free(header); free(footer); + free(filename); return ret; } } From f1b81c995393d274b8c4031e6070364e7d18f53e Mon Sep 17 00:00:00 2001 From: Andrew Pamment Date: Tue, 23 Jan 2018 21:31:50 +1000 Subject: [PATCH 10/87] another fix --- src/bbs.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bbs.h b/src/bbs.h index dc38da1..197290e 100644 --- a/src/bbs.h +++ b/src/bbs.h @@ -353,6 +353,7 @@ extern char *www_new_msg(struct user_record *user, int conference, int area); extern char *www_last10(); extern void www_expire_old_links(); extern char *www_create_link(int dir, int sub, int fid); +extern char *www_decode_hash(char *hash); #endif extern int menu_system(char *menufile); #endif From 256aa800f73ad902e70e36c6f3af5c39cb79a3a6 Mon Sep 17 00:00:00 2001 From: Andrew Pamment Date: Tue, 23 Jan 2018 21:37:23 +1000 Subject: [PATCH 11/87] fix mimetype --- src/www.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/www.c b/src/www.c index 91e221b..d648900 100644 --- a/src/www.c +++ b/src/www.c @@ -830,6 +830,23 @@ int www_handler(void * cls, struct MHD_Connection * connection, const char * url } else if (strncasecmp(url, "/files/", 7) == 0) { filename = www_decode_hash(&url[7]); if (filename != NULL) { + mime = NULL; + // get mimetype + for (i=strlen(filename);i>0;--i) { + if (filename[i] == '.') { + mime = www_get_mime_type(&filename[i+1]); + break; + } + if (filename[i] == '/') { + mime = www_get_mime_type(NULL); + break; + } + } + + if (mime = NULL) { + mime = www_get_mime_type(NULL); + } + if (stat(filename, &s) == 0 && S_ISREG(s.st_mode)) { fno = open(filename, O_RDONLY); if (fno != -1) { From 7a09cb9c612997b255cdebec7759d4a0c37f3c22 Mon Sep 17 00:00:00 2001 From: Andrew Pamment Date: Tue, 23 Jan 2018 21:47:34 +1000 Subject: [PATCH 12/87] fixes... looks to be working now --- src/www.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/www.c b/src/www.c index d648900..a3163fb 100644 --- a/src/www.c +++ b/src/www.c @@ -8,6 +8,7 @@ #include #include #include +#include #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__) #include #endif @@ -855,6 +856,7 @@ int www_handler(void * cls, struct MHD_Connection * connection, const char * url MHD_add_response_header(response, MHD_HTTP_HEADER_CONTENT_TYPE, mime); sprintf(buffer, "%ld", s.st_size); MHD_add_response_header(response, MHD_HTTP_HEADER_CONTENT_LENGTH, buffer); + 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); From be99702b848d2b8707c1356e86fd34aa18acdaa6 Mon Sep 17 00:00:00 2001 From: Andrew Pamment Date: Tue, 23 Jan 2018 21:54:45 +1000 Subject: [PATCH 13/87] graphical fixes --- src/files.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/files.c b/src/files.c index bb643e4..9babbd1 100644 --- a/src/files.c +++ b/src/files.c @@ -804,7 +804,7 @@ void genurls() { int i; char *url; for (i=0;i Date: Tue, 23 Jan 2018 22:09:23 +1000 Subject: [PATCH 14/87] update file menu ansi with the new option --- dist/ansis/filemenu.ans | Bin 1784 -> 1821 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/dist/ansis/filemenu.ans b/dist/ansis/filemenu.ans index 5202b6c1d99f82b51f7716c5a829cdaff0fcbb76..e5d3ea00dd221c9814744f3a58aea84682e0d2da 100644 GIT binary patch delta 78 zcmeytJC|>RJ&UHLvvjnvS#G$3f^@W@wXu1wOMZD?PJUvFf?H-zYO#VwczC#`bhLr> iWEYl9CL^=Smskv#j7=u5V=>$;$a;{Gan9t+Y^ng5dlzN^ delta 40 wcmbQs_k(wXJqxR`k+XF4 Date: Wed, 24 Jan 2018 11:39:27 +1000 Subject: [PATCH 15/87] disable genurls if www_server is not enabled --- src/files.c | 48 +++++++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/src/files.c b/src/files.c index 9babbd1..d62b7fb 100644 --- a/src/files.c +++ b/src/files.c @@ -803,31 +803,37 @@ void genurls() { #if defined(ENABLE_WWW) int i; char *url; - for (i=0;idir, tagged_files[i]->sub, tagged_files[i]->fid); + url = www_create_link(tagged_files[i]->dir, tagged_files[i]->sub, tagged_files[i]->fid); - if (url != NULL) { - s_printf(get_string(255), basename(tagged_files[i]->filename)); - s_printf(get_string(256), url); - free(url); - } else { - s_printf(get_string(257)); + if (url != NULL) { + s_printf(get_string(255), basename(tagged_files[i]->filename)); + s_printf(get_string(256), url); + free(url); + } else { + s_printf(get_string(257)); + } } + for (i=0;ifilename); + free(tagged_files[i]); + } + free(tagged_files); + tagged_count = 0; + s_printf(get_string(6)); + s_getc(); + } else { + s_printf(get_string(258)); + s_printf(get_string(6)); + s_getc(); } - for (i=0;ifilename); - free(tagged_files[i]); - } - free(tagged_files); - tagged_count = 0; - s_printf(get_string(6)); - s_getc(); #else s_printf(get_string(258)); s_printf(get_string(6)); From 251692d2c6ab56906631e9691b40f1c3235f562b Mon Sep 17 00:00:00 2001 From: Andrew Pamment Date: Wed, 24 Jan 2018 11:59:53 +1000 Subject: [PATCH 16/87] add space at the end of magicka.strings --- dist/magicka.strings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist/magicka.strings b/dist/magicka.strings index 6415ebb..671b5bd 100644 --- a/dist/magicka.strings +++ b/dist/magicka.strings @@ -256,4 +256,4 @@ File exists!\r\n \r\n\e[1;34mFilename\e[1;30m: \e[1;37m%s\e[0m\r\n \e[1;34mURL\e[1;30m: \e[1;37m%s\e[0m\r\n \r\n\e[1;31mError creating URL!\e[0m\r\n -\e[1;33mSorry this BBS does not have the webserver enabled.\e[0m\r\n \ No newline at end of file +\e[1;33mSorry this BBS does not have the webserver enabled.\e[0m\r\n From 2fcf6305c060b0650abecc470ef275addb29c17a Mon Sep 17 00:00:00 2001 From: Andrew Pamment Date: Thu, 25 Jan 2018 09:37:22 +1000 Subject: [PATCH 17/87] add a * next to areas that have new messages --- STRINGS.CHANGES | 10 ++++- dist/magicka.strings | 2 + src/bbs.h | 1 + src/mail_menu.c | 90 ++++++++++++++++++++++++++++++++++++++++---- src/www_msgs.c | 52 ------------------------- 5 files changed, 95 insertions(+), 60 deletions(-) diff --git a/STRINGS.CHANGES b/STRINGS.CHANGES index ef53413..7b4cff1 100644 --- a/STRINGS.CHANGES +++ b/STRINGS.CHANGES @@ -25,4 +25,12 @@ NEWSTRING: "\r\n\e[1;31mError creating URL!\e[0m\r\n" LINE 259 NEW OLDSTRING: (NONE) -NEWSTRING: "\e[1;33mSorry this BBS does not have the webserver enabled.\e[0m\r\n" \ No newline at end of file +NEWSTRING: "\e[1;33mSorry this BBS does not have the webserver enabled.\e[0m\r\n" + +LINE 260 NEW +OLDSTRING: (NONE) +NEWSTRING: "\e[%d;1H\e[1;30;40m[\e[1;34;44m%4d\e[1;30;40m]\e[1;32m*\e[1;37m%s\e[K" + +LINE 261 NEW +OLDSTRING: (NONE) +NEWSTRING: "\e[%d;1H\e[1;30;40m[\e[1;34m%4d\e[1;30;40m]\e[1;32m*\e[1;37m%s\e[K" \ No newline at end of file diff --git a/dist/magicka.strings b/dist/magicka.strings index 671b5bd..54970f5 100644 --- a/dist/magicka.strings +++ b/dist/magicka.strings @@ -257,3 +257,5 @@ File exists!\r\n \e[1;34mURL\e[1;30m: \e[1;37m%s\e[0m\r\n \r\n\e[1;31mError creating URL!\e[0m\r\n \e[1;33mSorry this BBS does not have the webserver enabled.\e[0m\r\n +\e[%d;1H\e[1;30;40m[\e[1;34;44m%4d\e[1;30;40m]\e[1;32m*\e[1;37m%s\e[K +\e[%d;1H\e[1;30;40m[\e[1;34m%4d\e[1;30;40m]\e[1;32m*\e[1;37m%s\e[K diff --git a/src/bbs.h b/src/bbs.h index 197290e..615716a 100644 --- a/src/bbs.h +++ b/src/bbs.h @@ -293,6 +293,7 @@ extern void msgbase_reset_pointers(int conference, int msgarea); extern void msgbase_reset_all_pointers(); extern void full_mail_scan(struct user_record *user); extern int read_new_msgs(struct user_record *user, struct msg_headers *msghs); +extern int new_messages(struct user_record *user, int conference, int area); extern void rundoor(struct user_record *user, char *cmd, int stdio, char *codepage); extern void runexternal(struct user_record *user, char *cmd, int stdio, char **argv, char *cwd, int raw, char *codepage); diff --git a/src/mail_menu.c b/src/mail_menu.c index 1fc5a0d..c01090a 100644 --- a/src/mail_menu.c +++ b/src/mail_menu.c @@ -2756,9 +2756,17 @@ void choose_area() { s_printf(get_string(248)); for (i=start;iindex, area_tmp[i]->area->name); + if (new_messages(gUser, gUser->cur_mail_conf, area_tmp[i]->index)) { + s_printf(get_string(259), i - start + 2, area_tmp[i]->index, area_tmp[i]->area->name); + } else { + s_printf(get_string(249), i - start + 2, area_tmp[i]->index, area_tmp[i]->area->name); + } } else { - s_printf(get_string(250), i - start + 2, area_tmp[i]->index, area_tmp[i]->area->name); + if (new_messages(gUser, gUser->cur_mail_conf, area_tmp[i]->index)) { + s_printf(get_string(260), i - start + 2, area_tmp[i]->index, area_tmp[i]->area->name); + } else { + s_printf(get_string(250), i - start + 2, area_tmp[i]->index, area_tmp[i]->area->name); + } } } s_printf("\e[%d;5H", selected - start + 2); @@ -2785,8 +2793,16 @@ void choose_area() { selected = list_tmp - 1; } else { if (!redraw) { - s_printf(get_string(250), selected - start + 1, area_tmp[selected - 1]->index, area_tmp[selected - 1]->area->name); - s_printf(get_string(249), selected - start + 2, area_tmp[selected]->index, area_tmp[selected]->area->name); + if (new_messages(gUser, gUser->cur_mail_conf, area_tmp[selected - 1]->index)) { + s_printf(get_string(260), selected - start + 1, area_tmp[selected - 1]->index, area_tmp[selected - 1]->area->name); + } else { + s_printf(get_string(250), selected - start + 1, area_tmp[selected - 1]->index, area_tmp[selected - 1]->area->name); + } + if (new_messages(gUser, gUser->cur_mail_conf, area_tmp[selected]->index)) { + s_printf(get_string(259), selected - start + 2, area_tmp[selected]->index, area_tmp[selected]->area->name); + } else { + s_printf(get_string(249), selected - start + 2, area_tmp[selected]->index, area_tmp[selected]->area->name); + } s_printf("\e[%d;5H", selected - start + 2); } } @@ -2803,9 +2819,17 @@ void choose_area() { if (selected < 0) { selected = 0; } else { - if (!redraw) { - s_printf(get_string(249), selected - start + 2, area_tmp[selected]->index, area_tmp[selected]->area->name); - s_printf(get_string(250), selected - start + 3, area_tmp[selected + 1]->index, area_tmp[selected + 1]->area->name); + if (!redraw) { + if (new_messages(gUser, gUser->cur_mail_conf, area_tmp[selected]->index)) { + s_printf(get_string(259), selected - start + 2, area_tmp[selected]->index, area_tmp[selected]->area->name); + } else { + s_printf(get_string(249), selected - start + 2, area_tmp[selected]->index, area_tmp[selected]->area->name); + } + if (new_messages(gUser, gUser->cur_mail_conf, area_tmp[selected + 1]->index)) { + s_printf(get_string(260), selected - start + 3, area_tmp[selected + 1]->index, area_tmp[selected + 1]->area->name); + } else { + s_printf(get_string(250), selected - start + 3, area_tmp[selected + 1]->index, area_tmp[selected + 1]->area->name); + } s_printf("\e[%d;5H", selected - start + 2); } } @@ -3233,3 +3257,55 @@ void msgbase_reset_all_pointers() { } } } + +int new_messages(struct user_record *user, int conference, int area) { + int count = 0; + s_JamBase *jb; + s_JamBaseHeader jbh; + s_JamLastRead jlr; + struct msg_headers *msghs; + + jb = open_jam_base(conf.mail_conferences[conference]->mail_areas[area]->path); + if (!jb) { + return 0; + } + if (JAM_ReadMBHeader(jb, &jbh) != 0) { + JAM_CloseMB(jb); + return 0; + } + if (JAM_ReadLastRead(jb, user->id, &jlr) == JAM_NO_USER) { + if (jbh.ActiveMsgs == 0) { + JAM_CloseMB(jb); + return 0; + } + if (conf.mail_conferences[conference]->mail_areas[area]->type == TYPE_NETMAIL_AREA) { + msghs = read_message_headers(conference, area, user); + if (msghs != NULL) { + if (msghs->msg_count > 0) { + count = msghs->msg_count; + } + free_message_headers(msghs); + } + } else { + count = jbh.ActiveMsgs; + } + } else { + if (jlr.HighReadMsg < jbh.ActiveMsgs) { + if (conf.mail_conferences[conference]->mail_areas[area]->type == TYPE_NETMAIL_AREA) { + msghs = read_message_headers(conference, area, user); + if (msghs != NULL) { + if (msghs->msg_count > 0) { + if (msghs->msgs[msghs->msg_count-1]->msg_h->MsgNum > jlr.HighReadMsg) { + count = msghs->msgs[msghs->msg_count-1]->msg_h->MsgNum - jlr.HighReadMsg; + } + } + free_message_headers(msghs); + } + } else { + count = jbh.ActiveMsgs - jlr.HighReadMsg; + } + } + } + JAM_CloseMB(jb); + return count; +} diff --git a/src/www_msgs.c b/src/www_msgs.c index 28de7bf..0581e87 100644 --- a/src/www_msgs.c +++ b/src/www_msgs.c @@ -13,58 +13,6 @@ extern char * aha(char *input); extern struct bbs_config conf; -static int new_messages(struct user_record *user, int conference, int area) { - int count = 0; - s_JamBase *jb; - s_JamBaseHeader jbh; - s_JamLastRead jlr; - struct msg_headers *msghs; - - jb = open_jam_base(conf.mail_conferences[conference]->mail_areas[area]->path); - if (!jb) { - return 0; - } - if (JAM_ReadMBHeader(jb, &jbh) != 0) { - JAM_CloseMB(jb); - return 0; - } - if (JAM_ReadLastRead(jb, user->id, &jlr) == JAM_NO_USER) { - if (jbh.ActiveMsgs == 0) { - JAM_CloseMB(jb); - return 0; - } - if (conf.mail_conferences[conference]->mail_areas[area]->type == TYPE_NETMAIL_AREA) { - msghs = read_message_headers(conference, area, user); - if (msghs != NULL) { - if (msghs->msg_count > 0) { - count = msghs->msg_count; - } - free_message_headers(msghs); - } - } else { - count = jbh.ActiveMsgs; - } - } else { - if (jlr.HighReadMsg < jbh.ActiveMsgs) { - if (conf.mail_conferences[conference]->mail_areas[area]->type == TYPE_NETMAIL_AREA) { - msghs = read_message_headers(conference, area, user); - if (msghs != NULL) { - if (msghs->msg_count > 0) { - if (msghs->msgs[msghs->msg_count-1]->msg_h->MsgNum > jlr.HighReadMsg) { - count = msghs->msgs[msghs->msg_count-1]->msg_h->MsgNum - jlr.HighReadMsg; - } - } - free_message_headers(msghs); - } - } else { - count = jbh.ActiveMsgs - jlr.HighReadMsg; - } - } - } - JAM_CloseMB(jb); - return count; -} - static char *www_sanitize(char *inp) { int i; char *result; From 14b77790a6ad01e545a1eef54f6a8c91753008a5 Mon Sep 17 00:00:00 2001 From: Andrew Pamment Date: Thu, 25 Jan 2018 17:01:19 +1000 Subject: [PATCH 18/87] Bootstrap theme and form validation on message entry. --- dist/www-bootstrap/401.tpl | 2 + dist/www-bootstrap/403.tpl | 2 + dist/www-bootstrap/404.tpl | 2 + dist/www-bootstrap/footer.tpl | 19 + dist/www-bootstrap/header.tpl | 76 ++ dist/www-bootstrap/index.tpl | 3 + dist/www-bootstrap/mime.types | 3 + dist/www-bootstrap/static/delete.png | Bin 0 -> 292 bytes dist/www-bootstrap/static/fonts/LICENSE.TXT | 428 ++++++++++ .../static/fonts/pxplus_ibm_vga8-webfont.svg | 807 ++++++++++++++++++ .../static/fonts/pxplus_ibm_vga8-webfont.woff | Bin 0 -> 57816 bytes .../fonts/pxplus_ibm_vga8-webfont.woff2 | Bin 0 -> 39416 bytes dist/www-bootstrap/static/header.png | Bin 0 -> 7299 bytes dist/www-bootstrap/static/style.css | 345 ++++++++ dist/www/header.tpl | 17 + src/www_email.c | 10 +- src/www_msgs.c | 8 +- 17 files changed, 1713 insertions(+), 9 deletions(-) create mode 100644 dist/www-bootstrap/401.tpl create mode 100644 dist/www-bootstrap/403.tpl create mode 100644 dist/www-bootstrap/404.tpl create mode 100644 dist/www-bootstrap/footer.tpl create mode 100644 dist/www-bootstrap/header.tpl create mode 100644 dist/www-bootstrap/index.tpl create mode 100644 dist/www-bootstrap/mime.types create mode 100644 dist/www-bootstrap/static/delete.png create mode 100755 dist/www-bootstrap/static/fonts/LICENSE.TXT create mode 100755 dist/www-bootstrap/static/fonts/pxplus_ibm_vga8-webfont.svg create mode 100755 dist/www-bootstrap/static/fonts/pxplus_ibm_vga8-webfont.woff create mode 100755 dist/www-bootstrap/static/fonts/pxplus_ibm_vga8-webfont.woff2 create mode 100644 dist/www-bootstrap/static/header.png create mode 100644 dist/www-bootstrap/static/style.css diff --git a/dist/www-bootstrap/401.tpl b/dist/www-bootstrap/401.tpl new file mode 100644 index 0000000..f63524b --- /dev/null +++ b/dist/www-bootstrap/401.tpl @@ -0,0 +1,2 @@ +

401 - Not authorized

+The page you are looking for can not be accessed. diff --git a/dist/www-bootstrap/403.tpl b/dist/www-bootstrap/403.tpl new file mode 100644 index 0000000..9bd457e --- /dev/null +++ b/dist/www-bootstrap/403.tpl @@ -0,0 +1,2 @@ +

403 - Forbidden

+The page you are looking for can not be accessed. diff --git a/dist/www-bootstrap/404.tpl b/dist/www-bootstrap/404.tpl new file mode 100644 index 0000000..0c731a1 --- /dev/null +++ b/dist/www-bootstrap/404.tpl @@ -0,0 +1,2 @@ +

404 - Page not found

+The page you are looking for can not be found. diff --git a/dist/www-bootstrap/footer.tpl b/dist/www-bootstrap/footer.tpl new file mode 100644 index 0000000..2a8005a --- /dev/null +++ b/dist/www-bootstrap/footer.tpl @@ -0,0 +1,19 @@ + + +
+
+
+ +
+
+ + + + + + + + + diff --git a/dist/www-bootstrap/header.tpl b/dist/www-bootstrap/header.tpl new file mode 100644 index 0000000..38d8d2d --- /dev/null +++ b/dist/www-bootstrap/header.tpl @@ -0,0 +1,76 @@ + + + + + + + + + + + Magicka BBS + + + + + + + + + + + + + + +
+
+
diff --git a/dist/www-bootstrap/index.tpl b/dist/www-bootstrap/index.tpl new file mode 100644 index 0000000..0de5d06 --- /dev/null +++ b/dist/www-bootstrap/index.tpl @@ -0,0 +1,3 @@ +

Welcome to another Magicka BBS!

+ +The sysop should customize this file with what he/she wants on the front page! diff --git a/dist/www-bootstrap/mime.types b/dist/www-bootstrap/mime.types new file mode 100644 index 0000000..ac18d9d --- /dev/null +++ b/dist/www-bootstrap/mime.types @@ -0,0 +1,3 @@ +image/png png +application/javascript js +text/css css diff --git a/dist/www-bootstrap/static/delete.png b/dist/www-bootstrap/static/delete.png new file mode 100644 index 0000000000000000000000000000000000000000..f9643dabaa2b14c96c9895063b049cc6d77431da GIT binary patch literal 292 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjY)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYYs>cdx@v7EBgZuVRkXmJ8rJpKq1Kz*N775{M_8syb=cIqSVBa)D(sC z%#sWRcTeAd@J2pyprRg67sn8f<43~|3La44@Sbx*)2d{7f%5P0EY7LM@xp-}3I>an z`#huF4#j4hbgW$J$iNV@w)geCv+BCKO%f?9pGqH;d=l)ff05(Sr2x?tcTTKaaA#Up zT=<3{Nv(NFY^%Nn&lUT$<5L*dq(U9nm9BnUGhaD-=Zda8`z~hpJ=209_hqhc?A!Kv e@BVuG6GNs|Pr;I%ucCnNV(@hJb6Mw<&;$SgVrJn0 literal 0 HcmV?d00001 diff --git a/dist/www-bootstrap/static/fonts/LICENSE.TXT b/dist/www-bootstrap/static/fonts/LICENSE.TXT new file mode 100755 index 0000000..fd662a7 --- /dev/null +++ b/dist/www-bootstrap/static/fonts/LICENSE.TXT @@ -0,0 +1,428 @@ +Attribution-ShareAlike 4.0 International + +======================================================================= + +Creative Commons Corporation ("Creative Commons") is not a law firm and +does not provide legal services or legal advice. Distribution of +Creative Commons public licenses does not create a lawyer-client or +other relationship. Creative Commons makes its licenses and related +information available on an "as-is" basis. Creative Commons gives no +warranties regarding its licenses, any material licensed under their +terms and conditions, or any related information. Creative Commons +disclaims all liability for damages resulting from their use to the +fullest extent possible. + +Using Creative Commons Public Licenses + +Creative Commons public licenses provide a standard set of terms and +conditions that creators and other rights holders may use to share +original works of authorship and other material subject to copyright +and certain other rights specified in the public license below. The +following considerations are for informational purposes only, are not +exhaustive, and do not form part of our licenses. + + Considerations for licensors: Our public licenses are + intended for use by those authorized to give the public + permission to use material in ways otherwise restricted by + copyright and certain other rights. Our licenses are + irrevocable. Licensors should read and understand the terms + and conditions of the license they choose before applying it. + Licensors should also secure all rights necessary before + applying our licenses so that the public can reuse the + material as expected. Licensors should clearly mark any + material not subject to the license. This includes other CC- + licensed material, or material used under an exception or + limitation to copyright. More considerations for licensors: + wiki.creativecommons.org/Considerations_for_licensors + + Considerations for the public: By using one of our public + licenses, a licensor grants the public permission to use the + licensed material under specified terms and conditions. If + the licensor's permission is not necessary for any reason--for + example, because of any applicable exception or limitation to + copyright--then that use is not regulated by the license. Our + licenses grant only permissions under copyright and certain + other rights that a licensor has authority to grant. Use of + the licensed material may still be restricted for other + reasons, including because others have copyright or other + rights in the material. A licensor may make special requests, + such as asking that all changes be marked or described. + Although not required by our licenses, you are encouraged to + respect those requests where reasonable. More_considerations + for the public: + wiki.creativecommons.org/Considerations_for_licensees + +======================================================================= + +Creative Commons Attribution-ShareAlike 4.0 International Public +License + +By exercising the Licensed Rights (defined below), You accept and agree +to be bound by the terms and conditions of this Creative Commons +Attribution-ShareAlike 4.0 International Public License ("Public +License"). To the extent this Public License may be interpreted as a +contract, You are granted the Licensed Rights in consideration of Your +acceptance of these terms and conditions, and the Licensor grants You +such rights in consideration of benefits the Licensor receives from +making the Licensed Material available under these terms and +conditions. + + +Section 1 -- Definitions. + + a. Adapted Material means material subject to Copyright and Similar + Rights that is derived from or based upon the Licensed Material + and in which the Licensed Material is translated, altered, + arranged, transformed, or otherwise modified in a manner requiring + permission under the Copyright and Similar Rights held by the + Licensor. For purposes of this Public License, where the Licensed + Material is a musical work, performance, or sound recording, + Adapted Material is always produced where the Licensed Material is + synched in timed relation with a moving image. + + b. Adapter's License means the license You apply to Your Copyright + and Similar Rights in Your contributions to Adapted Material in + accordance with the terms and conditions of this Public License. + + c. BY-SA Compatible License means a license listed at + creativecommons.org/compatiblelicenses, approved by Creative + Commons as essentially the equivalent of this Public License. + + d. Copyright and Similar Rights means copyright and/or similar rights + closely related to copyright including, without limitation, + performance, broadcast, sound recording, and Sui Generis Database + Rights, without regard to how the rights are labeled or + categorized. For purposes of this Public License, the rights + specified in Section 2(b)(1)-(2) are not Copyright and Similar + Rights. + + e. Effective Technological Measures means those measures that, in the + absence of proper authority, may not be circumvented under laws + fulfilling obligations under Article 11 of the WIPO Copyright + Treaty adopted on December 20, 1996, and/or similar international + agreements. + + f. Exceptions and Limitations means fair use, fair dealing, and/or + any other exception or limitation to Copyright and Similar Rights + that applies to Your use of the Licensed Material. + + g. License Elements means the license attributes listed in the name + of a Creative Commons Public License. The License Elements of this + Public License are Attribution and ShareAlike. + + h. Licensed Material means the artistic or literary work, database, + or other material to which the Licensor applied this Public + License. + + i. Licensed Rights means the rights granted to You subject to the + terms and conditions of this Public License, which are limited to + all Copyright and Similar Rights that apply to Your use of the + Licensed Material and that the Licensor has authority to license. + + j. Licensor means the individual(s) or entity(ies) granting rights + under this Public License. + + k. Share means to provide material to the public by any means or + process that requires permission under the Licensed Rights, such + as reproduction, public display, public performance, distribution, + dissemination, communication, or importation, and to make material + available to the public including in ways that members of the + public may access the material from a place and at a time + individually chosen by them. + + l. Sui Generis Database Rights means rights other than copyright + resulting from Directive 96/9/EC of the European Parliament and of + the Council of 11 March 1996 on the legal protection of databases, + as amended and/or succeeded, as well as other essentially + equivalent rights anywhere in the world. + + m. You means the individual or entity exercising the Licensed Rights + under this Public License. Your has a corresponding meaning. + + +Section 2 -- Scope. + + a. License grant. + + 1. Subject to the terms and conditions of this Public License, + the Licensor hereby grants You a worldwide, royalty-free, + non-sublicensable, non-exclusive, irrevocable license to + exercise the Licensed Rights in the Licensed Material to: + + a. reproduce and Share the Licensed Material, in whole or + in part; and + + b. produce, reproduce, and Share Adapted Material. + + 2. Exceptions and Limitations. For the avoidance of doubt, where + Exceptions and Limitations apply to Your use, this Public + License does not apply, and You do not need to comply with + its terms and conditions. + + 3. Term. The term of this Public License is specified in Section + 6(a). + + 4. Media and formats; technical modifications allowed. The + Licensor authorizes You to exercise the Licensed Rights in + all media and formats whether now known or hereafter created, + and to make technical modifications necessary to do so. The + Licensor waives and/or agrees not to assert any right or + authority to forbid You from making technical modifications + necessary to exercise the Licensed Rights, including + technical modifications necessary to circumvent Effective + Technological Measures. For purposes of this Public License, + simply making modifications authorized by this Section 2(a) + (4) never produces Adapted Material. + + 5. Downstream recipients. + + a. Offer from the Licensor -- Licensed Material. Every + recipient of the Licensed Material automatically + receives an offer from the Licensor to exercise the + Licensed Rights under the terms and conditions of this + Public License. + + b. Additional offer from the Licensor -- Adapted Material. + Every recipient of Adapted Material from You + automatically receives an offer from the Licensor to + exercise the Licensed Rights in the Adapted Material + under the conditions of the Adapter's License You apply. + + c. No downstream restrictions. You may not offer or impose + any additional or different terms or conditions on, or + apply any Effective Technological Measures to, the + Licensed Material if doing so restricts exercise of the + Licensed Rights by any recipient of the Licensed + Material. + + 6. No endorsement. Nothing in this Public License constitutes or + may be construed as permission to assert or imply that You + are, or that Your use of the Licensed Material is, connected + with, or sponsored, endorsed, or granted official status by, + the Licensor or others designated to receive attribution as + provided in Section 3(a)(1)(A)(i). + + b. Other rights. + + 1. Moral rights, such as the right of integrity, are not + licensed under this Public License, nor are publicity, + privacy, and/or other similar personality rights; however, to + the extent possible, the Licensor waives and/or agrees not to + assert any such rights held by the Licensor to the limited + extent necessary to allow You to exercise the Licensed + Rights, but not otherwise. + + 2. Patent and trademark rights are not licensed under this + Public License. + + 3. To the extent possible, the Licensor waives any right to + collect royalties from You for the exercise of the Licensed + Rights, whether directly or through a collecting society + under any voluntary or waivable statutory or compulsory + licensing scheme. In all other cases the Licensor expressly + reserves any right to collect such royalties. + + +Section 3 -- License Conditions. + +Your exercise of the Licensed Rights is expressly made subject to the +following conditions. + + a. Attribution. + + 1. If You Share the Licensed Material (including in modified + form), You must: + + a. retain the following if it is supplied by the Licensor + with the Licensed Material: + + i. identification of the creator(s) of the Licensed + Material and any others designated to receive + attribution, in any reasonable manner requested by + the Licensor (including by pseudonym if + designated); + + ii. a copyright notice; + + iii. a notice that refers to this Public License; + + iv. a notice that refers to the disclaimer of + warranties; + + v. a URI or hyperlink to the Licensed Material to the + extent reasonably practicable; + + b. indicate if You modified the Licensed Material and + retain an indication of any previous modifications; and + + c. indicate the Licensed Material is licensed under this + Public License, and include the text of, or the URI or + hyperlink to, this Public License. + + 2. You may satisfy the conditions in Section 3(a)(1) in any + reasonable manner based on the medium, means, and context in + which You Share the Licensed Material. For example, it may be + reasonable to satisfy the conditions by providing a URI or + hyperlink to a resource that includes the required + information. + + 3. If requested by the Licensor, You must remove any of the + information required by Section 3(a)(1)(A) to the extent + reasonably practicable. + + b. ShareAlike. + + In addition to the conditions in Section 3(a), if You Share + Adapted Material You produce, the following conditions also apply. + + 1. The Adapter's License You apply must be a Creative Commons + license with the same License Elements, this version or + later, or a BY-SA Compatible License. + + 2. You must include the text of, or the URI or hyperlink to, the + Adapter's License You apply. You may satisfy this condition + in any reasonable manner based on the medium, means, and + context in which You Share Adapted Material. + + 3. You may not offer or impose any additional or different terms + or conditions on, or apply any Effective Technological + Measures to, Adapted Material that restrict exercise of the + rights granted under the Adapter's License You apply. + + +Section 4 -- Sui Generis Database Rights. + +Where the Licensed Rights include Sui Generis Database Rights that +apply to Your use of the Licensed Material: + + a. for the avoidance of doubt, Section 2(a)(1) grants You the right + to extract, reuse, reproduce, and Share all or a substantial + portion of the contents of the database; + + b. if You include all or a substantial portion of the database + contents in a database in which You have Sui Generis Database + Rights, then the database in which You have Sui Generis Database + Rights (but not its individual contents) is Adapted Material, + + including for purposes of Section 3(b); and + c. You must comply with the conditions in Section 3(a) if You Share + all or a substantial portion of the contents of the database. + +For the avoidance of doubt, this Section 4 supplements and does not +replace Your obligations under this Public License where the Licensed +Rights include other Copyright and Similar Rights. + + +Section 5 -- Disclaimer of Warranties and Limitation of Liability. + + a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE + EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS + AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF + ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, + IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, + WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, + ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT + KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT + ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. + + b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE + TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, + NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, + INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, + COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR + USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR + DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR + IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. + + c. The disclaimer of warranties and limitation of liability provided + above shall be interpreted in a manner that, to the extent + possible, most closely approximates an absolute disclaimer and + waiver of all liability. + + +Section 6 -- Term and Termination. + + a. This Public License applies for the term of the Copyright and + Similar Rights licensed here. However, if You fail to comply with + this Public License, then Your rights under this Public License + terminate automatically. + + b. Where Your right to use the Licensed Material has terminated under + Section 6(a), it reinstates: + + 1. automatically as of the date the violation is cured, provided + it is cured within 30 days of Your discovery of the + violation; or + + 2. upon express reinstatement by the Licensor. + + For the avoidance of doubt, this Section 6(b) does not affect any + right the Licensor may have to seek remedies for Your violations + of this Public License. + + c. For the avoidance of doubt, the Licensor may also offer the + Licensed Material under separate terms or conditions or stop + distributing the Licensed Material at any time; however, doing so + will not terminate this Public License. + + d. Sections 1, 5, 6, 7, and 8 survive termination of this Public + License. + + +Section 7 -- Other Terms and Conditions. + + a. The Licensor shall not be bound by any additional or different + terms or conditions communicated by You unless expressly agreed. + + b. Any arrangements, understandings, or agreements regarding the + Licensed Material not stated herein are separate from and + independent of the terms and conditions of this Public License. + + +Section 8 -- Interpretation. + + a. For the avoidance of doubt, this Public License does not, and + shall not be interpreted to, reduce, limit, restrict, or impose + conditions on any use of the Licensed Material that could lawfully + be made without permission under this Public License. + + b. To the extent possible, if any provision of this Public License is + deemed unenforceable, it shall be automatically reformed to the + minimum extent necessary to make it enforceable. If the provision + cannot be reformed, it shall be severed from this Public License + without affecting the enforceability of the remaining terms and + conditions. + + c. No term or condition of this Public License will be waived and no + failure to comply consented to unless expressly agreed to by the + Licensor. + + d. Nothing in this Public License constitutes or may be interpreted + as a limitation upon, or waiver of, any privileges and immunities + that apply to the Licensor or You, including from the legal + processes of any jurisdiction or authority. + + +======================================================================= + +Creative Commons is not a party to its public +licenses. Notwithstanding, Creative Commons may elect to apply one of +its public licenses to material it publishes and in those instances +will be considered the “Licensor.” The text of the Creative Commons +public licenses is dedicated to the public domain under the CC0 Public +Domain Dedication. Except for the limited purpose of indicating that +material is shared under a Creative Commons public license or as +otherwise permitted by the Creative Commons policies published at +creativecommons.org/policies, Creative Commons does not authorize the +use of the trademark "Creative Commons" or any other trademark or logo +of Creative Commons without its prior written consent including, +without limitation, in connection with any unauthorized modifications +to any of its public licenses or any other arrangements, +understandings, or agreements concerning use of licensed material. For +the avoidance of doubt, this paragraph does not form part of the +public licenses. + +Creative Commons may be contacted at creativecommons.org. + diff --git a/dist/www-bootstrap/static/fonts/pxplus_ibm_vga8-webfont.svg b/dist/www-bootstrap/static/fonts/pxplus_ibm_vga8-webfont.svg new file mode 100755 index 0000000..33f2d81 --- /dev/null +++ b/dist/www-bootstrap/static/fonts/pxplus_ibm_vga8-webfont.svg @@ -0,0 +1,807 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dist/www-bootstrap/static/fonts/pxplus_ibm_vga8-webfont.woff b/dist/www-bootstrap/static/fonts/pxplus_ibm_vga8-webfont.woff new file mode 100755 index 0000000000000000000000000000000000000000..74d9735b233fd1ea6b70141e19ec997b3e5f4295 GIT binary patch literal 57816 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�`XCxE*cB+W z!^^ElD45H|yHNbt8Y`--L+P#uIlvZ7ovjVQ&X+@~B~{{iG$m7S!N4}REtI+dSoIyWEXc68p}kZ*aD@Vwe75iNLYFuLrsEp$-Pt9 zFam~(2)fCm>D1Jxc?zW`P**EPO>!3088+C^!x@h<+08jrtGRi=hkazVC&n~?h3{pt z1uW>Gejmo=jV2-^@6YEtzBcP+GxevTwhar;qze`zQYLG-NqQ_T&MgL5nJG|iVIFr7 zF@}C^f{H5e{6*>}beP8ri3rQkxSv<1+He>_5tSBT)~o|6^dRh)2FM+RS>|Sp(`NH^ zQr*yr^(|NcbOQEm?KlE6QDU)FkaG^r7wfU`zdhZ(!GeS@mV8&rEliDP7Na<0%CC;FV~K_nV(pyc;_EuIen1sO}1Ts@fCs#i8Yx3>7#O%A&>pw8(;jMLaHqkNpBK!Ab-vmkUmc}Xzoj%qF)ATEQ0^EXcCt^sD&7VtF&{8F zG9NRihJb$Jt294}CkmN-7~p6p{nx1xkR;_1PS6k8a9 z&TFv_Z4|L4)u7HwI0prm%bBAv^;CV5jH;aX0$|2Tt2VsKo1xx%yKnb?ktQA&xOEFTMOTY0<3L(z_HTo z(41Yg@xQ60c+jS)$N|xLp>7j(kG+JU1Y+H5LZ$6@Clg^8TqDC5la3vj^V&L@^9Gpn zG}a#VR@iKJh^4E=v;lB26%uZ2*q5zMg7K@3uOEdjXDE4pVCa^O#J{@X-} zZNuZx##dq2)FRU%c%rH{ge}A90JIrRI=gk+07zyla9(4GsH+V(19Xon4e*$FS)wuD z)_M3IeL!i;%dt)!8v_K4odnfx zm)|qplQ0oV{{RV=0L4C}al25?$IyU0I3JEtYfnbOk*Z42o8V1K0VT-8c)m4FyD*Rk zgyl*<6!j*Xv9_QC61v`}()6S!1Os^Ba3l|X5V2M$>re3?-_eV386OH8uf#B9=h-r|w2*LGeca;%hOfB$ThTYEuWvfu zZio^K06{>$zqF+RR6CA6qveS~z3VI8px3l=>KC2eC>wb4WW z880fewW)JlSuwSTUt{alXriw#m9anWpo$|z6~_iuY-VwCyCKxG zRUWy4;L@plHVJS-EJeK~>~JTC8TJ?>EG*Z8jL7y1!1njx?5wVSwk>J@+H$>|tr*_mQd!lq}qnVk|d zy@TbUuHakjs6XTzO(1OOI|axwo_mws`?%i#t8H*TMHv<#0Jdb5I-(H;pdXqKA_m)2 z4O4FWmbvZQD{i~d1zvIM4I`Oz_qms#tO>~A41bgA)6(o#dBsDcaE81T&oer2jiaI6a&KE=@2{Vhyk;afTQq9oZRdLM0wC zw+596+&cuG{CBdL%9A#A*~8z*OiWZWuD{JKA>#R6o|GA`oRkTcCsLhB)Vnh?aOUDI z|6DCjBf}?Z&eGSAyPRTDyd5el=+{{cVlzb88Lwoxgtkj9VM1O3XPjlb%4!^(%(Ro+ zJ$kL4OlHU!hE9EUBZAanR0;!p!?RFxDx5}>svm5cZtFDfR;hSugf)pFl%Ew;^ylZM z1i%IgHOI0t@)D0dp9#7EWNjIib7Z~lW=>)ajV@a3P8$M6*?S}Jm=juMs7%!atZW_%A2W1-NOE(Dd z!hpI4u-y>xU15I6Bo335{sNuvk1*Jzx&9d0?PbwYTP!w6A zRG>iZSE+Y(T~d#_!7{*%2MWmX;HKM&NGqV_7j@{2#uyj1d04@c9**KO5EM(>-Um7v zMv|k9iO-ln`@E1venBl7{Jbn-SaA@X2t{5KBnC9TV(gXT0~1+QttsmaUb%+mnT;3W zN@_q8+wM()KNT2=17RTE!{S5s@dZjIFJNKGzVs>b^Bymn85%sdZRx}3-6(uV^_cRej7x@SqgsNDcji%tc%lT;6-5%olkh*#iQwSqr zij}r91ewhiH@Np?_uqnKJA^ zl-Bh1w_@I~EsZgPO8~H$7K)beIiMaDT&!!?_X$nHQx61{A;M>gD+#mdu}-%(3_^V! zs@Zos*T8Ryw!zM10@b7~qOUe=ZR zaY(!wni>(5g_vUiHr`?Amk}2z5TQa~UZ0_NReJq3D+Rr>&s#DU0tYB7>MVMb(YXrNx_ysoKjdSYJa%R?h9@EXiT2ggNFxw+^A zXE6F`SwHYs?WZ3f56QEbSTD*w7Y*TFdzB}Ll?Kt1Rqh3;rO?Yy0 zL-aK`B19%{k@VzArR7~ys@dkcGFcI9hfo=LV9Lk?fyF=>8H{PXjb&sgegbHJi-zWI zm5S>d=(FMum60j$jH)M;k&i1MuPhuND5qrnEk3tz?ajwer~u3>V1aU)_SGbt*Bi7B z>Za@8F-HC#d3-*1m#I=HIlYqU(S3Jz|GTsMx!L_A!K}PbS#Fw=&U+AjuHcTaFKVtJ z49DcMwnBlem9fxd2n^I(n`*2zzljg9#F{2Ntzv%Z{vB5XaD){ zed8Bl_L^=5p;9xS{Y>WlEnPvLCw*C^+Hu8_v3SzWctv!>?RsNQ9fQ4)&r3_S#H@G| zSDZh*ea{bvsGwQPfagL?T{=q-CA%Q!#CbaILoNADV{NIr!nUnBc6t{%QybBEMLjYm zmMH`U?_G+WAfi?!?eb2X7PNhn@Bw$v;#^|5piA~tDE7FRPZVF|B+Z6TPg2;_!J+XAK$`m+6W01S!Bp~4X5 zgxG}ExI(c>DHEGSSfW})7@I^Th)q@$v#{#e<1*Hw3NY3cRV3fi zxhls!^q|V-EQ(N(=bB}n2y$cbK4_=c9YrkfvO#8^043!15I~n>{J@a z+4}NV^F2e%;-S9f1Ff`)AOQvKZFs?&=#9l(pTDOTvh~IXN!^^Y>#lVm&fSe)H z6wtoeuigkv$SfOd`wW7-iz5n$3L|dM(S!M`Cu;=Cig%1~9XCFOGQ_W3N{eebNxz{a zkT7wn^IK-+duWlrRf2vw4L>Ib3TIL&Z#zuiHFMS&ohq-^<@OWRWm__22FAM{F`~9h zfgE7>^yxC9pWU{Eas7DFfcErsUc>53HRi;CUkPqcoJkKos;&6SW{H6-ZR5=xtU1;G zKb5tdO`0_07C==hF0V}|;DKuV{>%(!W6dZtZ_>&r@SKc{dR=S%K3$80nW^>T^TmYX zZ?YaASoS7L@--C=p7h3~t}`&Wg|?|+8~WfDYU`aCAP%McLpqMVHqwiGb|5@<>-iln z=lg=0p%@k=o(|NZ=jVi=3kej;mYG4mBYt9E<>rvT#Al<^hbg|mnUE=w zISMhcEChGbN+U@e{u^6L%S$o089FtL6=Px1yA*B`Q^o_kqWGu)n~KU9kzM;RS$CVOH-mmo6*JD~sC z)Yv=Fn*oM|`8vX_N^L5$H$i7Gnodtf$t+jdebzc)l%%I}_vTx!#_qFZ0c=y|J}lSR z{Wq@0j(=zGj6fmqX6NRlU+WrsfELflw0@h+i@&-Wd%(&S*}26&F#G_22B=X%bg2kv z5@6RFDv5PURy>L?bxhGka8P%R1k(bhNh}f~ph9H?iZ!A13G^d~pW%rSm6jRb6~v2T zGe-Nb7Yc!zu8gr$dfzj0UY=k|j!^OHK-TI=E%7yc#8JQ`-m|8+YFfPO>YvpObP&P@ z9JX}=<`#$vhgA7Ad&r~TtOe)`z=y&HcVs2QJ9Jz<+@pH9|N7U%Nz6)kzOu8dUvlc< z+IDuEDcq`N=jQ7nE6C$S4Lpa}8v2p_Mz`G+9%Z=D@;UBEz_8aX^$vL#`8U<&vk` z&>6n&f}O4zy`)OL!&UIA-1XcTcBcAm$)Ffc&33?!V;?Np0-V(uaorm%cR#^jvN)*J zz%%mYJ(;_Kv(4pi#om*P<9n~F8a}es@E}fifH114?|pNZ>f?(VWz4pSwLh^m(fc{2 z)O{;jo^`=iU(`-yE0-_g4XuX<%(3Ct!_kkt?)7lx880@=`ODX%9v&Dnk-Iae9*!~3 zH@_ZkpN_Y}@##==_~~ptoH+`)EKW6XHoUJvX?&>&-diq$`$T*q={#>=W+p#Y-=D34 zSE)|&Dof!f7QF*$!I608?5?Xr%xn4Lan+mGy8I0)#JNH@(O3A&=ChfSP39i-)#tcZ z%Ds=yWOe>3iR<9l#1(|*!j2g|8QKIExC`|EwybPU?z->ht}F7^1J{@xWNUxH?AxQp zjG;7g>)OcGd4~=$1GrNijYMGEMM``7GP1;#K5$PRF80~kj*bCpV@(auP@`5Mc4S6t zo8Y@G!bXxEWh%@=kB$*D5IMC24#9moMb3O|thUsi`Wwepq_%BEYL9N`(9E2JW<%S6 z5I4cXoHEs_Z5qc;{fJ4lHYKG;UUI`{s~yvP$JDb%a8ZUQ*RWz%UjSDc=j&NA`j@Y2 zh4wIJIR&5|2YjGkIc^2k>_#mqPa>ilfWi3Rgo zu4~^Hqos@W(bWIOqHpZlyO`>$Fp03mB!vLX=ra*&8#rIrfzJ`Srl>eUoK4JNH*u$X zX95ziCB8ri1rBDEC1rKwW;nzAM-M#XyD>%*Qlej;uSGy|DTNxik=fF=&#ZSm3)>c% zGE=cSuJ*kWDBbfin$kh0O7GUgL*>SUOMZZ8FW}U+?Y#DKN@(ljFr}?zN*iK<$oK=; z^C45f>eEVo0GJU%@dKFzv9~Ho%qNPH2F!A?{y$!xxAm|Kd+f-q_XdsJ0`?h4ZDTWP zi|%iK3kF3;=Z9{wL0S~Sf<>|BPTW%T z>%?i!#BFBYmTHnAPD99JI`&L4uh2(%onZdDj8gDEavE*%bYK`%P1oz1c22eUJ_4BLNA zMs4psR4Yu0#EZ4`eBkqbGTR?-lM#IFM{DnIh&GU>jreZSwl{vdr+$v3t(cA>t3@sO ztu^smJ@H%2-C2W+vSQi=&m}a{;x^7)D;>f?(>R*u-Bi!c)3SS#iCP(Xqdd*^NgL{% z`nM0(C6M{rb7SOgI6Y2J!L)6Zp7lvi`IruZkh7d40-)t?LR#LHSzBNlff7i1hDJ6~ z2J2P!6oQN|^OlMm$F&*4C4N)XPT5hvf1mxNjWIfkP4pQ;s0pMLW-ew`Uuj!hH}Ris z(y?atBxiINx=ce6Fg&T7#4%~Un?#{YrkP|0R(+?ww*v^+W2=)VP3W@!>oVM^zp{D> zWG)pFi&>t}g-YhFYK`Z997owcy8Bocx8^m zPAm$@?og;8T^bGU-amH2jvPV*qL{-@@bLregwJK~kgVxl7egA(zIC3D_*XdrLsFsu zhAjde#WK}2IYhLE5+uxkd)?L_L%@oEHOq^>MpYUQK?(ZI7y|K%WqfX|KqUmihPIJ| zA`nkn%%$;)VMSk5YeVTLPXzhQc!Y@&;>@EGe1modw51@Oojza)n7jAq`Bjc5S6OCO z(Qg_<_f6?&myoN4m?u4?-8AXZC^loy4jha}2)^};?4epzb8jTpNp;263STxkSk4tX zhI7S`fuk?Q5%Vq)Y6wZAN3+-Z;o8%AnL23rko(M%*0Yn9E;YZvQZVoHT>L`_^Eo$J zMZw|gEsK7FLnyr{V&+%W>&9(F;g-f|iO5|7TVD-{bMtMc>+S9eog|KbrLm1$QI)O0 ziN4a*ZU$-|i4Ft8gpP0w)P6Ge(R_NZee+(qm%?6Tp@>)+l6{y5M)IM9&J8GCW>Tm?VXfO|qpW!{$*0m|M4Y>Pt=5}AyF}|#JcHi`+oh@1>{tEO#>~2!i zhycKh6ssFd_D!o6rxf*oHfZIrimIxLs0;=5qBonT4qqtfHlYp z?8_+mY$gQ&&SWUNxhque`1~H$De#QH+nn*@m}mJP{HPa8u{cUEbI1uaF30>xXBJq| zF<1V=h)j=eMUi*3{exrksOYh#h-1E zxXhOG*uvu(S1vilDZT6xiqekN<i72rWI5DFHVVpbC#i$~iE|;nsxlS%1>4 zf{sO$A;8)%K5hBsRMnG2n4KjP87~UhFDw8*bpa*9rR1pHF?&+bF7 zIkM#qJ{HB$Q2qxk8kH*WsFWg&fjc zqXx01Bcc$G=wL!z+r=K;j5sD*J}$wJ+d^cSmx7AP@G z-~t}T#K0bsCWPv4);~UMejp-g7}c8ez`cK;bvmJCYRhxM+|%z?Xy6$v!f};{j0>5^y6^4=|W0#3lPqL6|!x zMA_ulNgFmBXk}71&(Sz@0Gl=kAgb=W1RwF8y=bW);N56U9z@H}>SD$sn=65B8rG-B zO8AlglI^oOUiO(jED@CRKvGI8@+i;!KU?#GpN+1b^K8C-ws$BHtzZU}TJrFVcE68- z8lWCfI`~i*E2)c8cLH-4`gDVQ=Tl1taO`olTZC|_yi4yCP@Rq6DWj-NkwVD47tzw6 z&Kd+6kvH>BEPBHKb!B*Gc6vVVJAcUTI7_$|l1x)at}fd#SZwxs=Y~=0Xy*JH!5AeOW0WgH`y>ZNY z@8#dyTlwDmd4N#n-K8iS0IUnpP&EGR%=SFkKCjY!U%Ag~=6%;6cAvW^?Xyu*clMcd zdX~01oaMD)PTpsJ#~s>dz1<*~ynf<7Z<~D{nD^eq_h#C_*KD6{zj4L8FKu&RaTkH} z?trWROZVJqh()FAMy-UdL7n8bJB$AX;(!{d<37~xTIr(fEk*}-(*6dSdH4-%me?BI#-wscDkPxJr(I^O(_Y==I@wUrj31deqt*s5td{LE1eEDp_0CW~4m_#6i1 zur3&F*$~o9Z%UIjdxn;eU_?ShJu~A0he9#o&wRsxPDxjwGQDlGFMt1}-uAtn$*LZ= zY2a@PAdjHUtHyTr+~VoO^tFvY$@jIzqquEtXI69uF|R+ncc0T|&2;nq3O+ZO@$bW* zqwx1nE&VwPhNFtA6kc-wNS}W6RsO7go=~0m{P38edbsb$Gr}TwCAH~Jci>(2=q6)O z$PgUJghN_tthd6a6`XjU$`@gFgwW@@s>JgQnx=?4wB%DO{=5gz4?>$CU_BT|oJ#7l zS_FuzBW+j3Pw2gj)s7N!tJ^=3&7{Wx8`C(fc*cS-Ai=B4JG)Bc=AB6}g=PFg&LVIR zLh^;#9L9HZ7|-M|xfK;J-V%MmhRI<_PL>)H*h(`wjI6ll@UX6YhSxEV3iEjs+bc!+ z>APsRz&oH4Ie^QcZVO|iWqOL-&OulMl@}PUYH^!Ho`N6Z4F8ucXLfJpL6+8{U^K&R zp6r`EdA06*HmZspsc_LL#=OAf$)UR#GsU@c0cJJctDMSa!4wdxl}kcD9Y8Gs(=Hs< z!FJW6QWdd4ClBL{tFupXfLL4+J~(WNqaV48_Y&$ z4ul3P^wcKr+R zY4~XK`6KY3g0Vy1Ove3W76a$)`j!b2SVd7*4gRRT1dGCO^;Cqx>zaU4x~z!+jU|0N zhSVW!3;t&aB@TlVA5eF2J=-1JL^WcBh(}J~w;35*0tDiq^*(ZK9O<$>>9H|zUKODgsd^7g`eY~&0Rs*IhOz`a0+@S=F_yBI=6HUJOFtHmh1-~&8{828@iS1p z@2g72kvVksa}$x;rfx8Wqya~Fu~a0wO2dSQ1@$8nET>(>Ss}luW6HQlQ8m?%JQyfg z0}#%lKNvb75IXrIXDz`q%yMGLfpYI5OGf4PTxS7Q8f|RQ)^omJ5FTK6&m$tei4zV! z<`sDUY7tF@-_*}foC37_!ui{XjheIU{@%Vh0fvKi#wqL}J2So`fy5xML(UXCIg?G9 zB#S*V*e{5K!UwDMgi;6aXZZY(cYZ(}*EU8p{eyIl0oQaZ2y1oJ{#f0urEIU@P#^j1 zgTWqnu%_=cc-2C}Z?<|dvB_tkKr->G2=zycd4r^x2&{^@5M{|q#s1^xZm7>GnT~5E z7&q0aOqp@Gjs$xLjbDQjjV_y=8Y{{RlA5S1ZbwE`Ngr3xo*IbzdeW17!w@!^I@+hk zD><&*Tqz67&z$G)sP9pW5~4f(I|S^AEk{Jr7LQioy-896MuYrfwMP7fappD?8-!2{ zd$N<6TWp`jXo;aJyGI}(uu5Zy*voo98Eaf+ujajcJ0!2>VPfyKXjTQhEM&7#Ygsf9 zkJcy|uXa7_)b@;5JIpvW_qpEVtWisbU+XeqNQ)Cm9lBr-J0V~Q0o$~IVVcmi4rDJD zp9YKMxt@dTPW&7lz-*KSY1m9?!-{0_Vj6Pwd8b;`#n*?g0f)?+q;+kOgAxj9<6vV| zd>ep)^fe?VvW#mR0dCy&Z7$a&N6NXidLP`w*TTiAvcb0Q$HzIjB_C(bHTbw+;qz3- z$x0Lvq2__5c`KurE85E$&`jh2=ReoT%K@TUyF-~}(4GzcAg`dkL{uc|AM$bvkZ4`x zcoQ#oec8$3s-DYvIXC68i#wYwpMg&?0;?gIJa%&I{9a>UcRjwBugiKmijCnvHJMn4 z`wUN3)P4ddLlpK+$7qx*FV8(1y$+H^8Qof0yAdaXl~R*+aC_FnadlMY?sQB}jZJmN zb_?(eba6VTy6w9zZbAX~L0+?YNBupQ6$9g<4T_6~$!fjyI_l}QCXzLa>>6dwNGmW% zlEoIHX18`K(0g0>TLxo|VdvHg@pQd+!XXc%@*zgndooW4r)!0{9-g+I^tF$i!xgyt zdL&unnSS>f(C;||@4e%h*SkKXs-wok)G3LYsY8J>vR`%6G#P~^&rHA_@ip^{0(*t zy9NwdMKI(xq!q|Zu2&`O>Q&hu!a8h27B`HH4CQ#fIdLWV+S?E(6-z!2;SM)g^PM?H z;eO(nM~4$yo~Pd@ysNpaY+efZ@4FbMiguA1#X;=H%wX|eM2k*L0E=4L4D>T%tC1{< zp71${ozLI^oYQNG8hNBecn8Th?=#Ly$j*Ej5Mqoch-M%O{@o1TYo;!#f6dwsbZ+P8 zCU|tW646Mcn;YVm6==&^hBKs+u;{iozdW8_f@`&rjXnvlHUql?T z*g22KdPD#J^U?e)!v@Z1*HB-hOTA0%f+MOyT>(3L3N$4zTm*j2f;j zLhO{y0QCqZsc31?TbLd8Orw3}U#iIZImA6MQ8(1%>S@nc^JJVpp_k(Pcs`z_7lJ$U zE6Mz6yy=(723#U%zD~z`K;wWscXI}ZZbr0}BjUx5#_8rG+PO6RJLx{Pr*4kZDea1= zgFgdd+?WRMLx? zSSwdII#PB>d{r$e5MtNaUFC>C%vT9Be?4|&uX~J9-zNp28BUXeK z)Iy&Eu$BPfON%1X;1%oIZM#N`#pVFDK{QHB|ht zI3bpFHY}F9HxeRiy?xl>(qH>_4x8WbkdZ&UsR!&^+!%}N#6nOQJ7NJ)i`qnE4W&CI zg>%EH9m=0WW?|luzqxx_4*0$i_rt2{NQ!1mf zId>|Mu^<+6YzHz(#B37J@|7xR*72`_3yAOk!EBjh=UZRrA#i-fj=G}$n_BF`6JODJ z@I~0TGw2`Al7Bc${^5KwKNHd;Rx-C!(r#@v&Xn}l0O*xPp2cdWhf|4@r7u)^2$l3pC6=iSAlv8TT}lguZ$;3JP2 zEmnBqE;;~S$z#^p)86u)3%pCt_8JKv0f1z2>f+T2Q3TDeMd@XzAzarxa4zRzPoLLD z>72X9`>@8BE^4!RZaTjb&(Gg`orm6jKJnZiEvmpQDIUulpHX_g8tg@3r*iAmftnp1vkauJ1kT&>tFSz^No1E z=G+J_bD09~-qN-eR&UwiOlVPZIqve_IpwA!wTgQ%$l0dFK2R2VAl?nre`nGu3jY{a6t&pF1T0a zI(mU~dOyxg=cnWO+57PX@t(u&xZ=`q@N?pg@m#(~=e|t6D{65a7Wxr$Ujio&1A{d` zm&~uyia$C|Z+NfrvOM-sm*rwj@4=%9C0e^2lhr43d&W_EvxZ^W1n!RBtobCG@556( zTEyqx*Lm{xHT-?&x;%~>a$Rr8csjot&#z6>;L>Yzd6u{Bn2WQtf2(edvw`lN8SAWi zs1`S1;~vvHcn!X|PCIy=cJL9pGmjj1XPy}A92Rpkom+2FZoNgh^;L|MFHu&#J4UCa zBj$@^_EzAkFu7JQFE$~4PFABS01UPb4h53D^RPK`y~Lq}(fk@hSf9}LZJ+kkTrEh# zp+xx<9g8VkE%>2nKD|!W4ZU0Y)A=Lu{Ly<|Ei!Hy12^* zuc8)X*sw(J+7`lliTNb<;bd?LwB?&H{0S>M20e=JEk}25!|5jdV?nVE^S_=00Abg zv~_+IC(P38dT-Xj5?+r)Kz#t!7}y(dN>`@y%kliGzGW9kW3&JoqjslwlAil!ll!?< zv!gtiYsHn~e;=yVS87F!tUb{M*pkaA{!JI_97YZpK%8|$Ux>fg}&v?5e?5Gt#^ z(cMhhFuV4buuj;qG2HxevUmc%o=_MErYga;r{E1NKdgOn+}f|QYZuY3og=%(IgGw& zmgICdkfLF_xl2X#`DwEsdK)flixzI{|MO&c=T`UB`Q&up8a0XqE=ROES0CfedD2+0 z8@bK7_Q*|&_VV^Dndr^Aa&>w?w#>O1L45C>ILS@g7p{KEFJ{ z4ZErh0hz7QI8_(*LO=wkbN9#Hl>Sv@m`~jM#!O(VMtZCE;m+LTJG0n3b6rxNeKcQb zb*jJVDma%5Zpw4+(ik@9s=GN)!shJmYZLa!bUum~H*QX+_j7}?SR|^kpV6DcZQ6W} zpKsgVJ0FsqsE~;fo>OmC@ANJzv|{roCh2o};h#$8&yLgQ^;Z+UH*iQHQn;DS--&zk z=m~rC@Ugu%kQJJA?3M#FXD}p&dQNJ9^&T z(I;U?cdx*XJ`G*7({D;R#-DG~nCw}72zf^@jUSgCeL6~?fgOEL|KLs7(TTgG*Y~IJ z$J}&x^sTU?7oXNU`V^G-7SF!vIVeSMRkWWxcmCcc*r}>MfH9V8>wWF2XDY8N46~<@ zR!Qa|T4SEq5T=w$Vr0j=<9YP5ozYmdFp6*0P#r5bv9V}3WQvT3H(D!(H|$&s9q&DC z?|MA&wluuqnVw)vy^}dzTKJ?ix-Sn5YJU-e_Co0uEE-Kw5E8(*GSIk=={plGn`vWO z$hYu8nYH?Y5~Y;PS_z#Xj@d!CiI=0%HUdU%I@O5wqi2hd7%Vbt6-UHvrs8>Xnx`+0 zahTrDk3gdDtK;WgoHctv)TLaErbq1h6%YZ%WvkSDl(XueC7%L6Tuk8r38 zs-1&vjuS%Q0knjhl~_(A^w(Mj{YA(U2mgggDS~wgPsA~=(_uj^xbiXcs!5l~>Tqy}j_m5rnt zi0Ewkar;(SXttomy0fK!5yhl;o^Gy#qy*4rY{!eHxrK80ejivLCuv`J|JVyTo z$mK2-dOF2BX%XgIhUlugj1B=db2Xhe+jD)|&8!!28Ir5-FqnYE9dXKl-91qrv%U@f zD-d6Hn9;#N-n5Bg0G^=lz!U<|`UK`QQB)0hz^tggp$fBag8b(Zv#TQOH_03|8(GVdc(b z#`Or)$>Sl`Ng;@yF;xb_Fhg`h#z~o&QDwMPPU0d7EZ50*&V1vmoZ0snp9Qw$W2`{y zj9N<^jiD+0Ig4f>k*Kf@AeC?^^G;|=faV^A0z!}nCbi(S(VPm|Eo;po@`{=OhhztF zO!XBRs0iTkkWZk7X!?)h)L5M~T{$2OFd%FR=1Q>isEbVFB@C-~m2m3>zyYf1B~@ID zWH1WYLcLF3$-o3j9M8!|AmhBIm==B!D4|;QARM8sklzKxvXZ^%J>VmSiu<8^e&M~p zmvL96$-|5Sr&V}U&o7YRH8RX!w-}??3 zJHm$RI$;@x6hUq}L3fi*N!si4fIu1*T)uwR6t#RL6AQ}SCq=-#Q}FYPnSJj+SyB;z zKmlHGM?4`%40Vwa#ETN!8JQ68hYc41rd&7SLXk=FIb0}5G&DA3iG-mUg~b;y6-b)1 z66+v3Z8A!rLnr}v0Y(l1g~Sm^E0}eRvpgHi%;8QXAM!=^adoTi(i*Su99dnL#&OQ0 z;V3$z06gPVB*@8>-_{2qX!KK4DR^uRiL_I*rlEAQkh zk>t+Kt$f?&FnrXERI}J;i34cdbP;-@CLwVEjx{U8U0jlRnjVDvq_lg;vE3nI=V3k% zxo{9_yeQ!ybP1(K9)=&pb9}2OUiDBFxm5HQ5`*}_TUk@zCvhP}HC16#r6^`K`xJgM ziXK(<=Y|aC=0H%DEK&TP!-924*8s8{GvoJQoQ1Gn_{{MACkMcXs;s_l*Vvyu%$|9; zXCCrg9D>@d6F*^0F7Y60GEl`Z<*y*6q6hO87>_+feCc7m zlVX1OQ|>xzi)-aRqdSFP6m~v`h$Qoj9!9L-YwbD~A>VyU@i@ASKj@!a1V#I}4xOVu z%=nq5f>CqxczD!ffpplayScTM&&jTBF~`b)LJC48uu3&9miIWKH~BjA)hRv`{245x zmSNn#e`PxOj1ZG}pTlf>wzKa61QWUE=PfAsh6Tadjm&$PJ*FylCXRpoc`SIZcpdMW z_w?yKgBiwh>$ynIVFisjd?Qv+aTcJfeMtPd@blZs<;8UDjl+y-6rTBxXYP3b^Px{F zE+Z|<1yMvZ{Re;o7j2z!XSJqC=8W>GT$GBU+lj2Qb-WdD(aSY+D~gHmIu=%+QIfY-#=FDff>fsU@ikzx zt$_Kdy0+IPbXO%g#7m*6 zNZp6>6wV`vvb~(-nYa%Vdj!rifZF2w71u`><)UNP7?7}NV2iu~4^zu9{IaG(H4%x> zQqk}onrDG0ac-7qtm8AG5iXd6ZeyYvF)q7St7>d<=E#$_3eL{w1Xj$x*h6oR{gE7e zij<7a#5e}`Who*9D1mbk_*kxr%iu0#IcrUb#TqFR;n>4h;-^c*ezhv1bc$Nbfh9bb zvrc7ai+cPxJqj_QmMdYVrz{5|#U!W|>uBt_hlDT8!z=ED%J@`{P(t1tj!`PIH^738 z6u61ILsjcrqmz9rDATp@s<$e*wfVj2QQ+h=v)Un1Jj>oVVT{D5Y**fyuQcYEsA+E; z$0U1GF?-`)pPt7dGAxD(&u4TzGC6KhnZ1D=7YUwo-lKl9_mC&5<>K?adlp~9JcF)1 z`=DD>u1*-`;VgjIFYrJl*Ba2;zc#tRW!w|(Zu($*T}RZMAz^JpaP1+j^svJ5E9KC|P! z=qef?CKu9dy1AG%uW@MOvsm?kA#c@68~X{hxe_)`Tr1ik&ggquQRt(@SdL6vMI_4^ zt}>~{^SP#VCX&Zl1Do-L9x1NldA?%#W;`}e&G%&mTgW|@BmrJ=r$pSqb3h_C{{Znw{U8wI%)c-}Zk%60-ir?sxcfs1%u#%qV8vh2H)00FelMx89CZhq zr~3)F|6kJ9yS=u)4QTCVlwR^Ky|jD!^0h~9J^|lzk-lf|?A7Ga$DV@kxfrGI*5C8Y zo8R`H@B6?9;d@@7?|IYn?|AR`|Im-X_q-6LpVZ&;kstf1&-~mMz6{^m6b^hs`@c;1tzsjGVy#{~z$SrEvcRa(wGvoQ2AoqXZ zpKm<;kE&;!d-OZLesQ$D1bM;@ug{V(-@)c@7SPMezR_gMe<9_t@}oB#amoA}ooeeS+F zKdO!InmO-R)OEG5rZhXD-mbn!eXq`Xe^7l${iyo5j>|r!en!U(zo5RNzUqCNks|LP zQ~N@)xC+1gahi^KF`1tm&reNo^!?Mx{K9yCdIAgu^LHonN5}J@rdh;K0Hk~VE;8!x zP3HS(x*yZO_*pdf+CZ1}FTNkfalk-7rGN2x(6j&p4KCt`U?2+&^qcfAzKG648))b( z{s<0rXaoHg{fl2j7C`NCy6AG|Zy(QR6O^9YPM`;=J;^|aZZLb}&3}13zo0F7P^z^$ zeXylB!aFYwuO^Q@^`^Ig`MnVV!`4e)q0)$Zm*5-D7Vo_Dju*f@e-ysqY?R*A->`9Q z^7zxwy%oOU)A}2>e*8r?&ht-4>1Xse?EJ(hKl}4v`Xw;nr>L!YDoRI182o$bo$q6j^~7zRWl$VIv#u9ge3#(vuEBy^aM$4O?!jFa zhd^+53l_4t1_%~h0>Pby5Ln#d=6qL9)vYr>o|>7eshOJj(>-r>_muU}L!ZiUs2!rmE}s4RFnl3E5+q_%%rv4UK#VGD`9^$u zha}LGgzo;6&V=X}8NxIL9U7$HQ4%n$CVc5Ja;ZdOkH?5MJ5?GcId<(teQ_bVlNlt- z5^X+|$)fA9X|&K^B>m8PWDB|uiD~mG4d6ZBx^)QOtrHWVH(Ay@h<^HLU&02u>YS@> z*{oPFw-oPN{!lsJB&*N6u5OVrlmq;iwMmbYH-4gxykpHe42dZEO#~X3V>ZoV)00Ab zxY~KLx#tNzq=^0DF6bHZa#teB9e5!So=Hwzxuu1voXdZIJ93v|e(BqZjIOpM}+YiW=e_>}NB+Rdc3R}kR zsE){2G$JW(Pwh)qI9hJr#^z1&Surk(lENx|>aY)h4-CaNKcYN7ks+Z6ucC1wgf(Z4 zcAMgbbAXiDB#mQ1AG2l8C-TBtRd)%)*nei=jJ(SQPH5Y`1s6}UXOEPO2F>B6YUEGA zGq9{@+|%9K%NW$)`L|9i`9FAKMY965U)Ue*vU8b-7dSGQYf^|3+?i+m2o$4J*bX%4 zxGY*mHt=u5r6lzzGv^j03;9NaenB3X{)Mn+=MRoJW|7W!Yez+A*_)WD{=DUOOH^f4 zw|6gXmambV*)G0ZW=u2_Fu+>cmX8U3uBxNkaS?mpYwkx8qebNLdMBq~NJ4-OWOEsk zGqkx^U9b3&nf03_AUGrtVoYIZA@oPUyl=y4W}%_KKx$CdpZuDKMrgwDErowK^hiP6 zmE}WyZ^7)cd5G-btJv)@Q-_qNAp24Ib0IulOO27_H%AK^$6twTl0rXwI*JGag?HCC zCJ!>-I83bZy&U+RfIlRvP0}>OY!T-Hc>(giFuoJ+y(8UfE-FC2fWQ@((xTxTE=w9@ zHT#y1NY6pB_DD)CgS7cSe~pmY&{=nrZ*k}qN}<&{PJCbO*b7LTSE7exP@}NXCLcyu zo`7ZTx#3bE(A!@oBL)jL-PByA@08Pla` z)28tD8(YW9NbT4UNWE{FxRwFQ3cW#T0jc)p%WZT({dGhCplm$Leuc^jZza4OfPxmK zpjWOzUp8VtdHEvi`<3#l3ba)UGIWU*WUX8l)YN?btfG(-lXCSVCKAEA*i%8@yPvn2 zyHvq%Xpo|ig#Rjvd7amIMAVJji?7`RMdAygQ@4)~xpySjIHS*B9oiVgpoTNrf*5|> zB!}H}J7H#wIH$501<4FoK(tehF&Xvk+u2qh`-nO6xHpUI9-Qx^T7@2PzmDfvUBYD* zomUHrWIh0LijZd?5pl(6_*U<5W*k5-A?@wGr zz5Vv&v7$KS>6@15uEWS)b-zbT@z=8%hGjjc|Jo&AkR~M$^fP$>J@FjW6UTcUpE7AE zI?8GT>;~6hZ<{avPDYpDo8}2g^Y;-6FLR$)w$7%bc1hvJ^3DC-M_W4$b(jN>34S)( z_bGR4m*`j@VST59bffT1hKZVdvoy9LCu+9W#>~*hy9TsRBDUL2oJEb;=QC9YUJ-Rk zZy=`5wB|6Ft(l*O%?J=VWwpPawVpzfx0-w2;Ktb^%U{;5s!=wV^g=s7f3rOgVbCf4 z8MEm}`^$6+c|Ku-^hpNH)5@POV-_i3m~f%#<0BYs!yat8mA{P{L%c6Nb!D0pk&(%! z#)L_1$;5M2ZNy<8jDLxaeN2X`$2t|n1lstjAbP=Wb>Mnsj7S|R=kIWkpSSHLb$x4< z?~%cXb1o-*RBP3)?^e2J1SU*$eM(9XwY zhl9eG=!OHaO^A_&C}U0E6NkySGZ}R6K?CJ5!jHs;iCW24+b)^D$Q`xAaoee?aZS|l0iQ->* zAMbEA{|L^gb~1dO-5d_p77mg@BWb4S#kChJc>rfTx&~i=d2)?{C^(4)w1Ikz5+@{K z{-_sPdrm}RK{cjS*+Oa2n_in=CXQld6h2Z&T>1}-~ zQMpm+5F#G}g&KI21DKOF9+xcbw-8)t4Hu?=VcWyAy)n9kvza3{w+-@)UL-TPwwu-g zBk=FlR|$e?keX3HO4Tc_31*JTnaUp+!}Cdu!}EM1E;`lBP7xs9u{UG)B28ZJ0In?; zI{3W76cm{+e_jzJn5!890D#|$mASRKIlwZ8AYpa)-ldmk%D#+{{R>2Vv8M-Cemxhnj|=Jnx(!c%@_uZ6WgLZ>6sYZG0ZkxnG8J(j5!ITntk zX{BlAh={Ziv~LwL(Bd)T;~`4bHgdeWd!ID9mEvXNqVMUHc;v>iOBZOP-z1IWXW(9b zDUFPei;q|2FB*Ocx2W&g*xm5D`E6G;Xr%D^sQ7}%k@gX#UaO0IjK$FL49iEMEjrBd z$Y-kHvRp(G)$`Ol&A3#ue!-*HI}2Q$eyaBQ)B|Dd<0%lMJaD}~WQ-qgLBT|+{Bcd{ zg~R(AD67?GToYK}9r}4sE_v0mhRIiqLaWiS#+RNM*}dHt(M5|2++=!e#OVL&pP02! z)cJhm05~jM2zvV_T?uLXigp7tX~P|ifjA_F{Azv?JaeX;OeF?V%y{yD(54G}LEOfo z_hAl*8~|)!MG6paMvzr(?`xrnL2$|9U*5nd;xe1C9Pm4~?}*i0k@@Mil2ib{0k1C+ zRA4-j+(J3tNam-Is4i}nIsJpTnZ2dw0>EeP{E<0n=V-oUp`m-_^9fo?vE3S>@DRM2 z^sqC$S)sV>u?2N{#y8-!Y*kzj?d)@%TZ!-fJi=AmKfSLesY8H$(|banLu}7qm|L`S zWLckTUgr?TplbCB<`@t-QeWRS#UN^XxK{*A1 z(Var>d&O2H*O_>2`5|7jSFA01{auI+8CUu8>mMc_`E6eVBCmj7-R9;UgV+F0uzL>p zJLd9{mb*^E24A=p1?eyDTkJjO@+rCF9wRP-@6VLaJ=5ZD1AkQEgk|SQj?O?To<7`w zS0=;Ow~_UJ8W>CR?ykE}RtJW_X{Lpz^e4|9aVsK;k(j?jr&}F(MSWqf$~&ypj|7jc z31aJ$FS;dF@dhU}q2R;7b1SOH3x2P<@Ix}6E0KV;Y4SchAJmyZoI>f7C5yY1Efb24 zkNMAG@)A3VQu6%mw#nDBSs@xPnbE5`8Q#af2qxC#&>ftRp2J@$L$3&8pdESc{Fcp8E<V-+Qi~}^cpm0rm^0yhVY{V>;gvl`Zd>w^ zFhor0wFcA1w#>>WVS+rMDB%EVoinm#JvW;%b#@8!GA)=0x+8LL18}5#zLY7Qcz-1x zmn?fSMC&NlqR$vfB9TN)ou*bG#tUIis zV&YKN+otTYLIN=I^X?qObYJ6)3T6mAgT`^r^6Q#LgHI+A}Q#U**!3!Jm z6H60qz*ooEdthjv&2(S%tH=xR<{Rc_**@T#P?#I)wzz^ZN6*s0N3UlCE%^YxFkzybq*r-jANOn4`7V!fQ0OGVj#0KUrigFGOQY5wQvap%17Y&| zlX>h7x2<)qli#X0rPwJU47UOY@W8UV6>HV{I*u$CJ;tAH%dL&+Jz@&KIuu%^<4+3K zd?&K@$(%(}=W~el1b%bwd7E&p27h%1p9b{rXR@r$qxLT*(nGLu?ZpSmPA%Qr4%rZVrY?29JA@PNa z{i8hK*11dOb>wQwLkM=WbhQ|=c&O*o?D%WaJ3ul(5GmIhX_ii(gAv>{6@$#`xmdH?|H0&w=vK1)g)QycgvPQDWI?exFLvogjRP{Jz-LxNCPk`sbb zWlXYhs!`$ya9A~W>F$v^jmyNt8_k2zUIPQdM}c!|7uWfLFT4om2oh-hXb=GT<()J2 z09TP})V3qYoM<{XQen&F5;+t8#UJ+#U9~^PyqtET_TaK ztV$>)*1xzTLH1keJ(A+3>?PB{!IuNBi@fPg1ok|W{4E5^$LbOgs%BmBpjlok&``fZ zHn?r(APIO@P1d?RuRt5EIwus&=~l3fpCZc1zY3+YM3vv!ln1R|iB!)WmdgB)((#co z&g3r_T%_N5uJh>CrrRl%CK=IWam=tZv(Y#Va}}fltLoaGYks?|{#-6bQ@vp{L0;433j@AVz1@HfDyJWkcKQ=b>+=?A0yuK<4 zzlKgNE-v-}5nnHv`a|HM;&b!>`t-L^7K!HgMok1(%McIe5pF@kk!`>HFt#lj<2QN( z86E`21bTyu9@zO&PCM4dm`gzP_c#zVnGzI38lVeKj1MuAl?8cX40;oyN)&+wgFcCF z_y-GqeTrXUicO3vkQQ?nebmbS&L+w_Fj+sO>5Vg1UVmj1i8IJZ5_Pm#5;5&l1YdQr z6tFd_-rQ*!*c$!UJP;Pe34>6MzUNYjc9=n(w*XE=8N4NXumGI^yet3*->FZ~E-je! z0hktc%P2n4>*l`8NZ!V%RsGTKIOJHqgDh|oa>SATRQGqrAfoL~cjRsa)PcBm$_B9f zV2wMmDB9T;&>duqAn`o~&T9ci=wCx^1_9%1{2`q zqTr?X2)&WJ+XQ~-rV!d7bhE+jCNve|aGv!3h|7M+4~=lvg?<#&%zow|1Z4{$_DC@c zw`EM%$V&^e<&mzU$3ZIh^MyG7N+9ZCosiN?AOq zt-JCXM%%E9yU`k`EyiqH;ADvNWSDZol1uG}!*a~L2XJc0K#=Uw1M~!H+yMy^p}JFo zc9I3Dd}X8SGJ&EKdRN73mI@EE#N7^l3`b?4Uo z3ITPtBg=cRJZ)o7rfgXmLwF~j(mqK{sV6tR}@`+SR1Y*img7v3s(`voF4Xq8;gRcW0tmpy8#a1 z7z$J^<#*tzmvx#K=8OJSacv*G685e<$=+%u>RrX8z1K>FumWQ=ZhAR>g(5=|50t@0 z)@c46l*2`SRh#LfrogpEW`F~$YMFSh8m~R$Wa;k(buW9=TxBG_6rh8AuDZx9qM?Gw zJSUXxuUywWW%)eLKC?OyTRS}7dXAQ~1UF-hHjfpWU8_SEV{G`o44R%f>$&pzrnJX_ zY9;HY?D+^F{0USVd4waJ4k{bm2DYar7t?JMwi8g6mTfV%lTcQcZ3FxOplG%uVqrqc zl3kdeFv4kg;E{}Q+&=?%i&Hp5t!(}XOZf9t>9-?t;jF2$%Ok|jPn@L*N4TBooMk_c zFgnv3BFtcposfo#Kd^w#aM!4^E#uBO*GeOpZfBBfl?Y6&GvTx{5N6t$a$1E7lM0BX ztdxgo1|(9(%)`*z6APnwx4iE%3rnlEEd|31OYFAU+wqet4!7t9a|)}7V6p*mrj>fI z4*^N0RRS>8fP{@oUzkZi%0?9!CjAgAUa1b#en=Fr;({qZ#P?RZ!Hgb~d#k8m5?6H3 zG7|G#S8UI6ee+aTOwY2R^AflU%&GK>G%W10<<$$cElS)qs`1Ky=ZGEZ_&}~%!^(K& z1m$sa@pDRZ<8!QYwR4Vh$8)4}^bV>H&CpC}D>Ru;)=)6mX=Jub0t9elEuHvrZ zsp6sHr6c4>&Py&LZ@1Xa;r!F6?Pycxd z8CFcwWuMKKeq6$K{Jm{T3v9&nTI#E(-p&c>@MjXgS&y-=GHK$lqOaw3{xg-cm~TYM zNus>!iB0)uYBjm=CrKvWPju3wv7?V;qLGy9X1=8cuJ-PO?7VzIu{LDyA;q)o>VxLQ zV?45hF|9SKiUhf7xhpfQXrx8C-+tN@2wzS4l-?2?c}-|-#Ab`j zJo+&(HkPM+uxxJlvn!N`RpTa{ldw`L;Lq*|ze_x*lY3cY*1;ZRJ<{EnkhMJ)TH>Z< zpxWWhYh>f+r{y(3%?Lu9ys8CfbT^JV6S{r9`#pKC>-F?sT~O;)yopz>PldgL!53;0 zU7D5Ygf{>4=Q_XDn46bUCxWY5BhI6Sc~^lpS}z08hs?pX1M=EQp$Quy9TKdj>Rhl3 zlIps?)A6wXq@&um6;a0BCdwSWz6!PHOi;7YakG)|=oe4_50Q1OOEGZsMJR?v+snH6 zT_eW&fv)$b&44Tk{>!{(3YQ(s+`DFA3cGa+=PgZZ6L(@3CMoA{-4epq1fRu=BAX87 zq>sONt)x1OXQ$Yu*Uf{M%-D`vXm@=gM^JMg8-6XouL;CaS%N@XTF$Q8I`8yY)}0%a zs(&|G8Tr(UxsiS-v;Fm?TlYl5~mLXJ2NvsT45wVglPj0_I^-TA6%@uDyQ`^g(fitDcjP z@?4qi{$J_tuFf$}hngd?-jHCe7JGTe>z%zOaN6$T=yOH9p4rsnZLUSv#`*byIMt(s z!|>mOu7h`*{6=g1nR4Jj35I~*k8gj^&enqSDo=W<@eq{9B3L5$rx;O`(K88E2vqRc z@tUCS%0Jio%0Z;q!dG{HeaoAn{ zeN(wP%lEm6nh1vooAyw+^Jp{NabaeZbC6csF*gM#rQ&l0e{uziHVWR?AS}PclyKqC zDB8%%XpEvd+a(y_4}R4H(ggq6G3I|b1S4EyA8KA}e!`J^{7-MTlj(@*aoMM2nAA*| z;L`c%rphyJE^fq@_%I_Zk^L`n3F%;o?cU$7;${&6Uk|l=NN``mmA*O z__J{?YfRd6j}zGCED>qCeb+y5(v-D$v<35WcOB#Z`RUw)FThbH9_5*Q^w%KqM?;4U z7m03i(np5DctvmTsDxG{-j$v=dd--&YFz$*X7$CE19_CxWM^oqY>M?7UUO$OnRu8e zBIprIk?BcrIH+^N%8^Qe^gk4NW;7$3HGExa67J_k9FIdYu{uoawCzrGCK`wdMMkww|GL&^sJeCk z5gH_mQI?Ue?a;MeW)7s|)_KKPVl{0jF&?A9Ai`efoz4sRoj1EO?wXV$Yo&q*u6&pA z?6a`?O8%u?0X)^^y}gRPPJ&o5p5e%JRA$%-rT7ML6so0OOsoJzL745h;tK$8h@ z!$C*nA*HnuXmS{ldFyPhf0RR9100000000000000000000 z0000#Mn+Uk92zDDU;vF?2o4E^Wf2GpiNipM!FvHV0we>NSPPhV00bZfhfD{uPz-xN zcV%K`23urRl0w1c{rsKu`$Ps#M7eNijEJ@|>lVO36SmXwa2D6@@UM)qTRfjGA>*ISi0_ zBye8(go#k8|YmXPG88m2C_l%Ya%S50ZuEN;Uhf6bK!bZpnJKOEjnDzU~}tI7=~_|R_=EZ$SLLdrCZ z(_?t`((9k`82*HU_T6>qB~5DZF`O}H_42Q7-Ipx=$L@@@Jla|LMAq6j z>Tt0kfSRsB0{LBj>3J~^r$wz4w~E;gCVK9&Kh5?34x9l#!^tGs?B0Fw!IdnjvaTc$ zx>kIv>-RY|X2Bs3vM=O?tVPm?KT3|NYVKWMx~cE=BAVQ9XOJ)j9(+s( z5JG^cVzql4_VKZzv--6a9&kC;@KjyA@BYqK9exa$O%sMKM5&%wb0k8m^tCtfiR*Pj zCZggYa|Q9IcT>@3^&LyHOY=(bfD>?wkZ@p+nP?I6hcfiO0h;L5Y3jk zUG%lvz&TA$vaEi0i;tK8S(|@4q{l`6YUZMf;Zw1YT1~qI;J^}1IItobKl(jx&b|Nw z;OqS7zyDdHM2Qw{Yg;?wig8@ynU5C$L+|;PsgwqK7abJ27{0a;C;)+NYBgi9ar|5r zcYK&W#HN!$3;F}ePq+Y)y9H5k^j46x#nu+c0S72u0RZ~)+k(Ts*x=mPMp}vSLI3FQ zUtg~a(2?Oj17F9$TOoz$|Dr2rmSk6DP}OM!GN*sT%G##0J@eHx&C<6i&%ptQ%vbq7 zzrR=2YTpN_HOPySHzsWgMQ3fQFLaIn`yY^gfM^0BH2_3uDbj(YWFJV$Go-9J%Ff&v zDsSiOT;5#8;3R2ds&=a@ujxW;imR%tuDrHRO0lWb~ybtBl)c82l|COfIHPQeDP^}(g zcm3hGhhtT-q_zHZBO>De5D+Gt$OJGflo_##Vv{V9&q^av>W+xaL}j9i6aZ1Jl3KGe zEjd%p*b9YS zm>qyZVCWiM8=@9a)>qoX^6>wsde%)hX+c}1F~*~ukbbP@7@K*x{KP`Bh8rSLtBn zy}#D~H{G`f&&2w_!~BL8lxPrC0tu-~)lOs>n=Zrck!B!Z4N)v`vF**btKD_>NPc&w z$7kP>%f!ZjK@t)YY!|2Y;3;g&8Kn=j)X8nH? z=|3d<2c%eov4CCq1Hdl2e>rDKfEQ@^-avQ+{C!jr!dV6%h*GBGC_63te`=MsMLVhe zhdtd&ZKB=uc?Y3($9;+W7WZ4R7BAsprRN3DSNT#^PcRZXCC*FSl=#{EK_m!Bf$q=? z`oKUK3@*rk3TT8WFas9DcGv}bVL$ie;XH~9Zt$+WlsE9Te7A5DUcyHNi!c!>;zW|@ zEKHFjnnkgUT#(!C5#L7vd6JjazU(9>Fts4zJ-N zuHrtP;ZHr-a2aVvlhJB)7^73de>=YbfZs5;|FXypvPb4_U*^7TbiLw=JNZCn_W$Hr z4TNYgpd0i|$bgZdWbDtI1>0^b;pKdV=}AJbh!u%fHHo&z0#}sa%sW@$X532_%)M;` zN8622DfuoXs;nB<^uJUl0hB-@ou&Qw2L*CuNRc4^sSkF!)hcf0`Lq2$ZXc#m-8wZh zD~0;)x~t9$`3^Gy!1XAlw_fsv2~kZa#p)3P1c^Mf#olQheVvZ|Z5>xXfgmv!5Z^SYn+`vcj1BLK8G3;!V| zQn^ys$imjRNzk5oSo0uDQV>n5m^4Cc z`s2*hy6UfQosDy_mUOZ&3&b=$ToZ3cv*XeU#D+ufIUGJ(^hlBIU0d+s=A0F4F+i>o#mk!A zg*+^=K3ww2>gC0O{yOKj?hI08 zs7?DhRtnKWxU#ap1^0ZJ3V@H%jl9h|1&}SXnn!_xwia=mBLj`n^*(SQ+c`ERiSI~V zQcBKI+bsa_!y_jKRA4C=h*i3!IL}hBCE=0gz7kY^xz0(m zhdSQ;Vy<)~IJu>4=H^=@Q5Ooi1Y{vYt;eQY7)Xaq$@M8sLEt(Jx4?0^AZC5@+N9%6 zP@)FwmnOH2u#Pg9=4zj&<)1CVCa?-Qy-Edr%9LyYV)9q|8Z>&=H*l4yBLL~pns!8> z!NF9cl`6K!n+YQ=ng}Ja@`H6@V*dXhd>{dMRRn39;v5yB$6Ubre+KxIO+;IC2^e7H z2nb=-cEe*MCC?@nVGgHBO97}Sc%W2xDr`m6SSfZ|q0$?$@}e2@*mfd7gvU%U`&<)R zt{&(2I)>wfBb?%}OMN0`O}}6Ftl4Uxiem5n)cQBrnHBNbhDoBCM8uxiQsFj8Cb|VYii|@s z4Zao2kwh6pKZBbhRobgFy{*p$0?8tZ5pYJ$DX`fZE+_1TAA}R(t$V}U6E(CY$~1yG zvuSOPK&lG?F>=?c9dAJxd`SToREOF)p+##`1SAkuHM#WSe{&)-M@N{Ed=b74e^6#y z&}r7~XJnGIg-?nL;4oAm`Z?6~%8rgq6NHi*uDsbkwTkqMtMZELdVxg}He+((Kz z@*{UpgiL>$gG-ZmagsS23c~qAI~@z`yO7yfD9)u0=S{0mPsh-a!O(&D04sCY`mk|8a$_CGATeIh41;E;?Nq8m_sxp(wj4wQ+1)r zW&eAWKF&BKb;4o29?LdRZ*N0`?`L0ot&TG3S2VXlEakZjYue4UJ?o*8yk!wy(atsx zP4%-p9Zb%fjup}+#g&pBW92*&D*6ZBDITZ!NlK5evZ`Fj|7m zW~bC@2#3D2R};Y|TOQMLYXTxi-;?RyX=hTWb=f06{jmYUU=G>4Tzxq2&rxL@}8sCjOvB7+A#o zT?6au(B6i2^z@s}g(^_{4b)o&{$Xx~ybMtgjKafEZ_k&avH3vrOl)OEXdK+lKFRF= zgJnSe1kD@btkWVY&D>=(k3YLB9zoO}n=6u#t#OwvhLoeeSykhz6Mp`ua0&`ufI^ju^Y3QYw9+QkC3 zXr4_Gj)ub z%TIV&^%C-blG`dO=g6GPo?T+eg zk|qh{2G#nVH4U6(j+(Js(>nN=ilkk$juGzMsr>7A8Ilg#=P$!cM36&%)kj0c6Y<_k zvNqFD;pUL>uITWZ=RNWy($B!I(-GS{sq7<8zuD?eCS98>sG!pPBh<{X25$)kM*f!Q zKZjg5EhXq_^a*}KB+VsJUtT!*q9v-X-6EOijp+I8ARRoP>sQDz-R1cjir!YM!Z)wX z&K^0u8!v)K(LrPSe&z}?^c@u1LfUoS4GT5NQrK)RERMx1q(e7QqpCpu)oC<;Fl6D0 zH3}8DHI%woYmqXn#im)wb;eX>`Jx6zuOl>i=6ns**i5`zQz)@bF;TR(?IS(ckNlm*by8H(?P1PWS#s!O=1I-%~dPc|<9;z0@=e2uhIlM!p+{RfeXPI5v zMa)-XYWsV7fwm!-!=a4^osE)Wc{`k_)R)8Q2zPn9D0M@=Q`-6{LsPv;7CJHl;L>^c zJqWt)W!kd729V=%&hncHIvVRbhPN+io0z<3ad>ejTq!h`(b>HAdH(^qMyYjO2MUE8 zIeK`P8w0pWQP5sHn`O>u1LyMax&A3Mnw+Mq-V23t_M04dH7bd=-#YROEL+z@4gC!n zXHTIVs*RRI&P!5hmep9NDS7vIr0=;_Xs6kVJ&D;_qnMr8{CF~ANuA2}Uki;rV>{;o z&f)%OC-U%SZGzc!sJ(uqA7PX;soEwK1RashO~^`&WzY*!qkxsCiGB`b0aJsGYtGcR z>DU4AU?4&Fp%}st43io7(?PgEJk0q1Hq|+9uDSAWZXMZ48TCE~%A)&=za*g~DjG8O z&y3UyyT>eP;jEX*(Xw9s*${ULKqLW)0i#V%MLkU)e7} zLnu^B>Kh-(Fo2N%FsuF^rFH$*EPf*0P0*m-MAN>QB{7n%@Ocoo#UtIN)Y!5=GHo3&ewFk+f9p=b z-wB~U({I%i)y_Lnwc^Q~*0ABxp-@baZ>(39W&M&{H?Tqz+Ortsy`ufqm51+OiAq$* zss&FQhs`+O@+JyL8ZPsC%B?%?dl@Q&NYbHa;B+G1ckc~wMj052<|Px9yOQ%Vz69LhpZ6#D>TyhNU8WsA<(TBU=I#{Q?|_)R*E`67d$gT>%zs57ACcKg__pkk_mHc zPc+ZW(wq_zLo5Z{T}&rsRGCcK6XN3W$+QrB&qP`Jx*~{``b{LfasTA^tkn2MOth zB+LG3tSb~AHyg!lwp|tss9uR{b$E*4B}14aU5Kegf?JhQ!`L@-4JkW*{Oe3oD-t4r z%dUTQqUA%5@#y@Gi>g+=#X`|J{s$NB7K7#|X1sfzo8>Medw$71#8AiQR6#k_dGmggL{apVER zFCE=69Hfxl3{R$WC7P}3Y43=_(WinW+d>X9B>S9Ho(jaNSJ*owjc1LpAfGt_QTlMR zlr$uEk~|MnJ`Bj#M>r`O#7byDb`MxD+Z}?KT(3|9>0sNhGU&CoW8ns`CQNo|bt$=x zt`Dk3n_7#08kod-=TNFZok3~~lZ~3?$Hx`Ls+b>zxrEvzD*)wbS*u0mw~G{CMxr@^ ze*Eju{wE%ZnS47dp9>kOByDDoP0UsTb%-d4*e$l@&O9$ZQlytA>B(Hg1lL zOAag0axw$vazXS3WuxGa%v#2>mHG<@v8j!hlz)zNlq_pRtG~K$!^N&PA&(z~$@p&N(wMYWztW_Y1P_1b9Xril#`WPJ@6XZEgZpv@ z$@r8y>msva4D^^JQK5T+uRno6Yz7Ra{HC~jU-oAD?obW5#=Vtd!O}yv-C4x$Bc`C^ zB93nA%D?}(OEqN^(?kco7`7@nnYc4yiju>_wsRJ)*?;n-6U~loI?sw$#!T?s*|AN1zG*NT?Ll}&nEv@tabc|1%Mp`NSTe8y$PUt zK=hc_bdr{182IG>u~z>I6|+!=K7PGXStql3g+u4v;w~H@ymF`6V0^vTjT`(4qCDPG zH!#71EER)N7ot%r54%(jw@8;$oiFBRgj@z8+59`75!!ZG7JNB&|8=@>?*SO7d(I3B zT498aU0ROL1brNX!IL5&b}IMdx+Dg$_i;nbP|HhmYU3pP+8)A|ia-STb#OEeAFTQu z#0MBw95Z<)B|&BmpAjJ2JR(z;^5x-<8@rG9tzygS{qtfcr}fBSZTM)@fRN4<3Rz|7D9)~J3XMX&M?+RJ z3gL&x40qy_#(mf}Jit4G5myoxQ%_h^YSw7UXn6t`CCUwBp}G)iCu; z;bp$Z&mF{c4S3tc31&|Y{n$Ps19O}jR=~XKtxByfphUaBGoSTkNG?Q_&(EG4l?@HIV-R8$PnJ7r!E zlsF!+8(jcm>7iDgvr$AmiuQPdke#QnP<5%RW=b`&XHNnZ39y-;)U(g zlUNb_+2SPniESr?*nAUEkRN62ra-I{_!_Qzx9L|tH7NAZen6%#i)MQoJ&1vC$K(j1$n;N$VSDn!8-8?cE4ac_UV75UB)mFQ` zEoGoC0`104(`k3!nxlfM1lt&3Px)DPwK-rdHLy)**+IV&oO(IQiv0hfeKw2nL*!)I z@G}pJ^PLy%E#%LB|MSy9M~>0oeANB9;#Uh>F}eK-?3_{bZc%d4vQTn)SlNva=I05; zUj#|RkmOyh@Keqiw@X;iTvJ||l@u5|IA8h1Nz3mzVtq&JTPIVCwUp-&GGwhzt$#3D zSJB6w){oPUUa0DafqpOg%F#Oazj4&Rl1#ggClvkrZuo}oTv9byHSCz+@7n;st_oFm z4_1GrIHE;C*9cMu?>GD-XePl?0WgJM zGR8z3qNYO*-CeAjj=B4bAR2eMRN~A)&Ah`H2rNp@lC0H_ZK)Oms|1Uud-h@1nZ*t> zA<2_Hs7O}+A-pKJu)}n@mkS+Fz1MN@$akd1_EZh|K|YOT+Vl@J_lVNus;;FV4BSrKB`aPxxOPf=~ueVDWJ+K^g`MG`$JH z`^vD6q8Ijy1fad6KGXoe*f368n$DM2o!&(Y{t)NL-B;h$uS(SJQm2?G!Qt@~R| zyzw-Xf0eGZ6YILP{r%7;YYm!Ir!zdzFuMAH?gSpWIi19};TxG^zb#2Ta!c~nkK+V| zyJ`nL68*e%s`G^F%c{V7f5Ol{2kSPS=DGW2(ByDUf2qJR+%nL6n3@MuWDYfp{x__{yNxT$> zAC&?p6^1w!0zXY0BISixqQ0g_%f~{@6GwWzp*OIGK5mg*X94Go-X0x@iTeFk0*STj1HiLsN%-;L zL{OQxD+1+wMKt~v8ii^GF%;qjQpR9WX6K&u-*-Pmf-MW)t>faF!y{)1^AlKEgWJjj zLiq;zb&jJ-1h33a?=586QDAa^hsmJF9ycri>F59(tXA`OnZ5Dnm2pQC&l2H`YEO~X z&nX3JLd4u4-KKaO$Y93z4K8Qi4a|Rga*MoxI_h23qu_(rh3u-ONMh{Yhhg}4MEUIw z*ksQ<);w$1NKe!8Y%9iY^7|yZJ=CiT3N}Km$`7rRVagHQKEFF?xb~1#;s2Sh6paUT z>qC63By35>?MDw)qsJ<_v_uQ|7;xKmIEq#^8S|Eh=F>LsXD-rg&a}*Lg8*XcV2vsutIHL$#3|Ql+R+9XNLNbXl$~se{M}W_5L_LEZS3-$=y-lig9h z>4FQ&pEPTzole<-_sXuqH-camV!FNsa^-%?kzkxfFXF29D1TIfUmCD)0+G+zy*fm& z?B`u8MB-l|#0>0SN}x{JpuV3I8$fMlJ+F&1k*2Ic-G7JZ_F$T03jR@SvqSvFrIoC8 zNuV7s0NFOLPa1%<5CfZD@=&dPNy1o`=s@O&3~K<553;pldpV26x%cVzmD0e%tRF&- z{W3+_U0O|4lNJ4Is@Ec<0!gWO>nkoy9wt-cizsYEmL38*<-z#AH7Yh3NsML#_9f7X z&hZy1NDKvi@^pW-seN^7U>OAa;Wwb>yA=hdZzrie4t!HUOX#ZK^_02D_C(U38*tMUkSL76qXWkD?oq9qv+3M-4p7KqDhBvX8D<7?o)n(L^-oVe1 zhZj^=vyX86quNNP?1mWMlwJ1 zNd_Fve?KoFN`seUwco`8I9@1Mc%o3ey55a8gPQKH%>7QF;)+W8z(_kC-j*Yl~5bcn5gP%)*nX2@(tpS6CBlE zmWsvtY^ryyLachAA;NqK z)teF+A!vUo)kk=-yuYg?5c#i)s@i4^FY^+OHr9@7=VOm4>YLm|3mf-%=N<|?$p;*0 ztn!1sv}##=iU(7!x3Bp=mO^`HHH~5DHq@NNvfH{mDC=Y?ZjGx9;#< zeG8#mo?fw`HN0Af;F_0$W{O{-HdvHsc%&Ay-|xyt26aPWFY0R?1UoX^T5lI5lMFee z@hu4n%i-;|I+Enr#;bQ0m2WQWhza}0)W^9qC&m9GKDK?22;hCghPwXANot$O|d8`{Qz%y}CxRX$Z-8sS??_LkM*s z75D@|-%#dmUa>kV$_$7MC{H60aWaj_$FVqPN+Px7wIo9#Z!6GZT?)1ff8)qSn*!9k z0BuE68P5*kw~s6-+2SZYz^1Gj!NJPXzp*r?8OjE7PE3QP#a8hb!sp4*Oa1zu4iWiM zne4O=do6s}5mrsMArsHKHKvL$QPd4}rBQ^g(jsG)P8WEQU^>w*>m>j3_{ z@i?q7yiU|+jwEUc05q)Xn_|&dH#AVmiA=jUSt_(z*k)}}&_%Y6YO{UR@=5NJ5E@Mk|2op0l=@)i~#-sc>F+YuQ zrUP(8#QM$v(T^u}U(bcNh2-pPe|%RWI>zg~z_jam?C1Q2=Fu2W`ME3ka|74Ty}I)=M|<%1JpUjHdgv^u!>>TGhuEF45T!k@RO!VjEe}7G zn^sj1Q3590B!m>UhSAyFe;*c1J~Ev<+S7Tw9|YR-S20GvnW7`pYAQy`>U4ooRvB;9 z?iwQN$Rk#(aQ{sC(a=5|^5at+BoDV{i9e$SeuY-%WKJZ)ylkObi+Kx_U?!e2jgI^v zLtx26Y&QwPlhqpoG@v(?1;JPzTY+Yd3xbQi?T#`j*AK1z4b{WoRZ=xPD&WjkbpvjC5zXjBSIhaUO3*Uq^@<^=&Ip`8^1-? zm@FCs(Q!K~axwlnp)Zfd2$FIga3dRy?73KW4ZPN&*et6P2Hp}`v(GniZ#-uOdud}! z7N7;)UUkb{#Psx%L$@ncAZ$|2iXa{`g{?=LhU#Ybq>rRwOBc67B(3)NABf;`s#CS3o0W`ACKZbP z+$4k)RDF`JS{vIni22SXM2#TEjYoRz4pNqWbM7gx!SPYsR_~)yR+|t&GX#IWHqG|*C zywqlHT+ZQ?8@y#j$*;7PQb1-x5n-DuM2};O2M-aZZrpk+ zt0&*U8gK-`uWMei+C$?w4I=3EMb+I=sWha6<>Ok>vch!=FOx;E*3~c4AYI@Sy`YSh z0Ak}8KJvv#;)7gCw(lWczG)M~2XD&-|=)Vzy!|9I6-&4gh z?A+4|ITKbmZxNFD$Y9wbu0j;Yi5<@379T^zrVJ%!pODCyDCWgT=Ln#|t31Rn@Gs&+ z+8peLDrPI7!X7ryofg$bhzYF|_W%aP%MT+VWIkS5m7V56xgAwt?6O=Kgz;?6PZupN zCMR_Q#{>mRe@>T1MJ=PXdLdbX>R_QbB91b@boC%QgK>AUDeC91H3f)KnI$;36E3>4 zEG2v2~a}FcUfxO@cES zn$cLUR5x^C!dY2&geuLBdS#Zn@=^#3>}tzq?$0M-BEAI+=aIZy=4}kRG4k6%)rtdF z#qLd=r8wfE3#sjFqB}gB*>o!4pGBR^psoS!n{OM(au-NXV~cGEQW%;Kxpf_4Ri@sr zYSZ5q6;}}+&$!J^`9Q}9x@=K2;6Y;cCr$+ogH`5@$5Ni)13Q|~J-r#`mDI*&TZd)(i~^cpYz`5{$+e5+fd zXd1`DZu~qdViheWh6bNYmVykk*HoS)0$M}6?C~p}JrK95j!y^?dtf0Bs?za(9_Sn< z#;YomVcTXXS+s7PwlLNVaE;61n<%o_nzYnTNC|y+o`6itMEg0^+n?p&DstpxMQq}o zcDILUek2VanX2_;QQ)KR0|PQ(v~`3U=7+=r@qHFWT2Y+tE5L-ZH|n2LO+Jc2-oPy_ zE?g|C0@}1=VIq+2bK-e^Wd$klCxcHd2U6=3>(@a9QeOF}1Yab2uuzEG-)q>z{A}>& z@ID`gJ1mVTsyII+RDSA&JRdb(h?AAU8rs?sChQ{j;G>3Z8IVRHj^{VwO%Rd^`1bUz zT0T96fhC_=)`{n6f+J}nG?hNRMQkl@h+6wX7b!WYY@BVcunB3fSyBUOh;+S1(FcA} zPWSF%;;w^AE;HW0At>b{p}b@@v|;fph{UeTK^H)>8SMG^8fO6*uX%*!?i3mEFHNf- zNe618^|kpFC~Z~t4@HRG(%xrH6v~<;76KdK!$cD)&&NaBC4R8Q=$K@>LVOjUdGk}n zV3B$q_Mt8dhCDJ~$@x?zv9vjcV7E3cQ6izxYn@JvujfQjIxLlhD30^^j3NGCMc1=3 zcuf(;v*`DO6!qN&rV@ufK)j%VxPHCvlJ&6CZU&V%3o@(=*QNaQSPXpXNMMjC2n-`a zC{%f4K`yDPn{2)z>_#+lPJCq-WQ4jx3b2Y(HoATjNd^Bbs!UR^P$ky?dD0BeaoO%v z@*5=0*L>6@zz-rsuO9C%IRFGDGn&|*JkdHAZ_rxB6kb$xe}(w3G7W zo`Z_LsUFZ==zhVf#NGjM5dxlE{4LOuTwGY|%<6r21a=FUf|X z`ruOAb#u5GsPIXLJp05xSNAaIz3#8{Oa1&Wzqn&6wNpIy^96`sF?_XOndb*ON2m9d zT}Lop()#>7)Uy7Ghz>x=$YFI*D)ExWDi#r68R=oA#On?1dYHpb%``ex$u;kZZUO^m zdj6TMc$($E{aU2o?#+NlFDZjIJwY-B;e-KK#)C(obG&{5)G|g4#43++{S6pTT^n^a zX+<4V&?@&j-@a>ssw$}jZ=@`gfFKq_$!2WXzV~*Bl?LH#NUqO)6m>93K)xt>MSVeS?DI4|pS^2T@B30y`1LisI^GM_8(hQabQje% ztQB3Un$611HZYBq<&4wXg?VrNHNZ=l+rZl-C1@B7DdZ9!?F(~GOVHIY)i-a+B%w;D zN1?T?&Dc{{Rjf3>RcPHS;z;Rpab>W}fWr$ItMeeuh!U6xc8))N1?ePJ#stf_syo#r z`4HqAbO9l>$|55QtzwI+7KkiY?Y~H=r*#Jo+vVdzV)rm=8tMDSR!>pJ26Ct(hG2TX z1h8uGEK&f)9vZA#R_D7R6CJt`M|G?=AezDf&JwvwqAEeQ0RX#4V(IjitP6lJnNhWzt3m~|CU+beJjS+Q^+={3q|yp{0~Xnq*~~`L+sFbem}p961y)Ut zJ6PcI!qw~c!e9&nW=~D~v3_J(g6GJMjWi&h4BhmE!A7F7VA=u~im8;e+}wW2ntr!{ zFsia_a$*vbQ7BMiF8b*rwjU$RJ%g=&fbxk&1pZoReki;64ed40WmM7!>E(Ls1s zN1gWDxVgOU>j4nk(p5vtL#fSd=BA^d_SV7`CCjIkYn@=5R=&!cd*&))s8Br7$ffhM&$gUtkOImM|W0pa_gqN zy1aGn5{P8p4_BZ@wPW|l@FDtHLkTiCU=n)2ybvIdHKJyoqHtW0U4&E>tIfGZL3%vU zupJ#+ng;>mXzRCijN+R!;$2n7n;6Z@#`4LhI#_fPjTqk&0^&8ZqE$h(#AJ~2=ps;U zb*kwnyUN$~fJR#C2`>eHnh{i4&aVN;R5do^lYKVx85j4}L>Z1M&nPSe39U!7XQ3DC zN$?5YD~o@t{5Bedkxhi#CQUQXdmjU9;wn6K`LW>tM!XZbG=Zplew@5oD37vA+#NTF zik1@1O^Vs$sO9m7xTmEFvJkau44D4b(<59UV+3 zP;D@xB(}C(wbl{6NO;F)jMO28tf3s8j_?XLb0M%!q@)D-5G7PvS`!t5q_egf6Z9=K zRELrGqU~qxqy;=fH$Jl+&m8gt<;|tkk zlE|v7kmO6*T#lhgJfnR2_IxV8@@-0-cIm+;Y*W}d^=R$($1kn+5@iZKcPjI7JxLxV zZIhQKr}Kwwj(dQvJlz+e7tFe^vtAsgFey_FTuEu{S=EF2HcAAB0~n)AN#vA=Tt69D z0^3wiQeIxTSLI^Mv96ne<6PJWjj1VnshbXuPzk-8IDJxYSymGYM2Q7+eAKDZ5!FwYGOuqF^oUfb3cKD+5}7uDMk%l?P$yEb zjTPo8^Xi;xqISCOLm=KCN23gd z2SO?tF^4VBGFZ-n8e^%MWXEVE{uPg1tM9i+-4eG>a&|<@$0sulE?~}|3&-yVOgsU~ z#NbHQnbxtJlD|?5GipdH{-VBd5aw>o8*G>B<`P8bs!Xo0l34ro$1638XBAD}Wc_R_ z2ZC0rQvjaKwWf@(Kr*>rin!1xWYHWI!T8@5IB6!MJRZG{qV=XTE1%7PnO-9Tdl?gE zgii~#6WEA`m1cq5QEVEXb`r*;0p5Wsi#{s&dExM3PZfAJ>EXt$>N)$u7KeCnYxAOsSfU^7mASQop37ZXr#)s*5)?M!z0W=+*_C!%(FKSAzm&9iYGnR zSPexi)A`Tmm-7BPI;n6dxwPu<(F2~hC-zW@@fh{T=M;&pFlfl%C#Q!?nv7~>t`u`- zg$E@CsR1Q%J$4P@d*o z0x>GuIeXW%!N3rCnamE8yv7i@5j1p>%%H~`wCK`CE^sw9yC{=Eu5)gJz$7A{XPenE zFIhMJ_kmDiiVhg&^O*HXUbmT8zae!6+sJtkuJq$pXk9z$#VF0@&h+UaEj8v;t=>A~ z@nLcC_|2L*K>-zyG#r4j1t;bPKnWOXM0Pk0J{^hd%rM?@hmEZ4>9CcK-LIXod;pqZ z`N+AQI)G5U`z>X}-qlUdcj1 zb3(W|#+**Bn!S_pybGko2tEy2g8gn0-tkU(i7_ub7_>Ax0BF^hWkNpbs{_+#1ovyO_|(H!C)!oC)8*>$6=fVleuhWvSTWGlSXmq{=?3L zWw7gLD;I4(PhQL7;1Hb6iV4J65qOM7!08KpFFVkH**nu8p@n67PQsZ~#KZ4UMo;=g zhh?goI`i+7wq*&z6kHS*8@>_WH7NG^Hg&Y<2 ztss*=o5@O{0YuvT!_2bXBy_Vicr4WLVW*^A6p+YL3S8H|B!r;Tq#Rf#HEJ>yT%eRO z1*ym6V7;env!aEdsmXV!jh3*;kkmNQ)(J=njB4w^9W%@$OzXkVZ|~NTg``UvWAbjd z)K1m4sREHVk^mu3e_VR;#Wq7KYK)+G#sb_x!@9yzQ|1 zY?(!#Gr~Lc7`nq20xbE<*1ItsePwqLFwVrT71=d?s?tXrr8uf~2k*-9t&} zLJQvKXR>I!>!n2pOcWvXJ$R(Zqpg z>Xp1xC*#h?C}-+3IFpe{0o;yX{5AO45-#ORZF`TRzbD#e4_l?equsS zrxW#9$R{=Bjj$61TgSSy*qC@r|b+?_FoExS{7evNiz&IY6?bD-mQ<8ozluv$JRfW!qs1M} zvJcuZmYqkU%y{@Z7JC!VHrOO_^{l-9VlT@4I(nc+Jl!g5y*N_q!wcE_gg7)U^ z(Wcl#2j9H$Z?lE}rRvRfc3;kp!oi+&9Xay11T3r}Y|OG_t2O__Dq> z&a_*3Dw)-WM=;a!Vj}1t@Ce(knsiwbg5CU-8{`@7RZB{j6d+Fx^EPwUaA}jej1_gJ zbF0s?S5(*SHYm~^v62?9aV6iF_o>Bp6kcshKdW!*8KLC$5Ys$4*4A_FamjvMgnT%I zyvOFl?;2}4%kx&-Zswt?pxCPW&YH(P)`R3vMhYvjd*M1NYuw^=of;z7rUEA!d45cj zlljC_FfO&TJwLIG`P_`h3^%er0*SD$#IFX%nAa?$smIo2RWhxV4C0sx-i|fEWhR!q zL?khA>-w?X=2MHr4@IhezF*a0s9Fo9V1l-J#x7#O)CnmG`%5447*7bWn)m~3Y5+Gt z$iH3!2ge!IU|n5#xq5QGR&>7ycl`&k7#8dqZ(DntKH)#!ib)*Wi>yp zKJGY@5g1*fVrs$BJ_GGyB5{)GJps3|eQbcsUU3Ual})=D^W zM^p-%(a=)itDxt>V_~ry-$zxWHlykLq;u6b?~Ko=$ft0*^m)K2xg{WE(s2SG={@H; zHqP}Rh>nKONXuwH^0?V)X)IIy2{w!b)1kMwu_(tVc|dZ25>ryP+XOV_90p*P1sY_c z6IA-_?&LqC+Dc3HuhQiupcsZ+nr4kk@`HH)ZqyYEsVgGm8(6fE@={bQJX>zyq@iuQ zcY>naQ2oG#7Gpe~3~0)|!q$NyRj3*;i1Ui8M!Rme_&q={&}h|Yzb>L&C)^3&1&}Yw zd(z;A?20KuK>8RA2qoi%pVrE;^g~ljf1ExUxSp!nGsN|NDHVwWj^=1enZ(auqFJTuvUpO2$Mcr<$*8?{B*7t7A<=(@}hx{&&0xH$XV3Akk2F9M7auf|~ z3)MzBu34xxT6CU)M>lg-&yu?~DqUkkon%yPm9*wcJf8bl=%^rd@|qP~+lE!pnqVYf z_Kr(@v@#kc?(s8zvJ7c+X;F`cQO%|6U^2q+&rf(vR07wCfy4%gG^n$IEhKsNvR=_B zvHDud5{p{f^9N8;Y~0N@K!p$PUSVP9G3?sbbF3+94lzO`s z9iReU7uF|XpQ7BWKnYT_7Y?jU9Yl>;6w(lyeKSQvc@y1GI_lC~;91)+sfxKIvny=d zD6ccQ&JaJfcE3QRQhsJ633g6S#fiR5;dM4+rf%eJolDwHxbBsvMEz@MkbDhFfyDtu z+3d(qiGwy)yJ=QO{ezSRs+g3w-kiMDp{+G+EI5tN`)azdBsa*Ju9haPI%!c^M@p8x z1Vp>@9~_m=)6Vo`-owWHzEU{M9(DsG<87y&E`}7gng6yYsI@}}&1U-o%v<}ApGQ{RQKTd5LFzbT8& z#Bj2{ZWyJ`NVPG-+vJ{jfOYAThy>CCn-=_i=W(GR(?1dx@H7FzGLO@(#?oW&%lv0V z=XT!@SKLWX@wZFe6R8=HzC_T)3yB>}jYq+yNP6);wo#U=z2OnXK*p2!+{R57xb?~%r^I@eu^QgJ)|hZP3nmf+ zeFG8R+EhsW6=WlITu~Db!(_0M(PnI5qXPla&5U4XN~O7T};CpQ^p4J7D9%Y zl^lOE=vtLcc*0ZSvsl~+@=&-y8H7oV+9yGbiUp@*2t3C4Ev!mYrY;G08sOYW4>F!B zsTFND>?ov3)$KN(rUJ)3BrBx|VuqspV*+IvVJCy$)6~n+K^Xh(av}mVYPR~akQ^3k zx;$(j%tPB__RDCHC|y}ke_*o1(V+OI+ivi+vkZJ3116@-{+ zDRlb=IhhrX)Ew7g?g;uG0wy*2l;kU|)CV8TzhP~1F&wuY7CU`2&{Lopd0Vc|E*@7< zW${o=g}EhZ)hBvA4m?3x3Sqzp_q(&J}jwEZHI6}qHFa^g{Z2al`x}q*&B_IFV zDQD?btIv*H$}J!sf}xR(3~?hf%5IMGTn*SOj4X|DI30OeT2hxD9DZJ?GM2-Rj!V2_pe$}J#hAd)>g z#wiJ+B{LXz`0ixSg0me_oBEF-kSr!`e(JHNNMMS;ZE+p=4EO8X4g1?Yl=|^dheuAz zeJ~ATL2R0{OH^tJu^JJ(7GgJum#uzB5FatcvAO!HqU%nx*LYmkJDavu@JuqaKMM|o zZ~_ByhV~sk$F3K{zliKWyFqVbrQLi*_oumoymenUqkB@^`?9 zjm-7U1${dWI>bA>yQ$mZ`Bg=@s&lo8?CWqL7$$OJ>xb<=OXU8(vXst6`)gh7q_Ch{G#`EH1bl#)ZmkR4bfgeDG)ciTe;C zRI84bFE8vpqRGA9o9@?7OrCbV;BWT0pE*D1%_|vF?_FwM=j14k0zF=g8rMZ{Nm-ij z>VFE8&8w7P!qf(+L|E5E^8kSq>b#cDdK{={nM8ZE0=t?jvU|w?ybMs0mhQ+oW{j?~ zcp8z^AccjWq-=|tt41@OlAES zbzKR1Mu^l(Jmy1)zBQO@Fb}0PLs*@m0%vKWiy)L}R(oL6jzM_G{|tA=cyzMpQghdv z@iKYr6$K`IpCroLiGz)ms=ehg6`IXDqd8{!;1Y8`hV7q&%!Z)Ih4;2nB~6Tzx>+!> zZZ0P=G;qyZ8HNCGp4wmBk{n;+3akW6swPLD^ZXijQ^4s8j)_2eEtSyd_?SX3#z*Zo zQ2DRzOD{{Uwtt=i{VcXMt8wSgYeF0kpb|T{zQZV?)z%s!;_z5p2`Uz`o+QUdV2S%JO5>w2bp@b{+{Yx$bNa5d9>_& zATC#Qjjvazf<)cv(~CR{DO#^%6gUEhDM}e%8M!P9^obSl-}J=%5xeuXb?u2V2Gu>) z%xKFVT`6r>-Bo_qpJ~B?7RnB0QhjHCPH?$FAjeW_R)EFCCFU8R?^f%t_>0b68k*_@6&A>|wlSCS|uK%yyf0sVz7@UR%hsWI?5}MC`LakZg`LF%{uKhh{ zs4uGn%VS&?Rd~(g>UgM<;~%&0Y{#HZ@m2HJ=3_09%u`oC?>*{h=G*Fw7DJu?pC9>b zV<5JHxx)b}TGYv@wnFc2_Na0UD4*6DGJ1StrYC+mr53gqgO5WG*;#6D0|mf?WN_s% zK}K64snR3Mg18ewD#naZkwtkVU4<<)G0|5z@tKxgJG&~n_cQdZMCR_HcrvlAj6Ud)Nr>wE>2{n8fw=cV-ZTLJvMXKB&Z zZoa1XM6BIgSyt1d-&CCrp`jMic`?0^@jGj!Yft68=CNC=;sRRS@6$Blt6qA$qY-6n zBm0^wTyO;@@-*9nf~sF9$<4%m^F>Mo+=bAK4L9z0d$Y9jJ%lQWY$MI2jK}^2Mojd~ zAJ2K0p~#M6%Dn_wMC;JW{}6x6e&2V!ToG<(3`9AHo40agVfwUe9JkwQ7SD>}{`12C z-o`5Gkh@e&^kzmM8@{oRLz?>jp)U=4h7OeS77tQm#pvP!0$uwCtuWE-YV!3I?#J?X zOffu$d%iu#cp4+gQwY}{wPCxLs!(dTNg|F}p&^in8i*JKUuvZaz;?+#m6VOl8??x* z3ET!v29?bNne#bNv#r-SIzksvE{nK$-USBP=OPLYV=x5EXbGqMDdfyBwg*r!7~X*c zx!E#-pOxYzM=2Hd96LST2Mky|royk1NpXr=B5kEz4ax%MV}z_`k2jC_$%qx{liF9` zk9^0Ru6!b%Av96+{ktGVTL-OuQ6F)iE$YOqh~|2EwFPSCPt_z^Zu< z^gQhPiTQ_U$nqJ$K6C!$$@ed5k9s)C80HI%N4?)>_9AxWT;RD z6q%BML{H2N9f<)yEz5O@oQ)rG*t-Ae8SxJ>Vd-!Hq>bainowhF-HoY+Ruz&jgDgNK z5$9>6&6D<8$sS(h6anx<_GPHFdvMvq-@;nuJ+WauQ^lmX-Reei^&0r^qjXwrV`}|V z)}EwKq}3MZqik|3z2I!Rj28LaoZFmLtyrH-{zP%!ptsT-C}hx^6(187 zrcox{w^6@(J|@|OCh;*ul2!3Rk$M5cK|cZSBoFv}6w{m}f(&s-nd)9NnZ$Oj|3)~7 zm>`Uyn9?jAB#oAVtY1woc7042>d~agx*f`@p&uBKR;M+JrZOQ1VYF--pPMa#Rhy=v zIE-ns1;}?5r4M*nhc37xR2_50=vfm#Mi6|1!kS2ZuK1L1P4`MvIAuC9az5JWYU|ou zNegr1Q+Y15rwctM@2m`e^Y~JjcZMF1u-`19Q40au9+RJ zWFannPzk@!_0zQlyX%8n>^^rjRi0uuYJI_|mV^W?A2ZmgyU%to+|#4O)L>+2@4A%f zSi!C(m#-kFyrNWdn*m)FXrXb<*|k6G{oxZNAb)jg@%E|Rhb4{E4TkM_59g^zkTcy0 zN^PGK4`J!g2D1c$`+MMh2QFKKhMs#g58~aY!%A$BhZ-~+hBnHO@v$0b`WRZ-QnffI zJI0L$GJjaCzF^To!BV*(6IV87lWuL4LR;6bG<(lr>h6xPpI-ezcY_u|BPA1GY z)I@KD2n|6avP>m77A$vZ$|O=?@P9XDu z-MQEWTe(cdRQ5|af zQc-jq0r$^Un^kLs(`>Qq;fP>45G7Zz?dX&~MPS5QjO^I1^$vXUL4MyN5M<^;5Y&s; zWJ_7G{XoGyngjT4ZiqiBGd-}z^8(n*XK7NdjZLs%MwG};7|nF|3Y@TrxwIAd8>j8Z zeY3EgsT=rGd&B-cB7ss~Ut)7|@M+k1*$%tn^J}u0w!@~zahC<*e?w>MN-TeZz`fFdTJUd;+DzBW|#UeJI_YSz#RDfj4FI+3lFD+W{5R`FL^6rDbKzDdn9ZD^s15UM$B z)(w7*P&O&xq6STdAu=5JsFvF7JmXothDrqpyJa7yFQ~uWUYUDRsr8U`lc>;xGkOHN)mOx@aU4#so z(^9GFR!2;8kcWM59M#WO#WdQYB^FjcuR)ll!d0}1R4VRa;-9(zEc0p%uVI;qN97`# zZc@@nL>F_cs2fU%khF|qrFACLBOE&BfiR&`xF~jUrGPGVCAp%PI5;0k z5>b}mdYUP2HF=K?tdKK}k`H_60RA0g3@IDy40)OL8I&s3O;+wI=({vWte(Oae%Vnb zs5nd@>Qa)DfujKvPv0s_7@-7jC~Tn$go}q0nJ9t^p2!i&s1r8%x~z}L(HiuGA!=^U zPqOH;-v8>v^1LTbb#m!XzUL*i)^t|$S1XkAS*+%9q3;c@U?;CumOu0n^ zCDM`P9R$O(PylY(E!cfds3-I2m$xM_<0L_6F%5I@GVv95+6?Xkq!suUTrq!C@69Rq zaDRmMHqx4ES#VV5T#Kx`I8zaNUd&8H5j8XSf+gWgYtAJu^gO#6nE>Ru6MuKu<1(aaOhO^93e{4xNe6U$cBl{lg z!SY&y<1wYOnwubPk#&)!`~S=hQY(3HYE&XMxpyevW#?LC>7K9cm;_FDFSGSB}fxQBm%SbD*c zfTU}Lf^?>Hz6NR$Z+O1CWt9ah*L4AR=B*wH)W7Cp_D?tZ`r*v23EF=y~6{rq=cFgo9(0KISNhwo z*Ok=KS>^98V3HmuuI$n6Mkn~z+YDd*8MNDZ?d_jR(TD_wGW?~_6ppd<=Lld?SqMP6 zA15o{<@8j8+G?ZqyfE2WS<5T;qfL)L)7R_sF9TQgpE>#Qd7b}gZv8)YfAm!7f_~ax zjaJZXI^Pod^gz=SyLBbg%3 z3WvIa2i*CGX$JImPxogbdSApf2v3H-gYMI>8cB;zT?U6Ma+V_jdg%Q0vc{R0(`|xNb_hA@r)L)m5 za4V$@LndYuGH`p5;I`;?xuH=1T$PVxHWk`R(c;peEc-(#x5C+o+&3Xf_QDbML_X@^ zf{+P80N#ZMcVOaM^e*(n>#5AU{_9Fu(6K#qzWHc5pFRAGR!lj9Hd0tLEOp&M?SW4nPP=gZ-#| z&NMGR(L&ZHD6*;4E08@0eObH0AEFkCkh)K1JC;GPXM40_bQ?1|19g9A0Yp|l4Z*e&bsq82fd3EdJ|IIhev zzIcEQjpa@M!K4@sK;YSi!dcIw01#5z44r%SImF`jETvUK*MnEIL4MCqy5~J{1 zdhc{kgP2{wRRO=hXaFsW!0kC;hKusti~(V&as%Nls1ue6#*$v@E9+W*CPC*F_!7(R zBK7ZZ$NccZKUI80L(xkYUYS0U2RLNYe4ELnOujGC(tQ2;{3aJrvpCs>6gW`~9}aj#M>}vkg3$?DsJ)D6sdnbo(mx0MTreyrcs)2pk%>_y{*MrvgKl>1se;gS-aQPDjKuSUVRoy~OQ#*H^bR zx;{Nf$*h`vmL5ecLr`-Y#yH!6 zolulZ0TnK?A-|)Qp_AX4Weh>EkEHS_#^Ps`xgTjTbD0^V;oN^|d#DNej?)85j)EB%t}x$HSd->^R<8lO-I{6VEo^#VrRUf%3W`w#O%=8v zWf^j)#7+CondZ-pg{*9uF;Cc*P$l)vsN$*Sh*Z~Ey@IAATPTrix3g)Qt9>doMd`J9 zoY40q2^V%LDvu<{%lQKZafDF*LJhXv!)426r}%~hAS;fPQ?lzMg--=P4g)D6jtYgX zIE&B+jUtqGh&w7hr^VWP=XC$s_9Mh~duc-z@Qk(~BWJ#nq6w^XU1)|<1Xdfb6}*@@lqd%M{h^FO}% zge8BsI0TGkO=CQm+a_jlOVl&K_Htm)^7~Rq!78bgX2Nj3Hf!rj9Waq3YjAm!Pc|xT zV?LmZ0SgYYqvAiR0IN<~Ajrlfy|Tg#RhOvp3rPJy*~h%PWA!J5WZY+_VGu*tk=5mM zQ<8un@9?TYx85=16A_2jXQ_I1VkzQP>YBo2N@tZ5ctg9LJX(kg>{g$pl;To%F8dN& zLh3yOQ4&1U88D(}N&{s4q?k0?k(mhj8V)KYoHuoB%9G;keMB{2ATwmD!$@dTu5Nt7 zMK&f8+~vIlOu+fB>SL&C!EM=Nv%$Fj%V zZYwZVa=MZwk`%~_y|S(|nKEjfNJ|%b7C`RI%8lH?|s_ zLLSM0GhFVinrZl&RQG7c>*Db}@U2O^;)8=}^!QX#Y~Y35fgusbBkPmRgkRw79BE&V z?}{fw@N7g=!=nkQR958A8T`C|ZoIZuyeR%ej%ZS6@?_K{Y>)sl+j5<>a^F`_Q24@$ zc*Z^GhkWR`!>Qzj)PS*E6F(b%lzu&xZ+y=1S%ObQJ_vj@2uSCVA^gaM#h%zmjUn0O ze;JFjQ|nxZ%$EQ*LMU=VP&9r?^j?*2M>dMka$ug%ffBb3RPcaGO$C|_i+!bwOy-kF z`~c>vKbt54D^iq#)agw%IYoyd7uM2F)8gGhsluXcGTY|&wm(Di+Hu^TLV@%Z;t-+$ z_9WS06$^2EbcHuyuv_4;1AE}fRU!^hCgUo4bZI^mnzVdEan-&nA8SSE7kYEE+TCSo zDA9Ce)f|o!7RPIwx7n`l2z#SAxDv_S7jzk5KQAu}USvwmG!!Zp z^mI%p(>!QUD}j3uwqxM}O4?OfA@6IuMaFyca28cy60R&4IjFdc2U38<(<7^#-mu4L zECW=!-(DB(^W86R5vetGkfOdwB@eI&&v2S1Fe>)p+hw#`*cpe^R>Z+eNRf)wk<2t6 z70rOL`^+g7FW{jJ8+F30XR+0gH8+onh7j%BX3t^Ib~{^A|1O0^pF?8Tw4zMztfBW~ zUi2{?@)}ZFc-(MO^Lz?uUN3kX3XZjy#nZd4vIF@a*2M zapPY?;ibKGWc)Cyz(O~GUX?!|++;hQ_LIX*&0TCCV=olR z(NWDa0a?QhrKYINt-S_Cn#|U6E~t=Gwu|tN&=aT_7+}@TSN@!)&+@6c_Q-pC|2Y(o zcgkaQd|g%s=QEkUomjMtFlR3x`MMOB7BJNUN-Z8HEs^Z70#c%a)LK;ZYNc*Lr+$Ud zQ|H82`EVv9GNmy~Y|eW zv6>6HK*JiM!O=@RY2b$nRzm>-NHX!5C;!r~2;+ij@M#`$B*_*!Kfh zQ>As~_U^XB&84NO?UzQVTXO?LuWuZ~_9${`iNFfZ`Aio34&fhA(iVF;)OV!cTUi@@ zjbS-!WP7FH7AGCF0BJ+1^pKfg&_aWxLPyP6;Cv>DXj}HN;nZ*``dLLZ^RS*X2p}zx zns>%mkcR?X^udunun|sdl#~n&SR6@B-cza#uTQG_o+uA#fG^*R10TGi*Rt1M`tw=c z@07mlKD_#O5JMrnR(n4gzb5175bX@{^&d9ydbp!J>;Aoiue#rch}Q-t1uNwRaewgY zah{X@F@?;Z`7u8?KH_f{?U%r^$2rfkAGIi)0M~vu_s?;^=!4_x|8o8K@WYmeNpSg2 zK5hj{1oG(@V(4%kC7K1-j8SB~y6?lo&#Kq$THiN3xIhzgbfL|eh~n93?(9u=t1xi) z;<(96a8bc=CgM2oIKC+rM+WUfZs$Fkh0v6B2EA>U58~vmD5_tTP)VroK%?H1{$zK( zN+?+MS2Y}bSbKdyud2ABtHev6oOoNv^U5Cv!Cu^Zz@S- z`nN5cab|1V$CAaK`6ssB=JXiWHvC5K*G`8VW@F{1WUzTV`0*Q&;XF}$6*aZ%jFS#=#ldCZJ`<-CGiXo%U}t7 z+!#d|ZcnR>ot(=D;R*x6I|I}PeUS<-v5I8QaQx`RjPOb>AoXC9p8~34l1Xj|NNcPV zdxjBnzR_$DKn)?7rx;gqETbk#wiT`#`(FrY@bVB&dsQ-Kk^gT)4@=HIQOh640h(o` z#hM6_!&&cIF?Id44IE#x$sc2QE=gz+m8Ur(7XiI1|1Q+CwY(?f3%V#KM2;^)#A0{{ zOI7|=Jajj!-O3nex7Ogxdn{;>Xieo1*=Co5?}KbF_ulYG99g|MBaf%ZFz8tl9_mtENMa-# z;$!e_a*^+$pJ10)_ju8IxSxq%J9UZRx|_0+ZdjQDgTc{aSRl;B#dq_jbx-39_>+n2 zVu|Z!Tb|w@pgzrt&$8Tb9g?5;DJK1mdboZp*v1J=CoqRq9N=+>|hhk$5S1bDhbsn zu?&2OA4$)EY{2Ojbmlm&<|lxp?MJ{f(r8V=MuS2=jqel1=r$xrUgWYj-_n6Ns^{RR zPHQ2heO4wd*xK`~g9N^A&96n9`!PnqlUve++Kx9tBTo6HT_f1*%h1um@kHB&rN= z`6bI8*S`oU`;od8>X%SSe-55Tvaz3&H@jddKRoXr<2$_7gwu+kYz~inkc)jnYKm?) zbxL5eP9$M`k{z0hNz$BgOrN%Ot$d6dLB+A*Lt-UJv??s5K6r+x?bnf3sCxQ&c3Db9(YOP1nWYf2n$#WxZhOCi^GrtpI{@p+k>O>Ua zj-;kH*X+sXAD8^<`kj$okZ%VGkl=TM2_R7wbI~r4ikY(UA#lr9u1}9zhyvPA@ZM*) ze-MT-E|6~|8d1(XZWDR#^A)sFv=64tN3Rbm>PWF+^JVu zjsl68!foG^eGdv-7MDK=O&o}PNjlK0rQ1C`VALo#Q9ayZnv*eCJgP5?6S+ACc?}}+< zP}p(~#qnZF0UoUlU}M*>5Z9P06rNj|XX&=FrS3P`90Evf16(`w^1TcP8XI5RYsT$o zrt^gKy+Ot0XaJ_;YP+^rh7AIV^l@no^#Qg>7QHT38D~wB%@4TlYfB?*-w^|n*rHlB zGThWs;BZTFyD?VW#nH@cD@ zT3jRg3^V{>7k9M98pHf}#{omG3&OKWwl5#bUYeV({ho(KUsJj*IOFjfoaH1F(tK@= zzb!Eztwdm0yED5qFJrDiIhs!oH6hi8lr0s|{3Fx}ns#)+VmI5P^%9OlQk{*hsLF`S z#`Us7ZS&a;F0An(Of;pLsW9-RhQ_DV5-KX&D-Nz0l5}DRD|I5+=)(rCCFhsn3r-1) z@H1S3KxF7cDghN9?i(jj?~f)0355Q|4D2*kx#4+n^-zN(yli2#>|-(p$O-mcpKg~= zb@jAM;+?;Cvq?MVt7|08M@YsSsAx#!h7vn+8=EL!I6+E6Bv0dCDMv)^~iBdSi zi;n$AYxN1>bJZj9h>`Jwc*XivUJ&PmP(( zcE}pIIJ^lmm9b0U23|=xv@La=CyZ@hNu}*t=+X6zWVCDCTtR zWMB#BB$AlFm_tVls`mAU2yHlg2|drG6E4Ne9BlRynG>fGw6^h;%QkLS`x>(6uD5&o z*0BRap`U_z_J!Lqs$*koxe;|>7mVjCwP>5o0w__cWxyWnBMs8c2;5h-v|_h?#(*4A zfxR1A%`@c|TXOf1GH5%dJ5TTK8^J6@jqSGc0`m1YTHFNURnXY_3Ie*;THIN6J4AGy zYK6ij3zdpzbWPB^UYFyFY->gCfv5v^uoEGl+Y47(mu1zA2?0HoX z+nGyKOW`gseP`q?HX*56do{JCQ{#Mk5X?E{6-%E%xW=8vT-QQ02aH&}!KS%3_UK*K zbhw9yX+RYsMF-}gN`nm2J0Dln?4m8XZIWg7latVko7Py)g~{m=%PQ;FH$pO|_kyYNePP>>#G#lvTrByVq1-Ij;1=Itl?g78y+>5Sm24NHZjq-bjTE;g#H zFKh4&Q3!swXZF9rRion_kL~E;ty=rD54kno;A`1wL_EOLHQA2+-<>`=;`x)6$V}Dw zzA&2FtymGbX(=UMKDna{fDQqJA7>N(5>2EoE;mEw{yZu=JPqKuRE;W#?cF7hXR85& zA0Z5wKa@zglbB6B(hz`J&!w|%H@3?r(RpnJM>v*46kdm@+J!{t{D6E3hK0tKj|tf= zEJQ!r)?`>t`38)I^cpbuRfL|f3(;m?9`B%YOh~_B=rZ>qqzd7M^;YYwJD!tZsIhRY z*^ERlA7yaDNn7A2+{t4{E2Ea<&03PhYNN?SimVr)ISnM(a7E7In>0W|2 z)dk7e0V#sXdKqbl1`Q)0te$lNtCM35w3v%bUQMM!xu_ zLbpRa3T(l|ZvYP~!C>EQ1T&ff>CB$C#{@`>x8{N zd<+0^c08-x4AjBq`$X1HYKiy%!x@vVLPs;@M|rKTrm%zO>Z~9m@#taj>Aej!e6a^f zH3p$yl1XCsZQPd(-#$;E?%>4rSU(eL^PR#m#T|c>y<+phj7cB)fW&RHW_d#BysJzz znMY``?yT;!zu}(H{M}IqQI@ueg@NFpr0OA_BBEZ zRB^A%(j+{j{WapAg-auz@XM(vCl*EcMo(-5*R-6NfTq^{OumGL8b2FtUF~a03U|IC z_U^#?LXEhLwgT5jwIS7{M$%@tMX8nr7dlBN#1-te;ge^d1-*nN)jPvuc1&?kknft~ zV{w^eMYP1v62pS!&DJsH6DLjcoJG25lF^rlMFPR}G@E&MA+FDm&dL?r)~f)`z>&;V zL&2bD1eUfmCrTtmWh2ol5u&c)#FVE{v$`t5%c_r5!@qq!zm`IL*3)NZowj^jwRoNK zs>ff)M{$hn-fwIP1oGf5WP8@hFNYnjh=H*D(k`M1OfAM`yS|#JD+N0mkRU3`EIm>g zHm6hF4?txOkL(HF0I(@VtrRPoHztvC#5C*)HZ5_KxnP$_!&(F9Hm63KSl&obVW`5y ztKB;*`co@)qJfuPv}$8vQ|SP%G!Haweu; z+=&?76D>_j-k6kCp|FHgiOpBxk;d$EYKTuONdKR4Uu!g4JkIK>(-lyvX@kcN< zi;44k)>&pbC7j^ZoumF92JAgjYx(vLJzX~|CuUPOA_hEETmV_h#AsP77`Ue?Bj1xi zCRa3bb)hUmC;+)_J{Am09_T2_;>OaMYd4bP?z`7x+b}Ob?m;Erj9`hut zkCi@?7_{RIXb=8gq4_j>)E}lhCT)TPLOZ8BV`(;8j!GuF!bP1X`4u?6)BQ9*h!61# zC$QYrFKX7lg|FU9cs@-eFnq|*H@*paP0h2439TujC_$p@pCB4z^+^QZ|) zAuZh(py2#XmY=6k<`Eo+Q8kvjl8OnTOdqTZRE)jgK|xMvxW&M6$ll4zbmyHSV z2dJMJ_Dqy_OF_##giEvS&SvDyY}*^IN7ivm5?4#$4Ve7)E%r4PE*N8{-0VB-ozh0X zz;pW!RK!>jq_o^xdKPXe9lDLg_)&!~+-}vGpiEqD4gd@WJ=t3M>KG7bS4?;kNx}=h zVPZ$mumwk{CwZY~uE##s!s-1WCMB%pGm%7x-w~(^z80aQxPc?AuwI42(#+;LJqr{q zG&Q&CBU`9PJ?16!5=}C;X0+@VcNn7kCZlr+!8tT2VJY4Wl#?>A602yzH<+`HbENTh z;lNwzvZSGSR^bZ!<3AQ1Otd7SQ-b-l@mF?^IjBpi@0*2Hyr96Kk1)%ki0|g&pijt~ zie3{M4{Qre)P$9(X@}7>5wfaAG|8aETV)VyIIu@08Pe1- z!V!rERa#nPH#1|_Xu)e(lLXx-cq2oJgNy$bHmBV`@(bd8^|S|q{6|RHf2q~yTSo}U zv6zn#wSU9d(UP;T9Bqb6Fqx2WuV~B=4B%s=Fmie`a;d&x@i!8JOHpuQ5d=VUqh_4x zDh4_Q!AAiyg$vC&8FAL2NxjwS;-0RCS~>+_YL<{@i11YkH5+@NYI;ID#Ed;_@0f~{ z6~9Pkxcp=ug~qNcPC8L!%OcL6O=}c%up7h?eQXh;85T3P67bcqn%OjSuhjDOFs9@O z=-XMQ-rR>fuFR!1ZELWdyas%Y+UFY4vO^sj7HUUU-Hx9&(Tm9rp&vKN!NrfUCmZ}ZJBjfN)4b;06GLF^F(75wGqwd)qz?RIO%kbZUiTS- zSM9etu@KzCmXQs~=;*pAs#34YD?eD# zBeNfCQ)Q)d%rOHF?1!L9M{jIl{Zuk@8ehuByoa|R4>t>1>JCikTc2ebAq-z%Cx@49 z&Bg&gzF7H4_?R9z-@AX=l5IIxR3?OV z=2SsEl!ZY+?X^lOEFLSARBFjEG?V?u`xRMiVdDq{T(HXX;qiOoj0>8rblm@{{FDgc zXe2*ZOp2A=WilB9z=?JRFOlyRV^1OouGPcjek`W!kSlAYNxW2hAm<4+M6{{S39kd8 zm-QaWr;1lp6;YkLZ`85w_TkL=Q~P$Z5%p-$yZk~?d8NE=B&i%sjZsLj)R9pFi+7tB zW*t&KJw|1e;x&H^?fi)EPjphHoH>j&M|?UOWrN!U=YS`d5B236q)S3V45yBUd2)bo zwbY$zmvfjR$<;e>x*+HuPe;ZkQeq1wdSLAJLy!CX*&}y?J^=>F<$*BHpcQRqb6ZaVwd>foe~$EbF-E2hJH@ zB=%pOvs@+C?twl;oQJ1EZ1sL5;t-O@9*vDxz!k)o4X{BZisvL?%E+tfgt+6)a)bF` zk9ip`B($hzBOooYG_JGG6ea;obCcVsRjO#!!$M2RWi9JQDnN_b%(QrIuS&969s{*} z!%%N)#}I-I&J++_Uk{C&oLqo;_RJ@e)tZh_E@8&U#_<4dg~~FW`08n z?8$+%qY7sWW?ypxrPQ+cdJ+HC$Or>?SvJl0>~f*Smk#?)$8QNxa#5Nu-T4`Q~8OifT> zVS%CyEuz?ZsK<<^z3XuxUI_K|EE&8wPt7m3l5jy;RRP+!34v&aTgb(lT-{Td_N+vB zyO!fD;`Ehl{v2?T_mU)45^*U}f|6eX&H8|N!`(V4#tskkF6@T1s$O?($3>)7=A?Kt zmpu{Wm84~iFLggrk+r18$u+BS7sQdl?rS##$!%I^7<7Jl)g~Kh%eg3jfa7-uhmK>_ zSBM5h6W);s**k6%rVQ5guDMVXE5e7m3m|V#M1GTI_9Gi60=|;D#pIHp)e?yUIB2up zf`C^HJ_esfF#($yWaiDd`cYD@dDaIu#T;~jq9q=$dxS#`MOOCVXCOTvd`S8-<4YdP zUA4cQ;RIf=a_IvN2v$@qJa)#eaX7nujQVNr7umkAU|Z#rFWx&q(IV(RB4fM;Uk5kC zcU|zgHV0{HY5Ler1)}q6_7g0Q?hFk!4l2(^NRC<}vgEO;lPD}&u&(EE*RJ)5+w6ij zg8?=WfuvPlHx>`W0xgcguR;6dI&s@`tzjF8rLPA>l1?DDT30G&U!OV@cg;c_7Kh50 zD>mk9K0fS)!UH5pKhqfAkSuui0#c@%JOiYmbtwq9u_9EH?M0q--FtpUZE!2Y3dpDS zA^fxB=Y~f!G`bF)y=k}dKOZg$b9w=1zXIV1e+34KN#cQE+}SZ($vlTBj>9;-?Fyaw z0N=~1L=3wv?9L40j@3S~cdrs;UM;oT2$W>T6kZ*X@rzTJKURB;y37Cir6raU>WA}b zL$f=olNR56k`y89lg9fhl2o(9FP!uAj%GgYcX|}16Rvk%iZ4$qUPex&H^gsYv9WM} zGyrqhS8Plf+TVa&Ca6$_N1|T~4%+emNGsT-rhH;UmE!yB41d>mAPs|?g&K$DgfhMw z8`&R4pj4cN_RPT}0VJGLXX3#=ESGXVF|bu8{Q)dCw7>2+Hui{X`-}qae0IiB;%-Fn z``vu0@_w$KykrN*&7(UyLiK}=HJ?j?^MDV6sjg;VuM;k~gCME}ge|ODztT>Am6R$D zhc&X%WE+RQzYmh}dVc;e*4ipnO?V*I$|u3fH}qG8GdfI(+ieVE_-_-FSW{(xf-)3A zwT!ca67eS@3xGSXgsUN(pu*jvhFfKjY#RB5OQ?O}^tM!>=#x01HAr1Y7H>BW^ZO{N zc40V;A}3is9(V-?AKFF=}12qZqPe2c!bdgfE%FuR^r0SanKZWRZ$M%@D$tzJr zAVagKr)3CwCNwdv$s|Vmu`&Tg#-CGTQe~6KVOMFCPGrB|)<26<3trl7o7aC+<ku?_hwGfjN%oES~B5p6e7C+`%P;+ ztm0Jv}tEBTrwrwv>^ubHS#6ONOKSIIZ+Bc*>Fh8#!!tH9JCVbK}5d)w^_qR z>cW%X-$@TrS=OAQ0?IxGO@kz=4MW!}STG?)Sf%y$Yrd`8me>E4T^quo9StNQlB5s6 z?CM6i3i>dOvp9>(HI@H%M>t8Q04~h&t%Cm{@;efIa1Iw&N;>^v%GDTFNvLCT>vdtb z$5VY>{GjWdxA2z;;1@Sq9i8f&GNnE%A%Z-_F^P%dqlDsBudIpK8-n~`1y8wOu&YB& z3QtVdGV~lZd2+K$NVtA+Z93er=SEPxv}#DyZ#4xRE9A@xU*8qQxDp1!7^ty ze5SlEu4lftjb|}uJh_T9BaMq-lKIKTNt~=H z&+QZujS>HJR7@MA48(U&&7H$Hu_Mt1_^)KD{2*7qtDF)~&7ao!)FybZnQ=WIkIRc> zYW^j4YpSty{zLbsGvsLSeK8|GhTBD`NRrie2+OlD#uNhhlwp~8qGnBxbA+Pis;H{$ z#nkonUy5J78~3WJ_euBXRm#o_&f~?z80y|kkYoz=ivY^Ag=w1goOxBKGMc|>@C2LTi$9+3 z!2;GsDeow?sWjnyOm_L(1g+sor_W#pu(b0#dtkkwBUl!hbC??DegSD4I*L4BzW zBT~MY;@{<49eFVu1OgDH-e|vpk9v0Fo z>&Z6!WAJA&Hq|!Fl&>Z_s0abP#nper+10uztCTE?Z+~zvOzGyL$H%)=9!@D6dR~l#WxYW)93aD zta35(rQOedQEIF~pBB{_Mzn@QepYRq;uNPblVxGP8wf=fBbtH|~1 zA}OR06SL@S*yS7qB?cY{VY`oI0jO!ARQP4?rd;%?`TDz+%@yMSH%ur4V&c&u)a?n_ zXgGL&<%c%Mdp-kFj=uPaaZ!X`SOL?~(@W>3q-kEoV(;4~UoaxkjWFwS?55>=r3^Fo zY!qOw_9}7=$OSxE=dUX2f=v(NSMESFAPNf+|gB?6<{qYqKy)`S<^E8+i3m5rnu3krJ+26+3Xt6dJ;67RJ39!}u~L+o92V+9f(J zoy92KYgU023GV8zmaId29MumM9tyxmYNWTeASq`r@vKmO*bWRfcJdt#X6K(%h}ee; zlz-Sl&)%r?EsS<`YK-=veT0OzDr5k(OE*^G)eyzAU_Gi{@?)ZiW#iL42D6xA=PWE7k1iBCGmI}^?Ir&kxx3=0Zd7ghYXNE&US)kZjh2BzM zCej2j2gt*M%y8XKCjkRuo8;z~7jt`pwGQo5epHP`h6^=dS@e`C(NLtfrfaARq0g7h zy>2SFSy3->|0ABik*0?^f&Z_7ODO)&oD|vCYmW{D0nqJ#Rmh>rfVY2|EFQ*8=T(8!86hTN=`CCpg=j zYVL%;ZqZTg+u*tOTT}l3_a3yzD+qg9qKWN_0k2&RxfaT6$d|{TUa3Ej8w4r$Z5QZ z?K<9a0BLLf=Ck}h6m-Hs*7a?KYmhrA)2z&Ov+}g7MIKkSVzkMt;0-9JtsynT!{*-K zUNYxQ0hFWl;2V0-HQqUca9tX%M|H4e-j(`%*2 z->}`Tv0Cc<*O@!e`8w(ouv30wf1feLCb8trFl!Po&3!S5smf5-qMqvD*6owwtawy6 zC&K4E(e!YEgw$H)5!Rm^Uw*ll>?g`OA<;S3DVe@O#}QJ{DpzHc7nC-HaGxE>A1@ST z7`}%^DL8$2tv^z3yZW8iKD*>eeS?YoO>CYF!xgXU&wK3pugSKt>R((+^-Cd*{-Yt_ z^56gHhwqL57PDyizkl?DDmP#?_Xl(35tI$QR7LkYWd}#{6SNV(#-IZ%?UzeH0Dg5} ze@YF22~y$Z5kL&anI!TikViVMvArq*$iW=Z%~cDnNuA!qgG@yY)=IApHgJLXU~WPs z8o$J2@q8)?S<45^mMzzB-krG%4E008+w$cTYWef()cZZ}>euz%kH5k@@!eBz#(7z{ zQ{H!W(!GI6_s8Sz`r+hq2)c` z4Lp_*X}J%Og04vb)GAouKI;%vl5z`Eu zGV*eF^p*+v+KWb?x6kQypA1{@OyqaJ=*LgL{Z-4^TUxyO>wVot59#0i=AS=p*B9*j z6|{e^WtII)eZU8oU(zfu`kjWS&JqWO*yTG_d7vNwAaxZ1t#r<`<^SFPM`ewnOooB? zF;BZ9)}?*T!|{HWd-wQd@i-l}f5nS8+dZQx&&sbvEFM2Sgfb*6g&EH8`3xSR#GS%U zdowtl(o?@1@m3s}mz8qm+nMhvlZWUzZZgqHXIJ|4EMxR>EL_)HhuT2!89uk$r+5LR zPg+r`PsMCqAM5OMpO|cVe#lc|Z3_W|w^dY(yp%Yez%{(jv5U3Zft&{u#m>JWb20t5 zHKGa-wD@TCqV4J{k}?7xe3f5{f3zkA$bc_Gkn;D{jNjV73A^moxeZW!31HEA< zzED(iJdGR0m^torWb$~Rnakq|6?_^`sWuqTC{QhuA89gPNUi;h6dC!`o}$bb_MT#l z6dsiNLBAfqOS%3zevcOYZ~Q*R>Qr06o3_#H#C?c!W1RORurnQ3wlt9 zi(k(gxw{yUYNoHA+d=`5W(h=utk_+*fKN91mUABt5dc-vqt(AkA z-MD=^f1Kcxc~y|f6_hAdPMPw0#|QkwreZ3t63Qy7YU&!A+O%uw(5Xug-FoWvfwTGN zH~&s5*PDZuTj7$O-m%g~>+E*ip{FBjyF?hLf}X1Cq<*mE!ce!0)YzWUuQKvB+RQ8#VZ599QD ze|&tVU??1k#^Q-&DxJyZ@_u%MVyRrI*6NLBtKI4LthR749E~T_*?h5Ftv6et_CNc> z@dIn~AK`kt`}=X?h@P+a=llB)1ViCSG!{=JQ|V0BU@l)MI&;O!Fi_5F)EH7&HMzd_SJKbJ?FdU61 z)7gBnT&*`-!Qb8fa6Fwa*W3N^e7!&4U-f5E^FUV5-ut8j+&z4F`sUMjKi)eDTV4L} z<^Sye>$^YHr=}aGWjn6-1N5hSzeS?-LzdljMMA=0YC^wPz)zXie^}j z7eq-`R82Qb%XVDP55g!;(kw5^s&3k@AI523)@?t|>wezv9|(rRk!UQQ(A7((42|qF zACsIv#UTr{g{iVR$3mfKX;ms$s^+zNquFYAy1o8jI2uo;v-x7VTKBJPZf)=E?xA`6 z2Zu+;C#PrU7nfJp)mpvrQPKJRv^!n;tNe}0@HZGrh@WG&4EIf@{2Uw}9iN<@onKsD zUEkc^-9J1&J-@uZy?=auegFLa{gX7yi?XVlwgW8;4tUOZauaaDC0AT?^Q!XynCF2< zo;c>e55ozPq8avMsq_AVD9MUycQ{?YOq6E2Gr1!dzzIlFG-B8}IJxEH!2nJ`lA;mA z&cVsWouf9LyxnpTdw3#ln-yhnMcCj^Cnt0ke8dS~-C~dgVSF$+{lsQEDz4{S!sm^g z9$rl^4V*)6E4iAU$_~_BUezL{vg$c#rlJjy6#kv0>hy(n>7SNi zifd$D-ooznsxc4_b!1UWdW`7~M}Lr0S%EIxjvDl%Zo;^G>(vA`K58tskItJeGpdb$ z{@|mYsGD0&=X^x;y(nR+hecShQXTAAQMw}RK4QTv4HFXVm8((`W{u62cFHz{PVc=; zmmvFEJK+*l;z~qnGTGf}wF7X<0vR8C!5&@aB3= zK0OSbK6LvqCu96GhCZoblyO8MgBn9Oj%-o=NXjfm`;~ND+~>F9jCswK9}cWI3b7r0 zSD@%QAO6L%o(b$69A|R0Fo8AjGzAD2c0B%ass8& zR85q@6{f3eR34zpKqJ~K;^6>}`{(ciO?#z6h=>4`O4D9FA|fIpVpM|Cw4WVqzy(UB zX|I$*04`7}O?&mm7-Nk2Oy8H|w7*ugGc$%QvpwZIG=_~~V^|AopzD~vT?i8Q6UQ#I zsL8IoV@W5)i^XEG#{T!Ivp0Qg z3ca9*8vX2aXKwo2;;~dG%wuOdc$bDhuI5TbFI0VM&wKfKhs0j4Np!+9jz(_q>=I-J zxdWr;u5(M9X*LPDDcb~+q7lQ+kyBv>zzIlFG-BBAKl1SksK69s#Rj*{&Zt+V7wM0E zfq$;1sHeFr(l@A$GPL-OA+3G^Ka8Yf_diG6xGg62x?zt`4wb#w2 z$Ch29;q^@mE=8Ua-kPB!{aWjCIhNfNeO_f+IxR8_&xGe49X%_~kgxV~9@Y#b%)dkD ztRw4f^I@gMpV-?V?UdW?^RjCsyutrYkC2cZCjCC1ToGoAE4|`zw_TSckb}h1R>1?I zKx$XJ{cQ8d5DLTT2Dqj|xuTL9RjSE=DgqY`6DY4Vh%|IZ3VHC-0&*ro1*DpCBhU8e z0n&t9-p+s!QjLO2RahcffXu;(s8@ZRN!-KLsiKs^df{=X$B7`g)p^lSbE^?Nj#X@| z2XyJhrj*d1@;ue8TgU49dnILl2;s4F7Ie+1LJ<0ux@Gu%&r!Nff5ZHQLM;&+<;Sz{ zWuu(ExUvhG!R_t;oQuqq@CFWdp2^-oB|A?xW=N>ZjYfHaM@>>cM;Af!`7DAg?63e{CSqz6WqFYw?Uo UHz_3kUkBJ!#$-}&?d1Rf0QdAnzyJUM literal 0 HcmV?d00001 diff --git a/dist/www-bootstrap/static/header.png b/dist/www-bootstrap/static/header.png new file mode 100644 index 0000000000000000000000000000000000000000..ef4f9f1804f81584e105db9a558806225df74c77 GIT binary patch literal 7299 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 literal 0 HcmV?d00001 diff --git a/dist/www-bootstrap/static/style.css b/dist/www-bootstrap/static/style.css new file mode 100644 index 0000000..b9ded1b --- /dev/null +++ b/dist/www-bootstrap/static/style.css @@ -0,0 +1,345 @@ +@font-face { + font-family: 'pxplus_ibm_vga8regular'; + src: url('/static/fonts/pxplus_ibm_vga8-webfont.woff2') format('woff2'), + url('static/fonts/pxplus_ibm_vga8-webfont.svg') format('svg'), + url('/static/fonts/pxplus_ibm_vga8-webfont.woff') format('woff'); + font-weight: normal; + font-style: normal; + +} + +.footer { + font-size: small; +} + +.div-table { + background-color: #eee; + border: 1px solid #666666; + border-spacing: 5px; +} + +.email-summary-seen { + background-color: #eee; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; +} + +.email-summary { + background-color: #b2ffb0; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; +} + +.email-id { + position: relative; + width: 100%; + min-height: 1px; + padding-right: 15px; + padding-left: 15px; + + -webkit-box-flex: 0; + -ms-flex: 0 0 5%; + flex: 0 0 5%; + max-width: 5%; + +} + +.email-subject { + position: relative; + width: 100%; + min-height: 1px; + padding-right: 15px; + padding-left: 15px; + + -webkit-box-flex: 0; + -ms-flex: 0 0 45%; + flex: 0 0 45%; + max-width: 45%; + +} + +.email-from { + position: relative; + width: 100%; + min-height: 1px; + padding-right: 15px; + padding-left: 15px; + + -webkit-box-flex: 0; + -ms-flex: 0 0 20%; + flex: 0 0 20%; + max-width: 20%; + +} + +.email-date { + position: relative; + width: 100%; + min-height: 1px; + padding-right: 15px; + padding-left: 15px; + + -webkit-box-flex: 0; + -ms-flex: 0 0 20%; + flex: 0 0 20%; + max-width: 20%; +} + +.email-delete { + position: relative; + width: 100%; + min-height: 1px; + padding-right: 15px; + padding-left: 15px; + + -webkit-box-flex: 0; + -ms-flex: 0 0 5%; + flex: 0 0 5%; + max-width: 5%; + +} + +.email-view-header { + background-color: #eee; + border: 1px solid #666666; + padding: 5px; + margin-bottom: 10px; +} + +.email-view-subject { + font-size: xx-large; +} + +.email-view-from { + color: #222; +} + +.email-view-date { + color: #222; +} + +.conference-list-item { + background-color: #333333; + color: white; + padding: 5px; +} + +.area-list-item { + padding: 5px 0 5px 15px; +} + +.area-list-new { + padding: 5px 0 5px 15px; + background-color: #b2ffb0; +} + +.msg-summary-seen { + background-color: #eee; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; +} + +.msg-summary { + background-color: #b2ffb0; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; +} +.msg-summary-id { + position: relative; + width: 100%; + min-height: 1px; + padding-right: 15px; + padding-left: 15px; + + -webkit-box-flex: 0; + -ms-flex: 0 0 5%; + flex: 0 0 5%; + max-width: 5%; +} + +.msg-summary-subject { + position: relative; + width: 100%; + min-height: 1px; + padding-right: 15px; + padding-left: 15px; + + -webkit-box-flex: 0; + -ms-flex: 0 0 35%; + flex: 0 0 35%; + max-width: 35%; +} + +.msg-summary-from { + position: relative; + width: 100%; + min-height: 1px; + padding-right: 15px; + padding-left: 15px; + + -webkit-box-flex: 0; + -ms-flex: 0 0 20%; + flex: 0 0 20%; + max-width: 20%; +} + +.msg-summary-to { + position: relative; + width: 100%; + min-height: 1px; + padding-right: 15px; + padding-left: 15px; + + -webkit-box-flex: 0; + -ms-flex: 0 0 20%; + flex: 0 0 20%; + max-width: 20%; + +} + +.msg-summary-date { + position: relative; + width: 100%; + min-height: 1px; + padding-right: 15px; + padding-left: 15px; + + -webkit-box-flex: 0; + -ms-flex: 0 0 20%; + flex: 0 0 20%; + max-width: 20%; + +} + +.msg-view-header { + background-color: #eee; + border: 1px solid #666666; + padding: 5px; + margin-bottom: 10px; +} + +.msg-view-subject { + font-size: xx-large; +} + +.msg-view-from { + color: #222; +} + +.msg-view-to { + color: #222; +} + +.msg-view-date { + color: #222; +} + +.menu ul { + list-style-type: none; + margin: 0; + padding: 0; + overflow: hidden; + background-color: #333333; +} + +.menu li { + float: left; +} + +.menu li a { + display: block; + color: white; + text-align: center; + padding: 16px; + text-decoration: none; +} + +.menu li a:hover { + background-color: #111111; +} + +.email-reply-form { + margin-left: 20px; +} +.button { + padding-bottom:10px; +} +.button a { + width: auto; + padding: 5px; + color: white; + background-color: #333; + text-decoration: none; +} + +.button a:hover { + background-color: #111111; +} + +.last10-row { + background-color: #eee; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; +} + +.last10-name { + position: relative; + width: 100%; + min-height: 1px; + padding-right: 15px; + padding-left: 15px; + + -webkit-box-flex: 0; + -ms-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333%; +} + +.last10-location { + position: relative; + width: 100%; + min-height: 1px; + padding-right: 15px; + padding-left: 15px; + + -webkit-box-flex: 0; + -ms-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333%; +} + +.last10-date { + position: relative; + width: 100%; + min-height: 1px; + padding-right: 15px; + padding-left: 15px; + + -webkit-box-flex: 0; + -ms-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333%; +} + +#msgbody { + background-color: black; + color: gray; + font-family: 'pxplus_ibm_vga8regular'; + line-height: 1; + padding: 5px; +} diff --git a/dist/www/header.tpl b/dist/www/header.tpl index 7dd9a84..a6a204e 100644 --- a/dist/www/header.tpl +++ b/dist/www/header.tpl @@ -3,6 +3,23 @@ Magicka BBS +
diff --git a/src/www_email.c b/src/www_email.c index 28c00e9..3d7959a 100644 --- a/src/www_email.c +++ b/src/www_email.c @@ -156,7 +156,7 @@ char *www_new_email() { max_len = 4096; len = 0; memset(page, 0, 4096); - + sprintf(buffer, "

New Email

\n"); if (len + strlen(buffer) > max_len - 1) { max_len += 4096; @@ -165,7 +165,7 @@ char *www_new_email() { strcat(page, buffer); len += strlen(buffer); - sprintf(buffer, "\n", conf.www_url); + sprintf(buffer, "\n", conf.www_url); if (len + strlen(buffer) > max_len - 1) { max_len += 4096; page = (char *)realloc(page, max_len); @@ -173,7 +173,7 @@ char *www_new_email() { strcat(page, buffer); len += strlen(buffer); - sprintf(buffer, "To :
\n"); + sprintf(buffer, "To :
\n"); if (len + strlen(buffer) > max_len - 1) { max_len += 4096; page = (char *)realloc(page, max_len); @@ -181,7 +181,7 @@ char *www_new_email() { strcat(page, buffer); len += strlen(buffer); - sprintf(buffer, "Subject :
\n"); + sprintf(buffer, "Subject :
\n"); if (len + strlen(buffer) > max_len - 1) { max_len += 4096; page = (char *)realloc(page, max_len); @@ -189,7 +189,7 @@ char *www_new_email() { strcat(page, buffer); len += strlen(buffer); - sprintf(buffer, "\n
"); + sprintf(buffer, "\n
"); if (len + strlen(buffer) > max_len - 1) { max_len += 4096; page = (char *)realloc(page, max_len); diff --git a/src/www_msgs.c b/src/www_msgs.c index 0581e87..c365184 100644 --- a/src/www_msgs.c +++ b/src/www_msgs.c @@ -893,7 +893,7 @@ char *www_new_msg(struct user_record *user, int conference, int area) { strcat(page, buffer); len += strlen(buffer); - sprintf(buffer, "\n", conf.www_url); + sprintf(buffer, "\n", conf.www_url); if (len + strlen(buffer) > max_len - 1) { max_len += 4096; page = (char *)realloc(page, max_len); @@ -924,7 +924,7 @@ char *www_new_msg(struct user_record *user, int conference, int area) { strcat(page, buffer); len += strlen(buffer); - sprintf(buffer, "To :
\n"); + sprintf(buffer, "To :
\n"); if (len + strlen(buffer) > max_len - 1) { max_len += 4096; page = (char *)realloc(page, max_len); @@ -932,7 +932,7 @@ char *www_new_msg(struct user_record *user, int conference, int area) { strcat(page, buffer); len += strlen(buffer); - sprintf(buffer, "Subject :
\n"); + sprintf(buffer, "Subject :
\n"); if (len + strlen(buffer) > max_len - 1) { max_len += 4096; page = (char *)realloc(page, max_len); @@ -940,7 +940,7 @@ char *www_new_msg(struct user_record *user, int conference, int area) { strcat(page, buffer); len += strlen(buffer); - sprintf(buffer, "\n
"); + sprintf(buffer, "\n
"); if (len + strlen(buffer) > max_len - 1) { max_len += 4096; page = (char *)realloc(page, max_len); From 7d0c55885c43ade84d851b4bb5ce330630136b46 Mon Sep 17 00:00:00 2001 From: Andrew Pamment Date: Thu, 25 Jan 2018 20:25:17 +1000 Subject: [PATCH 19/87] fix crash on garbage input in www server --- src/www.c | 50 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/src/www.c b/src/www.c index a3163fb..732d48a 100644 --- a/src/www.c +++ b/src/www.c @@ -307,6 +307,7 @@ int www_403(char *header, char *footer, struct MHD_Connection * connection) { struct MHD_Response *response; int ret; FILE *fptr; + char *endptr; snprintf(buffer, PATH_MAX, "%s/403.tpl", conf.www_path); @@ -417,6 +418,8 @@ int www_handler(void * cls, struct MHD_Connection * connection, const char * url int skip; char *replyid; char *filename; + int email; + char *endptr; // char *static_buffer; if (strcmp(method, "GET") == 0) { @@ -613,8 +616,8 @@ int www_handler(void * cls, struct MHD_Connection * connection, const char * url free(footer); return MHD_YES; } - - if (!www_email_delete(con_inf->user, atoi(&url[14]))) { + email = strtol(&url[14], &endptr, 10); + if (email == -1 || !www_email_delete(con_inf->user, email)) { page = (char *)malloc(31); if (page == NULL) { free(header); @@ -648,7 +651,13 @@ int www_handler(void * cls, struct MHD_Connection * connection, const char * url free(footer); return MHD_YES; } - page = www_email_display(con_inf->user, atoi(&url[7])); + email = strtol(&url[7], &endptr, 10); + if (email == -1) { + free(header); + free(footer); + return MHD_NO; + } + page = www_email_display(con_inf->user, email); if (page == NULL) { free(header); free(footer); @@ -690,10 +699,16 @@ int www_handler(void * cls, struct MHD_Connection * connection, const char * url aptr = strtok(url_copy, "/"); if (aptr != NULL) { - conference = atoi(aptr); + conference = strtol(aptr, &endptr, 10); + if (endptr == aptr) { + conference = -1; + } aptr = strtok(NULL, "/"); if (aptr != NULL) { - area = atoi(aptr); + area = strtol(aptr, &endptr, 10); + if (endptr == aptr) { + area = -1; + } } } free(url_copy); @@ -724,13 +739,22 @@ int www_handler(void * cls, struct MHD_Connection * connection, const char * url aptr = strtok(url_copy, "/"); if (aptr != NULL) { - conference = atoi(aptr); + conference = strtol(aptr, &endptr, 10); + if (endptr == aptr) { + conference = -1; + } aptr = strtok(NULL, "/"); if (aptr != NULL) { - area = atoi(aptr); + area = strtol(aptr, &endptr, 10); + if (endptr == aptr) { + area = -1; + } aptr = strtok(NULL, "/"); if (aptr != NULL) { - msg = atoi(aptr); + msg = strtol(aptr, &endptr, 10); + if (endptr == aptr) { + msg = -1; + } } } } @@ -974,9 +998,15 @@ int www_handler(void * cls, struct MHD_Connection * connection, const char * url } else if (strcmp(con_inf->keys[i], "body") == 0) { body = con_inf->values[i]; } else if (strcmp(con_inf->keys[i], "conference") == 0) { - conference = atoi(con_inf->values[i]); + conference = strtol(con_inf->values[i], &endptr, 10); + if (endptr == con_inf->values[i]) { + conference = -1; + } } else if (strcmp(con_inf->keys[i], "area") == 0) { - area = atoi(con_inf->values[i]); + area = strtol(con_inf->values[i], &endptr, 10); + if (endptr == con_inf->values[i]) { + area = -1; + } } else if (strcmp(con_inf->keys[i], "replyid") == 0) { replyid = con_inf->values[i]; } From 133555c1d18ab7d5d28f732abf932d4933db34e4 Mon Sep 17 00:00:00 2001 From: Andrew Pamment Date: Thu, 25 Jan 2018 20:34:26 +1000 Subject: [PATCH 20/87] fix again for garbage input --- src/www.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/www.c b/src/www.c index 732d48a..25ed557 100644 --- a/src/www.c +++ b/src/www.c @@ -422,6 +422,8 @@ int www_handler(void * cls, struct MHD_Connection * connection, const char * url char *endptr; // char *static_buffer; + page = NULL; + if (strcmp(method, "GET") == 0) { if (*ptr == NULL) { con_inf = (struct connection_info_s *)malloc(sizeof(struct connection_info_s)); From 732055b4a28b4209ff48f4fa29ff4d2973a2ae02 Mon Sep 17 00:00:00 2001 From: Andrew Pamment Date: Fri, 26 Jan 2018 07:50:52 +1000 Subject: [PATCH 21/87] experiment with aha modification --- deps/aha/aha.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/deps/aha/aha.c b/deps/aha/aha.c index c99e39c..faa53de 100644 --- a/deps/aha/aha.c +++ b/deps/aha/aha.c @@ -359,9 +359,9 @@ char * aha(char *input) else if (c==13) { - for (;line<80;line++) + //for (;line<80;line++) - append_output(&output, " ", &size, &outat); + // append_output(&output, " ", &size, &outat); line=0; momline++; append_output(&output, "
\n", &size, &outat); @@ -520,7 +520,7 @@ char * aha(char *input) case '\xda' : append_output(&output, "┌", &size, &outat); break; case '\xdb' : append_output(&output, "█", &size, &outat); break; case '\xdc' : append_output(&output, "▄", &size, &outat); break; - case '\xdd' : append_output(&output, "▼", &size, &outat); break; + case '\xdd' : append_output(&output, "▌", &size, &outat); break; case '\xde' : append_output(&output, "▐", &size, &outat); break; case '\xdf' : append_output(&output, "▀", &size, &outat); break; case '\xe0' : append_output(&output, "α", &size, &outat); break; From b6f5623826e94b7b45bef2ab98febdc1d306c4d2 Mon Sep 17 00:00:00 2001 From: Andrew Pamment Date: Fri, 26 Jan 2018 08:19:13 +1000 Subject: [PATCH 22/87] work on mobile site --- dist/www-bootstrap/header.tpl | 12 +- dist/www-bootstrap/static/header-m.png | Bin 0 -> 4239 bytes dist/www-bootstrap/static/style-mobile.css | 370 +++++++++++++++++++++ dist/www-bootstrap/static/style.css | 6 +- dist/www/static/style.css | 2 + src/www_email.c | 4 +- 6 files changed, 387 insertions(+), 7 deletions(-) create mode 100644 dist/www-bootstrap/static/header-m.png create mode 100644 dist/www-bootstrap/static/style-mobile.css diff --git a/dist/www-bootstrap/header.tpl b/dist/www-bootstrap/header.tpl index 38d8d2d..a2db158 100644 --- a/dist/www-bootstrap/header.tpl +++ b/dist/www-bootstrap/header.tpl @@ -12,7 +12,8 @@ - + + ",rE:!0,sL:"css"}},{cN:"tag",b:"|$)",e:">",k:{title:"script"},c:[c],starts:{e:"",rE:!0,sL:""}},s,{cN:"pi",b:/<\?\w+/,e:/\?>/,r:10},{cN:"tag",b:"",c:[{cN:"title",b:/[^ \/><\n\t]+/,r:0},c]}]}});hljs.registerLanguage("autohotkey",function(e){var r={cN:"escape",b:"`[\\s\\S]"},c=e.C(";","$",{r:0}),n=[{cN:"built_in",b:"A_[a-zA-Z0-9]+"},{cN:"built_in",bK:"ComSpec Clipboard ClipboardAll ErrorLevel"}];return{cI:!0,k:{keyword:"Break Continue Else Gosub If Loop Return While",literal:"A true false NOT AND OR"},c:n.concat([r,e.inherit(e.QSM,{c:[r]}),c,{cN:"number",b:e.NR,r:0},{cN:"var_expand",b:"%",e:"%",i:"\\n",c:[r]},{cN:"label",c:[r],v:[{b:'^[^\\n";]+::(?!=)'},{b:'^[^\\n";]+:(?!=)',r:0}]},{b:",\\s*,",r:10}])}});hljs.registerLanguage("r",function(e){var r="([a-zA-Z]|\\.[a-zA-Z.])[a-zA-Z0-9._]*";return{c:[e.HCM,{b:r,l:r,k:{keyword:"function if in break next repeat else for return switch while try tryCatch stop warning require library attach detach source setMethod setGeneric setGroupGeneric setClass ...",literal:"NULL NA TRUE FALSE T F Inf NaN NA_integer_|10 NA_real_|10 NA_character_|10 NA_complex_|10"},r:0},{cN:"number",b:"0[xX][0-9a-fA-F]+[Li]?\\b",r:0},{cN:"number",b:"\\d+(?:[eE][+\\-]?\\d*)?L\\b",r:0},{cN:"number",b:"\\d+\\.(?!\\d)(?:i\\b)?",r:0},{cN:"number",b:"\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d*)?i?\\b",r:0},{cN:"number",b:"\\.\\d+(?:[eE][+\\-]?\\d*)?i?\\b",r:0},{b:"`",e:"`",r:0},{cN:"string",c:[e.BE],v:[{b:'"',e:'"'},{b:"'",e:"'"}]}]}});hljs.registerLanguage("cs",function(e){var r="abstract as base bool break byte case catch char checked const continue decimal dynamic default delegate do double else enum event explicit extern false finally fixed float for foreach goto if implicit in int interface internal is lock long null when object operator out override params private protected public readonly ref sbyte sealed short sizeof stackalloc static string struct switch this true try typeof uint ulong unchecked unsafe ushort using virtual volatile void while async protected public private internal ascending descending from get group into join let orderby partial select set value var where yield",t=e.IR+"(<"+e.IR+">)?";return{aliases:["csharp"],k:r,i:/::/,c:[e.C("///","$",{rB:!0,c:[{cN:"xmlDocTag",v:[{b:"///",r:0},{b:""},{b:""}]}]}),e.CLCM,e.CBCM,{cN:"preprocessor",b:"#",e:"$",k:"if else elif endif define undef warning error line region endregion pragma checksum"},{cN:"string",b:'@"',e:'"',c:[{b:'""'}]},e.ASM,e.QSM,e.CNM,{bK:"class namespace interface",e:/[{;=]/,i:/[^\s:]/,c:[e.TM,e.CLCM,e.CBCM]},{bK:"new return throw await",r:0},{cN:"function",b:"("+t+"\\s+)+"+e.IR+"\\s*\\(",rB:!0,e:/[{;=]/,eE:!0,k:r,c:[{b:e.IR+"\\s*\\(",rB:!0,c:[e.TM],r:0},{cN:"params",b:/\(/,e:/\)/,k:r,r:0,c:[e.ASM,e.QSM,e.CNM,e.CBCM]},e.CLCM,e.CBCM]}]}});hljs.registerLanguage("nsis",function(e){var t={cN:"symbol",b:"\\$(ADMINTOOLS|APPDATA|CDBURN_AREA|CMDLINE|COMMONFILES32|COMMONFILES64|COMMONFILES|COOKIES|DESKTOP|DOCUMENTS|EXEDIR|EXEFILE|EXEPATH|FAVORITES|FONTS|HISTORY|HWNDPARENT|INSTDIR|INTERNET_CACHE|LANGUAGE|LOCALAPPDATA|MUSIC|NETHOOD|OUTDIR|PICTURES|PLUGINSDIR|PRINTHOOD|PROFILE|PROGRAMFILES32|PROGRAMFILES64|PROGRAMFILES|QUICKLAUNCH|RECENT|RESOURCES_LOCALIZED|RESOURCES|SENDTO|SMPROGRAMS|SMSTARTUP|STARTMENU|SYSDIR|TEMP|TEMPLATES|VIDEOS|WINDIR)"},n={cN:"constant",b:"\\$+{[a-zA-Z0-9_]+}"},i={cN:"variable",b:"\\$+[a-zA-Z0-9_]+",i:"\\(\\){}"},r={cN:"constant",b:"\\$+\\([a-zA-Z0-9_]+\\)"},o={cN:"params",b:"(ARCHIVE|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_NORMAL|FILE_ATTRIBUTE_OFFLINE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_TEMPORARY|HKCR|HKCU|HKDD|HKEY_CLASSES_ROOT|HKEY_CURRENT_CONFIG|HKEY_CURRENT_USER|HKEY_DYN_DATA|HKEY_LOCAL_MACHINE|HKEY_PERFORMANCE_DATA|HKEY_USERS|HKLM|HKPD|HKU|IDABORT|IDCANCEL|IDIGNORE|IDNO|IDOK|IDRETRY|IDYES|MB_ABORTRETRYIGNORE|MB_DEFBUTTON1|MB_DEFBUTTON2|MB_DEFBUTTON3|MB_DEFBUTTON4|MB_ICONEXCLAMATION|MB_ICONINFORMATION|MB_ICONQUESTION|MB_ICONSTOP|MB_OK|MB_OKCANCEL|MB_RETRYCANCEL|MB_RIGHT|MB_RTLREADING|MB_SETFOREGROUND|MB_TOPMOST|MB_USERICON|MB_YESNO|NORMAL|OFFLINE|READONLY|SHCTX|SHELL_CONTEXT|SYSTEM|TEMPORARY)"},l={cN:"constant",b:"\\!(addincludedir|addplugindir|appendfile|cd|define|delfile|echo|else|endif|error|execute|finalize|getdllversionsystem|ifdef|ifmacrodef|ifmacrondef|ifndef|if|include|insertmacro|macroend|macro|makensis|packhdr|searchparse|searchreplace|tempfile|undef|verbose|warning)"};return{cI:!1,k:{keyword:"Abort AddBrandingImage AddSize AllowRootDirInstall AllowSkipFiles AutoCloseWindow BGFont BGGradient BrandingText BringToFront Call CallInstDLL Caption ChangeUI CheckBitmap ClearErrors CompletedText ComponentText CopyFiles CRCCheck CreateDirectory CreateFont CreateShortCut Delete DeleteINISec DeleteINIStr DeleteRegKey DeleteRegValue DetailPrint DetailsButtonText DirText DirVar DirVerify EnableWindow EnumRegKey EnumRegValue Exch Exec ExecShell ExecWait ExpandEnvStrings File FileBufSize FileClose FileErrorText FileOpen FileRead FileReadByte FileReadUTF16LE FileReadWord FileSeek FileWrite FileWriteByte FileWriteUTF16LE FileWriteWord FindClose FindFirst FindNext FindWindow FlushINI FunctionEnd GetCurInstType GetCurrentAddress GetDlgItem GetDLLVersion GetDLLVersionLocal GetErrorLevel GetFileTime GetFileTimeLocal GetFullPathName GetFunctionAddress GetInstDirError GetLabelAddress GetTempFileName Goto HideWindow Icon IfAbort IfErrors IfFileExists IfRebootFlag IfSilent InitPluginsDir InstallButtonText InstallColors InstallDir InstallDirRegKey InstProgressFlags InstType InstTypeGetText InstTypeSetText IntCmp IntCmpU IntFmt IntOp IsWindow LangString LicenseBkColor LicenseData LicenseForceSelection LicenseLangString LicenseText LoadLanguageFile LockWindow LogSet LogText ManifestDPIAware ManifestSupportedOS MessageBox MiscButtonText Name Nop OutFile Page PageCallbacks PageExEnd Pop Push Quit ReadEnvStr ReadINIStr ReadRegDWORD ReadRegStr Reboot RegDLL Rename RequestExecutionLevel ReserveFile Return RMDir SearchPath SectionEnd SectionGetFlags SectionGetInstTypes SectionGetSize SectionGetText SectionGroupEnd SectionIn SectionSetFlags SectionSetInstTypes SectionSetSize SectionSetText SendMessage SetAutoClose SetBrandingImage SetCompress SetCompressor SetCompressorDictSize SetCtlColors SetCurInstType SetDatablockOptimize SetDateSave SetDetailsPrint SetDetailsView SetErrorLevel SetErrors SetFileAttributes SetFont SetOutPath SetOverwrite SetPluginUnload SetRebootFlag SetRegView SetShellVarContext SetSilent ShowInstDetails ShowUninstDetails ShowWindow SilentInstall SilentUnInstall Sleep SpaceTexts StrCmp StrCmpS StrCpy StrLen SubCaption SubSectionEnd Unicode UninstallButtonText UninstallCaption UninstallIcon UninstallSubCaption UninstallText UninstPage UnRegDLL Var VIAddVersionKey VIFileVersion VIProductVersion WindowIcon WriteINIStr WriteRegBin WriteRegDWORD WriteRegExpandStr WriteRegStr WriteUninstaller XPStyle",literal:"admin all auto both colored current false force hide highest lastused leave listonly none normal notset off on open print show silent silentlog smooth textonly true user "},c:[e.HCM,e.CBCM,{cN:"string",b:'"',e:'"',i:"\\n",c:[{cN:"symbol",b:"\\$(\\\\(n|r|t)|\\$)"},t,n,i,r]},e.C(";","$",{r:0}),{cN:"function",bK:"Function PageEx Section SectionGroup SubSection",e:"$"},l,n,i,r,o,e.NM,{cN:"literal",b:e.IR+"::"+e.IR}]}});hljs.registerLanguage("less",function(e){var r="[\\w-]+",t="("+r+"|@{"+r+"})",a=[],c=[],n=function(e){return{cN:"string",b:"~?"+e+".*?"+e}},i=function(e,r,t){return{cN:e,b:r,r:t}},s=function(r,t,a){return e.inherit({cN:r,b:t+"\\(",e:"\\(",rB:!0,eE:!0,r:0},a)},b={b:"\\(",e:"\\)",c:c,r:0};c.push(e.CLCM,e.CBCM,n("'"),n('"'),e.CSSNM,i("hexcolor","#[0-9A-Fa-f]+\\b"),s("function","(url|data-uri)",{starts:{cN:"string",e:"[\\)\\n]",eE:!0}}),s("function",r),b,i("variable","@@?"+r,10),i("variable","@{"+r+"}"),i("built_in","~?`[^`]*?`"),{cN:"attribute",b:r+"\\s*:",e:":",rB:!0,eE:!0});var o=c.concat({b:"{",e:"}",c:a}),u={bK:"when",eW:!0,c:[{bK:"and not"}].concat(c)},C={cN:"attribute",b:t,e:":",eE:!0,c:[e.CLCM,e.CBCM],i:/\S/,starts:{e:"[;}]",rE:!0,c:c,i:"[<=$]"}},l={cN:"at_rule",b:"@(import|media|charset|font-face|(-[a-z]+-)?keyframes|supports|document|namespace|page|viewport|host)\\b",starts:{e:"[;{}]",rE:!0,c:c,r:0}},d={cN:"variable",v:[{b:"@"+r+"\\s*:",r:15},{b:"@"+r}],starts:{e:"[;}]",rE:!0,c:o}},p={v:[{b:"[\\.#:&\\[]",e:"[;{}]"},{b:t+"[^;]*{",e:"{"}],rB:!0,rE:!0,i:"[<='$\"]",c:[e.CLCM,e.CBCM,u,i("keyword","all\\b"),i("variable","@{"+r+"}"),i("tag",t+"%?",0),i("id","#"+t),i("class","\\."+t,0),i("keyword","&",0),s("pseudo",":not"),s("keyword",":extend"),i("pseudo","::?"+t),{cN:"attr_selector",b:"\\[",e:"\\]"},{b:"\\(",e:"\\)",c:o},{b:"!important"}]};return a.push(e.CLCM,e.CBCM,l,d,p,C),{cI:!0,i:"[=>'/<($\"]",c:a}});hljs.registerLanguage("pf",function(t){var o={cN:"variable",b:/\$[\w\d#@][\w\d_]*/},e={cN:"variable",b://};return{aliases:["pf.conf"],l:/[a-z0-9_<>-]+/,k:{built_in:"block match pass load anchor|5 antispoof|10 set table",keyword:"in out log quick on rdomain inet inet6 proto from port os to routeallow-opts divert-packet divert-reply divert-to flags group icmp-typeicmp6-type label once probability recieved-on rtable prio queuetos tag tagged user keep fragment for os dropaf-to|10 binat-to|10 nat-to|10 rdr-to|10 bitmask least-stats random round-robinsource-hash static-portdup-to reply-to route-toparent bandwidth default min max qlimitblock-policy debug fingerprints hostid limit loginterface optimizationreassemble ruleset-optimization basic none profile skip state-defaultsstate-policy timeoutconst counters persistno modulate synproxy state|5 floating if-bound no-sync pflow|10 sloppysource-track global rule max-src-nodes max-src-states max-src-connmax-src-conn-rate overload flushscrub|5 max-mss min-ttl no-df|10 random-id",literal:"all any no-route self urpf-failed egress|5 unknown"},c:[t.HCM,t.NM,t.QSM,o,e]}});hljs.registerLanguage("lasso",function(e){var r="[a-zA-Z_][a-zA-Z0-9_.]*",a="<\\?(lasso(script)?|=)",t="\\]|\\?>",s={literal:"true false none minimal full all void and or not bw nbw ew new cn ncn lt lte gt gte eq neq rx nrx ft",built_in:"array date decimal duration integer map pair string tag xml null boolean bytes keyword list locale queue set stack staticarray local var variable global data self inherited",keyword:"error_code error_msg error_pop error_push error_reset cache database_names database_schemanames database_tablenames define_tag define_type email_batch encode_set html_comment handle handle_error header if inline iterate ljax_target link link_currentaction link_currentgroup link_currentrecord link_detail link_firstgroup link_firstrecord link_lastgroup link_lastrecord link_nextgroup link_nextrecord link_prevgroup link_prevrecord log loop namespace_using output_none portal private protect records referer referrer repeating resultset rows search_args search_arguments select sort_args sort_arguments thread_atomic value_list while abort case else if_empty if_false if_null if_true loop_abort loop_continue loop_count params params_up return return_value run_children soap_definetag soap_lastrequest soap_lastresponse tag_name ascending average by define descending do equals frozen group handle_failure import in into join let match max min on order parent protected provide public require returnhome skip split_thread sum take thread to trait type where with yield yieldhome"},n=e.C("",{r:0}),o={cN:"preprocessor",b:"\\[noprocess\\]",starts:{cN:"markup",e:"\\[/noprocess\\]",rE:!0,c:[n]}},i={cN:"preprocessor",b:"\\[/noprocess|"+a},l={cN:"variable",b:"'"+r+"'"},c=[e.CLCM,{cN:"javadoc",b:"/\\*\\*!",e:"\\*/",c:[e.PWM]},e.CBCM,e.inherit(e.CNM,{b:e.CNR+"|(-?infinity|nan)\\b"}),e.inherit(e.ASM,{i:null}),e.inherit(e.QSM,{i:null}),{cN:"string",b:"`",e:"`"},{cN:"variable",v:[{b:"[#$]"+r},{b:"#",e:"\\d+",i:"\\W"}]},{cN:"tag",b:"::\\s*",e:r,i:"\\W"},{cN:"attribute",v:[{b:"-"+e.UIR,r:0},{b:"(\\.\\.\\.)"}]},{cN:"subst",v:[{b:"->\\s*",c:[l]},{b:":=|/(?!\\w)=?|[-+*%=<>&|!?\\\\]+",r:0}]},{cN:"built_in",b:"\\.\\.?\\s*",r:0,c:[l]},{cN:"class",bK:"define",rE:!0,e:"\\(|=>",c:[e.inherit(e.TM,{b:e.UIR+"(=(?!>))?"})]}];return{aliases:["ls","lassoscript"],cI:!0,l:r+"|&[lg]t;",k:s,c:[{cN:"preprocessor",b:t,r:0,starts:{cN:"markup",e:"\\[|"+a,rE:!0,r:0,c:[n]}},o,i,{cN:"preprocessor",b:"\\[no_square_brackets",starts:{e:"\\[/no_square_brackets\\]",l:r+"|&[lg]t;",k:s,c:[{cN:"preprocessor",b:t,r:0,starts:{cN:"markup",e:"\\[noprocess\\]|"+a,rE:!0,c:[n]}},o,i].concat(c)}},{cN:"preprocessor",b:"\\[",r:0},{cN:"shebang",b:"^#!.+lasso9\\b",r:10}].concat(c)}});hljs.registerLanguage("prolog",function(c){var r={cN:"atom",b:/[a-z][A-Za-z0-9_]*/,r:0},b={cN:"name",v:[{b:/[A-Z][a-zA-Z0-9_]*/},{b:/_[A-Za-z0-9_]*/}],r:0},a={b:/\(/,e:/\)/,r:0},e={b:/\[/,e:/\]/},n={cN:"comment",b:/%/,e:/$/,c:[c.PWM]},t={cN:"string",b:/`/,e:/`/,c:[c.BE]},g={cN:"string",b:/0\'(\\\'|.)/},N={cN:"string",b:/0\'\\s/},o={b:/:-/},s=[r,b,a,o,e,n,c.CBCM,c.QSM,c.ASM,t,g,N,c.CNM];return a.c=s,e.c=s,{c:s.concat([{b:/\.$/}])}});hljs.registerLanguage("oxygene",function(e){var r="abstract add and array as asc aspect assembly async begin break block by case class concat const copy constructor continue create default delegate desc distinct div do downto dynamic each else empty end ensure enum equals event except exit extension external false final finalize finalizer finally flags for forward from function future global group has if implementation implements implies in index inherited inline interface into invariants is iterator join locked locking loop matching method mod module namespace nested new nil not notify nullable of old on operator or order out override parallel params partial pinned private procedure property protected public queryable raise read readonly record reintroduce remove repeat require result reverse sealed select self sequence set shl shr skip static step soft take then to true try tuple type union unit unsafe until uses using var virtual raises volatile where while with write xor yield await mapped deprecated stdcall cdecl pascal register safecall overload library platform reference packed strict published autoreleasepool selector strong weak unretained",t=e.C("{","}",{r:0}),a=e.C("\\(\\*","\\*\\)",{r:10}),n={cN:"string",b:"'",e:"'",c:[{b:"''"}]},o={cN:"string",b:"(#\\d+)+"},i={cN:"function",bK:"function constructor destructor procedure method",e:"[:;]",k:"function constructor|10 destructor|10 procedure|10 method|10",c:[e.TM,{cN:"params",b:"\\(",e:"\\)",k:r,c:[n,o]},t,a]};return{cI:!0,k:r,i:'("|\\$[G-Zg-z]|\\/\\*||->)',c:[t,a,e.CLCM,n,o,e.NM,i,{cN:"class",b:"=\\bclass\\b",e:"end;",k:r,c:[n,o,t,a,e.CLCM,i]}]}});hljs.registerLanguage("applescript",function(e){var t=e.inherit(e.QSM,{i:""}),r={cN:"params",b:"\\(",e:"\\)",c:["self",e.CNM,t]},o=e.C("--","$"),n=e.C("\\(\\*","\\*\\)",{c:["self",o]}),a=[o,n,e.HCM];return{aliases:["osascript"],k:{keyword:"about above after against and around as at back before beginning behind below beneath beside between but by considering contain contains continue copy div does eighth else end equal equals error every exit fifth first for fourth from front get given global if ignoring in into is it its last local me middle mod my ninth not of on onto or over prop property put ref reference repeat returning script second set seventh since sixth some tell tenth that the|0 then third through thru timeout times to transaction try until where while whose with without",constant:"AppleScript false linefeed return pi quote result space tab true",type:"alias application boolean class constant date file integer list number real record string text",command:"activate beep count delay launch log offset read round run say summarize write",property:"character characters contents day frontmost id item length month name paragraph paragraphs rest reverse running time version weekday word words year"},c:[t,e.CNM,{cN:"type",b:"\\bPOSIX file\\b"},{cN:"command",b:"\\b(clipboard info|the clipboard|info for|list (disks|folder)|mount volume|path to|(close|open for) access|(get|set) eof|current date|do shell script|get volume settings|random number|set volume|system attribute|system info|time to GMT|(load|run|store) script|scripting components|ASCII (character|number)|localized string|choose (application|color|file|file name|folder|from list|remote application|URL)|display (alert|dialog))\\b|^\\s*return\\b"},{cN:"constant",b:"\\b(text item delimiters|current application|missing value)\\b"},{cN:"keyword",b:"\\b(apart from|aside from|instead of|out of|greater than|isn't|(doesn't|does not) (equal|come before|come after|contain)|(greater|less) than( or equal)?|(starts?|ends|begins?) with|contained by|comes (before|after)|a (ref|reference))\\b"},{cN:"property",b:"\\b(POSIX path|(date|time) string|quoted form)\\b"},{cN:"function_start",bK:"on",i:"[${=;\\n]",c:[e.UTM,r]}].concat(a),i:"//|->|=>"}});hljs.registerLanguage("makefile",function(e){var a={cN:"variable",b:/\$\(/,e:/\)/,c:[e.BE]};return{aliases:["mk","mak"],c:[e.HCM,{b:/^\w+\s*\W*=/,rB:!0,r:0,starts:{cN:"constant",e:/\s*\W*=/,eE:!0,starts:{e:/$/,r:0,c:[a]}}},{cN:"title",b:/^[\w]+:\s*$/},{cN:"phony",b:/^\.PHONY:/,e:/$/,k:".PHONY",l:/[\.\w]+/},{b:/^\t+/,e:/$/,r:0,c:[e.QSM,a]}]}});hljs.registerLanguage("dust",function(e){var a="if eq ne lt lte gt gte select default math sep";return{aliases:["dst"],cI:!0,sL:"xml",subLanguageMode:"continuous",c:[{cN:"expression",b:"{",e:"}",r:0,c:[{cN:"begin-block",b:"#[a-zA-Z- .]+",k:a},{cN:"string",b:'"',e:'"'},{cN:"end-block",b:"\\/[a-zA-Z- .]+",k:a},{cN:"variable",b:"[a-zA-Z-.]+",k:a,r:0}]}]}});hljs.registerLanguage("clojure-repl",function(e){return{c:[{cN:"prompt",b:/^([\w.-]+|\s*#_)=>/,starts:{e:/$/,sL:"clojure",subLanguageMode:"continuous"}}]}});hljs.registerLanguage("dart",function(e){var t={cN:"subst",b:"\\$\\{",e:"}",k:"true false null this is new super"},r={cN:"string",v:[{b:"r'''",e:"'''"},{b:'r"""',e:'"""'},{b:"r'",e:"'",i:"\\n"},{b:'r"',e:'"',i:"\\n"},{b:"'''",e:"'''",c:[e.BE,t]},{b:'"""',e:'"""',c:[e.BE,t]},{b:"'",e:"'",i:"\\n",c:[e.BE,t]},{b:'"',e:'"',i:"\\n",c:[e.BE,t]}]};t.c=[e.CNM,r];var n={keyword:"assert break case catch class const continue default do else enum extends false final finally for if in is new null rethrow return super switch this throw true try var void while with",literal:"abstract as dynamic export external factory get implements import library operator part set static typedef",built_in:"print Comparable DateTime Duration Function Iterable Iterator List Map Match Null Object Pattern RegExp Set Stopwatch String StringBuffer StringSink Symbol Type Uri bool double int num document window querySelector querySelectorAll Element ElementList"};return{k:n,c:[r,{cN:"dartdoc",b:"/\\*\\*",e:"\\*/",sL:"markdown",subLanguageMode:"continuous"},{cN:"dartdoc",b:"///",e:"$",sL:"markdown",subLanguageMode:"continuous"},e.CLCM,e.CBCM,{cN:"class",bK:"class interface",e:"{",eE:!0,c:[{bK:"extends implements"},e.UTM]},e.CNM,{cN:"annotation",b:"@[A-Za-z]+"},{b:"=>"}]}}); \ No newline at end of file diff --git a/docs/cinder/js/jquery-1.10.2.min.js b/docs/cinder/js/jquery-1.10.2.min.js new file mode 100644 index 0000000..da41706 --- /dev/null +++ b/docs/cinder/js/jquery-1.10.2.min.js @@ -0,0 +1,6 @@ +/*! jQuery v1.10.2 | (c) 2005, 2013 jQuery Foundation, Inc. | jquery.org/license +//@ sourceMappingURL=jquery-1.10.2.min.map +*/ +(function(e,t){var n,r,i=typeof t,o=e.location,a=e.document,s=a.documentElement,l=e.jQuery,u=e.$,c={},p=[],f="1.10.2",d=p.concat,h=p.push,g=p.slice,m=p.indexOf,y=c.toString,v=c.hasOwnProperty,b=f.trim,x=function(e,t){return new x.fn.init(e,t,r)},w=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,T=/\S+/g,C=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,N=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,k=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,E=/^[\],:{}\s]*$/,S=/(?:^|:|,)(?:\s*\[)+/g,A=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,j=/"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,D=/^-ms-/,L=/-([\da-z])/gi,H=function(e,t){return t.toUpperCase()},q=function(e){(a.addEventListener||"load"===e.type||"complete"===a.readyState)&&(_(),x.ready())},_=function(){a.addEventListener?(a.removeEventListener("DOMContentLoaded",q,!1),e.removeEventListener("load",q,!1)):(a.detachEvent("onreadystatechange",q),e.detachEvent("onload",q))};x.fn=x.prototype={jquery:f,constructor:x,init:function(e,n,r){var i,o;if(!e)return this;if("string"==typeof e){if(i="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:N.exec(e),!i||!i[1]&&n)return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e);if(i[1]){if(n=n instanceof x?n[0]:n,x.merge(this,x.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:a,!0)),k.test(i[1])&&x.isPlainObject(n))for(i in n)x.isFunction(this[i])?this[i](n[i]):this.attr(i,n[i]);return this}if(o=a.getElementById(i[2]),o&&o.parentNode){if(o.id!==i[2])return r.find(e);this.length=1,this[0]=o}return this.context=a,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):x.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),x.makeArray(e,this))},selector:"",length:0,toArray:function(){return g.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=x.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return x.each(this,e,t)},ready:function(e){return x.ready.promise().done(e),this},slice:function(){return this.pushStack(g.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(x.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:h,sort:[].sort,splice:[].splice},x.fn.init.prototype=x.fn,x.extend=x.fn.extend=function(){var e,n,r,i,o,a,s=arguments[0]||{},l=1,u=arguments.length,c=!1;for("boolean"==typeof s&&(c=s,s=arguments[1]||{},l=2),"object"==typeof s||x.isFunction(s)||(s={}),u===l&&(s=this,--l);u>l;l++)if(null!=(o=arguments[l]))for(i in o)e=s[i],r=o[i],s!==r&&(c&&r&&(x.isPlainObject(r)||(n=x.isArray(r)))?(n?(n=!1,a=e&&x.isArray(e)?e:[]):a=e&&x.isPlainObject(e)?e:{},s[i]=x.extend(c,a,r)):r!==t&&(s[i]=r));return s},x.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),noConflict:function(t){return e.$===x&&(e.$=u),t&&e.jQuery===x&&(e.jQuery=l),x},isReady:!1,readyWait:1,holdReady:function(e){e?x.readyWait++:x.ready(!0)},ready:function(e){if(e===!0?!--x.readyWait:!x.isReady){if(!a.body)return setTimeout(x.ready);x.isReady=!0,e!==!0&&--x.readyWait>0||(n.resolveWith(a,[x]),x.fn.trigger&&x(a).trigger("ready").off("ready"))}},isFunction:function(e){return"function"===x.type(e)},isArray:Array.isArray||function(e){return"array"===x.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?c[y.call(e)]||"object":typeof e},isPlainObject:function(e){var n;if(!e||"object"!==x.type(e)||e.nodeType||x.isWindow(e))return!1;try{if(e.constructor&&!v.call(e,"constructor")&&!v.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(r){return!1}if(x.support.ownLast)for(n in e)return v.call(e,n);for(n in e);return n===t||v.call(e,n)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||a;var r=k.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=x.buildFragment([e],t,i),i&&x(i).remove(),x.merge([],r.childNodes))},parseJSON:function(n){return e.JSON&&e.JSON.parse?e.JSON.parse(n):null===n?n:"string"==typeof n&&(n=x.trim(n),n&&E.test(n.replace(A,"@").replace(j,"]").replace(S,"")))?Function("return "+n)():(x.error("Invalid JSON: "+n),t)},parseXML:function(n){var r,i;if(!n||"string"!=typeof n)return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(o){r=t}return r&&r.documentElement&&!r.getElementsByTagName("parsererror").length||x.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&x.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(D,"ms-").replace(L,H)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,a=M(e);if(n){if(a){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(a){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:b&&!b.call("\ufeff\u00a0")?function(e){return null==e?"":b.call(e)}:function(e){return null==e?"":(e+"").replace(C,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(M(Object(e))?x.merge(n,"string"==typeof e?[e]:e):h.call(n,e)),n},inArray:function(e,t,n){var r;if(t){if(m)return m.call(t,e,n);for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,o=0;if("number"==typeof r)for(;r>o;o++)e[i++]=n[o];else while(n[o]!==t)e[i++]=n[o++];return e.length=i,e},grep:function(e,t,n){var r,i=[],o=0,a=e.length;for(n=!!n;a>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,a=M(e),s=[];if(a)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(s[s.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(s[s.length]=r);return d.apply([],s)},guid:1,proxy:function(e,n){var r,i,o;return"string"==typeof n&&(o=e[n],n=e,e=o),x.isFunction(e)?(r=g.call(arguments,2),i=function(){return e.apply(n||this,r.concat(g.call(arguments)))},i.guid=e.guid=e.guid||x.guid++,i):t},access:function(e,n,r,i,o,a,s){var l=0,u=e.length,c=null==r;if("object"===x.type(r)){o=!0;for(l in r)x.access(e,n,l,r[l],!0,a,s)}else if(i!==t&&(o=!0,x.isFunction(i)||(s=!0),c&&(s?(n.call(e,i),n=null):(c=n,n=function(e,t,n){return c.call(x(e),n)})),n))for(;u>l;l++)n(e[l],r,s?i:i.call(e[l],l,n(e[l],r)));return o?e:c?n.call(e):u?n(e[0],r):a},now:function(){return(new Date).getTime()},swap:function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i}}),x.ready.promise=function(t){if(!n)if(n=x.Deferred(),"complete"===a.readyState)setTimeout(x.ready);else if(a.addEventListener)a.addEventListener("DOMContentLoaded",q,!1),e.addEventListener("load",q,!1);else{a.attachEvent("onreadystatechange",q),e.attachEvent("onload",q);var r=!1;try{r=null==e.frameElement&&a.documentElement}catch(i){}r&&r.doScroll&&function o(){if(!x.isReady){try{r.doScroll("left")}catch(e){return setTimeout(o,50)}_(),x.ready()}}()}return n.promise(t)},x.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){c["[object "+t+"]"]=t.toLowerCase()});function M(e){var t=e.length,n=x.type(e);return x.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}r=x(a),function(e,t){var n,r,i,o,a,s,l,u,c,p,f,d,h,g,m,y,v,b="sizzle"+-new Date,w=e.document,T=0,C=0,N=st(),k=st(),E=st(),S=!1,A=function(e,t){return e===t?(S=!0,0):0},j=typeof t,D=1<<31,L={}.hasOwnProperty,H=[],q=H.pop,_=H.push,M=H.push,O=H.slice,F=H.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},B="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",P="[\\x20\\t\\r\\n\\f]",R="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",W=R.replace("w","w#"),$="\\["+P+"*("+R+")"+P+"*(?:([*^$|!~]?=)"+P+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+W+")|)|)"+P+"*\\]",I=":("+R+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+$.replace(3,8)+")*)|.*)\\)|)",z=RegExp("^"+P+"+|((?:^|[^\\\\])(?:\\\\.)*)"+P+"+$","g"),X=RegExp("^"+P+"*,"+P+"*"),U=RegExp("^"+P+"*([>+~]|"+P+")"+P+"*"),V=RegExp(P+"*[+~]"),Y=RegExp("="+P+"*([^\\]'\"]*)"+P+"*\\]","g"),J=RegExp(I),G=RegExp("^"+W+"$"),Q={ID:RegExp("^#("+R+")"),CLASS:RegExp("^\\.("+R+")"),TAG:RegExp("^("+R.replace("w","w*")+")"),ATTR:RegExp("^"+$),PSEUDO:RegExp("^"+I),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+P+"*(even|odd|(([+-]|)(\\d*)n|)"+P+"*(?:([+-]|)"+P+"*(\\d+)|))"+P+"*\\)|)","i"),bool:RegExp("^(?:"+B+")$","i"),needsContext:RegExp("^"+P+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+P+"*((?:-\\d)?\\d*)"+P+"*\\)|)(?=[^-]|$)","i")},K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,et=/^(?:input|select|textarea|button)$/i,tt=/^h\d$/i,nt=/'|\\/g,rt=RegExp("\\\\([\\da-f]{1,6}"+P+"?|("+P+")|.)","ig"),it=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:0>r?String.fromCharCode(r+65536):String.fromCharCode(55296|r>>10,56320|1023&r)};try{M.apply(H=O.call(w.childNodes),w.childNodes),H[w.childNodes.length].nodeType}catch(ot){M={apply:H.length?function(e,t){_.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function at(e,t,n,i){var o,a,s,l,u,c,d,m,y,x;if((t?t.ownerDocument||t:w)!==f&&p(t),t=t||f,n=n||[],!e||"string"!=typeof e)return n;if(1!==(l=t.nodeType)&&9!==l)return[];if(h&&!i){if(o=Z.exec(e))if(s=o[1]){if(9===l){if(a=t.getElementById(s),!a||!a.parentNode)return n;if(a.id===s)return n.push(a),n}else if(t.ownerDocument&&(a=t.ownerDocument.getElementById(s))&&v(t,a)&&a.id===s)return n.push(a),n}else{if(o[2])return M.apply(n,t.getElementsByTagName(e)),n;if((s=o[3])&&r.getElementsByClassName&&t.getElementsByClassName)return M.apply(n,t.getElementsByClassName(s)),n}if(r.qsa&&(!g||!g.test(e))){if(m=d=b,y=t,x=9===l&&e,1===l&&"object"!==t.nodeName.toLowerCase()){c=mt(e),(d=t.getAttribute("id"))?m=d.replace(nt,"\\$&"):t.setAttribute("id",m),m="[id='"+m+"'] ",u=c.length;while(u--)c[u]=m+yt(c[u]);y=V.test(e)&&t.parentNode||t,x=c.join(",")}if(x)try{return M.apply(n,y.querySelectorAll(x)),n}catch(T){}finally{d||t.removeAttribute("id")}}}return kt(e.replace(z,"$1"),t,n,i)}function st(){var e=[];function t(n,r){return e.push(n+=" ")>o.cacheLength&&delete t[e.shift()],t[n]=r}return t}function lt(e){return e[b]=!0,e}function ut(e){var t=f.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function ct(e,t){var n=e.split("|"),r=e.length;while(r--)o.attrHandle[n[r]]=t}function pt(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||D)-(~e.sourceIndex||D);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function ft(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function dt(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function ht(e){return lt(function(t){return t=+t,lt(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}s=at.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},r=at.support={},p=at.setDocument=function(e){var n=e?e.ownerDocument||e:w,i=n.defaultView;return n!==f&&9===n.nodeType&&n.documentElement?(f=n,d=n.documentElement,h=!s(n),i&&i.attachEvent&&i!==i.top&&i.attachEvent("onbeforeunload",function(){p()}),r.attributes=ut(function(e){return e.className="i",!e.getAttribute("className")}),r.getElementsByTagName=ut(function(e){return e.appendChild(n.createComment("")),!e.getElementsByTagName("*").length}),r.getElementsByClassName=ut(function(e){return e.innerHTML="
",e.firstChild.className="i",2===e.getElementsByClassName("i").length}),r.getById=ut(function(e){return d.appendChild(e).id=b,!n.getElementsByName||!n.getElementsByName(b).length}),r.getById?(o.find.ID=function(e,t){if(typeof t.getElementById!==j&&h){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){return e.getAttribute("id")===t}}):(delete o.find.ID,o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){var n=typeof e.getAttributeNode!==j&&e.getAttributeNode("id");return n&&n.value===t}}),o.find.TAG=r.getElementsByTagName?function(e,n){return typeof n.getElementsByTagName!==j?n.getElementsByTagName(e):t}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},o.find.CLASS=r.getElementsByClassName&&function(e,n){return typeof n.getElementsByClassName!==j&&h?n.getElementsByClassName(e):t},m=[],g=[],(r.qsa=K.test(n.querySelectorAll))&&(ut(function(e){e.innerHTML="",e.querySelectorAll("[selected]").length||g.push("\\["+P+"*(?:value|"+B+")"),e.querySelectorAll(":checked").length||g.push(":checked")}),ut(function(e){var t=n.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("t",""),e.querySelectorAll("[t^='']").length&&g.push("[*^$]="+P+"*(?:''|\"\")"),e.querySelectorAll(":enabled").length||g.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),g.push(",.*:")})),(r.matchesSelector=K.test(y=d.webkitMatchesSelector||d.mozMatchesSelector||d.oMatchesSelector||d.msMatchesSelector))&&ut(function(e){r.disconnectedMatch=y.call(e,"div"),y.call(e,"[s!='']:x"),m.push("!=",I)}),g=g.length&&RegExp(g.join("|")),m=m.length&&RegExp(m.join("|")),v=K.test(d.contains)||d.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},A=d.compareDocumentPosition?function(e,t){if(e===t)return S=!0,0;var i=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t);return i?1&i||!r.sortDetached&&t.compareDocumentPosition(e)===i?e===n||v(w,e)?-1:t===n||v(w,t)?1:c?F.call(c,e)-F.call(c,t):0:4&i?-1:1:e.compareDocumentPosition?-1:1}:function(e,t){var r,i=0,o=e.parentNode,a=t.parentNode,s=[e],l=[t];if(e===t)return S=!0,0;if(!o||!a)return e===n?-1:t===n?1:o?-1:a?1:c?F.call(c,e)-F.call(c,t):0;if(o===a)return pt(e,t);r=e;while(r=r.parentNode)s.unshift(r);r=t;while(r=r.parentNode)l.unshift(r);while(s[i]===l[i])i++;return i?pt(s[i],l[i]):s[i]===w?-1:l[i]===w?1:0},n):f},at.matches=function(e,t){return at(e,null,null,t)},at.matchesSelector=function(e,t){if((e.ownerDocument||e)!==f&&p(e),t=t.replace(Y,"='$1']"),!(!r.matchesSelector||!h||m&&m.test(t)||g&&g.test(t)))try{var n=y.call(e,t);if(n||r.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(i){}return at(t,f,null,[e]).length>0},at.contains=function(e,t){return(e.ownerDocument||e)!==f&&p(e),v(e,t)},at.attr=function(e,n){(e.ownerDocument||e)!==f&&p(e);var i=o.attrHandle[n.toLowerCase()],a=i&&L.call(o.attrHandle,n.toLowerCase())?i(e,n,!h):t;return a===t?r.attributes||!h?e.getAttribute(n):(a=e.getAttributeNode(n))&&a.specified?a.value:null:a},at.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},at.uniqueSort=function(e){var t,n=[],i=0,o=0;if(S=!r.detectDuplicates,c=!r.sortStable&&e.slice(0),e.sort(A),S){while(t=e[o++])t===e[o]&&(i=n.push(o));while(i--)e.splice(n[i],1)}return e},a=at.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=a(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=a(t);return n},o=at.selectors={cacheLength:50,createPseudo:lt,match:Q,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(rt,it),e[3]=(e[4]||e[5]||"").replace(rt,it),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||at.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&at.error(e[0]),e},PSEUDO:function(e){var n,r=!e[5]&&e[2];return Q.CHILD.test(e[0])?null:(e[3]&&e[4]!==t?e[2]=e[4]:r&&J.test(r)&&(n=mt(r,!0))&&(n=r.indexOf(")",r.length-n)-r.length)&&(e[0]=e[0].slice(0,n),e[2]=r.slice(0,n)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(rt,it).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=N[e+" "];return t||(t=RegExp("(^|"+P+")"+e+"("+P+"|$)"))&&N(e,function(e){return t.test("string"==typeof e.className&&e.className||typeof e.getAttribute!==j&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=at.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,l){var u,c,p,f,d,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!l&&!s;if(m){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){c=m[b]||(m[b]={}),u=c[e]||[],d=u[0]===T&&u[1],f=u[0]===T&&u[2],p=d&&m.childNodes[d];while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[T,d,f];break}}else if(v&&(u=(t[b]||(t[b]={}))[e])&&u[0]===T)f=u[1];else while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(v&&((p[b]||(p[b]={}))[e]=[T,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=o.pseudos[e]||o.setFilters[e.toLowerCase()]||at.error("unsupported pseudo: "+e);return r[b]?r(t):r.length>1?(n=[e,e,"",t],o.setFilters.hasOwnProperty(e.toLowerCase())?lt(function(e,n){var i,o=r(e,t),a=o.length;while(a--)i=F.call(e,o[a]),e[i]=!(n[i]=o[a])}):function(e){return r(e,0,n)}):r}},pseudos:{not:lt(function(e){var t=[],n=[],r=l(e.replace(z,"$1"));return r[b]?lt(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:lt(function(e){return function(t){return at(e,t).length>0}}),contains:lt(function(e){return function(t){return(t.textContent||t.innerText||a(t)).indexOf(e)>-1}}),lang:lt(function(e){return G.test(e||"")||at.error("unsupported lang: "+e),e=e.replace(rt,it).toLowerCase(),function(t){var n;do if(n=h?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===d},focus:function(e){return e===f.activeElement&&(!f.hasFocus||f.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!o.pseudos.empty(e)},header:function(e){return tt.test(e.nodeName)},input:function(e){return et.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:ht(function(){return[0]}),last:ht(function(e,t){return[t-1]}),eq:ht(function(e,t,n){return[0>n?n+t:n]}),even:ht(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:ht(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:ht(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:ht(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}},o.pseudos.nth=o.pseudos.eq;for(n in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})o.pseudos[n]=ft(n);for(n in{submit:!0,reset:!0})o.pseudos[n]=dt(n);function gt(){}gt.prototype=o.filters=o.pseudos,o.setFilters=new gt;function mt(e,t){var n,r,i,a,s,l,u,c=k[e+" "];if(c)return t?0:c.slice(0);s=e,l=[],u=o.preFilter;while(s){(!n||(r=X.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),l.push(i=[])),n=!1,(r=U.exec(s))&&(n=r.shift(),i.push({value:n,type:r[0].replace(z," ")}),s=s.slice(n.length));for(a in o.filter)!(r=Q[a].exec(s))||u[a]&&!(r=u[a](r))||(n=r.shift(),i.push({value:n,type:a,matches:r}),s=s.slice(n.length));if(!n)break}return t?s.length:s?at.error(e):k(e,l).slice(0)}function yt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function vt(e,t,n){var r=t.dir,o=n&&"parentNode"===r,a=C++;return t.first?function(t,n,i){while(t=t[r])if(1===t.nodeType||o)return e(t,n,i)}:function(t,n,s){var l,u,c,p=T+" "+a;if(s){while(t=t[r])if((1===t.nodeType||o)&&e(t,n,s))return!0}else while(t=t[r])if(1===t.nodeType||o)if(c=t[b]||(t[b]={}),(u=c[r])&&u[0]===p){if((l=u[1])===!0||l===i)return l===!0}else if(u=c[r]=[p],u[1]=e(t,n,s)||i,u[1]===!0)return!0}}function bt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function xt(e,t,n,r,i){var o,a=[],s=0,l=e.length,u=null!=t;for(;l>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),u&&t.push(s));return a}function wt(e,t,n,r,i,o){return r&&!r[b]&&(r=wt(r)),i&&!i[b]&&(i=wt(i,o)),lt(function(o,a,s,l){var u,c,p,f=[],d=[],h=a.length,g=o||Nt(t||"*",s.nodeType?[s]:s,[]),m=!e||!o&&t?g:xt(g,f,e,s,l),y=n?i||(o?e:h||r)?[]:a:m;if(n&&n(m,y,s,l),r){u=xt(y,d),r(u,[],s,l),c=u.length;while(c--)(p=u[c])&&(y[d[c]]=!(m[d[c]]=p))}if(o){if(i||e){if(i){u=[],c=y.length;while(c--)(p=y[c])&&u.push(m[c]=p);i(null,y=[],u,l)}c=y.length;while(c--)(p=y[c])&&(u=i?F.call(o,p):f[c])>-1&&(o[u]=!(a[u]=p))}}else y=xt(y===a?y.splice(h,y.length):y),i?i(null,a,y,l):M.apply(a,y)})}function Tt(e){var t,n,r,i=e.length,a=o.relative[e[0].type],s=a||o.relative[" "],l=a?1:0,c=vt(function(e){return e===t},s,!0),p=vt(function(e){return F.call(t,e)>-1},s,!0),f=[function(e,n,r){return!a&&(r||n!==u)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;i>l;l++)if(n=o.relative[e[l].type])f=[vt(bt(f),n)];else{if(n=o.filter[e[l].type].apply(null,e[l].matches),n[b]){for(r=++l;i>r;r++)if(o.relative[e[r].type])break;return wt(l>1&&bt(f),l>1&&yt(e.slice(0,l-1).concat({value:" "===e[l-2].type?"*":""})).replace(z,"$1"),n,r>l&&Tt(e.slice(l,r)),i>r&&Tt(e=e.slice(r)),i>r&&yt(e))}f.push(n)}return bt(f)}function Ct(e,t){var n=0,r=t.length>0,a=e.length>0,s=function(s,l,c,p,d){var h,g,m,y=[],v=0,b="0",x=s&&[],w=null!=d,C=u,N=s||a&&o.find.TAG("*",d&&l.parentNode||l),k=T+=null==C?1:Math.random()||.1;for(w&&(u=l!==f&&l,i=n);null!=(h=N[b]);b++){if(a&&h){g=0;while(m=e[g++])if(m(h,l,c)){p.push(h);break}w&&(T=k,i=++n)}r&&((h=!m&&h)&&v--,s&&x.push(h))}if(v+=b,r&&b!==v){g=0;while(m=t[g++])m(x,y,l,c);if(s){if(v>0)while(b--)x[b]||y[b]||(y[b]=q.call(p));y=xt(y)}M.apply(p,y),w&&!s&&y.length>0&&v+t.length>1&&at.uniqueSort(p)}return w&&(T=k,u=C),x};return r?lt(s):s}l=at.compile=function(e,t){var n,r=[],i=[],o=E[e+" "];if(!o){t||(t=mt(e)),n=t.length;while(n--)o=Tt(t[n]),o[b]?r.push(o):i.push(o);o=E(e,Ct(i,r))}return o};function Nt(e,t,n){var r=0,i=t.length;for(;i>r;r++)at(e,t[r],n);return n}function kt(e,t,n,i){var a,s,u,c,p,f=mt(e);if(!i&&1===f.length){if(s=f[0]=f[0].slice(0),s.length>2&&"ID"===(u=s[0]).type&&r.getById&&9===t.nodeType&&h&&o.relative[s[1].type]){if(t=(o.find.ID(u.matches[0].replace(rt,it),t)||[])[0],!t)return n;e=e.slice(s.shift().value.length)}a=Q.needsContext.test(e)?0:s.length;while(a--){if(u=s[a],o.relative[c=u.type])break;if((p=o.find[c])&&(i=p(u.matches[0].replace(rt,it),V.test(s[0].type)&&t.parentNode||t))){if(s.splice(a,1),e=i.length&&yt(s),!e)return M.apply(n,i),n;break}}}return l(e,f)(i,t,!h,n,V.test(e)),n}r.sortStable=b.split("").sort(A).join("")===b,r.detectDuplicates=S,p(),r.sortDetached=ut(function(e){return 1&e.compareDocumentPosition(f.createElement("div"))}),ut(function(e){return e.innerHTML="","#"===e.firstChild.getAttribute("href")})||ct("type|href|height|width",function(e,n,r){return r?t:e.getAttribute(n,"type"===n.toLowerCase()?1:2)}),r.attributes&&ut(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||ct("value",function(e,n,r){return r||"input"!==e.nodeName.toLowerCase()?t:e.defaultValue}),ut(function(e){return null==e.getAttribute("disabled")})||ct(B,function(e,n,r){var i;return r?t:(i=e.getAttributeNode(n))&&i.specified?i.value:e[n]===!0?n.toLowerCase():null}),x.find=at,x.expr=at.selectors,x.expr[":"]=x.expr.pseudos,x.unique=at.uniqueSort,x.text=at.getText,x.isXMLDoc=at.isXML,x.contains=at.contains}(e);var O={};function F(e){var t=O[e]={};return x.each(e.match(T)||[],function(e,n){t[n]=!0}),t}x.Callbacks=function(e){e="string"==typeof e?O[e]||F(e):x.extend({},e);var n,r,i,o,a,s,l=[],u=!e.once&&[],c=function(t){for(r=e.memory&&t,i=!0,a=s||0,s=0,o=l.length,n=!0;l&&o>a;a++)if(l[a].apply(t[0],t[1])===!1&&e.stopOnFalse){r=!1;break}n=!1,l&&(u?u.length&&c(u.shift()):r?l=[]:p.disable())},p={add:function(){if(l){var t=l.length;(function i(t){x.each(t,function(t,n){var r=x.type(n);"function"===r?e.unique&&p.has(n)||l.push(n):n&&n.length&&"string"!==r&&i(n)})})(arguments),n?o=l.length:r&&(s=t,c(r))}return this},remove:function(){return l&&x.each(arguments,function(e,t){var r;while((r=x.inArray(t,l,r))>-1)l.splice(r,1),n&&(o>=r&&o--,a>=r&&a--)}),this},has:function(e){return e?x.inArray(e,l)>-1:!(!l||!l.length)},empty:function(){return l=[],o=0,this},disable:function(){return l=u=r=t,this},disabled:function(){return!l},lock:function(){return u=t,r||p.disable(),this},locked:function(){return!u},fireWith:function(e,t){return!l||i&&!u||(t=t||[],t=[e,t.slice?t.slice():t],n?u.push(t):c(t)),this},fire:function(){return p.fireWith(this,arguments),this},fired:function(){return!!i}};return p},x.extend({Deferred:function(e){var t=[["resolve","done",x.Callbacks("once memory"),"resolved"],["reject","fail",x.Callbacks("once memory"),"rejected"],["notify","progress",x.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return x.Deferred(function(n){x.each(t,function(t,o){var a=o[0],s=x.isFunction(e[t])&&e[t];i[o[1]](function(){var e=s&&s.apply(this,arguments);e&&x.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a+"With"](this===r?n.promise():this,s?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?x.extend(e,r):r}},i={};return r.pipe=r.then,x.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=g.call(arguments),r=n.length,i=1!==r||e&&x.isFunction(e.promise)?r:0,o=1===i?e:x.Deferred(),a=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?g.call(arguments):r,n===s?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},s,l,u;if(r>1)for(s=Array(r),l=Array(r),u=Array(r);r>t;t++)n[t]&&x.isFunction(n[t].promise)?n[t].promise().done(a(t,u,n)).fail(o.reject).progress(a(t,l,s)):--i;return i||o.resolveWith(u,n),o.promise()}}),x.support=function(t){var n,r,o,s,l,u,c,p,f,d=a.createElement("div");if(d.setAttribute("className","t"),d.innerHTML="
a",n=d.getElementsByTagName("*")||[],r=d.getElementsByTagName("a")[0],!r||!r.style||!n.length)return t;s=a.createElement("select"),u=s.appendChild(a.createElement("option")),o=d.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t.getSetAttribute="t"!==d.className,t.leadingWhitespace=3===d.firstChild.nodeType,t.tbody=!d.getElementsByTagName("tbody").length,t.htmlSerialize=!!d.getElementsByTagName("link").length,t.style=/top/.test(r.getAttribute("style")),t.hrefNormalized="/a"===r.getAttribute("href"),t.opacity=/^0.5/.test(r.style.opacity),t.cssFloat=!!r.style.cssFloat,t.checkOn=!!o.value,t.optSelected=u.selected,t.enctype=!!a.createElement("form").enctype,t.html5Clone="<:nav>"!==a.createElement("nav").cloneNode(!0).outerHTML,t.inlineBlockNeedsLayout=!1,t.shrinkWrapBlocks=!1,t.pixelPosition=!1,t.deleteExpando=!0,t.noCloneEvent=!0,t.reliableMarginRight=!0,t.boxSizingReliable=!0,o.checked=!0,t.noCloneChecked=o.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!u.disabled;try{delete d.test}catch(h){t.deleteExpando=!1}o=a.createElement("input"),o.setAttribute("value",""),t.input=""===o.getAttribute("value"),o.value="t",o.setAttribute("type","radio"),t.radioValue="t"===o.value,o.setAttribute("checked","t"),o.setAttribute("name","t"),l=a.createDocumentFragment(),l.appendChild(o),t.appendChecked=o.checked,t.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,d.attachEvent&&(d.attachEvent("onclick",function(){t.noCloneEvent=!1}),d.cloneNode(!0).click());for(f in{submit:!0,change:!0,focusin:!0})d.setAttribute(c="on"+f,"t"),t[f+"Bubbles"]=c in e||d.attributes[c].expando===!1;d.style.backgroundClip="content-box",d.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===d.style.backgroundClip;for(f in x(t))break;return t.ownLast="0"!==f,x(function(){var n,r,o,s="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",l=a.getElementsByTagName("body")[0];l&&(n=a.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",l.appendChild(n).appendChild(d),d.innerHTML="
t
",o=d.getElementsByTagName("td"),o[0].style.cssText="padding:0;margin:0;border:0;display:none",p=0===o[0].offsetHeight,o[0].style.display="",o[1].style.display="none",t.reliableHiddenOffsets=p&&0===o[0].offsetHeight,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",x.swap(l,null!=l.style.zoom?{zoom:1}:{},function(){t.boxSizing=4===d.offsetWidth}),e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(d,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(d,null)||{width:"4px"}).width,r=d.appendChild(a.createElement("div")),r.style.cssText=d.style.cssText=s,r.style.marginRight=r.style.width="0",d.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),typeof d.style.zoom!==i&&(d.innerHTML="",d.style.cssText=s+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=3===d.offsetWidth,d.style.display="block",d.innerHTML="
",d.firstChild.style.width="5px",t.shrinkWrapBlocks=3!==d.offsetWidth,t.inlineBlockNeedsLayout&&(l.style.zoom=1)),l.removeChild(n),n=d=o=r=null)}),n=s=l=u=r=o=null,t +}({});var B=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,P=/([A-Z])/g;function R(e,n,r,i){if(x.acceptData(e)){var o,a,s=x.expando,l=e.nodeType,u=l?x.cache:e,c=l?e[s]:e[s]&&s;if(c&&u[c]&&(i||u[c].data)||r!==t||"string"!=typeof n)return c||(c=l?e[s]=p.pop()||x.guid++:s),u[c]||(u[c]=l?{}:{toJSON:x.noop}),("object"==typeof n||"function"==typeof n)&&(i?u[c]=x.extend(u[c],n):u[c].data=x.extend(u[c].data,n)),a=u[c],i||(a.data||(a.data={}),a=a.data),r!==t&&(a[x.camelCase(n)]=r),"string"==typeof n?(o=a[n],null==o&&(o=a[x.camelCase(n)])):o=a,o}}function W(e,t,n){if(x.acceptData(e)){var r,i,o=e.nodeType,a=o?x.cache:e,s=o?e[x.expando]:x.expando;if(a[s]){if(t&&(r=n?a[s]:a[s].data)){x.isArray(t)?t=t.concat(x.map(t,x.camelCase)):t in r?t=[t]:(t=x.camelCase(t),t=t in r?[t]:t.split(" ")),i=t.length;while(i--)delete r[t[i]];if(n?!I(r):!x.isEmptyObject(r))return}(n||(delete a[s].data,I(a[s])))&&(o?x.cleanData([e],!0):x.support.deleteExpando||a!=a.window?delete a[s]:a[s]=null)}}}x.extend({cache:{},noData:{applet:!0,embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(e){return e=e.nodeType?x.cache[e[x.expando]]:e[x.expando],!!e&&!I(e)},data:function(e,t,n){return R(e,t,n)},removeData:function(e,t){return W(e,t)},_data:function(e,t,n){return R(e,t,n,!0)},_removeData:function(e,t){return W(e,t,!0)},acceptData:function(e){if(e.nodeType&&1!==e.nodeType&&9!==e.nodeType)return!1;var t=e.nodeName&&x.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),x.fn.extend({data:function(e,n){var r,i,o=null,a=0,s=this[0];if(e===t){if(this.length&&(o=x.data(s),1===s.nodeType&&!x._data(s,"parsedAttrs"))){for(r=s.attributes;r.length>a;a++)i=r[a].name,0===i.indexOf("data-")&&(i=x.camelCase(i.slice(5)),$(s,i,o[i]));x._data(s,"parsedAttrs",!0)}return o}return"object"==typeof e?this.each(function(){x.data(this,e)}):arguments.length>1?this.each(function(){x.data(this,e,n)}):s?$(s,e,x.data(s,e)):null},removeData:function(e){return this.each(function(){x.removeData(this,e)})}});function $(e,n,r){if(r===t&&1===e.nodeType){var i="data-"+n.replace(P,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"==typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null:+r+""===r?+r:B.test(r)?x.parseJSON(r):r}catch(o){}x.data(e,n,r)}else r=t}return r}function I(e){var t;for(t in e)if(("data"!==t||!x.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}x.extend({queue:function(e,n,r){var i;return e?(n=(n||"fx")+"queue",i=x._data(e,n),r&&(!i||x.isArray(r)?i=x._data(e,n,x.makeArray(r)):i.push(r)),i||[]):t},dequeue:function(e,t){t=t||"fx";var n=x.queue(e,t),r=n.length,i=n.shift(),o=x._queueHooks(e,t),a=function(){x.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return x._data(e,n)||x._data(e,n,{empty:x.Callbacks("once memory").add(function(){x._removeData(e,t+"queue"),x._removeData(e,n)})})}}),x.fn.extend({queue:function(e,n){var r=2;return"string"!=typeof e&&(n=e,e="fx",r--),r>arguments.length?x.queue(this[0],e):n===t?this:this.each(function(){var t=x.queue(this,e,n);x._queueHooks(this,e),"fx"===e&&"inprogress"!==t[0]&&x.dequeue(this,e)})},dequeue:function(e){return this.each(function(){x.dequeue(this,e)})},delay:function(e,t){return e=x.fx?x.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,o=x.Deferred(),a=this,s=this.length,l=function(){--i||o.resolveWith(a,[a])};"string"!=typeof e&&(n=e,e=t),e=e||"fx";while(s--)r=x._data(a[s],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(l));return l(),o.promise(n)}});var z,X,U=/[\t\r\n\f]/g,V=/\r/g,Y=/^(?:input|select|textarea|button|object)$/i,J=/^(?:a|area)$/i,G=/^(?:checked|selected)$/i,Q=x.support.getSetAttribute,K=x.support.input;x.fn.extend({attr:function(e,t){return x.access(this,x.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){x.removeAttr(this,e)})},prop:function(e,t){return x.access(this,x.prop,e,t,arguments.length>1)},removeProp:function(e){return e=x.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,o,a=0,s=this.length,l="string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).addClass(e.call(this,t,this.className))});if(l)for(t=(e||"").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(U," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=x.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,a=0,s=this.length,l=0===arguments.length||"string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).removeClass(e.call(this,t,this.className))});if(l)for(t=(e||"").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(U," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?x.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e;return"boolean"==typeof t&&"string"===n?t?this.addClass(e):this.removeClass(e):x.isFunction(e)?this.each(function(n){x(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var t,r=0,o=x(this),a=e.match(T)||[];while(t=a[r++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else(n===i||"boolean"===n)&&(this.className&&x._data(this,"__className__",this.className),this.className=this.className||e===!1?"":x._data(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(U," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,o=this[0];{if(arguments.length)return i=x.isFunction(e),this.each(function(n){var o;1===this.nodeType&&(o=i?e.call(this,n,x(this).val()):e,null==o?o="":"number"==typeof o?o+="":x.isArray(o)&&(o=x.map(o,function(e){return null==e?"":e+""})),r=x.valHooks[this.type]||x.valHooks[this.nodeName.toLowerCase()],r&&"set"in r&&r.set(this,o,"value")!==t||(this.value=o))});if(o)return r=x.valHooks[o.type]||x.valHooks[o.nodeName.toLowerCase()],r&&"get"in r&&(n=r.get(o,"value"))!==t?n:(n=o.value,"string"==typeof n?n.replace(V,""):null==n?"":n)}}}),x.extend({valHooks:{option:{get:function(e){var t=x.find.attr(e,"value");return null!=t?t:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,l=0>i?s:o?i:0;for(;s>l;l++)if(n=r[l],!(!n.selected&&l!==i||(x.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&x.nodeName(n.parentNode,"optgroup"))){if(t=x(n).val(),o)return t;a.push(t)}return a},set:function(e,t){var n,r,i=e.options,o=x.makeArray(t),a=i.length;while(a--)r=i[a],(r.selected=x.inArray(x(r).val(),o)>=0)&&(n=!0);return n||(e.selectedIndex=-1),o}}},attr:function(e,n,r){var o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return typeof e.getAttribute===i?x.prop(e,n,r):(1===s&&x.isXMLDoc(e)||(n=n.toLowerCase(),o=x.attrHooks[n]||(x.expr.match.bool.test(n)?X:z)),r===t?o&&"get"in o&&null!==(a=o.get(e,n))?a:(a=x.find.attr(e,n),null==a?t:a):null!==r?o&&"set"in o&&(a=o.set(e,r,n))!==t?a:(e.setAttribute(n,r+""),r):(x.removeAttr(e,n),t))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(T);if(o&&1===e.nodeType)while(n=o[i++])r=x.propFix[n]||n,x.expr.match.bool.test(n)?K&&Q||!G.test(n)?e[r]=!1:e[x.camelCase("default-"+n)]=e[r]=!1:x.attr(e,n,""),e.removeAttribute(Q?n:r)},attrHooks:{type:{set:function(e,t){if(!x.support.radioValue&&"radio"===t&&x.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{"for":"htmlFor","class":"className"},prop:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return a=1!==s||!x.isXMLDoc(e),a&&(n=x.propFix[n]||n,o=x.propHooks[n]),r!==t?o&&"set"in o&&(i=o.set(e,r,n))!==t?i:e[n]=r:o&&"get"in o&&null!==(i=o.get(e,n))?i:e[n]},propHooks:{tabIndex:{get:function(e){var t=x.find.attr(e,"tabindex");return t?parseInt(t,10):Y.test(e.nodeName)||J.test(e.nodeName)&&e.href?0:-1}}}}),X={set:function(e,t,n){return t===!1?x.removeAttr(e,n):K&&Q||!G.test(n)?e.setAttribute(!Q&&x.propFix[n]||n,n):e[x.camelCase("default-"+n)]=e[n]=!0,n}},x.each(x.expr.match.bool.source.match(/\w+/g),function(e,n){var r=x.expr.attrHandle[n]||x.find.attr;x.expr.attrHandle[n]=K&&Q||!G.test(n)?function(e,n,i){var o=x.expr.attrHandle[n],a=i?t:(x.expr.attrHandle[n]=t)!=r(e,n,i)?n.toLowerCase():null;return x.expr.attrHandle[n]=o,a}:function(e,n,r){return r?t:e[x.camelCase("default-"+n)]?n.toLowerCase():null}}),K&&Q||(x.attrHooks.value={set:function(e,n,r){return x.nodeName(e,"input")?(e.defaultValue=n,t):z&&z.set(e,n,r)}}),Q||(z={set:function(e,n,r){var i=e.getAttributeNode(r);return i||e.setAttributeNode(i=e.ownerDocument.createAttribute(r)),i.value=n+="","value"===r||n===e.getAttribute(r)?n:t}},x.expr.attrHandle.id=x.expr.attrHandle.name=x.expr.attrHandle.coords=function(e,n,r){var i;return r?t:(i=e.getAttributeNode(n))&&""!==i.value?i.value:null},x.valHooks.button={get:function(e,n){var r=e.getAttributeNode(n);return r&&r.specified?r.value:t},set:z.set},x.attrHooks.contenteditable={set:function(e,t,n){z.set(e,""===t?!1:t,n)}},x.each(["width","height"],function(e,n){x.attrHooks[n]={set:function(e,r){return""===r?(e.setAttribute(n,"auto"),r):t}}})),x.support.hrefNormalized||x.each(["href","src"],function(e,t){x.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}}),x.support.style||(x.attrHooks.style={get:function(e){return e.style.cssText||t},set:function(e,t){return e.style.cssText=t+""}}),x.support.optSelected||(x.propHooks.selected={get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}}),x.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){x.propFix[this.toLowerCase()]=this}),x.support.enctype||(x.propFix.enctype="encoding"),x.each(["radio","checkbox"],function(){x.valHooks[this]={set:function(e,n){return x.isArray(n)?e.checked=x.inArray(x(e).val(),n)>=0:t}},x.support.checkOn||(x.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var Z=/^(?:input|select|textarea)$/i,et=/^key/,tt=/^(?:mouse|contextmenu)|click/,nt=/^(?:focusinfocus|focusoutblur)$/,rt=/^([^.]*)(?:\.(.+)|)$/;function it(){return!0}function ot(){return!1}function at(){try{return a.activeElement}catch(e){}}x.event={global:{},add:function(e,n,r,o,a){var s,l,u,c,p,f,d,h,g,m,y,v=x._data(e);if(v){r.handler&&(c=r,r=c.handler,a=c.selector),r.guid||(r.guid=x.guid++),(l=v.events)||(l=v.events={}),(f=v.handle)||(f=v.handle=function(e){return typeof x===i||e&&x.event.triggered===e.type?t:x.event.dispatch.apply(f.elem,arguments)},f.elem=e),n=(n||"").match(T)||[""],u=n.length;while(u--)s=rt.exec(n[u])||[],g=y=s[1],m=(s[2]||"").split(".").sort(),g&&(p=x.event.special[g]||{},g=(a?p.delegateType:p.bindType)||g,p=x.event.special[g]||{},d=x.extend({type:g,origType:y,data:o,handler:r,guid:r.guid,selector:a,needsContext:a&&x.expr.match.needsContext.test(a),namespace:m.join(".")},c),(h=l[g])||(h=l[g]=[],h.delegateCount=0,p.setup&&p.setup.call(e,o,m,f)!==!1||(e.addEventListener?e.addEventListener(g,f,!1):e.attachEvent&&e.attachEvent("on"+g,f))),p.add&&(p.add.call(e,d),d.handler.guid||(d.handler.guid=r.guid)),a?h.splice(h.delegateCount++,0,d):h.push(d),x.event.global[g]=!0);e=null}},remove:function(e,t,n,r,i){var o,a,s,l,u,c,p,f,d,h,g,m=x.hasData(e)&&x._data(e);if(m&&(c=m.events)){t=(t||"").match(T)||[""],u=t.length;while(u--)if(s=rt.exec(t[u])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){p=x.event.special[d]||{},d=(r?p.delegateType:p.bindType)||d,f=c[d]||[],s=s[2]&&RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),l=o=f.length;while(o--)a=f[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&("**"!==r||!a.selector)||(f.splice(o,1),a.selector&&f.delegateCount--,p.remove&&p.remove.call(e,a));l&&!f.length&&(p.teardown&&p.teardown.call(e,h,m.handle)!==!1||x.removeEvent(e,d,m.handle),delete c[d])}else for(d in c)x.event.remove(e,d+t[u],n,r,!0);x.isEmptyObject(c)&&(delete m.handle,x._removeData(e,"events"))}},trigger:function(n,r,i,o){var s,l,u,c,p,f,d,h=[i||a],g=v.call(n,"type")?n.type:n,m=v.call(n,"namespace")?n.namespace.split("."):[];if(u=f=i=i||a,3!==i.nodeType&&8!==i.nodeType&&!nt.test(g+x.event.triggered)&&(g.indexOf(".")>=0&&(m=g.split("."),g=m.shift(),m.sort()),l=0>g.indexOf(":")&&"on"+g,n=n[x.expando]?n:new x.Event(g,"object"==typeof n&&n),n.isTrigger=o?2:3,n.namespace=m.join("."),n.namespace_re=n.namespace?RegExp("(^|\\.)"+m.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,n.result=t,n.target||(n.target=i),r=null==r?[n]:x.makeArray(r,[n]),p=x.event.special[g]||{},o||!p.trigger||p.trigger.apply(i,r)!==!1)){if(!o&&!p.noBubble&&!x.isWindow(i)){for(c=p.delegateType||g,nt.test(c+g)||(u=u.parentNode);u;u=u.parentNode)h.push(u),f=u;f===(i.ownerDocument||a)&&h.push(f.defaultView||f.parentWindow||e)}d=0;while((u=h[d++])&&!n.isPropagationStopped())n.type=d>1?c:p.bindType||g,s=(x._data(u,"events")||{})[n.type]&&x._data(u,"handle"),s&&s.apply(u,r),s=l&&u[l],s&&x.acceptData(u)&&s.apply&&s.apply(u,r)===!1&&n.preventDefault();if(n.type=g,!o&&!n.isDefaultPrevented()&&(!p._default||p._default.apply(h.pop(),r)===!1)&&x.acceptData(i)&&l&&i[g]&&!x.isWindow(i)){f=i[l],f&&(i[l]=null),x.event.triggered=g;try{i[g]()}catch(y){}x.event.triggered=t,f&&(i[l]=f)}return n.result}},dispatch:function(e){e=x.event.fix(e);var n,r,i,o,a,s=[],l=g.call(arguments),u=(x._data(this,"events")||{})[e.type]||[],c=x.event.special[e.type]||{};if(l[0]=e,e.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,e)!==!1){s=x.event.handlers.call(this,e,u),n=0;while((o=s[n++])&&!e.isPropagationStopped()){e.currentTarget=o.elem,a=0;while((i=o.handlers[a++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(i.namespace))&&(e.handleObj=i,e.data=i.data,r=((x.event.special[i.origType]||{}).handle||i.handler).apply(o.elem,l),r!==t&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,e),e.result}},handlers:function(e,n){var r,i,o,a,s=[],l=n.delegateCount,u=e.target;if(l&&u.nodeType&&(!e.button||"click"!==e.type))for(;u!=this;u=u.parentNode||this)if(1===u.nodeType&&(u.disabled!==!0||"click"!==e.type)){for(o=[],a=0;l>a;a++)i=n[a],r=i.selector+" ",o[r]===t&&(o[r]=i.needsContext?x(r,this).index(u)>=0:x.find(r,this,null,[u]).length),o[r]&&o.push(i);o.length&&s.push({elem:u,handlers:o})}return n.length>l&&s.push({elem:this,handlers:n.slice(l)}),s},fix:function(e){if(e[x.expando])return e;var t,n,r,i=e.type,o=e,s=this.fixHooks[i];s||(this.fixHooks[i]=s=tt.test(i)?this.mouseHooks:et.test(i)?this.keyHooks:{}),r=s.props?this.props.concat(s.props):this.props,e=new x.Event(o),t=r.length;while(t--)n=r[t],e[n]=o[n];return e.target||(e.target=o.srcElement||a),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,o):e},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,i,o,s=n.button,l=n.fromElement;return null==e.pageX&&null!=n.clientX&&(i=e.target.ownerDocument||a,o=i.documentElement,r=i.body,e.pageX=n.clientX+(o&&o.scrollLeft||r&&r.scrollLeft||0)-(o&&o.clientLeft||r&&r.clientLeft||0),e.pageY=n.clientY+(o&&o.scrollTop||r&&r.scrollTop||0)-(o&&o.clientTop||r&&r.clientTop||0)),!e.relatedTarget&&l&&(e.relatedTarget=l===e.target?n.toElement:l),e.which||s===t||(e.which=1&s?1:2&s?3:4&s?2:0),e}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==at()&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:"focusin"},blur:{trigger:function(){return this===at()&&this.blur?(this.blur(),!1):t},delegateType:"focusout"},click:{trigger:function(){return x.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):t},_default:function(e){return x.nodeName(e.target,"a")}},beforeunload:{postDispatch:function(e){e.result!==t&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=x.extend(new x.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?x.event.trigger(i,null,t):x.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},x.removeEvent=a.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]===i&&(e[r]=null),e.detachEvent(r,n))},x.Event=function(e,n){return this instanceof x.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?it:ot):this.type=e,n&&x.extend(this,n),this.timeStamp=e&&e.timeStamp||x.now(),this[x.expando]=!0,t):new x.Event(e,n)},x.Event.prototype={isDefaultPrevented:ot,isPropagationStopped:ot,isImmediatePropagationStopped:ot,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=it,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=it,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=it,this.stopPropagation()}},x.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){x.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return(!i||i!==r&&!x.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),x.support.submitBubbles||(x.event.special.submit={setup:function(){return x.nodeName(this,"form")?!1:(x.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=x.nodeName(n,"input")||x.nodeName(n,"button")?n.form:t;r&&!x._data(r,"submitBubbles")&&(x.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),x._data(r,"submitBubbles",!0))}),t)},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&x.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){return x.nodeName(this,"form")?!1:(x.event.remove(this,"._submit"),t)}}),x.support.changeBubbles||(x.event.special.change={setup:function(){return Z.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(x.event.add(this,"propertychange._change",function(e){"checked"===e.originalEvent.propertyName&&(this._just_changed=!0)}),x.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),x.event.simulate("change",this,e,!0)})),!1):(x.event.add(this,"beforeactivate._change",function(e){var t=e.target;Z.test(t.nodeName)&&!x._data(t,"changeBubbles")&&(x.event.add(t,"change._change",function(e){!this.parentNode||e.isSimulated||e.isTrigger||x.event.simulate("change",this.parentNode,e,!0)}),x._data(t,"changeBubbles",!0))}),t)},handle:function(e){var n=e.target;return this!==n||e.isSimulated||e.isTrigger||"radio"!==n.type&&"checkbox"!==n.type?e.handleObj.handler.apply(this,arguments):t},teardown:function(){return x.event.remove(this,"._change"),!Z.test(this.nodeName)}}),x.support.focusinBubbles||x.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){x.event.simulate(t,e.target,x.event.fix(e),!0)};x.event.special[t]={setup:function(){0===n++&&a.addEventListener(e,r,!0)},teardown:function(){0===--n&&a.removeEventListener(e,r,!0)}}}),x.fn.extend({on:function(e,n,r,i,o){var a,s;if("object"==typeof e){"string"!=typeof n&&(r=r||n,n=t);for(a in e)this.on(a,n,r,e[a],o);return this}if(null==r&&null==i?(i=n,r=n=t):null==i&&("string"==typeof n?(i=r,r=t):(i=r,r=n,n=t)),i===!1)i=ot;else if(!i)return this;return 1===o&&(s=i,i=function(e){return x().off(e),s.apply(this,arguments)},i.guid=s.guid||(s.guid=x.guid++)),this.each(function(){x.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,o;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,x(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if("object"==typeof e){for(o in e)this.off(o,n,e[o]);return this}return(n===!1||"function"==typeof n)&&(r=n,n=t),r===!1&&(r=ot),this.each(function(){x.event.remove(this,e,r,n)})},trigger:function(e,t){return this.each(function(){x.event.trigger(e,t,this)})},triggerHandler:function(e,n){var r=this[0];return r?x.event.trigger(e,n,r,!0):t}});var st=/^.[^:#\[\.,]*$/,lt=/^(?:parents|prev(?:Until|All))/,ut=x.expr.match.needsContext,ct={children:!0,contents:!0,next:!0,prev:!0};x.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if("string"!=typeof e)return this.pushStack(x(e).filter(function(){for(t=0;i>t;t++)if(x.contains(r[t],this))return!0}));for(t=0;i>t;t++)x.find(e,r[t],n);return n=this.pushStack(i>1?x.unique(n):n),n.selector=this.selector?this.selector+" "+e:e,n},has:function(e){var t,n=x(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++)if(x.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e||[],!0))},filter:function(e){return this.pushStack(ft(this,e||[],!1))},is:function(e){return!!ft(this,"string"==typeof e&&ut.test(e)?x(e):e||[],!1).length},closest:function(e,t){var n,r=0,i=this.length,o=[],a=ut.test(e)||"string"!=typeof e?x(e,t||this.context):0;for(;i>r;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(11>n.nodeType&&(a?a.index(n)>-1:1===n.nodeType&&x.find.matchesSelector(n,e))){n=o.push(n);break}return this.pushStack(o.length>1?x.unique(o):o)},index:function(e){return e?"string"==typeof e?x.inArray(this[0],x(e)):x.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?x(e,t):x.makeArray(e&&e.nodeType?[e]:e),r=x.merge(this.get(),n);return this.pushStack(x.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function pt(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}x.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return x.dir(e,"parentNode")},parentsUntil:function(e,t,n){return x.dir(e,"parentNode",n)},next:function(e){return pt(e,"nextSibling")},prev:function(e){return pt(e,"previousSibling")},nextAll:function(e){return x.dir(e,"nextSibling")},prevAll:function(e){return x.dir(e,"previousSibling")},nextUntil:function(e,t,n){return x.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return x.dir(e,"previousSibling",n)},siblings:function(e){return x.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return x.sibling(e.firstChild)},contents:function(e){return x.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:x.merge([],e.childNodes)}},function(e,t){x.fn[e]=function(n,r){var i=x.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=x.filter(r,i)),this.length>1&&(ct[e]||(i=x.unique(i)),lt.test(e)&&(i=i.reverse())),this.pushStack(i)}}),x.extend({filter:function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?x.find.matchesSelector(r,e)?[r]:[]:x.find.matches(e,x.grep(t,function(e){return 1===e.nodeType}))},dir:function(e,n,r){var i=[],o=e[n];while(o&&9!==o.nodeType&&(r===t||1!==o.nodeType||!x(o).is(r)))1===o.nodeType&&i.push(o),o=o[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function ft(e,t,n){if(x.isFunction(t))return x.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return x.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(st.test(t))return x.filter(t,e,n);t=x.filter(t,e)}return x.grep(e,function(e){return x.inArray(e,t)>=0!==n})}function dt(e){var t=ht.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}var ht="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",gt=/ jQuery\d+="(?:null|\d+)"/g,mt=RegExp("<(?:"+ht+")[\\s/>]","i"),yt=/^\s+/,vt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bt=/<([\w:]+)/,xt=/\s*$/g,At={option:[1,""],legend:[1,"
","
"],area:[1,"",""],param:[1,"",""],thead:[1,"","
"],tr:[2,"","
"],col:[2,"","
"],td:[3,"","
"],_default:x.support.htmlSerialize?[0,"",""]:[1,"X
","
"]},jt=dt(a),Dt=jt.appendChild(a.createElement("div"));At.optgroup=At.option,At.tbody=At.tfoot=At.colgroup=At.caption=At.thead,At.th=At.td,x.fn.extend({text:function(e){return x.access(this,function(e){return e===t?x.text(this):this.empty().append((this[0]&&this[0].ownerDocument||a).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.appendChild(e)}})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=e?x.filter(e,this):this,i=0;for(;null!=(n=r[i]);i++)t||1!==n.nodeType||x.cleanData(Ft(n)),n.parentNode&&(t&&x.contains(n.ownerDocument,n)&&_t(Ft(n,"script")),n.parentNode.removeChild(n));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++){1===e.nodeType&&x.cleanData(Ft(e,!1));while(e.firstChild)e.removeChild(e.firstChild);e.options&&x.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return x.clone(this,e,t)})},html:function(e){return x.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return 1===n.nodeType?n.innerHTML.replace(gt,""):t;if(!("string"!=typeof e||Tt.test(e)||!x.support.htmlSerialize&&mt.test(e)||!x.support.leadingWhitespace&&yt.test(e)||At[(bt.exec(e)||["",""])[1].toLowerCase()])){e=e.replace(vt,"<$1>");try{for(;i>r;r++)n=this[r]||{},1===n.nodeType&&(x.cleanData(Ft(n,!1)),n.innerHTML=e);n=0}catch(o){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=x.map(this,function(e){return[e.nextSibling,e.parentNode]}),t=0;return this.domManip(arguments,function(n){var r=e[t++],i=e[t++];i&&(r&&r.parentNode!==i&&(r=this.nextSibling),x(this).remove(),i.insertBefore(n,r))},!0),t?this:this.remove()},detach:function(e){return this.remove(e,!0)},domManip:function(e,t,n){e=d.apply([],e);var r,i,o,a,s,l,u=0,c=this.length,p=this,f=c-1,h=e[0],g=x.isFunction(h);if(g||!(1>=c||"string"!=typeof h||x.support.checkClone)&&Nt.test(h))return this.each(function(r){var i=p.eq(r);g&&(e[0]=h.call(this,r,i.html())),i.domManip(e,t,n)});if(c&&(l=x.buildFragment(e,this[0].ownerDocument,!1,!n&&this),r=l.firstChild,1===l.childNodes.length&&(l=r),r)){for(a=x.map(Ft(l,"script"),Ht),o=a.length;c>u;u++)i=l,u!==f&&(i=x.clone(i,!0,!0),o&&x.merge(a,Ft(i,"script"))),t.call(this[u],i,u);if(o)for(s=a[a.length-1].ownerDocument,x.map(a,qt),u=0;o>u;u++)i=a[u],kt.test(i.type||"")&&!x._data(i,"globalEval")&&x.contains(s,i)&&(i.src?x._evalUrl(i.src):x.globalEval((i.text||i.textContent||i.innerHTML||"").replace(St,"")));l=r=null}return this}});function Lt(e,t){return x.nodeName(e,"table")&&x.nodeName(1===t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function Ht(e){return e.type=(null!==x.find.attr(e,"type"))+"/"+e.type,e}function qt(e){var t=Et.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function _t(e,t){var n,r=0;for(;null!=(n=e[r]);r++)x._data(n,"globalEval",!t||x._data(t[r],"globalEval"))}function Mt(e,t){if(1===t.nodeType&&x.hasData(e)){var n,r,i,o=x._data(e),a=x._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)x.event.add(t,n,s[n][r])}a.data&&(a.data=x.extend({},a.data))}}function Ot(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!x.support.noCloneEvent&&t[x.expando]){i=x._data(t);for(r in i.events)x.removeEvent(t,r,i.handle);t.removeAttribute(x.expando)}"script"===n&&t.text!==e.text?(Ht(t).text=e.text,qt(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),x.support.html5Clone&&e.innerHTML&&!x.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Ct.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}x.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){x.fn[e]=function(e){var n,r=0,i=[],o=x(e),a=o.length-1;for(;a>=r;r++)n=r===a?this:this.clone(!0),x(o[r])[t](n),h.apply(i,n.get());return this.pushStack(i)}});function Ft(e,n){var r,o,a=0,s=typeof e.getElementsByTagName!==i?e.getElementsByTagName(n||"*"):typeof e.querySelectorAll!==i?e.querySelectorAll(n||"*"):t;if(!s)for(s=[],r=e.childNodes||e;null!=(o=r[a]);a++)!n||x.nodeName(o,n)?s.push(o):x.merge(s,Ft(o,n));return n===t||n&&x.nodeName(e,n)?x.merge([e],s):s}function Bt(e){Ct.test(e.type)&&(e.defaultChecked=e.checked)}x.extend({clone:function(e,t,n){var r,i,o,a,s,l=x.contains(e.ownerDocument,e);if(x.support.html5Clone||x.isXMLDoc(e)||!mt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(Dt.innerHTML=e.outerHTML,Dt.removeChild(o=Dt.firstChild)),!(x.support.noCloneEvent&&x.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||x.isXMLDoc(e)))for(r=Ft(o),s=Ft(e),a=0;null!=(i=s[a]);++a)r[a]&&Ot(i,r[a]);if(t)if(n)for(s=s||Ft(e),r=r||Ft(o),a=0;null!=(i=s[a]);a++)Mt(i,r[a]);else Mt(e,o);return r=Ft(o,"script"),r.length>0&&_t(r,!l&&Ft(e,"script")),r=s=i=null,o},buildFragment:function(e,t,n,r){var i,o,a,s,l,u,c,p=e.length,f=dt(t),d=[],h=0;for(;p>h;h++)if(o=e[h],o||0===o)if("object"===x.type(o))x.merge(d,o.nodeType?[o]:o);else if(wt.test(o)){s=s||f.appendChild(t.createElement("div")),l=(bt.exec(o)||["",""])[1].toLowerCase(),c=At[l]||At._default,s.innerHTML=c[1]+o.replace(vt,"<$1>")+c[2],i=c[0];while(i--)s=s.lastChild;if(!x.support.leadingWhitespace&&yt.test(o)&&d.push(t.createTextNode(yt.exec(o)[0])),!x.support.tbody){o="table"!==l||xt.test(o)?""!==c[1]||xt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;while(i--)x.nodeName(u=o.childNodes[i],"tbody")&&!u.childNodes.length&&o.removeChild(u)}x.merge(d,s.childNodes),s.textContent="";while(s.firstChild)s.removeChild(s.firstChild);s=f.lastChild}else d.push(t.createTextNode(o));s&&f.removeChild(s),x.support.appendChecked||x.grep(Ft(d,"input"),Bt),h=0;while(o=d[h++])if((!r||-1===x.inArray(o,r))&&(a=x.contains(o.ownerDocument,o),s=Ft(f.appendChild(o),"script"),a&&_t(s),n)){i=0;while(o=s[i++])kt.test(o.type||"")&&n.push(o)}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,l=x.expando,u=x.cache,c=x.support.deleteExpando,f=x.event.special;for(;null!=(n=e[s]);s++)if((t||x.acceptData(n))&&(o=n[l],a=o&&u[o])){if(a.events)for(r in a.events)f[r]?x.event.remove(n,r):x.removeEvent(n,r,a.handle); +u[o]&&(delete u[o],c?delete n[l]:typeof n.removeAttribute!==i?n.removeAttribute(l):n[l]=null,p.push(o))}},_evalUrl:function(e){return x.ajax({url:e,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})}}),x.fn.extend({wrapAll:function(e){if(x.isFunction(e))return this.each(function(t){x(this).wrapAll(e.call(this,t))});if(this[0]){var t=x(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&1===e.firstChild.nodeType)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return x.isFunction(e)?this.each(function(t){x(this).wrapInner(e.call(this,t))}):this.each(function(){var t=x(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=x.isFunction(e);return this.each(function(n){x(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){x.nodeName(this,"body")||x(this).replaceWith(this.childNodes)}).end()}});var Pt,Rt,Wt,$t=/alpha\([^)]*\)/i,It=/opacity\s*=\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp("^("+w+")(.*)$","i"),Yt=RegExp("^("+w+")(?!px)[a-z%]+$","i"),Jt=RegExp("^([+-])=("+w+")","i"),Gt={BODY:"block"},Qt={position:"absolute",visibility:"hidden",display:"block"},Kt={letterSpacing:0,fontWeight:400},Zt=["Top","Right","Bottom","Left"],en=["Webkit","O","Moz","ms"];function tn(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--)if(t=en[i]+n,t in e)return t;return r}function nn(e,t){return e=t||e,"none"===x.css(e,"display")||!x.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++)r=e[a],r.style&&(o[a]=x._data(r,"olddisplay"),n=r.style.display,t?(o[a]||"none"!==n||(r.style.display=""),""===r.style.display&&nn(r)&&(o[a]=x._data(r,"olddisplay",ln(r.nodeName)))):o[a]||(i=nn(r),(n&&"none"!==n||!i)&&x._data(r,"olddisplay",i?n:x.css(r,"display"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[a]||"":"none"));return e}x.fn.extend({css:function(e,n){return x.access(this,function(e,n,r){var i,o,a={},s=0;if(x.isArray(n)){for(o=Rt(e),i=n.length;i>s;s++)a[n[s]]=x.css(e,n[s],!1,o);return a}return r!==t?x.style(e,n,r):x.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){nn(this)?x(this).show():x(this).hide()})}}),x.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":x.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,l=x.camelCase(n),u=e.style;if(n=x.cssProps[l]||(x.cssProps[l]=tn(u,l)),s=x.cssHooks[n]||x.cssHooks[l],r===t)return s&&"get"in s&&(o=s.get(e,!1,i))!==t?o:u[n];if(a=typeof r,"string"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(x.css(e,n)),a="number"),!(null==r||"number"===a&&isNaN(r)||("number"!==a||x.cssNumber[l]||(r+="px"),x.support.clearCloneStyle||""!==r||0!==n.indexOf("background")||(u[n]="inherit"),s&&"set"in s&&(r=s.set(e,r,i))===t)))try{u[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,l=x.camelCase(n);return n=x.cssProps[l]||(x.cssProps[l]=tn(e.style,l)),s=x.cssHooks[n]||x.cssHooks[l],s&&"get"in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),"normal"===a&&n in Kt&&(a=Kt[n]),""===r||r?(o=parseFloat(a),r===!0||x.isNumeric(o)?o||0:a):a}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s.getPropertyValue(n)||s[n]:t,u=e.style;return s&&(""!==l||x.contains(e.ownerDocument,e)||(l=x.style(e,n)),Yt.test(l)&&Ut.test(n)&&(i=u.width,o=u.minWidth,a=u.maxWidth,u.minWidth=u.maxWidth=u.width=l,l=s.width,u.width=i,u.minWidth=o,u.maxWidth=a)),l}):a.documentElement.currentStyle&&(Rt=function(e){return e.currentStyle},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s[n]:t,u=e.style;return null==l&&u&&u[n]&&(l=u[n]),Yt.test(l)&&!zt.test(n)&&(i=u.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),u.left="fontSize"===n?"1em":l,l=u.pixelLeft+"px",u.left=i,a&&(o.left=a)),""===l?"auto":l});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function an(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;for(;4>o;o+=2)"margin"===n&&(a+=x.css(e,n+Zt[o],!0,i)),r?("content"===n&&(a-=x.css(e,"padding"+Zt[o],!0,i)),"margin"!==n&&(a-=x.css(e,"border"+Zt[o]+"Width",!0,i))):(a+=x.css(e,"padding"+Zt[o],!0,i),"padding"!==n&&(a+=x.css(e,"border"+Zt[o]+"Width",!0,i)));return a}function sn(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i))return i;r=a&&(x.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+an(e,t,n||(a?"border":"content"),r,o)+"px"}function ln(e){var t=a,n=Gt[e];return n||(n=un(e,t),"none"!==n&&n||(Pt=(Pt||x("