chiark / gitweb /
redirect()
authorRichard Kettlewell <rjk@greenend.org.uk>
Sat, 10 May 2008 10:31:16 +0000 (11:31 +0100)
committerRichard Kettlewell <rjk@greenend.org.uk>
Sat, 10 May 2008 10:31:16 +0000 (11:31 +0100)
lib/cgi.c
lib/cgi.h
server/actions.c
server/dcgi.c

index 1c1154d..9e455bf 100644 (file)
--- a/lib/cgi.c
+++ b/lib/cgi.c
@@ -207,6 +207,12 @@ const char *cgi_get(const char *name) {
   return v ? *v : NULL;
 }
 
+/** @brief Set a CGI argument */
+void cgi_set(const char *name, const char *value) {
+  value = xstrdup(value);
+  hash_add(cgi_args, name, &value, HASH_INSERT_OR_REPLACE);
+}
+
 /** @brief Add SGML-style quoting
  * @param src String to quote (UTF-8)
  * @return Quoted string
index a9944e4..a26ee14 100644 (file)
--- a/lib/cgi.h
+++ b/lib/cgi.h
@@ -28,6 +28,7 @@ struct sink;
 
 void cgi_init(void);
 const char *cgi_get(const char *name);
+void cgi_set(const char *name, const char *value)
 char *cgi_sgmlquote(const char *src);
 void cgi_attr(struct sink *output, const char *name, const char *value);
 void cgi_opentag(struct sink *output, const char *name, ...);
index 2fa3f8a..2bdb8c4 100644 (file)
 /** @brief Login cookie */
 char *login_cookie;
 
+/** @brief Return a Cookie: header */
+static char *cookie(void) {
+  struct dynstr d[1];
+  struct url u;
+  char *s;
+
+  memset(&u, 0, sizeof u);
+  dynstr_init(d);
+  parse_url(config->url, &u);
+  if(login_cookie) {
+    dynstr_append_string(d, "disorder=");
+    dynstr_append_string(d, login_cookie);
+  } else {
+    /* Force browser to discard cookie */
+    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, ";Version=1;Path=");
+    /* Formally we are supposed to quote the path, since it invariably has a
+     * slash in it.  However Safari does not parse quoted paths correctly, so
+     * this won't work.  Fortunately nothing else seems to care about proper
+     * quoting of paths, so in practice we get with it.  (See also
+     * parse_cookie() where we are liberal about cookie paths on the way back
+     * in.) */
+    dynstr_append_string(d, u.path);
+  }
+  dynstr_terminate(d);
+  byte_xasprintf(&s, "Set-Cookie: %s", d->vec);
+  return s;
+}
+
+/** @brief Redirect to some other action or URL */
+static void redirect(const char *url) {
+  /* By default use the 'back' argument */
+  if(!url)
+    url = cgi_get("back")
+  if(url) {
+    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 back= is not set just go back to the front page */
+    url = config->url;
+  }
+  if(printf("Location: %s\n"
+            "%s\n"
+            "\n", url, cookie()) < 0)
+    fatal(errno, "error writing to stdout");
+}
+
 /* 'playing' and 'manage' just add a Refresh: header */
 static void act_playing(void) {
   long refresh = config->refresh;
@@ -67,9 +121,9 @@ static void act_playing(void) {
     url = config->url;
   if(printf("Content-Type: text/html\n"
             "Refresh: %ld;url=%s\n"
-            /* TODO cookie */
+            "%s\n"
             "\n",
-            refresh, url) < 0)
+            refresh, url, cookie()) < 0)
     fatal(errno, "error writing to stdout");
   disorder_cgi_expand(action ? action : "playing");
 }
@@ -141,6 +195,8 @@ void disorder_cgi_action(const char *action) {
       action = "confirm";
     else
       action = "playing";
+    /* Make sure 'action' is always set */
+    cgi_set("action", action);
   }
   if((n = TABLE_FIND(actions, struct action, name, action)) >= 0)
     /* Its a known action */
@@ -148,8 +204,8 @@ void disorder_cgi_action(const char *action) {
   else {
     /* Just expand the template */
     if(printf("Content-Type: text/html\n"
-              /* TODO cookie */
-              "\n") < 0)
+              "%s\n"
+              "\n", cookie()) < 0)
       fatal(errno, "error writing to stdout");
     disorder_cgi_expand(action);
   }
index 65f0b33..1ba638f 100644 (file)
@@ -63,38 +63,6 @@ static const char *front_url(void) {
   return config->url;
 }
 
-static void header_cookie(struct sink *output) {
-  struct dynstr d[1];
-  struct url u;
-
-  memset(&u, 0, sizeof u);
-  dynstr_init(d);
-  parse_url(config->url, &u);
-  if(login_cookie) {
-    dynstr_append_string(d, "disorder=");
-    dynstr_append_string(d, login_cookie);
-  } else {
-    /* Force browser to discard cookie */
-    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, ";Version=1;Path=");
-    /* Formally we are supposed to quote the path, since it invariably has a
-     * slash in it.  However Safari does not parse quoted paths correctly, so
-     * this won't work.  Fortunately nothing else seems to care about proper
-     * quoting of paths, so in practice we get with it.  (See also
-     * parse_cookie() where we are liberal about cookie paths on the way back
-     * in.) */
-    dynstr_append_string(d, u.path);
-  }
-  dynstr_terminate(d);
-  cgi_header(output, "Set-Cookie", d->vec);
-}
-
 static void redirect(struct sink *output) {
   const char *back;
 
@@ -170,49 +138,6 @@ static void act_scratch(cgi_sink *output,
   redirect(output->sink);
 }
 
-static void act_playing(cgi_sink *output, dcgi_state *ds) {
-  char r[1024];
-  long refresh = config->refresh, length;
-  time_t now, fin;
-  int random_enabled = 0;
-  int enabled = 0;
-
-  lookups(ds, DC_PLAYING|DC_QUEUE);
-  cgi_header(output->sink, "Content-Type", "text/html");
-  disorder_random_enabled(ds->g->client, &random_enabled);
-  disorder_enabled(ds->g->client, &enabled);
-  if(ds->g->playing
-     && ds->g->playing->state == playing_started /* i.e. not paused */
-     && !disorder_length(ds->g->client, ds->g->playing->track, &length)
-     && length
-     && ds->g->playing->sofar >= 0) {
-    /* Try to put the next refresh at the start of the next track. */
-    time(&now);
-    fin = now + length - ds->g->playing->sofar + config->gap;
-    if(now + refresh > fin)
-      refresh = fin - now;
-  }
-  if(ds->g->queue && ds->g->queue->state == playing_isscratch) {
-    /* next track is a scratch, don't leave more than the inter-track gap */
-    if(refresh > config->gap)
-      refresh = config->gap;
-  }
-  if(!ds->g->playing && ((ds->g->queue
-                         && ds->g->queue->state != playing_random)
-                        || random_enabled) && enabled) {
-    /* no track playing but playing is enabled and there is something coming
-     * up, must be in a gap */
-    if(refresh > config->gap)
-      refresh = config->gap;
-  }
-  byte_snprintf(r, sizeof r, "%ld;url=%s", refresh > 0 ? refresh : 1,
-               front_url());
-  cgi_header(output->sink, "Refresh", r);
-  header_cookie(output->sink);
-  cgi_body(output->sink);
-  expand(output, "playing", ds);
-}
-
 static void act_play(cgi_sink *output,
                     dcgi_state *ds) {
   const char *track, *dir;