Almost compiles, will not work though
[disorder] / server / actions.c
index 2fa3f8a..341f881 100644 (file)
 #include <config.h>
 #include "types.h"
 
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <time.h>
+#include <ctype.h>
+#include <stddef.h>
+
+#include "hash.h"
+#include "table.h"
+#include "client.h"
+#include "rights.h"
+#include "mem.h"
+#include "sink.h"
+#include "vector.h"
+#include "printf.h"
 #include "actions.h"
-#include "lookups.h"
+#include "lookup.h"
+#include "url.h"
+#include "configuration.h"
+#include "cgi.h"
+#include "log.h"
+#include "queue.h"
+#include "macros.h"
+#include "macros-disorder.h"
 
 /** @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;
   long length;
   time_t now, fin;
   char *url;
+  const char *action;
 
-  lookups(DC_PLAYING|DC_QUEUE|DC_ENABLED|DC_RANDOM_ENABLED);
+  lookup(DC_PLAYING|DC_QUEUE|DC_ENABLED|DC_RANDOM_ENABLED);
   if(playing
      && playing->state == playing_started /* i.e. not paused */
      && !disorder_length(client, playing->track, &length)
@@ -67,9 +144,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");
 }
@@ -81,6 +158,7 @@ static const struct action {
   /** @brief Action handler */
   void (*handler)(void);
 } actions[] = {
+#if 0
   { "confirm", act_confirm },
   { "disable", act_disable },
   { "edituser", act_edituser },
@@ -91,7 +169,9 @@ static const struct action {
   { "move", act_move },
   { "pause", act_pause },
   { "play", act_play },
+#endif
   { "playing", act_playing },
+#if 0
   { "prefs", act_prefs },
   { "random-disable", act_random_disable },
   { "random-enable", act_random_enable },
@@ -101,6 +181,7 @@ static const struct action {
   { "resume", act_resume },
   { "scratch", act_scratch },
   { "volume", act_volume },
+#endif
 };
 
 /** @brief Expand a template
@@ -113,9 +194,9 @@ void disorder_cgi_expand(const char *name) {
   for(p = name; *p && isalnum((unsigned char)*p); ++p)
     ;
   if(*p)
-    fatal(0, "invalid action name '%s'", action);
-  byte_xasprintf((char **)&p, "%s.tmpl", action);
-  if(mx_expand_file(p, sink_stdio(stdout), 0) == -1
+    fatal(0, "invalid action name '%s'", name);
+  byte_xasprintf((char **)&p, "%s.tmpl", name);
+  if(mx_expand_file(p, sink_stdio("stdout", stdout), 0) == -1
      || fflush(stdout) < 0)
     fatal(errno, "error writing to stdout");
 }
@@ -127,7 +208,6 @@ void disorder_cgi_expand(const char *name) {
  */
 void disorder_cgi_action(const char *action) {
   int n;
-  char *s;
 
   /* Consult CGI args if caller had no view */
   if(!action)
@@ -141,6 +221,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 +230,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);
   }
@@ -166,16 +248,16 @@ void disorder_cgi_error(const char *msg, ...) {
 }
 
 /** @brief Log in as the current user or guest if none */
-void disorder_cgi_login(dcgi_state *ds, struct sink *output) {
+void disorder_cgi_login(void) {
   /* Junk old data */
-  disorder_macros_reset();
+  lookup_reset();
   /* Reconnect */
   if(disorder_connect_cookie(client, login_cookie)) {
     disorder_cgi_error("Cannot connect to server");
     exit(0);
   }
   /* If there was a cookie but it went bad, we forget it */
-  if(login_cookie && !strcmp(disorder_user(>client), "guest"))
+  if(login_cookie && !strcmp(disorder_user(client), "guest"))
     login_cookie = 0;
 }