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->HR.ReqLine, 0, '/');
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)
283 const StrBuf *MimeType;
287 safestrncpy(buf, bstr("file"), sizeof buf);
289 serv_printf("DELF %s", buf);
291 StrBuf_ServGetln(Buf);
292 GetServerStatus(Buf, NULL);
293 StrBufCutLeft(Buf, 4);
294 strcpy(WC->ImportantMessage, ChrPtr(Buf));
295 MimeType = DoTemplate(HKEY("files"), NULL, &NoCtx);
296 http_transmit_thing(ChrPtr(MimeType), 0);
302 void upload_file(void)
304 const StrBuf *RetMimeType;
305 const char *MimeType;
307 long bytes_transmitted = 0;
309 wcsession *WCC = WC; /* stack this for faster access (WC is a function) */
311 MimeType = GuessMimeType(ChrPtr(WCC->upload), WCC->upload_length);
312 serv_printf("UOPN %s|%s|%s", WCC->upload_filename, MimeType, bstr("description"));
313 serv_getln(buf, sizeof buf);
316 strcpy(WCC->ImportantMessage, &buf[4]);
317 RetMimeType = DoTemplate(HKEY("files"), NULL, &NoCtx);
318 http_transmit_thing(ChrPtr(RetMimeType), 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(&ChrPtr(WCC->upload)[bytes_transmitted], blocksize);
335 bytes_transmitted += blocksize;
340 serv_getln(buf, sizeof buf);
341 strcpy(WCC->ImportantMessage, &buf[4]);
342 RetMimeType = DoTemplate(HKEY("files"), NULL, &NoCtx);
343 http_transmit_thing(ChrPtr(RetMimeType), 0);
349 * When the browser requests an image file from the Citadel server,
350 * this function is called to transmit it.
352 void output_image(void)
357 const char *MimeType;
360 serv_printf("OIMG %s|%s", bstr("name"), bstr("parm"));
361 StrBuf_ServGetln(Buf);
362 if (GetServerStatus(Buf, NULL) == 2) {
363 StrBufCutLeft(Buf, 4);
364 bytes = StrBufExtract_long(Buf, 0, '|');
366 /** Read it from the server */
368 if (read_server_binary(WCC->WBuf, bytes, Buf) > 0) {
370 StrBuf_ServGetln(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);
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 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);