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
f969b6cdde 2009-09-22       drh: ** URL: /doc/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;
292e585661 2009-08-15       drh:   }
292e585661 2009-08-15       drh:   if( strcmp(zBaseline,"ckout")==0 && db_open_local()==0 ){
292e585661 2009-08-15       drh:     strcpy(zBaseline,"tip");
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:   */
f969b6cdde 2009-09-22       drh:   zMime = P("mimetype");
f969b6cdde 2009-09-22       drh:   if( zMime==0 ){
f969b6cdde 2009-09-22       drh:     zMime = mimetype_from_name(zName);
f969b6cdde 2009-09-22       drh:   }
5cf1206dfa 2008-05-15       drh:   if( strcmp(zMime, "application/x-fossil-wiki")==0 ){
f88e2e7a13 2009-06-07       drh:     Blob title, tail;
f88e2e7a13 2009-06-07       drh:     if( wiki_find_title(&filebody, &title, &tail) ){
f88e2e7a13 2009-06-07       drh:       style_header(blob_str(&title));
f88e2e7a13 2009-06-07       drh:       wiki_convert(&tail, 0, 0);
f88e2e7a13 2009-06-07       drh:     }else{
f88e2e7a13 2009-06-07       drh:       style_header("Documentation");
f88e2e7a13 2009-06-07       drh:       wiki_convert(&filebody, 0, 0);
f88e2e7a13 2009-06-07       drh:     }
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;
43481115ed 2009-09-21       drh: }
43481115ed 2009-09-21       drh: 
43481115ed 2009-09-21       drh: /*
43481115ed 2009-09-21       drh: ** The default logo.
43481115ed 2009-09-21       drh: */
43481115ed 2009-09-21       drh: static const unsigned char aLogo[] = {
43481115ed 2009-09-21       drh:     71,  73,  70,  56,  55,  97,  62,   0,  71,   0, 244,   0,   0,  85,
43481115ed 2009-09-21       drh:    129, 149,  95, 136, 155,  99, 139, 157, 106, 144, 162, 113, 150, 166,
43481115ed 2009-09-21       drh:    116, 152, 168, 127, 160, 175, 138, 168, 182, 148, 176, 188, 159, 184,
43481115ed 2009-09-21       drh:    195, 170, 192, 202, 180, 199, 208, 184, 202, 210, 191, 207, 215, 201,
43481115ed 2009-09-21       drh:    215, 221, 212, 223, 228, 223, 231, 235, 226, 227, 226, 226, 234, 237,
43481115ed 2009-09-21       drh:    233, 239, 241, 240, 244, 246, 244, 247, 248, 255, 255, 255,   0,   0,
43481115ed 2009-09-21       drh:      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
43481115ed 2009-09-21       drh:      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  44,   0,   0,
43481115ed 2009-09-21       drh:      0,   0,  62,   0,  71,   0,   0,   5, 255,  96, 100, 141, 100, 105,
43481115ed 2009-09-21       drh:    158, 168,  37,  41, 132, 192, 164, 112,  44, 207, 102,  99,   0,  56,
43481115ed 2009-09-21       drh:     16,  84, 116, 239, 199, 141,  65, 110, 232, 248,  25, 141, 193, 161,
43481115ed 2009-09-21       drh:     82, 113, 108, 202,  32,  55, 229, 210,  73,  61,  41, 164,  88, 102,
43481115ed 2009-09-21       drh:    181,  10,  41,  96, 179,  91, 106,  35, 240,   5, 135, 143, 137, 242,
43481115ed 2009-09-21       drh:     87, 123, 246,  33, 190,  81, 108, 163, 237, 198,  14,  30, 113, 233,
43481115ed 2009-09-21       drh:    131,  78, 115,  72,  11, 115,  87, 101,  19, 124,  51,  66,  74,   8,
43481115ed 2009-09-21       drh:     19,  16,  67, 100,  74, 133,  50,  15, 101, 135,  56,  11,  74,   6,
43481115ed 2009-09-21       drh:    143,  49, 126, 106,  56,   8, 145,  67,   9, 152,  48, 139, 155,   5,
43481115ed 2009-09-21       drh:     22,  13,  74, 115, 161,  41, 147, 101,  13, 130,  57, 132, 170,  40,
43481115ed 2009-09-21       drh:    167, 155,   0,  94,  57,   3, 178,  48, 183, 181,  57, 160, 186,  40,
43481115ed 2009-09-21       drh:     19, 141, 189,   0,  69, 192,  40,  16, 195, 155, 185, 199,  41, 201,
43481115ed 2009-09-21       drh:    189, 191, 205, 193, 188, 131, 210,  49, 175,  88, 209, 214,  38,  19,
43481115ed 2009-09-21       drh:      3,  11,  19, 111, 127,  60, 219,  39,  55, 204,  19,  11,   6, 100,
43481115ed 2009-09-21       drh:      5,  10, 227, 228,  37, 163,   0, 239, 117,  56, 238, 243,  49, 195,
43481115ed 2009-09-21       drh:    177, 247,  48, 158,  56, 251,  50, 216, 254, 197,  56, 128, 107, 158,
43481115ed 2009-09-21       drh:      2, 125, 171, 114,  92, 218, 246,  96,  66,   3,   4,  50, 134, 176,
43481115ed 2009-09-21       drh:    145,   6,  97,  64, 144,  24,  19, 136, 108,  91, 177, 160,   0, 194,
43481115ed 2009-09-21       drh:     19, 253,   0, 216, 107, 214, 224, 192, 129,   5,  16,  83, 255, 244,
43481115ed 2009-09-21       drh:     43, 213, 195,  24, 159,  27, 169,  64, 230,  88, 208, 227, 129, 182,
43481115ed 2009-09-21       drh:     54,   4,  89, 158,  24, 181, 163, 199,   1, 155,  52, 233,   8, 130,
43481115ed 2009-09-21       drh:    176,  83,  24, 128, 137,  50,  18,  32,  48,  48, 114,  11, 173, 137,
43481115ed 2009-09-21       drh:     19, 110,   4,  64, 105,   1, 194,  30, 140,  68,  15,  24,  24, 224,
43481115ed 2009-09-21       drh:     50,  76,  70,   0,  11, 171,  54,  26, 160, 181, 194, 149, 148,  40,
43481115ed 2009-09-21       drh:    174, 148, 122,  64, 180, 208, 161,  17, 207, 112, 164,   1, 128,  96,
43481115ed 2009-09-21       drh:    148,  78,  18,  21, 194,  33, 229,  51, 247,  65, 133,  97,   5, 250,
43481115ed 2009-09-21       drh:     69, 229, 100,  34, 220, 128, 166, 116, 190,  62,   8, 167, 195, 170,
43481115ed 2009-09-21       drh:     47, 163,   0, 130,  90, 152,  11, 160, 173, 170,  27, 154,  26,  91,
43481115ed 2009-09-21       drh:    232, 151, 171,  18,  14, 162, 253,  98, 170,  18,  70, 171,  64, 219,
43481115ed 2009-09-21       drh:     10,  67, 136, 134, 187, 116,  75, 180,  46, 179, 174, 135,   4, 189,
43481115ed 2009-09-21       drh:    229, 231,  78,  40,  10,  62, 226, 164, 172,  64, 240, 167, 170,  10,
43481115ed 2009-09-21       drh:     18, 124, 188,  10, 107,  65, 193,  94,  11,  93, 171,  28, 248,  17,
43481115ed 2009-09-21       drh:    239,  46, 140,  78,  97,  34,  25, 153,  36,  99,  65, 130,   7, 203,
43481115ed 2009-09-21       drh:    183, 168,  51,  34, 136,  25, 140,  10,   6,  16,  28, 255, 145, 241,
43481115ed 2009-09-21       drh:    230, 140,  10,  66, 178, 167, 112,  48, 192, 128, 129,   9,  31, 141,
43481115ed 2009-09-21       drh:     84, 138,  63, 163, 162,   2, 203, 206, 240,  56,  55,  98, 192, 188,
43481115ed 2009-09-21       drh:     15, 185,  50, 160,   6,   0, 125,  62,  33, 214, 195,  33,   5,  24,
43481115ed 2009-09-21       drh:    184,  25, 231,  14, 201, 245, 144,  23, 126, 104, 228,   0, 145,   2,
43481115ed 2009-09-21       drh:     13, 140, 244, 212,  17,  21,  20, 176, 159,  17,  95, 225, 160, 128,
43481115ed 2009-09-21       drh:     16,   1,  32, 224, 142,  32, 227, 125,  87,  64,   0,  16,  54, 129,
43481115ed 2009-09-21       drh:    205,   2, 141,  76,  53, 130, 103,  37, 166,  64, 144, 107,  78, 196,
43481115ed 2009-09-21       drh:      5, 192,   0,  54,  50, 229,   9, 141,  49,  84, 194,  35,  12, 196,
43481115ed 2009-09-21       drh:    153,  48, 192, 137,  57,  84,  24,   7,  87, 159, 249, 240, 215, 143,
43481115ed 2009-09-21       drh:    105, 241, 118, 149,   9, 139,   4,  64, 203, 141,  35, 140, 129, 131,
43481115ed 2009-09-21       drh:     16, 222, 125, 231, 128,   2, 238,  17, 152,  66,   3,   5,  56, 224,
43481115ed 2009-09-21       drh:    159, 103,  16,  76,  25,  75,   5,  11, 164, 215,  96,   9,  14,  16,
43481115ed 2009-09-21       drh:     36, 225,  15,  11,  40, 144, 192, 156,  41,  10, 178, 199,   3,  66,
43481115ed 2009-09-21       drh:     64,  80, 193,   3, 124,  90,  48, 129, 129, 102, 177,  18, 192, 154,
43481115ed 2009-09-21       drh:     49,  84, 240, 208,  92,  22, 149,  96,  39,   9,  31,  74,  17,  94,
43481115ed 2009-09-21       drh:      3,   8, 177, 199,  72,  59,  85,  76,  25, 216,   8, 139, 194, 197,
43481115ed 2009-09-21       drh:    138, 163,  69,  96, 115,   0, 147,  72,  72,  84,  28,  14,  79,  86,
43481115ed 2009-09-21       drh:    233, 230,  23, 113,  26, 160, 128,   3,  10,  58, 129, 103,  14, 159,
43481115ed 2009-09-21       drh:    214, 163, 146, 117, 238, 213, 154, 128, 151, 109,  84,  64, 217,  13,
43481115ed 2009-09-21       drh:     27,  10, 228,  39,   2, 235, 164, 168,  74,   8,   0,  59,
43481115ed 2009-09-21       drh: };
43481115ed 2009-09-21       drh: 
43481115ed 2009-09-21       drh: /*
43481115ed 2009-09-21       drh: ** WEBPAGE: logo
43481115ed 2009-09-21       drh: **
43481115ed 2009-09-21       drh: ** Return the logo image.  This image is available to anybody who can see
43481115ed 2009-09-21       drh: ** the login page.  It is designed for use in the upper left-hand corner
43481115ed 2009-09-21       drh: ** of the header.
43481115ed 2009-09-21       drh: */
43481115ed 2009-09-21       drh: void logo_page(void){
43481115ed 2009-09-21       drh:   Blob logo;
43481115ed 2009-09-21       drh:   char *zMime;
43481115ed 2009-09-21       drh: 
43481115ed 2009-09-21       drh:   zMime = db_get("logo-mimetype", "image/gif");
43481115ed 2009-09-21       drh:   blob_zero(&logo);
43481115ed 2009-09-21       drh:   db_blob(&logo, "SELECT value FROM config WHERE name='logo-image'");
43481115ed 2009-09-21       drh:   if( blob_size(&logo)==0 ){
43481115ed 2009-09-21       drh:     blob_init(&logo, (char*)aLogo, sizeof(aLogo));
43481115ed 2009-09-21       drh:   }
43481115ed 2009-09-21       drh:   cgi_set_content_type(zMime);
43481115ed 2009-09-21       drh:   cgi_set_content(&logo);
5cf1206dfa 2008-05-15       drh: }