Fossil SCM

Fix the /file page so that it is able to play sound files that are checked into the repository. Example: [/file/src/sounds/plunk.wav]

drh 2021-01-03 15:30 trunk
Commit 6643d4a0c1aabb8562fc1ab1803d13fa859b2266befb73f60e82f368ea8d802c
2 files changed +18 -9 +13 -6
+18 -9
--- src/doc.c
+++ src/doc.c
@@ -38,30 +38,39 @@
3838
const unsigned char *x;
3939
4040
/* A table of mimetypes based on file content prefixes
4141
*/
4242
static const struct {
43
- const char *zPrefix; /* The file prefix */
44
- const int size; /* Length of the prefix */
43
+ const char *z; /* Identifying file text */
44
+ const unsigned char sz1; /* Length of the prefix */
45
+ const unsigned char of2; /* Offset to the second segment */
46
+ const unsigned char sz2; /* Size of the second segment */
47
+ const unsigned char mn; /* Minimum size of input */
4548
const char *zMimetype; /* The corresponding mimetype */
4649
} aMime[] = {
47
- { "GIF87a", 6, "image/gif" },
48
- { "GIF89a", 6, "image/gif" },
49
- { "\211PNG\r\n\032\n", 8, "image/png" },
50
- { "\377\332\377", 3, "image/jpeg" },
51
- { "\377\330\377", 3, "image/jpeg" },
50
+ { "GIF87a", 6, 0, 0, 6, "image/gif" },
51
+ { "GIF89a", 6, 0, 0, 6, "image/gif" },
52
+ { "\211PNG\r\n\032\n", 8, 0, 0, 8, "image/png" },
53
+ { "\377\332\377", 3, 0, 0, 3, "image/jpeg" },
54
+ { "\377\330\377", 3, 0, 0, 3, "image/jpeg" },
55
+ { "RIFFWAVEfmt", 4, 8, 7, 15, "sound/wav" },
5256
};
5357
5458
if( !looks_like_binary(pBlob) ) {
5559
return 0; /* Plain text */
5660
}
5761
x = (const unsigned char*)blob_buffer(pBlob);
5862
n = blob_size(pBlob);
5963
for(i=0; i<count(aMime); i++){
60
- if( n>=aMime[i].size && memcmp(x, aMime[i].zPrefix, aMime[i].size)==0 ){
61
- return aMime[i].zMimetype;
64
+ if( n<aMime[i].mn ) continue;
65
+ if( memcmp(x, aMime[i].z, aMime[i].sz1)!=0 ) continue;
66
+ if( aMime[i].sz2
67
+ && memcmp(x+aMime[i].of2, aMime[i].z+aMime[i].sz1, aMime[i].sz2)!=0
68
+ ){
69
+ continue;
6270
}
71
+ return aMime[i].zMimetype;
6372
}
6473
return "unknown/unknown";
6574
}
6675
6776
/* A table of mimetypes based on file suffixes.
6877
--- src/doc.c
+++ src/doc.c
@@ -38,30 +38,39 @@
38 const unsigned char *x;
39
40 /* A table of mimetypes based on file content prefixes
41 */
42 static const struct {
43 const char *zPrefix; /* The file prefix */
44 const int size; /* Length of the prefix */
 
 
 
45 const char *zMimetype; /* The corresponding mimetype */
46 } aMime[] = {
47 { "GIF87a", 6, "image/gif" },
48 { "GIF89a", 6, "image/gif" },
49 { "\211PNG\r\n\032\n", 8, "image/png" },
50 { "\377\332\377", 3, "image/jpeg" },
51 { "\377\330\377", 3, "image/jpeg" },
 
52 };
53
54 if( !looks_like_binary(pBlob) ) {
55 return 0; /* Plain text */
56 }
57 x = (const unsigned char*)blob_buffer(pBlob);
58 n = blob_size(pBlob);
59 for(i=0; i<count(aMime); i++){
60 if( n>=aMime[i].size && memcmp(x, aMime[i].zPrefix, aMime[i].size)==0 ){
61 return aMime[i].zMimetype;
 
 
 
 
62 }
 
63 }
64 return "unknown/unknown";
65 }
66
67 /* A table of mimetypes based on file suffixes.
68
--- src/doc.c
+++ src/doc.c
@@ -38,30 +38,39 @@
38 const unsigned char *x;
39
40 /* A table of mimetypes based on file content prefixes
41 */
42 static const struct {
43 const char *z; /* Identifying file text */
44 const unsigned char sz1; /* Length of the prefix */
45 const unsigned char of2; /* Offset to the second segment */
46 const unsigned char sz2; /* Size of the second segment */
47 const unsigned char mn; /* Minimum size of input */
48 const char *zMimetype; /* The corresponding mimetype */
49 } aMime[] = {
50 { "GIF87a", 6, 0, 0, 6, "image/gif" },
51 { "GIF89a", 6, 0, 0, 6, "image/gif" },
52 { "\211PNG\r\n\032\n", 8, 0, 0, 8, "image/png" },
53 { "\377\332\377", 3, 0, 0, 3, "image/jpeg" },
54 { "\377\330\377", 3, 0, 0, 3, "image/jpeg" },
55 { "RIFFWAVEfmt", 4, 8, 7, 15, "sound/wav" },
56 };
57
58 if( !looks_like_binary(pBlob) ) {
59 return 0; /* Plain text */
60 }
61 x = (const unsigned char*)blob_buffer(pBlob);
62 n = blob_size(pBlob);
63 for(i=0; i<count(aMime); i++){
64 if( n<aMime[i].mn ) continue;
65 if( memcmp(x, aMime[i].z, aMime[i].sz1)!=0 ) continue;
66 if( aMime[i].sz2
67 && memcmp(x+aMime[i].of2, aMime[i].z+aMime[i].sz1, aMime[i].sz2)!=0
68 ){
69 continue;
70 }
71 return aMime[i].zMimetype;
72 }
73 return "unknown/unknown";
74 }
75
76 /* A table of mimetypes based on file suffixes.
77
+13 -6
--- src/info.c
+++ src/info.c
@@ -2366,14 +2366,17 @@
23662366
@ part of check-in %z(href("%R/info/%!S",zCIUuid))%S(zCIUuid)</a></h2>
23672367
}
23682368
blob_reset(&path);
23692369
}
23702370
style_submenu_element("Artifact", "%R/artifact/%S", zUuid);
2371
- style_submenu_element("Annotate", "%R/annotate?filename=%T&checkin=%T",
2372
- zName, zCI);
2373
- style_submenu_element("Blame", "%R/blame?filename=%T&checkin=%T",
2374
- zName, zCI);
2371
+ zMime = mimetype_from_name(zName);
2372
+ if( zMime && strncmp(zMime, "text/", 5)==0 ){
2373
+ style_submenu_element("Annotate", "%R/annotate?filename=%T&checkin=%T",
2374
+ zName, zCI);
2375
+ style_submenu_element("Blame", "%R/blame?filename=%T&checkin=%T",
2376
+ zName, zCI);
2377
+ }
23752378
blob_init(&downloadName, zName, -1);
23762379
objType = OBJTYPE_CONTENT;
23772380
}else{
23782381
@ <h2>Artifact
23792382
style_copy_button(1, "hash-ar", 0, 2, "%s", zUuid);
@@ -2384,10 +2387,11 @@
23842387
}
23852388
blob_zero(&downloadName);
23862389
if( asText ) objdescFlags &= ~OBJDESC_BASE;
23872390
objType = object_description(rid, objdescFlags,
23882391
(isFile?zName:0), &downloadName);
2392
+ zMime = mimetype_from_name(blob_str(&downloadName));
23892393
}
23902394
if( !descOnly && P("download")!=0 ){
23912395
cgi_redirectf("%R/raw/%s?at=%T",
23922396
db_text("x", "SELECT uuid FROM blob WHERE rid=%d", rid),
23932397
file_tail(blob_str(&downloadName)));
@@ -2439,11 +2443,10 @@
24392443
}
24402444
style_submenu_element("Download", "%R/raw/%s?at=%T", zUuid, file_tail(zName));
24412445
if( db_exists("SELECT 1 FROM mlink WHERE fid=%d", rid) ){
24422446
style_submenu_element("Check-ins Using", "%R/timeline?uf=%s", zUuid);
24432447
}
2444
- zMime = mimetype_from_name(blob_str(&downloadName));
24452448
if( zMime ){
24462449
if( fossil_strcmp(zMime, "text/html")==0 ){
24472450
if( asText ){
24482451
style_submenu_element("Html", "%s", url_render(&url, "txt", 0, 0, 0));
24492452
}else{
@@ -2504,11 +2507,11 @@
25042507
style_submenu_element("Hex", "%R/hexdump?name=%s", zUuid);
25052508
if( zLn==0 || atoi(zLn)==0 ){
25062509
style_submenu_checkbox("ln", "Line Numbers", 0, 0);
25072510
}
25082511
blob_to_utf8_no_bom(&content, 0);
2509
- zMime = mimetype_from_content(&content);
2512
+ if( zMime==0 ) zMime = mimetype_from_content(&content);
25102513
@ <blockquote class="file-content">
25112514
if( zMime==0 ){
25122515
const char *z, *zFileName, *zExt;
25132516
z = blob_str(&content);
25142517
zFileName = db_text(0,
@@ -2531,10 +2534,14 @@
25312534
}
25322535
}else if( strncmp(zMime, "image/", 6)==0 ){
25332536
@ <p>(file is %d(blob_size(&content)) bytes of image data)</i></p>
25342537
@ <p><img src="%R/raw/%s(zUuid)?m=%s(zMime)"></p>
25352538
style_submenu_element("Image", "%R/raw/%s?m=%s", zUuid, zMime);
2539
+ }else if( strncmp(zMime, "audio/", 6)==0 ){
2540
+ @ <audio controls src="%R/raw/%s(zUuid)?m=%s(zMime)">
2541
+ @ (Not supported by this browser)
2542
+ @ </audio>
25362543
}else{
25372544
@ <i>(file is %d(blob_size(&content)) bytes of binary data)</i>
25382545
}
25392546
@ </blockquote>
25402547
}
25412548
--- src/info.c
+++ src/info.c
@@ -2366,14 +2366,17 @@
2366 @ part of check-in %z(href("%R/info/%!S",zCIUuid))%S(zCIUuid)</a></h2>
2367 }
2368 blob_reset(&path);
2369 }
2370 style_submenu_element("Artifact", "%R/artifact/%S", zUuid);
2371 style_submenu_element("Annotate", "%R/annotate?filename=%T&checkin=%T",
2372 zName, zCI);
2373 style_submenu_element("Blame", "%R/blame?filename=%T&checkin=%T",
2374 zName, zCI);
 
 
 
2375 blob_init(&downloadName, zName, -1);
2376 objType = OBJTYPE_CONTENT;
2377 }else{
2378 @ <h2>Artifact
2379 style_copy_button(1, "hash-ar", 0, 2, "%s", zUuid);
@@ -2384,10 +2387,11 @@
2384 }
2385 blob_zero(&downloadName);
2386 if( asText ) objdescFlags &= ~OBJDESC_BASE;
2387 objType = object_description(rid, objdescFlags,
2388 (isFile?zName:0), &downloadName);
 
2389 }
2390 if( !descOnly && P("download")!=0 ){
2391 cgi_redirectf("%R/raw/%s?at=%T",
2392 db_text("x", "SELECT uuid FROM blob WHERE rid=%d", rid),
2393 file_tail(blob_str(&downloadName)));
@@ -2439,11 +2443,10 @@
2439 }
2440 style_submenu_element("Download", "%R/raw/%s?at=%T", zUuid, file_tail(zName));
2441 if( db_exists("SELECT 1 FROM mlink WHERE fid=%d", rid) ){
2442 style_submenu_element("Check-ins Using", "%R/timeline?uf=%s", zUuid);
2443 }
2444 zMime = mimetype_from_name(blob_str(&downloadName));
2445 if( zMime ){
2446 if( fossil_strcmp(zMime, "text/html")==0 ){
2447 if( asText ){
2448 style_submenu_element("Html", "%s", url_render(&url, "txt", 0, 0, 0));
2449 }else{
@@ -2504,11 +2507,11 @@
2504 style_submenu_element("Hex", "%R/hexdump?name=%s", zUuid);
2505 if( zLn==0 || atoi(zLn)==0 ){
2506 style_submenu_checkbox("ln", "Line Numbers", 0, 0);
2507 }
2508 blob_to_utf8_no_bom(&content, 0);
2509 zMime = mimetype_from_content(&content);
2510 @ <blockquote class="file-content">
2511 if( zMime==0 ){
2512 const char *z, *zFileName, *zExt;
2513 z = blob_str(&content);
2514 zFileName = db_text(0,
@@ -2531,10 +2534,14 @@
2531 }
2532 }else if( strncmp(zMime, "image/", 6)==0 ){
2533 @ <p>(file is %d(blob_size(&content)) bytes of image data)</i></p>
2534 @ <p><img src="%R/raw/%s(zUuid)?m=%s(zMime)"></p>
2535 style_submenu_element("Image", "%R/raw/%s?m=%s", zUuid, zMime);
 
 
 
 
2536 }else{
2537 @ <i>(file is %d(blob_size(&content)) bytes of binary data)</i>
2538 }
2539 @ </blockquote>
2540 }
2541
--- src/info.c
+++ src/info.c
@@ -2366,14 +2366,17 @@
2366 @ part of check-in %z(href("%R/info/%!S",zCIUuid))%S(zCIUuid)</a></h2>
2367 }
2368 blob_reset(&path);
2369 }
2370 style_submenu_element("Artifact", "%R/artifact/%S", zUuid);
2371 zMime = mimetype_from_name(zName);
2372 if( zMime && strncmp(zMime, "text/", 5)==0 ){
2373 style_submenu_element("Annotate", "%R/annotate?filename=%T&checkin=%T",
2374 zName, zCI);
2375 style_submenu_element("Blame", "%R/blame?filename=%T&checkin=%T",
2376 zName, zCI);
2377 }
2378 blob_init(&downloadName, zName, -1);
2379 objType = OBJTYPE_CONTENT;
2380 }else{
2381 @ <h2>Artifact
2382 style_copy_button(1, "hash-ar", 0, 2, "%s", zUuid);
@@ -2384,10 +2387,11 @@
2387 }
2388 blob_zero(&downloadName);
2389 if( asText ) objdescFlags &= ~OBJDESC_BASE;
2390 objType = object_description(rid, objdescFlags,
2391 (isFile?zName:0), &downloadName);
2392 zMime = mimetype_from_name(blob_str(&downloadName));
2393 }
2394 if( !descOnly && P("download")!=0 ){
2395 cgi_redirectf("%R/raw/%s?at=%T",
2396 db_text("x", "SELECT uuid FROM blob WHERE rid=%d", rid),
2397 file_tail(blob_str(&downloadName)));
@@ -2439,11 +2443,10 @@
2443 }
2444 style_submenu_element("Download", "%R/raw/%s?at=%T", zUuid, file_tail(zName));
2445 if( db_exists("SELECT 1 FROM mlink WHERE fid=%d", rid) ){
2446 style_submenu_element("Check-ins Using", "%R/timeline?uf=%s", zUuid);
2447 }
 
2448 if( zMime ){
2449 if( fossil_strcmp(zMime, "text/html")==0 ){
2450 if( asText ){
2451 style_submenu_element("Html", "%s", url_render(&url, "txt", 0, 0, 0));
2452 }else{
@@ -2504,11 +2507,11 @@
2507 style_submenu_element("Hex", "%R/hexdump?name=%s", zUuid);
2508 if( zLn==0 || atoi(zLn)==0 ){
2509 style_submenu_checkbox("ln", "Line Numbers", 0, 0);
2510 }
2511 blob_to_utf8_no_bom(&content, 0);
2512 if( zMime==0 ) zMime = mimetype_from_content(&content);
2513 @ <blockquote class="file-content">
2514 if( zMime==0 ){
2515 const char *z, *zFileName, *zExt;
2516 z = blob_str(&content);
2517 zFileName = db_text(0,
@@ -2531,10 +2534,14 @@
2534 }
2535 }else if( strncmp(zMime, "image/", 6)==0 ){
2536 @ <p>(file is %d(blob_size(&content)) bytes of image data)</i></p>
2537 @ <p><img src="%R/raw/%s(zUuid)?m=%s(zMime)"></p>
2538 style_submenu_element("Image", "%R/raw/%s?m=%s", zUuid, zMime);
2539 }else if( strncmp(zMime, "audio/", 6)==0 ){
2540 @ <audio controls src="%R/raw/%s(zUuid)?m=%s(zMime)">
2541 @ (Not supported by this browser)
2542 @ </audio>
2543 }else{
2544 @ <i>(file is %d(blob_size(&content)) bytes of binary data)</i>
2545 }
2546 @ </blockquote>
2547 }
2548

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button