Fossil SCM
Fix the abbreviated project name escape mechanism for two less obvious dangers: - spaces at the end of the filename should be stripped. - control charaters are not allowed in filenames either.
Commit
e161527c3a372a97f396f5ff3c3e225323d94501
Parent
c334fc9ac711c2f…
1 file changed
+11
-8
+11
-8
| --- src/info.c | ||
| +++ src/info.c | ||
| @@ -579,17 +579,20 @@ | ||
| 579 | 579 | @ <td>%h(zUser) @ %h(zIpAddr) on %s(zDate)</td></tr> |
| 580 | 580 | } |
| 581 | 581 | db_finalize(&q2); |
| 582 | 582 | } |
| 583 | 583 | if( g.perm.Hyperlink ){ |
| 584 | - const char *zPJ = db_get("short-project-name", 0); | |
| 585 | - char *zProjName; | |
| 584 | + char *zPJ = db_get("short-project-name", 0); | |
| 585 | + Blob projName; | |
| 586 | 586 | int jj; |
| 587 | 587 | if( zPJ==0 ) zPJ = db_get("project-name", "unnamed"); |
| 588 | - zProjName = mprintf("%s", zPJ); | |
| 589 | - for(jj=0; zProjName[jj]; jj++){ | |
| 590 | - if( strchr("\"*/:<>?\\|", zProjName[jj]) ) zProjName[jj] = '_'; | |
| 588 | + blob_zero(&projName); | |
| 589 | + blob_append(&projName, zPJ, -1); | |
| 590 | + blob_trim(&projName); | |
| 591 | + zPJ = blob_str(&projName); | |
| 592 | + for(jj=0; zPJ[jj]; jj++){ | |
| 593 | + if( zPJ[jj]<' '||strchr("\"*/:<>?\\|", zPJ[jj]) ) zPJ[jj] = '_'; | |
| 591 | 594 | } |
| 592 | 595 | @ <tr><th>Timelines:</th><td> |
| 593 | 596 | @ %z(href("%R/timeline?f=%S",zUuid))family</a> |
| 594 | 597 | if( zParent ){ |
| 595 | 598 | @ | %z(href("%R/timeline?p=%S",zUuid))ancestors</a> |
| @@ -612,15 +615,15 @@ | ||
| 612 | 615 | |
| 613 | 616 | |
| 614 | 617 | /* The Download: line */ |
| 615 | 618 | if( g.perm.Zip ){ |
| 616 | 619 | char *zUrl = mprintf("%R/tarball/%t-%S.tar.gz?uuid=%s", |
| 617 | - zProjName, zUuid, zUuid); | |
| 620 | + zPJ, zUuid, zUuid); | |
| 618 | 621 | @ </td></tr> |
| 619 | 622 | @ <tr><th>Downloads:</th><td> |
| 620 | 623 | @ %z(href("%s",zUrl))Tarball</a> |
| 621 | - @ | %z(href("%R/zip/%t-%S.zip?uuid=%s",zProjName,zUuid,zUuid)) | |
| 624 | + @ | %z(href("%R/zip/%t-%S.zip?uuid=%s",zPJ,zUuid,zUuid)) | |
| 622 | 625 | @ ZIP archive</a> |
| 623 | 626 | fossil_free(zUrl); |
| 624 | 627 | } |
| 625 | 628 | @ </td></tr> |
| 626 | 629 | @ <tr><th>Other Links:</th> |
| @@ -631,11 +634,11 @@ | ||
| 631 | 634 | if( g.perm.Write ){ |
| 632 | 635 | @ | %z(href("%R/ci_edit?r=%S",zUuid))edit</a> |
| 633 | 636 | } |
| 634 | 637 | @ </td> |
| 635 | 638 | @ </tr> |
| 636 | - fossil_free(zProjName); | |
| 639 | + blob_reset(&projName); | |
| 637 | 640 | } |
| 638 | 641 | @ </table> |
| 639 | 642 | }else{ |
| 640 | 643 | style_header("Check-in Information"); |
| 641 | 644 | login_anonymous_available(); |
| 642 | 645 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -579,17 +579,20 @@ | |
| 579 | @ <td>%h(zUser) @ %h(zIpAddr) on %s(zDate)</td></tr> |
| 580 | } |
| 581 | db_finalize(&q2); |
| 582 | } |
| 583 | if( g.perm.Hyperlink ){ |
| 584 | const char *zPJ = db_get("short-project-name", 0); |
| 585 | char *zProjName; |
| 586 | int jj; |
| 587 | if( zPJ==0 ) zPJ = db_get("project-name", "unnamed"); |
| 588 | zProjName = mprintf("%s", zPJ); |
| 589 | for(jj=0; zProjName[jj]; jj++){ |
| 590 | if( strchr("\"*/:<>?\\|", zProjName[jj]) ) zProjName[jj] = '_'; |
| 591 | } |
| 592 | @ <tr><th>Timelines:</th><td> |
| 593 | @ %z(href("%R/timeline?f=%S",zUuid))family</a> |
| 594 | if( zParent ){ |
| 595 | @ | %z(href("%R/timeline?p=%S",zUuid))ancestors</a> |
| @@ -612,15 +615,15 @@ | |
| 612 | |
| 613 | |
| 614 | /* The Download: line */ |
| 615 | if( g.perm.Zip ){ |
| 616 | char *zUrl = mprintf("%R/tarball/%t-%S.tar.gz?uuid=%s", |
| 617 | zProjName, zUuid, zUuid); |
| 618 | @ </td></tr> |
| 619 | @ <tr><th>Downloads:</th><td> |
| 620 | @ %z(href("%s",zUrl))Tarball</a> |
| 621 | @ | %z(href("%R/zip/%t-%S.zip?uuid=%s",zProjName,zUuid,zUuid)) |
| 622 | @ ZIP archive</a> |
| 623 | fossil_free(zUrl); |
| 624 | } |
| 625 | @ </td></tr> |
| 626 | @ <tr><th>Other Links:</th> |
| @@ -631,11 +634,11 @@ | |
| 631 | if( g.perm.Write ){ |
| 632 | @ | %z(href("%R/ci_edit?r=%S",zUuid))edit</a> |
| 633 | } |
| 634 | @ </td> |
| 635 | @ </tr> |
| 636 | fossil_free(zProjName); |
| 637 | } |
| 638 | @ </table> |
| 639 | }else{ |
| 640 | style_header("Check-in Information"); |
| 641 | login_anonymous_available(); |
| 642 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -579,17 +579,20 @@ | |
| 579 | @ <td>%h(zUser) @ %h(zIpAddr) on %s(zDate)</td></tr> |
| 580 | } |
| 581 | db_finalize(&q2); |
| 582 | } |
| 583 | if( g.perm.Hyperlink ){ |
| 584 | char *zPJ = db_get("short-project-name", 0); |
| 585 | Blob projName; |
| 586 | int jj; |
| 587 | if( zPJ==0 ) zPJ = db_get("project-name", "unnamed"); |
| 588 | blob_zero(&projName); |
| 589 | blob_append(&projName, zPJ, -1); |
| 590 | blob_trim(&projName); |
| 591 | zPJ = blob_str(&projName); |
| 592 | for(jj=0; zPJ[jj]; jj++){ |
| 593 | if( zPJ[jj]<' '||strchr("\"*/:<>?\\|", zPJ[jj]) ) zPJ[jj] = '_'; |
| 594 | } |
| 595 | @ <tr><th>Timelines:</th><td> |
| 596 | @ %z(href("%R/timeline?f=%S",zUuid))family</a> |
| 597 | if( zParent ){ |
| 598 | @ | %z(href("%R/timeline?p=%S",zUuid))ancestors</a> |
| @@ -612,15 +615,15 @@ | |
| 615 | |
| 616 | |
| 617 | /* The Download: line */ |
| 618 | if( g.perm.Zip ){ |
| 619 | char *zUrl = mprintf("%R/tarball/%t-%S.tar.gz?uuid=%s", |
| 620 | zPJ, zUuid, zUuid); |
| 621 | @ </td></tr> |
| 622 | @ <tr><th>Downloads:</th><td> |
| 623 | @ %z(href("%s",zUrl))Tarball</a> |
| 624 | @ | %z(href("%R/zip/%t-%S.zip?uuid=%s",zPJ,zUuid,zUuid)) |
| 625 | @ ZIP archive</a> |
| 626 | fossil_free(zUrl); |
| 627 | } |
| 628 | @ </td></tr> |
| 629 | @ <tr><th>Other Links:</th> |
| @@ -631,11 +634,11 @@ | |
| 634 | if( g.perm.Write ){ |
| 635 | @ | %z(href("%R/ci_edit?r=%S",zUuid))edit</a> |
| 636 | } |
| 637 | @ </td> |
| 638 | @ </tr> |
| 639 | blob_reset(&projName); |
| 640 | } |
| 641 | @ </table> |
| 642 | }else{ |
| 643 | style_header("Check-in Information"); |
| 644 | login_anonymous_available(); |
| 645 |