X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/disorder/blobdiff_plain/938d815790a53407a3113b183319b985135e1d1d..ac152d06f4cfa9abcd4a88de7dbc6a9040f99c0d:/server/dcgi.c diff --git a/server/dcgi.c b/server/dcgi.c index 08203f8..27c77b1 100644 --- a/server/dcgi.c +++ b/server/dcgi.c @@ -54,6 +54,9 @@ #include "trackname.h" #include "charset.h" #include "dcgi.h" +#include "url.h" +#include "mime.h" +#include "sendmail.h" char *login_cookie; @@ -103,21 +106,28 @@ static const char *front_url(void) { static void header_cookie(struct sink *output) { struct dynstr d[1]; - char *s; + struct url u; + memset(&u, 0, sizeof u); + dynstr_init(d); + parse_url(config->url, &u); if(login_cookie) { - dynstr_init(d); - for(s = login_cookie; *s; ++s) { - if(*s == '"') - dynstr_append(d, '\\'); - dynstr_append(d, *s); - } - dynstr_terminate(d); - byte_xasprintf(&s, "disorder=\"%s\"", d->vec); /* TODO domain, path, expiry */ - cgi_header(output, "Set-Cookie", s); - } else + dynstr_append_string(d, "disorder="); + dynstr_append_string(d, quote822(login_cookie, 0)); + } else { /* Force browser to discard cookie */ - cgi_header(output, "Set-Cookie", "disorder=none;Max-Age=0"); + dynstr_append_string(d, "disorder=none;Max-Age=0"); + } + if(u.path) { + /* The default domain matches the request host, so we need not override + * that. But the default path only goes up to the rightmost /, which would + * cause the browser to expose the cookie to other CGI programs on the same + * web server. */ + dynstr_append_string(d, ";Path="); + dynstr_append_string(d, quote822(u.path, 0)); + } + dynstr_terminate(d); + cgi_header(output, "Set-Cookie", d->vec); } static void redirect(struct sink *output) { @@ -467,7 +477,8 @@ static void act_login(cgi_sink *output, } /* We have a new cookie */ header_cookie(output->sink); - if((back = cgi_get("back")) && back) + cgi_set_option("status", "loginok"); + if((back = cgi_get("back")) && *back) /* Redirect back to somewhere or other */ redirect(output->sink); else @@ -482,13 +493,15 @@ static void act_logout(cgi_sink *output, /* Reconnect as guest */ disorder_cgi_login(ds, output); /* Back to the login page */ + cgi_set_option("status", "logoutok"); expand_template(ds, output, "login"); } static void act_register(cgi_sink *output, dcgi_state *ds) { const char *username, *password, *email; - char *confirm; + char *confirm, *content_type; + const char *text, *encoding, *charset; username = cgi_get("username"); password = cgi_get("password"); @@ -521,8 +534,36 @@ static void act_register(cgi_sink *output, expand_template(ds, output, "login"); return; } + /* Send the user a mail */ + /* TODO templatize this */ + byte_xasprintf((char **)&text, + "Welcome to DisOrder. To active your login, please visit this URL:\n" + "\n" + "%s?c=%s\n", config->url, urlencodestring(confirm)); + if(!(text = mime_encode_text(text, &charset, &encoding))) + fatal(0, "cannot encode email"); + byte_xasprintf(&content_type, "text/plain;charset=%s", + quote822(charset, 0)); + sendmail("", config->mail_sender, email, "Welcome to DisOrder", + encoding, content_type, text); /* TODO error checking */ /* We'll go back to the login page with a suitable message */ - cgi_set_option("registered", "registeredok"); + cgi_set_option("status", "registered"); + expand_template(ds, output, "login"); +} + +static void act_confirm(cgi_sink *output, + dcgi_state *ds) { + const char *confirmation; + + if(!(confirmation = cgi_get("c"))) { + cgi_set_option("error", "noconfirm"); + expand_template(ds, output, "login"); + } + if(disorder_confirm(ds->g->client, confirmation)) { + cgi_set_option("error", "badconfirm"); + expand_template(ds, output, "login"); + } + cgi_set_option("status", "confirmed"); expand_template(ds, output, "login"); } @@ -530,6 +571,7 @@ static const struct action { const char *name; void (*handler)(cgi_sink *output, dcgi_state *ds); } actions[] = { + { "confirm", act_confirm }, { "disable", act_disable }, { "enable", act_enable }, { "login", act_login }, @@ -1664,7 +1706,14 @@ static void perform_action(cgi_sink *output, dcgi_state *ds, void disorder_cgi(cgi_sink *output, dcgi_state *ds) { const char *action = cgi_get("action"); - if(!action) action = "playing"; + if(!action) { + /* We allow URLs which are just confirm=... in order to keep confirmation + * URLs, which are user-facing, as short as possible. */ + if(cgi_get("c")) + action = "confirm"; + else + action = "playing"; + } perform_action(output, ds, action); }