5 #include <sys/socket.h>
19 #include "server-cgi.h"
21 #include "configuration.h"
32 #include "trackname.h"
46 static int compare_entry(const void *a
, const void *b
) {
47 const struct entry
*ea
= a
, *eb
= b
;
49 return compare_tracks(ea
->sort
, eb
->sort
,
50 ea
->display
, eb
->display
,
54 static const char *front_url(void) {
58 /* preserve management interface visibility */
59 if((mgmt
= cgi_get("mgmt")) && !strcmp(mgmt
, "true")) {
60 byte_xasprintf(&url
, "%s?mgmt=true", config
->url
);
66 static void redirect(struct sink
*output
) {
69 back
= cgi_get("back");
70 cgi_header(output
, "Location", back
&& *back ? back
: front_url());
71 header_cookie(output
);
75 static void expand_template(dcgi_state
*ds
, cgi_sink
*output
,
77 cgi_header(output
->sink
, "Content-Type", "text/html");
78 header_cookie(output
->sink
);
79 cgi_body(output
->sink
);
80 expand(output
, action
, ds
);
83 /* actions ********************************************************************/
85 static void act_prefs_errors(const char *msg
,
86 void attribute((unused
)) *u
) {
87 fatal(0, "error splitting parts list: %s", msg
);
90 static const char *numbered_arg(const char *argname
, int numfile
) {
93 byte_xasprintf(&fullname
, "%d_%s", numfile
, argname
);
94 return cgi_get(fullname
);
97 static void process_prefs(dcgi_state
*ds
, int numfile
) {
98 const char *file
, *name
, *value
, *part
, *parts
, *current
, *context
;
101 if(!(file
= numbered_arg("file", numfile
)))
102 /* The first file doesn't need numbering. */
103 if(numfile
> 0 || !(file
= cgi_get("file")))
105 if((parts
= numbered_arg("parts", numfile
))
106 || (parts
= cgi_get("parts"))) {
107 /* Default context is display. Other contexts not actually tested. */
108 if(!(context
= numbered_arg("context", numfile
))) context
= "display";
109 partslist
= split(parts
, 0, 0, act_prefs_errors
, 0);
110 while((part
= *partslist
++)) {
111 if(!(value
= numbered_arg(part
, numfile
)))
113 /* If it's already right (whether regexps or db) don't change anything,
114 * so we don't fill the database up with rubbish. */
115 if(disorder_part(ds
->g
->client
, (char **)¤t
,
116 file
, context
, part
))
117 fatal(0, "disorder_part() failed");
118 if(!strcmp(current
, value
))
120 byte_xasprintf((char **)&name
, "trackname_%s_%s", context
, part
);
121 disorder_set(ds
->g
->client
, file
, name
, value
);
123 if((value
= numbered_arg("random", numfile
)))
124 disorder_unset(ds
->g
->client
, file
, "pick_at_random");
126 disorder_set(ds
->g
->client
, file
, "pick_at_random", "0");
127 if((value
= numbered_arg("tags", numfile
))) {
129 disorder_unset(ds
->g
->client
, file
, "tags");
131 disorder_set(ds
->g
->client
, file
, "tags", value
);
133 if((value
= numbered_arg("weight", numfile
))) {
134 if(!*value
|| !strcmp(value
, "90000"))
135 disorder_unset(ds
->g
->client
, file
, "weight");
137 disorder_set(ds
->g
->client
, file
, "weight", value
);
139 } else if((name
= cgi_get("name"))) {
140 /* Raw preferences. Not well supported in the templates at the moment. */
141 value
= cgi_get("value");
143 disorder_set(ds
->g
->client
, file
, name
, value
);
145 disorder_unset(ds
->g
->client
, file
, name
);
149 static void act_prefs(cgi_sink
*output
, dcgi_state
*ds
) {
153 if((files
= cgi_get("files"))) nfiles
= atoi(files
);
155 for(numfile
= 0; numfile
< nfiles
; ++numfile
)
156 process_prefs(ds
, numfile
);
157 cgi_header(output
->sink
, "Content-Type", "text/html");
158 header_cookie(output
->sink
);
159 cgi_body(output
->sink
);
160 expand(output
, "prefs", ds
);
162 /* expansions *****************************************************************/
164 static void exp_label(int attribute((unused
)) nargs
,
167 void attribute((unused
)) *u
) {
168 cgi_output(output
, "%s", cgi_label(args
[0]));
171 struct trackinfo_state
{
173 const struct queue_entry
*q
;
183 static int compare_result(const void *a
, const void *b
) {
184 const struct result
*ra
= a
, *rb
= b
;
187 if(!(c
= strcmp(ra
->sort
, rb
->sort
)))
188 c
= strcmp(ra
->track
, rb
->track
);
192 static void exp_stats(int attribute((unused
)) nargs
,
193 char attribute((unused
)) **args
,
199 cgi_opentag(output
->sink
, "pre", "class", "stats", (char *)0);
200 if(!disorder_stats(ds
->g
->client
, &v
, 0)) {
202 cgi_output(output
, "%s\n", *v
++);
204 cgi_closetag(output
->sink
, "pre");
207 static char *expandarg(const char *arg
, dcgi_state
*ds
) {
213 output
.sink
= sink_dynstr(&d
);
214 expandstring(&output
, arg
, ds
);
215 dynstr_terminate(&d
);
219 static void exp_navigate(int attribute((unused
)) nargs
,
225 const char *path
= expandarg(args
[0], ds
);
230 memset(&substate
, 0, sizeof substate
);
232 ptr
= path
+ 1; /* skip root */
234 substate
.nav_path
= path
;
237 while(*ptr
&& *ptr
!= '/')
239 substate
.last
= !*ptr
;
240 substate
.nav_len
= ptr
- path
;
241 substate
.nav_dirlen
= dirlen
;
242 expandstring(output
, args
[1], &substate
);
243 dirlen
= substate
.nav_len
;
250 static void exp_fullname(int attribute((unused
)) nargs
,
251 char attribute((unused
)) **args
,
255 cgi_output(output
, "%.*s", ds
->nav_len
, ds
->nav_path
);