Overview
SHA1 Hash: | d14adf1032924428f6eda72570fa81b68fe69621 |
---|---|
Date: | 2008-11-19 16:55:14 |
User: | kejoki |
Comment: | Merge src & doc leaves back. |
Timelines: | ancestors | descendants | both | trunk |
Other Links: | files | ZIP archive | manifest |
Tags And Properties
- branch=trunk inherited from [a28c83647d]
- sym-trunk inherited from [a28c83647d]
Changes
[hide diffs]Modified src/cgi.c from [40d3404d8c] to [e524bac009].
@@ -336,11 +336,27 @@ blob_compress(&cgiContent[0], &cgiContent[0]); } if( iReplyStatus != 304 ) { total_size = blob_size(&cgiContent[0]) + blob_size(&cgiContent[1]); +#ifdef __MINGW32__ + /* In windows versions of Apache, extra \r characters get added to the + ** response, which mess up the Content-Length. So let apache figure + ** out the content length for itself if we are using CGI. If this + ** is a complete stand-alone webserver, on the other hand, we still + ** need the Content-Length. + */ + if( g.fullHttpReply ){ + fprintf(g.httpOut, "Content-Length: %d\r\n", total_size); + } +#else + /* On unix, \n to \r\n translation is never a problem. We know the + ** content length, so we might as well go ahead and tell the webserver + ** what it is in all cases. + */ fprintf(g.httpOut, "Content-Length: %d\r\n", total_size); +#endif } fprintf(g.httpOut, "\r\n"); if( total_size>0 && iReplyStatus != 304 ){ int i, size; for(i=0; i<2; i++){
Modified src/clearsign.c from [3868e827c1] to [3e61358e2b].
@@ -37,10 +37,13 @@ char *zIn; char *zOut; char *zBase = db_get("pgp-command", "gpg --clearsign -o "); char *zCmd; int rc; + if( is_false(zBase) ){ + return 0; + } zRand = db_text(0, "SELECT hex(randomblob(10))"); zOut = mprintf("out-%s", zRand); zIn = mprintf("in-%z", zRand); blob_write_to_file(pIn, zOut); zCmd = mprintf("%s %s %s", zBase, zIn, zOut);
Modified src/doc.c from [2b833a11d7] to [a23503395b].
@@ -25,10 +25,62 @@ ** pages. */ #include "config.h" #include "doc.h" #include <assert.h> + +/* +** Try to guess the mimetype from content. +** +** If the content is pure text, return NULL. +** +** For image types, attempt to return an appropriate mimetype +** name like "image/gif" or "image/jpeg". +** +** For any other binary type, return "unknown/unknown". +*/ +const char *mimetype_from_content(Blob *pBlob){ + int i; + int n; + const unsigned char *x; + + static const char isBinary[] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, + }; + + /* A table of mimetypes based on file content prefixes + */ + static const struct { + const char *zPrefix; /* The file prefix */ + int size; /* Length of the prefix */ + const char *zMimetype; /* The corresponding mimetype */ + } aMime[] = { + { "GIF87a", 6, "image/gif" }, + { "GIF89a", 6, "image/gif" }, + { "\211PNG\r\n\032\r", 8, "image/png" }, + { "\377\332\377", 3, "image/jpeg" }, + }; + + x = (const unsigned char*)blob_buffer(pBlob); + n = blob_size(pBlob); + for(i=0; i<n; i++){ + unsigned char c = x[i]; + if( c<=0x1f && isBinary[c] ){ + break; + } + } + if( i>=n ){ + return 0; /* Plain text */ + } + for(i=0; i<sizeof(aMime)/sizeof(aMime[0]); i++){ + if( n>=aMime[i].size && memcmp(x, aMime[i].zPrefix, aMime[i].size)==0 ){ + return aMime[i].zMimetype; + } + } + return "unknown/unknown"; +} /* ** Guess the mime-type of a document based on its name. */ const char *mimetype_from_name(const char *zName){
Modified src/info.c from [97b0bae401] to [594a3689d1].
@@ -686,11 +686,14 @@ ** ** * It's uuid ** * date of check-in ** * Comment & user */ -static void object_description(int rid, int linkToView){ +static void object_description( + int rid, /* The artifact ID */ + int linkToView /* Add viewer link if true */ +){ Stmt q; int cnt = 0; int nWiki = 0; db_prepare(&q, "SELECT filename.name, datetime(event.mtime), substr(a.uuid,1,10)," @@ -710,14 +713,19 @@ const char *zDate = db_column_text(&q, 1); const char *zFuuid = db_column_text(&q, 2); const char *zCom = db_column_text(&q, 3); const char *zUser = db_column_text(&q, 4); const char *zVers = db_column_text(&q, 5); - @ File <a href="%s(g.zBaseURL)/finfo?name=%T(zName)">%h(zName)</a> + if( cnt>0 ){ + @ Also file + }else{ + @ File + } + @ <a href="%s(g.zBaseURL)/finfo?name=%T(zName)">%h(zName)</a> @ uuid %s(zFuuid) part of check-in hyperlink_to_uuid(zVers); - @ %w(zCom) by %h(zUser) on %s(zDate) + @ %w(zCom) by %h(zUser) on %s(zDate). cnt++; } db_finalize(&q); db_prepare(&q, "SELECT substr(tagname, 6, 10000), datetime(event.mtime)," @@ -733,13 +741,17 @@ while( db_step(&q)==SQLITE_ROW ){ const char *zPagename = db_column_text(&q, 0); const char *zDate = db_column_text(&q, 1); const char *zUser = db_column_text(&q, 2); const char *zUuid = db_column_text(&q, 3); - @ Wiki page + if( cnt>0 ){ + @ Also wiki page + }else{ + @ Wiki page + } @ [<a href="%s(g.zBaseURL)/wiki?name=%t(zPagename)">%h(zPagename)</a>] - @ uuid %s(zUuid) by %h(zUser) on %s(zDate) + @ uuid %s(zUuid) by %h(zUser) on %s(zDate). nWiki++; cnt++; } db_finalize(&q); if( nWiki==0 ){ @@ -754,10 +766,13 @@ const char *zDate = db_column_text(&q, 0); const char *zUuid = db_column_text(&q, 3); const char *zUser = db_column_text(&q, 1); const char *zCom = db_column_text(&q, 2); const char *zType = db_column_text(&q, 4); + if( cnt>0 ){ + @ Also + } if( zType[0]=='w' ){ @ Wiki edit }else if( zType[0]=='t' ){ @ Ticket change }else if( zType[0]=='c' ){ @@ -764,11 +779,11 @@ @ Manifest of baseline }else{ @ Control file referencing } hyperlink_to_uuid(zUuid); - @ %w(zCom) by %h(zUser) on %s(zDate) + @ %w(zCom) by %h(zUser) on %s(zDate). cnt++; } db_finalize(&q); } if( cnt==0 ){ @@ -814,19 +829,131 @@ blob_reset(&diff); style_footer(); } /* +** WEBPAGE: raw +** URL: /raw?name=ARTIFACTID&m=TYPE +** +** Return the uninterpreted content of an artifact. Used primarily +** to view artifacts that are images. +*/ +void rawartifact_page(void){ + int rid; + const char *zMime; + Blob content; + + rid = name_to_rid(PD("name","0")); + zMime = PD("m","application/x-fossil-artifact"); + login_check_credentials(); + if( !g.okRead ){ login_needed(); return; } + if( rid==0 ){ cgi_redirect("/home"); } + content_get(rid, &content); + cgi_set_content_type(zMime); + cgi_set_content(&content); +} + +/* +** Render a hex dump of a file. +*/ +static void hexdump(Blob *pBlob){ + const unsigned char *x; + int n, i, j, k; + char zLine[100]; + static const char zHex[] = "0123456789abcdef"; + + x = (const unsigned char*)blob_buffer(pBlob); + n = blob_size(pBlob); + for(i=0; i<n; i+=16){ + j = 0; + zLine[0] = zHex[(i>>24)&0xf]; + zLine[1] = zHex[(i>>16)&0xf]; + zLine[2] = zHex[(i>>8)&0xf]; + zLine[3] = zHex[i&0xf]; + zLine[4] = ':'; + sprintf(zLine, "%04x: ", i); + for(j=0; j<16; j++){ + k = 5+j*3; + zLine[k] = ' '; + if( i+j<n ){ + unsigned char c = x[i+j]; + zLine[k+1] = zHex[c>>4]; + zLine[k+2] = zHex[c&0xf]; + }else{ + zLine[k+1] = ' '; + zLine[k+2] = ' '; + } + } + zLine[53] = ' '; + zLine[54] = ' '; + for(j=0; j<16; j++){ + k = j+55; + if( i+j<n ){ + unsigned char c = x[i+j]; + if( c>=0x20 && c<=0x7e ){ + zLine[k] = c; + }else{ + zLine[k] = '.'; + } + }else{ + zLine[k] = 0; + } + } + zLine[71] = 0; + @ %h(zLine) + } +} + +/* +** WEBPAGE: hexdump +** URL: /hexdump?name=ARTIFACTID +** +** Show the complete content of a file identified by ARTIFACTID +** as preformatted text. +*/ +void hexdump_page(void){ + int rid; + Blob content; + + rid = name_to_rid(PD("name","0")); + login_check_credentials(); + if( !g.okRead ){ login_needed(); return; } + if( rid==0 ){ cgi_redirect("/home"); } + if( g.okAdmin ){ + const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid); + if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){ + style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1", + g.zTop, zUuid); + }else{ + style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun", + g.zTop, zUuid); + } + } + style_header("Hex Artifact Content"); + @ <h2>Hexadecimal Content Of:</h2> + @ <blockquote> + object_description(rid, 0); + @ </blockquote> + @ <hr> + content_get(rid, &content); + @ <blockquote><pre> + hexdump(&content); + @ </pre></blockquote> + style_footer(); +} + +/* ** WEBPAGE: artifact ** URL: /artifact?name=ARTIFACTID ** ** Show the complete content of a file identified by ARTIFACTID ** as preformatted text. */ void artifact_page(void){ int rid; Blob content; + const char *zMime; rid = name_to_rid(PD("name","0")); login_check_credentials(); if( !g.okRead ){ login_needed(); return; } if( rid==0 ){ cgi_redirect("/home"); } @@ -844,15 +971,27 @@ @ <h2>Content Of:</h2> @ <blockquote> object_description(rid, 0); @ </blockquote> @ <hr> - @ <blockquote><pre> + @ <blockquote> content_get(rid, &content); - @ %h(blob_str(&content)) - @ </pre></blockquote> - blob_reset(&content); + zMime = mimetype_from_content(&content); + if( zMime==0 ){ + @ <pre> + @ %h(blob_str(&content)) + @ </pre> + style_submenu_element("Hex","Hex", "%s/hexdump?name=%d", g.zTop, rid); + }else if( strncmp(zMime, "image/", 6)==0 ){ + @ <img src="%s(g.zBaseURL)/raw?name=%d(rid)&m=%s(zMime)"></img> + style_submenu_element("Hex","Hex", "%s/hexdump?name=%d", g.zTop, rid); + }else{ + @ <pre> + hexdump(&content); + @ </pre> + } + @ </blockquote> style_footer(); } /* ** WEBPAGE: tinfo
Modified src/wiki.c from [45c7efaf6d] to [8673214ab7].
@@ -83,13 +83,11 @@ if( zPageName ){ login_check_credentials(); g.zExtra = zPageName; cgi_set_parameter_nocopy("name", g.zExtra); g.okRdWiki = 1; - g.okApndWiki = 0; - g.okWrWiki = 0; - g.okHistory = 0; + g.argv[1] = "home"; wiki_page(); return; } login_check_credentials(); style_header("Home"); @@ -121,10 +119,11 @@ Blob wiki; Manifest m; const char *zPageName; char *zHtmlPageName; char *zBody = mprintf("%s","<i>Empty Page</i>"); + int isHome = g.argv[1][0]=='h'; login_check_credentials(); if( !g.okRdWiki ){ login_needed(); return; } zPageName = P("name"); if( zPageName==0 ){ @@ -169,21 +168,23 @@ if( m.type==CFTYPE_WIKI ){ zBody = m.zWiki; } } } - if( isSandbox || (rid && g.okWrWiki) || (!rid && g.okNewWiki) ){ - style_submenu_element("Edit", "Edit Wiki Page", "%s/wikiedit?name=%T", - g.zTop, zPageName); - } - if( isSandbox || (rid && g.okApndWiki) ){ - style_submenu_element("Append", "Add A Comment", "%s/wikiappend?name=%T", - g.zTop, zPageName); - } - if( !isSandbox && g.okHistory ){ - style_submenu_element("History", "History", "%s/whistory?name=%T", - g.zTop, zPageName); + if( !isHome ){ + if( isSandbox || (rid && g.okWrWiki) || (!rid && g.okNewWiki) ){ + style_submenu_element("Edit", "Edit Wiki Page", "%s/wikiedit?name=%T", + g.zTop, zPageName); + } + if( isSandbox || (rid && g.okApndWiki) ){ + style_submenu_element("Append", "Add A Comment", "%s/wikiappend?name=%T", + g.zTop, zPageName); + } + if( !isSandbox && g.okHistory ){ + style_submenu_element("History", "History", "%s/whistory?name=%T", + g.zTop, zPageName); + } } zHtmlPageName = mprintf("%h", zPageName); style_header(zHtmlPageName); blob_init(&wiki, zBody, -1); wiki_convert(&wiki, 0, 0);
Modified src/wikiformat.c from [ad6f4b4c31] to [51759e15ab].
@@ -936,10 +936,16 @@ ){ blob_appendf(p->pOut, "<a href=\"%s\">", zTarget); }else if( zTarget[0]=='/' ){ if( g.okHistory ){ blob_appendf(p->pOut, "<a href=\"%s%h\">", g.zBaseURL, zTarget); + }else{ + zTerm = ""; + } + }else if( zTarget[0]=='.' ){ + if( g.okHistory ){ + blob_appendf(p->pOut, "<a href=\"%h\">", zTarget); }else{ zTerm = ""; } }else if( is_valid_uuid(zTarget) ){ int isClosed;