Fossil SCM

Handle short UUID collisions for events, tickets and other artifacts in the /info page.

drh 2014-04-22 12:51 trunk merge
Commit 49467d2a494aae8b65e6ec8d118cb4fb0fe080c1
2 files changed +21 -10 +68 -1
+21 -10
--- src/info.c
+++ src/info.c
@@ -1890,28 +1890,39 @@
18901890
void info_page(void){
18911891
const char *zName;
18921892
Blob uuid;
18931893
int rid;
18941894
int rc;
1895
+ int nLen;
18951896
18961897
zName = P("name");
18971898
if( zName==0 ) fossil_redirect_home();
1898
- if( validate16(zName, strlen(zName)) ){
1899
- if( db_exists("SELECT 1 FROM ticket WHERE tkt_uuid GLOB '%q*'", zName) ){
1900
- tktview_page();
1901
- return;
1902
- }
1903
- if( db_exists("SELECT 1 FROM tag WHERE tagname GLOB 'event-%q*'", zName) ){
1904
- event_page();
1905
- return;
1906
- }
1907
- }
1899
+ nLen = strlen(zName);
19081900
blob_set(&uuid, zName);
1901
+ if( name_collisions(zName) ){
1902
+ cgi_set_parameter("src","info");
1903
+ ambiguous_page();
1904
+ return;
1905
+ }
19091906
rc = name_to_uuid(&uuid, -1, "*");
19101907
if( rc==1 ){
1908
+ if( validate16(zName, nLen) ){
1909
+ if( db_exists("SELECT 1 FROM ticket WHERE tkt_uuid GLOB '%q*'", zName) ){
1910
+ tktview_page();
1911
+ return;
1912
+ }
1913
+ if( db_exists("SELECT 1 FROM tag"
1914
+ " WHERE tagname GLOB 'event-%q*'", zName) ){
1915
+ event_page();
1916
+ return;
1917
+ }
1918
+ }
19111919
style_header("No Such Object");
19121920
@ <p>No such object: %h(zName)</p>
1921
+ if( nLen<4 ){
1922
+ @ <p>Objects of length < 4 are too ambiguous to worry about</p>
1923
+ }
19131924
style_footer();
19141925
return;
19151926
}else if( rc==2 ){
19161927
cgi_set_parameter("src","info");
19171928
ambiguous_page();
19181929
--- src/info.c
+++ src/info.c
@@ -1890,28 +1890,39 @@
1890 void info_page(void){
1891 const char *zName;
1892 Blob uuid;
1893 int rid;
1894 int rc;
 
1895
1896 zName = P("name");
1897 if( zName==0 ) fossil_redirect_home();
1898 if( validate16(zName, strlen(zName)) ){
1899 if( db_exists("SELECT 1 FROM ticket WHERE tkt_uuid GLOB '%q*'", zName) ){
1900 tktview_page();
1901 return;
1902 }
1903 if( db_exists("SELECT 1 FROM tag WHERE tagname GLOB 'event-%q*'", zName) ){
1904 event_page();
1905 return;
1906 }
1907 }
1908 blob_set(&uuid, zName);
 
 
 
 
 
1909 rc = name_to_uuid(&uuid, -1, "*");
1910 if( rc==1 ){
 
 
 
 
 
 
 
 
 
 
 
1911 style_header("No Such Object");
1912 @ <p>No such object: %h(zName)</p>
 
 
 
1913 style_footer();
1914 return;
1915 }else if( rc==2 ){
1916 cgi_set_parameter("src","info");
1917 ambiguous_page();
1918
--- src/info.c
+++ src/info.c
@@ -1890,28 +1890,39 @@
1890 void info_page(void){
1891 const char *zName;
1892 Blob uuid;
1893 int rid;
1894 int rc;
1895 int nLen;
1896
1897 zName = P("name");
1898 if( zName==0 ) fossil_redirect_home();
1899 nLen = strlen(zName);
 
 
 
 
 
 
 
 
 
1900 blob_set(&uuid, zName);
1901 if( name_collisions(zName) ){
1902 cgi_set_parameter("src","info");
1903 ambiguous_page();
1904 return;
1905 }
1906 rc = name_to_uuid(&uuid, -1, "*");
1907 if( rc==1 ){
1908 if( validate16(zName, nLen) ){
1909 if( db_exists("SELECT 1 FROM ticket WHERE tkt_uuid GLOB '%q*'", zName) ){
1910 tktview_page();
1911 return;
1912 }
1913 if( db_exists("SELECT 1 FROM tag"
1914 " WHERE tagname GLOB 'event-%q*'", zName) ){
1915 event_page();
1916 return;
1917 }
1918 }
1919 style_header("No Such Object");
1920 @ <p>No such object: %h(zName)</p>
1921 if( nLen<4 ){
1922 @ <p>Objects of length < 4 are too ambiguous to worry about</p>
1923 }
1924 style_footer();
1925 return;
1926 }else if( rc==2 ){
1927 cgi_set_parameter("src","info");
1928 ambiguous_page();
1929
+68 -1
--- src/name.c
+++ src/name.c
@@ -266,11 +266,10 @@
266266
}
267267
}
268268
return rid;
269269
}
270270
271
-
272271
/*
273272
** This routine takes a user-entered UUID which might be in mixed
274273
** case and might only be a prefix of the full UUID and converts it
275274
** into the full-length UUID in canonical form.
276275
**
@@ -319,10 +318,39 @@
319318
}
320319
return rid;
321320
}
322321
323322
323
+/*
324
+** name_collisions searches through events, blobs, and tickets for
325
+** collisions of a given UUID based on its length on UUIDs no shorter
326
+** than 4 characters in length.
327
+*/
328
+int name_collisions(const char *zName){
329
+ Stmt q;
330
+ int c = 0; /* count of collisions for zName */
331
+ int nLen; /* length of zName */
332
+ nLen = strlen(zName);
333
+ if( nLen>=4 && nLen<=UUID_SIZE && validate16(zName, nLen) ){
334
+ db_prepare(&q,
335
+ "SELECT count(uuid) FROM"
336
+ " (SELECT substr(tkt_uuid, 1, %d) AS uuid FROM ticket"
337
+ " UNION ALL SELECT * FROM"
338
+ " (SELECT substr(tagname, 7, %d) FROM"
339
+ " tag WHERE tagname GLOB 'event-*')"
340
+ " UNION ALL SELECT * FROM"
341
+ " (SELECT substr(uuid, 1, %d) FROM blob))"
342
+ " WHERE uuid GLOB '%q*'"
343
+ " GROUP BY uuid HAVING count(uuid) > 1;",
344
+ nLen, nLen, nLen, zName);
345
+ if( db_step(&q)==SQLITE_ROW ){
346
+ c = db_column_int(&q, 0);
347
+ }
348
+ db_finalize(&q);
349
+ }
350
+ return c;
351
+}
324352
325353
/*
326354
** COMMAND: test-name-to-id
327355
**
328356
** Convert a name to a full artifact ID.
@@ -406,10 +434,49 @@
406434
int rid = db_column_int(&q, 1);
407435
@ <li><p><a href="%s(g.zTop)/%T(zSrc)/%s(zUuid)">
408436
@ %s(zUuid)</a> -
409437
object_description(rid, 0, 0);
410438
@ </p></li>
439
+ }
440
+ db_finalize(&q);
441
+ db_prepare(&q,
442
+ " SELECT tkt_rid, tkt_uuid, title"
443
+ " FROM ticket, ticketchng"
444
+ " WHERE ticket.tkt_id = ticketchng.tkt_id"
445
+ " AND tkt_uuid GLOB '%q*'"
446
+ " GROUP BY tkt_uuid"
447
+ " ORDER BY tkt_ctime DESC", z);
448
+ while( db_step(&q)==SQLITE_ROW ){
449
+ int rid = db_column_int(&q, 0);
450
+ const char *zUuid = db_column_text(&q, 1);
451
+ const char *zTitle = db_column_text(&q, 2);
452
+ @ <li><p><a href="%s(g.zTop)/%T(zSrc)/%s(zUuid)">
453
+ @ %s(zUuid)</a> -
454
+ @ <ul></ul>
455
+ @ Ticket
456
+ hyperlink_to_uuid(zUuid);
457
+ @ - %s(zTitle).
458
+ @ <ul><li>
459
+ object_description(rid, 0, 0);
460
+ @ </li></ul>
461
+ @ </p></li>
462
+ }
463
+ db_finalize(&q);
464
+ db_prepare(&q,
465
+ "SELECT rid, uuid FROM"
466
+ " (SELECT tagxref.rid AS rid, substr(tagname, 7) AS uuid"
467
+ " FROM tagxref, tag WHERE tagxref.tagid = tag.tagid"
468
+ " AND tagname GLOB 'event-%q*') GROUP BY uuid", z);
469
+ while( db_step(&q)==SQLITE_ROW ){
470
+ int rid = db_column_int(&q, 0);
471
+ const char* zUuid = db_column_text(&q, 1);
472
+ @ <li><p><a href="%s(g.zTop)/%T(zSrc)/%s(zUuid)">
473
+ @ %s(zUuid)</a> -
474
+ @ <ul><li>
475
+ object_description(rid, 0, 0);
476
+ @ </li></ul>
477
+ @ </p></li>
411478
}
412479
@ </ol>
413480
db_finalize(&q);
414481
style_footer();
415482
}
416483
--- src/name.c
+++ src/name.c
@@ -266,11 +266,10 @@
266 }
267 }
268 return rid;
269 }
270
271
272 /*
273 ** This routine takes a user-entered UUID which might be in mixed
274 ** case and might only be a prefix of the full UUID and converts it
275 ** into the full-length UUID in canonical form.
276 **
@@ -319,10 +318,39 @@
319 }
320 return rid;
321 }
322
323
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
324
325 /*
326 ** COMMAND: test-name-to-id
327 **
328 ** Convert a name to a full artifact ID.
@@ -406,10 +434,49 @@
406 int rid = db_column_int(&q, 1);
407 @ <li><p><a href="%s(g.zTop)/%T(zSrc)/%s(zUuid)">
408 @ %s(zUuid)</a> -
409 object_description(rid, 0, 0);
410 @ </p></li>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
411 }
412 @ </ol>
413 db_finalize(&q);
414 style_footer();
415 }
416
--- src/name.c
+++ src/name.c
@@ -266,11 +266,10 @@
266 }
267 }
268 return rid;
269 }
270
 
271 /*
272 ** This routine takes a user-entered UUID which might be in mixed
273 ** case and might only be a prefix of the full UUID and converts it
274 ** into the full-length UUID in canonical form.
275 **
@@ -319,10 +318,39 @@
318 }
319 return rid;
320 }
321
322
323 /*
324 ** name_collisions searches through events, blobs, and tickets for
325 ** collisions of a given UUID based on its length on UUIDs no shorter
326 ** than 4 characters in length.
327 */
328 int name_collisions(const char *zName){
329 Stmt q;
330 int c = 0; /* count of collisions for zName */
331 int nLen; /* length of zName */
332 nLen = strlen(zName);
333 if( nLen>=4 && nLen<=UUID_SIZE && validate16(zName, nLen) ){
334 db_prepare(&q,
335 "SELECT count(uuid) FROM"
336 " (SELECT substr(tkt_uuid, 1, %d) AS uuid FROM ticket"
337 " UNION ALL SELECT * FROM"
338 " (SELECT substr(tagname, 7, %d) FROM"
339 " tag WHERE tagname GLOB 'event-*')"
340 " UNION ALL SELECT * FROM"
341 " (SELECT substr(uuid, 1, %d) FROM blob))"
342 " WHERE uuid GLOB '%q*'"
343 " GROUP BY uuid HAVING count(uuid) > 1;",
344 nLen, nLen, nLen, zName);
345 if( db_step(&q)==SQLITE_ROW ){
346 c = db_column_int(&q, 0);
347 }
348 db_finalize(&q);
349 }
350 return c;
351 }
352
353 /*
354 ** COMMAND: test-name-to-id
355 **
356 ** Convert a name to a full artifact ID.
@@ -406,10 +434,49 @@
434 int rid = db_column_int(&q, 1);
435 @ <li><p><a href="%s(g.zTop)/%T(zSrc)/%s(zUuid)">
436 @ %s(zUuid)</a> -
437 object_description(rid, 0, 0);
438 @ </p></li>
439 }
440 db_finalize(&q);
441 db_prepare(&q,
442 " SELECT tkt_rid, tkt_uuid, title"
443 " FROM ticket, ticketchng"
444 " WHERE ticket.tkt_id = ticketchng.tkt_id"
445 " AND tkt_uuid GLOB '%q*'"
446 " GROUP BY tkt_uuid"
447 " ORDER BY tkt_ctime DESC", z);
448 while( db_step(&q)==SQLITE_ROW ){
449 int rid = db_column_int(&q, 0);
450 const char *zUuid = db_column_text(&q, 1);
451 const char *zTitle = db_column_text(&q, 2);
452 @ <li><p><a href="%s(g.zTop)/%T(zSrc)/%s(zUuid)">
453 @ %s(zUuid)</a> -
454 @ <ul></ul>
455 @ Ticket
456 hyperlink_to_uuid(zUuid);
457 @ - %s(zTitle).
458 @ <ul><li>
459 object_description(rid, 0, 0);
460 @ </li></ul>
461 @ </p></li>
462 }
463 db_finalize(&q);
464 db_prepare(&q,
465 "SELECT rid, uuid FROM"
466 " (SELECT tagxref.rid AS rid, substr(tagname, 7) AS uuid"
467 " FROM tagxref, tag WHERE tagxref.tagid = tag.tagid"
468 " AND tagname GLOB 'event-%q*') GROUP BY uuid", z);
469 while( db_step(&q)==SQLITE_ROW ){
470 int rid = db_column_int(&q, 0);
471 const char* zUuid = db_column_text(&q, 1);
472 @ <li><p><a href="%s(g.zTop)/%T(zSrc)/%s(zUuid)">
473 @ %s(zUuid)</a> -
474 @ <ul><li>
475 object_description(rid, 0, 0);
476 @ </li></ul>
477 @ </p></li>
478 }
479 @ </ol>
480 db_finalize(&q);
481 style_footer();
482 }
483

Keyboard Shortcuts

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