chiark / gitweb /
Bring CGI docs pretty much up to date
[disorder] / server / dcgi.c
1
2 #include <stdio.h>
3 #include <errno.h>
4 #include <sys/types.h>
5 #include <sys/socket.h>
6 #include <stddef.h>
7 #include <stdlib.h>
8 #include <time.h>
9 #include <unistd.h>
10 #include <string.h>
11 #include <sys/wait.h>
12 #include <pcre.h>
13 #include <assert.h>
14
15 #include "client.h"
16 #include "mem.h"
17 #include "vector.h"
18 #include "sink.h"
19 #include "server-cgi.h"
20 #include "log.h"
21 #include "configuration.h"
22 #include "table.h"
23 #include "queue.h"
24 #include "plugin.h"
25 #include "split.h"
26 #include "wstat.h"
27 #include "kvp.h"
28 #include "syscalls.h"
29 #include "printf.h"
30 #include "regsub.h"
31 #include "defs.h"
32 #include "trackname.h"
33 #include "charset.h"
34 #include "dcgi.h"
35 #include "url.h"
36 #include "mime.h"
37 #include "sendmail.h"
38 #include "base64.h"
39
40 struct entry {
41   const char *path;
42   const char *sort;
43   const char *display;
44 };
45
46 static int compare_entry(const void *a, const void *b) {
47   const struct entry *ea = a, *eb = b;
48
49   return compare_tracks(ea->sort, eb->sort,
50                         ea->display, eb->display,
51                         ea->path, eb->path);
52 }
53
54 static const char *front_url(void) {
55   char *url;
56   const char *mgmt;
57
58   /* preserve management interface visibility */
59   if((mgmt = cgi_get("mgmt")) && !strcmp(mgmt, "true")) {
60     byte_xasprintf(&url, "%s?mgmt=true", config->url);
61     return url;
62   }
63   return config->url;
64 }
65
66 static void redirect(struct sink *output) {
67   const char *back;
68
69   back = cgi_get("back");
70   cgi_header(output, "Location", back && *back ? back : front_url());
71   header_cookie(output);
72   cgi_body(output);
73 }
74
75 static void expand_template(dcgi_state *ds, cgi_sink *output,
76                             const char *action) {
77   cgi_header(output->sink, "Content-Type", "text/html");
78   header_cookie(output->sink);
79   cgi_body(output->sink);
80   expand(output, action, ds);
81 }
82
83 /* expansions *****************************************************************/
84
85 struct trackinfo_state {
86   dcgi_state *ds;
87   const struct queue_entry *q;
88   long length;
89   time_t when;
90 };
91
92 struct result {
93   char *track;
94   const char *sort;
95 };
96
97 static int compare_result(const void *a, const void *b) {
98   const struct result *ra = a, *rb = b;
99   int c;
100
101   if(!(c = strcmp(ra->sort, rb->sort)))
102     c = strcmp(ra->track, rb->track);
103   return c;
104 }
105
106 static void exp_stats(int attribute((unused)) nargs,
107                       char attribute((unused)) **args,
108                       cgi_sink *output,
109                       void *u) {
110   dcgi_state *ds = u;
111   char **v;
112
113   cgi_opentag(output->sink, "pre", "class", "stats", (char *)0);
114   if(!disorder_stats(ds->g->client, &v, 0)) {
115     while(*v)
116       cgi_output(output, "%s\n", *v++);
117   }
118   cgi_closetag(output->sink, "pre");
119 }
120
121 static char *expandarg(const char *arg, dcgi_state *ds) {
122   struct dynstr d;
123   cgi_sink output;
124
125   dynstr_init(&d);
126   output.quote = 0;
127   output.sink = sink_dynstr(&d);
128   expandstring(&output, arg, ds);
129   dynstr_terminate(&d);
130   return d.vec;
131 }
132
133 static void exp_navigate(int attribute((unused)) nargs,
134                          char **args,
135                          cgi_sink *output,
136                          void *u) {
137   dcgi_state *ds = u;
138   dcgi_state substate;
139   const char *path = expandarg(args[0], ds);
140   const char *ptr;
141   int dirlen;
142
143   if(*path) {
144     memset(&substate, 0, sizeof substate);
145     substate.g = ds->g;
146     ptr = path + 1;                     /* skip root */
147     dirlen = 0;
148     substate.nav_path = path;
149     substate.first = 1;
150     while(*ptr) {
151       while(*ptr && *ptr != '/')
152         ++ptr;
153       substate.last = !*ptr;
154       substate.nav_len = ptr - path;
155       substate.nav_dirlen = dirlen;
156       expandstring(output, args[1], &substate);
157       dirlen = substate.nav_len;
158       if(*ptr) ++ptr;
159       substate.first = 0;
160     }
161   }
162 }
163
164 static void exp_fullname(int attribute((unused)) nargs,
165                          char attribute((unused)) **args,
166                          cgi_sink *output,
167                          void *u) {
168   dcgi_state *ds = u;
169   cgi_output(output, "%.*s", ds->nav_len, ds->nav_path);
170 }
171
172 /*
173 Local Variables:
174 c-basic-offset:2
175 comment-column:40
176 fill-column:79
177 End:
178 */