From: Richard Kettlewell Date: Sat, 10 May 2008 10:31:16 +0000 (+0100) Subject: redirect() X-Git-Tag: 4.0~76^2~43 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/disorder/commitdiff_plain/5a7df0480aa9e958e612b2da9addd589d404fd95 redirect() --- diff --git a/lib/cgi.c b/lib/cgi.c index 1c1154d..9e455bf 100644 --- 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 diff --git a/lib/cgi.h b/lib/cgi.h index a9944e4..a26ee14 100644 --- 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, ...); diff --git a/server/actions.c b/server/actions.c index 2fa3f8a..2bdb8c4 100644 --- a/server/actions.c +++ b/server/actions.c @@ -27,6 +27,60 @@ /** @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); } diff --git a/server/dcgi.c b/server/dcgi.c index 65f0b33..1ba638f 100644 --- a/server/dcgi.c +++ b/server/dcgi.c @@ -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;