File Annotation
Not logged in
5cf1206dfa 2008-05-15       drh: /*
5cf1206dfa 2008-05-15       drh: ** Copyright (c) 2007 D. Richard Hipp
5cf1206dfa 2008-05-15       drh: **
5cf1206dfa 2008-05-15       drh: ** This program is free software; you can redistribute it and/or
5cf1206dfa 2008-05-15       drh: ** modify it under the terms of the GNU General Public
5cf1206dfa 2008-05-15       drh: ** License version 2 as published by the Free Software Foundation.
5cf1206dfa 2008-05-15       drh: **
5cf1206dfa 2008-05-15       drh: ** This program is distributed in the hope that it will be useful,
5cf1206dfa 2008-05-15       drh: ** but WITHOUT ANY WARRANTY; without even the implied warranty of
5cf1206dfa 2008-05-15       drh: ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
5cf1206dfa 2008-05-15       drh: ** General Public License for more details.
5cf1206dfa 2008-05-15       drh: **
5cf1206dfa 2008-05-15       drh: ** You should have received a copy of the GNU General Public
5cf1206dfa 2008-05-15       drh: ** License along with this library; if not, write to the
5cf1206dfa 2008-05-15       drh: ** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
5cf1206dfa 2008-05-15       drh: ** Boston, MA  02111-1307, USA.
5cf1206dfa 2008-05-15       drh: **
5cf1206dfa 2008-05-15       drh: ** Author contact information:
5cf1206dfa 2008-05-15       drh: **   drh@hwaci.com
5cf1206dfa 2008-05-15       drh: **   http://www.hwaci.com/drh/
5cf1206dfa 2008-05-15       drh: **
5cf1206dfa 2008-05-15       drh: *******************************************************************************
5cf1206dfa 2008-05-15       drh: **
5cf1206dfa 2008-05-15       drh: ** This file contains code to implement the "/doc" web page and related
5cf1206dfa 2008-05-15       drh: ** pages.
5cf1206dfa 2008-05-15       drh: */
5cf1206dfa 2008-05-15       drh: #include "config.h"
5cf1206dfa 2008-05-15       drh: #include "doc.h"
5cf1206dfa 2008-05-15       drh: #include <assert.h>
5cf1206dfa 2008-05-15       drh: 
5cf1206dfa 2008-05-15       drh: /*
7303bfeb12 2008-11-17       drh: ** Try to guess the mimetype from content.
7303bfeb12 2008-11-17       drh: **
7303bfeb12 2008-11-17       drh: ** If the content is pure text, return NULL.
7303bfeb12 2008-11-17       drh: **
7303bfeb12 2008-11-17       drh: ** For image types, attempt to return an appropriate mimetype
7303bfeb12 2008-11-17       drh: ** name like "image/gif" or "image/jpeg".
7303bfeb12 2008-11-17       drh: **
7303bfeb12 2008-11-17       drh: ** For any other binary type, return "unknown/unknown".
7303bfeb12 2008-11-17       drh: */
7303bfeb12 2008-11-17       drh: const char *mimetype_from_content(Blob *pBlob){
7303bfeb12 2008-11-17       drh:   int i;
7303bfeb12 2008-11-17       drh:   int n;
7303bfeb12 2008-11-17       drh:   const unsigned char *x;
7303bfeb12 2008-11-17       drh: 
7303bfeb12 2008-11-17       drh:   static const char isBinary[] = {
7303bfeb12 2008-11-17       drh:      1, 1, 1, 1,  1, 1, 1, 1,    1, 0, 0, 1,  0, 0, 1, 1,
7303bfeb12 2008-11-17       drh:      1, 1, 1, 1,  1, 1, 1, 1,    1, 1, 1, 0,  1, 1, 1, 1,
7303bfeb12 2008-11-17       drh:   };
7303bfeb12 2008-11-17       drh: 
7303bfeb12 2008-11-17       drh:   /* A table of mimetypes based on file content prefixes
7303bfeb12 2008-11-17       drh:   */
7303bfeb12 2008-11-17       drh:   static const struct {
7303bfeb12 2008-11-17       drh:     const char *zPrefix;       /* The file prefix */
7303bfeb12 2008-11-17       drh:     int size;                  /* Length of the prefix */
7303bfeb12 2008-11-17       drh:     const char *zMimetype;     /* The corresponding mimetype */
7303bfeb12 2008-11-17       drh:   } aMime[] = {
7303bfeb12 2008-11-17       drh:     { "GIF87a",                  6, "image/gif"  },
7303bfeb12 2008-11-17       drh:     { "GIF89a",                  6, "image/gif"  },
7303bfeb12 2008-11-17       drh:     { "\211PNG\r\n\032\r",       8, "image/png"  },
7303bfeb12 2008-11-17       drh:     { "\377\332\377",            3, "image/jpeg" },
7303bfeb12 2008-11-17       drh:   };
7303bfeb12 2008-11-17       drh: 
7303bfeb12 2008-11-17       drh:   x = (const unsigned char*)blob_buffer(pBlob);
7303bfeb12 2008-11-17       drh:   n = blob_size(pBlob);
7303bfeb12 2008-11-17       drh:   for(i=0; i<n; i++){
7303bfeb12 2008-11-17       drh:     unsigned char c = x[i];
7303bfeb12 2008-11-17       drh:     if( c<=0x1f && isBinary[c] ){
7303bfeb12 2008-11-17       drh:       break;
7303bfeb12 2008-11-17       drh:     }
7303bfeb12 2008-11-17       drh:   }
7303bfeb12 2008-11-17       drh:   if( i>=n ){
7303bfeb12 2008-11-17       drh:     return 0;   /* Plain text */
7303bfeb12 2008-11-17       drh:   }
7303bfeb12 2008-11-17       drh:   for(i=0; i<sizeof(aMime)/sizeof(aMime[0]); i++){
7303bfeb12 2008-11-17       drh:     if( n>=aMime[i].size && memcmp(x, aMime[i].zPrefix, aMime[i].size)==0 ){
7303bfeb12 2008-11-17       drh:       return aMime[i].zMimetype;
7303bfeb12 2008-11-17       drh:     }
7303bfeb12 2008-11-17       drh:   }
7303bfeb12 2008-11-17       drh:   return "unknown/unknown";
7303bfeb12 2008-11-17       drh: }
7303bfeb12 2008-11-17       drh: 
7303bfeb12 2008-11-17       drh: /*
5cf1206dfa 2008-05-15       drh: ** Guess the mime-type of a document based on its name.
5cf1206dfa 2008-05-15       drh: */
5cf1206dfa 2008-05-15       drh: const char *mimetype_from_name(const char *zName){
5cf1206dfa 2008-05-15       drh:   const char *z;
5cf1206dfa 2008-05-15       drh:   int i;
8e66784522 2008-08-30       drh:   int first, last;
8e66784522 2008-08-30       drh:   int len;
5cf1206dfa 2008-05-15       drh:   char zSuffix[20];
8e66784522 2008-08-30       drh: 
8e66784522 2008-08-30       drh:   /* A table of mimetypes based on file suffixes.
8e66784522 2008-08-30       drh:   ** Suffixes must be in sorted order so that we can do a binary
8e66784522 2008-08-30       drh:   ** search to find the mime-type
8e66784522 2008-08-30       drh:   */
5cf1206dfa 2008-05-15       drh:   static const struct {
8e66784522 2008-08-30       drh:     const char *zSuffix;       /* The file suffix */
8e66784522 2008-08-30       drh:     int size;                  /* Length of the suffix */
8e66784522 2008-08-30       drh:     const char *zMimetype;     /* The corresponding mimetype */
5cf1206dfa 2008-05-15       drh:   } aMime[] = {
8e66784522 2008-08-30       drh:     { "ai",         2, "application/postscript"            },
8e66784522 2008-08-30       drh:     { "aif",        3, "audio/x-aiff"                      },
8e66784522 2008-08-30       drh:     { "aifc",       4, "audio/x-aiff"                      },
8e66784522 2008-08-30       drh:     { "aiff",       4, "audio/x-aiff"                      },
8e66784522 2008-08-30       drh:     { "arj",        3, "application/x-arj-compressed"      },
8e66784522 2008-08-30       drh:     { "asc",        3, "text/plain"                        },
8e66784522 2008-08-30       drh:     { "asf",        3, "video/x-ms-asf"                    },
8e66784522 2008-08-30       drh:     { "asx",        3, "video/x-ms-asx"                    },
8e66784522 2008-08-30       drh:     { "au",         2, "audio/ulaw"                        },
8e66784522 2008-08-30       drh:     { "avi",        3, "video/x-msvideo"                   },
8e66784522 2008-08-30       drh:     { "bat",        3, "application/x-msdos-program"       },
8e66784522 2008-08-30       drh:     { "bcpio",      5, "application/x-bcpio"               },
8e66784522 2008-08-30       drh:     { "bin",        3, "application/octet-stream"          },
23e96cf795 2009-01-30       drh:     { "c",          1, "text/plain"                        },
8e66784522 2008-08-30       drh:     { "cc",         2, "text/plain"                        },
23e96cf795 2009-01-30       drh:     { "ccad",       4, "application/clariscad"             },
8e66784522 2008-08-30       drh:     { "cdf",        3, "application/x-netcdf"              },
8e66784522 2008-08-30       drh:     { "class",      5, "application/octet-stream"          },
8e66784522 2008-08-30       drh:     { "cod",        3, "application/vnd.rim.cod"           },
8e66784522 2008-08-30       drh:     { "com",        3, "application/x-msdos-program"       },
8e66784522 2008-08-30       drh:     { "cpio",       4, "application/x-cpio"                },
8e66784522 2008-08-30       drh:     { "cpt",        3, "application/mac-compactpro"        },
8e66784522 2008-08-30       drh:     { "csh",        3, "application/x-csh"                 },
8e66784522 2008-08-30       drh:     { "css",        3, "text/css"                          },
8e66784522 2008-08-30       drh:     { "dcr",        3, "application/x-director"            },
8e66784522 2008-08-30       drh:     { "deb",        3, "application/x-debian-package"      },
8e66784522 2008-08-30       drh:     { "dir",        3, "application/x-director"            },
8e66784522 2008-08-30       drh:     { "dl",         2, "video/dl"                          },
8e66784522 2008-08-30       drh:     { "dms",        3, "application/octet-stream"          },
8e66784522 2008-08-30       drh:     { "doc",        3, "application/msword"                },
8e66784522 2008-08-30       drh:     { "drw",        3, "application/drafting"              },
8e66784522 2008-08-30       drh:     { "dvi",        3, "application/x-dvi"                 },
8e66784522 2008-08-30       drh:     { "dwg",        3, "application/acad"                  },
8e66784522 2008-08-30       drh:     { "dxf",        3, "application/dxf"                   },
8e66784522 2008-08-30       drh:     { "dxr",        3, "application/x-director"            },
8e66784522 2008-08-30       drh:     { "eps",        3, "application/postscript"            },
8e66784522 2008-08-30       drh:     { "etx",        3, "text/x-setext"                     },
8e66784522 2008-08-30       drh:     { "exe",        3, "application/octet-stream"          },
8e66784522 2008-08-30       drh:     { "ez",         2, "application/andrew-inset"          },
23e96cf795 2009-01-30       drh:     { "f",          1, "text/plain"                        },
8e66784522 2008-08-30       drh:     { "f90",        3, "text/plain"                        },
8e66784522 2008-08-30       drh:     { "fli",        3, "video/fli"                         },
8e66784522 2008-08-30       drh:     { "flv",        3, "video/flv"                         },
8e66784522 2008-08-30       drh:     { "gif",        3, "image/gif"                         },
8e66784522 2008-08-30       drh:     { "gl",         2, "video/gl"                          },
8e66784522 2008-08-30       drh:     { "gtar",       4, "application/x-gtar"                },
8e66784522 2008-08-30       drh:     { "gz",         2, "application/x-gzip"                },
8e66784522 2008-08-30       drh:     { "hdf",        3, "application/x-hdf"                 },
8e66784522 2008-08-30       drh:     { "hh",         2, "text/plain"                        },
8e66784522 2008-08-30       drh:     { "hqx",        3, "application/mac-binhex40"          },
8e66784522 2008-08-30       drh:     { "h",          1, "text/plain"                        },
8e66784522 2008-08-30       drh:     { "htm",        3, "text/html"                         },
fa1c7d598f 2008-09-23       drh:     { "html",       4, "text/html"                         },
8e66784522 2008-08-30       drh:     { "ice",        3, "x-conference/x-cooltalk"           },
8e66784522 2008-08-30       drh:     { "ief",        3, "image/ief"                         },
8e66784522 2008-08-30       drh:     { "iges",       4, "model/iges"                        },
8e66784522 2008-08-30       drh:     { "igs",        3, "model/iges"                        },
8e66784522 2008-08-30       drh:     { "ips",        3, "application/x-ipscript"            },
8e66784522 2008-08-30       drh:     { "ipx",        3, "application/x-ipix"                },
8e66784522 2008-08-30       drh:     { "jad",        3, "text/vnd.sun.j2me.app-descriptor"  },
8e66784522 2008-08-30       drh:     { "jar",        3, "application/java-archive"          },
8e66784522 2008-08-30       drh:     { "jpeg",       4, "image/jpeg"                        },
8e66784522 2008-08-30       drh:     { "jpe",        3, "image/jpeg"                        },
8e66784522 2008-08-30       drh:     { "jpg",        3, "image/jpeg"                        },
8e66784522 2008-08-30       drh:     { "js",         2, "application/x-javascript"          },
8e66784522 2008-08-30       drh:     { "kar",        3, "audio/midi"                        },
8e66784522 2008-08-30       drh:     { "latex",      5, "application/x-latex"               },
8e66784522 2008-08-30       drh:     { "lha",        3, "application/octet-stream"          },
8e66784522 2008-08-30       drh:     { "lsp",        3, "application/x-lisp"                },
8e66784522 2008-08-30       drh:     { "lzh",        3, "application/octet-stream"          },
23e96cf795 2009-01-30       drh:     { "m",          1, "text/plain"                        },
8e66784522 2008-08-30       drh:     { "m3u",        3, "audio/x-mpegurl"                   },
8e66784522 2008-08-30       drh:     { "man",        3, "application/x-troff-man"           },
8e66784522 2008-08-30       drh:     { "me",         2, "application/x-troff-me"            },
8e66784522 2008-08-30       drh:     { "mesh",       4, "model/mesh"                        },
8e66784522 2008-08-30       drh:     { "mid",        3, "audio/midi"                        },
8e66784522 2008-08-30       drh:     { "midi",       4, "audio/midi"                        },
8e66784522 2008-08-30       drh:     { "mif",        3, "application/x-mif"                 },
8e66784522 2008-08-30       drh:     { "mime",       4, "www/mime"                          },
8e66784522 2008-08-30       drh:     { "movie",      5, "video/x-sgi-movie"                 },
8e66784522 2008-08-30       drh:     { "mov",        3, "video/quicktime"                   },
8e66784522 2008-08-30       drh:     { "mp2",        3, "audio/mpeg"                        },
8e66784522 2008-08-30       drh:     { "mp2",        3, "video/mpeg"                        },
8e66784522 2008-08-30       drh:     { "mp3",        3, "audio/mpeg"                        },
8e66784522 2008-08-30       drh:     { "mpeg",       4, "video/mpeg"                        },
8e66784522 2008-08-30       drh:     { "mpe",        3, "video/mpeg"                        },
8e66784522 2008-08-30       drh:     { "mpga",       4, "audio/mpeg"                        },
8e66784522 2008-08-30       drh:     { "mpg",        3, "video/mpeg"                        },
8e66784522 2008-08-30       drh:     { "ms",         2, "application/x-troff-ms"            },
8e66784522 2008-08-30       drh:     { "msh",        3, "model/mesh"                        },
8e66784522 2008-08-30       drh:     { "nc",         2, "application/x-netcdf"              },
8e66784522 2008-08-30       drh:     { "oda",        3, "application/oda"                   },
8e66784522 2008-08-30       drh:     { "ogg",        3, "application/ogg"                   },
8e66784522 2008-08-30       drh:     { "ogm",        3, "application/ogg"                   },
8e66784522 2008-08-30       drh:     { "pbm",        3, "image/x-portable-bitmap"           },
8e66784522 2008-08-30       drh:     { "pdb",        3, "chemical/x-pdb"                    },
8e66784522 2008-08-30       drh:     { "pdf",        3, "application/pdf"                   },
8e66784522 2008-08-30       drh:     { "pgm",        3, "image/x-portable-graymap"          },
8e66784522 2008-08-30       drh:     { "pgn",        3, "application/x-chess-pgn"           },
8e66784522 2008-08-30       drh:     { "pgp",        3, "application/pgp"                   },
8e66784522 2008-08-30       drh:     { "pl",         2, "application/x-perl"                },
8e66784522 2008-08-30       drh:     { "pm",         2, "application/x-perl"                },
8e66784522 2008-08-30       drh:     { "png",        3, "image/png"                         },
8e66784522 2008-08-30       drh:     { "pnm",        3, "image/x-portable-anymap"           },
8e66784522 2008-08-30       drh:     { "pot",        3, "application/mspowerpoint"          },
8e66784522 2008-08-30       drh:     { "ppm",        3, "image/x-portable-pixmap"           },
8e66784522 2008-08-30       drh:     { "pps",        3, "application/mspowerpoint"          },
8e66784522 2008-08-30       drh:     { "ppt",        3, "application/mspowerpoint"          },
8e66784522 2008-08-30       drh:     { "ppz",        3, "application/mspowerpoint"          },
8e66784522 2008-08-30       drh:     { "pre",        3, "application/x-freelance"           },
8e66784522 2008-08-30       drh:     { "prt",        3, "application/pro_eng"               },
8e66784522 2008-08-30       drh:     { "ps",         2, "application/postscript"            },
8e66784522 2008-08-30       drh:     { "qt",         2, "video/quicktime"                   },
8e66784522 2008-08-30       drh:     { "ra",         2, "audio/x-realaudio"                 },
8e66784522 2008-08-30       drh:     { "ram",        3, "audio/x-pn-realaudio"              },
8e66784522 2008-08-30       drh:     { "rar",        3, "application/x-rar-compressed"      },
8e66784522 2008-08-30       drh:     { "ras",        3, "image/cmu-raster"                  },
8e66784522 2008-08-30       drh:     { "ras",        3, "image/x-cmu-raster"                },
8e66784522 2008-08-30       drh:     { "rgb",        3, "image/x-rgb"                       },
8e66784522 2008-08-30       drh:     { "rm",         2, "audio/x-pn-realaudio"              },
8e66784522 2008-08-30       drh:     { "roff",       4, "application/x-troff"               },
8e66784522 2008-08-30       drh:     { "rpm",        3, "audio/x-pn-realaudio-plugin"       },
8e66784522 2008-08-30       drh:     { "rtf",        3, "application/rtf"                   },
8e66784522 2008-08-30       drh:     { "rtf",        3, "text/rtf"                          },
8e66784522 2008-08-30       drh:     { "rtx",        3, "text/richtext"                     },
8e66784522 2008-08-30       drh:     { "scm",        3, "application/x-lotusscreencam"      },
8e66784522 2008-08-30       drh:     { "set",        3, "application/set"                   },
8e66784522 2008-08-30       drh:     { "sgml",       4, "text/sgml"                         },
8e66784522 2008-08-30       drh:     { "sgm",        3, "text/sgml"                         },
8e66784522 2008-08-30       drh:     { "sh",         2, "application/x-sh"                  },
8e66784522 2008-08-30       drh:     { "shar",       4, "application/x-shar"                },
8e66784522 2008-08-30       drh:     { "silo",       4, "model/mesh"                        },
8e66784522 2008-08-30       drh:     { "sit",        3, "application/x-stuffit"             },
8e66784522 2008-08-30       drh:     { "skd",        3, "application/x-koan"                },
8e66784522 2008-08-30       drh:     { "skm",        3, "application/x-koan"                },
8e66784522 2008-08-30       drh:     { "skp",        3, "application/x-koan"                },
8e66784522 2008-08-30       drh:     { "skt",        3, "application/x-koan"                },
8e66784522 2008-08-30       drh:     { "smi",        3, "application/smil"                  },
8e66784522 2008-08-30       drh:     { "smil",       4, "application/smil"                  },
8e66784522 2008-08-30       drh:     { "snd",        3, "audio/basic"                       },
8e66784522 2008-08-30       drh:     { "sol",        3, "application/solids"                },
8e66784522 2008-08-30       drh:     { "spl",        3, "application/x-futuresplash"        },
8e66784522 2008-08-30       drh:     { "src",        3, "application/x-wais-source"         },
8e66784522 2008-08-30       drh:     { "step",       4, "application/STEP"                  },
8e66784522 2008-08-30       drh:     { "stl",        3, "application/SLA"                   },
8e66784522 2008-08-30       drh:     { "stp",        3, "application/STEP"                  },
8e66784522 2008-08-30       drh:     { "sv4cpio",    7, "application/x-sv4cpio"             },
8e66784522 2008-08-30       drh:     { "sv4crc",     6, "application/x-sv4crc"              },
8e66784522 2008-08-30       drh:     { "swf",        3, "application/x-shockwave-flash"     },
8e66784522 2008-08-30       drh:     { "t",          1, "application/x-troff"               },
8e66784522 2008-08-30       drh:     { "tar",        3, "application/x-tar"                 },
8e66784522 2008-08-30       drh:     { "tcl",        3, "application/x-tcl"                 },
8e66784522 2008-08-30       drh:     { "tex",        3, "application/x-tex"                 },
8e66784522 2008-08-30       drh:     { "texi",       4, "application/x-texinfo"             },
8e66784522 2008-08-30       drh:     { "texinfo",    7, "application/x-texinfo"             },
8e66784522 2008-08-30       drh:     { "tgz",        3, "application/x-tar-gz"              },
8e66784522 2008-08-30       drh:     { "tiff",       4, "image/tiff"                        },
8e66784522 2008-08-30       drh:     { "tif",        3, "image/tiff"                        },
8e66784522 2008-08-30       drh:     { "tr",         2, "application/x-troff"               },
8e66784522 2008-08-30       drh:     { "tsi",        3, "audio/TSP-audio"                   },
8e66784522 2008-08-30       drh:     { "tsp",        3, "application/dsptype"               },
8e66784522 2008-08-30       drh:     { "tsv",        3, "text/tab-separated-values"         },
8e66784522 2008-08-30       drh:     { "txt",        3, "text/plain"                        },
8e66784522 2008-08-30       drh:     { "unv",        3, "application/i-deas"                },
8e66784522 2008-08-30       drh:     { "ustar",      5, "application/x-ustar"               },
8e66784522 2008-08-30       drh:     { "vcd",        3, "application/x-cdlink"              },
8e66784522 2008-08-30       drh:     { "vda",        3, "application/vda"                   },
8e66784522 2008-08-30       drh:     { "viv",        3, "video/vnd.vivo"                    },
23e96cf795 2009-01-30       drh:     { "vivo",       4, "video/vnd.vivo"                    },
8e66784522 2008-08-30       drh:     { "vrml",       4, "model/vrml"                        },
8e66784522 2008-08-30       drh:     { "wav",        3, "audio/x-wav"                       },
8e66784522 2008-08-30       drh:     { "wax",        3, "audio/x-ms-wax"                    },
8e66784522 2008-08-30       drh:     { "wiki",       4, "application/x-fossil-wiki"         },
8e66784522 2008-08-30       drh:     { "wma",        3, "audio/x-ms-wma"                    },
8e66784522 2008-08-30       drh:     { "wmv",        3, "video/x-ms-wmv"                    },
8e66784522 2008-08-30       drh:     { "wmx",        3, "video/x-ms-wmx"                    },
8e66784522 2008-08-30       drh:     { "wrl",        3, "model/vrml"                        },
8e66784522 2008-08-30       drh:     { "wvx",        3, "video/x-ms-wvx"                    },
8e66784522 2008-08-30       drh:     { "xbm",        3, "image/x-xbitmap"                   },
8e66784522 2008-08-30       drh:     { "xlc",        3, "application/vnd.ms-excel"          },
8e66784522 2008-08-30       drh:     { "xll",        3, "application/vnd.ms-excel"          },
8e66784522 2008-08-30       drh:     { "xlm",        3, "application/vnd.ms-excel"          },
8e66784522 2008-08-30       drh:     { "xls",        3, "application/vnd.ms-excel"          },
8e66784522 2008-08-30       drh:     { "xlw",        3, "application/vnd.ms-excel"          },
8e66784522 2008-08-30       drh:     { "xml",        3, "text/xml"                          },
8e66784522 2008-08-30       drh:     { "xpm",        3, "image/x-xpixmap"                   },
8e66784522 2008-08-30       drh:     { "xwd",        3, "image/x-xwindowdump"               },
8e66784522 2008-08-30       drh:     { "xyz",        3, "chemical/x-pdb"                    },
8e66784522 2008-08-30       drh:     { "zip",        3, "application/zip"                   },
5cf1206dfa 2008-05-15       drh:   };
5cf1206dfa 2008-05-15       drh: 
5cf1206dfa 2008-05-15       drh:   z = zName;
5cf1206dfa 2008-05-15       drh:   for(i=0; zName[i]; i++){
5cf1206dfa 2008-05-15       drh:     if( zName[i]=='.' ) z = &zName[i+1];
5cf1206dfa 2008-05-15       drh:   }
8e66784522 2008-08-30       drh:   len = strlen(z);
8e66784522 2008-08-30       drh:   if( len<sizeof(zSuffix)-1 ){
5cf1206dfa 2008-05-15       drh:     strcpy(zSuffix, z);
5cf1206dfa 2008-05-15       drh:     for(i=0; zSuffix[i]; i++) zSuffix[i] = tolower(zSuffix[i]);
8e66784522 2008-08-30       drh:     first = 0;
8e66784522 2008-08-30       drh:     last = sizeof(aMime)/sizeof(aMime[0]);
8e66784522 2008-08-30       drh:     while( first<=last ){
8e66784522 2008-08-30       drh:       int c;
8e66784522 2008-08-30       drh:       i = (first+last)/2;
8e66784522 2008-08-30       drh:       c = strcmp(zSuffix, aMime[i].zSuffix);
8e66784522 2008-08-30       drh:       if( c==0 ) return aMime[i].zMimetype;
8e66784522 2008-08-30       drh:       if( c<0 ){
8e66784522 2008-08-30       drh:         last = i-1;
8e66784522 2008-08-30       drh:       }else{
8e66784522 2008-08-30       drh:         first = i+1;
5cf1206dfa 2008-05-15       drh:       }
5cf1206dfa 2008-05-15       drh:     }
5cf1206dfa 2008-05-15       drh:   }
5cf1206dfa 2008-05-15       drh:   return "application/x-fossil-artifact";
5cf1206dfa 2008-05-15       drh: }
5cf1206dfa 2008-05-15       drh: 
5cf1206dfa 2008-05-15       drh: /*
5cf1206dfa 2008-05-15       drh: ** WEBPAGE: doc
5cf1206dfa 2008-05-15       drh: ** URL: /doc?name=BASELINE/PATH
5cf1206dfa 2008-05-15       drh: **
5cf1206dfa 2008-05-15       drh: ** BASELINE can be either a baseline uuid prefix or magic words "tip"
5cf1206dfa 2008-05-15       drh: ** to me the most recently checked in baseline or "ckout" to mean the
5cf1206dfa 2008-05-15       drh: ** content of the local checkout, if any.  PATH is the relative pathname
5cf1206dfa 2008-05-15       drh: ** of some file.  This method returns the file content.
5cf1206dfa 2008-05-15       drh: **
5cf1206dfa 2008-05-15       drh: ** If PATH matches the patterns *.wiki or *.txt then formatting content
5cf1206dfa 2008-05-15       drh: ** is added before returning the file.  For all other names, the content
5cf1206dfa 2008-05-15       drh: ** is returned straight without any interpretation or processing.
5cf1206dfa 2008-05-15       drh: */
5cf1206dfa 2008-05-15       drh: void doc_page(void){
5cf1206dfa 2008-05-15       drh:   const char *zName;                /* Argument to the /doc page */
5cf1206dfa 2008-05-15       drh:   const char *zMime;                /* Document MIME type */
5cf1206dfa 2008-05-15       drh:   int vid = 0;                      /* Artifact of baseline */
5cf1206dfa 2008-05-15       drh:   int rid = 0;                      /* Artifact of file */
5cf1206dfa 2008-05-15       drh:   int i;                            /* Loop counter */
5cf1206dfa 2008-05-15       drh:   Blob filebody;                    /* Content of the documentation file */
5cf1206dfa 2008-05-15       drh:   char zBaseline[UUID_SIZE+1];      /* Baseline UUID */
5cf1206dfa 2008-05-15       drh: 
5cf1206dfa 2008-05-15       drh:   login_check_credentials();
5cf1206dfa 2008-05-15       drh:   if( !g.okRead ){ login_needed(); return; }
5cf1206dfa 2008-05-15       drh:   zName = PD("name", "tip/index.wiki");
5cf1206dfa 2008-05-15       drh:   for(i=0; zName[i] && zName[i]!='/'; i++){}
5cf1206dfa 2008-05-15       drh:   if( zName[i]==0 || i>UUID_SIZE ){
5cf1206dfa 2008-05-15       drh:     goto doc_not_found;
5cf1206dfa 2008-05-15       drh:   }
5cf1206dfa 2008-05-15       drh:   memcpy(zBaseline, zName, i);
5cf1206dfa 2008-05-15       drh:   zBaseline[i] = 0;
5cf1206dfa 2008-05-15       drh:   zName += i;
5cf1206dfa 2008-05-15       drh:   while( zName[0]=='/' ){ zName++; }
5cf1206dfa 2008-05-15       drh:   if( !file_is_simple_pathname(zName) ){
5cf1206dfa 2008-05-15       drh:     goto doc_not_found;
5cf1206dfa 2008-05-15       drh:   }
5cf1206dfa 2008-05-15       drh:   if( strcmp(zBaseline,"ckout")==0 ){
5cf1206dfa 2008-05-15       drh:     /* Read from the local checkout */
5cf1206dfa 2008-05-15       drh:     char *zFullpath;
5cf1206dfa 2008-05-15       drh:     db_must_be_within_tree();
5cf1206dfa 2008-05-15       drh:     zFullpath = mprintf("%s/%s", g.zLocalRoot, zName);
5cf1206dfa 2008-05-15       drh:     if( !file_isfile(zFullpath) ){
5cf1206dfa 2008-05-15       drh:       goto doc_not_found;
5cf1206dfa 2008-05-15       drh:     }
5cf1206dfa 2008-05-15       drh:     if( blob_read_from_file(&filebody, zFullpath)<0 ){
5cf1206dfa 2008-05-15       drh:       goto doc_not_found;
5cf1206dfa 2008-05-15       drh:     }
5cf1206dfa 2008-05-15       drh:   }else{
5cf1206dfa 2008-05-15       drh:     db_begin_transaction();
5cf1206dfa 2008-05-15       drh:     if( strcmp(zBaseline,"tip")==0 ){
5cf1206dfa 2008-05-15       drh:       vid = db_int(0, "SELECT objid FROM event WHERE type='ci'"
5cf1206dfa 2008-05-15       drh:                       " ORDER BY mtime DESC LIMIT 1");
5cf1206dfa 2008-05-15       drh:     }else{
5cf1206dfa 2008-05-15       drh:       vid = name_to_rid(zBaseline);
5cf1206dfa 2008-05-15       drh:     }
5cf1206dfa 2008-05-15       drh: 
5cf1206dfa 2008-05-15       drh:     /* Create the baseline cache if it does not already exist */
5cf1206dfa 2008-05-15       drh:     db_multi_exec(
5cf1206dfa 2008-05-15       drh:       "CREATE TABLE IF NOT EXISTS vcache(\n"
5cf1206dfa 2008-05-15       drh:       "  vid INTEGER,         -- baseline ID\n"
5cf1206dfa 2008-05-15       drh:       "  fname TEXT,          -- filename\n"
5cf1206dfa 2008-05-15       drh:       "  rid INTEGER,         -- artifact ID\n"
5cf1206dfa 2008-05-15       drh:       "  UNIQUE(vid,fname,rid)\n"
5cf1206dfa 2008-05-15       drh:       ")"
5cf1206dfa 2008-05-15       drh:     );
5cf1206dfa 2008-05-15       drh: 
5cf1206dfa 2008-05-15       drh:     /* Check to see if the documentation file artifact ID is contained
5cf1206dfa 2008-05-15       drh:     ** in the baseline cache */
5cf1206dfa 2008-05-15       drh:     rid = db_int(0, "SELECT rid FROM vcache"
5cf1206dfa 2008-05-15       drh:                     " WHERE vid=%d AND fname=%Q", vid, zName);
5cf1206dfa 2008-05-15       drh:     if( rid==0 && db_exists("SELECT 1 FROM vcache WHERE vid=%d", vid) ){
5cf1206dfa 2008-05-15       drh:       goto doc_not_found;
5cf1206dfa 2008-05-15       drh:     }
5cf1206dfa 2008-05-15       drh: 
5cf1206dfa 2008-05-15       drh:     if( rid==0 ){
5cf1206dfa 2008-05-15       drh:       Stmt s;
5cf1206dfa 2008-05-15       drh:       Blob baseline;
5cf1206dfa 2008-05-15       drh:       Manifest m;
5cf1206dfa 2008-05-15       drh: 
5cf1206dfa 2008-05-15       drh:       /* Add the vid baseline to the cache */
5cf1206dfa 2008-05-15       drh:       if( db_int(0, "SELECT count(*) FROM vcache")>10000 ){
5cf1206dfa 2008-05-15       drh:         db_multi_exec("DELETE FROM vcache");
5cf1206dfa 2008-05-15       drh:       }
5cf1206dfa 2008-05-15       drh:       if( content_get(vid, &baseline)==0 ){
5cf1206dfa 2008-05-15       drh:         goto doc_not_found;
5cf1206dfa 2008-05-15       drh:       }
5cf1206dfa 2008-05-15       drh:       if( manifest_parse(&m, &baseline)==0 || m.type!=CFTYPE_MANIFEST ){
5cf1206dfa 2008-05-15       drh:         goto doc_not_found;
5cf1206dfa 2008-05-15       drh:       }
5cf1206dfa 2008-05-15       drh:       db_prepare(&s,
5cf1206dfa 2008-05-15       drh:         "INSERT INTO vcache(vid,fname,rid)"
5cf1206dfa 2008-05-15       drh:         " SELECT %d, :fname, rid FROM blob"
5cf1206dfa 2008-05-15       drh:         "  WHERE uuid=:uuid",
5cf1206dfa 2008-05-15       drh:         vid
5cf1206dfa 2008-05-15       drh:       );
5cf1206dfa 2008-05-15       drh:       for(i=0; i<m.nFile; i++){
5cf1206dfa 2008-05-15       drh:         db_bind_text(&s, ":fname", m.aFile[i].zName);
5cf1206dfa 2008-05-15       drh:         db_bind_text(&s, ":uuid", m.aFile[i].zUuid);
5cf1206dfa 2008-05-15       drh:         db_step(&s);
5cf1206dfa 2008-05-15       drh:         db_reset(&s);
5cf1206dfa 2008-05-15       drh:       }
5cf1206dfa 2008-05-15       drh:       db_finalize(&s);
5cf1206dfa 2008-05-15       drh:       manifest_clear(&m);
5cf1206dfa 2008-05-15       drh: 
5cf1206dfa 2008-05-15       drh:       /* Try again to find the file */
5cf1206dfa 2008-05-15       drh:       rid = db_int(0, "SELECT rid FROM vcache"
5cf1206dfa 2008-05-15       drh:                       " WHERE vid=%d AND fname=%Q", vid, zName);
5cf1206dfa 2008-05-15       drh:     }
5cf1206dfa 2008-05-15       drh:     if( rid==0 ){
5cf1206dfa 2008-05-15       drh:       goto doc_not_found;
5cf1206dfa 2008-05-15       drh:     }
5cf1206dfa 2008-05-15       drh: 
5cf1206dfa 2008-05-15       drh:     /* Get the file content */
5cf1206dfa 2008-05-15       drh:     if( content_get(rid, &filebody)==0 ){
5cf1206dfa 2008-05-15       drh:       goto doc_not_found;
5cf1206dfa 2008-05-15       drh:     }
5cf1206dfa 2008-05-15       drh:     db_end_transaction(0);
5cf1206dfa 2008-05-15       drh:   }
5cf1206dfa 2008-05-15       drh: 
5cf1206dfa 2008-05-15       drh:   /* The file is now contained in the filebody blob.  Deliver the
5cf1206dfa 2008-05-15       drh:   ** file to the user
5cf1206dfa 2008-05-15       drh:   */
5cf1206dfa 2008-05-15       drh:   zMime = mimetype_from_name(zName);
5cf1206dfa 2008-05-15       drh:   if( strcmp(zMime, "application/x-fossil-wiki")==0 ){
5cf1206dfa 2008-05-15       drh:     style_header("Documentation");
5cf1206dfa 2008-05-15       drh:     wiki_convert(&filebody, 0, 0);
5cf1206dfa 2008-05-15       drh:     style_footer();
5cf1206dfa 2008-05-15       drh:   }else if( strcmp(zMime, "text/plain")==0 ){
5cf1206dfa 2008-05-15       drh:     style_header("Documentation");
5cf1206dfa 2008-05-15       drh:     @ <blockquote><pre>
5cf1206dfa 2008-05-15       drh:     @ %h(blob_str(&filebody))
5cf1206dfa 2008-05-15       drh:     @ </pre></blockquote>
5cf1206dfa 2008-05-15       drh:     style_footer();
5cf1206dfa 2008-05-15       drh:   }else{
5cf1206dfa 2008-05-15       drh:     cgi_set_content_type(zMime);
5cf1206dfa 2008-05-15       drh:     cgi_set_content(&filebody);
5cf1206dfa 2008-05-15       drh:   }
5cf1206dfa 2008-05-15       drh:   return;
5cf1206dfa 2008-05-15       drh: 
5cf1206dfa 2008-05-15       drh: doc_not_found:
5cf1206dfa 2008-05-15       drh:   /* Jump here when unable to locate the document */
5cf1206dfa 2008-05-15       drh:   db_end_transaction(0);
5cf1206dfa 2008-05-15       drh:   style_header("Document Not Found");
5cf1206dfa 2008-05-15       drh:   @ <p>No such document: %h(PD("name","tip/index.wiki"))</p>
5cf1206dfa 2008-05-15       drh:   style_footer();
5cf1206dfa 2008-05-15       drh:   return;
5cf1206dfa 2008-05-15       drh: }