2 * $Id: webcit.c 7459 2009-05-17 08:34:33Z dothebart $
4 * This is the main transaction loop of the web service. It maintains a
5 * persistent session to the Citadel server, handling HTTP WebCit requests as
6 * they arrive and presenting a user interface.
18 #include "webserver.h"
21 HashList *StaticFilemappings[4] = {NULL, NULL, NULL, NULL};
25 for ( a = 0; a < 9; ++a)
27 extract_token(index[a], ChrPtr(ReqLine), a + 1, '/', sizes[a]);
28 if (strstr(index[a], "?")) *strstr(index[a], "?") = 0;
29 if (strstr(index[a], "&")) *strstr(index[a], "&") = 0;
30 if (strstr(index[a], " ")) *strstr(index[a], " ") = 0;
31 if ((index[a][0] == '.') && (index[a][1] == '.'))
33 if (index[a][0] == '\0')
42 /** Figure out the action * /
44 sizes[0] = sizeof action;
48 sizes[a] = sizeof arg[a-1];
54 /* Static content can be sent without connecting to Citadel. * /
56 for (a=0; a<ndirs && ! is_static; ++a) {
57 if (!strcasecmp(action, (char*)static_content_dirs[a])) { /* map web to disk location * /
65 snprintf(buf, sizeof buf, "%s/%s/%s/%s/%s/%s/%s/%s",
66 static_dirs[n_static],
67 index[1], index[2], index[3], index[4], index[5], index[6], index[7]);
69 if (buf[strlen(buf)-1] == '/') {
70 buf[strlen(buf)-1] = 0;
73 for (a = 0; a < strlen(buf); ++a) {
74 if (isspace(buf[a])) {
82 lprintf(9, "Suspicious request. Ignoring.");
83 hprintf("HTTP/1.1 404 Security check failed\r\n");
84 hprintf("Content-Type: text/plain\r\n\r\n");
85 wprintf("You have sent a malformed or invalid request.\r\n");
88 goto SKIP_ALL_THIS_CRAP; /* Don't try to connect * /
94 * dump out static pages from disk
96 void output_static(const char *what)
102 const char *content_type;
106 fd = open(what, O_RDONLY);
108 lprintf(9, "output_static('%s') [%s] -- NOT FOUND --\n", what, ChrPtr(WC->Hdr->this_page));
109 hprintf("HTTP/1.1 404 %s\r\n", strerror(errno));
110 hprintf("Content-Type: text/plain\r\n");
111 wprintf("Cannot open %s: %s\r\n", what, strerror(errno));
115 content_type = GuessMimeByFilename(what, len);
117 if (fstat(fd, &statbuf) == -1) {
118 lprintf(9, "output_static('%s') -- FSTAT FAILED --\n", what);
119 hprintf("HTTP/1.1 404 %s\r\n", strerror(errno));
120 hprintf("Content-Type: text/plain\r\n");
121 wprintf("Cannot fstat %s: %s\n", what, strerror(errno));
127 bytes = statbuf.st_size;
129 if (StrBufReadBLOB(WC->WBuf, &fd, 1, bytes, &Err) < 0)
131 if (fd > 0) close(fd);
132 lprintf(9, "output_static('%s') -- FREAD FAILED (%s) --\n", what, strerror(errno));
133 hprintf("HTTP/1.1 500 internal server error \r\n");
134 hprintf("Content-Type: text/plain\r\n");
142 lprintf(9, "output_static('%s') %s\n", what, content_type);
144 http_transmit_thing(content_type, 1);
146 if (yesbstr("force_close_session")) {
147 end_webcit_session();
151 /* TODO: integrate this into the static startup logic
153 * While we're at it, gracefully handle requests for the
154 * robots.txt and favicon.ico files.
156 if ((StrLength(ReqLine) >= 11) &&
157 !strncasecmp(ChrPtr(ReqLine), "/robots.txt", 11)) {
159 HKEY("/static/robots.txt"
160 "?force_close_session=yes HTTP/1.1"));
163 else if ((StrLength(ReqLine) >= 11) &&
164 !strncasecmp(ChrPtr(ReqLine), "/favicon.ico", 12)) {
165 StrBufPlain(ReqLine, HKEY("/static/favicon.ico"));
174 int LoadStaticDir(const char *DirName, HashList *DirList, const char *RelDir)
176 char dirname[PATH_MAX];
177 char reldir[PATH_MAX];
178 StrBuf *FileName = NULL;
180 StrBuf *WebDir = NULL;
181 StrBuf *OneWebName = NULL;
184 struct dirent *filedir_entry;
188 filedir = opendir (DirName);
189 if (filedir == NULL) {
193 Dir = NewStrBufPlain(DirName, -1);
194 WebDir = NewStrBufPlain(RelDir, -1);
195 OneWebName = NewStrBuf();
197 while ((readdir_r(filedir, &d, &filedir_entry) == 0) &&
198 (filedir_entry != NULL))
201 #ifdef _DIRENT_HAVE_D_NAMELEN
202 d_namelen = filedir_entry->d_namelen;
204 d_namelen = strlen(filedir_entry->d_name);
206 d_without_ext = d_namelen;
208 if ((d_namelen > 1) && filedir_entry->d_name[d_namelen - 1] == '~')
209 continue; /* Ignore backup files... */
211 if ((d_namelen == 1) &&
212 (filedir_entry->d_name[0] == '.'))
215 if ((d_namelen == 2) &&
216 (filedir_entry->d_name[0] == '.') &&
217 (filedir_entry->d_name[1] == '.'))
220 switch (filedir_entry->d_type)
223 /* Skip directories we are not interested in... */
224 if ((strcmp(filedir_entry->d_name, ".svn") == 0) ||
225 (strcmp(filedir_entry->d_name, "t") == 0))
227 snprintf(dirname, PATH_MAX, "%s/%s",
228 DirName, filedir_entry->d_name);
229 snprintf(reldir, PATH_MAX, "%s/%s",
230 RelDir, filedir_entry->d_name);
231 LoadStaticDir(dirname, DirList, reldir);
233 case DT_LNK: /* TODO: check whether its a file or a directory */
235 PStart = filedir_entry->d_name;
236 FileName = NewStrBufDup(Dir);
237 if (ChrPtr(FileName) [ StrLength(FileName) - 1] != '/')
238 StrBufAppendBufPlain(FileName, "/", 1, 0);
239 StrBufAppendBufPlain(FileName, filedir_entry->d_name, d_namelen, 0);
241 FlushStrBuf(OneWebName);
242 StrBufAppendBuf(OneWebName, WebDir, 0);
243 if ((StrLength(OneWebName) != 0) &&
244 (ChrPtr(OneWebName) [ StrLength(OneWebName)] != '/'))
245 StrBufAppendBufPlain(OneWebName, "/", 1, 0);
246 StrBufAppendBufPlain(OneWebName, filedir_entry->d_name, d_namelen, 0);
248 Put(DirList, SKEY(OneWebName), FileName, HFreeStrBuf);
249 /* printf("[%s | %s] \n", ChrPtr(OneWebName), ChrPtr(FileName));*/
260 FreeStrBuf(&OneWebName);
265 void output_static_safe(HashList *DirList)
271 if (GetHash(DirList, SKEY(WCC->Hdr->ReqLine), &vFile) &&
274 File = (StrBuf*) vFile;
275 output_static(ChrPtr(vFile));
278 ///TODO: detect image & output blank image
281 void output_static_0(void)
283 output_static_safe(StaticFilemappings[0]);
285 void output_static_1(void)
287 output_static_safe(StaticFilemappings[1]);
289 void output_static_2(void)
291 output_static_safe(StaticFilemappings[2]);
293 void output_static_3(void)
295 output_static_safe(StaticFilemappings[3]);
299 ServerStartModule_STATIC
302 StaticFilemappings[0] = NewHash(1, NULL);
303 StaticFilemappings[1] = NewHash(1, NULL);
304 StaticFilemappings[2] = NewHash(1, NULL);
305 StaticFilemappings[3] = NewHash(1, NULL);
308 ServerShutdownModule_STATIC
311 DeleteHash(&StaticFilemappings[0]);
312 DeleteHash(&StaticFilemappings[1]);
313 DeleteHash(&StaticFilemappings[2]);
314 DeleteHash(&StaticFilemappings[3]);
322 LoadStaticDir(static_dirs[0], StaticFilemappings[0], "");
323 LoadStaticDir(static_dirs[1], StaticFilemappings[1], "");
324 LoadStaticDir(static_dirs[2], StaticFilemappings[2], "");
325 LoadStaticDir(static_dirs[3], StaticFilemappings[3], "");
327 WebcitAddUrlHandler(HKEY("robots.txt"), output_static_0, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC);
328 WebcitAddUrlHandler(HKEY("favicon.ico"), output_static_0, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC);
329 WebcitAddUrlHandler(HKEY("static"), output_static_0, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC);
330 WebcitAddUrlHandler(HKEY("static.local"), output_static_1, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC);
331 WebcitAddUrlHandler(HKEY("tinymce"), output_static_2, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC);