X-Git-Url: https://git.distorted.org.uk/~mdw/disorder/blobdiff_plain/448d3570a4b73f0056c4bb61c5d80e4778a5e0bd..71634563a24f62eedab5fd97fed3c029061acf43:/server/actions.c diff --git a/server/actions.c b/server/actions.c index 2fa3f8a..341f881 100644 --- a/server/actions.c +++ b/server/actions.c @@ -21,20 +21,97 @@ #include #include "types.h" +#include +#include +#include +#include +#include +#include + +#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; }