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
, 0);
440 WebcitAddUrlHandler(HKEY("display_mime_icon"), display_mime_icon
, 0);
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);