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 StrBufUnescape(WCC->UrlFragment2, 1);
253 serv_printf("OPEN %s", ChrPtr(WCC->UrlFragment2));
254 StrBuf_ServGetln(Buf);
255 if (GetServerStatus(Buf, NULL) == 2) {
256 StrBufCutLeft(Buf, 4);
257 bytes = StrBufExtract_long(Buf, 0, '|');
258 if (!force_download) {
259 StrBufExtract_token(ContentType, Buf, 3, '|');
261 read_server_binary(WCC->WBuf, bytes, Buf);
263 StrBuf_ServGetln(Buf);
264 http_transmit_thing(ChrPtr(ContentType), 0);
266 StrBufCutLeft(Buf, 4);
267 hprintf("HTTP/1.1 404 %s\n", ChrPtr(Buf));
268 output_headers(0, 0, 0, 0, 0, 0);
269 hprintf("Content-Type: text/plain\r\n");
270 wprintf(_("An error occurred while retrieving this file: %s\n"),
274 FreeStrBuf(&ContentType);
280 void delete_file(void)
285 safestrncpy(buf, bstr("file"), sizeof buf);
287 serv_printf("DELF %s", buf);
289 StrBuf_ServGetln(Buf);
290 GetServerStatus(Buf, NULL);
291 StrBufCutLeft(Buf, 4);
292 strcpy(WC->ImportantMessage, ChrPtr(Buf));
293 do_template("files", CTX_NONE);
294 output_headers(0, 0, 0, 0, 0, 0);
301 void upload_file(void)
303 const char *MimeType;
305 long bytes_transmitted = 0;
307 wcsession *WCC = WC; /* stack this for faster access (WC is a function) */
309 MimeType = GuessMimeType(WCC->upload, WCC->upload_length);
310 serv_printf("UOPN %s|%s|%s", WCC->upload_filename, MimeType, bstr("description"));
311 serv_getln(buf, sizeof buf);
314 strcpy(WCC->ImportantMessage, &buf[4]);
315 do_template("files", NULL);
316 output_headers(0, 0, 0, 0, 0, 0);
321 while (bytes_transmitted < WCC->upload_length)
324 if (blocksize > (WCC->upload_length - bytes_transmitted))
326 blocksize = (WCC->upload_length - bytes_transmitted);
328 serv_printf("WRIT %ld", blocksize);
329 serv_getln(buf, sizeof buf);
332 blocksize = atoi(&buf[4]);
333 serv_write(&WCC->upload[bytes_transmitted], blocksize);
334 bytes_transmitted += blocksize;
339 serv_getln(buf, sizeof buf);
340 strcpy(WCC->ImportantMessage, &buf[4]);
341 do_template("files", CTX_NONE);
342 output_headers(0, 0, 0, 0, 0, 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);
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 StrBufPrintf (Buf, "%s%s", static_dirs[0], "/blank.gif");
389 output_static(ChrPtr(Buf));
398 RegisterIterator("ROOM:FILES", 0, NULL, LoadFileList,
399 NULL, DeleteHash, CTX_FILELIST, CTX_NONE,
400 IT_FLAG_DETECT_GROUPCHANGE);
402 RegisterSortFunc(HKEY("filemime"),
404 CompareFilelistByMime,
405 CompareFilelistByMimeRev,
406 GroupchangeFilelistByMime,
408 RegisterSortFunc(HKEY("filename"),
410 CompareFilelistByName,
411 CompareFilelistByNameRev,
412 GroupchangeFilelistByName,
414 RegisterSortFunc(HKEY("filesize"),
416 CompareFilelistBySize,
417 CompareFilelistBySizeRev,
418 GroupchangeFilelistBySize,
420 RegisterSortFunc(HKEY("filesubject"),
422 CompareFilelistByComment,
423 CompareFilelistByCommentRev,
424 GroupchangeFilelistByComment,
426 RegisterSortFunc(HKEY("fileunsorted"),
428 CompareFilelistBySequence,
429 CompareFilelistBySequence,
430 GroupchangeFilelistBySequence,
433 RegisterNamespace("FILE:NAME", 0, 2, tmplput_FILE_NAME, CTX_FILELIST);
434 RegisterNamespace("FILE:SIZE", 0, 1, tmplput_FILE_SIZE, CTX_FILELIST);
435 RegisterNamespace("FILE:MIMETYPE", 0, 2, tmplput_FILEMIMETYPE, CTX_FILELIST);
436 RegisterNamespace("FILE:COMMENT", 0, 2, tmplput_FILE_COMMENT, CTX_FILELIST);
438 RegisterConditional(HKEY("COND:FILE:ISPIC"), 0, Conditional_FILE_ISPIC, CTX_FILELIST);
440 WebcitAddUrlHandler(HKEY("image"), output_image, ANONYMOUS);
441 WebcitAddUrlHandler(HKEY("display_mime_icon"), display_mime_icon , ANONYMOUS);
442 WebcitAddUrlHandler(HKEY("download_file"), download_file, NEED_URL);
443 WebcitAddUrlHandler(HKEY("delete_file"), delete_file, NEED_URL);
444 WebcitAddUrlHandler(HKEY("upload_file"), upload_file, 0);