Fossil SCM
Use function more specific to detecting collisions to catch events, tickets and other types in blob.
Commit
ae6f27004b4210dc6cb60fae806efa11acebccac
Parent
0066d6c6a9afe51…
2 files changed
+23
-17
+27
-25
+23
-17
| --- src/info.c | ||
| +++ src/info.c | ||
| @@ -1890,36 +1890,42 @@ | ||
| 1890 | 1890 | void info_page(void){ |
| 1891 | 1891 | const char *zName; |
| 1892 | 1892 | Blob uuid; |
| 1893 | 1893 | int rid; |
| 1894 | 1894 | int rc; |
| 1895 | + int nLen; | |
| 1895 | 1896 | |
| 1896 | 1897 | zName = P("name"); |
| 1897 | 1898 | if( zName==0 ) fossil_redirect_home(); |
| 1899 | + nLen = strlen(zName); | |
| 1898 | 1900 | blob_set(&uuid, zName); |
| 1899 | - rc = name_to_uuid3(&uuid, -1, "*"); | |
| 1901 | + if( name_collisions(zName) ){ | |
| 1902 | + cgi_set_parameter("src","info"); | |
| 1903 | + ambiguous_page(); | |
| 1904 | + return; | |
| 1905 | + } | |
| 1906 | + rc = name_to_uuid(&uuid, -1, "*"); | |
| 1900 | 1907 | if( rc==1 ){ |
| 1901 | - if( validate16(zName, strlen(zName)) && | |
| 1902 | - db_exists("SELECT 1 FROM tag" | |
| 1903 | - " WHERE tagname GLOB 'event-%q*'", zName) ){ | |
| 1904 | - event_page(); | |
| 1905 | - return; | |
| 1906 | - }else{ | |
| 1907 | - style_header("No Such Object"); | |
| 1908 | - @ <p>No such object: %h(zName)</p> | |
| 1909 | - style_footer(); | |
| 1910 | - return; | |
| 1911 | - } | |
| 1908 | + if( validate16(zName, nLen) ){ | |
| 1909 | + if( db_exists("SELECT 1 FROM tag" | |
| 1910 | + " WHERE tagname GLOB 'event-%q*'", zName) ){ | |
| 1911 | + event_page(); | |
| 1912 | + return; | |
| 1913 | + } | |
| 1914 | + if( db_exists("SELECT 1 FROM ticket WHERE tkt_uuid GLOB '%q*'", zName) ){ | |
| 1915 | + tktview_page(); | |
| 1916 | + return; | |
| 1917 | + } | |
| 1918 | + } | |
| 1919 | + style_header("No Such Object"); | |
| 1920 | + @ <p>No such object of length %d(nLen): %h(zName)</p> | |
| 1921 | + style_footer(); | |
| 1922 | + return; | |
| 1912 | 1923 | }else if( rc==2 ){ |
| 1913 | 1924 | cgi_set_parameter("src","info"); |
| 1914 | 1925 | ambiguous_page(); |
| 1915 | 1926 | return; |
| 1916 | - }else if( rc==3 && validate16(zName, strlen(zName)) ){ | |
| 1917 | - if( db_exists("SELECT 1 FROM ticket WHERE tkt_uuid GLOB '%q*'", zName) ){ | |
| 1918 | - tktview_page(); | |
| 1919 | - return; | |
| 1920 | - } | |
| 1921 | 1927 | } |
| 1922 | 1928 | zName = blob_str(&uuid); |
| 1923 | 1929 | rid = db_int(0, "SELECT rid FROM blob WHERE uuid='%s'", zName); |
| 1924 | 1930 | if( rid==0 ){ |
| 1925 | 1931 | style_header("Broken Link"); |
| 1926 | 1932 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -1890,36 +1890,42 @@ | |
| 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 | blob_set(&uuid, zName); |
| 1899 | rc = name_to_uuid3(&uuid, -1, "*"); |
| 1900 | if( rc==1 ){ |
| 1901 | if( validate16(zName, strlen(zName)) && |
| 1902 | db_exists("SELECT 1 FROM tag" |
| 1903 | " WHERE tagname GLOB 'event-%q*'", zName) ){ |
| 1904 | event_page(); |
| 1905 | return; |
| 1906 | }else{ |
| 1907 | style_header("No Such Object"); |
| 1908 | @ <p>No such object: %h(zName)</p> |
| 1909 | style_footer(); |
| 1910 | return; |
| 1911 | } |
| 1912 | }else if( rc==2 ){ |
| 1913 | cgi_set_parameter("src","info"); |
| 1914 | ambiguous_page(); |
| 1915 | return; |
| 1916 | }else if( rc==3 && validate16(zName, strlen(zName)) ){ |
| 1917 | if( db_exists("SELECT 1 FROM ticket WHERE tkt_uuid GLOB '%q*'", zName) ){ |
| 1918 | tktview_page(); |
| 1919 | return; |
| 1920 | } |
| 1921 | } |
| 1922 | zName = blob_str(&uuid); |
| 1923 | rid = db_int(0, "SELECT rid FROM blob WHERE uuid='%s'", zName); |
| 1924 | if( rid==0 ){ |
| 1925 | style_header("Broken Link"); |
| 1926 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -1890,36 +1890,42 @@ | |
| 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 tag" |
| 1910 | " WHERE tagname GLOB 'event-%q*'", zName) ){ |
| 1911 | event_page(); |
| 1912 | return; |
| 1913 | } |
| 1914 | if( db_exists("SELECT 1 FROM ticket WHERE tkt_uuid GLOB '%q*'", zName) ){ |
| 1915 | tktview_page(); |
| 1916 | return; |
| 1917 | } |
| 1918 | } |
| 1919 | style_header("No Such Object"); |
| 1920 | @ <p>No such object of length %d(nLen): %h(zName)</p> |
| 1921 | style_footer(); |
| 1922 | return; |
| 1923 | }else if( rc==2 ){ |
| 1924 | cgi_set_parameter("src","info"); |
| 1925 | ambiguous_page(); |
| 1926 | return; |
| 1927 | } |
| 1928 | zName = blob_str(&uuid); |
| 1929 | rid = db_int(0, "SELECT rid FROM blob WHERE uuid='%s'", zName); |
| 1930 | if( rid==0 ){ |
| 1931 | style_header("Broken Link"); |
| 1932 |
+27
-25
| --- src/name.c | ||
| +++ src/name.c | ||
| @@ -337,38 +337,40 @@ | ||
| 337 | 337 | if((rid>0) && pUuid){ |
| 338 | 338 | *pUuid = db_text(NULL, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 339 | 339 | } |
| 340 | 340 | return rid; |
| 341 | 341 | } |
| 342 | + | |
| 342 | 343 | |
| 343 | 344 | /* |
| 344 | -** This routine is similar to name_to_uuid() except it also accounts for | |
| 345 | -** collisions in tickets which don't have an entry in blob (only associated | |
| 346 | -** ticket changes). | |
| 347 | -** Return 0 if rid is found. Return 1 if neither rid nor tkt_id is found. | |
| 348 | -** Return 2 if name is ambiguous. Return 3 if tkt_id is found. | |
| 345 | +** name_collisions searches through events, blobs, and tickets for | |
| 346 | +** collisions of a given UUID based on its length on UUIDs no shorter | |
| 347 | +** than 4 characters in length. | |
| 349 | 348 | */ |
| 350 | -int name_to_uuid3(Blob *pName, int iErrPriority, const char *zType){ | |
| 351 | - char *zName = blob_str(pName); | |
| 352 | - int tkt_id = 0; | |
| 353 | - int rid = symbolic_name_to_rid(zName, zType); | |
| 354 | - if( zType && zType[0]=='*' ){ | |
| 355 | - tkt_id = symbolic_name_to_tktid(zName); | |
| 356 | - } | |
| 357 | - if( rid<0 || tkt_id<0 || (rid>0 && tkt_id>0) ){ | |
| 358 | - fossil_error(iErrPriority, "ambiguous name: %s", zName); | |
| 359 | - return 2; | |
| 360 | - }else if( rid==0 && tkt_id==0 ){ | |
| 361 | - fossil_error(iErrPriority, "not found: %s", zName); | |
| 362 | - return 1; | |
| 363 | - }else if( tkt_id>0 ){ | |
| 364 | - return 3; | |
| 365 | - }else{ | |
| 366 | - blob_reset(pName); | |
| 367 | - db_blob(pName, "SELECT uuid FROM blob WHERE rid=%d", rid); | |
| 368 | - return 0; | |
| 369 | - } | |
| 349 | +int name_collisions(const char *zName){ | |
| 350 | + Stmt q; | |
| 351 | + int c = 0; /* count of collisions for zName */ | |
| 352 | + int nLen; /* length of zName */ | |
| 353 | + nLen = strlen(zName); | |
| 354 | + if( nLen>=4 && nLen<=UUID_SIZE && validate16(zName, nLen) ){ | |
| 355 | + db_prepare(&q, | |
| 356 | + "SELECT count(uuid) FROM" | |
| 357 | + " (SELECT substr(tkt_uuid, 1, %d) AS uuid FROM ticket" | |
| 358 | + " UNION ALL SELECT * FROM" | |
| 359 | + " (SELECT substr(tagname, 7, %d) FROM" | |
| 360 | + " tag WHERE tagname GLOB 'event-*')" | |
| 361 | + " UNION ALL SELECT * FROM" | |
| 362 | + " (SELECT substr(uuid, 1, %d) FROM blob))" | |
| 363 | + " WHERE uuid GLOB '%q*'" | |
| 364 | + " GROUP BY uuid HAVING count(uuid) > 1;", | |
| 365 | + nLen, nLen, nLen, zName); | |
| 366 | + if( db_step(&q)==SQLITE_ROW ){ | |
| 367 | + c = db_column_int(&q, 0); | |
| 368 | + } | |
| 369 | + db_finalize(&q); | |
| 370 | + } | |
| 371 | + return c; | |
| 370 | 372 | } |
| 371 | 373 | |
| 372 | 374 | /* |
| 373 | 375 | ** COMMAND: test-name-to-id |
| 374 | 376 | ** |
| 375 | 377 |
| --- src/name.c | |
| +++ src/name.c | |
| @@ -337,38 +337,40 @@ | |
| 337 | if((rid>0) && pUuid){ |
| 338 | *pUuid = db_text(NULL, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 339 | } |
| 340 | return rid; |
| 341 | } |
| 342 | |
| 343 | /* |
| 344 | ** This routine is similar to name_to_uuid() except it also accounts for |
| 345 | ** collisions in tickets which don't have an entry in blob (only associated |
| 346 | ** ticket changes). |
| 347 | ** Return 0 if rid is found. Return 1 if neither rid nor tkt_id is found. |
| 348 | ** Return 2 if name is ambiguous. Return 3 if tkt_id is found. |
| 349 | */ |
| 350 | int name_to_uuid3(Blob *pName, int iErrPriority, const char *zType){ |
| 351 | char *zName = blob_str(pName); |
| 352 | int tkt_id = 0; |
| 353 | int rid = symbolic_name_to_rid(zName, zType); |
| 354 | if( zType && zType[0]=='*' ){ |
| 355 | tkt_id = symbolic_name_to_tktid(zName); |
| 356 | } |
| 357 | if( rid<0 || tkt_id<0 || (rid>0 && tkt_id>0) ){ |
| 358 | fossil_error(iErrPriority, "ambiguous name: %s", zName); |
| 359 | return 2; |
| 360 | }else if( rid==0 && tkt_id==0 ){ |
| 361 | fossil_error(iErrPriority, "not found: %s", zName); |
| 362 | return 1; |
| 363 | }else if( tkt_id>0 ){ |
| 364 | return 3; |
| 365 | }else{ |
| 366 | blob_reset(pName); |
| 367 | db_blob(pName, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 368 | return 0; |
| 369 | } |
| 370 | } |
| 371 | |
| 372 | /* |
| 373 | ** COMMAND: test-name-to-id |
| 374 | ** |
| 375 |
| --- src/name.c | |
| +++ src/name.c | |
| @@ -337,38 +337,40 @@ | |
| 337 | if((rid>0) && pUuid){ |
| 338 | *pUuid = db_text(NULL, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 339 | } |
| 340 | return rid; |
| 341 | } |
| 342 | |
| 343 | |
| 344 | /* |
| 345 | ** name_collisions searches through events, blobs, and tickets for |
| 346 | ** collisions of a given UUID based on its length on UUIDs no shorter |
| 347 | ** than 4 characters in length. |
| 348 | */ |
| 349 | int name_collisions(const char *zName){ |
| 350 | Stmt q; |
| 351 | int c = 0; /* count of collisions for zName */ |
| 352 | int nLen; /* length of zName */ |
| 353 | nLen = strlen(zName); |
| 354 | if( nLen>=4 && nLen<=UUID_SIZE && validate16(zName, nLen) ){ |
| 355 | db_prepare(&q, |
| 356 | "SELECT count(uuid) FROM" |
| 357 | " (SELECT substr(tkt_uuid, 1, %d) AS uuid FROM ticket" |
| 358 | " UNION ALL SELECT * FROM" |
| 359 | " (SELECT substr(tagname, 7, %d) FROM" |
| 360 | " tag WHERE tagname GLOB 'event-*')" |
| 361 | " UNION ALL SELECT * FROM" |
| 362 | " (SELECT substr(uuid, 1, %d) FROM blob))" |
| 363 | " WHERE uuid GLOB '%q*'" |
| 364 | " GROUP BY uuid HAVING count(uuid) > 1;", |
| 365 | nLen, nLen, nLen, zName); |
| 366 | if( db_step(&q)==SQLITE_ROW ){ |
| 367 | c = db_column_int(&q, 0); |
| 368 | } |
| 369 | db_finalize(&q); |
| 370 | } |
| 371 | return c; |
| 372 | } |
| 373 | |
| 374 | /* |
| 375 | ** COMMAND: test-name-to-id |
| 376 | ** |
| 377 |