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, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
30 FileListStruct *F = (FileListStruct*) Context;
31 StrBufAppendTemplate(Target, nArgs, Tokens, Context, ContextType, F->Filename, 0);
33 void tmplput_FILE_SIZE(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
35 FileListStruct *F = (FileListStruct*) Context;
36 StrBufAppendPrintf(Target, "%ld", F->FileSize);
38 void tmplput_FILEMIMETYPE(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
40 FileListStruct *F = (FileListStruct*) Context;
41 StrBufAppendTemplate(Target, nArgs, Tokens, Context, ContextType, F->MimeType, 0);
43 void tmplput_FILE_COMMENT(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
45 FileListStruct *F = (FileListStruct*) Context;
46 StrBufAppendTemplate(Target, nArgs, Tokens, Context, ContextType, F->Comment, 0);
49 /* -------------------------------------------------------------------------------- */
51 int Conditional_FILE_ISPIC(WCTemplateToken *Tokens, void *Context, int ContextType)
53 FileListStruct *F = (FileListStruct*) Context;
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, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
168 FileListStruct *Entry;
178 serv_getln(buf, sizeof buf);
179 if (buf[0] != '1') return NULL;
182 Files = NewHash(1, NULL);
183 while (!Done && (StrBuf_ServGetln(Buf)>=0)) {
184 if ( (StrLength(Buf)==3) &&
185 !strcmp(ChrPtr(Buf), "000"))
191 Entry = (FileListStruct*) malloc(sizeof (FileListStruct));
192 Entry->Filename = NewStrBufPlain(NULL, StrLength(Buf));
193 Entry->MimeType = NewStrBufPlain(NULL, StrLength(Buf));
194 Entry->Comment = NewStrBufPlain(NULL, StrLength(Buf));
196 Entry->Sequence = sequence++;
198 StrBufExtract_token(Entry->Filename, Buf, 0, '|');
199 Entry->FileSize = StrBufExtract_long(Buf, 1, '|');
200 StrBufExtract_token(Entry->MimeType, Buf, 2, '|');
201 StrBufExtract_token(Entry->Comment, Buf, 3, '|');
205 Entry->IsPic = (strstr(ChrPtr(Entry->MimeType), "image") != NULL);
209 Put(Files, SKEY(Entry->Filename), Entry, FreeFiles);
211 SortIt = RetrieveSort(CTX_FILELIST, NULL, HKEY("fileunsorted"), 0);
213 SortByPayload(Files, SortIt);
215 SortByPayload(Files, CompareFilelistBySequence);
217 svputlong("FILE:HAVEPICS", HavePic);
221 void display_mime_icon(void)
224 const char *FileName;
228 MimeType = xbstr("type", &tlen);
229 FileName = GetIconFilename(MimeType, tlen);
231 if (FileName == NULL)
232 snprintf (FileBuf, SIZ, "%s%s", static_dirs[0], "/diskette_24x.gif");
234 snprintf (FileBuf, SIZ, "%s%s", static_dirs[3], FileName);
235 output_static(FileBuf);
238 void download_file(void)
242 char content_type[256];
243 char *content = NULL;
245 /* Setting to nonzero forces a MIME type of application/octet-stream */
246 int force_download = 1;
248 safestrncpy(buf, ChrPtr(WC->UrlFragment2), sizeof buf);
250 serv_printf("OPEN %s", buf);
251 serv_getln(buf, sizeof buf);
253 bytes = extract_long(&buf[4], 0);
254 content = malloc(bytes + 2);
255 if (force_download) {
256 strcpy(content_type, "application/octet-stream");
259 extract_token(content_type, &buf[4], 3, '|', sizeof content_type);
261 output_headers(0, 0, 0, 0, 0, 0);
262 read_server_binary(WC->WBuf, bytes);
264 serv_getln(buf, sizeof buf);
265 http_transmit_thing(content_type, 0);
268 hprintf("HTTP/1.1 404 %s\n", &buf[4]);
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"), &buf[4]);
278 void upload_file(void)
280 const char *MimeType;
282 long bytes_transmitted = 0;
284 wcsession *WCC = WC; /* stack this for faster access (WC is a function) */
286 MimeType = GuessMimeType(WCC->upload, WCC->upload_length);
287 serv_printf("UOPN %s|%s|%s", WCC->upload_filename, MimeType, bstr("description"));
288 serv_getln(buf, sizeof buf);
291 strcpy(WCC->ImportantMessage, &buf[4]);
292 do_template("files", NULL);
296 while (bytes_transmitted < WCC->upload_length)
299 if (blocksize > (WCC->upload_length - bytes_transmitted))
301 blocksize = (WCC->upload_length - bytes_transmitted);
303 serv_printf("WRIT %ld", blocksize);
304 serv_getln(buf, sizeof buf);
307 blocksize = atoi(&buf[4]);
308 serv_write(&WCC->upload[bytes_transmitted], blocksize);
309 bytes_transmitted += blocksize;
314 serv_getln(buf, sizeof buf);
315 strcpy(WCC->ImportantMessage, &buf[4]);
316 do_template("files", CTX_NONE);
322 * When the browser requests an image file from the Citadel server,
323 * this function is called to transmit it.
325 void output_image(void)
331 const char *MimeType;
333 serv_printf("OIMG %s|%s", bstr("name"), bstr("parm"));
334 serv_getln(buf, sizeof buf);
336 bytes = extract_long(&buf[4], 0);
338 /** Read it from the server */
340 if (read_server_binary(WCC->WBuf, bytes) > 0) {
342 serv_getln(buf, sizeof buf);
344 MimeType = GuessMimeType (ChrPtr(WCC->WBuf), StrLength(WCC->WBuf));
345 /** Write it to the browser */
346 if (!IsEmptyStr(MimeType))
348 http_transmit_thing(MimeType, 0);
352 /* hm... unknown mimetype? fallback to blank gif */
357 * Instead of an ugly 404, send a 1x1 transparent GIF
358 * when there's no such image on the server.
360 snprintf (blank_gif, SIZ, "%s%s", static_dirs[0], "/blank.gif");
361 output_static(blank_gif);
369 RegisterIterator("ROOM:FILES", 0, NULL, LoadFileList,
370 NULL, DeleteHash, CTX_FILELIST, CTX_NONE,
371 IT_FLAG_DETECT_GROUPCHANGE);
373 RegisterSortFunc(HKEY("filemime"),
375 CompareFilelistByMime,
376 CompareFilelistByMimeRev,
377 GroupchangeFilelistByMime,
379 RegisterSortFunc(HKEY("filename"),
381 CompareFilelistByName,
382 CompareFilelistByNameRev,
383 GroupchangeFilelistByName,
385 RegisterSortFunc(HKEY("filesize"),
387 CompareFilelistBySize,
388 CompareFilelistBySizeRev,
389 GroupchangeFilelistBySize,
391 RegisterSortFunc(HKEY("filesubject"),
393 CompareFilelistByComment,
394 CompareFilelistByCommentRev,
395 GroupchangeFilelistByComment,
397 RegisterSortFunc(HKEY("fileunsorted"),
399 CompareFilelistBySequence,
400 CompareFilelistBySequence,
401 GroupchangeFilelistBySequence,
404 RegisterNamespace("FILE:NAME", 0, 2, tmplput_FILE_NAME, CTX_FILELIST);
405 RegisterNamespace("FILE:SIZE", 0, 1, tmplput_FILE_SIZE, CTX_FILELIST);
406 RegisterNamespace("FILE:MIMETYPE", 0, 2, tmplput_FILEMIMETYPE, CTX_FILELIST);
407 RegisterNamespace("FILE:COMMENT", 0, 2, tmplput_FILE_COMMENT, CTX_FILELIST);
409 RegisterConditional(HKEY("COND:FILE:ISPIC"), 0, Conditional_FILE_ISPIC, CTX_FILELIST);
411 WebcitAddUrlHandler(HKEY("image"), output_image, 0);
412 WebcitAddUrlHandler(HKEY("display_mime_icon"), display_mime_icon , 0);
413 WebcitAddUrlHandler(HKEY("download_file"), download_file, NEED_URL);
414 WebcitAddUrlHandler(HKEY("upload_file"), upload_file, 0);