Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Modify the artifact viewer to base the mimetype off of artifact content, not the artifact name. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA1: |
7303bfeb129c55fe9ad55a48050f6b4c |
| User & Date: | drh 2008-11-17 19:11:32.000 |
References
|
2009-03-21
| ||
| 16:35 | • Closed ticket [d67855cceb]: css files served as application/x-fossil-artifact not text/css plus 2 other changes artifact: a9c69fdc12 user: drh | |
Context
|
2008-11-17
| ||
| 19:17 | Improvements to object description on an artifact display. check-in: 5452b32a9f user: drh tags: trunk | |
| 19:11 | Modify the artifact viewer to base the mimetype off of artifact content, not the artifact name. check-in: 7303bfeb12 user: drh tags: trunk | |
| 17:14 | The "artifact" webpage shows images as images, rather than trying to render their binary content as text. check-in: 389bf5c4da user: drh tags: trunk | |
Changes
Changes to src/doc.c.
| ︙ | ︙ | |||
23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
**
** This file contains code to implement the "/doc" web page and related
** pages.
*/
#include "config.h"
#include "doc.h"
#include <assert.h>
/*
** Guess the mime-type of a document based on its name.
*/
const char *mimetype_from_name(const char *zName){
const char *z;
int i;
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
**
** This file contains code to implement the "/doc" web page and related
** 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){
const char *z;
int i;
|
| ︙ | ︙ |
Changes to src/info.c.
| ︙ | ︙ | |||
684 685 686 687 688 689 690 | ** ** If the object is a manifest, then mention: ** ** * It's uuid ** * date of check-in ** * Comment & user */ | | < | 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 |
**
** If the object is a manifest, then mention:
**
** * It's uuid
** * date of check-in
** * Comment & user
*/
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),"
" coalesce(event.ecomment,event.comment),"
" coalesce(event.euser,event.user),"
" b.uuid"
" FROM mlink, filename, event, blob a, blob b"
" WHERE filename.fnid=mlink.fnid"
|
| ︙ | ︙ | |||
716 717 718 719 720 721 722 |
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>
@ uuid %s(zFuuid) part of check-in
hyperlink_to_uuid(zVers);
@ %w(zCom) by %h(zUser) on %s(zDate)
| < > | 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 |
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>
@ uuid %s(zFuuid) part of check-in
hyperlink_to_uuid(zVers);
@ %w(zCom) by %h(zUser) on %s(zDate)
cnt++;
break;
}
db_finalize(&q);
db_prepare(&q,
"SELECT substr(tagname, 6, 10000), datetime(event.mtime),"
" coalesce(event.euser, event.user), uuid"
" FROM tagxref, tag, event, blob"
" WHERE tagxref.rid=%d"
|
| ︙ | ︙ | |||
741 742 743 744 745 746 747 |
const char *zUser = db_column_text(&q, 2);
const char *zUuid = db_column_text(&q, 3);
@ Wiki page
@ [<a href="%s(g.zBaseURL)/wiki?name=%t(zPagename)">%h(zPagename)</a>]
@ uuid %s(zUuid) by %h(zUser) on %s(zDate)
nWiki++;
cnt++;
| < | 740 741 742 743 744 745 746 747 748 749 750 751 752 753 |
const char *zUser = db_column_text(&q, 2);
const char *zUuid = db_column_text(&q, 3);
@ Wiki page
@ [<a href="%s(g.zBaseURL)/wiki?name=%t(zPagename)">%h(zPagename)</a>]
@ uuid %s(zUuid) by %h(zUser) on %s(zDate)
nWiki++;
cnt++;
}
db_finalize(&q);
if( nWiki==0 ){
db_prepare(&q,
"SELECT datetime(mtime), user, comment, uuid, type"
" FROM event, blob"
" WHERE event.objid=%d"
|
| ︙ | ︙ | |||
779 780 781 782 783 784 785 |
}
if( cnt==0 ){
char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
@ Control file %s(zUuid).
}else if( linkToView ){
@ <a href="%s(g.zBaseURL)/artifact/%d(rid)">[view]</a>
}
| < | 777 778 779 780 781 782 783 784 785 786 787 788 789 790 |
}
if( cnt==0 ){
char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
@ Control file %s(zUuid).
}else if( linkToView ){
@ <a href="%s(g.zBaseURL)/artifact/%d(rid)">[view]</a>
}
}
/*
** WEBPAGE: fdiff
**
** Two arguments, v1 and v2, are integers. Show the difference between
** the two records.
|
| ︙ | ︙ | |||
839 840 841 842 843 844 845 846 847 848 849 850 851 852 |
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);
}
/*
** WEBPAGE: artifact
** URL: /artifact?name=ARTIFACTID
**
** Show the complete content of a file identified by ARTIFACTID
** as preformatted text.
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 |
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.
|
| ︙ | ︙ | |||
869 870 871 872 873 874 875 |
style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
g.zTop, zUuid);
}
}
style_header("Artifact Content");
@ <h2>Content Of:</h2>
@ <blockquote>
| | > > > > > > > > | > | < | | < > | 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 |
style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
g.zTop, zUuid);
}
}
style_header("Artifact Content");
@ <h2>Content Of:</h2>
@ <blockquote>
object_description(rid, 0);
@ </blockquote>
@ <hr>
@ <blockquote>
content_get(rid, &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
** URL: /tinfo?name=ARTIFACTID
**
|
| ︙ | ︙ |