Fossil SCM

Enable diff expansion with the exbase= query parameter on /ckout.

drh 2024-12-14 23:42 ckout-exbase
Commit 4ba97a66aaad0f64695c4dd06c5d5f8d01cfe219772dddc67d36220388ea6d5a
1 file changed +62 -21
+62 -21
--- src/info.c
+++ src/info.c
@@ -778,16 +778,29 @@
778778
}
779779
blob_read_from_file(&rhs, zRhs, ExtFILE);
780780
if( blob_size(&lhs)!=blob_size(&rhs)
781781
|| memcmp(blob_buffer(&lhs), blob_buffer(&rhs), blob_size(&lhs))!=0
782782
){
783
+ char *zFullFN;
784
+ char *zHexFN;
785
+ int nFullFN;
786
+ zFullFN = file_canonical_name_dup(zLhs);
787
+ nFullFN = (int)strlen(zFullFN);
788
+ zHexFN = fossil_malloc( nFullFN*2 + 5 );
789
+ zHexFN[0] = 'x';
790
+ encode16((const u8*)zFullFN, (u8*)(zHexFN+1), nFullFN);
791
+ zHexFN[1+nFullFN*2] = 0;
792
+ fossil_free(zFullFN);
793
+ pCfg->zLeftHash = zHexFN;
783794
@ <div class='file-change-line'><span>
784795
@ Changes to %h(zFile)
785796
@ </span></div>
786797
if( pCfg ){
787798
text_diff(&lhs, &rhs, cgi_output_blob(), pCfg);
788799
}
800
+ pCfg->zLeftHash = 0;
801
+ fossil_free(zHexFN);
789802
}
790803
blob_reset(&lhs);
791804
blob_reset(&rhs);
792805
fossil_free(zLhs);
793806
fossil_free(zRhs);
@@ -2165,10 +2178,16 @@
21652178
** WEBPAGE: jchunk hidden
21662179
** URL: /jchunk/HASH?from=N&to=M
21672180
**
21682181
** Return lines of text from a file as a JSON array - one entry in the
21692182
** array for each line of text.
2183
+**
2184
+** The HASH is normally a sha1 or sha3 hash that identifies an artifact
2185
+** in the BLOB table of the database. However, if HASH starts with an "x"
2186
+** and is followed by valid hexadecimal, and if we are running in a
2187
+** "fossil ui" situation (locally and with privilege), then decode the hex
2188
+** into a filename and read the file content from that name.
21702189
**
21712190
** **Warning:** This is an internal-use-only interface that is subject to
21722191
** change at any moment. External application should not use this interface
21732192
** since the application will break when this interface changes, and this
21742193
** interface will undoubtedly change.
@@ -2180,10 +2199,11 @@
21802199
** ajax_route_error().
21812200
*/
21822201
void jchunk_page(void){
21832202
int rid = 0;
21842203
const char *zName = PD("name", "");
2204
+ int nName = (int)(strlen(zName)&0x7fffffff);
21852205
int iFrom = atoi(PD("from","0"));
21862206
int iTo = atoi(PD("to","0"));
21872207
int ln;
21882208
int go = 1;
21892209
const char *zSep;
@@ -2200,36 +2220,57 @@
22002220
cgi_check_for_malice();
22012221
if( !g.perm.Read ){
22022222
ajax_route_error(403, "Access requires Read permissions.");
22032223
return;
22042224
}
2205
-#if 1
2206
- /* Re-enable this block once this code is integrated somewhere into
2207
- the UI. */
2208
- rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", zName);
2209
- if( rid==0 ){
2210
- ajax_route_error(404, "Unknown artifact: %h", zName);
2211
- return;
2212
- }
2213
-#else
2214
- /* This impl is only to simplify "manual" testing via the JS
2215
- console. */
2216
- rid = symbolic_name_to_rid(zName, "*");
2217
- if( rid==0 ){
2218
- ajax_route_error(404, "Unknown artifact: %h", zName);
2219
- return;
2220
- }else if( rid<0 ){
2221
- ajax_route_error(418, "Ambiguous artifact name: %h", zName);
2222
- return;
2223
- }
2224
-#endif
22252225
if( iFrom<1 || iTo<iFrom ){
22262226
ajax_route_error(500, "Invalid line range from=%d, to=%d.",
22272227
iFrom, iTo);
22282228
return;
22292229
}
2230
- content_get(rid, &content);
2230
+ if( zName[0]=='x'
2231
+ && ((nName-1)&1)==0
2232
+ && validate16(&zName[1],nName-1)
2233
+ && g.perm.Admin
2234
+ && db_open_local(0)
2235
+ && cgi_is_loopback(g.zIpAddr)
2236
+ ){
2237
+ /* Treat the HASH as a hex-encoded filename */
2238
+ int n = (nName-1)/2;
2239
+ char *zFN = fossil_malloc(n+1);
2240
+ decode16((const u8*)&zName[1], (u8*)zFN, nName-1);
2241
+ zFN[n] = 0;
2242
+ if( file_size(zFN, ExtFILE)<0 ){
2243
+ blob_zero(&content);
2244
+ }else{
2245
+ blob_read_from_file(&content, zFN, ExtFILE);
2246
+ }
2247
+ fossil_free(zFN);
2248
+ }else{
2249
+ /* Treat the HASH as an artifact hash matching BLOB.UUID */
2250
+#if 1
2251
+ /* Re-enable this block once this code is integrated somewhere into
2252
+ the UI. */
2253
+ rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", zName);
2254
+ if( rid==0 ){
2255
+ ajax_route_error(404, "Unknown artifact: %h", zName);
2256
+ return;
2257
+ }
2258
+#else
2259
+ /* This impl is only to simplify "manual" testing via the JS
2260
+ console. */
2261
+ rid = symbolic_name_to_rid(zName, "*");
2262
+ if( rid==0 ){
2263
+ ajax_route_error(404, "Unknown artifact: %h", zName);
2264
+ return;
2265
+ }else if( rid<0 ){
2266
+ ajax_route_error(418, "Ambiguous artifact name: %h", zName);
2267
+ return;
2268
+ }
2269
+#endif
2270
+ content_get(rid, &content);
2271
+ }
22312272
g.isConst = 1;
22322273
cgi_set_content_type("application/json");
22332274
ln = 0;
22342275
while( go && ln<iFrom ){
22352276
go = blob_line(&content, &line);
22362277
--- src/info.c
+++ src/info.c
@@ -778,16 +778,29 @@
778 }
779 blob_read_from_file(&rhs, zRhs, ExtFILE);
780 if( blob_size(&lhs)!=blob_size(&rhs)
781 || memcmp(blob_buffer(&lhs), blob_buffer(&rhs), blob_size(&lhs))!=0
782 ){
 
 
 
 
 
 
 
 
 
 
 
783 @ <div class='file-change-line'><span>
784 @ Changes to %h(zFile)
785 @ </span></div>
786 if( pCfg ){
787 text_diff(&lhs, &rhs, cgi_output_blob(), pCfg);
788 }
 
 
789 }
790 blob_reset(&lhs);
791 blob_reset(&rhs);
792 fossil_free(zLhs);
793 fossil_free(zRhs);
@@ -2165,10 +2178,16 @@
2165 ** WEBPAGE: jchunk hidden
2166 ** URL: /jchunk/HASH?from=N&to=M
2167 **
2168 ** Return lines of text from a file as a JSON array - one entry in the
2169 ** array for each line of text.
 
 
 
 
 
 
2170 **
2171 ** **Warning:** This is an internal-use-only interface that is subject to
2172 ** change at any moment. External application should not use this interface
2173 ** since the application will break when this interface changes, and this
2174 ** interface will undoubtedly change.
@@ -2180,10 +2199,11 @@
2180 ** ajax_route_error().
2181 */
2182 void jchunk_page(void){
2183 int rid = 0;
2184 const char *zName = PD("name", "");
 
2185 int iFrom = atoi(PD("from","0"));
2186 int iTo = atoi(PD("to","0"));
2187 int ln;
2188 int go = 1;
2189 const char *zSep;
@@ -2200,36 +2220,57 @@
2200 cgi_check_for_malice();
2201 if( !g.perm.Read ){
2202 ajax_route_error(403, "Access requires Read permissions.");
2203 return;
2204 }
2205 #if 1
2206 /* Re-enable this block once this code is integrated somewhere into
2207 the UI. */
2208 rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", zName);
2209 if( rid==0 ){
2210 ajax_route_error(404, "Unknown artifact: %h", zName);
2211 return;
2212 }
2213 #else
2214 /* This impl is only to simplify "manual" testing via the JS
2215 console. */
2216 rid = symbolic_name_to_rid(zName, "*");
2217 if( rid==0 ){
2218 ajax_route_error(404, "Unknown artifact: %h", zName);
2219 return;
2220 }else if( rid<0 ){
2221 ajax_route_error(418, "Ambiguous artifact name: %h", zName);
2222 return;
2223 }
2224 #endif
2225 if( iFrom<1 || iTo<iFrom ){
2226 ajax_route_error(500, "Invalid line range from=%d, to=%d.",
2227 iFrom, iTo);
2228 return;
2229 }
2230 content_get(rid, &content);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2231 g.isConst = 1;
2232 cgi_set_content_type("application/json");
2233 ln = 0;
2234 while( go && ln<iFrom ){
2235 go = blob_line(&content, &line);
2236
--- src/info.c
+++ src/info.c
@@ -778,16 +778,29 @@
778 }
779 blob_read_from_file(&rhs, zRhs, ExtFILE);
780 if( blob_size(&lhs)!=blob_size(&rhs)
781 || memcmp(blob_buffer(&lhs), blob_buffer(&rhs), blob_size(&lhs))!=0
782 ){
783 char *zFullFN;
784 char *zHexFN;
785 int nFullFN;
786 zFullFN = file_canonical_name_dup(zLhs);
787 nFullFN = (int)strlen(zFullFN);
788 zHexFN = fossil_malloc( nFullFN*2 + 5 );
789 zHexFN[0] = 'x';
790 encode16((const u8*)zFullFN, (u8*)(zHexFN+1), nFullFN);
791 zHexFN[1+nFullFN*2] = 0;
792 fossil_free(zFullFN);
793 pCfg->zLeftHash = zHexFN;
794 @ <div class='file-change-line'><span>
795 @ Changes to %h(zFile)
796 @ </span></div>
797 if( pCfg ){
798 text_diff(&lhs, &rhs, cgi_output_blob(), pCfg);
799 }
800 pCfg->zLeftHash = 0;
801 fossil_free(zHexFN);
802 }
803 blob_reset(&lhs);
804 blob_reset(&rhs);
805 fossil_free(zLhs);
806 fossil_free(zRhs);
@@ -2165,10 +2178,16 @@
2178 ** WEBPAGE: jchunk hidden
2179 ** URL: /jchunk/HASH?from=N&to=M
2180 **
2181 ** Return lines of text from a file as a JSON array - one entry in the
2182 ** array for each line of text.
2183 **
2184 ** The HASH is normally a sha1 or sha3 hash that identifies an artifact
2185 ** in the BLOB table of the database. However, if HASH starts with an "x"
2186 ** and is followed by valid hexadecimal, and if we are running in a
2187 ** "fossil ui" situation (locally and with privilege), then decode the hex
2188 ** into a filename and read the file content from that name.
2189 **
2190 ** **Warning:** This is an internal-use-only interface that is subject to
2191 ** change at any moment. External application should not use this interface
2192 ** since the application will break when this interface changes, and this
2193 ** interface will undoubtedly change.
@@ -2180,10 +2199,11 @@
2199 ** ajax_route_error().
2200 */
2201 void jchunk_page(void){
2202 int rid = 0;
2203 const char *zName = PD("name", "");
2204 int nName = (int)(strlen(zName)&0x7fffffff);
2205 int iFrom = atoi(PD("from","0"));
2206 int iTo = atoi(PD("to","0"));
2207 int ln;
2208 int go = 1;
2209 const char *zSep;
@@ -2200,36 +2220,57 @@
2220 cgi_check_for_malice();
2221 if( !g.perm.Read ){
2222 ajax_route_error(403, "Access requires Read permissions.");
2223 return;
2224 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2225 if( iFrom<1 || iTo<iFrom ){
2226 ajax_route_error(500, "Invalid line range from=%d, to=%d.",
2227 iFrom, iTo);
2228 return;
2229 }
2230 if( zName[0]=='x'
2231 && ((nName-1)&1)==0
2232 && validate16(&zName[1],nName-1)
2233 && g.perm.Admin
2234 && db_open_local(0)
2235 && cgi_is_loopback(g.zIpAddr)
2236 ){
2237 /* Treat the HASH as a hex-encoded filename */
2238 int n = (nName-1)/2;
2239 char *zFN = fossil_malloc(n+1);
2240 decode16((const u8*)&zName[1], (u8*)zFN, nName-1);
2241 zFN[n] = 0;
2242 if( file_size(zFN, ExtFILE)<0 ){
2243 blob_zero(&content);
2244 }else{
2245 blob_read_from_file(&content, zFN, ExtFILE);
2246 }
2247 fossil_free(zFN);
2248 }else{
2249 /* Treat the HASH as an artifact hash matching BLOB.UUID */
2250 #if 1
2251 /* Re-enable this block once this code is integrated somewhere into
2252 the UI. */
2253 rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", zName);
2254 if( rid==0 ){
2255 ajax_route_error(404, "Unknown artifact: %h", zName);
2256 return;
2257 }
2258 #else
2259 /* This impl is only to simplify "manual" testing via the JS
2260 console. */
2261 rid = symbolic_name_to_rid(zName, "*");
2262 if( rid==0 ){
2263 ajax_route_error(404, "Unknown artifact: %h", zName);
2264 return;
2265 }else if( rid<0 ){
2266 ajax_route_error(418, "Ambiguous artifact name: %h", zName);
2267 return;
2268 }
2269 #endif
2270 content_get(rid, &content);
2271 }
2272 g.isConst = 1;
2273 cgi_set_content_type("application/json");
2274 ln = 0;
2275 while( go && ln<iFrom ){
2276 go = blob_line(&content, &line);
2277

Keyboard Shortcuts

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