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: /* 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" }, 8e66784522 2008-08-30 drh: { "ccad", 4, "application/clariscad" }, 8e66784522 2008-08-30 drh: { "cc", 2, "text/plain" }, 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: { "c", 1, "text/plain" }, 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" }, 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: { "f", 1, "text/plain" }, 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-gunzip" }, 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" }, 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/vnd.mif" }, 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: { "m", 1, "text/plain" }, 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: { "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: { "vivo", 4, "video/vnd.vivo" }, 8e66784522 2008-08-30 drh: { "viv", 3, "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: }