Fossil SCM

Improved quoting for filenames on constructed command-lines.

drh 2021-06-22 18:57 trunk
Commit b3fab9b5ddfedf9332c177a1959c44bbc5dfe75879b845feae4f63df61ea16d0
2 files changed +93 -49 +6 -1
+93 -49
--- src/blob.c
+++ src/blob.c
@@ -1293,10 +1293,52 @@
12931293
z[--j] = z[i];
12941294
}
12951295
}
12961296
}
12971297
1298
+/*
1299
+** ASCII (for reference):
1300
+** x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf
1301
+** 0x ^` ^a ^b ^c ^d ^e ^f ^g \b \t \n () \f \r ^n ^o
1302
+** 1x ^p ^q ^r ^s ^t ^u ^v ^w ^x ^y ^z ^{ ^| ^} ^~ ^
1303
+** 2x () ! " # $ % & ' ( ) * + , - . /
1304
+** 3x 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
1305
+** 4x @ A B C D E F G H I J K L M N O
1306
+** 5x P Q R S T U V W X Y Z [ \ ] ^ _
1307
+** 6x ` a b c d e f g h i j k l m n o
1308
+** 7x p q r s t u v w x y z { | } ~ ^_
1309
+*/
1310
+
1311
+/*
1312
+** Characters that need to be escaped are marked with 1.
1313
+** Illegal characters are marked with 2.
1314
+*/
1315
+static const char aSafeChar[256] = {
1316
+#ifdef _WIN32
1317
+/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */
1318
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x */
1319
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 1x */
1320
+ 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, /* 2x */
1321
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, /* 3x */
1322
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4x */
1323
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, /* 5x */
1324
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6x */
1325
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* 7x */
1326
+#else
1327
+/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */
1328
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x */
1329
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 1x */
1330
+ 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, /* 2x */
1331
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, /* 3x */
1332
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4x */
1333
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, /* 5x */
1334
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6x */
1335
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* 7x */
1336
+#endif
1337
+ /* All the rest are zeros */
1338
+};
1339
+
12981340
/*
12991341
** pBlob is a shell command under construction. This routine safely
13001342
** appends argument zIn.
13011343
**
13021344
** The argument is escaped if it contains white space or other characters
@@ -1309,69 +1351,71 @@
13091351
** filenames that begin with "-", if zIn begins with "-", prepend
13101352
** an additional "./".
13111353
*/
13121354
void blob_append_escaped_arg(Blob *pBlob, const char *zIn){
13131355
int i;
1314
- char c;
1356
+ unsigned char c;
13151357
int needEscape = 0;
1358
+ int hasIllegal = 0;
13161359
int n = blob_size(pBlob);
13171360
char *z = blob_buffer(pBlob);
13181361
#if defined(_WIN32)
1319
- const char cDirSep = '\\'; /* Use \ as directory separator */
1320
- const char cQuote = '"'; /* Use "..." quoting on windows */
1321
- const char cEscape = '^'; /* Use ^X escaping on windows */
1362
+ const char *zNeedQuote = "\"^[];*? ";
13221363
#else
1323
- const char cDirSep = '/'; /* Use / as directory separator */
1324
- const char cQuote = '\''; /* Use '...' quoting on unix */
1325
- const char cEscape = '\\'; /* Use \X escaping on unix */
1364
+ const char *zNeedQuote = "\"'\\*?$&|` ";
13261365
#endif
13271366
1328
- for(i=0; (c = zIn[i])!=0; i++){
1329
- if( c==cQuote || (unsigned char)c<' ' ||
1330
- c==cEscape || c==';' || c=='*' || c=='?' || c=='[' ){
1331
- Blob bad;
1332
- blob_token(pBlob, &bad);
1333
- fossil_fatal("the [%s] argument to the \"%s\" command contains "
1334
- "a character (ascii 0x%02x) that is a security risk",
1335
- zIn, blob_str(&bad), c);
1336
- }
1337
- if( !needEscape && !fossil_isalnum(c) && c!=cDirSep && c!='.' && c!='_' ){
1338
- needEscape = 1;
1339
- }
1340
- }
1367
+ /* Any control character is illegal. This prevents \n and \r in an
1368
+ ** argument. */
1369
+ for(i=0; (c = (unsigned char)zIn[i])!=0; i++){
1370
+ if( aSafeChar[c] ){
1371
+ if( aSafeChar[c]==2 ){
1372
+ Blob bad;
1373
+ blob_token(pBlob, &bad);
1374
+ fossil_fatal("the [%s] argument to the \"%s\" command contains "
1375
+ "a character (ascii 0x%02x) that is a security risk",
1376
+ zIn, blob_str(&bad), c);
1377
+ }else{
1378
+ needEscape = 1;
1379
+ }
1380
+ break;
1381
+ }
1382
+ }
1383
+
1384
+ /* Separate from the previous argument by a space */
13411385
if( n>0 && !fossil_isspace(z[n-1]) ){
13421386
blob_append_char(pBlob, ' ');
13431387
}
1344
- if( needEscape ) blob_append_char(pBlob, cQuote);
1345
- if( zIn[0]=='-' ){
1346
- blob_append_char(pBlob, '.');
1347
- blob_append_char(pBlob, cDirSep);
1348
-#if defined(_WIN32)
1349
- }else if( zIn[0]=='/' ){
1350
- blob_append_char(pBlob, '.');
1351
-#endif
1352
- }
1353
-#if defined(_WIN32)
1354
- if( needEscape ){
1355
- for(i=0; (c = zIn[i])!=0; i++){
1356
- if( c==cQuote ) blob_append_char(pBlob, cDirSep);
1357
- blob_append_char(pBlob, c);
1358
- }
1359
- }else{
1360
- blob_append(pBlob, zIn, -1);
1361
- }
1362
-#else
1363
- blob_append(pBlob, zIn, -1);
1364
-#endif
1365
- if( needEscape ){
1366
-#if defined(_WIN32)
1367
- /* NOTE: Trailing backslash must be doubled before final double quote. */
1368
- if( pBlob->aData[pBlob->nUsed-1]==cDirSep ){
1369
- blob_append_char(pBlob, cDirSep);
1370
- }
1371
-#endif
1372
- blob_append_char(pBlob, cQuote);
1388
+
1389
+ /* Check for characters that need quoting */
1390
+ needEscape = strpbrk(zIn, zNeedQuote)!=0;
1391
+ if( !needEscape ){
1392
+ blob_append(pBlob, zIn, -1);
1393
+ }else{
1394
+#if defined(_WIN32)
1395
+ blob_append_char(pBlob, '"');
1396
+ if( zIn[0]=='-' ){
1397
+ blob_append_char(pBlob, '.');
1398
+ blob_append_char(pBlob, '\\');
1399
+ }else if( zIn[0]=='/' ){
1400
+ blob_append_char(pBlob, '.');
1401
+ }
1402
+ for(i=0; (c = (unsigned char)zIn[i])!=0; i++){
1403
+ blob_append_char(pBlob, (char)c);
1404
+ if( c=='"' ) blob_append_char(pBlob, '"');
1405
+ }
1406
+ blob_append_char(pBlob, '"');
1407
+#else
1408
+ if( zIn[0]=='-' ){
1409
+ blob_append_char(pBlob, '.');
1410
+ blob_append_char(pBlob, '/');
1411
+ }
1412
+ for(i=0; (c = (unsigned char)zIn[i])!=0; i++){
1413
+ if( aSafeChar[c] ) blob_append_char(pBlob, '\\');
1414
+ blob_append_char(pBlob, (char)c);
1415
+ }
1416
+#endif
13731417
}
13741418
}
13751419
13761420
/*
13771421
** COMMAND: test-escaped-arg
13781422
--- src/blob.c
+++ src/blob.c
@@ -1293,10 +1293,52 @@
1293 z[--j] = z[i];
1294 }
1295 }
1296 }
1297
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1298 /*
1299 ** pBlob is a shell command under construction. This routine safely
1300 ** appends argument zIn.
1301 **
1302 ** The argument is escaped if it contains white space or other characters
@@ -1309,69 +1351,71 @@
1309 ** filenames that begin with "-", if zIn begins with "-", prepend
1310 ** an additional "./".
1311 */
1312 void blob_append_escaped_arg(Blob *pBlob, const char *zIn){
1313 int i;
1314 char c;
1315 int needEscape = 0;
 
1316 int n = blob_size(pBlob);
1317 char *z = blob_buffer(pBlob);
1318 #if defined(_WIN32)
1319 const char cDirSep = '\\'; /* Use \ as directory separator */
1320 const char cQuote = '"'; /* Use "..." quoting on windows */
1321 const char cEscape = '^'; /* Use ^X escaping on windows */
1322 #else
1323 const char cDirSep = '/'; /* Use / as directory separator */
1324 const char cQuote = '\''; /* Use '...' quoting on unix */
1325 const char cEscape = '\\'; /* Use \X escaping on unix */
1326 #endif
1327
1328 for(i=0; (c = zIn[i])!=0; i++){
1329 if( c==cQuote || (unsigned char)c<' ' ||
1330 c==cEscape || c==';' || c=='*' || c=='?' || c=='[' ){
1331 Blob bad;
1332 blob_token(pBlob, &bad);
1333 fossil_fatal("the [%s] argument to the \"%s\" command contains "
1334 "a character (ascii 0x%02x) that is a security risk",
1335 zIn, blob_str(&bad), c);
1336 }
1337 if( !needEscape && !fossil_isalnum(c) && c!=cDirSep && c!='.' && c!='_' ){
1338 needEscape = 1;
1339 }
1340 }
 
 
 
 
 
1341 if( n>0 && !fossil_isspace(z[n-1]) ){
1342 blob_append_char(pBlob, ' ');
1343 }
1344 if( needEscape ) blob_append_char(pBlob, cQuote);
1345 if( zIn[0]=='-' ){
1346 blob_append_char(pBlob, '.');
1347 blob_append_char(pBlob, cDirSep);
1348 #if defined(_WIN32)
1349 }else if( zIn[0]=='/' ){
1350 blob_append_char(pBlob, '.');
1351 #endif
1352 }
1353 #if defined(_WIN32)
1354 if( needEscape ){
1355 for(i=0; (c = zIn[i])!=0; i++){
1356 if( c==cQuote ) blob_append_char(pBlob, cDirSep);
1357 blob_append_char(pBlob, c);
1358 }
1359 }else{
1360 blob_append(pBlob, zIn, -1);
1361 }
1362 #else
1363 blob_append(pBlob, zIn, -1);
1364 #endif
1365 if( needEscape ){
1366 #if defined(_WIN32)
1367 /* NOTE: Trailing backslash must be doubled before final double quote. */
1368 if( pBlob->aData[pBlob->nUsed-1]==cDirSep ){
1369 blob_append_char(pBlob, cDirSep);
1370 }
1371 #endif
1372 blob_append_char(pBlob, cQuote);
1373 }
1374 }
1375
1376 /*
1377 ** COMMAND: test-escaped-arg
1378
--- src/blob.c
+++ src/blob.c
@@ -1293,10 +1293,52 @@
1293 z[--j] = z[i];
1294 }
1295 }
1296 }
1297
1298 /*
1299 ** ASCII (for reference):
1300 ** x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf
1301 ** 0x ^` ^a ^b ^c ^d ^e ^f ^g \b \t \n () \f \r ^n ^o
1302 ** 1x ^p ^q ^r ^s ^t ^u ^v ^w ^x ^y ^z ^{ ^| ^} ^~ ^
1303 ** 2x () ! " # $ % & ' ( ) * + , - . /
1304 ** 3x 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
1305 ** 4x @ A B C D E F G H I J K L M N O
1306 ** 5x P Q R S T U V W X Y Z [ \ ] ^ _
1307 ** 6x ` a b c d e f g h i j k l m n o
1308 ** 7x p q r s t u v w x y z { | } ~ ^_
1309 */
1310
1311 /*
1312 ** Characters that need to be escaped are marked with 1.
1313 ** Illegal characters are marked with 2.
1314 */
1315 static const char aSafeChar[256] = {
1316 #ifdef _WIN32
1317 /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */
1318 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x */
1319 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 1x */
1320 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, /* 2x */
1321 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, /* 3x */
1322 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4x */
1323 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, /* 5x */
1324 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6x */
1325 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* 7x */
1326 #else
1327 /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */
1328 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x */
1329 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 1x */
1330 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, /* 2x */
1331 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, /* 3x */
1332 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4x */
1333 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, /* 5x */
1334 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6x */
1335 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* 7x */
1336 #endif
1337 /* All the rest are zeros */
1338 };
1339
1340 /*
1341 ** pBlob is a shell command under construction. This routine safely
1342 ** appends argument zIn.
1343 **
1344 ** The argument is escaped if it contains white space or other characters
@@ -1309,69 +1351,71 @@
1351 ** filenames that begin with "-", if zIn begins with "-", prepend
1352 ** an additional "./".
1353 */
1354 void blob_append_escaped_arg(Blob *pBlob, const char *zIn){
1355 int i;
1356 unsigned char c;
1357 int needEscape = 0;
1358 int hasIllegal = 0;
1359 int n = blob_size(pBlob);
1360 char *z = blob_buffer(pBlob);
1361 #if defined(_WIN32)
1362 const char *zNeedQuote = "\"^[];*? ";
 
 
1363 #else
1364 const char *zNeedQuote = "\"'\\*?$&|` ";
 
 
1365 #endif
1366
1367 /* Any control character is illegal. This prevents \n and \r in an
1368 ** argument. */
1369 for(i=0; (c = (unsigned char)zIn[i])!=0; i++){
1370 if( aSafeChar[c] ){
1371 if( aSafeChar[c]==2 ){
1372 Blob bad;
1373 blob_token(pBlob, &bad);
1374 fossil_fatal("the [%s] argument to the \"%s\" command contains "
1375 "a character (ascii 0x%02x) that is a security risk",
1376 zIn, blob_str(&bad), c);
1377 }else{
1378 needEscape = 1;
1379 }
1380 break;
1381 }
1382 }
1383
1384 /* Separate from the previous argument by a space */
1385 if( n>0 && !fossil_isspace(z[n-1]) ){
1386 blob_append_char(pBlob, ' ');
1387 }
1388
1389 /* Check for characters that need quoting */
1390 needEscape = strpbrk(zIn, zNeedQuote)!=0;
1391 if( !needEscape ){
1392 blob_append(pBlob, zIn, -1);
1393 }else{
1394 #if defined(_WIN32)
1395 blob_append_char(pBlob, '"');
1396 if( zIn[0]=='-' ){
1397 blob_append_char(pBlob, '.');
1398 blob_append_char(pBlob, '\\');
1399 }else if( zIn[0]=='/' ){
1400 blob_append_char(pBlob, '.');
1401 }
1402 for(i=0; (c = (unsigned char)zIn[i])!=0; i++){
1403 blob_append_char(pBlob, (char)c);
1404 if( c=='"' ) blob_append_char(pBlob, '"');
1405 }
1406 blob_append_char(pBlob, '"');
1407 #else
1408 if( zIn[0]=='-' ){
1409 blob_append_char(pBlob, '.');
1410 blob_append_char(pBlob, '/');
1411 }
1412 for(i=0; (c = (unsigned char)zIn[i])!=0; i++){
1413 if( aSafeChar[c] ) blob_append_char(pBlob, '\\');
1414 blob_append_char(pBlob, (char)c);
1415 }
1416 #endif
1417 }
1418 }
1419
1420 /*
1421 ** COMMAND: test-escaped-arg
1422
+6 -1
--- src/file.c
+++ src/file.c
@@ -1780,20 +1780,21 @@
17801780
** the root of zBasis in its name.
17811781
**
17821782
** If zTag is not NULL, then try to create the temp-file using zTag
17831783
** as a differentiator. If that fails, or if zTag is NULL, then use
17841784
** a bunch of random characters as the tag.
1785
+**
1786
+** Dangerous characters in zBasis are changed.
17851787
*/
17861788
void file_tempname(Blob *pBuf, const char *zBasis, const char *zTag){
17871789
#if defined(_WIN32)
17881790
const char *azDirs[] = {
17891791
0, /* GetTempPath */
17901792
0, /* TEMP */
17911793
0, /* TMP */
17921794
".",
17931795
};
1794
- char *z;
17951796
#else
17961797
static const char *azDirs[] = {
17971798
0, /* TMPDIR */
17981799
"/var/tmp",
17991800
"/usr/tmp",
@@ -1810,10 +1811,11 @@
18101811
const char *zDir = ".";
18111812
int cnt = 0;
18121813
char zRand[16];
18131814
int nBasis;
18141815
const char *zSuffix;
1816
+ char *z;
18151817
18161818
#if defined(_WIN32)
18171819
wchar_t zTmpPath[MAX_PATH];
18181820
18191821
if( GetTempPathW(MAX_PATH, zTmpPath) ){
@@ -1868,10 +1870,13 @@
18681870
zRand[15] = 0;
18691871
zTag = zRand;
18701872
}
18711873
blob_appendf(pBuf, "%s/%.*s~%s%s", zDir, nBasis, zBasis, zTag, zSuffix);
18721874
zTag = 0;
1875
+ for(z=blob_str(pBuf); z!=0 && (z=strpbrk(z,"'\"`;|$&"))!=0; z++){
1876
+ z[0] = '_';
1877
+ }
18731878
}while( file_size(blob_str(pBuf), ExtFILE)>=0 );
18741879
18751880
#if defined(_WIN32)
18761881
fossil_path_free((char *)azDirs[0]);
18771882
fossil_path_free((char *)azDirs[1]);
18781883
--- src/file.c
+++ src/file.c
@@ -1780,20 +1780,21 @@
1780 ** the root of zBasis in its name.
1781 **
1782 ** If zTag is not NULL, then try to create the temp-file using zTag
1783 ** as a differentiator. If that fails, or if zTag is NULL, then use
1784 ** a bunch of random characters as the tag.
 
 
1785 */
1786 void file_tempname(Blob *pBuf, const char *zBasis, const char *zTag){
1787 #if defined(_WIN32)
1788 const char *azDirs[] = {
1789 0, /* GetTempPath */
1790 0, /* TEMP */
1791 0, /* TMP */
1792 ".",
1793 };
1794 char *z;
1795 #else
1796 static const char *azDirs[] = {
1797 0, /* TMPDIR */
1798 "/var/tmp",
1799 "/usr/tmp",
@@ -1810,10 +1811,11 @@
1810 const char *zDir = ".";
1811 int cnt = 0;
1812 char zRand[16];
1813 int nBasis;
1814 const char *zSuffix;
 
1815
1816 #if defined(_WIN32)
1817 wchar_t zTmpPath[MAX_PATH];
1818
1819 if( GetTempPathW(MAX_PATH, zTmpPath) ){
@@ -1868,10 +1870,13 @@
1868 zRand[15] = 0;
1869 zTag = zRand;
1870 }
1871 blob_appendf(pBuf, "%s/%.*s~%s%s", zDir, nBasis, zBasis, zTag, zSuffix);
1872 zTag = 0;
 
 
 
1873 }while( file_size(blob_str(pBuf), ExtFILE)>=0 );
1874
1875 #if defined(_WIN32)
1876 fossil_path_free((char *)azDirs[0]);
1877 fossil_path_free((char *)azDirs[1]);
1878
--- src/file.c
+++ src/file.c
@@ -1780,20 +1780,21 @@
1780 ** the root of zBasis in its name.
1781 **
1782 ** If zTag is not NULL, then try to create the temp-file using zTag
1783 ** as a differentiator. If that fails, or if zTag is NULL, then use
1784 ** a bunch of random characters as the tag.
1785 **
1786 ** Dangerous characters in zBasis are changed.
1787 */
1788 void file_tempname(Blob *pBuf, const char *zBasis, const char *zTag){
1789 #if defined(_WIN32)
1790 const char *azDirs[] = {
1791 0, /* GetTempPath */
1792 0, /* TEMP */
1793 0, /* TMP */
1794 ".",
1795 };
 
1796 #else
1797 static const char *azDirs[] = {
1798 0, /* TMPDIR */
1799 "/var/tmp",
1800 "/usr/tmp",
@@ -1810,10 +1811,11 @@
1811 const char *zDir = ".";
1812 int cnt = 0;
1813 char zRand[16];
1814 int nBasis;
1815 const char *zSuffix;
1816 char *z;
1817
1818 #if defined(_WIN32)
1819 wchar_t zTmpPath[MAX_PATH];
1820
1821 if( GetTempPathW(MAX_PATH, zTmpPath) ){
@@ -1868,10 +1870,13 @@
1870 zRand[15] = 0;
1871 zTag = zRand;
1872 }
1873 blob_appendf(pBuf, "%s/%.*s~%s%s", zDir, nBasis, zBasis, zTag, zSuffix);
1874 zTag = 0;
1875 for(z=blob_str(pBuf); z!=0 && (z=strpbrk(z,"'\"`;|$&"))!=0; z++){
1876 z[0] = '_';
1877 }
1878 }while( file_size(blob_str(pBuf), ExtFILE)>=0 );
1879
1880 #if defined(_WIN32)
1881 fossil_path_free((char *)azDirs[0]);
1882 fossil_path_free((char *)azDirs[1]);
1883

Keyboard Shortcuts

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