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
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, ...);
/** @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;
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");
}
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 */
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);
}
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;
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;