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)
245 char content_type[256];
246 char *content = NULL;
248 /* Setting to nonzero forces a MIME type of application/octet-stream */
249 int force_download = 1;
251 safestrncpy(buf, ChrPtr(WC->UrlFragment2), sizeof buf);
253 serv_printf("OPEN %s", buf);
254 serv_getln(buf, sizeof buf);
256 bytes = extract_long(&buf[4], 0);
257 content = malloc(bytes + 2);
258 if (force_download) {
259 strcpy(content_type, "application/octet-stream");
262 extract_token(content_type, &buf[4], 3, '|', sizeof content_type);
264 output_headers(0, 0, 0, 0, 0, 0);
265 read_server_binary(WC->WBuf, bytes);
267 serv_getln(buf, sizeof buf);
268 http_transmit_thing(content_type, 0);
271 hprintf("HTTP/1.1 404 %s\n", &buf[4]);
272 output_headers(0, 0, 0, 0, 0, 0);
273 hprintf("Content-Type: text/plain\r\n");
274 wprintf(_("An error occurred while retrieving this file: %s\n"), &buf[4]);
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)
359 const char *MimeType;
361 serv_printf("OIMG %s|%s", bstr("name"), bstr("parm"));
362 serv_getln(buf, sizeof buf);
364 bytes = extract_long(&buf[4], 0);
366 /** Read it from the server */
368 if (read_server_binary(WCC->WBuf, bytes) > 0) {
370 serv_getln(buf, sizeof buf);
372 MimeType = GuessMimeType (ChrPtr(WCC->WBuf), StrLength(WCC->WBuf));
373 /** Write it to the browser */
374 if (!IsEmptyStr(MimeType))
376 http_transmit_thing(MimeType, 0);
380 /* hm... unknown mimetype? fallback to blank gif */
385 * Instead of an ugly 404, send a 1x1 transparent GIF
386 * when there's no such image on the server.
388 snprintf (blank_gif, SIZ, "%s%s", static_dirs[0], "/blank.gif");
389 output_static(blank_gif);
397 RegisterIterator("ROOM:FILES", 0, NULL, LoadFileList,
398 NULL, DeleteHash, CTX_FILELIST, CTX_NONE,
399 IT_FLAG_DETECT_GROUPCHANGE);
401 RegisterSortFunc(HKEY("filemime"),
403 CompareFilelistByMime,
404 CompareFilelistByMimeRev,
405 GroupchangeFilelistByMime,
407 RegisterSortFunc(HKEY("filename"),
409 CompareFilelistByName,
410 CompareFilelistByNameRev,
411 GroupchangeFilelistByName,
413 RegisterSortFunc(HKEY("filesize"),
415 CompareFilelistBySize,
416 CompareFilelistBySizeRev,
417 GroupchangeFilelistBySize,
419 RegisterSortFunc(HKEY("filesubject"),
421 CompareFilelistByComment,
422 CompareFilelistByCommentRev,
423 GroupchangeFilelistByComment,
425 RegisterSortFunc(HKEY("fileunsorted"),
427 CompareFilelistBySequence,
428 CompareFilelistBySequence,
429 GroupchangeFilelistBySequence,
432 RegisterNamespace("FILE:NAME", 0, 2, tmplput_FILE_NAME, CTX_FILELIST);
433 RegisterNamespace("FILE:SIZE", 0, 1, tmplput_FILE_SIZE, CTX_FILELIST);
434 RegisterNamespace("FILE:MIMETYPE", 0, 2, tmplput_FILEMIMETYPE, CTX_FILELIST);
435 RegisterNamespace("FILE:COMMENT", 0, 2, tmplput_FILE_COMMENT, CTX_FILELIST);
437 RegisterConditional(HKEY("COND:FILE:ISPIC"), 0, Conditional_FILE_ISPIC, CTX_FILELIST);
439 WebcitAddUrlHandler(HKEY("image"), output_image, ANONYMOUS);
440 WebcitAddUrlHandler(HKEY("display_mime_icon"), display_mime_icon , ANONYMOUS);
441 WebcitAddUrlHandler(HKEY("download_file"), download_file, NEED_URL);
442 WebcitAddUrlHandler(HKEY("delete_file"), delete_file, NEED_URL);
443 WebcitAddUrlHandler(HKEY("upload_file"), upload_file, 0);