aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--src/sledjchisl/sledjchisl.c409
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
492char *logTypes[] = 494char *logTypes[] =
493{ 495{
@@ -633,7 +635,9 @@ int sendTmuxCmd(char *dest, char *cmd)
633void waitTmuxText(char *dest, char *text) 635void 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 \ " `
712char *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
707simList *getSims() 730simList *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
2247void santize(qhashtbl_t *tbl, bool decode) 2270void 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/*
2280char *unsantize(char *str)
2281{
2282 char *ret = qurl_decode(xstrdup(str));
2283 return ret;
2284}
2285*/
2286
2287void outize(qgrow_t *reply, qhashtbl_t *tbl, char *label) 2286void 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
2299char *displayPrep(char *str)
2300{
2301 char *ret = xstrdup(str), *t;
2302
2303 qurl_decode(ret);
2304 t = qstrreplace("tn", ret, "<", "&lt;");
2305 free(ret);
2306 ret = NULL;
2307 if (NULL != t)
2308 {
2309 ret = qstrreplace("tn", t, ">", "&gt;");
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
2322char *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
2337enum cookieSame 2299enum 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?
2442char *HTMLentities[] =
2443{
2444 "", "", "", "", "", "", "", "", "", // NUL SOH STX ETX EOT ENQ ACK BEL BS
2445 "&Tab;", "&NewLine;",
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 "&excl;", "&quot;",
2449 "&num;", "&dollar;",
2450 "&percnt;", "&amp;",
2451 "&apos;",
2452 "&lpar;", "&rpar;",
2453 "&ast;",
2454 "&plus;",
2455 "&comma;",
2456 "-",
2457 "&period;",
2458 "&sol;",
2459 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
2460 "&colon;", "&semi;",
2461 "&lt;", "&equals;", "&gt;",
2462 "&quest;",
2463 "&commat;",
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 "&lsqb;", "&bsol;", "&rsqb;",
2466 "&Hat;",
2467 "&lowbar;",
2468 "&grave;",
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 "&lcub;", "&verbar;", "&rcub;",
2471 "~",
2472 "", // DEL
2473 "&nbsp;" // This is actually 160, not 128, but I hack around that.
2474};
2475static 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 &nbsp;.
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
2479static void HTMLtable(qgrow_t *reply, MYSQL *db, MYSQL_RES *result, char *caption, char *URL, char *id) 2524static 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
2543static void HTMLhidden(qgrow_t *reply, char *name, char *val) 2588static 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
2549static void HTMLform(qgrow_t *reply, char *action, char *token) 2598static 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
3687boolean 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
3703boolean 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
3719boolean 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
3626static void accountWrite(reqData *Rd) 3764static 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 }
3827notWritten:
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}
4555static void emailWeb(reqData *Rd, inputForm *oF, inputValue *oV) 4676static 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. &nbsp; " 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. &nbsp; "
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 &lt; u&gt; 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
6749t("COOKIES"); 6870t("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.
6754t("QUERY"); 6875t("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 }