chiark / gitweb /
Tidy up login reporting.
[disorder] / server / dcgi.c
index 08203f8052f16a37fd46ac298a55eb52d53fe58d..27c77b1037a85fe89b5d440ff9d0e60e759fac8b 100644 (file)
@@ -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);
 }