diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/sledjchisl/sledjchisl.c | 409 |
1 files changed, 266 insertions, 143 deletions
diff --git a/src/sledjchisl/sledjchisl.c b/src/sledjchisl/sledjchisl.c index 3391ad3..07477db 100644 --- a/src/sledjchisl/sledjchisl.c +++ b/src/sledjchisl/sledjchisl.c | |||
@@ -488,6 +488,8 @@ qlist_t *dbRequests; | |||
488 | // A better idea, when we spawn tmux or spawn-fcgi, capture STDERR, full log everything to that, filtered log to the tmux console (STDOUT). | 488 | // A better idea, when we spawn tmux or spawn-fcgi, capture STDERR, full log everything to that, filtered log to the tmux console (STDOUT). |
489 | // Then we can use STDOUT / STDIN to run the console stuff. | 489 | // Then we can use STDOUT / STDIN to run the console stuff. |
490 | 490 | ||
491 | // TODO - escape anything that will turn the console into garbage. | ||
492 | |||
491 | // https://stackoverflow.com/questions/4842424/list-of-ansi-color-escape-sequences | 493 | // https://stackoverflow.com/questions/4842424/list-of-ansi-color-escape-sequences |
492 | char *logTypes[] = | 494 | char *logTypes[] = |
493 | { | 495 | { |
@@ -633,7 +635,9 @@ int sendTmuxCmd(char *dest, char *cmd) | |||
633 | void waitTmuxText(char *dest, char *text) | 635 | void waitTmuxText(char *dest, char *text) |
634 | { | 636 | { |
635 | int i; | 637 | int i; |
636 | char *c = xmprintf("sleep 5; %s %s/%s capture-pane -t %s:'%s' -p | grep -E '%s' 2>&1 > /dev/null", Tcmd, scRun, Tsocket, Tconsole, dest, text); | 638 | // Using " for the grep pattern, coz ' might be used in a sim name. |
639 | // TODO - should escape \ " ` in text. | ||
640 | char *c = xmprintf("sleep 5; %s %s/%s capture-pane -t %s:'%s' -p | grep -F \"%s\" 2>&1 > /dev/null", Tcmd, scRun, Tsocket, Tconsole, dest, text); | ||
637 | 641 | ||
638 | D("Waiting for '%s'.", text); | 642 | D("Waiting for '%s'.", text); |
639 | do | 643 | do |
@@ -704,6 +708,25 @@ static int filterSims(struct dirtree *node) | |||
704 | return 0; | 708 | return 0; |
705 | } | 709 | } |
706 | 710 | ||
711 | // We particularly don't want \ " ` | ||
712 | char *cleanSimName(char *name) | ||
713 | { | ||
714 | size_t l = strlen(name); | ||
715 | char *ret = xmalloc(l + 1); | ||
716 | int i, j = 0; | ||
717 | |||
718 | for (i = 0; i < l; i++) | ||
719 | { | ||
720 | char r = name[i]; | ||
721 | |||
722 | if ((' ' == r) || (isalnum(r) != 0)) | ||
723 | ret[j++] = r; | ||
724 | } | ||
725 | ret[j] = '\0'; | ||
726 | |||
727 | return ret; | ||
728 | } | ||
729 | |||
707 | simList *getSims() | 730 | simList *getSims() |
708 | { | 731 | { |
709 | simList *sims = xmalloc(sizeof(simList)); | 732 | simList *sims = xmalloc(sizeof(simList)); |
@@ -2244,7 +2267,7 @@ d(" %s = %s", qstrtrim_head(key), val); | |||
2244 | return ret; | 2267 | return ret; |
2245 | } | 2268 | } |
2246 | 2269 | ||
2247 | void santize(qhashtbl_t *tbl, bool decode) | 2270 | void santize(qhashtbl_t *tbl) |
2248 | { | 2271 | { |
2249 | qhashtbl_obj_t obj; | 2272 | qhashtbl_obj_t obj; |
2250 | 2273 | ||
@@ -2254,36 +2277,12 @@ void santize(qhashtbl_t *tbl, bool decode) | |||
2254 | { | 2277 | { |
2255 | char *n = obj.name, *o = (char *) obj.data; | 2278 | char *n = obj.name, *o = (char *) obj.data; |
2256 | 2279 | ||
2257 | if (decode) | 2280 | qurl_decode(o); |
2258 | qurl_decode(o); | ||
2259 | |||
2260 | // if ((strcmp(n, "password") != 0) && (strcmp(n, "psswd") != 0)) | ||
2261 | { | ||
2262 | // Poor mans Bobby Tables protection. | ||
2263 | // TODO - make this reversable, especially so these things can be used in aboutMe, and come out the other end unscathed. | ||
2264 | // qurl_encode doesn't handle \, but does the rest. | ||
2265 | // So that means don't qurl_decode it, and encode \\. | ||
2266 | // But then I have to qurl_decode everwhere. | ||
2267 | o = qstrreplace("tr", o, "'", "_"); | ||
2268 | o = qstrreplace("tr", o, "\"", "_"); | ||
2269 | o = qstrreplace("tr", o, ";", "_"); | ||
2270 | o = qstrreplace("tr", o, "(", "_"); | ||
2271 | o = qstrreplace("tr", o, ")", "_"); | ||
2272 | } | ||
2273 | |||
2274 | tbl->putstr(tbl, n, o); | 2281 | tbl->putstr(tbl, n, o); |
2275 | } | 2282 | } |
2276 | tbl->unlock(tbl); | 2283 | tbl->unlock(tbl); |
2277 | } | 2284 | } |
2278 | 2285 | ||
2279 | /* | ||
2280 | char *unsantize(char *str) | ||
2281 | { | ||
2282 | char *ret = qurl_decode(xstrdup(str)); | ||
2283 | return ret; | ||
2284 | } | ||
2285 | */ | ||
2286 | |||
2287 | void outize(qgrow_t *reply, qhashtbl_t *tbl, char *label) | 2286 | void outize(qgrow_t *reply, qhashtbl_t *tbl, char *label) |
2288 | { | 2287 | { |
2289 | reply->addstrf(reply, "%s:<br>\n<pre>\n", label); | 2288 | reply->addstrf(reply, "%s:<br>\n<pre>\n", label); |
@@ -2296,43 +2295,6 @@ void outize(qgrow_t *reply, qhashtbl_t *tbl, char *label) | |||
2296 | reply->addstr(reply, "</pre>\n"); | 2295 | reply->addstr(reply, "</pre>\n"); |
2297 | } | 2296 | } |
2298 | 2297 | ||
2299 | char *displayPrep(char *str) | ||
2300 | { | ||
2301 | char *ret = xstrdup(str), *t; | ||
2302 | |||
2303 | qurl_decode(ret); | ||
2304 | t = qstrreplace("tn", ret, "<", "<"); | ||
2305 | free(ret); | ||
2306 | ret = NULL; | ||
2307 | if (NULL != t) | ||
2308 | { | ||
2309 | ret = qstrreplace("tn", t, ">", ">"); | ||
2310 | if (NULL == ret) | ||
2311 | ret = t; | ||
2312 | else | ||
2313 | free(t); | ||
2314 | } | ||
2315 | |||
2316 | if (NULL == ret) | ||
2317 | ret = xstrdup(str); | ||
2318 | |||
2319 | return ret; | ||
2320 | } | ||
2321 | |||
2322 | char *encodeSlash(char *str) | ||
2323 | { | ||
2324 | char *ret = xstrdup(str), *t = qstrreplace("tn", str, "\\", "%5c"); | ||
2325 | |||
2326 | if (NULL != t) | ||
2327 | { | ||
2328 | free(ret); | ||
2329 | ret = t; | ||
2330 | } | ||
2331 | |||
2332 | return ret; | ||
2333 | } | ||
2334 | |||
2335 | |||
2336 | // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie | 2298 | // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie |
2337 | enum cookieSame | 2299 | enum cookieSame |
2338 | { | 2300 | { |
@@ -2476,6 +2438,89 @@ static void HTMLheader(qgrow_t *reply, char *title) | |||
2476 | HTMLdebug(reply); | 2438 | HTMLdebug(reply); |
2477 | } | 2439 | } |
2478 | 2440 | ||
2441 | // TODO - maybe escape non printables as well? | ||
2442 | char *HTMLentities[] = | ||
2443 | { | ||
2444 | "", "", "", "", "", "", "", "", "", // NUL SOH STX ETX EOT ENQ ACK BEL BS | ||
2445 | "	", "
", | ||
2446 | "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", // VT FF CR SO SI DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US | ||
2447 | " ", // Space | ||
2448 | "!", """, | ||
2449 | "#", "$", | ||
2450 | "%", "&", | ||
2451 | "'", | ||
2452 | "(", ")", | ||
2453 | "*", | ||
2454 | "+", | ||
2455 | ",", | ||
2456 | "-", | ||
2457 | ".", | ||
2458 | "/", | ||
2459 | "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", | ||
2460 | ":", ";", | ||
2461 | "<", "=", ">", | ||
2462 | "?", | ||
2463 | "@", | ||
2464 | "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", | ||
2465 | "[", "\", "]", | ||
2466 | "^", | ||
2467 | "_", | ||
2468 | "`", | ||
2469 | "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", | ||
2470 | "{", "|", "}", | ||
2471 | "~", | ||
2472 | "", // DEL | ||
2473 | " " // This is actually 160, not 128, but I hack around that. | ||
2474 | }; | ||
2475 | static void HTMLescapeString(qgrow_t *reply, char *string) | ||
2476 | { | ||
2477 | size_t l = strlen(string); | ||
2478 | char *t = xmalloc(l * 10 + 1); | ||
2479 | int i, j = 0; | ||
2480 | boolean space = FALSE; | ||
2481 | |||
2482 | for (i = 0; i < l; i++) | ||
2483 | { | ||
2484 | int s = string[i]; | ||
2485 | |||
2486 | // Alternate long line of spaces with space and . | ||
2487 | if (' ' == s) | ||
2488 | { | ||
2489 | if (space) | ||
2490 | { | ||
2491 | s = 128; | ||
2492 | space = FALSE; | ||
2493 | } | ||
2494 | else | ||
2495 | space = TRUE; | ||
2496 | } | ||
2497 | else | ||
2498 | { | ||
2499 | space = FALSE; | ||
2500 | if (128 == s) // The real 128 character. | ||
2501 | { | ||
2502 | t[j++] = ' '; | ||
2503 | continue; | ||
2504 | } | ||
2505 | } | ||
2506 | |||
2507 | if (128 >= s) | ||
2508 | { | ||
2509 | char *r = HTMLentities[s]; | ||
2510 | size_t m = strlen(r); | ||
2511 | int k; | ||
2512 | |||
2513 | for (k = 0; k < m; k++) | ||
2514 | t[j++] = r[k]; | ||
2515 | } | ||
2516 | else | ||
2517 | t[j++] = ' '; | ||
2518 | } | ||
2519 | t[j] = '\0'; | ||
2520 | reply->addstr(reply, t); | ||
2521 | free(t); | ||
2522 | } | ||
2523 | |||
2479 | static void HTMLtable(qgrow_t *reply, MYSQL *db, MYSQL_RES *result, char *caption, char *URL, char *id) | 2524 | static void HTMLtable(qgrow_t *reply, MYSQL *db, MYSQL_RES *result, char *caption, char *URL, char *id) |
2480 | { | 2525 | { |
2481 | char *tbl = ""; | 2526 | char *tbl = ""; |
@@ -2543,7 +2588,11 @@ static void HTMLtable(qgrow_t *reply, MYSQL *db, MYSQL_RES *result, char *captio | |||
2543 | static void HTMLhidden(qgrow_t *reply, char *name, char *val) | 2588 | static void HTMLhidden(qgrow_t *reply, char *name, char *val) |
2544 | { | 2589 | { |
2545 | if ((NULL != val) && ("" != val)) | 2590 | if ((NULL != val) && ("" != val)) |
2546 | reply->addstrf(reply, " <input type=\"hidden\" name=\"%s\" value=\"%s\">\n", name, val); | 2591 | { |
2592 | reply->addstrf(reply, " <input type=\"hidden\" name=\"%s\" value=\"", name); | ||
2593 | HTMLescapeString(reply, val); | ||
2594 | reply->addstr(reply, "\">\n"); | ||
2595 | } | ||
2547 | } | 2596 | } |
2548 | 2597 | ||
2549 | static void HTMLform(qgrow_t *reply, char *action, char *token) | 2598 | static void HTMLform(qgrow_t *reply, char *action, char *token) |
@@ -2596,7 +2645,11 @@ static void HTMLtextArea(qgrow_t *reply, char *name, char *title, int rows, int | |||
2596 | if ("" != wrap) | 2645 | if ("" != wrap) |
2597 | reply->addstrf(reply, " wrap=\"%s\"", wrap); | 2646 | reply->addstrf(reply, " wrap=\"%s\"", wrap); |
2598 | if ((NULL != val) && ("" != val)) | 2647 | if ((NULL != val) && ("" != val)) |
2599 | reply->addstrf(reply, ">%s</textarea></label></p>\n", val); | 2648 | { |
2649 | reply->addstr(reply, ">"); | ||
2650 | HTMLescapeString(reply, val); | ||
2651 | reply->addstr(reply, "</textarea></label></p>\n"); | ||
2652 | } | ||
2600 | else | 2653 | else |
2601 | reply->addstrf(reply, "></textarea></label></p>\n"); | 2654 | reply->addstrf(reply, "></textarea></label></p>\n"); |
2602 | } | 2655 | } |
@@ -2605,7 +2658,11 @@ static void HTMLtext(qgrow_t *reply, char *type, char *title, char *name, char * | |||
2605 | { | 2658 | { |
2606 | reply->addstrf(reply, " <p><label>%s : <input type=\"%s\" name=\"%s\"", title, type, name); | 2659 | reply->addstrf(reply, " <p><label>%s : <input type=\"%s\" name=\"%s\"", title, type, name); |
2607 | if ((NULL != val) && ("" != val)) | 2660 | if ((NULL != val) && ("" != val)) |
2608 | reply->addstrf(reply, " value=\"%s\"", val); | 2661 | { |
2662 | reply->addstr(reply, " value=\""); | ||
2663 | HTMLescapeString(reply, val); | ||
2664 | reply->addstr(reply, "\""); | ||
2665 | } | ||
2609 | if (0 < size) | 2666 | if (0 < size) |
2610 | reply->addstrf(reply, " size=\"%d\"", size); | 2667 | reply->addstrf(reply, " size=\"%d\"", size); |
2611 | if (0 < max) | 2668 | if (0 < max) |
@@ -2653,7 +2710,11 @@ static void HTMLlist(qgrow_t *reply, char *title, qlist_t *list) | |||
2653 | memset((void*)&obj, 0, sizeof(obj)); // must be cleared before call | 2710 | memset((void*)&obj, 0, sizeof(obj)); // must be cleared before call |
2654 | list->lock(list); | 2711 | list->lock(list); |
2655 | while (list->getnext(list, &obj, false) == true) | 2712 | while (list->getnext(list, &obj, false) == true) |
2656 | reply->addstrf(reply, "<li>%s</li>\n", (char *) obj.data); | 2713 | { |
2714 | reply->addstr(reply, "<li>"); | ||
2715 | HTMLescapeString(reply, (char *) obj.data); | ||
2716 | reply->addstr(reply, "</li>\n"); | ||
2717 | } | ||
2657 | list->unlock(list); | 2718 | list->unlock(list); |
2658 | reply->addstr(reply, "</ul>\n"); | 2719 | reply->addstr(reply, "</ul>\n"); |
2659 | } | 2720 | } |
@@ -3623,61 +3684,95 @@ systemFolders sysFolders[] = | |||
3623 | {NULL, -1} | 3684 | {NULL, -1} |
3624 | }; | 3685 | }; |
3625 | 3686 | ||
3687 | boolean writeLuaDouble(reqData *Rd, int fd, char *file, char *name, double number) | ||
3688 | { | ||
3689 | boolean ret = TRUE; | ||
3690 | // TODO - putting these in Lua as numbers causes lua_tolstring to barf when we read them. Though Lua is supposed to convert between numbers and strings. | ||
3691 | char *t = xmprintf(" ['%s'] = '%f',\n", name, number); // NOTE - default precision is 6 decimal places. | ||
3692 | size_t l = strlen(t); | ||
3693 | |||
3694 | if (l != writeall(fd, t, l)) | ||
3695 | { | ||
3696 | perror_msg("Writing %s", file); | ||
3697 | ret = FALSE; | ||
3698 | } | ||
3699 | free(t); | ||
3700 | return ret; | ||
3701 | } | ||
3702 | |||
3703 | boolean writeLuaInteger(reqData *Rd, int fd, char *file, char *name, long number) | ||
3704 | { | ||
3705 | boolean ret = TRUE; | ||
3706 | // TODO - putting these in Lua as numbers causes lua_tolstring to barf when we read them. Though Lua is supposed to convert between numbers and strings. | ||
3707 | char *t = xmprintf(" ['%s'] = '%ld',\n", name, number); | ||
3708 | size_t l = strlen(t); | ||
3709 | |||
3710 | if (l != writeall(fd, t, l)) | ||
3711 | { | ||
3712 | perror_msg("Writing %s", file); | ||
3713 | ret = FALSE; | ||
3714 | } | ||
3715 | free(t); | ||
3716 | return ret; | ||
3717 | } | ||
3718 | |||
3719 | boolean writeLuaString(reqData *Rd, int fd, char *file, char *name, char *string) | ||
3720 | { | ||
3721 | boolean ret = TRUE; | ||
3722 | |||
3723 | if (NULL == string) | ||
3724 | string = getStrH(Rd->stuff, name); | ||
3725 | |||
3726 | size_t l = strlen(string); | ||
3727 | char *t0 = xmalloc(l * 2 + 1); | ||
3728 | int i, j = 0; | ||
3729 | |||
3730 | // TODO - maybe escape other non printables as well? | ||
3731 | for (i = 0; i < l; i++) | ||
3732 | { | ||
3733 | // We don't need to escape [] here, coz we are using '' below. Same applies to ", but do it anyway. | ||
3734 | switch(string[i]) | ||
3735 | { | ||
3736 | case '\n': | ||
3737 | case '\\': | ||
3738 | case '\'': | ||
3739 | case '"': | ||
3740 | t0[j++] = '\\'; break; | ||
3741 | } | ||
3742 | if ('\n' == string[i]) | ||
3743 | t0[j++] = 'n'; | ||
3744 | else if ('\r' == string[i]) | ||
3745 | ; | ||
3746 | else | ||
3747 | t0[j++] = string[i]; | ||
3748 | } | ||
3749 | t0[j] = '\0'; | ||
3750 | |||
3751 | char *t1 = xmprintf(" ['%s'] = '%s',\n", name, t0); | ||
3752 | |||
3753 | l = strlen(t1); | ||
3754 | if (l != writeall(fd, t1, l)) | ||
3755 | { | ||
3756 | perror_msg("Writing %s to %s", name, file); | ||
3757 | ret = FALSE; | ||
3758 | } | ||
3759 | free(t1); | ||
3760 | free(t0); | ||
3761 | return ret; | ||
3762 | } | ||
3763 | |||
3626 | static void accountWrite(reqData *Rd) | 3764 | static void accountWrite(reqData *Rd) |
3627 | { | 3765 | { |
3628 | char *uuid = getStrH(Rd->database, "UserAccounts.PrincipalID"); | 3766 | char *uuid = getStrH(Rd->database, "UserAccounts.PrincipalID"); |
3629 | char *file = xmprintf("%s/users/%s.lua", scData, uuid); | 3767 | char *file = xmprintf("%s/users/%s.lua", scData, uuid); |
3630 | char *level = getStrH(Rd->database, "UserAccounts.UserLevel"); | 3768 | char *level = getStrH(Rd->database, "UserAccounts.UserLevel"); |
3631 | char *link = (NULL == Rd->lnk) ? "" : Rd->lnk->hashish; | 3769 | char *link = (NULL == Rd->lnk) ? "" : Rd->lnk->hashish; |
3632 | char *about = encodeSlash(getStrH(Rd->stuff, "aboutMe")); | 3770 | char *tnm = "user = \n{\n"; |
3633 | char *voucher = encodeSlash(getStrH(Rd->stuff, "voucher")); | ||
3634 | char *tnm = xmprintf( "user = \n" | ||
3635 | "{\n" | ||
3636 | " ['name']='%s',\n" | ||
3637 | // TODO - putting these in Lua as numbers causes lua_tolstring to barf when we read them. Though Lua is supposed to convert between numbers and strings. | ||
3638 | " ['created']='%ld',\n" | ||
3639 | " ['email']='%s',\n" | ||
3640 | " ['title']='%s',\n" | ||
3641 | " ['level']='%s',\n" | ||
3642 | " ['flags']='%d',\n" | ||
3643 | " ['active']='%d',\n" | ||
3644 | " ['passwordHash']='%s',\n" | ||
3645 | " ['passwordSalt']='%s',\n" | ||
3646 | " ['UUID']='%s',\n" | ||
3647 | " ['DoB']='%s',\n" | ||
3648 | " ['agree']='%s',\n" | ||
3649 | " ['adult']='%s',\n" | ||
3650 | " ['aboutMe']='%s',\n" | ||
3651 | " ['vouched']='%s',\n" | ||
3652 | " ['voucher']='%s',\n" | ||
3653 | " ['linky-hashish']='%s',\n" | ||
3654 | "}\n" | ||
3655 | "return user\n", | ||
3656 | getStrH(Rd->stuff, "name"), | ||
3657 | (strcmp("", getStrH(Rd->stuff, "created")) != 0) ? atol(getStrH(Rd->stuff, "created")) : (long) Rd->shs.timeStamp[1].tv_sec, | ||
3658 | getStrH(Rd->stuff, "email"), | ||
3659 | getLevel(atoi(level)), | ||
3660 | level, | ||
3661 | 0, | ||
3662 | 1, | ||
3663 | getStrH(Rd->stuff, "passwordHash"), | ||
3664 | getStrH(Rd->stuff, "passwordSalt"), | ||
3665 | uuid, | ||
3666 | getStrH(Rd->stuff, "DoB"), | ||
3667 | getStrH(Rd->stuff, "agree"), | ||
3668 | getStrH(Rd->stuff, "adult"), | ||
3669 | about, | ||
3670 | "off", | ||
3671 | voucher, | ||
3672 | link | ||
3673 | ); | ||
3674 | 3771 | ||
3675 | struct stat st; | 3772 | struct stat st; |
3676 | int s = stat(file, &st); | 3773 | int s = stat(file, &st); |
3677 | |||
3678 | int fd = notstdio(xcreate_stdio(file, O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC, S_IRUSR | S_IWUSR)); | 3774 | int fd = notstdio(xcreate_stdio(file, O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC, S_IRUSR | S_IWUSR)); |
3679 | size_t l = strlen(tnm); | 3775 | size_t l = strlen(tnm); |
3680 | |||
3681 | uuid_t binuuid; | 3776 | uuid_t binuuid; |
3682 | 3777 | ||
3683 | uuid_clear(binuuid); | 3778 | uuid_clear(binuuid); |
@@ -3689,19 +3784,48 @@ static void accountWrite(reqData *Rd) | |||
3689 | I("Creating user %s.", file); | 3784 | I("Creating user %s.", file); |
3690 | else | 3785 | else |
3691 | I("Updating user %s.", file); | 3786 | I("Updating user %s.", file); |
3787 | |||
3692 | if (l != writeall(fd, tnm, l)) | 3788 | if (l != writeall(fd, tnm, l)) |
3693 | perror_msg("Writing %s", file); | 3789 | perror_msg("Writing %s", file); |
3694 | else | 3790 | else |
3695 | { | 3791 | { |
3696 | char *name = Rd->stuff->getstr(Rd->stuff, "name", true); | 3792 | char *name = Rd->stuff->getstr(Rd->stuff, "name", true); |
3697 | char *nm = xmprintf("%s/users/%s.lua", scData, qstrreplace("tr", name, " ", "_")); | 3793 | char *end = "}\nreturn user\n"; |
3698 | 3794 | ||
3699 | free(file); | 3795 | if (!writeLuaString (Rd, fd, file, "name", name)) goto notWritten; |
3700 | file = xmprintf("%s.lua", uuid); | 3796 | if (!writeLuaInteger(Rd, fd, file, "created", |
3701 | I("Symlinking %s to %s", file, nm); | 3797 | (strcmp("", getStrH(Rd->stuff, "created")) != 0) ? atol(getStrH(Rd->stuff, "created")) : (long) Rd->shs.timeStamp[1].tv_sec)) goto notWritten; |
3702 | if (0 != symlink(file, nm)) | 3798 | if (!writeLuaString (Rd, fd, file, "email", NULL)) goto notWritten; |
3703 | perror_msg("Symlinking %s to %s", file, nm); | 3799 | if (!writeLuaString (Rd, fd, file, "title", getLevel(atoi(level)))) goto notWritten; |
3704 | free(nm); free(name); | 3800 | if (!writeLuaString (Rd, fd, file, "level", level)) goto notWritten; |
3801 | if (!writeLuaInteger(Rd, fd, file, "flags", 0)) goto notWritten; | ||
3802 | if (!writeLuaInteger(Rd, fd, file, "active", 1)) goto notWritten; | ||
3803 | if (!writeLuaString (Rd, fd, file, "passwordHash", NULL)) goto notWritten; | ||
3804 | if (!writeLuaString (Rd, fd, file, "passwordSalt", NULL)) goto notWritten; | ||
3805 | if (!writeLuaString (Rd, fd, file, "UUID", uuid)) goto notWritten; | ||
3806 | if (!writeLuaString (Rd, fd, file, "DoB", NULL)) goto notWritten; | ||
3807 | if (!writeLuaString (Rd, fd, file, "agree", NULL)) goto notWritten; | ||
3808 | if (!writeLuaString (Rd, fd, file, "adult", NULL)) goto notWritten; | ||
3809 | if (!writeLuaString (Rd, fd, file, "aboutMe", NULL)) goto notWritten; | ||
3810 | if (!writeLuaString (Rd, fd, file, "vouched", "off")) goto notWritten; | ||
3811 | if (!writeLuaString (Rd, fd, file, "voucher", NULL)) goto notWritten; | ||
3812 | if (!writeLuaString (Rd, fd, file, "link", link)) goto notWritten; | ||
3813 | l = strlen(end); | ||
3814 | if (l != writeall(fd, end, l)) | ||
3815 | perror_msg("Writing %s", file); | ||
3816 | else | ||
3817 | { | ||
3818 | char *nm = xmprintf("%s/users/%s.lua", scData, qstrreplace("tr", name, " ", "_")); | ||
3819 | |||
3820 | free(file); | ||
3821 | file = xmprintf("%s.lua", uuid); | ||
3822 | I("Symlinking %s to %s", file, nm); | ||
3823 | if (0 != symlink(file, nm)) | ||
3824 | perror_msg("Symlinking %s to %s", file, nm); | ||
3825 | free(nm); | ||
3826 | } | ||
3827 | notWritten: | ||
3828 | free(name); | ||
3705 | } | 3829 | } |
3706 | xclose(fd); | 3830 | xclose(fd); |
3707 | 3831 | ||
@@ -3925,9 +4049,6 @@ T(c); | |||
3925 | } | 4049 | } |
3926 | else | 4050 | else |
3927 | W("Not writing NULL UUID user!"); | 4051 | W("Not writing NULL UUID user!"); |
3928 | free(tnm); | ||
3929 | free(voucher); | ||
3930 | free(about); | ||
3931 | free(file); | 4052 | free(file); |
3932 | } | 4053 | } |
3933 | 4054 | ||
@@ -4554,7 +4675,7 @@ static int emailValidate(reqData *Rd, inputForm *iF, inputValue *iV) | |||
4554 | } | 4675 | } |
4555 | static void emailWeb(reqData *Rd, inputForm *oF, inputValue *oV) | 4676 | static void emailWeb(reqData *Rd, inputForm *oF, inputValue *oV) |
4556 | { | 4677 | { |
4557 | HTMLtext(Rd->reply, "email", oV->field->title, oV->field->name, displayPrep(getStrH(Rd->stuff, oV->field->name)), oV->field->viewLength, oV->field->maxLength, oV->field->flags & FLD_REQUIRED); | 4678 | HTMLtext(Rd->reply, "email", oV->field->title, oV->field->name, getStrH(Rd->stuff, oV->field->name), oV->field->viewLength, oV->field->maxLength, oV->field->flags & FLD_REQUIRED); |
4558 | Rd->reply->addstrf(Rd->reply, "<p>An email will be sent from %s@%s, and it might be in your spam folder, coz these sorts of emails sometimes end up there. " | 4679 | Rd->reply->addstrf(Rd->reply, "<p>An email will be sent from %s@%s, and it might be in your spam folder, coz these sorts of emails sometimes end up there. " |
4559 | "You should add that email address to your contacts, or otherwise let it through your spam filter.</p>", | 4680 | "You should add that email address to your contacts, or otherwise let it through your spam filter.</p>", |
4560 | "grid_no_reply", Rd->Host); | 4681 | "grid_no_reply", Rd->Host); |
@@ -4748,9 +4869,10 @@ static int voucherValidate(reqData *Rd, inputForm *oF, inputValue *oV) | |||
4748 | 4869 | ||
4749 | if ((0 == ret) && (NULL != voucher)) | 4870 | if ((0 == ret) && (NULL != voucher)) |
4750 | { | 4871 | { |
4751 | char *t = qurl_encode(voucher, strlen(voucher)); | 4872 | // char *t = qurl_encode(voucher, strlen(voucher)); |
4752 | Rd->stuff->putstr(Rd->stuff, "voucher", t); | 4873 | // Rd->stuff->putstr(Rd->stuff, "voucher", t); |
4753 | free(t); | 4874 | Rd->stuff->putstr(Rd->stuff, "voucher", voucher); |
4875 | // free(t); | ||
4754 | } | 4876 | } |
4755 | 4877 | ||
4756 | return ret; | 4878 | return ret; |
@@ -4773,9 +4895,10 @@ static int aboutMeValidate(reqData *Rd, inputForm *oF, inputValue *oV) | |||
4773 | 4895 | ||
4774 | if ((0 == ret) && (NULL != about)) | 4896 | if ((0 == ret) && (NULL != about)) |
4775 | { | 4897 | { |
4776 | char *t = qurl_encode(about, strlen(about)); | 4898 | // char *t = qurl_encode(about, strlen(about)); |
4777 | Rd->stuff->putstr(Rd->stuff, "aboutMe", t); | 4899 | // Rd->stuff->putstr(Rd->stuff, "aboutMe", t); |
4778 | free(t); | 4900 | Rd->stuff->putstr(Rd->stuff, "aboutMe", about); |
4901 | // free(t); | ||
4779 | } | 4902 | } |
4780 | 4903 | ||
4781 | return ret; | 4904 | return ret; |
@@ -4880,15 +5003,13 @@ static void accountViewWeb(reqData *Rd, inputForm *oF, inputValue *oV) | |||
4880 | { | 5003 | { |
4881 | char *name = getStrH(Rd->database, "Lua.name"), | 5004 | char *name = getStrH(Rd->database, "Lua.name"), |
4882 | *level = getStrH(Rd->database, "UserAccounts.UserLevel"), | 5005 | *level = getStrH(Rd->database, "UserAccounts.UserLevel"), |
4883 | *email = displayPrep(getStrH(Rd->database, "UserAccounts.Email")), | 5006 | *email = getStrH(Rd->database, "UserAccounts.Email"), |
4884 | *voucher = displayPrep(getStrH(Rd->database, "Lua.voucher")), | 5007 | *voucher = getStrH(Rd->database, "Lua.voucher"), |
4885 | *about = displayPrep(getStrH(Rd->database, "Lua.aboutMe")); | 5008 | *about = getStrH(Rd->database, "Lua.aboutMe"); |
4886 | time_t crtd = atol(getStrH(Rd->database, "UserAccounts.Created")); | 5009 | time_t crtd = atol(getStrH(Rd->database, "UserAccounts.Created")); |
4887 | 5010 | ||
4888 | accountWebHeaders(Rd, oF); | 5011 | accountWebHeaders(Rd, oF); |
4889 | accountWebFields(Rd, oF, oV); | 5012 | accountWebFields(Rd, oF, oV); |
4890 | // TODO - still need to encode < > as < u> for email, voucher, and about. | ||
4891 | // TODO - dammit, qurl_decode returns the string length, and decodes the string in place. | ||
4892 | Rd->reply->addstrf(Rd->reply, "<p><font size='5'><span style='font-size: x-large'><b>Name :</b></span></font> %s</p>", name); | 5013 | Rd->reply->addstrf(Rd->reply, "<p><font size='5'><span style='font-size: x-large'><b>Name :</b></span></font> %s</p>", name); |
4893 | Rd->reply->addstrf(Rd->reply, "<p><font size='5'><span style='font-size: x-large'><b>Title / level :</b></span></font> %s / %s</p>", getLevel(atoi(level)), level); | 5014 | Rd->reply->addstrf(Rd->reply, "<p><font size='5'><span style='font-size: x-large'><b>Title / level :</b></span></font> %s / %s</p>", getLevel(atoi(level)), level); |
4894 | Rd->reply->addstrf(Rd->reply, "<p><font size='5'><span style='font-size: x-large'><b>Date of birth :</b></span></font> %s</p>", getStrH(Rd->database, "Lua.DoB")); | 5015 | Rd->reply->addstrf(Rd->reply, "<p><font size='5'><span style='font-size: x-large'><b>Date of birth :</b></span></font> %s</p>", getStrH(Rd->database, "Lua.DoB")); |
@@ -4909,9 +5030,9 @@ static void accountEditWeb(reqData *Rd, inputForm *oF, inputValue *oV) | |||
4909 | { | 5030 | { |
4910 | char *name = getStrH(Rd->database, "Lua.name"), | 5031 | char *name = getStrH(Rd->database, "Lua.name"), |
4911 | *level = getStrH(Rd->database, "UserAccounts.UserLevel"), | 5032 | *level = getStrH(Rd->database, "UserAccounts.UserLevel"), |
4912 | *email = displayPrep(getStrH(Rd->database, "UserAccounts.Email")), | 5033 | *email = getStrH(Rd->database, "UserAccounts.Email"), |
4913 | *voucher = displayPrep(getStrH(Rd->database, "Lua.voucher")), | 5034 | *voucher = getStrH(Rd->database, "Lua.voucher"), |
4914 | *about = displayPrep(getStrH(Rd->database, "Lua.aboutMe")), | 5035 | *about = getStrH(Rd->database, "Lua.aboutMe"), |
4915 | *lvl = getLevel(atoi(level)); | 5036 | *lvl = getLevel(atoi(level)); |
4916 | short lv = atoi(level); | 5037 | short lv = atoi(level); |
4917 | 5038 | ||
@@ -6748,12 +6869,12 @@ if ((strcmp("HTTP_COOKIE", ky) == 0) || (strcmp("CONTENT_LENGTH", ky) == 0) || ( | |||
6748 | 6869 | ||
6749 | t("COOKIES"); | 6870 | t("COOKIES"); |
6750 | Rd->cookies = toknize(Rd->headers->getstr(Rd->headers, "HTTP_COOKIE", false), "=;"); | 6871 | Rd->cookies = toknize(Rd->headers->getstr(Rd->headers, "HTTP_COOKIE", false), "=;"); |
6751 | santize(Rd->cookies, TRUE); | 6872 | santize(Rd->cookies); |
6752 | if (strcmp("GET", Rd->Method) == 0) | 6873 | if (strcmp("GET", Rd->Method) == 0) |
6753 | { // In theory a POST has body fields INSTEAD of query fields. Especially for ignoring the linky-hashish after the validation page. | 6874 | { // In theory a POST has body fields INSTEAD of query fields. Especially for ignoring the linky-hashish after the validation page. |
6754 | t("QUERY"); | 6875 | t("QUERY"); |
6755 | Rd->queries = toknize(Rd->headers->getstr(Rd->headers, "QUERY_STRING", false), "=&"); | 6876 | Rd->queries = toknize(Rd->headers->getstr(Rd->headers, "QUERY_STRING", false), "=&"); |
6756 | santize(Rd->queries, TRUE); | 6877 | santize(Rd->queries); |
6757 | } | 6878 | } |
6758 | else | 6879 | else |
6759 | { | 6880 | { |
@@ -6779,7 +6900,7 @@ t("BODY"); | |||
6779 | Length = "0"; | 6900 | Length = "0"; |
6780 | Rd->body = toknize(Body, "=&"); | 6901 | Rd->body = toknize(Body, "=&"); |
6781 | free(Body); | 6902 | free(Body); |
6782 | santize(Rd->body, TRUE); | 6903 | santize(Rd->body); |
6783 | 6904 | ||
6784 | I("%s %s://%s%s -> %s%s", Rd->Method, Rd->Scheme, Rd->Host, Rd->RUri, webRoot, Path); | 6905 | I("%s %s://%s%s -> %s%s", Rd->Method, Rd->Scheme, Rd->Host, Rd->RUri, webRoot, Path); |
6785 | D("Started FCGI web request ROLE = %s, body is %s bytes, pid %d.", Role, Length, getpid()); | 6906 | D("Started FCGI web request ROLE = %s, body is %s bytes, pid %d.", Role, Length, getpid()); |
@@ -7072,10 +7193,12 @@ fcgiDone: | |||
7072 | 7193 | ||
7073 | if (!checkSimIsRunning(sim)) | 7194 | if (!checkSimIsRunning(sim)) |
7074 | { | 7195 | { |
7196 | char *nm = cleanSimName(name); | ||
7197 | |||
7075 | I("%s is starting up.", name); | 7198 | I("%s is starting up.", name); |
7076 | memset(toybuf, 0, sizeof(toybuf)); | 7199 | memset(toybuf, 0, sizeof(toybuf)); |
7077 | snprintf(toybuf, sizeof(toybuf), "%s %s/%s new-window -dn '%s' -t '%s:%d' 'cd %s/current/bin; mono OpenSim.exe -inidirectory=%s/config/%s'", | 7200 | snprintf(toybuf, sizeof(toybuf), "%s %s/%s new-window -dn '%s' -t '%s:%d' 'cd %s/current/bin; mono OpenSim.exe -inidirectory=%s/config/%s'", |
7078 | Tcmd, scRun, Tsocket, name, Tconsole, i + 1, scRoot, scRoot, sim); | 7201 | Tcmd, scRun, Tsocket, nm, Tconsole, i + 1, scRoot, scRoot, sim); |
7079 | int r = system(toybuf); | 7202 | int r = system(toybuf); |
7080 | if (!WIFEXITED(r)) | 7203 | if (!WIFEXITED(r)) |
7081 | E("tmux new-window command failed!"); | 7204 | E("tmux new-window command failed!"); |
@@ -7083,7 +7206,7 @@ fcgiDone: | |||
7083 | { | 7206 | { |
7084 | memset(toybuf, 0, sizeof(toybuf)); | 7207 | memset(toybuf, 0, sizeof(toybuf)); |
7085 | snprintf(toybuf, sizeof(toybuf), "INITIALIZATION COMPLETE FOR %s", name); | 7208 | snprintf(toybuf, sizeof(toybuf), "INITIALIZATION COMPLETE FOR %s", name); |
7086 | waitTmuxText(name, toybuf); | 7209 | waitTmuxText(nm, toybuf); |
7087 | I("%s is done starting up.", name); | 7210 | I("%s is done starting up.", name); |
7088 | la = waitLoadAverage(la, loadAverageInc, simTimeOut); | 7211 | la = waitLoadAverage(la, loadAverageInc, simTimeOut); |
7089 | } | 7212 | } |