chiark / gitweb /
Fix login/logout/etc and misc other bits and pieces
authorRichard Kettlewell <rjk@greenend.org.uk>
Sat, 17 May 2008 20:13:25 +0000 (21:13 +0100)
committerRichard Kettlewell <rjk@greenend.org.uk>
Sat, 17 May 2008 20:13:25 +0000 (21:13 +0100)
lib/cgi.c
lib/macros.c
server/actions.c
server/dcgi.c
server/disorder-cgi.h
server/macros-disorder.c
templates/choose.tmpl
templates/disorder.css
templates/macros.tmpl
templates/new.tmpl
templates/options.labels

index 9e455bfff40c4d818da4b33b1fce7d07f0a737c1..1d1ddd708e85725d45edc462ac182ca230d8bedd 100644 (file)
--- a/lib/cgi.c
+++ b/lib/cgi.c
@@ -350,13 +350,11 @@ char *cgi_thisurl(const char *url) {
 
   dynstr_init(d);
   dynstr_append_string(d, url);
 
   dynstr_init(d);
   dynstr_append_string(d, url);
-  if(*keys) {
-    dynstr_append(d, '?');
-    for(n = 0; keys[n]; ++n) {
-      dynstr_append_string(d, urlencodestring(keys[n]));
-      dynstr_append(d, '=');
-      dynstr_append_string(d, cgi_get(keys[n]));
-    }
+  for(n = 0; keys[n]; ++n) {
+    dynstr_append(d, n ? '&' : '?');
+    dynstr_append_string(d, urlencodestring(keys[n]));
+    dynstr_append(d, '=');
+    dynstr_append_string(d, cgi_get(keys[n]));
   }
   dynstr_terminate(d);
   return d->vec;
   }
   dynstr_terminate(d);
   return d->vec;
index f177ae0e10f9749a12966bcceb841d4ad6edc47f..4d3b9a0f1c9d713e4f52224d9186d2086f722979 100644 (file)
@@ -350,9 +350,7 @@ static int mx__register(unsigned flags,
   e->args = args;
   e->callback = callback;
   e->definition = definition;
   e->args = args;
   e->callback = callback;
   e->definition = definition;
-  return hash_add(expansions, name, &e,
-                  ((flags & EXP_TYPE_MASK) == EXP_MACRO)
-                      ? HASH_INSERT : HASH_INSERT_OR_REPLACE);
+  return hash_add(expansions, name, &e, HASH_INSERT_OR_REPLACE);
 }
 
 /** @brief Register a simple expansion rule
 }
 
 /** @brief Register a simple expansion rule
@@ -394,11 +392,13 @@ int mx_register_macro(const char *name,
                       const struct mx_node *definition) {
   if(mx__register(EXP_MACRO, name, nargs, nargs, args,  0/*callback*/,
                   definition)) {
                       const struct mx_node *definition) {
   if(mx__register(EXP_MACRO, name, nargs, nargs, args,  0/*callback*/,
                   definition)) {
+#if 0
     /* This locates the error to the definition, which may be a line or two
      * beyond the @define command itself.  The backtrace generated by
      * mx_expand() may help more. */
     error(0, "%s:%d: duplicate definition of '%s'",
           definition->filename, definition->line, name);
     /* This locates the error to the definition, which may be a line or two
      * beyond the @define command itself.  The backtrace generated by
      * mx_expand() may help more. */
     error(0, "%s:%d: duplicate definition of '%s'",
           definition->filename, definition->line, name);
+#endif
     return -2;
   }
   return 0;
     return -2;
   }
   return 0;
index 59d6bccfac67b3e147373583ad883f44d2e0a598..4754a8c57b4fabfc1a7aee4b1afe32b5673fc2d6 100644 (file)
@@ -34,7 +34,7 @@ static void redirect(const char *url) {
   if(!url)
     url = cgi_get("back");
   if(url) {
   if(!url)
     url = cgi_get("back");
   if(url) {
-    if(!strncmp(url, "http", 4))
+    if(strncmp(url, "http", 4))
       /* If the target is not a full URL assume it's the action */
       url = cgi_makeurl(config->url, "action", url, (char *)0);
   } else {
       /* If the target is not a full URL assume it's the action */
       url = cgi_makeurl(config->url, "action", url, (char *)0);
   } else {
@@ -86,13 +86,10 @@ static void act_playing(void) {
     url = cgi_makeurl(config->url, "action", action, (char *)0);
   else
     url = config->url;
     url = cgi_makeurl(config->url, "action", action, (char *)0);
   else
     url = config->url;
-  if(printf("Content-Type: text/html\n"
-            "Refresh: %ld;url=%s\n"
-            "%s\n"
-            "\n",
-            refresh, url, dcgi_cookie_header()) < 0)
+  if(printf("Refresh: %ld;url=%s\n",
+            refresh, url) < 0)
     fatal(errno, "error writing to stdout");
     fatal(errno, "error writing to stdout");
-  dcgi_expand("playing");
+  dcgi_expand("playing", 1);
 }
 
 static void act_disable(void) {
 }
 
 static void act_disable(void) {
@@ -237,6 +234,253 @@ static void act_volume(void) {
   redirect(0);
 }
 
   redirect(0);
 }
 
+/** @brief Expand the login template with @b @@error set to @p error
+ * @param error Error keyword
+ */
+static void login_error(const char *error) {
+  dcgi_error_string = error;
+  dcgi_expand("login", 1);
+}
+
+/** @brief Log in
+ * @param username Login name
+ * @param password Password
+ * @return 0 on success, non-0 on error
+ *
+ * On error, calls login_error() to expand the login template.
+ */
+static int login_as(const char *username, const char *password) {
+  disorder_client *c;
+
+  if(dcgi_cookie && dcgi_client)
+    disorder_revoke(dcgi_client);
+  /* We'll need a new connection as we are going to stop being guest */
+  c = disorder_new(0);
+  if(disorder_connect_user(c, username, password)) {
+    login_error("loginfailed");
+    return -1;
+  }
+  /* Generate a cookie so we can log in again later */
+  if(disorder_make_cookie(c, &dcgi_cookie)) {
+    login_error("cookiefailed");
+    return -1;
+  }
+  /* Use the new connection henceforth */
+  dcgi_client = c;
+  dcgi_lookup_reset();
+  return 0;                             /* OK */
+}
+
+static void act_login(void) {
+  const char *username, *password;
+
+  /* We try all this even if not connected since the subsequent connection may
+   * succeed. */
+  
+  username = cgi_get("username");
+  password = cgi_get("password");
+  if(!username
+     || !password
+     || !strcmp(username, "guest")/*bodge to avoid guest cookies*/) {
+    /* We're just visiting the login page, not performing an action at all. */
+    dcgi_expand("login", 1);
+    return;
+  }
+  if(!login_as(username, password)) {
+    /* Report the succesful login */
+    dcgi_status_string = "loginok";
+    dcgi_expand("login", 1);
+  }
+}
+
+static void act_logout(void) {
+  if(dcgi_client) {
+    /* Ask the server to revoke the cookie */
+    if(!disorder_revoke(dcgi_client))
+      dcgi_status_string = "logoutok";
+    else
+      dcgi_error_string = "revokefailed";
+  } else {
+    /* We can't guarantee a logout if we can't connect to the server to revoke
+     * the cookie, so we report an error.  We'll still ask the browser to
+     * forget the cookie though. */
+    dcgi_error_string = "connect";
+  }
+  /* Attempt to reconnect without the cookie */
+  dcgi_cookie = 0;
+  dcgi_login();
+  /* Back to login page, hopefuly forcing the browser to forget the cookie. */
+  dcgi_expand("login", 1);
+}
+
+static void act_register(void) {
+  const char *username, *password, *password2, *email;
+  char *confirm, *content_type;
+  const char *text, *encoding, *charset;
+
+  /* If we're not connected then this is a hopeless exercise */
+  if(!dcgi_client) {
+    login_error("connect");
+    return;
+  }
+
+  /* Collect arguments */
+  username = cgi_get("username");
+  password = cgi_get("password1");
+  password2 = cgi_get("password2");
+  email = cgi_get("email");
+
+  /* Verify arguments */
+  if(!username || !*username) {
+    login_error("nousername");
+    return;
+  }
+  if(!password || !*password) {
+    login_error("nopassword");
+    return;
+  }
+  if(!password2 || !*password2 || strcmp(password, password2)) {
+    login_error("passwordmismatch");
+    return;
+  }
+  if(!email || !*email) {
+    login_error("noemail");
+    return;
+  }
+  /* We could well do better address validation but for now we'll just do the
+   * minimum */
+  if(!strchr(email, '@')) {
+    login_error("bademail");
+    return;
+  }
+  if(disorder_register(dcgi_client, username, password, email, &confirm)) {
+    login_error("cannotregister");
+    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 */
+  dcgi_status_string = "registered";
+  dcgi_expand("login", 1);
+}
+
+static void act_confirm(void) {
+  const char *confirmation;
+
+  /* If we're not connected then this is a hopeless exercise */
+  if(!dcgi_client) {
+    login_error("connect");
+    return;
+  }
+
+  if(!(confirmation = cgi_get("c"))) {
+    login_error("noconfirm");
+    return;
+  }
+  /* Confirm our registration */
+  if(disorder_confirm(dcgi_client, confirmation)) {
+    login_error("badconfirm");
+    return;
+  }
+  /* Get a cookie */
+  if(disorder_make_cookie(dcgi_client, &dcgi_cookie)) {
+    login_error("cookiefailed");
+    return;
+  }
+  /* Junk cached data */
+  dcgi_lookup_reset();
+  /* Report success */
+  dcgi_status_string = "confirmed";
+  dcgi_expand("login", 1);
+}
+
+static void act_edituser(void) {
+  const char *email = cgi_get("email"), *password = cgi_get("changepassword1");
+  const char *password2 = cgi_get("changepassword2");
+  int newpassword = 0;
+
+  /* If we're not connected then this is a hopeless exercise */
+  if(!dcgi_client) {
+    login_error("connect");
+    return;
+  }
+
+  /* Verify input */
+
+  /* If either password or password2 is set we insist they match.  If they
+   * don't we report an error. */
+  if((password && *password) || (password2 && *password2)) {
+    if(!password || !password2 || strcmp(password, password2)) {
+      login_error("passwordmismatch");
+      return;
+    }
+  } else
+    password = password2 = 0;
+  if(email && !strchr(email, '@')) {
+    login_error("bademail");
+    return;
+  }
+
+  /* Commit changes */
+  if(email) {
+    if(disorder_edituser(dcgi_client, disorder_user(dcgi_client),
+                        "email", email)) {
+      login_error("badedit");
+      return;
+    }
+  }
+  if(password) {
+    if(disorder_edituser(dcgi_client, disorder_user(dcgi_client),
+                        "password", password)) {
+      login_error("badedit");
+      return;
+    }
+    newpassword = 1;
+  }
+
+  if(newpassword) {
+    /* If we changed the password, the cookie is now invalid, so we must log
+     * back in. */
+    if(login_as(disorder_user(dcgi_client), password))
+      return;
+  }
+  /* Report success */
+  dcgi_status_string = "edited";
+  dcgi_expand("login", 1);
+}
+
+static void act_reminder(void) {
+  const char *const username = cgi_get("username");
+
+  /* If we're not connected then this is a hopeless exercise */
+  if(!dcgi_client) {
+    login_error("connect");
+    return;
+  }
+
+  if(!username || !*username) {
+    login_error("nousername");
+    return;
+  }
+  if(disorder_reminder(dcgi_client, username)) {
+    login_error("reminderfailed");
+    return;
+  }
+  /* Report success */
+  dcgi_status_string = "reminded";
+  dcgi_expand("login", 1);
+}
+
 /** @brief Table of actions */
 static const struct action {
   /** @brief Action name */
 /** @brief Table of actions */
 static const struct action {
   /** @brief Action name */
@@ -244,8 +488,12 @@ static const struct action {
   /** @brief Action handler */
   void (*handler)(void);
 } actions[] = {
   /** @brief Action handler */
   void (*handler)(void);
 } actions[] = {
+  { "confirm", act_confirm },
   { "disable", act_disable },
   { "disable", act_disable },
+  { "edituser", act_edituser },
   { "enable", act_enable },
   { "enable", act_enable },
+  { "login", act_login },
+  { "logout", act_logout },
   { "manage", act_playing },
   { "move", act_move },
   { "pause", act_pause },
   { "manage", act_playing },
   { "move", act_move },
   { "pause", act_pause },
@@ -253,6 +501,8 @@ static const struct action {
   { "playing", act_playing },
   { "randomdisable", act_random_disable },
   { "randomenable", act_random_enable },
   { "playing", act_playing },
   { "randomdisable", act_random_disable },
   { "randomenable", act_random_enable },
+  { "register", act_register },
+  { "reminder", act_reminder },
   { "remove", act_remove },
   { "resume", act_resume },
   { "volume", act_volume },
   { "remove", act_remove },
   { "resume", act_resume },
   { "volume", act_volume },
@@ -281,8 +531,9 @@ static int dcgi_valid_action(const char *name) {
 
 /** @brief Expand a template
  * @param name Base name of template, or NULL to consult CGI args
 
 /** @brief Expand a template
  * @param name Base name of template, or NULL to consult CGI args
+ * @param header True to write header
  */
  */
-void dcgi_expand(const char *name) {
+void dcgi_expand(const char *name, int header) {
   const char *p, *found;
 
   /* Parse macros first */
   const char *p, *found;
 
   /* Parse macros first */
@@ -294,6 +545,12 @@ void dcgi_expand(const char *name) {
   byte_xasprintf((char **)&p, "%s.tmpl", name);
   if(!(found = mx_find(p)))
     fatal(errno, "cannot find %s", p);
   byte_xasprintf((char **)&p, "%s.tmpl", name);
   if(!(found = mx_find(p)))
     fatal(errno, "cannot find %s", p);
+  if(header) {
+    if(printf("Content-Type: text/html\n"
+              "%s\n"
+              "\n", dcgi_cookie_header()) < 0)
+      fatal(errno, "error writing to stdout");
+  }
   if(mx_expand_file(found, sink_stdio("stdout", stdout), 0) == -1
      || fflush(stdout) < 0)
     fatal(errno, "error writing to stdout");
   if(mx_expand_file(found, sink_stdio("stdout", stdout), 0) == -1
      || fflush(stdout) < 0)
     fatal(errno, "error writing to stdout");
@@ -327,18 +584,14 @@ void dcgi_action(const char *action) {
     actions[n].handler();
   else {
     /* Just expand the template */
     actions[n].handler();
   else {
     /* Just expand the template */
-    if(printf("Content-Type: text/html\n"
-              "%s\n"
-              "\n", dcgi_cookie_header()) < 0)
-      fatal(errno, "error writing to stdout");
-    dcgi_expand(action);
+    dcgi_expand(action, 1/*header*/);
   }
 }
 
 /** @brief Generate an error page */
 void dcgi_error(const char *key) {
   dcgi_error_string = xstrdup(key);
   }
 }
 
 /** @brief Generate an error page */
 void dcgi_error(const char *key) {
   dcgi_error_string = xstrdup(key);
-  dcgi_expand("error");
+  dcgi_expand("error", 1);
 }
 
 /*
 }
 
 /*
index c38ee6c1e383d77fd76752434670d13cde8cc09f..9a510c8e18030ea0868224de5971539250d6f4d6 100644 (file)
@@ -159,219 +159,6 @@ static void act_prefs(cgi_sink *output, dcgi_state *ds) {
   cgi_body(output->sink);
   expand(output, "prefs", ds);
 }
   cgi_body(output->sink);
   expand(output, "prefs", ds);
 }
-
-static void act_login(cgi_sink *output,
-                     dcgi_state *ds) {
-  const char *username, *password, *back;
-  disorder_client *c;
-
-  username = cgi_get("username");
-  password = cgi_get("password");
-  if(!username || !password
-     || !strcmp(username, "guest")/*bodge to avoid guest cookies*/) {
-    /* We're just visiting the login page */
-    expand_template(ds, output, "login");
-    return;
-  }
-  /* We'll need a new connection as we are going to stop being guest */
-  c = disorder_new(0);
-  if(disorder_connect_user(c, username, password)) {
-    cgi_set_option("error", "loginfailed");
-    expand_template(ds, output, "login");
-    return;
-  }
-  if(disorder_make_cookie(c, &login_cookie)) {
-    cgi_set_option("error", "cookiefailed");
-    expand_template(ds, output, "login");
-    return;
-  }
-  /* Use the new connection henceforth */
-  ds->g->client = c;
-  ds->g->flags = 0;
-  /* We have a new cookie */
-  header_cookie(output->sink);
-  cgi_set_option("status", "loginok");
-  if((back = cgi_get("back")) && *back)
-    /* Redirect back to somewhere or other */
-    redirect(output->sink);
-  else
-    /* Stick to the login page */
-    expand_template(ds, output, "login");
-}
-
-static void act_logout(cgi_sink *output,
-                      dcgi_state *ds) {
-  disorder_revoke(ds->g->client);
-  login_cookie = 0;
-  /* 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, *password2, *email;
-  char *confirm, *content_type;
-  const char *text, *encoding, *charset;
-
-  username = cgi_get("username");
-  password = cgi_get("password1");
-  password2 = cgi_get("password2");
-  email = cgi_get("email");
-
-  if(!username || !*username) {
-    cgi_set_option("error", "nousername");
-    expand_template(ds, output, "login");
-    return;
-  }
-  if(!password || !*password) {
-    cgi_set_option("error", "nopassword");
-    expand_template(ds, output, "login");
-    return;
-  }
-  if(!password2 || !*password2 || strcmp(password, password2)) {
-    cgi_set_option("error", "passwordmismatch");
-    expand_template(ds, output, "login");
-    return;
-  }
-  if(!email || !*email) {
-    cgi_set_option("error", "noemail");
-    expand_template(ds, output, "login");
-    return;
-  }
-  /* We could well do better address validation but for now we'll just do the
-   * minimum */
-  if(!strchr(email, '@')) {
-    cgi_set_option("error", "bademail");
-    expand_template(ds, output, "login");
-    return;
-  }
-  if(disorder_register(ds->g->client, username, password, email, &confirm)) {
-    cgi_set_option("error", "cannotregister");
-    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("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");
-  }
-  /* Confirm our registration */
-  if(disorder_confirm(ds->g->client, confirmation)) {
-    cgi_set_option("error", "badconfirm");
-    expand_template(ds, output, "login");
-  }
-  /* Get a cookie */
-  if(disorder_make_cookie(ds->g->client, &login_cookie)) {
-    cgi_set_option("error", "cookiefailed");
-    expand_template(ds, output, "login");
-    return;
-  }
-  /* Discard any cached data JIC */
-  ds->g->flags = 0;
-  /* We have a new cookie */
-  header_cookie(output->sink);
-  cgi_set_option("status", "confirmed");
-  expand_template(ds, output, "login");
-}
-
-static void act_edituser(cgi_sink *output,
-                        dcgi_state *ds) {
-  const char *email = cgi_get("email"), *password = cgi_get("changepassword1");
-  const char *password2 = cgi_get("changepassword2");
-  int newpassword = 0;
-  disorder_client *c;
-
-  if((password && *password) || (password && *password2)) {
-    if(!password || !password2 || strcmp(password, password2)) {
-      cgi_set_option("error", "passwordmismatch");
-      expand_template(ds, output, "login");
-      return;
-    }
-  } else
-    password = password2 = 0;
-  
-  if(email) {
-    if(disorder_edituser(ds->g->client, disorder_user(ds->g->client),
-                        "email", email)) {
-      cgi_set_option("error", "badedit");
-      expand_template(ds, output, "login");
-      return;
-    }
-  }
-  if(password) {
-    if(disorder_edituser(ds->g->client, disorder_user(ds->g->client),
-                        "password", password)) {
-      cgi_set_option("error", "badedit");
-      expand_template(ds, output, "login");
-      return;
-    }
-    newpassword = 1;
-  }
-  if(newpassword) {
-    login_cookie = 0;                  /* it'll be invalid now */
-    /* This is a bit duplicative of act_login() */
-    c = disorder_new(0);
-    if(disorder_connect_user(c, disorder_user(ds->g->client), password)) {
-      cgi_set_option("error", "loginfailed");
-      expand_template(ds, output, "login");
-      return;
-    }
-    if(disorder_make_cookie(c, &login_cookie)) {
-      cgi_set_option("error", "cookiefailed");
-      expand_template(ds, output, "login");
-      return;
-    }
-    /* Use the new connection henceforth */
-    ds->g->client = c;
-    ds->g->flags = 0;
-    /* We have a new cookie */
-    header_cookie(output->sink);
-  }
-  cgi_set_option("status", "edited");
-  expand_template(ds, output, "login");  
-}
-
-static void act_reminder(cgi_sink *output,
-                        dcgi_state *ds) {
-  const char *const username = cgi_get("username");
-
-  if(!username || !*username) {
-    cgi_set_option("error", "nousername");
-    expand_template(ds, output, "login");
-    return;
-  }
-  if(disorder_reminder(ds->g->client, username)) {
-    cgi_set_option("error", "reminderfailed");
-    expand_template(ds, output, "login");
-    return;
-  }
-  cgi_set_option("status", "reminded");
-  expand_template(ds, output, "login");  
-}
-
 /* expansions *****************************************************************/
 
 static void exp_label(int attribute((unused)) nargs,
 /* expansions *****************************************************************/
 
 static void exp_label(int attribute((unused)) nargs,
index 93e4e2fe1c5c9e4f8c06f491506d8295c813a3c1..9da897591fc701eaa841e484f009d9960bdc2eca 100644 (file)
 #include "inputline.h"
 #include "split.h"
 #include "mime.h"
 #include "inputline.h"
 #include "split.h"
 #include "mime.h"
+#include "sendmail.h"
 
 extern disorder_client *dcgi_client;
 extern char *dcgi_cookie;
 
 extern disorder_client *dcgi_client;
 extern char *dcgi_cookie;
-extern char *dcgi_error_string;
+extern const char *dcgi_error_string;
+extern const char *dcgi_status_string;
 
 /** @brief Entry in a list of tracks or directories */
 struct dcgi_entry {
 
 /** @brief Entry in a list of tracks or directories */
 struct dcgi_entry {
@@ -73,7 +75,7 @@ struct dcgi_entry {
 /** @brief Compare two @ref entry objects */
 int dcgi_compare_entry(const void *a, const void *b);
 
 /** @brief Compare two @ref entry objects */
 int dcgi_compare_entry(const void *a, const void *b);
 
-void dcgi_expand(const char *name);
+void dcgi_expand(const char *name, int header);
 void dcgi_action(const char *action);
 void dcgi_error(const char *key);
 void dcgi_login(void);
 void dcgi_action(const char *action);
 void dcgi_error(const char *key);
 void dcgi_login(void);
index a08f0ed767a77ff34c0f2f99d43362da318e44a8..807f398ac909dcd05de2403291e8c698185127b5 100644 (file)
@@ -1,3 +1,4 @@
+
 /*
  * This file is part of DisOrder.
  * Copyright (C) 2004-2008 Richard Kettlewell
 /*
  * This file is part of DisOrder.
  * Copyright (C) 2004-2008 Richard Kettlewell
 #include "disorder-cgi.h"
 
 /** @brief For error template */
 #include "disorder-cgi.h"
 
 /** @brief For error template */
-char *dcgi_error_string;
+const char *dcgi_error_string;
 
 /** @brief For login template */
 
 /** @brief For login template */
-char *dcgi_status_string;
+const char *dcgi_status_string;
 
 /** @brief Return @p i as a string */
 static const char *make_index(int i) {
 
 /** @brief Return @p i as a string */
 static const char *make_index(int i) {
index 7e60d55fd48da86056d96e64490dff77ae689d31..a0d55492fa0bdaadb6cc117ab3fc853bd74b00f8 100644 (file)
@@ -24,7 +24,7 @@ USA
  </head>
  <body>
 @stdmenu{choose}
  </head>
  <body>
 @stdmenu{choose}
-   <h1>@label:choose.title@</h1>
+   <h1>@label{choose.title}</h1>
   
   @if{@eq{@label{menu.choosewhich}}{choosealpha}}
      {
   
   @if{@eq{@label{menu.choosewhich}}{choosealpha}}
      {
@@ -97,7 +97,7 @@ USA
        <button class=search name=submit type=submit>
          @label{search.search}
        </button>
        <button class=search name=submit type=submit>
          @label{search.search}
        </button>
-       <input name=action type=hidden value=search>
+       <input name=action type=hidden value=choose>
      </p>
    </form>
 
      </p>
    </form>
 
@@ -117,8 +117,8 @@ USA
     <tr class=@parity>
      <td class=artist>@martist{search}{@track}</td>
      <td class=album>@malbum{search}{@track}</td>
     <tr class=@parity>
      <td class=artist>@martist{search}{@track}</td>
      <td class=album>@malbum{search}{@track}</td>
-     <td class=title>@mtitle{search}{@track}</td>
-     <td class=length>@length{@id}</td>
+     <td class=title>@mtitleplay{search}{@track}</td>
+     <td class=length>@length{@track}</td>
      @right{prefs}{
      <td class=imgbutton>
       <a class=imgbutton
      @right{prefs}{
      <td class=imgbutton>
       <a class=imgbutton
@@ -152,16 +152,16 @@ USA
 
    <div class=files>
     <div class=filesdirectories>
 
    <div class=files>
     <div class=filesdirectories>
-     @dirs{@arg{dir}}{@arg{re}}{
+     @tracks{@arg{dir}}{@arg{re}}{
       <p class=entry>
 @define{sometracks}{template}{@template}@#
       <p class=entry>
 @define{sometracks}{template}{@template}@#
-       @rights{prefs}{
+       @right{prefs}{
         <a class=imgprefs
            href="@url?action=prefs&#38;0_file=@urlquote{@resolve{@track}}">
          <img class=button
               src="@image{edit}"
         <a class=imgprefs
            href="@url?action=prefs&#38;0_file=@urlquote{@resolve{@track}}">
          <img class=button
               src="@image{edit}"
-              title="@label:choose.prefsverbose@"
-              alt="@label:choose.prefs@">
+              title="@label{choose.prefsverbose}"
+              alt="@label{choose.prefs}">
         </a>
        }@#
        <a href="@url?action=play&#38;file=@urlquote{@track}&#38;back=@urlquote{@thisurl}"
         </a>
        }@#
        <a href="@url?action=play&#38;file=@urlquote{@track}&#38;back=@urlquote{@thisurl}"
@@ -180,8 +180,8 @@ USA
            href="@url?action=prefs&#38;dir=@urlquote{@arg{dir}}">
          <img class=button
               src="@image{edit}"
            href="@url?action=prefs&#38;dir=@urlquote{@arg{dir}}">
          <img class=button
               src="@image{edit}"
-              title="@label:choose.allprefsverbose@"
-              alt="@label:choose.allprefs@">
+              title="@label{choose.allprefsverbose}"
+              alt="@label{choose.allprefs}">
         </a>}
         <a class=button
            href="@url?action=play&#38;dir=@urlquote{@arg{dir}}"&#38;back=@urlquote{@thisurl}">
         </a>}
         <a class=button
            href="@url?action=play&#38;dir=@urlquote{@arg{dir}}"&#38;back=@urlquote{@thisurl}">
index a1697c150ce335433f9ca2bffdcb6b5ea584e74a..578297506de52507bb63f306c2b2986bd8950322 100644 (file)
@@ -60,19 +60,19 @@ table {
 
 /* playing, recent and new classes correspond to the tables in playing.html,
  * recent.html and new.html */
 
 /* playing, recent and new classes correspond to the tables in playing.html,
  * recent.html and new.html */
-table.playing, table.recent, table.new {
+table.playing, table.recent, table.new, table.search {
   width: 100%                          /* use full screen width */
 }
 
   width: 100%                          /* use full screen width */
 }
 
-table.playing th, table.recent th, table.new th {
+table.playing th, table.recent th, table.new th, table.search th {
   text-align: left             /* titles should be left-aligned */
 }
 
   text-align: left             /* titles should be left-aligned */
 }
 
-table.playing td, table.recent td, table.new td {
+table.playing td, table.recent td, table.new td, table.search td {
   vertical-align: middle        /* centre cell contents vertically */
 }
 
   vertical-align: middle        /* centre cell contents vertically */
 }
 
-table.playing a, table.recent a, table.new a {
+table.playing a, table.recent a, table.new a, table.search a {
   color: black
 }
 
   color: black
 }
 
index c3b7ed8deab98a1afd562571b6e507c2e656fe99..495c29a978f772385bd3bac0bbeac14f846aa15a 100644 (file)
@@ -110,8 +110,8 @@ and then redefines macros as desired.
 @define {martist} {what track}
         {@right{play}
                {<a class=directory
 @define {martist} {what track}
         {@right{play}
                {<a class=directory
-                   href="@url?action=choose&amp;directory=@urlquote{@dirname{@dirname{@track}}}"
-                   title="@label{@what.artistverbose}">@part{@track}{artist}{short}</a>}
+                   href="@url?action=choose&amp;dir=@urlquote{@dirname{@dirname{@track}}}"
+                   title="@label{playing.artistverbose}">@part{@track}{artist}{short}</a>}
                {<span class=directory
                       title="@part{@track}{artist}">@part{@track}{artist}{short}</span>}}
 
                {<span class=directory
                       title="@part{@track}{artist}">@part{@track}{artist}{short}</span>}}
 
@@ -121,8 +121,8 @@ and then redefines macros as desired.
 @define {malbum} {what track}
         {@right{play}
                {<a class=directory
 @define {malbum} {what track}
         {@right{play}
                {<a class=directory
-                   href="@url?action=choose&amp;directory=@urlquote{@dirname{@track}}"
-                   title="@label{@what.albumverbose}">@part{@track}{album}{short}</a>}
+                   href="@url?action=choose&amp;dir=@urlquote{@dirname{@track}}"
+                   title="@label{playing.albumverbose}">@part{@track}{album}{short}</a>}
                {<span class=directory
                       title="@part{@track}{album}">@part{@track}{album}{short}</span>}}
 
                {<span class=directory
                       title="@part{@track}{album}">@part{@track}{album}{short}</span>}}
 
@@ -132,6 +132,12 @@ and then redefines macros as desired.
 @define {mtitle} {what track}
         {<span title="@part{@track}{title}">@part{@track}{title}{short}</span>}
 
 @define {mtitle} {what track}
         {<span title="@part{@track}{title}">@part{@track}{title}{short}</span>}
 
+@# As @mtitle but make a link to play the track
+@#  @what is the section
+@#  @track is the track name
+@define {mtitleplay} {what track}
+        {<a title="@part{@track}{title}" href="@url?action=play&#38;file=@urlquote{@track}&#38;back=@urlquote{@thisurl}">@part{@track}{title}{short}</a>}
+
 @# Expand to the remove/scratch entry for @id
 @#  @what is the section
 @#  @id is the track ID
 @# Expand to the remove/scratch entry for @id
 @#  @what is the section
 @#  @id is the track ID
index e017a740fe664720cb5bd6bacad53e693e98a7fc..6611f086e9262319e7904e80d8020779b46423ad 100644 (file)
@@ -41,8 +41,8 @@ USA
     <tr class=@parity>
      <td class=artist>@martist{new}{@track}</td>
      <td class=album>@malbum{new}{@track}</td>
     <tr class=@parity>
      <td class=artist>@martist{new}{@track}</td>
      <td class=album>@malbum{new}{@track}</td>
-     <td class=title>@mtitle{new}{@track}</td>
-     <td class=length>@length{@id}</td>
+     <td class=title>@mtitleplay{new}{@track}</td>
+     <td class=length>@length{@track}</td>
      @right{prefs}{
      <td class=imgbutton>
       <a class=imgbutton
      @right{prefs}{
      <td class=imgbutton>
       <a class=imgbutton
index eabcb4f832e62c11f5ff9dae4af9f8d39b61f9e0..ee9d8cc09e32dc81e4d1e86558025bc9fbceed59 100644 (file)
@@ -71,7 +71,7 @@ label volume.upverbose        "Increase volume"
 # Amount to increase/reduce volume by
 label  volume.resolution       4
 
 # Amount to increase/reduce volume by
 label  volume.resolution       4
 
-# Long text for linsk to album/artist
+# Long text for links to album/artist
 label  playing.artistverbose   "More tracks by this artist"
 label  playing.albumverbose    "More tracks from this album"
 
 label  playing.artistverbose   "More tracks by this artist"
 label  playing.albumverbose    "More tracks from this album"
 
@@ -184,6 +184,7 @@ label       error.connect           "Cannot connect to server."
 # Error messages for login.html
 label  error.loginfailed       "Incorrect username and/or password."
 label  error.cookiefailed      "Cannot create login cookie."
 # Error messages for login.html
 label  error.loginfailed       "Incorrect username and/or password."
 label  error.cookiefailed      "Cannot create login cookie."
+label  error.revokefailed      "Cannot revoke login cookie."
 label  error.nousername        "No username specified."
 label  error.nopassword        "No password specified."
 label  error.passwordmismatch  "Passwords do not match."
 label  error.nousername        "No username specified."
 label  error.nopassword        "No password specified."
 label  error.passwordmismatch  "Passwords do not match."