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.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 upload_file(void)
283 const char *MimeType;
285 long bytes_transmitted = 0;
287 wcsession *WCC = WC; /* stack this for faster access (WC is a function) */
289 MimeType = GuessMimeType(WCC->upload, WCC->upload_length);
290 serv_printf("UOPN %s|%s|%s", WCC->upload_filename, MimeType, bstr("description"));
291 serv_getln(buf, sizeof buf);
294 strcpy(WCC->ImportantMessage, &buf[4]);
295 do_template("files", NULL);
299 while (bytes_transmitted < WCC->upload_length)
302 if (blocksize > (WCC->upload_length - bytes_transmitted))
304 blocksize = (WCC->upload_length - bytes_transmitted);
306 serv_printf("WRIT %ld", blocksize);
307 serv_getln(buf, sizeof buf);
310 blocksize = atoi(&buf[4]);
311 serv_write(&WCC->upload[bytes_transmitted], blocksize);
312 bytes_transmitted += blocksize;
317 serv_getln(buf, sizeof buf);
318 strcpy(WCC->ImportantMessage, &buf[4]);
319 do_template("files", CTX_NONE);
325 * When the browser requests an image file from the Citadel server,
326 * this function is called to transmit it.
328 void output_image(void)
334 const char *MimeType;
336 serv_printf("OIMG %s|%s", bstr("name"), bstr("parm"));
337 serv_getln(buf, sizeof buf);
339 bytes = extract_long(&buf[4], 0);
341 /** Read it from the server */
343 if (read_server_binary(WCC->WBuf, bytes) > 0) {
345 serv_getln(buf, sizeof buf);
347 MimeType = GuessMimeType (ChrPtr(WCC->WBuf), StrLength(WCC->WBuf));
348 /** Write it to the browser */
349 if (!IsEmptyStr(MimeType))
351 http_transmit_thing(MimeType, 0);
355 /* hm... unknown mimetype? fallback to blank gif */
360 * Instead of an ugly 404, send a 1x1 transparent GIF
361 * when there's no such image on the server.
363 snprintf (blank_gif, SIZ, "%s%s", static_dirs[0], "/blank.gif");
364 output_static(blank_gif);
372 RegisterIterator("ROOM:FILES", 0, NULL, LoadFileList,
373 NULL, DeleteHash, CTX_FILELIST, CTX_NONE,
374 IT_FLAG_DETECT_GROUPCHANGE);
376 RegisterSortFunc(HKEY("filemime"),
378 CompareFilelistByMime,
379 CompareFilelistByMimeRev,
380 GroupchangeFilelistByMime,
382 RegisterSortFunc(HKEY("filename"),
384 CompareFilelistByName,
385 CompareFilelistByNameRev,
386 GroupchangeFilelistByName,
388 RegisterSortFunc(HKEY("filesize"),
390 CompareFilelistBySize,
391 CompareFilelistBySizeRev,
392 GroupchangeFilelistBySize,
394 RegisterSortFunc(HKEY("filesubject"),
396 CompareFilelistByComment,
397 CompareFilelistByCommentRev,
398 GroupchangeFilelistByComment,
400 RegisterSortFunc(HKEY("fileunsorted"),
402 CompareFilelistBySequence,
403 CompareFilelistBySequence,
404 GroupchangeFilelistBySequence,
407 RegisterNamespace("FILE:NAME", 0, 2, tmplput_FILE_NAME, CTX_FILELIST);
408 RegisterNamespace("FILE:SIZE", 0, 1, tmplput_FILE_SIZE, CTX_FILELIST);
409 RegisterNamespace("FILE:MIMETYPE", 0, 2, tmplput_FILEMIMETYPE, CTX_FILELIST);
410 RegisterNamespace("FILE:COMMENT", 0, 2, tmplput_FILE_COMMENT, CTX_FILELIST);
412 RegisterConditional(HKEY("COND:FILE:ISPIC"), 0, Conditional_FILE_ISPIC, CTX_FILELIST);
414 WebcitAddUrlHandler(HKEY("image"), output_image, 0);
415 WebcitAddUrlHandler(HKEY("display_mime_icon"), display_mime_icon , 0);
416 WebcitAddUrlHandler(HKEY("download_file"), download_file, NEED_URL);
417 WebcitAddUrlHandler(HKEY("upload_file"), upload_file, 0);