diff options
author | onefang | 2022-06-04 09:49:14 +1000 |
---|---|---|
committer | onefang | 2022-06-04 09:49:14 +1000 |
commit | 7e848f1e72a3717ae524d912e370c207b0e79c57 (patch) | |
tree | d016ebe8b91479c0358e722ed6bc97aeb1961df0 | |
parent | Add a web option to sledjchisl, to start the web stuff. (diff) | |
download | opensim-SC-7e848f1e72a3717ae524d912e370c207b0e79c57.zip opensim-SC-7e848f1e72a3717ae524d912e370c207b0e79c57.tar.gz opensim-SC-7e848f1e72a3717ae524d912e370c207b0e79c57.tar.bz2 opensim-SC-7e848f1e72a3717ae524d912e370c207b0e79c57.tar.xz |
Add experimental XMPP chat stuff.
-rw-r--r-- | src/sledjchisl/sledjchisl.c | 263 |
1 files changed, 236 insertions, 27 deletions
diff --git a/src/sledjchisl/sledjchisl.c b/src/sledjchisl/sledjchisl.c index 317d079..4f91fae 100644 --- a/src/sledjchisl/sledjchisl.c +++ b/src/sledjchisl/sledjchisl.c | |||
@@ -140,6 +140,9 @@ extern char **environ; | |||
140 | #include "lib/fcgi_SC.h" | 140 | #include "lib/fcgi_SC.h" |
141 | #include "lib/handlekeys.h" | 141 | #include "lib/handlekeys.h" |
142 | 142 | ||
143 | #include "lib/json.h" | ||
144 | #include "lib/json-builder.h" | ||
145 | |||
143 | // Both my_config.h and fcgi_config.h define the same PACKAGE* variables, which we don't use anyway, | 146 | // Both my_config.h and fcgi_config.h define the same PACKAGE* variables, which we don't use anyway, |
144 | // I deal with that by using a sed invokation when building fcgi2. | 147 | // I deal with that by using a sed invokation when building fcgi2. |
145 | 148 | ||
@@ -518,7 +521,7 @@ static void showSesh(qgrow_t *reply, sesh *shs) | |||
518 | } | 521 | } |
519 | 522 | ||
520 | 523 | ||
521 | char toybuf[4096]; | 524 | //char toybuf[4096]; |
522 | lua_State *L; | 525 | lua_State *L; |
523 | qhashtbl_t *configs; | 526 | qhashtbl_t *configs; |
524 | MYSQL *database, *dbconn; | 527 | MYSQL *database, *dbconn; |
@@ -548,6 +551,7 @@ int startPort = 8002; | |||
548 | char *backupIARsim = "Sandbox"; | 551 | char *backupIARsim = "Sandbox"; |
549 | char *rSync = ""; | 552 | char *rSync = ""; |
550 | int rSyncPort = 0; | 553 | int rSyncPort = 0; |
554 | char *webHost = "localhost"; | ||
551 | char *webRoot = "/var/www/html"; | 555 | char *webRoot = "/var/www/html"; |
552 | char *webSocket = "sledjchisl.socket"; | 556 | char *webSocket = "sledjchisl.socket"; |
553 | char *ToS = "Be good."; | 557 | char *ToS = "Be good."; |
@@ -808,6 +812,87 @@ char *myHMACkey(char *key, char *in, boolean b64) | |||
808 | } | 812 | } |
809 | 813 | ||
810 | 814 | ||
815 | static void print_depth_shift(int depth) | ||
816 | { | ||
817 | int j; | ||
818 | for (j=0; j < depth; j++) { | ||
819 | printf(" "); | ||
820 | } | ||
821 | } | ||
822 | static void process_value(json_value* value, int depth); | ||
823 | static void process_object(json_value* value, int depth) | ||
824 | { | ||
825 | int length, x; | ||
826 | if (value == NULL) { | ||
827 | return; | ||
828 | } | ||
829 | length = value->u.object.length; | ||
830 | for (x = 0; x < length; x++) { | ||
831 | print_depth_shift(depth); | ||
832 | printf("object[%d].name = %s\n", x, value->u.object.values[x].name); | ||
833 | process_value(value->u.object.values[x].value, depth+1); | ||
834 | } | ||
835 | } | ||
836 | static void process_array(json_value* value, int depth) | ||
837 | { | ||
838 | int length, x; | ||
839 | if (value == NULL) { | ||
840 | return; | ||
841 | } | ||
842 | length = value->u.array.length; | ||
843 | printf("array\n"); | ||
844 | for (x = 0; x < length; x++) { | ||
845 | process_value(value->u.array.values[x], depth); | ||
846 | } | ||
847 | } | ||
848 | static void process_value(json_value* value, int depth) | ||
849 | { | ||
850 | if (value == NULL) { | ||
851 | return; | ||
852 | } | ||
853 | if (value->type != json_object) { | ||
854 | print_depth_shift(depth); | ||
855 | } | ||
856 | switch (value->type) { | ||
857 | case json_none: | ||
858 | printf("none\n"); | ||
859 | break; | ||
860 | case json_null: | ||
861 | printf("null\n"); | ||
862 | break; | ||
863 | case json_object: | ||
864 | process_object(value, depth+1); | ||
865 | break; | ||
866 | case json_array: | ||
867 | process_array(value, depth+1); | ||
868 | break; | ||
869 | case json_integer: | ||
870 | printf("int: %10ld\n", (long)value->u.integer); | ||
871 | break; | ||
872 | case json_double: | ||
873 | printf("double: %f\n", value->u.dbl); | ||
874 | break; | ||
875 | case json_string: | ||
876 | printf("string: %s\n", value->u.string.ptr); | ||
877 | break; | ||
878 | case json_boolean: | ||
879 | printf("bool: %d\n", value->u.boolean); | ||
880 | break; | ||
881 | } | ||
882 | } | ||
883 | void PrintJSON(json_char* json) | ||
884 | { | ||
885 | json_value* value = json_parse(json, strlen((char *) json)); | ||
886 | |||
887 | if (value == NULL) | ||
888 | { | ||
889 | E("Unable to parse data! - %s", (char *) json); | ||
890 | return; | ||
891 | } | ||
892 | process_value(value, 0); | ||
893 | json_value_free(value); | ||
894 | } | ||
895 | |||
811 | // In Lua 5.0 reference manual is a table traversal example at page 29. | 896 | // In Lua 5.0 reference manual is a table traversal example at page 29. |
812 | void PrintTable(lua_State *L) | 897 | void PrintTable(lua_State *L) |
813 | { | 898 | { |
@@ -4626,8 +4711,17 @@ static void HTMLheader(qgrow_t *reply, char *title) | |||
4626 | " <head>\n" | 4711 | " <head>\n" |
4627 | " <title>%s</title>\n" | 4712 | " <title>%s</title>\n" |
4628 | " <meta charset=\"UTF-8\">\n" | 4713 | " <meta charset=\"UTF-8\">\n" |
4714 | " <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n" | ||
4715 | " <meta name=\"viewport\" content=\"width=device-width, initial-scale=0.5\" />\n" | ||
4716 | // " <meta name=\"description\" content=\"Converse XMPP/Jabber Chat\"/>\n" | ||
4717 | // " <meta name=\"author\" content=\"JC Brand\" />\n" | ||
4718 | " <link rel=\"manifest\" href=\"/converse.js/manifest.json\">\n" | ||
4719 | " <link type='text/css' rel='stylesheet' href='/converse.js/dist/converse.min.css' media='screen' />\n" | ||
4720 | " <script src='/converse.js/3rdparty/libsignal-protocol.min.js'></script>\n" | ||
4721 | " <script src='/converse.js/dist/converse.min.js'></script>\n" | ||
4629 | " <link rel=\"shortcut icon\" href=\"/SledjHamrIconSmall.png\">\n" | 4722 | " <link rel=\"shortcut icon\" href=\"/SledjHamrIconSmall.png\">\n" |
4630 | " <link type='text/css' rel='stylesheet' href='/SledjChisl.css' media='all' />\n" | 4723 | " <link type='text/css' rel='stylesheet' href='/SledjChisl.css' media='all' />\n" |
4724 | |||
4631 | , title); | 4725 | , title); |
4632 | 4726 | ||
4633 | if (DEBUG) | 4727 | if (DEBUG) |
@@ -4635,7 +4729,7 @@ static void HTMLheader(qgrow_t *reply, char *title) | |||
4635 | 4729 | ||
4636 | reply->addstrf(reply, | 4730 | reply->addstrf(reply, |
4637 | " </head>\n" | 4731 | " </head>\n" |
4638 | " <body bgcolor='black' text='white' link='aqua' vlink='fuchsia' alink='red'>\n" | 4732 | " <body bgcolor='black' text='white' link='aqua' vlink='fuchsia' alink='red' id='page-top' data-spy='scroll' class='converse-website'>\n" |
4639 | " <font face='sans-serif'>\n" | 4733 | " <font face='sans-serif'>\n" |
4640 | ); | 4734 | ); |
4641 | reply->addstrf(reply, " <div class='top-left'>\n"); | 4735 | reply->addstrf(reply, " <div class='top-left'>\n"); |
@@ -4979,10 +5073,10 @@ void HTMLfill(reqData *Rd, enum fragmentType type, char *text, int length) | |||
4979 | } | 5073 | } |
4980 | } | 5074 | } |
4981 | 5075 | ||
4982 | static void HTMLfooter(qgrow_t *reply) | 5076 | static void HTMLfooter(reqData *Rd) |
4983 | { | 5077 | { |
4984 | reply->addstrf(reply, " </div>\n"); | 5078 | Rd->reply->addstrf(Rd->reply, " </div>\n"); |
4985 | reply->addstr(reply, | 5079 | Rd->reply->addstr(Rd->reply, |
4986 | " <div class='top-right'>\n" | 5080 | " <div class='top-right'>\n" |
4987 | " <h1>Experimental account manager</h1>\n" | 5081 | " <h1>Experimental account manager</h1>\n" |
4988 | " <p>This account manager system is currently experimental, and under heavy development. " | 5082 | " <p>This account manager system is currently experimental, and under heavy development. " |
@@ -4994,16 +5088,48 @@ static void HTMLfooter(qgrow_t *reply) | |||
4994 | " <p>You will then be logged off. Now you have to wait for an admin to approve your new account. " | 5088 | " <p>You will then be logged off. Now you have to wait for an admin to approve your new account. " |
4995 | " They should check with the person you listed as vouching for you first. They will tell you after they approve your account.</p>" | 5089 | " They should check with the person you listed as vouching for you first. They will tell you after they approve your account.</p>" |
4996 | " <p>Missing bits that are still being written - editing accounts, listing accounts, deleting accounts.</p>\n" | 5090 | " <p>Missing bits that are still being written - editing accounts, listing accounts, deleting accounts.</p>\n" |
5091 | " <h1>Experimental chat thingy</h1>\n" | ||
5092 | " <p>In the bottom right corner is an experimental chat thingy, based on Jabber / XMPP.</p>\n" | ||
5093 | " <p>Click on the 'Toggle chat' button to pop it up, then use your grid user name for the 'XMPP Address:' field. " | ||
5094 | " Your user name has to be in the format 'first.last', two words with a dot in the middle. " | ||
5095 | " Then put your grid account password in the 'Password' field and click the 'Log in' button. " | ||
5096 | " Ignore the 'Don't have a chat account? Create an account' bit.</p>\n" | ||
5097 | " <p>Note that the chat windows can be resized by dragging their top or left edges, which I suggest you do, coz the default size is too small.</p>\n" | ||
5098 | " <p>You can also use any other Jabber / XMPP client as well.</p>\n" | ||
5099 | " <p>Remember this is <b>EXPERIMENTAL</b>, I'll be changing things. Next I'll make it so you don't have to log in to both this chat thingy and the account page separataly.<p>" | ||
5100 | " <p>P.S. Yes, I hate the default theme to. lol</p>\n" | ||
4997 | " </div>\n"); | 5101 | " </div>\n"); |
4998 | // reply->addstr(reply, " <div class='centre'>\n </div>\n"); | 5102 | // Rd->reply->addstr(Rd->reply, " <div class='centre'>\n </div>\n"); |
4999 | reply->addstr(reply, | 5103 | Rd->reply->addstrf(Rd->reply, |
5000 | // " <div class='bottom-left'>\n" | 5104 | " <div class='bottom-left'>\n" |
5001 | // " </div>\n" | ||
5002 | " <div class='bottom-right'>\n" | ||
5003 | " <iframe src='stats.html' style='border:none;height:100%;width:100%;'></iframe>\n" | 5105 | " <iframe src='stats.html' style='border:none;height:100%;width:100%;'></iframe>\n" |
5004 | " </div>\n" | 5106 | " </div>\n" |
5107 | " <div class='bottom-right'>\n" | ||
5108 | " </div>\n" | ||
5005 | " </font>\n" | 5109 | " </font>\n" |
5006 | "</body>\n</html>\n"); | 5110 | "</body>\n" |
5111 | |||
5112 | "<script>\n" | ||
5113 | " converse.initialize({\n" | ||
5114 | " assets_path: '/converse.js/dist/',\n" | ||
5115 | " bosh_service_url: 'https://%s:5281/http-bind/',\n" | ||
5116 | " view_mode: 'overlayed',\n" | ||
5117 | " default_domain: '%s',\n" | ||
5118 | " muc_clear_messages_on_leave: false,\n" | ||
5119 | " muc_domain: 'chat.%s',\n" | ||
5120 | " muc_history_max_stanzas: 0,\n" | ||
5121 | " muc_send_probes: true,\n" | ||
5122 | " notify_all_room_messages: true,\n" | ||
5123 | " notification_delay:500000,\n" | ||
5124 | " play_sounds: true,\n" | ||
5125 | " registration_domain: '%s',\n" | ||
5126 | " show_chat_state_notifications: true,\n" | ||
5127 | " show_message_avatar: false,\n" | ||
5128 | " theme: 'dracula',\n" | ||
5129 | " time_format: 'dddd YYYY-MMM-DD HH:mm:ss'\n" | ||
5130 | " });\n" | ||
5131 | "</script>\n" | ||
5132 | "</html>\n", webHost, webHost, webHost, webHost); | ||
5007 | } | 5133 | } |
5008 | 5134 | ||
5009 | 5135 | ||
@@ -6995,7 +7121,7 @@ static void accountWebFooter(reqData *Rd, inputForm *oF) | |||
6995 | if (0 != Rd->errors->size(Rd->errors)) | 7121 | if (0 != Rd->errors->size(Rd->errors)) |
6996 | HTMLlist(Rd->reply, "errors -", Rd->errors); | 7122 | HTMLlist(Rd->reply, "errors -", Rd->errors); |
6997 | HTMLformEnd(Rd->reply); | 7123 | HTMLformEnd(Rd->reply); |
6998 | HTMLfooter(Rd->reply); | 7124 | HTMLfooter(Rd); |
6999 | } | 7125 | } |
7000 | 7126 | ||
7001 | static void accountAddWeb(reqData *Rd, inputForm *oF, inputValue *oV) | 7127 | static void accountAddWeb(reqData *Rd, inputForm *oF, inputValue *oV) |
@@ -7176,6 +7302,8 @@ static int accountRead(reqData *Rd, char *uuid, char *firstName, char *lastName) | |||
7176 | d("accountRead() single name |%s| |%s|", first, last); | 7302 | d("accountRead() single name |%s| |%s|", first, last); |
7177 | if (NULL == t) | 7303 | if (NULL == t) |
7178 | t = strchr(first, '+'); | 7304 | t = strchr(first, '+'); |
7305 | if (NULL == t) | ||
7306 | t = strchr(first, '.'); | ||
7179 | if (NULL != t) | 7307 | if (NULL != t) |
7180 | { | 7308 | { |
7181 | *t++ = '\0'; | 7309 | *t++ = '\0'; |
@@ -8344,6 +8472,47 @@ void account_html(char *file, reqData *Rd, HTMLfile *thisFile) | |||
8344 | C("Ending dynamic page %s %s", Rd->RUri, form); | 8472 | C("Ending dynamic page %s %s", Rd->RUri, form); |
8345 | } | 8473 | } |
8346 | 8474 | ||
8475 | // TODO - This is arse about, I get JSON, but send plain text. Need to set content type ehaders in the mod_auth_custom_http, and maybe send json back as well. | ||
8476 | void prosody_mod_auth_custom_http_json(char *file, reqData *Rd, HTMLfile *thisFile) | ||
8477 | { | ||
8478 | char *user = getStrH(Rd->body, "username"), *password = getStrH(Rd->body, "password"); | ||
8479 | int c = accountRead(Rd, NULL, user, NULL); | ||
8480 | |||
8481 | C("Starting dynamic page %s [ %s ]", Rd->RUri, user); | ||
8482 | // TODO - check it's HTTPS, and check it came from the same server. Same as account,html does, except no external iFrame allowed this time maybe. | ||
8483 | // On the other hand, prosody can't handle 301 redirections? | ||
8484 | |||
8485 | if (1 != c) | ||
8486 | bitch(Rd, "Cannot validate account.", "Account doesn't exist."); | ||
8487 | else | ||
8488 | { | ||
8489 | char *salt = getStrH(Rd->database, "auth.passwordSalt"), *hash = getStrH(Rd->database, "auth.passwordHash"); | ||
8490 | |||
8491 | c = 0; | ||
8492 | if ((NULL == password) || ('\0' == password[0])) | ||
8493 | bitch(Rd, "Cannot validate account.", "No password supplied."); | ||
8494 | else if (('\0' != salt[0]) && ('\0' != hash[0])) | ||
8495 | { | ||
8496 | D("Comparing passwords. %s %s %s", password, salt, hash); | ||
8497 | char *h = checkSLOSpassword(Rd, salt, password, hash, "Passwords are not the same."); | ||
8498 | |||
8499 | if (NULL == h) | ||
8500 | bitch(Rd, "Cannot validate account.", "Passwords are not the same."); | ||
8501 | else | ||
8502 | { | ||
8503 | I("Authenticated XMPP user %s@%s", user, Rd->Host); | ||
8504 | c = 1; | ||
8505 | free(h); | ||
8506 | } | ||
8507 | } | ||
8508 | else | ||
8509 | bitch(Rd, "Cannot validate account.", "No salted hash."); | ||
8510 | } | ||
8511 | |||
8512 | Rd->reply->addstrf(Rd->reply, (1 == c) ? "true" : "false"); | ||
8513 | C("Ending dynamic page %s", Rd->RUri); | ||
8514 | } | ||
8515 | |||
8347 | 8516 | ||
8348 | void forEachMember(char *verb, simFunction func, simFunction not) | 8517 | void forEachMember(char *verb, simFunction func, simFunction not) |
8349 | { | 8518 | { |
@@ -8550,6 +8719,7 @@ int scanForConfigs(char **cPaths) | |||
8550 | if ((tmp = configs->getstr(configs, "backupIARsim", false)) != NULL) {backupIARsim = tmp; D("Setting backupIARsim = %s", backupIARsim);} | 8719 | if ((tmp = configs->getstr(configs, "backupIARsim", false)) != NULL) {backupIARsim = tmp; D("Setting backupIARsim = %s", backupIARsim);} |
8551 | if ((tmp = configs->getstr(configs, "rsync", false)) != NULL) {rSync = tmp; D("Setting rsync = %s", rSync);} | 8720 | if ((tmp = configs->getstr(configs, "rsync", false)) != NULL) {rSync = tmp; D("Setting rsync = %s", rSync);} |
8552 | if ((vd = configs->getstr(configs, "rsyncPort", false)) != NULL) {rSyncPort = (int) *((float *) vd); D("Setting rsyncPort = %d", rSyncPort);} | 8721 | if ((vd = configs->getstr(configs, "rsyncPort", false)) != NULL) {rSyncPort = (int) *((float *) vd); D("Setting rsyncPort = %d", rSyncPort);} |
8722 | if ((tmp = configs->getstr(configs, "webHost", false)) != NULL) {webHost = tmp; D("Setting webHost = %s", webHost);} | ||
8553 | if ((tmp = configs->getstr(configs, "webRoot", false)) != NULL) {webRoot = tmp; D("Setting webRoot = %s", webRoot);} | 8723 | if ((tmp = configs->getstr(configs, "webRoot", false)) != NULL) {webRoot = tmp; D("Setting webRoot = %s", webRoot);} |
8554 | if ((tmp = configs->getstr(configs, "webSocket", false)) != NULL) {webSocket = tmp; D("Setting webSocket = %s", webSocket);} | 8724 | if ((tmp = configs->getstr(configs, "webSocket", false)) != NULL) {webSocket = tmp; D("Setting webSocket = %s", webSocket);} |
8555 | if ((vd = configs->get (configs, "seshRenew", NULL, false)) != NULL) {seshRenew = (int) *((float *) vd); D("Setting seshRenew = %d", seshRenew);} | 8725 | if ((vd = configs->get (configs, "seshRenew", NULL, false)) != NULL) {seshRenew = (int) *((float *) vd); D("Setting seshRenew = %d", seshRenew);} |
@@ -9362,11 +9532,12 @@ V("Doing %s for %s '%s' %s %s", modeStrings[currentMode], FLAG(m) ? "member" : | |||
9362 | // Start of web wrangling section. | 9532 | // Start of web wrangling section. |
9363 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 9533 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
9364 | char **initialEnv = environ; | 9534 | char **initialEnv = environ; |
9365 | char *tmp0, *tmp1; | 9535 | char *tmp0, *tmp1, *type; |
9366 | int count = 0, entries, bytes; | 9536 | int count = 0, entries, bytes; |
9367 | 9537 | ||
9368 | dynPages = qhashtbl(0, 0); | 9538 | dynPages = qhashtbl(0, 0); |
9369 | newDynPage("account.html", (pageFunction) account_html); | 9539 | newDynPage("account.html", (pageFunction) account_html); |
9540 | newDynPage("prosody_mod_auth_custom_http.json", (pageFunction) prosody_mod_auth_custom_http_json); | ||
9370 | 9541 | ||
9371 | // FCGI_LISTENSOCK_FILENO is the socket to the web server. | 9542 | // FCGI_LISTENSOCK_FILENO is the socket to the web server. |
9372 | // STDOUT and STDERR go to the web servers error log, or at least it does in Apache 2 mod_fcgid. | 9543 | // STDOUT and STDERR go to the web servers error log, or at least it does in Apache 2 mod_fcgid. |
@@ -9492,6 +9663,14 @@ t("ignoring QUERY"); | |||
9492 | Rd->RUri = xmprintf("%s%s", Rd->Script, Rd->Path); | 9663 | Rd->RUri = xmprintf("%s%s", Rd->Script, Rd->Path); |
9493 | } | 9664 | } |
9494 | t("BODY"); | 9665 | t("BODY"); |
9666 | |||
9667 | // TODO - is there any sort of content type on the incoming request headers I could maybe use here? | ||
9668 | memset(toybuf, 0, sizeof(toybuf)); | ||
9669 | snprintf(toybuf, sizeof(toybuf), "%s%s%s", scRoot, webRoot, Rd->Path); | ||
9670 | tmp0 = qfile_get_ext(toybuf); | ||
9671 | type = mimeTypes->getstr(mimeTypes, tmp0, false); | ||
9672 | free(tmp0); | ||
9673 | |||
9495 | char *Body = NULL; | 9674 | char *Body = NULL; |
9496 | if (Length != NULL) | 9675 | if (Length != NULL) |
9497 | { | 9676 | { |
@@ -9499,16 +9678,51 @@ t("BODY"); | |||
9499 | Body = xmalloc(len + 1); | 9678 | Body = xmalloc(len + 1); |
9500 | int c = FCGI_fread(Body, 1, len, FCGI_stdin); | 9679 | int c = FCGI_fread(Body, 1, len, FCGI_stdin); |
9501 | if (c != len) | 9680 | if (c != len) |
9502 | { | ||
9503 | E("Tried to read %d of the body, only got %d!", len, c); | 9681 | E("Tried to read %d of the body, only got %d!", len, c); |
9504 | } | ||
9505 | Body[len] = '\0'; | 9682 | Body[len] = '\0'; |
9506 | } | 9683 | } |
9507 | else | 9684 | else |
9508 | Length = "0"; | 9685 | { |
9509 | Rd->body = toknize(Body, "=&"); | 9686 | Length = "0"; |
9687 | Body = xmalloc(1); | ||
9688 | Body[0] = '\0'; | ||
9689 | } | ||
9690 | if (strcmp("application/json", type) == 0) | ||
9691 | { | ||
9692 | json_char *json = (json_char*) Body; | ||
9693 | json_value* value = json_parse(json, strtol(Length, NULL, 10)); | ||
9694 | |||
9695 | Rd->body = qhashtbl(0, 0); | ||
9696 | if (value == NULL) | ||
9697 | E("Unable to parse NULL data!"); | ||
9698 | else | ||
9699 | { | ||
9700 | // PrintJSON(json); | ||
9701 | if (value->type == json_object) | ||
9702 | { | ||
9703 | int length = value->u.object.length, x; | ||
9704 | |||
9705 | for (x = 0; x < length; x++) | ||
9706 | { | ||
9707 | char *name = value->u.object.values[x].name; | ||
9708 | |||
9709 | if (value->u.object.values[x].value->type == json_string) | ||
9710 | { | ||
9711 | D("%s = %s", name, value->u.object.values[x].value->u.string.ptr); | ||
9712 | Rd->body->putstr(Rd->body, name, value->u.object.values[x].value->u.string.ptr); | ||
9713 | } | ||
9714 | |||
9715 | } | ||
9716 | } | ||
9717 | } | ||
9718 | json_value_free(value); | ||
9719 | } | ||
9720 | else | ||
9721 | { | ||
9722 | Rd->body = toknize(Body, "=&"); | ||
9723 | santize(Rd->body); | ||
9724 | } | ||
9510 | free(Body); | 9725 | free(Body); |
9511 | santize(Rd->body); | ||
9512 | 9726 | ||
9513 | D("%s %s://%s%s -> %s%s%s", Rd->Method, Rd->Scheme, Rd->Host, Rd->RUri, scRoot, webRoot, Rd->Path); | 9727 | D("%s %s://%s%s -> %s%s%s", Rd->Method, Rd->Scheme, Rd->Host, Rd->RUri, scRoot, webRoot, Rd->Path); |
9514 | D("Started FCGI web request ROLE = %s, body is %s bytes, pid %d.", Role, Length, getpid()); | 9728 | D("Started FCGI web request ROLE = %s, body is %s bytes, pid %d.", Role, Length, getpid()); |
@@ -9555,10 +9769,10 @@ t("BODY"); | |||
9555 | // Content-Security-Policy can get complex, and I first wrote that when it was very simple. lol | 9769 | // Content-Security-Policy can get complex, and I first wrote that when it was very simple. lol |
9556 | if ('\0' != webIframers[0]) | 9770 | if ('\0' != webIframers[0]) |
9557 | Rd->Rheaders->putstrf(Rd->Rheaders, "Content-Security-Policy", | 9771 | Rd->Rheaders->putstrf(Rd->Rheaders, "Content-Security-Policy", |
9558 | "default-src 'self'; script-src 'none'; form-action 'self'; style-src 'self' 'unsafe-inline'; frame-ancestors 'self' %s", webIframers); | 9772 | "default-src 'self'; script-src 'self' 'unsafe-inline'; form-action 'self'; style-src 'self' 'unsafe-inline'; frame-ancestors 'self' %s; connect-src 'self' %s:5281/http-bind/;", webIframers, webHost); |
9559 | else | 9773 | else |
9560 | { | 9774 | { |
9561 | Rd->Rheaders->putstr(Rd->Rheaders, "Content-Security-Policy", "default-src 'self'; script-src 'none'; form-action 'self'; style-src 'self' 'unsafe-inline'"); | 9775 | Rd->Rheaders->putstrf(Rd->Rheaders, "Content-Security-Policy", "default-src 'self'; script-src 'self' 'unsafe-inline'; form-action 'self'; style-src 'self' 'unsafe-inline'; connect-src 'self' %s:5281/http-bind/;", webHost); |
9562 | Rd->Rheaders->putstr(Rd->Rheaders, "X-Frame-Options", "SAMEORIGIN"); // This is deprecated, and is an all or nothing thing. | 9776 | Rd->Rheaders->putstr(Rd->Rheaders, "X-Frame-Options", "SAMEORIGIN"); // This is deprecated, and is an all or nothing thing. |
9563 | } | 9777 | } |
9564 | Rd->Rheaders->putstr(Rd->Rheaders, "X-XSS-Protection", "1;mode=block"); | 9778 | Rd->Rheaders->putstr(Rd->Rheaders, "X-XSS-Protection", "1;mode=block"); |
@@ -9573,8 +9787,6 @@ t("BODY"); | |||
9573 | goto sendReply; | 9787 | goto sendReply; |
9574 | } | 9788 | } |
9575 | 9789 | ||
9576 | memset(toybuf, 0, sizeof(toybuf)); | ||
9577 | snprintf(toybuf, sizeof(toybuf), "%s%s%s", scRoot, webRoot, Rd->Path); | ||
9578 | HTMLfile *thisFile = checkHTMLcache(toybuf); | 9790 | HTMLfile *thisFile = checkHTMLcache(toybuf); |
9579 | if (NULL == thisFile) | 9791 | if (NULL == thisFile) |
9580 | { | 9792 | { |
@@ -9597,12 +9809,9 @@ t("BODY"); | |||
9597 | goto sendReply; | 9809 | goto sendReply; |
9598 | } | 9810 | } |
9599 | 9811 | ||
9600 | tmp0 = qfile_get_ext(toybuf); | 9812 | if (NULL != type) |
9601 | tmp1 = mimeTypes->getstr(mimeTypes, tmp0, false); | ||
9602 | free(tmp0); | ||
9603 | if (NULL != tmp1) | ||
9604 | { | 9813 | { |
9605 | if (strncmp("text/", tmp1, 5) != 0) | 9814 | if (strncmp("text/", type, 5) != 0) |
9606 | { | 9815 | { |
9607 | E("Only text formats are supported - %s", toybuf); | 9816 | E("Only text formats are supported - %s", toybuf); |
9608 | Rd->Rheaders->putstr(Rd->Rheaders, "Status", "415 Unsupported Media Type"); | 9817 | Rd->Rheaders->putstr(Rd->Rheaders, "Status", "415 Unsupported Media Type"); |