| | @@ -31,10 +31,49 @@ |
| 31 | 31 | char *zPrevDir; /* Name of directory for previous entry */ |
| 32 | 32 | int nPrevDirAlloc; /* size of zPrevDir */ |
| 33 | 33 | Blob pax; /* PAX data */ |
| 34 | 34 | } tball; |
| 35 | 35 | |
| 36 | +/* |
| 37 | +** Compute a sensible base-name for an archive file (tarball, ZIP, or SQLAR) |
| 38 | +** based on the rid of the check-in contained in that file. |
| 39 | +** |
| 40 | +** PROJECTNAME-DATETIME-HASHPREFIX |
| 41 | +** |
| 42 | +** So that the name will be safe to use as a URL or a filename on any system, |
| 43 | +** the name is only allowed to contain lower-case ASCII alphabetics, |
| 44 | +** digits, '_' and '-'. Upper-case ASCII is converted to lower-case. All |
| 45 | +** other bytes are mapped into a lower-case alphabetic. |
| 46 | +** |
| 47 | +** The value returned is obtained from mprintf() or fossil_strdup() and should |
| 48 | +** be released by the caller using fossil_free(). |
| 49 | +*/ |
| 50 | +char *archive_base_name(int rid){ |
| 51 | + char *zName; |
| 52 | + int i; |
| 53 | + char c; |
| 54 | + zName = db_text(0, |
| 55 | + "SELECT coalesce(config.value,'unnamed')||" |
| 56 | + " strftime('-%%Y%%m%%d%%H%%M%%S-',event.mtime)||" |
| 57 | + " substr(blob.uuid,1,10)" |
| 58 | + " FROM blob, event LEFT JOIN config" |
| 59 | + " WHERE blob.rid=%d" |
| 60 | + " AND event.objid=%d" |
| 61 | + " AND config.name='project-name'", |
| 62 | + rid, rid); |
| 63 | + for(i=0; (c = zName[i])!=0; i++){ |
| 64 | + if( fossil_isupper(c) ){ |
| 65 | + zName[i] = fossil_tolower(c); |
| 66 | + }else if( !fossil_isalnum(c) && c!='_' && c!='-' ){ |
| 67 | + /* 123456789 123456789 123456 */ |
| 68 | + zName[i] = "abcdefghijklmnopqrstuvwxyz"[(unsigned)c%26]; |
| 69 | + } |
| 70 | + } |
| 71 | + return zName; |
| 72 | +} |
| 73 | + |
| 74 | + |
| 36 | 75 | |
| 37 | 76 | /* |
| 38 | 77 | ** field lengths of 'ustar' name and prefix fields. |
| 39 | 78 | */ |
| 40 | 79 | #define USTAR_NAME_LEN 100 |
| | @@ -653,19 +692,11 @@ |
| 653 | 692 | if( fossil_strcmp("/dev/null",zOut)==0 || fossil_strcmp("",zOut)==0 ){ |
| 654 | 693 | zOut = 0; |
| 655 | 694 | } |
| 656 | 695 | |
| 657 | 696 | if( zName==0 ){ |
| 658 | | - zName = db_text("default-name", |
| 659 | | - "SELECT replace(%Q,' ','_') " |
| 660 | | - " || strftime('_%%Y-%%m-%%d_%%H%%M%%S_', event.mtime) " |
| 661 | | - " || substr(blob.uuid, 1, 10)" |
| 662 | | - " FROM event, blob" |
| 663 | | - " WHERE event.objid=%d" |
| 664 | | - " AND blob.rid=%d", |
| 665 | | - db_get("project-name", "unnamed"), rid, rid |
| 666 | | - ); |
| 697 | + zName = archive_base_name(rid); |
| 667 | 698 | } |
| 668 | 699 | tarball_of_checkin(rid, zOut ? &tarball : 0, |
| 669 | 700 | zName, pInclude, pExclude, listFlag); |
| 670 | 701 | glob_free(pInclude); |
| 671 | 702 | glob_free(pExclude); |
| 672 | 703 | |