X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=webcit%2Fdownloads.c;h=8ec1137380154abe0b9ac4074137b8d12b29de22;hb=8c321fbcc2a64f0d0627562fdf5651442e525ab1;hp=a208e51b7dc317fb4248c7dbe94bcab4ca32344e;hpb=9f145319b92b196662aa51cb2e3d7c392629965e;p=citadel.git diff --git a/webcit/downloads.c b/webcit/downloads.c index a208e51b7..8ec113738 100644 --- a/webcit/downloads.c +++ b/webcit/downloads.c @@ -4,17 +4,213 @@ #include "webcit.h" #include "webserver.h" -void display_room_directory(void) +typedef struct _FileListStruct { + char Filename[256]; + int FilenameLen; + long FileSize; + char MimeType[64]; + int MimeTypeLen; + char Comment[512]; + int CommentLen; + int IsPic; + int Sequence; +}FileListStruct; + + +int CompareFilelistByMime(const void *vFile1, const void *vFile2) +{ + FileListStruct *File1 = (FileListStruct*) GetSearchPayload(vFile1); + FileListStruct *File2 = (FileListStruct*) GetSearchPayload(vFile2); + + if (File1->IsPic != File2->IsPic) + return File1->IsPic > File2->IsPic; + return strcasecmp(File1->MimeType, File2->MimeType); +} +int CompareFilelistByMimeRev(const void *vFile1, const void *vFile2) +{ + FileListStruct *File1 = (FileListStruct*) GetSearchPayload(vFile1); + FileListStruct *File2 = (FileListStruct*) GetSearchPayload(vFile2); + if (File1->IsPic != File2->IsPic) + return File1->IsPic < File2->IsPic; + return strcasecmp(File2->MimeType, File1->MimeType); +} + +int CompareFilelistBySize(const void *vFile1, const void *vFile2) +{ + FileListStruct *File1 = (FileListStruct*) GetSearchPayload(vFile1); + FileListStruct *File2 = (FileListStruct*) GetSearchPayload(vFile2); + if (File1->FileSize == File2->FileSize) + return 0; + return (File1->FileSize > File2->FileSize); +} + +int CompareFilelistBySizeRev(const void *vFile1, const void *vFile2) +{ + FileListStruct *File1 = (FileListStruct*) GetSearchPayload(vFile1); + FileListStruct *File2 = (FileListStruct*) GetSearchPayload(vFile2); + if (File1->FileSize == File2->FileSize) + return 0; + return (File1->FileSize < File2->FileSize); +} + +int CompareFilelistByComment(const void *vFile1, const void *vFile2) +{ + FileListStruct *File1 = (FileListStruct*) GetSearchPayload(vFile1); + FileListStruct *File2 = (FileListStruct*) GetSearchPayload(vFile2); + return strcasecmp(File1->Comment, File2->Comment); +} +int CompareFilelistByCommentRev(const void *vFile1, const void *vFile2) { + FileListStruct *File1 = (FileListStruct*) GetSearchPayload(vFile1); + FileListStruct *File2 = (FileListStruct*) GetSearchPayload(vFile2); + return strcasecmp(File2->Comment, File1->Comment); +} + +int CompareFilelistBySequence(const void *vFile1, const void *vFile2) +{ + FileListStruct *File1 = (FileListStruct*) GetSearchPayload(vFile1); + FileListStruct *File2 = (FileListStruct*) GetSearchPayload(vFile2); + return (File2->Sequence > File1->Sequence); +} + +HashList* LoadFileList(int *HavePic) +{ + FileListStruct *Entry; + HashList *Files; + int HavePics = 0; + int Order; + int sequence = 0; char buf[1024]; - char filename[256]; - char filesize[256]; - char mimetype[64]; - char comment[512]; - int bg = 0; + + serv_puts("RDIR"); + serv_getln(buf, sizeof buf); + if (buf[0] == '1') { + Files = NewHash(1, NULL); + while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) + { + Entry = (FileListStruct*) malloc(sizeof (FileListStruct)); + + Entry->FilenameLen = extract_token( + Entry->Filename, buf, 0, '|', + sizeof(Entry->Filename)); + Entry->FileSize = extract_long(buf, 1); + Entry->MimeTypeLen = extract_token( + Entry->MimeType, buf, 2, '|', + sizeof(Entry->MimeType)); + Entry->CommentLen = extract_token( + Entry->Comment, buf, 3, '|', + sizeof(Entry->Comment)); + + Entry->Sequence = sequence++; + Entry->IsPic = (strstr(Entry->MimeType, "image") != NULL); + if (!HavePics && Entry->IsPic) { + HavePics = 1; + *HavePic = 1; + } + Put(Files, Entry->Filename, + Entry->FilenameLen, + Entry, NULL); + } + Order = ibstr("SortOrder"); + switch (ibstr("SortBy")){ + case 1: /*NAME*/ + SortByHashKey(Files,Order); + break; + case 2: /* SIZE*/ + SortByPayload(Files, (Order)? + CompareFilelistBySize: + CompareFilelistBySizeRev); + break; + case 3: /*MIME*/ + SortByPayload(Files, (Order)? + CompareFilelistByMime: + CompareFilelistByMimeRev); + break; + case 4: /*COMM*/ + SortByPayload(Files, (Order)? + CompareFilelistByComment: + CompareFilelistByCommentRev); + break; + default: + SortByPayload(Files, CompareFilelistBySequence); + } + return Files; + } + else + return NULL; +} + +void FilePrintEntry(const char *FileName, void *vFile, int odd) +{ + FileListStruct *File = (FileListStruct*) vFile; + + wprintf("", (odd ? "DDDDDD" : "FFFFFF")); + wprintf("" + "Filename); + wprintf("\">\n", + File->MimeType); + escputs(File->Filename); wprintf(""); + wprintf("%ld", File->FileSize); + wprintf(""); escputs(File->MimeType); wprintf(""); + wprintf(""); escputs(File->Comment); wprintf(""); + wprintf("\n"); +} + +void FilePrintTransition(void *vFile1, void *vFile2, int odd) +{ + FileListStruct *File1 = (FileListStruct*) vFile1; + FileListStruct *File2 = (FileListStruct*) vFile2; + char StartChar[2] = "\0\0"; + char *SectionName; + + switch (ibstr("SortBy")){ + case 1: /*NAME*/ + if ((File2 != NULL) && + ((File1 == NULL) || + (File1->Filename[0] != File2->Filename[0]))) { + StartChar[0] = File2->Filename[0]; + SectionName = StartChar; + } + else return; + break; + case 2: /* SIZE*/ + return; + case 3: /*MIME*/ + return; /*TODO*/ + break; + case 4: /*COMM*/ + return; + default: + return; + } + + wprintf("%s", + (odd ? "DDDDDD" : "FFFFFF"), SectionName); +} + + +void display_room_directory(void) +{ char title[256]; int havepics = 0; - + HashList *Files; + int Order; + int SortRow; + int i; + + long SortDirections[5] = {2,2,2,2,2}; + const char* SortIcons[3] = { + "static/up_pointer.gif", + "static/down_pointer.gif", + "static/sort_none.gif"}; + char *RowNames[5] = {"", + _("Filename"), + _("Size"), + _("Content"), + _("Description")}; + + Files = LoadFileList (&havepics); output_headers(1, 1, 2, 0, 0, 0); wprintf("
\n"); wprintf("

"); @@ -27,34 +223,47 @@ void display_room_directory(void) wprintf("
" "\n", - _("Filename"), - _("Size"), - _("Content"), - _("Description") - ); - serv_puts("RDIR"); - serv_getln(buf, sizeof buf); - if (buf[0] == '1') while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) - { - extract_token(filename, buf, 0, '|', sizeof filename); - extract_token(filesize, buf, 1, '|', sizeof filesize); - extract_token(mimetype, buf, 2, '|', sizeof mimetype); - extract_token(comment, buf, 3, '|', sizeof comment); - bg = 1 - bg; - wprintf("", (bg ? "DDDDDD" : "FFFFFF")); - wprintf(""); - wprintf(""); - wprintf(""); - wprintf(""); - wprintf("\n"); - if (!havepics && (strstr(mimetype, "image") != NULL)) - havepics = 1; + + Order = ibstr("SortOrder"); + if (!havebstr("SortOrder") || Order > 2) + Order = 2; /* <- Unsorted... */ + SortRow = ibstr("SortBy"); + + SortDirections[SortRow] = Order; + + wprintf("\n"); + for (i = 1; i < 5; i++) { + switch (SortDirections[i]) { + default: + case 0: + Order = 2; + break; + case 1: + Order = 0; + break; + case 2: + Order = 1; + break; + } + + wprintf(" \n", + RowNames[i], + Order, i, + SortIcons[SortDirections[i]] + ); + + } + wprintf("\n"); +//\n", + //); + + if (Files != NULL) { + PrintHash(Files, FilePrintTransition, FilePrintEntry); + DeleteHash(&Files); } wprintf("
\n"); - wprintf("
%s%s%s%s
" - "\n", mimetype); - escputs(filename); wprintf(""); escputs(filesize); wprintf(""); escputs(mimetype); wprintf(""); escputs(comment); wprintf("
%s \n" + " \n" + " \n" + "
%s%s%s%s
\n"); @@ -70,7 +279,7 @@ void display_room_directory(void) "name=\"upload_file_form\"" ">\n" ); - wprintf("\n", WC->nonce); + wprintf("\n", WC->nonce); wprintf(_("Upload a file:")); wprintf("  \n"); @@ -158,9 +367,11 @@ void display_mime_icon(void) { char FileBuf[SIZ]; const char *FileName; + char *MimeType; size_t tlen; - FileName = GetIconFilename(xbstr("type", &tlen), tlen); + MimeType = xbstr("type", &tlen); + FileName = GetIconFilename(MimeType, tlen); if (FileName == NULL) snprintf (FileBuf, SIZ, "%s%s", static_dirs[0], "/diskette_24x.gif"); @@ -170,7 +381,7 @@ void display_mime_icon(void) } -void download_file(char *filename) +void download_file(void) { char buf[256]; off_t bytes; @@ -180,7 +391,7 @@ void download_file(char *filename) /* Setting to nonzero forces a MIME type of application/octet-stream */ int force_download = 1; - safestrncpy(buf, filename, sizeof buf); + safestrncpy(buf, ChrPtr(WC->UrlFragment2), sizeof buf); unescape_input(buf); serv_printf("OPEN %s", buf); serv_getln(buf, sizeof buf); @@ -194,17 +405,17 @@ void download_file(char *filename) extract_token(content_type, &buf[4], 3, '|', sizeof content_type); } output_headers(0, 0, 0, 0, 0, 0); - read_server_binary(content, bytes); + read_server_binary(WC->WBuf, bytes); serv_puts("CLOS"); serv_getln(buf, sizeof buf); - http_transmit_thing(content, bytes, content_type, 0); + http_transmit_thing(content_type, 0); free(content); } else { - wprintf("HTTP/1.1 404 %s\n", &buf[4]); + hprintf("HTTP/1.1 404 %s\n", &buf[4]); output_headers(0, 0, 0, 0, 0, 0); - wprintf("Content-Type: text/plain\r\n"); - wprintf("\r\n"); + hprintf("Content-Type: text/plain\r\n"); wprintf(_("An error occurred while retrieving this file: %s\n"), &buf[4]); + end_burst(); } } @@ -215,9 +426,9 @@ void upload_file(void) { const char *MimeType; char buf[1024]; - size_t bytes_transmitted = 0; - size_t blocksize; - struct wcsession *WCC = WC; /* stack this for faster access (WC is a function) */ + long bytes_transmitted = 0; + long blocksize; + wcsession *WCC = WC; /* stack this for faster access (WC is a function) */ MimeType = GuessMimeType(WCC->upload, WCC->upload_length); serv_printf("UOPN %s|%s|%s", WCC->upload_filename, MimeType, bstr("description")); @@ -251,3 +462,64 @@ void upload_file(void) strcpy(WCC->ImportantMessage, &buf[4]); display_room_directory(); } + + + +/* + * When the browser requests an image file from the Citadel server, + * this function is called to transmit it. + */ +void output_image() +{ + wcsession *WCC = WC; + char buf[SIZ]; + off_t bytes; + const char *MimeType; + + serv_printf("OIMG %s|%s", bstr("name"), bstr("parm")); + serv_getln(buf, sizeof buf); + if (buf[0] == '2') { + bytes = extract_long(&buf[4], 0); + + /** Read it from the server */ + + if (read_server_binary(WCC->WBuf, bytes) > 0) { + serv_puts("CLOS"); + serv_getln(buf, sizeof buf); + + MimeType = GuessMimeType (ChrPtr(WCC->WBuf), StrLength(WCC->WBuf)); + /** Write it to the browser */ + if (!IsEmptyStr(MimeType)) + { + http_transmit_thing(MimeType, 0); + return; + } + } + /* hm... unknown mimetype? fallback to blank gif */ + } + + + /* + * Instead of an ugly 404, send a 1x1 transparent GIF + * when there's no such image on the server. + */ + char blank_gif[SIZ]; + snprintf (blank_gif, SIZ, "%s%s", static_dirs[0], "/blank.gif"); + output_static(blank_gif); +} + + + + +void +InitModule_DOWNLOAD +(void) +{ + WebcitAddUrlHandler(HKEY("image"), output_image, 0); + WebcitAddUrlHandler(HKEY("display_mime_icon"), display_mime_icon , 0); + + WebcitAddUrlHandler(HKEY("display_room_directory"), display_room_directory, 0); + WebcitAddUrlHandler(HKEY("display_pictureview"), display_pictureview, 0); + WebcitAddUrlHandler(HKEY("download_file"), download_file, NEED_URL); + WebcitAddUrlHandler(HKEY("upload_file"), upload_file, 0); +}