7 extern char* static_dirs[];
9 typedef struct _FileListStruct {
18 void FreeFiles(void *vFile)
20 FileListStruct *F = (FileListStruct*) vFile;
21 FreeStrBuf(&F->Filename);
22 FreeStrBuf(&F->MimeType);
23 FreeStrBuf(&F->Comment);
27 /* -------------------------------------------------------------------------------- */
28 void tmplput_FILE_NAME(StrBuf *Target, WCTemplputParams *TP)
30 FileListStruct *F = (FileListStruct*) CTX;
31 StrBufAppendTemplate(Target, TP, F->Filename, 0);
33 void tmplput_FILE_SIZE(StrBuf *Target, WCTemplputParams *TP)
35 FileListStruct *F = (FileListStruct*) CTX;
36 StrBufAppendPrintf(Target, "%ld", F->FileSize);
38 void tmplput_FILEMIMETYPE(StrBuf *Target, WCTemplputParams *TP)
40 FileListStruct *F = (FileListStruct*) CTX;
41 StrBufAppendTemplate(Target, TP, F->MimeType, 0);
43 void tmplput_FILE_COMMENT(StrBuf *Target, WCTemplputParams *TP)
45 FileListStruct *F = (FileListStruct*) CTX;
46 StrBufAppendTemplate(Target, TP, F->Comment, 0);
49 /* -------------------------------------------------------------------------------- */
51 int Conditional_FILE_ISPIC(StrBuf *Target, WCTemplputParams *TP)
53 FileListStruct *F = (FileListStruct*) CTX;
57 /* -------------------------------------------------------------------------------- */
58 int CompareFilelistByMime(const void *vFile1, const void *vFile2)
60 FileListStruct *File1 = (FileListStruct*) GetSearchPayload(vFile1);
61 FileListStruct *File2 = (FileListStruct*) GetSearchPayload(vFile2);
63 if (File1->IsPic != File2->IsPic)
64 return File1->IsPic > File2->IsPic;
65 return strcasecmp(ChrPtr(File1->MimeType), ChrPtr(File2->MimeType));
67 int CompareFilelistByMimeRev(const void *vFile1, const void *vFile2)
69 FileListStruct *File1 = (FileListStruct*) GetSearchPayload(vFile1);
70 FileListStruct *File2 = (FileListStruct*) GetSearchPayload(vFile2);
71 if (File1->IsPic != File2->IsPic)
72 return File1->IsPic < File2->IsPic;
73 return strcasecmp(ChrPtr(File2->MimeType), ChrPtr(File1->MimeType));
75 int GroupchangeFilelistByMime(const void *vFile1, const void *vFile2)
77 FileListStruct *File1 = (FileListStruct*) vFile1;
78 FileListStruct *File2 = (FileListStruct*) vFile2;
80 if (File1->IsPic != File2->IsPic)
81 return File1->IsPic > File2->IsPic;
82 return strcasecmp(ChrPtr(File1->MimeType), ChrPtr(File2->MimeType)) != 0;
86 int CompareFilelistByName(const void *vFile1, const void *vFile2)
88 FileListStruct *File1 = (FileListStruct*) GetSearchPayload(vFile1);
89 FileListStruct *File2 = (FileListStruct*) GetSearchPayload(vFile2);
91 if (File1->IsPic != File2->IsPic)
92 return File1->IsPic > File2->IsPic;
93 return strcasecmp(ChrPtr(File1->Filename), ChrPtr(File2->Filename));
95 int CompareFilelistByNameRev(const void *vFile1, const void *vFile2)
97 FileListStruct *File1 = (FileListStruct*) GetSearchPayload(vFile1);
98 FileListStruct *File2 = (FileListStruct*) GetSearchPayload(vFile2);
99 if (File1->IsPic != File2->IsPic)
100 return File1->IsPic < File2->IsPic;
101 return strcasecmp(ChrPtr(File2->Filename), ChrPtr(File1->Filename));
103 int GroupchangeFilelistByName(const void *vFile1, const void *vFile2)
105 FileListStruct *File1 = (FileListStruct*) vFile1;
106 FileListStruct *File2 = (FileListStruct*) vFile2;
108 return ChrPtr(File1->Filename)[0] != ChrPtr(File2->Filename)[0];
112 int CompareFilelistBySize(const void *vFile1, const void *vFile2)
114 FileListStruct *File1 = (FileListStruct*) GetSearchPayload(vFile1);
115 FileListStruct *File2 = (FileListStruct*) GetSearchPayload(vFile2);
116 if (File1->FileSize == File2->FileSize)
118 return (File1->FileSize > File2->FileSize);
120 int CompareFilelistBySizeRev(const void *vFile1, const void *vFile2)
122 FileListStruct *File1 = (FileListStruct*) GetSearchPayload(vFile1);
123 FileListStruct *File2 = (FileListStruct*) GetSearchPayload(vFile2);
124 if (File1->FileSize == File2->FileSize)
126 return (File1->FileSize < File2->FileSize);
128 int GroupchangeFilelistBySize(const void *vFile1, const void *vFile2)
134 int CompareFilelistByComment(const void *vFile1, const void *vFile2)
136 FileListStruct *File1 = (FileListStruct*) GetSearchPayload(vFile1);
137 FileListStruct *File2 = (FileListStruct*) GetSearchPayload(vFile2);
138 return strcasecmp(ChrPtr(File1->Comment), ChrPtr(File2->Comment));
140 int CompareFilelistByCommentRev(const void *vFile1, const void *vFile2)
142 FileListStruct *File1 = (FileListStruct*) GetSearchPayload(vFile1);
143 FileListStruct *File2 = (FileListStruct*) GetSearchPayload(vFile2);
144 return strcasecmp(ChrPtr(File2->Comment), ChrPtr(File1->Comment));
146 int GroupchangeFilelistByComment(const void *vFile1, const void *vFile2)
148 FileListStruct *File1 = (FileListStruct*) vFile1;
149 FileListStruct *File2 = (FileListStruct*) vFile2;
150 return ChrPtr(File1->Comment)[9] != ChrPtr(File2->Comment)[0];
154 int CompareFilelistBySequence(const void *vFile1, const void *vFile2)
156 FileListStruct *File1 = (FileListStruct*) GetSearchPayload(vFile1);
157 FileListStruct *File2 = (FileListStruct*) GetSearchPayload(vFile2);
158 return (File2->Sequence > File1->Sequence);
160 int GroupchangeFilelistBySequence(const void *vFile1, const void *vFile2)
165 /* -------------------------------------------------------------------------------- */
166 HashList* LoadFileList(StrBuf *Target, WCTemplputParams *TP)
168 FileListStruct *Entry;
176 WCTemplputParams SubTP;
178 memset(&TP, 0, sizeof(WCTemplputParams));
180 serv_getln(buf, sizeof buf);
181 if (buf[0] != '1') return NULL;
184 Files = NewHash(1, NULL);
185 while (!Done && (StrBuf_ServGetln(Buf)>=0)) {
186 if ( (StrLength(Buf)==3) &&
187 !strcmp(ChrPtr(Buf), "000"))
193 Entry = (FileListStruct*) malloc(sizeof (FileListStruct));
194 Entry->Filename = NewStrBufPlain(NULL, StrLength(Buf));
195 Entry->MimeType = NewStrBufPlain(NULL, StrLength(Buf));
196 Entry->Comment = NewStrBufPlain(NULL, StrLength(Buf));
198 Entry->Sequence = sequence++;
200 StrBufExtract_token(Entry->Filename, Buf, 0, '|');
201 Entry->FileSize = StrBufExtract_long(Buf, 1, '|');
202 StrBufExtract_token(Entry->MimeType, Buf, 2, '|');
203 StrBufExtract_token(Entry->Comment, Buf, 3, '|');
207 Entry->IsPic = (strstr(ChrPtr(Entry->MimeType), "image") != NULL);
211 Put(Files, SKEY(Entry->Filename), Entry, FreeFiles);
213 SubTP.Filter.ContextType = CTX_FILELIST;
214 SortIt = RetrieveSort(&SubTP, NULL, 0, HKEY("fileunsorted"), 0);
216 SortByPayload(Files, SortIt);
218 SortByPayload(Files, CompareFilelistBySequence);
220 svputlong("FILE:HAVEPICS", HavePic);
224 void display_mime_icon(void)
227 const char *FileName;
231 MimeType = xbstr("type", &tlen);
232 FileName = GetIconFilename(MimeType, tlen);
234 if (FileName == NULL)
235 snprintf (FileBuf, SIZ, "%s%s", static_dirs[0], "/diskette_24x.gif");
237 snprintf (FileBuf, SIZ, "%s%s", static_dirs[3], FileName);
238 output_static(FileBuf);
241 void download_file(void)
246 StrBuf *ContentType = NewStrBufPlain(HKEY("application/octet-stream"));
248 /* Setting to nonzero forces a MIME type of application/octet-stream */
249 int force_download = 1;
252 StrBufExtract_token(Buf, WCC->Hdr->ReqLine, 2, '/');
253 StrBufUnescape(Buf, 1);
254 serv_printf("OPEN %s", ChrPtr(Buf));
255 StrBuf_ServGetln(Buf);
256 if (GetServerStatus(Buf, NULL) == 2) {
257 StrBufCutLeft(Buf, 4);
258 bytes = StrBufExtract_long(Buf, 0, '|');
259 if (!force_download) {
260 StrBufExtract_token(ContentType, Buf, 3, '|');
262 read_server_binary(WCC->WBuf, bytes, Buf);
264 StrBuf_ServGetln(Buf);
265 http_transmit_thing(ChrPtr(ContentType), 0);
267 StrBufCutLeft(Buf, 4);
268 hprintf("HTTP/1.1 404 %s\n", ChrPtr(Buf));
269 output_headers(0, 0, 0, 0, 0, 0);
270 hprintf("Content-Type: text/plain\r\n");
271 wprintf(_("An error occurred while retrieving this file: %s\n"),
275 FreeStrBuf(&ContentType);
281 void delete_file(void)
286 safestrncpy(buf, bstr("file"), sizeof buf);
288 serv_printf("DELF %s", buf);
290 StrBuf_ServGetln(Buf);
291 GetServerStatus(Buf, NULL);
292 StrBufCutLeft(Buf, 4);
293 strcpy(WC->ImportantMessage, ChrPtr(Buf));
294 do_template("files", CTX_NONE);
295 output_headers(0, 0, 0, 0, 0, 0);
302 void upload_file(void)
304 const char *MimeType;
306 long bytes_transmitted = 0;
308 wcsession *WCC = WC; /* stack this for faster access (WC is a function) */
310 MimeType = GuessMimeType(WCC->upload, WCC->upload_length);
311 serv_printf("UOPN %s|%s|%s", WCC->upload_filename, MimeType, bstr("description"));
312 serv_getln(buf, sizeof buf);
315 strcpy(WCC->ImportantMessage, &buf[4]);
316 do_template("files", NULL);
317 output_headers(0, 0, 0, 0, 0, 0);
322 while (bytes_transmitted < WCC->upload_length)
325 if (blocksize > (WCC->upload_length - bytes_transmitted))
327 blocksize = (WCC->upload_length - bytes_transmitted);
329 serv_printf("WRIT %ld", blocksize);
330 serv_getln(buf, sizeof buf);
333 blocksize = atoi(&buf[4]);
334 serv_write(&WCC->upload[bytes_transmitted], blocksize);
335 bytes_transmitted += blocksize;
340 serv_getln(buf, sizeof buf);
341 strcpy(WCC->ImportantMessage, &buf[4]);
342 do_template("files", CTX_NONE);
343 output_headers(0, 0, 0, 0, 0, 0);
350 * When the browser requests an image file from the Citadel server,
351 * this function is called to transmit it.
353 void output_image(void)
358 const char *MimeType;
361 serv_printf("OIMG %s|%s", bstr("name"), bstr("parm"));
362 StrBuf_ServGetln(Buf);
363 if (GetServerStatus(Buf, NULL) == 2) {
364 StrBufCutLeft(Buf, 4);
365 bytes = StrBufExtract_long(Buf, 0, '|');
367 /** Read it from the server */
369 if (read_server_binary(WCC->WBuf, bytes, Buf) > 0) {
371 StrBuf_ServGetln(Buf);
373 MimeType = GuessMimeType (ChrPtr(WCC->WBuf), StrLength(WCC->WBuf));
374 /** Write it to the browser */
375 if (!IsEmptyStr(MimeType))
377 http_transmit_thing(MimeType, 0);
381 /* hm... unknown mimetype? fallback to blank gif */
386 * Instead of an ugly 404, send a 1x1 transparent GIF
387 * when there's no such image on the server.
389 StrBufPrintf (Buf, "%s%s", static_dirs[0], "/blank.gif");
390 //// TDODO output_static(ChrPtr(Buf));
399 RegisterIterator("ROOM:FILES", 0, NULL, LoadFileList,
400 NULL, DeleteHash, CTX_FILELIST, CTX_NONE,
401 IT_FLAG_DETECT_GROUPCHANGE);
403 RegisterSortFunc(HKEY("filemime"),
405 CompareFilelistByMime,
406 CompareFilelistByMimeRev,
407 GroupchangeFilelistByMime,
409 RegisterSortFunc(HKEY("filename"),
411 CompareFilelistByName,
412 CompareFilelistByNameRev,
413 GroupchangeFilelistByName,
415 RegisterSortFunc(HKEY("filesize"),
417 CompareFilelistBySize,
418 CompareFilelistBySizeRev,
419 GroupchangeFilelistBySize,
421 RegisterSortFunc(HKEY("filesubject"),
423 CompareFilelistByComment,
424 CompareFilelistByCommentRev,
425 GroupchangeFilelistByComment,
427 RegisterSortFunc(HKEY("fileunsorted"),
429 CompareFilelistBySequence,
430 CompareFilelistBySequence,
431 GroupchangeFilelistBySequence,
434 RegisterNamespace("FILE:NAME", 0, 2, tmplput_FILE_NAME, CTX_FILELIST);
435 RegisterNamespace("FILE:SIZE", 0, 1, tmplput_FILE_SIZE, CTX_FILELIST);
436 RegisterNamespace("FILE:MIMETYPE", 0, 2, tmplput_FILEMIMETYPE, CTX_FILELIST);
437 RegisterNamespace("FILE:COMMENT", 0, 2, tmplput_FILE_COMMENT, CTX_FILELIST);
439 RegisterConditional(HKEY("COND:FILE:ISPIC"), 0, Conditional_FILE_ISPIC, CTX_FILELIST);
441 WebcitAddUrlHandler(HKEY("image"), output_image, ANONYMOUS);
442 WebcitAddUrlHandler(HKEY("display_mime_icon"), display_mime_icon , ANONYMOUS);
443 WebcitAddUrlHandler(HKEY("download_file"), download_file, NEED_URL);
444 WebcitAddUrlHandler(HKEY("delete_file"), delete_file, NEED_URL);
445 WebcitAddUrlHandler(HKEY("upload_file"), upload_file, 0);