* use strbuffer as wprintf backend
[citadel.git] / webcit / downloads.c
index d3ffe37bb5f3fa399fc073b73f5432ab670dd886..600d89de0769cdf0c9196c02eb31293811725296 100644 (file)
 /*
- * $Id: downloads.c 4849 2007-01-08 20:05:56Z ajc $
+ * $Id$
  */
 #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 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("<tr bgcolor=\"#%s\">", (odd ? "DDDDDD" : "FFFFFF"));
+       wprintf("<td>"
+               "<a href=\"download_file/");
+       urlescputs(File->Filename);
+       wprintf("\"><img src=\"display_mime_icon?type=%s\" border=0 align=middle>\n", 
+               File->MimeType);
+       escputs(File->Filename);        wprintf("</a></td>");
+       wprintf("<td>%ld</td>", File->FileSize);
+       wprintf("<td>");        escputs(File->MimeType);        wprintf("</td>");
+       wprintf("<td>");        escputs(File->Comment); wprintf("</td>");
+       wprintf("</tr>\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("<tr bgcolor=\"#%s\"><th colspan = 4>%s</th></tr>", 
+               (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("<div id=\"banner\">\n"
-               "<table class=\"downloads_banner\"><tr><td>"
-               "<span class=\"titlebar\">");
+       wprintf("<div id=\"banner\">\n");
+       wprintf("<h1>");
        snprintf(title, sizeof title, _("Files available for download in %s"), WC->wc_roomname);
        escputs(title);
-       wprintf("</span>"
-               "</td></tr></table>\n"
-               "</div>\n<div id=\"content\">\n"
-       );
+       wprintf("</h1>");
+       wprintf("</div>\n");
+
+       wprintf("<div id=\"content\" class=\"service\">\n");
 
        wprintf("<div class=\"fix_scrollbar_bug\">"
                "<table class=\"downloads_background\"><tr><td>\n");
-       wprintf("<tr><th>%s</th><th>%s</th><th>%s</th></tr>\n",
-                       _("Filename"),
-                       _("Size"),
-                       _("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(comment, buf, 2, '|', sizeof comment);
-               bg = 1 - bg;
-               wprintf("<tr bgcolor=\"#%s\">", (bg ? "DDDDDD" : "FFFFFF"));
-               wprintf("<td>"
-                       "<a href=\"download_file/");
-               urlescputs(filename);
-               wprintf("\"><img src=\"static/diskette_24x.gif\" border=0 align=middle>\n");
-                                       escputs(filename);      wprintf("</a></td>");
-               wprintf("<td>");        escputs(filesize);      wprintf("</td>");
-               wprintf("<td>");        escputs(comment);       wprintf("</td>");
-               wprintf("</tr>\n");
+
+       Order = ibstr("SortOrder");
+       if (!havebstr("SortOrder") || Order > 2)
+               Order = 2; /* <- Unsorted... */
+       SortRow = ibstr("SortBy");
+
+       SortDirections[SortRow] = Order;
+
+       wprintf("<tr>\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("  <th>%s \n"
+                       "      <a href=\"display_room_directory?SortOrder=%d&SortBy=%d\"> \n"
+                       "       <img src=\"%s\" border=\"0\"></a>\n"
+                       "  </th>\n",
+                       RowNames[i],
+                       Order, i,
+                       SortIcons[SortDirections[i]]
+                       );
+
        }
+       wprintf("</tr>\n");
+//<th>%s</th><th>%s</th><th>%s</th><th>%s</th></tr>\n",
+       //);
 
+       if (Files != NULL) {
+               PrintHash(Files, FilePrintTransition, FilePrintEntry);
+               DeleteHash(&Files);
+       }
        wprintf("</table>\n");
 
        /** Now offer the ability to upload files... */
@@ -64,6 +279,7 @@ void display_room_directory(void)
                        "name=\"upload_file_form\""
                        ">\n"
                );
+               wprintf("<input type=\"hidden\" name=\"nonce\" value=\"%d\">\n", WC->nonce);
 
                wprintf(_("Upload a file:"));
                wprintf("&nbsp;<input NAME=\"filename\" SIZE=16 TYPE=\"file\">&nbsp;\n");
@@ -75,12 +291,99 @@ void display_room_directory(void)
        }
 
        wprintf("</div>\n");
+       if (havepics)
+               wprintf("<div class=\"buttons\"><a href=\"display_pictureview&frame=1\">%s</a></div>", _("Slideshow"));
        wDumpContent(1);
 }
 
 
-void download_file(char *filename)
+void display_pictureview(void)
 {
+       char buf[1024];
+       char filename[256];
+       char filesize[256];
+       char mimetype[64];
+       char comment[512];
+       char title[256];
+       int n = 0;
+               
+
+       if (lbstr("frame") == 1) {
+
+               output_headers(1, 1, 2, 0, 0, 0);
+               wprintf("<div id=\"banner\">\n");
+               wprintf("<h1>");
+               snprintf(title, sizeof title, _("Pictures in %s"), WC->wc_roomname);
+               escputs(title);
+               wprintf("</h1>");
+               wprintf("</div>\n");
+               
+               wprintf("<div id=\"content\" class=\"service\">\n");
+
+               wprintf("<div class=\"fix_scrollbar_bug\">"
+                       "<table class=\"downloads_background\"><tr><td>\n");
+
+
+
+               wprintf("<script type=\"text/javascript\" language=\"JavaScript\" > \nvar fadeimages=new Array()\n");
+
+               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);
+                               if (strstr(mimetype, "image") != NULL) {
+                                       wprintf("fadeimages[%d]=[\"download_file/", n);
+                                       escputs(filename);
+                                       wprintf("\", \"\", \"\"]\n");
+
+                                       /*
+                                                          //mimetype);
+                                          escputs(filename);   wprintf("</a></td>");
+                                          wprintf("<td>");     escputs(filesize);      wprintf("</td>");
+                                          wprintf("<td>");     escputs(mimetype);      wprintf("</td>");
+                                          wprintf("<td>");     escputs(comment);       wprintf("</td>");
+                                          wprintf("</tr>\n");
+                                       */
+                                       n++;
+                               }
+                       }
+               wprintf("</script>\n");
+               wprintf("<tr><td><script type=\"text/javascript\" src=\"static/fadeshow.js\">\n</script>\n");
+               wprintf("<script type=\"text/javascript\" >\n");
+               wprintf("new fadeshow(fadeimages, 500, 400, 0, 3000, 1, \"R\");\n");
+               wprintf("</script></td><th>\n");
+               wprintf("</div>\n");
+       }
+       wDumpContent(1);
+
+
+}
+
+extern char* static_dirs[];
+void display_mime_icon(void)
+{
+       char FileBuf[SIZ];
+       const char *FileName;
+       char *MimeType;
+       size_t tlen;
+
+       MimeType = xbstr("type", &tlen);
+       FileName = GetIconFilename(MimeType, tlen);
+
+       if (FileName == NULL)
+               snprintf (FileBuf, SIZ, "%s%s", static_dirs[0], "/diskette_24x.gif");
+       else
+               snprintf (FileBuf, SIZ, "%s%s", static_dirs[3], FileName);
+       output_static(FileBuf);
+
+}
+
+void download_file(void)
+{
+       StrBuf *Buf;
        char buf[256];
        off_t bytes;
        char content_type[256];
@@ -89,7 +392,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->UrlFragment1), sizeof buf);
        unescape_input(buf);
        serv_printf("OPEN %s", buf);
        serv_getln(buf, sizeof buf);
@@ -103,17 +406,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);
+               Buf = read_server_binary(bytes);
                serv_puts("CLOS");
                serv_getln(buf, sizeof buf);
-               http_transmit_thing(content, bytes, content_type, 0);
+               http_transmit_thing(Buf, 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();
        }
 
 }
@@ -122,38 +425,51 @@ void download_file(char *filename)
 
 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) */
 
-       serv_printf("UOPN %s|%s", WC->upload_filename, bstr("description"));
+       MimeType = GuessMimeType(WCC->upload, WCC->upload_length); 
+       serv_printf("UOPN %s|%s|%s", WCC->upload_filename, MimeType, bstr("description"));
        serv_getln(buf, sizeof buf);
        if (buf[0] != '2')
        {
-               strcpy(WC->ImportantMessage, &buf[4]);
+               strcpy(WCC->ImportantMessage, &buf[4]);
                display_room_directory();
                return;
        }
 
-       while (bytes_transmitted < WC->upload_length)
+       while (bytes_transmitted < WCC->upload_length)
        {
                blocksize = 4096;
-               if (blocksize > (WC->upload_length - bytes_transmitted))
+               if (blocksize > (WCC->upload_length - bytes_transmitted))
                {
-                       blocksize = (WC->upload_length - bytes_transmitted);
+                       blocksize = (WCC->upload_length - bytes_transmitted);
                }
                serv_printf("WRIT %d", blocksize);
                serv_getln(buf, sizeof buf);
                if (buf[0] == '7')
                {
                        blocksize = atoi(&buf[4]);
-                       serv_write(&WC->upload[bytes_transmitted], blocksize);
+                       serv_write(&WCC->upload[bytes_transmitted], blocksize);
                        bytes_transmitted += blocksize;
                }
        }
 
        serv_puts("UCLS 1");
        serv_getln(buf, sizeof buf);
-       strcpy(WC->ImportantMessage, &buf[4]);
+       strcpy(WCC->ImportantMessage, &buf[4]);
        display_room_directory();
 }
+
+void 
+InitModule_DOWNLOAD
+(void)
+{
+       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);
+}