2 * This file is part of DisOrder.
3 * Copyright (C) 2004-2008 Richard Kettlewell
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
27 /** @brief Login cookie */
30 /* 'playing' and 'manage' just add a Refresh: header */
31 static void act_playing(void) {
32 long refresh
= config
->refresh
;
37 lookups(DC_PLAYING
|DC_QUEUE
|DC_ENABLED
|DC_RANDOM_ENABLED
);
39 && playing
->state
== playing_started
/* i.e. not paused */
40 && !disorder_length(client
, playing
->track
, &length
)
42 && playing
->sofar
>= 0) {
43 /* Try to put the next refresh at the start of the next track. */
45 fin
= now
+ length
- playing
->sofar
+ config
->gap
;
46 if(now
+ refresh
> fin
)
49 if(queue
&& queue
->state
== playing_isscratch
) {
50 /* next track is a scratch, don't leave more than the inter-track gap */
51 if(refresh
> config
->gap
)
52 refresh
= config
->gap
;
56 && queue
->state
!= playing_random
)
59 /* no track playing but playing is enabled and there is something coming
60 * up, must be in a gap */
61 if(refresh
> config
->gap
)
62 refresh
= config
->gap
;
64 if((action
= cgi_get("action")))
65 url
= cgi_makeurl(config
->url
, "action", action
, (char *)0);
68 if(printf("Content-Type: text/html\n"
69 "Refresh: %ld;url=%s\n"
73 fatal(errno
, "error writing to stdout");
74 disorder_cgi_expand(action ? action
: "playing");
77 /** @brief Table of actions */
78 static const struct action
{
79 /** @brief Action name */
81 /** @brief Action handler */
82 void (*handler
)(void);
84 { "confirm", act_confirm
},
85 { "disable", act_disable
},
86 { "edituser", act_edituser
},
87 { "enable", act_enable
},
88 { "login", act_login
},
89 { "logout", act_logout
},
90 { "manage", act_playing
},
92 { "pause", act_pause
},
94 { "playing", act_playing
},
95 { "prefs", act_prefs
},
96 { "random-disable", act_random_disable
},
97 { "random-enable", act_random_enable
},
98 { "register", act_register
},
99 { "reminder", act_reminder
},
100 { "remove", act_remove
},
101 { "resume", act_resume
},
102 { "scratch", act_scratch
},
103 { "volume", act_volume
},
106 /** @brief Expand a template
107 * @param name Base name of template, or NULL to consult CGI args
109 void disorder_cgi_expand(const char *name
) {
112 /* For unknown actions check that they aren't evil */
113 for(p
= name
; *p
&& isalnum((unsigned char)*p
); ++p
)
116 fatal(0, "invalid action name '%s'", action
);
117 byte_xasprintf((char **)&p
, "%s.tmpl", action
);
118 if(mx_expand_file(p
, sink_stdio(stdout
), 0) == -1
119 || fflush(stdout
) < 0)
120 fatal(errno
, "error writing to stdout");
123 /** @brief Execute a web action
124 * @param action Action to perform, or NULL to consult CGI args
126 * If no recognized action is specified then 'playing' is assumed.
128 void disorder_cgi_action(const char *action
) {
132 /* Consult CGI args if caller had no view */
134 action
= cgi_get("action");
135 /* Pick a default if nobody cares at all */
137 /* We allow URLs which are just c=... in order to keep confirmation URLs,
138 * which are user-facing, as short as possible. Actually we could lose the
145 if((n
= TABLE_FIND(actions
, struct action
, name
, action
)) >= 0)
146 /* Its a known action */
147 actions
[n
].handler();
149 /* Just expand the template */
150 if(printf("Content-Type: text/html\n"
153 fatal(errno
, "error writing to stdout");
154 disorder_cgi_expand(action
);
158 /** @brief Generate an error page */
159 void disorder_cgi_error(const char *msg
, ...) {
163 byte_xvasprintf(&error_string
, msg
, ap
);
165 disorder_cgi_expand("error");
168 /** @brief Log in as the current user or guest if none */
169 void disorder_cgi_login(dcgi_state
*ds
, struct sink
*output
) {
171 disorder_macros_reset();
173 if(disorder_connect_cookie(client
, login_cookie
)) {
174 disorder_cgi_error("Cannot connect to server");
177 /* If there was a cookie but it went bad, we forget it */
178 if(login_cookie
&& !strcmp(disorder_user(>client
), "guest"))