diff options
author | onefang | 2020-03-18 23:44:23 +1000 |
---|---|---|
committer | onefang | 2020-03-18 23:44:23 +1000 |
commit | 0dd0082560332995ba8e6ed86b3fd6b92ba783e8 (patch) | |
tree | 4b417ed9c5a5d5916cf29ba3e2734e8a0b4cda20 /src/sledjchisl/sledjchisl.c | |
parent | Include all stuff in a session file. (diff) | |
download | opensim-SC_OLD-0dd0082560332995ba8e6ed86b3fd6b92ba783e8.zip opensim-SC_OLD-0dd0082560332995ba8e6ed86b3fd6b92ba783e8.tar.gz opensim-SC_OLD-0dd0082560332995ba8e6ed86b3fd6b92ba783e8.tar.bz2 opensim-SC_OLD-0dd0082560332995ba8e6ed86b3fd6b92ba783e8.tar.xz |
Major rewrite of the validation code.
Other things might have snuck into this mess.
Make sure errors cause pages to reload with the data that was entered,
so they can easily correct it.
Diffstat (limited to 'src/sledjchisl/sledjchisl.c')
-rw-r--r-- | src/sledjchisl/sledjchisl.c | 576 |
1 files changed, 304 insertions, 272 deletions
diff --git a/src/sledjchisl/sledjchisl.c b/src/sledjchisl/sledjchisl.c index 06c6187..8bcf076 100644 --- a/src/sledjchisl/sledjchisl.c +++ b/src/sledjchisl/sledjchisl.c | |||
@@ -305,18 +305,18 @@ qhashtbl_t *HTMLfileCache = NULL; | |||
305 | typedef struct _reqData reqData; | 305 | typedef struct _reqData reqData; |
306 | 306 | ||
307 | 307 | ||
308 | typedef int (*fieldValidFunc) (reqData *Rd, qhashtbl_t *data); | 308 | typedef int (*fieldValidFunc) (reqData *Rd, qhashtbl_t *data, char *name); |
309 | typedef struct _validFunc validFunc; | 309 | typedef struct _validFunc validFunc; |
310 | struct _validFunc | 310 | struct _validFunc |
311 | { | 311 | { |
312 | char *name; | 312 | char *name, *title; |
313 | fieldValidFunc func; | 313 | fieldValidFunc func; |
314 | }; | 314 | }; |
315 | qlisttbl_t *fieldValidFuncs = NULL; | 315 | qlisttbl_t *fieldValidFuncs = NULL; |
316 | static void newValidFunc(char *name, fieldValidFunc func) | 316 | static void newValidFunc(char *name, char *title, fieldValidFunc func) |
317 | { | 317 | { |
318 | validFunc *vf = xmalloc(sizeof(validFunc)); | 318 | validFunc *vf = xmalloc(sizeof(validFunc)); |
319 | vf->name = name; vf->func = func; | 319 | vf->name = name; vf->title = title; vf->func = func; |
320 | fieldValidFuncs->put(fieldValidFuncs, vf->name, vf, sizeof(validFunc)); | 320 | fieldValidFuncs->put(fieldValidFuncs, vf->name, vf, sizeof(validFunc)); |
321 | } | 321 | } |
322 | 322 | ||
@@ -402,7 +402,7 @@ struct _sesh | |||
402 | struct _reqData | 402 | struct _reqData |
403 | { | 403 | { |
404 | lua_State *L; | 404 | lua_State *L; |
405 | qhashtbl_t *configs, *queries, *body, *cookies, *headers, *stuff, *database, *Rcookies, *Rheaders; | 405 | qhashtbl_t *configs, *queries, *body, *cookies, *headers, *valid, *stuff, *database, *Rcookies, *Rheaders; |
406 | char *Scheme, *Host, *Method, *Script, *RUri, *doit; | 406 | char *Scheme, *Host, *Method, *Script, *RUri, *doit; |
407 | sesh shs, *lnk; | 407 | sesh shs, *lnk; |
408 | MYSQL *db; | 408 | MYSQL *db; |
@@ -2727,6 +2727,96 @@ NOTE - storing a pepper on the same RAID array as everything else will be a prob | |||
2727 | https://stackoverflow.com/questions/16891729/best-practices-salting-peppering-passwords | 2727 | https://stackoverflow.com/questions/16891729/best-practices-salting-peppering-passwords |
2728 | */ | 2728 | */ |
2729 | 2729 | ||
2730 | |||
2731 | static void bitch(reqData *Rd, char *message, char *log) | ||
2732 | { | ||
2733 | addStrL(Rd->errors, message); | ||
2734 | E("%s %s %s %s %s", getStrH(Rd->headers, "REMOTE_ADDR"), getStrH(Rd->stuff, "UUID"), getStrH(Rd->stuff, "name"), message, log); | ||
2735 | } | ||
2736 | |||
2737 | /* "A token cookie that references a non-existent session, its value should be replaced immediately to prevent session fixation." | ||
2738 | https://owasp.org/www-community/attacks/Session_fixation | ||
2739 | Which describes the problem, but offers no solution. | ||
2740 | See https://stackoverflow.com/questions/549/the-definitive-guide-to-form-based-website-authentication?rq=1. | ||
2741 | I think this means send a new cookie. | ||
2742 | I clear out the cookies and send blank ones with -1 maxAge, so they should get deleted. | ||
2743 | */ | ||
2744 | static void bitchSession(reqData *Rd, char *message, char *log) | ||
2745 | { | ||
2746 | addStrL(Rd->errors, message); | ||
2747 | C("%s %s %s %s %s", getStrH(Rd->headers, "REMOTE_ADDR"), getStrH(Rd->stuff, "UUID"), getStrH(Rd->stuff, "name"), message, log); | ||
2748 | Rd->vegOut = TRUE; | ||
2749 | } | ||
2750 | |||
2751 | |||
2752 | int LuaToHash(reqData *Rd, char *file, char *var, qhashtbl_t *tnm, int ret, struct stat *st, struct timespec *now, char *type) | ||
2753 | { | ||
2754 | struct timespec then; | ||
2755 | |||
2756 | if (-1 == clock_gettime(CLOCK_REALTIME, &then)) | ||
2757 | perror_msg("Unable to get the time."); | ||
2758 | I("Reading %s file %s", type, file); | ||
2759 | if (0 != stat(file, st)) | ||
2760 | { | ||
2761 | D("No %s file.", file); | ||
2762 | perror_msg("Unable to stat %s", file); | ||
2763 | ret++; | ||
2764 | } | ||
2765 | else | ||
2766 | { | ||
2767 | int status = luaL_loadfile(Rd->L, file), result; | ||
2768 | |||
2769 | if (status) | ||
2770 | { | ||
2771 | bitchSession(Rd, "No such thing.", "Can't load file."); | ||
2772 | E("Couldn't load file: %s", lua_tostring(Rd->L, -1)); | ||
2773 | ret++; | ||
2774 | } | ||
2775 | else | ||
2776 | { | ||
2777 | result = lua_pcall(Rd->L, 0, LUA_MULTRET, 0); | ||
2778 | |||
2779 | if (result) | ||
2780 | { | ||
2781 | bitchSession(Rd, "Broken thing.", "Can't run file."); | ||
2782 | E("Failed to run script: %s", lua_tostring(Rd->L, -1)); | ||
2783 | ret++; | ||
2784 | } | ||
2785 | else | ||
2786 | { | ||
2787 | lua_getglobal(Rd->L, var); | ||
2788 | lua_pushnil(Rd->L); | ||
2789 | |||
2790 | while(lua_next(Rd->L, -2) != 0) | ||
2791 | { | ||
2792 | char *n = (char *) lua_tostring(Rd->L, -2); | ||
2793 | |||
2794 | if (lua_isstring(Rd->L, -1)) | ||
2795 | { | ||
2796 | tnm->putstr(tnm, n, (char *) lua_tostring(Rd->L, -1)); | ||
2797 | //d("Reading %s = %s", n, getStrH(tnm, n)); | ||
2798 | } | ||
2799 | else | ||
2800 | { | ||
2801 | char *v = (char *) lua_tostring(Rd->L, -1); | ||
2802 | W("Unknown Lua variable type for %s = %s", n, v); | ||
2803 | } | ||
2804 | lua_pop(Rd->L, 1); | ||
2805 | } | ||
2806 | |||
2807 | if (-1 == clock_gettime(CLOCK_REALTIME, now)) | ||
2808 | perror_msg("Unable to get the time."); | ||
2809 | double n = (now->tv_sec * 1000000000.0) + now->tv_nsec; | ||
2810 | double t = (then.tv_sec * 1000000000.0) + then.tv_nsec; | ||
2811 | T("Reading %s file took %lf seconds", type, (n - t) / 1000000000.0); | ||
2812 | } | ||
2813 | } | ||
2814 | } | ||
2815 | |||
2816 | return ret; | ||
2817 | } | ||
2818 | |||
2819 | |||
2730 | static void freeSesh(reqData *Rd, boolean linky, boolean wipe) | 2820 | static void freeSesh(reqData *Rd, boolean linky, boolean wipe) |
2731 | { | 2821 | { |
2732 | char *file = NULL; | 2822 | char *file = NULL; |
@@ -2933,26 +3023,6 @@ static void createUser(reqData *Rd) | |||
2933 | free(file); | 3023 | free(file); |
2934 | } | 3024 | } |
2935 | 3025 | ||
2936 | |||
2937 | static void bitch(reqData *Rd, char *message, char *log) | ||
2938 | { | ||
2939 | addStrL(Rd->errors, message); | ||
2940 | E("%s %s %s %s %s", getStrH(Rd->headers, "REMOTE_ADDR"), getStrH(Rd->stuff, "UUID"), getStrH(Rd->stuff, "name"), message, log); | ||
2941 | } | ||
2942 | |||
2943 | /* "A token cookie that references a non-existent session, its value should be replaced immediately to prevent session fixation." | ||
2944 | https://owasp.org/www-community/attacks/Session_fixation | ||
2945 | Which describes the problem, but offers no solution. | ||
2946 | See https://stackoverflow.com/questions/549/the-definitive-guide-to-form-based-website-authentication?rq=1. | ||
2947 | I think this means send a new cookie. | ||
2948 | I clear out the cookies and send blank ones with -1 maxAge, so they should get deleted. | ||
2949 | */ | ||
2950 | static void bitchSession(reqData *Rd, char *message, char *log) | ||
2951 | { | ||
2952 | addStrL(Rd->errors, message); | ||
2953 | C("%s %s %s %s %s", getStrH(Rd->headers, "REMOTE_ADDR"), getStrH(Rd->stuff, "UUID"), getStrH(Rd->stuff, "name"), message, log); | ||
2954 | Rd->vegOut = TRUE; | ||
2955 | } | ||
2956 | static sesh *newSesh(reqData *Rd, boolean linky) | 3026 | static sesh *newSesh(reqData *Rd, boolean linky) |
2957 | { | 3027 | { |
2958 | unsigned char *md5hash = xzalloc(17); | 3028 | unsigned char *md5hash = xzalloc(17); |
@@ -2961,7 +3031,7 @@ static sesh *newSesh(reqData *Rd, boolean linky) | |||
2961 | uuid_t binuuid; | 3031 | uuid_t binuuid; |
2962 | sesh *ret = &Rd->shs; | 3032 | sesh *ret = &Rd->shs; |
2963 | 3033 | ||
2964 | W("New sesh"); | 3034 | d("New sesh"); |
2965 | if (linky) | 3035 | if (linky) |
2966 | { | 3036 | { |
2967 | Rd->lnk = xzalloc(sizeof(sesh)); | 3037 | Rd->lnk = xzalloc(sizeof(sesh)); |
@@ -3044,132 +3114,72 @@ char *checkLinky(reqData *Rd) | |||
3044 | } | 3114 | } |
3045 | 3115 | ||
3046 | 3116 | ||
3047 | boolean prevalidate(qhashtbl_t *data, char *name) | ||
3048 | { | ||
3049 | if ('\0' != getStrH(data, name)[0]) | ||
3050 | { | ||
3051 | I("Already validated %s.", name); | ||
3052 | return TRUE; | ||
3053 | } | ||
3054 | return FALSE; | ||
3055 | } | ||
3056 | |||
3057 | boolean badBoy(int ret, reqData *Rd, qhashtbl_t *data, char *name, char *value) | 3117 | boolean badBoy(int ret, reqData *Rd, qhashtbl_t *data, char *name, char *value) |
3058 | { | 3118 | { |
3059 | if (NULL == value) | 3119 | if (NULL == value) |
3060 | value = getStrH(data, name); | 3120 | value = getStrH(data, name); |
3061 | |||
3062 | if (0 != ret) | 3121 | if (0 != ret) |
3063 | { | 3122 | { |
3064 | char *t = xmprintf("BAD - %s", name); | 3123 | Rd->valid->putint(Rd->valid, name, -1); |
3065 | 3124 | W("Bad boy %s = %s", name, value); | |
3066 | Rd->stuff->putstr(Rd->stuff, t, value); | ||
3067 | Rd->stuff->remove(data, name); | ||
3068 | free(t); | ||
3069 | return TRUE; | 3125 | return TRUE; |
3070 | } | 3126 | } |
3071 | data->putstr(data, name, value); | 3127 | Rd->stuff->putstr(Rd->stuff, name, value); |
3128 | Rd->valid->putint(Rd->valid, name, 1); | ||
3072 | return FALSE; | 3129 | return FALSE; |
3073 | } | 3130 | } |
3074 | 3131 | ||
3075 | char *months[] = | 3132 | int validateThings(reqData *Rd, char *doit, char *name, qhashtbl_t *things) |
3076 | { | ||
3077 | "january", | ||
3078 | "february", | ||
3079 | "march", | ||
3080 | "april", | ||
3081 | "may", | ||
3082 | "june", | ||
3083 | "july", | ||
3084 | "august", | ||
3085 | "september", | ||
3086 | "october", | ||
3087 | "november", | ||
3088 | "december" | ||
3089 | }; | ||
3090 | |||
3091 | |||
3092 | |||
3093 | int LuaToHash(reqData *Rd, char *file, char *var, qhashtbl_t *tnm, int ret, struct stat *st, struct timespec *now, char *type) | ||
3094 | { | 3133 | { |
3095 | struct timespec then; | 3134 | int e = 0; |
3135 | qlisttbl_obj_t obj; | ||
3096 | 3136 | ||
3097 | if (-1 == clock_gettime(CLOCK_REALTIME, &then)) | 3137 | D("For function %s, start of %s validation.", doit, name); |
3098 | perror_msg("Unable to get the time."); | 3138 | memset((void *) &obj, 0, sizeof(obj)); |
3099 | I("Reading %s file %s", type, file); | 3139 | fieldValidFuncs->lock(fieldValidFuncs); |
3100 | if (0 != stat(file, st)) | 3140 | while(fieldValidFuncs->getnext(fieldValidFuncs, &obj, NULL, false) == true) |
3101 | { | ||
3102 | bitchSession(Rd, "No such thing.", "No file."); | ||
3103 | perror_msg("Unable to stat %s", file); | ||
3104 | ret++; | ||
3105 | } | ||
3106 | else | ||
3107 | { | 3141 | { |
3108 | int status = luaL_loadfile(Rd->L, file), result; | 3142 | char *t = things->getstr(things, obj.name, false); |
3109 | 3143 | ||
3110 | if (status) | 3144 | if (NULL != t) |
3111 | { | ||
3112 | bitchSession(Rd, "No such thing.", "Can't load file."); | ||
3113 | E("Couldn't load file: %s", lua_tostring(Rd->L, -1)); | ||
3114 | ret++; | ||
3115 | } | ||
3116 | else | ||
3117 | { | 3145 | { |
3118 | result = lua_pcall(Rd->L, 0, LUA_MULTRET, 0); | 3146 | char *nm = obj.name; |
3147 | int valid = Rd->valid->getint(Rd->valid, nm); | ||
3148 | validFunc *vf = (validFunc *) obj.data; | ||
3119 | 3149 | ||
3120 | if (result) | 3150 | if (0 != valid) // Is it in the valid qhashtbl? |
3121 | { | 3151 | { |
3122 | bitchSession(Rd, "Broken thing.", "Can't run file."); | 3152 | if (0 < valid) // Positive valid means it's valid, negative means it's invald. |
3123 | E("Failed to run script: %s", lua_tostring(Rd->L, -1)); | 3153 | D("Already validated %s - %s.", vf->title, nm); |
3124 | ret++; | 3154 | else |
3155 | D("Already invalidated %s - %s.", vf->title, nm); | ||
3125 | } | 3156 | } |
3126 | else | 3157 | else |
3127 | { | 3158 | { |
3128 | lua_getglobal(Rd->L, var); | 3159 | D("Validating %s - %s.", vf->title, nm); |
3129 | lua_pushnil(Rd->L); | 3160 | if (vf->func) |
3130 | 3161 | e += vf->func(Rd, things, nm); | |
3131 | while(lua_next(Rd->L, -2) != 0) | 3162 | else |
3132 | { | 3163 | E("No validation function for %s - %s", vf->title, nm); |
3133 | char *n = (char *) lua_tostring(Rd->L, -2); | ||
3134 | |||
3135 | if (lua_isstring(Rd->L, -1)) | ||
3136 | { | ||
3137 | tnm->putstr(tnm, n, (char *) lua_tostring(Rd->L, -1)); | ||
3138 | //d("Reading %s %s", n, getStrH(tnm, n)); | ||
3139 | } | ||
3140 | else | ||
3141 | { | ||
3142 | char *v = (char *) lua_tostring(Rd->L, -1); | ||
3143 | W("Unknown Lua variable type for %s = %s", n, v); | ||
3144 | } | ||
3145 | lua_pop(Rd->L, 1); | ||
3146 | } | ||
3147 | |||
3148 | if (-1 == clock_gettime(CLOCK_REALTIME, now)) | ||
3149 | perror_msg("Unable to get the time."); | ||
3150 | double n = (now->tv_sec * 1000000000.0) + now->tv_nsec; | ||
3151 | double t = (then.tv_sec * 1000000000.0) + then.tv_nsec; | ||
3152 | T("Reading %s file took %lf seconds", type, (n - t) / 1000000000.0); | ||
3153 | } | 3164 | } |
3154 | } | 3165 | } |
3155 | } | 3166 | } |
3156 | 3167 | fieldValidFuncs->unlock(fieldValidFuncs); | |
3157 | return ret; | 3168 | return e; |
3158 | } | 3169 | } |
3159 | 3170 | ||
3160 | static int validateSesh(reqData *Rd, qhashtbl_t *data) | 3171 | |
3172 | static int validateSesh(reqData *Rd, qhashtbl_t *data, char *name) | ||
3161 | { | 3173 | { |
3162 | int ret = 0; | 3174 | int ret = 0; |
3163 | boolean linky = FALSE; | 3175 | boolean linky = FALSE; |
3164 | 3176 | ||
3165 | if ('\0' != Rd->shs.leaf[0]) | 3177 | if ('\0' != Rd->shs.leaf[0]) |
3166 | { | 3178 | { |
3167 | I("Already validated session."); | 3179 | d("Already validated session."); |
3168 | return ret; | 3180 | return ret; |
3169 | } | 3181 | } |
3170 | 3182 | ||
3171 | I("Validating session."); | ||
3172 | |||
3173 | char *toke_n_munchie = "", *munchie = "", *hashish = "", | 3183 | char *toke_n_munchie = "", *munchie = "", *hashish = "", |
3174 | *leaf, *timeStamp = "", *seshion = "", *seshID = "", | 3184 | *leaf, *timeStamp = "", *seshion = "", *seshID = "", |
3175 | *t0, *t1; | 3185 | *t0, *t1; |
@@ -3324,15 +3334,25 @@ W("Validated session linky."); | |||
3324 | Rd->stuff->putstr(Rd->stuff, "linky-hashish", t0); | 3334 | Rd->stuff->putstr(Rd->stuff, "linky-hashish", t0); |
3325 | } | 3335 | } |
3326 | } | 3336 | } |
3327 | Rd->stuff->putstr(Rd->stuff, "name", tnm->getstr(tnm, "name", true)); | 3337 | |
3328 | Rd->stuff->putstr(Rd->stuff, "UUID", tnm->getstr(tnm, "UUID", true)); | 3338 | qhashtbl_obj_t obj; |
3329 | Rd->stuff->putstr(Rd->stuff, "level", tnm->getstr(tnm, "level", true)); | 3339 | |
3330 | Rd->stuff->putstr(Rd->stuff, "passwordSalt", tnm->getstr(tnm, "passwordSalt", true)); | 3340 | memset((void*)&obj, 0, sizeof(obj)); |
3331 | Rd->stuff->putstr(Rd->stuff, "passwordHash", tnm->getstr(tnm, "passwordHash", true)); | 3341 | tnm->lock(tnm); |
3342 | while(tnm->getnext(tnm, &obj, false) == true) | ||
3343 | { | ||
3344 | char *n = obj.name; | ||
3345 | |||
3346 | if ((strcmp("salt", n) != 0) && (strcmp("seshID", n) != 0)) | ||
3347 | { | ||
3348 | t("Lua %s = %s", n, (char *) obj.data); | ||
3349 | Rd->stuff->putstr(Rd->stuff, obj.name, (char *) obj.data); | ||
3350 | } | ||
3351 | } | ||
3352 | tnm->unlock(tnm); | ||
3332 | Rd->database->putstr(Rd->database, "UserAccounts.PrincipalID", tnm->getstr(tnm, "UUID", true)); | 3353 | Rd->database->putstr(Rd->database, "UserAccounts.PrincipalID", tnm->getstr(tnm, "UUID", true)); |
3333 | } | 3354 | } |
3334 | } | 3355 | } |
3335 | |||
3336 | } | 3356 | } |
3337 | } | 3357 | } |
3338 | } | 3358 | } |
@@ -3342,15 +3362,48 @@ W("Validated session linky."); | |||
3342 | return ret; | 3362 | return ret; |
3343 | } | 3363 | } |
3344 | 3364 | ||
3345 | static int validateDoB(reqData *Rd, qhashtbl_t *data) | 3365 | static int validateAboutMe(reqData *Rd, qhashtbl_t *data, char *name) |
3366 | { | ||
3367 | int ret = 0; | ||
3368 | char *about = getStrH(data, "aboutMe"); | ||
3369 | |||
3370 | if ((strcmp("confirm", Rd->doit) != 0) && (strcmp("update", Rd->doit) != 0)) | ||
3371 | return ret; | ||
3372 | |||
3373 | if ('\0' == about[0]) | ||
3374 | { | ||
3375 | bitch(Rd, "Please fill in the 'About me' section.", "None supplied."); | ||
3376 | ret++; | ||
3377 | } | ||
3378 | |||
3379 | badBoy(ret, Rd, data, "aboutMe", about); | ||
3380 | return ret; | ||
3381 | } | ||
3382 | |||
3383 | |||
3384 | char *months[] = | ||
3385 | { | ||
3386 | "january", | ||
3387 | "february", | ||
3388 | "march", | ||
3389 | "april", | ||
3390 | "may", | ||
3391 | "june", | ||
3392 | "july", | ||
3393 | "august", | ||
3394 | "september", | ||
3395 | "october", | ||
3396 | "november", | ||
3397 | "december" | ||
3398 | }; | ||
3399 | static int validateDoB(reqData *Rd, qhashtbl_t *data, char *name) | ||
3346 | { | 3400 | { |
3347 | int ret = 0, i; | 3401 | int ret = 0, i; |
3348 | char *t; | 3402 | char *t; |
3349 | 3403 | ||
3350 | if (prevalidate(Rd->stuff, "year")) return ret; | 3404 | if ((strcmp("confirm", Rd->doit) != 0) && (strcmp("update", Rd->doit) != 0)) |
3351 | if (prevalidate(Rd->stuff, "month")) return ret; | 3405 | return ret; |
3352 | 3406 | ||
3353 | I("Validating DoB."); | ||
3354 | t = getStrH(data, "year"); | 3407 | t = getStrH(data, "year"); |
3355 | if ((NULL == t) || ('\0' == t[0])) | 3408 | if ((NULL == t) || ('\0' == t[0])) |
3356 | { | 3409 | { |
@@ -3392,19 +3445,15 @@ static int validateDoB(reqData *Rd, qhashtbl_t *data) | |||
3392 | return ret; | 3445 | return ret; |
3393 | } | 3446 | } |
3394 | 3447 | ||
3395 | static int validateEmail(reqData *Rd, qhashtbl_t *data) | 3448 | static int validateEmail(reqData *Rd, qhashtbl_t *data, char *name) |
3396 | { | 3449 | { |
3397 | int ret = 0; | 3450 | int ret = 0; |
3398 | char *email = getStrH(data, "email"); | 3451 | char *email = getStrH(data, "email"); |
3399 | char *emayl = getStrH(data, "emayl"); | 3452 | char *emayl = getStrH(data, "emayl"); |
3400 | 3453 | ||
3401 | if ((strcmp("create", Rd->doit) != 0) && (strcmp("update", Rd->doit) != 0)) | 3454 | if ((strcmp("confirm", Rd->doit) != 0) && (strcmp("update", Rd->doit) != 0)) |
3402 | return ret; | 3455 | return ret; |
3403 | 3456 | ||
3404 | if (prevalidate(Rd->stuff, "email")) return ret; | ||
3405 | if (prevalidate(Rd->stuff, "emayl")) return ret; | ||
3406 | |||
3407 | I("Validating email."); | ||
3408 | if ((NULL == email) || (NULL == emayl) || ('\0' == email[0]) || ('\0' == emayl[0])) | 3457 | if ((NULL == email) || (NULL == emayl) || ('\0' == email[0]) || ('\0' == emayl[0])) |
3409 | { | 3458 | { |
3410 | bitch(Rd, "Please supply an email address.", "None supplied."); | 3459 | bitch(Rd, "Please supply an email address.", "None supplied."); |
@@ -3425,25 +3474,20 @@ static int validateEmail(reqData *Rd, qhashtbl_t *data) | |||
3425 | // TODO - do other email checks - does the domain exist, .. | 3474 | // TODO - do other email checks - does the domain exist, .. |
3426 | } | 3475 | } |
3427 | 3476 | ||
3428 | badBoy(ret, Rd, data, "email", email); | 3477 | badBoy(ret, Rd, data, "email", NULL); |
3429 | badBoy(ret, Rd, data, "emayl", emayl); | 3478 | badBoy(ret, Rd, data, "emayl", NULL); |
3430 | return ret; | 3479 | return ret; |
3431 | } | 3480 | } |
3432 | 3481 | ||
3433 | static int validateLegal(reqData *Rd, qhashtbl_t *data) | 3482 | static int validateLegal(reqData *Rd, qhashtbl_t *data, char *name) |
3434 | { | 3483 | { |
3435 | int ret = 0; | 3484 | int ret = 0; |
3436 | char *t; | 3485 | char *t; |
3437 | 3486 | ||
3438 | if (prevalidate(Rd->stuff, "adult")) return ret; | ||
3439 | if (prevalidate(Rd->stuff, "agree")) return ret; | ||
3440 | |||
3441 | |||
3442 | I("Validating legal."); | ||
3443 | t = getStrH(data, "adult"); | 3487 | t = getStrH(data, "adult"); |
3444 | if ((NULL == t) || (strcmp("on", t) != 0)) | 3488 | if ((NULL == t) || (strcmp("on", t) != 0)) |
3445 | { | 3489 | { |
3446 | bitch(Rd, "You must be an adult to enter this world.", ""); | 3490 | bitch(Rd, "You must be an adult to enter this site.", ""); |
3447 | ret++; | 3491 | ret++; |
3448 | } | 3492 | } |
3449 | t = getStrH(data, "agree"); | 3493 | t = getStrH(data, "agree"); |
@@ -3458,19 +3502,16 @@ static int validateLegal(reqData *Rd, qhashtbl_t *data) | |||
3458 | return ret; | 3502 | return ret; |
3459 | } | 3503 | } |
3460 | 3504 | ||
3461 | static int validateName(reqData *Rd, qhashtbl_t *data) | 3505 | static int validateName(reqData *Rd, qhashtbl_t *data, char *nm) |
3462 | { | 3506 | { |
3463 | boolean login = strcmp("login", Rd->doit) == 0; | 3507 | boolean login = strcmp("login", Rd->doit) == 0; |
3464 | int ret = 0; | 3508 | int ret = 0; |
3465 | unsigned char *name = data->getstr(data, "name", true); // We have to be unsigned coz of isalnum(). | 3509 | unsigned char *name = data->getstr(data, "name", true); // We have to be unsigned coz of isalnum(). |
3466 | char *where = NULL; | 3510 | char *where = NULL; |
3467 | 3511 | ||
3468 | if (strcmp("logout", Rd->doit) == 0) | 3512 | if ((strcmp("cancel", Rd->doit) == 0) || (strcmp("logout", Rd->doit) == 0)) |
3469 | return ret; | 3513 | return ret; |
3470 | 3514 | ||
3471 | if (prevalidate(Rd->database, "UserAccounts.UserLevel")) return ret; | ||
3472 | |||
3473 | I("Validating name."); | ||
3474 | if ((NULL == name) || ('\0' == name[0])) | 3515 | if ((NULL == name) || ('\0' == name[0])) |
3475 | { | 3516 | { |
3476 | bitch(Rd, "Please supply an account name.", "None supplied."); | 3517 | bitch(Rd, "Please supply an account name.", "None supplied."); |
@@ -3557,102 +3598,105 @@ static int validateName(reqData *Rd, qhashtbl_t *data) | |||
3557 | } | 3598 | } |
3558 | dbDoSomething(acnts, FALSE, name, s); | 3599 | dbDoSomething(acnts, FALSE, name, s); |
3559 | rowData *rows = acnts->rows; | 3600 | rowData *rows = acnts->rows; |
3601 | int c = 0; | ||
3602 | |||
3560 | if (rows) | 3603 | if (rows) |
3561 | { | 3604 | c = rows->rows->size(rows->rows); |
3562 | int i = rows->rows->size(rows->rows); | ||
3563 | 3605 | ||
3564 | if (login) | 3606 | if (login) |
3607 | { | ||
3608 | if ((1 != c) && (rt)) | ||
3565 | { | 3609 | { |
3566 | if (rt) | 3610 | if (rt) |
3567 | { | 3611 | { |
3568 | bitch(Rd, "Login failed.", "Could not read user Lua file."); | 3612 | W("Could not read user Lua file."); |
3569 | ret += rt; | 3613 | ret += rt; |
3570 | if (i == 0) | 3614 | } |
3571 | { | 3615 | if (0 == c) |
3572 | bitch(Rd, "Login failed.", "No UserAccounts record with that name."); | 3616 | { |
3573 | ret++; | 3617 | W("No UserAccounts record with that name."); |
3574 | } | 3618 | ret++; |
3575 | else | ||
3576 | { | ||
3577 | if (i != 1) | ||
3578 | { | ||
3579 | bitch(Rd, "Login failed.", "More than one UserAccounts record with that name."); | ||
3580 | ret++; | ||
3581 | } | ||
3582 | else | ||
3583 | { | ||
3584 | dbPull(Rd, "UserAccounts", rows); | ||
3585 | Rd->stuff->putstr(Rd->stuff, "UUID", xstrdup(getStrH(Rd->database, "UserAccounts.PrincipalID"))); | ||
3586 | Rd->stuff->putstr(Rd->stuff, "level", xstrdup(getStrH(Rd->database, "UserAccounts.Userlevel"))); | ||
3587 | if (s) {s--; *s = ' '; s++;} | ||
3588 | Rd->stuff->putstr(Rd->stuff, "name", xstrdup(name)); | ||
3589 | } | ||
3590 | } | ||
3591 | } | 3619 | } |
3592 | else | 3620 | else |
3593 | { | 3621 | { |
3622 | W("More than one UserAccounts record with that name."); | ||
3623 | ret++; | ||
3624 | } | ||
3625 | bitch(Rd, "Login failed.", "Could not find user record."); | ||
3626 | } | ||
3627 | else | ||
3628 | { | ||
3629 | if (1 == c) | ||
3630 | dbPull(Rd, "UserAccounts", rows); | ||
3631 | else | ||
3632 | { | ||
3594 | Rd->database->putstr(Rd->database, "UserAccounts.FirstName", name); | 3633 | Rd->database->putstr(Rd->database, "UserAccounts.FirstName", name); |
3595 | Rd->database->putstr(Rd->database, "UserAccounts.LastName", s); | 3634 | Rd->database->putstr(Rd->database, "UserAccounts.LastName", s); |
3596 | Rd->database->putstr(Rd->database, "UserAccounts.Email", getStrH(tnm, "email")); | 3635 | Rd->database->putstr(Rd->database, "UserAccounts.Email", getStrH(tnm, "email")); |
3597 | Rd->database->putstr(Rd->database, "UserAccounts.Created", getStrH(tnm, "created")); | 3636 | Rd->database->putstr(Rd->database, "UserAccounts.Created", getStrH(tnm, "created")); |
3598 | Rd->database->putstr(Rd->database, "UserAccounts.PrincipleID", getStrH(tnm, "UUID")); | 3637 | Rd->database->putstr(Rd->database, "UserAccounts.PrincipleID", getStrH(tnm, "UUID")); |
3599 | Rd->database->putstr(Rd->database, "UserAccounts.UserLevel", getStrH(tnm, "level")); | 3638 | Rd->database->putstr(Rd->database, "UserAccounts.UserLevel", getStrH(tnm, "level")); |
3600 | Rd->database->putstr(Rd->database, "UserAccounts.UserFlags", getStrH(tnm, "flags")); | 3639 | Rd->database->putstr(Rd->database, "UserAccounts.UserFlags", getStrH(tnm, "flags")); |
3601 | Rd->database->putstr(Rd->database, "UserAccounts.UserTitle", getStrH(tnm, "title")); | 3640 | Rd->database->putstr(Rd->database, "UserAccounts.UserTitle", getStrH(tnm, "title")); |
3602 | Rd->database->putstr(Rd->database, "UserAccounts.active", getStrH(tnm, "active")); | 3641 | Rd->database->putstr(Rd->database, "UserAccounts.active", getStrH(tnm, "active")); |
3603 | Rd->database->putstr(Rd->database, "auth.passwordSalt", getStrH(tnm, "passwordSalt")); | 3642 | Rd->database->putstr(Rd->database, "auth.passwordSalt", getStrH(tnm, "passwordSalt")); |
3604 | Rd->database->putstr(Rd->database, "auth.passwordHash", getStrH(tnm, "passwordHash")); | 3643 | Rd->database->putstr(Rd->database, "auth.passwordHash", getStrH(tnm, "passwordHash")); |
3605 | 3644 | tnm->free(tnm); | |
3606 | Rd->stuff->putstr(Rd->stuff, "UUID", xstrdup(getStrH(Rd->database, "UserAccounts.PrincipalID"))); | ||
3607 | Rd->stuff->putstr(Rd->stuff, "level", xstrdup(getStrH(Rd->database, "UserAccounts.Userlevel"))); | ||
3608 | if (s) {s--; *s = ' '; s++;} | ||
3609 | Rd->stuff->putstr(Rd->stuff, "name", xstrdup(name)); | ||
3610 | if (s) {s--; *s = '\0'; s++;} | ||
3611 | } | 3645 | } |
3646 | Rd->stuff->putstr(Rd->stuff, "UUID", xstrdup(getStrH(Rd->database, "UserAccounts.PrincipalID"))); | ||
3647 | Rd->stuff->putstr(Rd->stuff, "level", xstrdup(getStrH(Rd->database, "UserAccounts.Userlevel"))); | ||
3648 | if (s) {s--; *s = ' '; s++;} | ||
3649 | Rd->stuff->putstr(Rd->stuff, "name", xstrdup(name)); | ||
3650 | if (s) {s--; *s = '\0'; s++;} | ||
3612 | } | 3651 | } |
3613 | else if (strcmp("create", Rd->doit) == 0) | 3652 | } |
3653 | else if (strcmp("create", Rd->doit) == 0) | ||
3654 | { | ||
3655 | if ((0 != c) && (!rt)) | ||
3656 | { | ||
3657 | bitch(Rd, "Pick a different name.", "An existing Lua user file or UserAccounts record matched that name."); | ||
3658 | ret++; | ||
3659 | } | ||
3660 | else | ||
3614 | { | 3661 | { |
3615 | if (i != 0) | ||
3616 | { | ||
3617 | bitch(Rd, "Pick a different name.", "An existing UserAccounts record matched that name."); | ||
3618 | ret++; | ||
3619 | } | ||
3620 | else | ||
3621 | { | ||
3622 | // TODO - compare first, last, and fullname against god names, complain and fail if there's a match. | 3662 | // TODO - compare first, last, and fullname against god names, complain and fail if there's a match. |
3623 | { | 3663 | // Generate a UUID, check it isn't already being used. |
3624 | // Generate a UUID, check it isn't already being used. | 3664 | char uuid[37]; |
3625 | char uuid[37]; | 3665 | uuid_t binuuid; |
3626 | uuid_t binuuid; | 3666 | my_ulonglong users = 0; |
3627 | my_ulonglong users = 0; | ||
3628 | 3667 | ||
3629 | do // UserAccounts.PrincipalID is a unique primary index anyway, but we want the user creation process to be a little on the slow side. | 3668 | do // UserAccounts.PrincipalID is a unique primary index anyway, but we want the user creation process to be a little on the slow side. |
3630 | { | 3669 | { |
3631 | uuid_generate_random(binuuid); | 3670 | struct stat st; |
3632 | uuid_unparse_lower(binuuid, uuid); | 3671 | |
3633 | where = xmprintf("UserAccounts.PrincipalID = '%s'", uuid); | 3672 | uuid_generate_random(binuuid); |
3634 | D("Trying new UUID %s.", where); | 3673 | uuid_unparse_lower(binuuid, uuid); |
3635 | users = dbCount(Rd->db, "UserAccounts", where); | 3674 | // Try Lua user file. |
3636 | free(where); | 3675 | where = xmprintf("%s/users/%s.lua", scData, uuid); |
3637 | } while (users != 0); | 3676 | c = stat(where, &st); |
3677 | if (c) | ||
3678 | users = 1; | ||
3679 | free(where); | ||
3680 | // Try database. | ||
3681 | where = xmprintf("UserAccounts.PrincipalID = '%s'", uuid); | ||
3682 | D("Trying new UUID %s.", where); | ||
3683 | users = dbCount(Rd->db, "UserAccounts", where); | ||
3684 | free(where); | ||
3685 | } while (users != 0); | ||
3638 | // TODO - perhaps create a place holder UserAccounts record? Then we'll have to deal with deleting them later. | 3686 | // TODO - perhaps create a place holder UserAccounts record? Then we'll have to deal with deleting them later. |
3639 | 3687 | Rd->stuff->putstr(Rd->stuff, "UUID", xstrdup(uuid)); | |
3640 | Rd->stuff->putstr(Rd->stuff, "UUID", xstrdup(uuid)); | 3688 | Rd->stuff->putstr(Rd->stuff, "level", xstrdup("-200")); |
3641 | Rd->stuff->putstr(Rd->stuff, "level", xstrdup("-200")); | 3689 | Rd->database->putstr(Rd->database, "UserAccounts.PrincipalID",xstrdup(uuid)); |
3642 | Rd->database->putstr(Rd->database, "UserAccounts.PrincipalID", xstrdup(uuid)); | 3690 | Rd->database->putstr(Rd->database, "UserAccounts.Userlevel", xstrdup("-200")); |
3643 | Rd->database->putstr(Rd->database, "UserAccounts.Userlevel", xstrdup("-200")); | 3691 | Rd->database->putstr(Rd->database, "UserAccounts.firstName", xstrdup(name)); |
3644 | Rd->database->putstr(Rd->database, "UserAccounts.firstName", xstrdup(name)); | 3692 | Rd->database->putstr(Rd->database, "UserAccounts.lastName", xstrdup(s)); |
3645 | Rd->database->putstr(Rd->database, "UserAccounts.lastName", xstrdup(s)); | 3693 | if (s) {s--; *s = ' '; s++;} |
3646 | if (s) {s--; *s = ' '; s++;} | 3694 | Rd->stuff->putstr(Rd->stuff, "name", xstrdup(name)); |
3647 | Rd->stuff->putstr(Rd->stuff, "name", xstrdup(name)); | ||
3648 | } | ||
3649 | } | ||
3650 | } | 3695 | } |
3651 | free(rows->rows); | ||
3652 | free(rows->fieldNames); | ||
3653 | free(rows); | ||
3654 | } | 3696 | } |
3655 | 3697 | free(rows->rows); | |
3698 | free(rows->fieldNames); | ||
3699 | free(rows); | ||
3656 | if (s) {s--; *s = ' '; s++;} | 3700 | if (s) {s--; *s = ' '; s++;} |
3657 | } | 3701 | } |
3658 | } | 3702 | } |
@@ -3661,7 +3705,7 @@ static int validateName(reqData *Rd, qhashtbl_t *data) | |||
3661 | return ret; | 3705 | return ret; |
3662 | } | 3706 | } |
3663 | 3707 | ||
3664 | static int validatePassword(reqData *Rd, qhashtbl_t *data) | 3708 | static int validatePassword(reqData *Rd, qhashtbl_t *data, char *name) |
3665 | { | 3709 | { |
3666 | boolean login = strcmp("login", Rd->doit) == 0; | 3710 | boolean login = strcmp("login", Rd->doit) == 0; |
3667 | boolean create = strcmp("create", Rd->doit) == 0; | 3711 | boolean create = strcmp("create", Rd->doit) == 0; |
@@ -3670,13 +3714,13 @@ static int validatePassword(reqData *Rd, qhashtbl_t *data) | |||
3670 | char *psswrdH = getStrH(Rd->stuff, "passwordHash"); | 3714 | char *psswrdH = getStrH(Rd->stuff, "passwordHash"); |
3671 | char *psswrdS = getStrH(Rd->stuff, "passwordSalt"); | 3715 | char *psswrdS = getStrH(Rd->stuff, "passwordSalt"); |
3672 | 3716 | ||
3673 | if (prevalidate(Rd->database, "auth.passwordSalt")) return ret; | ||
3674 | |||
3675 | I("Validating password."); | ||
3676 | if (login) | 3717 | if (login) |
3677 | { | 3718 | { |
3678 | char *UUID = getStrH(Rd->database, "UserAccounts.PrincipalID"); | 3719 | char *UUID = getStrH(Rd->database, "UserAccounts.PrincipalID"); |
3679 | static dbRequest *auth = NULL; | 3720 | static dbRequest *auth = NULL; |
3721 | |||
3722 | if ('\0' == UUID[0]) // If the name validation didn't find us a UUID, then this user doesn't exist, so can't log them on. | ||
3723 | return 1; | ||
3680 | if (NULL == auth) | 3724 | if (NULL == auth) |
3681 | { | 3725 | { |
3682 | static char *szi[] = {"UUID", NULL}; | 3726 | static char *szi[] = {"UUID", NULL}; |
@@ -3851,16 +3895,19 @@ static int validatePassword(reqData *Rd, qhashtbl_t *data) | |||
3851 | else | 3895 | else |
3852 | D("Account created%s.", password); | 3896 | D("Account created%s.", password); |
3853 | 3897 | ||
3898 | badBoy(ret, Rd, data, "auth.passwordSalt", NULL); | ||
3899 | |||
3854 | return ret; | 3900 | return ret; |
3855 | } | 3901 | } |
3856 | 3902 | ||
3857 | 3903 | ||
3858 | static int validateUUID(reqData *Rd, qhashtbl_t *data) | 3904 | static int validateUUID(reqData *Rd, qhashtbl_t *data, char *name) |
3859 | { | 3905 | { |
3860 | int ret = 0, i; | 3906 | int ret = 0, i; |
3861 | char uuid[37], *t; | 3907 | char uuid[37], *t; |
3862 | rowData *rows = NULL; | 3908 | rowData *rows = NULL; |
3863 | static dbRequest *uuids = NULL; | 3909 | static dbRequest *uuids = NULL; |
3910 | |||
3864 | if (NULL == uuids) | 3911 | if (NULL == uuids) |
3865 | { | 3912 | { |
3866 | static char *szi[] = {"PrincipalID", NULL}; | 3913 | static char *szi[] = {"PrincipalID", NULL}; |
@@ -3873,14 +3920,15 @@ static int validateUUID(reqData *Rd, qhashtbl_t *data) | |||
3873 | uuids->where = "PrincipalID=?"; | 3920 | uuids->where = "PrincipalID=?"; |
3874 | } | 3921 | } |
3875 | 3922 | ||
3876 | I("Validating UUID."); | 3923 | if ((strcmp("cancel", Rd->doit) == 0) || (strcmp("logout", Rd->doit) == 0)) |
3924 | return ret; | ||
3925 | |||
3926 | uuid[0] = '\0'; | ||
3877 | if (strcmp("create", Rd->doit) == 0) | 3927 | if (strcmp("create", Rd->doit) == 0) |
3878 | { | 3928 | { |
3879 | // Generate a UUID, check it isn't already being used, and totally ignore whatever UUID is in body. | 3929 | // Generate a UUID, check it isn't already being used, and totally ignore whatever UUID is in body. |
3880 | uuid_t binuuid; | 3930 | uuid_t binuuid; |
3881 | 3931 | ||
3882 | if (prevalidate(Rd->stuff, "UUID")) return ret; | ||
3883 | |||
3884 | do // UserAccounts.PrincipalID is a unique primary index anyway, but we want the user creation process to be a little on the slow side. | 3932 | do // UserAccounts.PrincipalID is a unique primary index anyway, but we want the user creation process to be a little on the slow side. |
3885 | { | 3933 | { |
3886 | uuid_generate_random(binuuid); | 3934 | uuid_generate_random(binuuid); |
@@ -3903,7 +3951,7 @@ static int validateUUID(reqData *Rd, qhashtbl_t *data) | |||
3903 | if (0 == ret) | 3951 | if (0 == ret) |
3904 | { | 3952 | { |
3905 | data->putstr(data, "UUID", xstrdup(uuid)); | 3953 | data->putstr(data, "UUID", xstrdup(uuid)); |
3906 | data->putstr(data, "NEW - UUID", uuid); | 3954 | Rd->stuff->putstr(Rd->stuff, "UUID", xstrdup(uuid)); |
3907 | } | 3955 | } |
3908 | rows = NULL; | 3956 | rows = NULL; |
3909 | } | 3957 | } |
@@ -3958,41 +4006,13 @@ static int validateUUID(reqData *Rd, qhashtbl_t *data) | |||
3958 | { | 4006 | { |
3959 | Rd->database->putstr(Rd->database, "UserAccounts.PrincipalID", xstrdup(uuid)); | 4007 | Rd->database->putstr(Rd->database, "UserAccounts.PrincipalID", xstrdup(uuid)); |
3960 | } | 4008 | } |
4009 | Rd->stuff->putstr(Rd->stuff, "UUID", xstrdup(uuid)); | ||
3961 | } | 4010 | } |
3962 | 4011 | ||
3963 | return ret; | 4012 | return ret; |
3964 | } | 4013 | } |
3965 | 4014 | ||
3966 | 4015 | ||
3967 | |||
3968 | int validateThings(reqData *Rd, char *doit, char *name, qhashtbl_t *things) | ||
3969 | { | ||
3970 | int e = 0; | ||
3971 | |||
3972 | W("%s start of %s validation.", doit, name); | ||
3973 | qlisttbl_obj_t obj; | ||
3974 | memset((void *) &obj, 0, sizeof(obj)); | ||
3975 | fieldValidFuncs->lock(fieldValidFuncs); | ||
3976 | while(fieldValidFuncs->getnext(fieldValidFuncs, &obj, NULL, false) == true) | ||
3977 | { | ||
3978 | char *t = getStrH(things, obj.name); | ||
3979 | |||
3980 | if ('\0' != t[0]) | ||
3981 | { | ||
3982 | validFunc *vf = (validFunc *) obj.data; | ||
3983 | |||
3984 | W("Validating %s", obj.name); | ||
3985 | if (vf->func) | ||
3986 | e += vf->func(Rd, things); | ||
3987 | else | ||
3988 | E("No validation function for %s", obj.name); | ||
3989 | } | ||
3990 | } | ||
3991 | fieldValidFuncs->unlock(fieldValidFuncs); | ||
3992 | return e; | ||
3993 | } | ||
3994 | |||
3995 | |||
3996 | void loginPage(reqData *Rd, char *message) | 4016 | void loginPage(reqData *Rd, char *message) |
3997 | { | 4017 | { |
3998 | char *name = xstrdup(getStrH(Rd->stuff, "name")); | 4018 | char *name = xstrdup(getStrH(Rd->stuff, "name")); |
@@ -4022,11 +4042,14 @@ void loginPage(reqData *Rd, char *message) | |||
4022 | 4042 | ||
4023 | void accountCreationPage(reqData *Rd, char *message) | 4043 | void accountCreationPage(reqData *Rd, char *message) |
4024 | { | 4044 | { |
4025 | char *name = getStrH(Rd->stuff, "name"); | 4045 | char *name = getStrH(Rd->body, "name"); |
4026 | char *toke_n_munchie = getCookie(Rd->Rcookies, "toke_n_munchie"); | 4046 | char *toke_n_munchie = getCookie(Rd->Rcookies, "toke_n_munchie"); |
4027 | char *tmp = xmalloc(16), *t; | 4047 | char *tmp = xmalloc(16), *t; |
4028 | int i, d; | 4048 | int i, d; |
4029 | 4049 | ||
4050 | if ('\0' == name[0]) | ||
4051 | name = getStrH(Rd->stuff, "name"); | ||
4052 | |||
4030 | // TODO - eww lots of memory leaks here. | 4053 | // TODO - eww lots of memory leaks here. |
4031 | // TODO - need to check if qlibc does it's own free() calls, and fill in the gaps for when it doesn't. | 4054 | // TODO - need to check if qlibc does it's own free() calls, and fill in the gaps for when it doesn't. |
4032 | HTMLheader(Rd->reply, "<!--#echo var=\"grid\" --> account manager"); | 4055 | HTMLheader(Rd->reply, "<!--#echo var=\"grid\" --> account manager"); |
@@ -4050,7 +4073,7 @@ void accountCreationPage(reqData *Rd, char *message) | |||
4050 | Rd->reply->addstr(Rd->reply, "<p>A validation email will be sent to this email address, you will need to click on the link in it to continue your account creation.</p>\n"); | 4073 | Rd->reply->addstr(Rd->reply, "<p>A validation email will be sent to this email address, you will need to click on the link in it to continue your account creation.</p>\n"); |
4051 | Rd->reply->addstr(Rd->reply, "<table><tr><td>\n"); | 4074 | Rd->reply->addstr(Rd->reply, "<table><tr><td>\n"); |
4052 | HTMLselect(Rd->reply, "Date of birth", "year"); | 4075 | HTMLselect(Rd->reply, "Date of birth", "year"); |
4053 | t = getStrH(Rd->stuff, "year"); | 4076 | t = getStrH(Rd->body, "year"); |
4054 | if (NULL == t) | 4077 | if (NULL == t) |
4055 | d = -1; | 4078 | d = -1; |
4056 | else | 4079 | else |
@@ -4068,7 +4091,7 @@ void accountCreationPage(reqData *Rd, char *message) | |||
4068 | HTMLselectEnd(Rd->reply); | 4091 | HTMLselectEnd(Rd->reply); |
4069 | Rd->reply->addstr(Rd->reply, "</tt><td>"); | 4092 | Rd->reply->addstr(Rd->reply, "</tt><td>"); |
4070 | HTMLselect(Rd->reply, NULL, "month"); | 4093 | HTMLselect(Rd->reply, NULL, "month"); |
4071 | t = getStrH(Rd->stuff, "month"); | 4094 | t = getStrH(Rd->body, "month"); |
4072 | HTMLoption(Rd->reply, xstrdup(""), FALSE); | 4095 | HTMLoption(Rd->reply, xstrdup(""), FALSE); |
4073 | for (i = 0; i <= 11; i++) | 4096 | for (i = 0; i <= 11; i++) |
4074 | { | 4097 | { |
@@ -4177,17 +4200,18 @@ void account_html(char *file, reqData *Rd, HTMLfile *thisFile) | |||
4177 | if (NULL == fieldValidFuncs) | 4200 | if (NULL == fieldValidFuncs) |
4178 | { | 4201 | { |
4179 | fieldValidFuncs = qlisttbl(QLISTTBL_LOOKUPFORWARD | QLISTTBL_THREADSAFE | QLISTTBL_UNIQUE); | 4202 | fieldValidFuncs = qlisttbl(QLISTTBL_LOOKUPFORWARD | QLISTTBL_THREADSAFE | QLISTTBL_UNIQUE); |
4180 | newValidFunc("hashish", (fieldValidFunc) validateSesh); | 4203 | newValidFunc("hashish", "session", (fieldValidFunc) validateSesh); |
4181 | newValidFunc("toke_n_munchie", (fieldValidFunc) validateSesh); | 4204 | newValidFunc("toke_n_munchie", "session", (fieldValidFunc) validateSesh); |
4182 | newValidFunc("UUID", (fieldValidFunc) validateUUID); | 4205 | newValidFunc("UUID", "UUID", (fieldValidFunc) validateUUID); |
4183 | newValidFunc("name", (fieldValidFunc) validateName); | 4206 | newValidFunc("name", "name", (fieldValidFunc) validateName); |
4184 | newValidFunc("password", (fieldValidFunc) validatePassword); | 4207 | newValidFunc("password", "password", (fieldValidFunc) validatePassword); |
4185 | newValidFunc("email", (fieldValidFunc) validateEmail); | 4208 | newValidFunc("email", "email", (fieldValidFunc) validateEmail); |
4186 | newValidFunc("emayl", (fieldValidFunc) validateEmail); | 4209 | newValidFunc("emayl", "email", (fieldValidFunc) validateEmail); |
4187 | newValidFunc("year", (fieldValidFunc) validateDoB); | 4210 | newValidFunc("year", "DoB", (fieldValidFunc) validateDoB); |
4188 | newValidFunc("month", (fieldValidFunc) validateDoB); | 4211 | newValidFunc("month", "DoB", (fieldValidFunc) validateDoB); |
4189 | newValidFunc("adult", (fieldValidFunc) validateLegal); | 4212 | newValidFunc("adult", "legal", (fieldValidFunc) validateLegal); |
4190 | newValidFunc("agree", (fieldValidFunc) validateLegal); | 4213 | newValidFunc("agree", "legal", (fieldValidFunc) validateLegal); |
4214 | newValidFunc("aboutMe", "about me", (fieldValidFunc) validateAboutMe); | ||
4191 | } | 4215 | } |
4192 | if (NULL == buildPages) | 4216 | if (NULL == buildPages) |
4193 | { | 4217 | { |
@@ -4329,6 +4353,12 @@ void account_html(char *file, reqData *Rd, HTMLfile *thisFile) | |||
4329 | freeSesh(Rd, FALSE, TRUE); | 4353 | freeSesh(Rd, FALSE, TRUE); |
4330 | newSesh(Rd, FALSE); | 4354 | newSesh(Rd, FALSE); |
4331 | } | 4355 | } |
4356 | else if ((0 != e)) // So we can reload details into a broken form, so the user doesn't have to retype everything. | ||
4357 | { | ||
4358 | freeSesh(Rd, FALSE, FALSE); | ||
4359 | newSesh(Rd, FALSE); | ||
4360 | } | ||
4361 | |||
4332 | Rd->func(Rd, ""); | 4362 | Rd->func(Rd, ""); |
4333 | } | 4363 | } |
4334 | 4364 | ||
@@ -4726,6 +4756,7 @@ jit library is loaded or the JIT compiler will not be activated. | |||
4726 | // Rd->body = qhashtbl(0, 0); // Inited in toknize below. | 4756 | // Rd->body = qhashtbl(0, 0); // Inited in toknize below. |
4727 | // Rd->cookies = qhashtbl(0, 0); // Inited in toknize below. | 4757 | // Rd->cookies = qhashtbl(0, 0); // Inited in toknize below. |
4728 | Rd->headers = qhashtbl(0, 0); | 4758 | Rd->headers = qhashtbl(0, 0); |
4759 | Rd->valid = qhashtbl(0, 0); | ||
4729 | Rd->stuff = qhashtbl(0, 0); | 4760 | Rd->stuff = qhashtbl(0, 0); |
4730 | Rd->database = qhashtbl(0, 0); | 4761 | Rd->database = qhashtbl(0, 0); |
4731 | Rd->Rcookies = qhashtbl(0, 0); | 4762 | Rd->Rcookies = qhashtbl(0, 0); |
@@ -4983,6 +5014,7 @@ fcgiDone: | |||
4983 | qhashtbl_free(Rd->Rcookies); | 5014 | qhashtbl_free(Rd->Rcookies); |
4984 | qhashtbl_free(Rd->database); | 5015 | qhashtbl_free(Rd->database); |
4985 | qhashtbl_free(Rd->stuff); | 5016 | qhashtbl_free(Rd->stuff); |
5017 | qhashtbl_free(Rd->valid); | ||
4986 | qhashtbl_free(Rd->headers); | 5018 | qhashtbl_free(Rd->headers); |
4987 | qhashtbl_free(Rd->cookies); | 5019 | qhashtbl_free(Rd->cookies); |
4988 | qhashtbl_free(Rd->body); | 5020 | qhashtbl_free(Rd->body); |