]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
From: Henrik Nordstrom <hno@hem.passagen.se>
authorwessels <>
Tue, 21 Jul 1998 04:50:37 +0000 (04:50 +0000)
committerwessels <>
Tue, 21 Jul 1998 04:50:37 +0000 (04:50 +0000)
Changed mime.conf (and related C code) to include additional options to
make it possible for the user to override mime.conf settings. Primary
use is to view a text file that mime.conf says is binary, but it also
allows the user do download a binary file that otherwise gets downloaded
as ascii (and displayed in the browser).
  +download     show a binary download icon in FTP listings
  +view         show a ascii download icon in FTP listings

+download should be set on every mimetype that may be binary files at
some locations. +view should be set when it is known that some files may
be ascii to make it easier for the users to view these files (like the
default mime type).

Had to rewrite most of the ftp listing formatting code, but now should
it be much easier to maintain.

Fixed a minor error in the slash hack.

src/ftp.cc
src/mime.cc
src/protos.h

index be093a643a136d279fe883b79cebd5152e375d4c..a48b4c3c9dfee9fbc02a52c3d1b66c84e07a4af5 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: ftp.cc,v 1.238 1998/07/20 22:16:35 wessels Exp $
+ * $Id: ftp.cc,v 1.239 1998/07/20 22:50:37 wessels Exp $
  *
  * DEBUG: section 9     File Transfer Protocol (FTP)
  * AUTHOR: Harvest Derived
@@ -564,47 +564,53 @@ dots_fill(size_t len)
 static char *
 ftpHtmlifyListEntry(char *line, FtpStateData * ftpState)
 {
-    LOCAL_ARRAY(char, link, 2048 + 40);
-    LOCAL_ARRAY(char, link2, 2048 + 40);
     LOCAL_ARRAY(char, icon, 2048);
+    LOCAL_ARRAY(char, href, 2048 + 40);
+    LOCAL_ARRAY(char, text, 2048);
+    LOCAL_ARRAY(char, size, 2048);
+    LOCAL_ARRAY(char, chdir, 2048 + 40);
+    LOCAL_ARRAY(char, view, 2048 + 40);
+    LOCAL_ARRAY(char, download, 2048 + 40);
+    LOCAL_ARRAY(char, link, 2048 + 40);
     LOCAL_ARRAY(char, html, 8192);
     size_t width = Config.Ftp.list_width;
     ftpListParts *parts;
+    *icon=*href=*text=*size=*chdir=*view=*download=*link=*html='\0';
     if ((int) strlen(line) > 1024) {
        snprintf(html, 8192, "%s\n", line);
        return html;
     }
     /* Handle builtin <dirup> */
     if (!strcmp(line, "<internal-dirup>")) {
+       /* <A HREF="{href}">{icon}</A> <A HREF="{href}">{text}</A> {link} */
        snprintf(icon, 2048, "<IMG BORDER=0 SRC=\"%s\" ALT=\"%-6s\">",
            mimeGetIconURL("internal-dirup"),
            "[DIRUP]");
        if (!ftpState->flags.no_dotdot && !ftpState->flags.root_dir) {
            /* Normal directory */
-           snprintf(link, 2048, "<A HREF=\"%s\">%s</A>",
-               "../",
-               "Parent Directory");
+           strcpy(href, "../");
+           strcpy(text, "Parent Directory");
        } else if (!ftpState->flags.no_dotdot && ftpState->flags.root_dir) {
            /* "Top level" directory */
-           snprintf(link, 2048, "<A HREF=\"%s\">%s</A> (<A HREF=\"%s\">%s</A>)",
-               "%2e%2e/",
-               "Parent Directory",
+           strcpy(href, "%2e%2e/");
+           strcpy(text, "Parent Directory");
+           snprintf(link, 2048, "(<A HREF=\"%s\">%s</A>)",
                "%2f/",
                "Root Directory");
        } else if (ftpState->flags.no_dotdot && !ftpState->flags.root_dir) {
            /* Normal directory where last component is / or ..  */
-           snprintf(link, 2048, "<A HREF=\"%s\">%s</A> (<A HREF=\"%s\">%s</A>)",
-               "%2e%2e/",
-               "Parent Directory",
+           strcpy(href, "%2e%2e/");
+           strcpy(text, "Parent Directory");
+           snprintf(link, 2048, "(<A HREF=\"%s\">%s</A>)",
                "../",
-               "Up");
+               "Back");
        } else {                /* NO_DOTDOT && ROOT_DIR */
            /* "UNIX Root" directory */
-           snprintf(link, 2048, "<A HREF=\"%s\">%s</A>",
-               "../",
-               "Home Directory");
+           strcpy(href, "../");
+           strcpy(text, "Home Directory");
        }
-       snprintf(html, 8192, "%s %s\n", icon, link);
+       snprintf(html, 8192, "<A HREF=\"%s\">%s</A> <A HREF=\"%s\">%s</A> %s\n",
+               href, icon, href, text, link);
        return html;
     }
     if ((parts = ftpListParseParts(line, ftpState->flags)) == NULL) {
@@ -629,69 +635,68 @@ ftpHtmlifyListEntry(char *line, FtpStateData * ftpState)
            *(parts->showname + width - 0) = '\0';
        }
     }
+    /* {icon} {text} . . . {date}{size}{chdir}{view}{download}{link}\n  */
+    xstrncpy(href,rfc1738_escape(parts->name),2048);
+    xstrncpy(text, parts->showname, 2048);
     switch (parts->type) {
     case 'd':
-       snprintf(icon, 2048, "<IMG SRC=\"%s\" ALT=\"%-6s\">",
+       snprintf(icon, 2048, "<IMG BORDER=0 SRC=\"%s\" ALT=\"%-6s\">",
            mimeGetIconURL("internal-dir"),
            "[DIR]");
-       snprintf(link, 2048, "<A HREF=\"%s/\">%s</A>%s",
-           rfc1738_escape(parts->name),
-           parts->showname,
-           dots_fill(strlen(parts->showname)));
-       snprintf(html, 8192, "%s %s  [%s]\n",
-           icon,
-           link,
-           parts->date);
+       strncat(href, "/", 2048);
        break;
     case 'l':
-       snprintf(icon, 2048, "<IMG SRC=\"%s\" ALT=\"%-6s\">",
+       snprintf(icon, 2048, "<IMG BORDER=0 SRC=\"%s\" ALT=\"%-6s\">",
            mimeGetIconURL("internal-link"),
            "[LINK]");
-       snprintf(link, 2048, "<A HREF=\"%s\">%s</A>%s",
-           rfc1738_escape(parts->name),
-           parts->showname,
-           dots_fill(strlen(parts->showname)));
        /* sometimes there is an 'l' flag, but no "->" link */
        if (parts->link)
-           snprintf(link2, 2048, "<A HREF=\"%s\">%s</A>",
+           snprintf(link, 2048, " -> <A HREF=\"%s\">%s</A>",
                rfc1738_escape(parts->link),
                parts->link);
-       snprintf(html, 8192, "%s %s  [%s] -> %s\n",
-           icon,
-           link,
-           parts->date,
-           link2);
        break;
     case '\0':
-       snprintf(icon, 2048, "<IMG SRC=\"%s\" ALT=\"%-6s\">",
+       snprintf(icon, 2048, "<IMG BORDER=0 SRC=\"%s\" ALT=\"%-6s\">",
            mimeGetIconURL(parts->name),
            "[UNKNOWN]");
-       snprintf(link, 2048, "<A HREF=\"%s\">%s</A>",
+       snprintf(chdir, 2048, " <A HREF=\"%s/;type=d\"><IMG BORDER=0 SRC=\"%s\" "
+                               "ALT=\"[DIR]\"></A>",
            rfc1738_escape(parts->name),
-           parts->name);
-       snprintf(link2, 2048, "(<A HREF=\"%s/;type=d\">chdir</A>)",
-           rfc1738_escape(parts->name));
-       snprintf(html, 8192, "%s %s %s\n",
-           icon,
-           link,
-           link2);
+           mimeGetIconURL("internal-dir"));
        break;
     case '-':
     default:
-       snprintf(icon, 2048, "<IMG SRC=\"%s\" ALT=\"%-6s\">",
+       snprintf(icon, 2048, "<IMG BORDER=0 SRC=\"%s\" ALT=\"%-6s\">",
            mimeGetIconURL(parts->name),
            "[FILE]");
-       snprintf(link, 2048, "<A HREF=\"%s\">%s</A>%s",
-           rfc1738_escape(parts->name),
-           parts->showname,
-           dots_fill(strlen(parts->showname)));
-       snprintf(html, 8192, "%s %s  [%s] %6dk\n",
-           icon,
-           link,
-           parts->date,
-           parts->size);
+       snprintf(size, 2048, " %6dk", parts->size);
        break;
     }
+    if (parts->type != 'd') {
+       if (mimeGetViewOption(parts->name)) {
+           snprintf(view, 2048, " <A HREF=\"%s;type=a\"><IMG BORDER=0 SRC=\"%s\" "
+                                   "ALT=\"[VIEW]\"></A>",
+               href, mimeGetIconURL("internal-view"));
+       }
+       if (mimeGetDownloadOption(parts->name)) {
+           snprintf(download, 2048, " <A HREF=\"%s;type=i\"><IMG BORDER=0 SRC=\"%s\" "
+                                   "ALT=\"[DOWNLOAD]\"></A>",
+               href, mimeGetIconURL("internal-download"));
+       }
+    }
+    /* <A HREF="{href}">{icon}</A> <A HREF="{href}">{text}</A> . . . {date}{size}{chdir}{view}{download}{link}\n  */
+    if (parts->type != '\0') {
+       snprintf(html, 8192, "<A HREF=\"%s\">%s</A> <A HREF=\"%s\">%s</A>%s "
+                               "%s%8s%s%s%s%s\n",
+           href, icon, href, text, dots_fill(strlen(text)),
+           parts->date, size, chdir, view, download, link);
+    } else {
+       /* Plain listing. {icon} {text} ... {chdir}{view}{download} */
+       snprintf(html, 8192, "<A HREF=\"%s\">%s</A> <A HREF=\"%s\">%s</A>%s "
+                               "%s%s%s%s\n",
+           href, icon, href, text, dots_fill(strlen(text)),
+           chdir, view, download, link);
+    }
     ftpListPartsFree(&parts);
     return html;
 }
@@ -2074,8 +2079,10 @@ ftpFail(FtpStateData * ftpState)
     ErrorState *err;
     debug(9, 3) ("ftpFail\n");
     /* Try the / hack to support "Netscape" FTP URL's for retreiving files */
-    if (!ftpState->flags.isdir &&
-       !ftpState->flags.try_slash_hack) {
+    if (!ftpState->flags.isdir &&                      /* Not a directory */
+       !ftpState->flags.try_slash_hack &&              /* Not in slash hack */
+       ftpState->mdtm <= 0 && ftpState->size < 0 &&    /* Not known as a file */
+       !strNCaseCmp(ftpState->request->urlpath, "/%2f", 4)) { /* No slash encoded */
        switch (ftpState->state) {
        case SENT_CWD:
        case SENT_RETR:
index a72c3e030effc06c2c7e3694399829f6c539386c..014b9e502b876da59338f0b09b32564f98b362c3 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: mime.cc,v 1.70 1998/07/20 22:42:23 wessels Exp $
+ * $Id: mime.cc,v 1.71 1998/07/20 22:50:38 wessels Exp $
  *
  * DEBUG: section 25    MIME Parsing
  * AUTHOR: Harvest Derived
@@ -115,6 +115,7 @@ typedef struct _mime_entry {
     char *content_type;
     char *content_encoding;
     char transfer_mode;
+    unsigned int view_option:1,download_option:1;
     struct _mime_entry *next;
 } mimeEntry;
 
@@ -288,16 +289,34 @@ mime_get_auth(const char *hdr, const char *auth_scheme, const char **auth_field)
     return base64_decode(t);
 }
 
-char *
-mimeGetIcon(const char *fn)
+static mimeEntry *
+mimeGetEntry(const char *fn, int skip_encodings)
 {
     mimeEntry *m;
+    char *t;
+    char *name = xstrdup(fn);
+try_again:
     for (m = MimeTable; m; m = m->next) {
-       if (m->icon == NULL)
-           continue;
-       if (regexec(&m->compiled_pattern, fn, 0, 0, 0) == 0)
+       if (regexec(&m->compiled_pattern, name, 0, 0, 0) == 0)
            break;
     }
+    if (skip_encodings && m != NULL && !strcmp(m->content_type, dash_str)) {
+       /* Assume we matched /\.\w$/ and cut off the last extension */
+       if ((t = strrchr(name, '.'))) {
+           *t = '\0';
+           goto try_again;
+       }
+       /* What? A encoding without a extension? */
+       m=NULL;
+    }
+    xfree(name);
+    return m;
+}
+
+char *
+mimeGetIcon(const char *fn)
+{
+    mimeEntry *m = mimeGetEntry(fn, 1);
     if (m == NULL)
        return NULL;
     if (!strcmp(m->icon, dash_str))
@@ -317,25 +336,7 @@ mimeGetIconURL(const char *fn)
 char *
 mimeGetContentType(const char *fn)
 {
-    mimeEntry *m;
-    char *name = xstrdup(fn);
-    char *t;
-try_again:
-    for (m = MimeTable; m; m = m->next) {
-       if (m->content_type == NULL)
-           continue;
-       if (regexec(&m->compiled_pattern, name, 0, 0, 0) == 0)
-           break;
-    }
-    if (!strcmp(m->content_type, dash_str)) {
-       /* Assume we matched /\.\w$/ and cut off the last extension */
-       if ((t = strrchr(name, '.'))) {
-           *t = '\0';
-           goto try_again;
-       }
-       /* What? A encoding without a extension? */
-    }
-    xfree(name);
+    mimeEntry *m = mimeGetEntry(fn, 1);
     if (m == NULL)
        return NULL;
     if (!strcmp(m->content_type, dash_str))
@@ -346,13 +347,7 @@ try_again:
 char *
 mimeGetContentEncoding(const char *fn)
 {
-    mimeEntry *m;
-    for (m = MimeTable; m; m = m->next) {
-       if (m->content_encoding == NULL)
-           continue;
-       if (regexec(&m->compiled_pattern, fn, 0, 0, 0) == 0)
-           break;
-    }
+    mimeEntry *m = mimeGetEntry(fn, 0);
     if (m == NULL)
        return NULL;
     if (!strcmp(m->content_encoding, dash_str))
@@ -363,14 +358,24 @@ mimeGetContentEncoding(const char *fn)
 char
 mimeGetTransferMode(const char *fn)
 {
-    mimeEntry *m;
-    for (m = MimeTable; m; m = m->next) {
-       if (regexec(&m->compiled_pattern, fn, 0, 0, 0) == 0)
-           break;
-    }
+    mimeEntry *m = mimeGetEntry(fn, 0);
     return m ? m->transfer_mode : 'I';
 }
 
+int
+mimeGetDownloadOption(const char *fn)
+{
+    mimeEntry *m = mimeGetEntry(fn, 1);
+    return m ? m->download_option : 0;
+}
+
+int
+mimeGetViewOption(const char *fn)
+{
+    mimeEntry *m = mimeGetEntry(fn, 0);
+    return m ? m->view_option : 0;
+}
+
 void
 mimeInit(char *filename)
 {
@@ -383,6 +388,9 @@ mimeInit(char *filename)
     char *type;
     char *encoding;
     char *mode;
+    char *option;
+    int view_option;
+    int download_option;
     regex_t re;
     mimeEntry *m;
     int re_flags = REG_EXTENDED | REG_NOSUB | REG_ICASE;
@@ -424,6 +432,16 @@ mimeInit(char *filename)
            debug(25, 1) ("mimeInit: parse error: '%s'\n", buf);
            continue;
        }
+       download_option=0;
+       view_option=0;
+       while ((option = strtok(NULL, w_space)) != NULL) {
+           if (!strcmp(option,"+download"))
+               download_option = 1;
+           else if (!strcmp(option,"+view"))
+               view_option = 1;
+           else 
+               debug(25, 1) ("mimeInit: unknown option: '%s' (%s)\n", buf, option);
+       }
        if (regcomp(&re, pattern, re_flags) != 0) {
            debug(25, 1) ("mimeInit: regcomp error: '%s'\n", buf);
            continue;
@@ -440,6 +458,8 @@ mimeInit(char *filename)
            m->transfer_mode = 'A';
        else
            m->transfer_mode = 'I';
+       m->view_option = view_option;
+       m->download_option = download_option;
        *MimeTableTail = m;
        MimeTableTail = &m->next;
        debug(25, 5) ("mimeInit: added '%s'\n", buf);
index 3a863e584c43382e1347806db0bfe192056e731e..1499a09fa54b5ee318d223a21491d0353a9408c7 100644 (file)
@@ -520,6 +520,8 @@ extern char *mimeGetContentType(const char *fn);
 extern char *mimeGetIcon(const char *fn);
 extern char *mimeGetIconURL(const char *fn);
 extern char mimeGetTransferMode(const char *fn);
+extern int mimeGetDownloadOption(const char *fn);
+extern int mimeGetViewOption(const char *fn);
 
 extern int mcastSetTtl(int, int);
 extern IPH mcastJoinGroups;