Fossil SCM

merge current trunk

jkosche 2025-05-24 16:31 quickfilter merge
Commit 8cbcf36be3d7b7c62a2b27542fef4b4eea9bd7e48aa807b8c5cad2a1cdae7688
+1 -1
--- VERSION
+++ VERSION
@@ -1,1 +1,1 @@
1
-2.26
1
+2.27
22
--- VERSION
+++ VERSION
@@ -1,1 +1,1 @@
1 2.26
2
--- VERSION
+++ VERSION
@@ -1,1 +1,1 @@
1 2.27
2
+208 -192
--- extsrc/shell.c
+++ extsrc/shell.c
@@ -1622,34 +1622,10 @@
16221622
if( n>350 ) n = 350;
16231623
sqlite3_snprintf(sizeof(z), z, "%#+.*e", n, r);
16241624
sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT);
16251625
}
16261626
1627
-
1628
-/*
1629
-** SQL function: shell_module_schema(X)
1630
-**
1631
-** Return a fake schema for the table-valued function or eponymous virtual
1632
-** table X.
1633
-*/
1634
-static void shellModuleSchema(
1635
- sqlite3_context *pCtx,
1636
- int nVal,
1637
- sqlite3_value **apVal
1638
-){
1639
- const char *zName;
1640
- char *zFake;
1641
- UNUSED_PARAMETER(nVal);
1642
- zName = (const char*)sqlite3_value_text(apVal[0]);
1643
- zFake = zName? shellFakeSchema(sqlite3_context_db_handle(pCtx), 0, zName) : 0;
1644
- if( zFake ){
1645
- sqlite3_result_text(pCtx, sqlite3_mprintf("/* %s */", zFake),
1646
- -1, sqlite3_free);
1647
- free(zFake);
1648
- }
1649
-}
1650
-
16511627
/*
16521628
** SQL function: shell_add_schema(S,X)
16531629
**
16541630
** Add the schema name X to the CREATE statement in S and return the result.
16551631
** Examples:
@@ -1820,10 +1796,11 @@
18201796
# ifdef FILENAME_MAX
18211797
# define NAME_MAX (FILENAME_MAX)
18221798
# else
18231799
# define NAME_MAX (260)
18241800
# endif
1801
+# define DIRENT_NAME_MAX (NAME_MAX)
18251802
#endif
18261803
18271804
/*
18281805
** We need to define "NULL_INTPTR_T" and "BAD_INTPTR_T".
18291806
*/
@@ -1863,12 +1840,11 @@
18631840
#endif
18641841
18651842
/*
18661843
** Provide a macro, for use by the implementation, to determine if a
18671844
** particular directory entry should be skipped over when searching for
1868
-** the next directory entry that should be returned by the readdir() or
1869
-** readdir_r() functions.
1845
+** the next directory entry that should be returned by the readdir().
18701846
*/
18711847
18721848
#ifndef is_filtered
18731849
# define is_filtered(a) ((((a).attrib)&_A_HIDDEN) || (((a).attrib)&_A_SYSTEM))
18741850
#endif
@@ -1880,16 +1856,15 @@
18801856
18811857
extern const char *windirent_getenv(const char *name);
18821858
18831859
/*
18841860
** Finally, we can provide the function prototypes for the opendir(),
1885
-** readdir(), readdir_r(), and closedir() POSIX functions.
1861
+** readdir(), and closedir() POSIX functions.
18861862
*/
18871863
18881864
extern LPDIR opendir(const char *dirname);
18891865
extern LPDIRENT readdir(LPDIR dirp);
1890
-extern INT readdir_r(LPDIR dirp, LPDIRENT entry, LPDIRENT *result);
18911866
extern INT closedir(LPDIR dirp);
18921867
18931868
#endif /* defined(WIN32) && defined(_MSC_VER) */
18941869
18951870
/************************* End test_windirent.h ********************/
@@ -1942,27 +1917,45 @@
19421917
19431918
/*
19441919
** Implementation of the POSIX opendir() function using the MSVCRT.
19451920
*/
19461921
LPDIR opendir(
1947
- const char *dirname
1922
+ const char *dirname /* Directory name, UTF8 encoding */
19481923
){
1949
- struct _finddata_t data;
1924
+ struct _wfinddata_t data;
19501925
LPDIR dirp = (LPDIR)sqlite3_malloc(sizeof(DIR));
19511926
SIZE_T namesize = sizeof(data.name) / sizeof(data.name[0]);
1927
+ wchar_t *b1;
1928
+ sqlite3_int64 sz;
19521929
19531930
if( dirp==NULL ) return NULL;
19541931
memset(dirp, 0, sizeof(DIR));
19551932
19561933
/* TODO: Remove this if Unix-style root paths are not used. */
19571934
if( sqlite3_stricmp(dirname, "/")==0 ){
19581935
dirname = windirent_getenv("SystemDrive");
19591936
}
19601937
1961
- memset(&data, 0, sizeof(struct _finddata_t));
1962
- _snprintf(data.name, namesize, "%s\\*", dirname);
1963
- dirp->d_handle = _findfirst(data.name, &data);
1938
+ memset(&data, 0, sizeof(data));
1939
+ sz = strlen(dirname);
1940
+ b1 = sqlite3_malloc64( (sz+3)*sizeof(b1[0]) );
1941
+ if( b1==0 ){
1942
+ closedir(dirp);
1943
+ return NULL;
1944
+ }
1945
+ sz = MultiByteToWideChar(CP_UTF8, 0, dirname, sz, b1, sz);
1946
+ b1[sz++] = '\\';
1947
+ b1[sz++] = '*';
1948
+ b1[sz] = 0;
1949
+ if( sz+1>(sqlite3_int64)namesize ){
1950
+ closedir(dirp);
1951
+ sqlite3_free(b1);
1952
+ return NULL;
1953
+ }
1954
+ memcpy(data.name, b1, (sz+1)*sizeof(b1[0]));
1955
+ sqlite3_free(b1);
1956
+ dirp->d_handle = _wfindfirst(data.name, &data);
19641957
19651958
if( dirp->d_handle==BAD_INTPTR_T ){
19661959
closedir(dirp);
19671960
return NULL;
19681961
}
@@ -1969,34 +1962,33 @@
19691962
19701963
/* TODO: Remove this block to allow hidden and/or system files. */
19711964
if( is_filtered(data) ){
19721965
next:
19731966
1974
- memset(&data, 0, sizeof(struct _finddata_t));
1975
- if( _findnext(dirp->d_handle, &data)==-1 ){
1967
+ memset(&data, 0, sizeof(data));
1968
+ if( _wfindnext(dirp->d_handle, &data)==-1 ){
19761969
closedir(dirp);
19771970
return NULL;
19781971
}
19791972
19801973
/* TODO: Remove this block to allow hidden and/or system files. */
19811974
if( is_filtered(data) ) goto next;
19821975
}
19831976
19841977
dirp->d_first.d_attributes = data.attrib;
1985
- strncpy(dirp->d_first.d_name, data.name, NAME_MAX);
1986
- dirp->d_first.d_name[NAME_MAX] = '\0';
1987
-
1978
+ WideCharToMultiByte(CP_UTF8, 0, data.name, -1,
1979
+ dirp->d_first.d_name, DIRENT_NAME_MAX, 0, 0);
19881980
return dirp;
19891981
}
19901982
19911983
/*
19921984
** Implementation of the POSIX readdir() function using the MSVCRT.
19931985
*/
19941986
LPDIRENT readdir(
19951987
LPDIR dirp
19961988
){
1997
- struct _finddata_t data;
1989
+ struct _wfinddata_t data;
19981990
19991991
if( dirp==NULL ) return NULL;
20001992
20011993
if( dirp->d_first.d_ino==0 ){
20021994
dirp->d_first.d_ino++;
@@ -2005,69 +1997,23 @@
20051997
return &dirp->d_first;
20061998
}
20071999
20082000
next:
20092001
2010
- memset(&data, 0, sizeof(struct _finddata_t));
2011
- if( _findnext(dirp->d_handle, &data)==-1 ) return NULL;
2002
+ memset(&data, 0, sizeof(data));
2003
+ if( _wfindnext(dirp->d_handle, &data)==-1 ) return NULL;
20122004
20132005
/* TODO: Remove this block to allow hidden and/or system files. */
20142006
if( is_filtered(data) ) goto next;
20152007
20162008
dirp->d_next.d_ino++;
20172009
dirp->d_next.d_attributes = data.attrib;
2018
- strncpy(dirp->d_next.d_name, data.name, NAME_MAX);
2019
- dirp->d_next.d_name[NAME_MAX] = '\0';
2020
-
2010
+ WideCharToMultiByte(CP_UTF8, 0, data.name, -1,
2011
+ dirp->d_next.d_name, DIRENT_NAME_MAX, 0, 0);
20212012
return &dirp->d_next;
20222013
}
20232014
2024
-/*
2025
-** Implementation of the POSIX readdir_r() function using the MSVCRT.
2026
-*/
2027
-INT readdir_r(
2028
- LPDIR dirp,
2029
- LPDIRENT entry,
2030
- LPDIRENT *result
2031
-){
2032
- struct _finddata_t data;
2033
-
2034
- if( dirp==NULL ) return EBADF;
2035
-
2036
- if( dirp->d_first.d_ino==0 ){
2037
- dirp->d_first.d_ino++;
2038
- dirp->d_next.d_ino++;
2039
-
2040
- entry->d_ino = dirp->d_first.d_ino;
2041
- entry->d_attributes = dirp->d_first.d_attributes;
2042
- strncpy(entry->d_name, dirp->d_first.d_name, NAME_MAX);
2043
- entry->d_name[NAME_MAX] = '\0';
2044
-
2045
- *result = entry;
2046
- return 0;
2047
- }
2048
-
2049
-next:
2050
-
2051
- memset(&data, 0, sizeof(struct _finddata_t));
2052
- if( _findnext(dirp->d_handle, &data)==-1 ){
2053
- *result = NULL;
2054
- return ENOENT;
2055
- }
2056
-
2057
- /* TODO: Remove this block to allow hidden and/or system files. */
2058
- if( is_filtered(data) ) goto next;
2059
-
2060
- entry->d_ino = (ino_t)-1; /* not available */
2061
- entry->d_attributes = data.attrib;
2062
- strncpy(entry->d_name, data.name, NAME_MAX);
2063
- entry->d_name[NAME_MAX] = '\0';
2064
-
2065
- *result = entry;
2066
- return 0;
2067
-}
2068
-
20692015
/*
20702016
** Implementation of the POSIX closedir() function using the MSVCRT.
20712017
*/
20722018
INT closedir(
20732019
LPDIR dirp
@@ -8085,18 +8031,13 @@
80858031
# include "windows.h"
80868032
# include <io.h>
80878033
# include <direct.h>
80888034
/* # include "test_windirent.h" */
80898035
# define dirent DIRENT
8090
-# ifndef chmod
8091
-# define chmod _chmod
8092
-# endif
8093
-# ifndef stat
8094
-# define stat _stat
8095
-# endif
8096
-# define mkdir(path,mode) _mkdir(path)
8097
-# define lstat(path,buf) stat(path,buf)
8036
+# define stat _stat
8037
+# define chmod(path,mode) fileio_chmod(path,mode)
8038
+# define mkdir(path,mode) fileio_mkdir(path)
80988039
#endif
80998040
#include <time.h>
81008041
#include <errno.h>
81018042
81028043
/* When used as part of the CLI, the sqlite3_stdio.h module will have
@@ -8117,10 +8058,44 @@
81178058
#define FSDIR_COLUMN_MTIME 2 /* Last modification time */
81188059
#define FSDIR_COLUMN_DATA 3 /* File content */
81198060
#define FSDIR_COLUMN_PATH 4 /* Path to top of search */
81208061
#define FSDIR_COLUMN_DIR 5 /* Path is relative to this directory */
81218062
8063
+/*
8064
+** UTF8 chmod() function for Windows
8065
+*/
8066
+#if defined(_WIN32) || defined(WIN32)
8067
+static int fileio_chmod(const char *zPath, int pmode){
8068
+ sqlite3_int64 sz = strlen(zPath);
8069
+ wchar_t *b1 = sqlite3_malloc64( (sz+1)*sizeof(b1[0]) );
8070
+ int rc;
8071
+ if( b1==0 ) return -1;
8072
+ sz = MultiByteToWideChar(CP_UTF8, 0, zPath, sz, b1, sz);
8073
+ b1[sz] = 0;
8074
+ rc = _wchmod(b1, pmode);
8075
+ sqlite3_free(b1);
8076
+ return rc;
8077
+}
8078
+#endif
8079
+
8080
+/*
8081
+** UTF8 mkdir() function for Windows
8082
+*/
8083
+#if defined(_WIN32) || defined(WIN32)
8084
+static int fileio_mkdir(const char *zPath){
8085
+ sqlite3_int64 sz = strlen(zPath);
8086
+ wchar_t *b1 = sqlite3_malloc64( (sz+1)*sizeof(b1[0]) );
8087
+ int rc;
8088
+ if( b1==0 ) return -1;
8089
+ sz = MultiByteToWideChar(CP_UTF8, 0, zPath, sz, b1, sz);
8090
+ b1[sz] = 0;
8091
+ rc = _wmkdir(b1);
8092
+ sqlite3_free(b1);
8093
+ return rc;
8094
+}
8095
+#endif
8096
+
81228097
81238098
/*
81248099
** Set the result stored by context ctx to a blob containing the
81258100
** contents of file zName. Or, leave the result unchanged (NULL)
81268101
** if the file does not exist or is unreadable.
@@ -8278,11 +8253,17 @@
82788253
static int fileStat(
82798254
const char *zPath,
82808255
struct stat *pStatBuf
82818256
){
82828257
#if defined(_WIN32)
8283
- int rc = stat(zPath, pStatBuf);
8258
+ sqlite3_int64 sz = strlen(zPath);
8259
+ wchar_t *b1 = sqlite3_malloc64( (sz+1)*sizeof(b1[0]) );
8260
+ int rc;
8261
+ if( b1==0 ) return 1;
8262
+ sz = MultiByteToWideChar(CP_UTF8, 0, zPath, sz, b1, sz);
8263
+ b1[sz] = 0;
8264
+ rc = _wstat(b1, pStatBuf);
82848265
if( rc==0 ) statTimesToUtc(zPath, pStatBuf);
82858266
return rc;
82868267
#else
82878268
return stat(zPath, pStatBuf);
82888269
#endif
@@ -8296,13 +8277,11 @@
82968277
static int fileLinkStat(
82978278
const char *zPath,
82988279
struct stat *pStatBuf
82998280
){
83008281
#if defined(_WIN32)
8301
- int rc = lstat(zPath, pStatBuf);
8302
- if( rc==0 ) statTimesToUtc(zPath, pStatBuf);
8303
- return rc;
8282
+ return fileStat(zPath, pStatBuf);
83048283
#else
83058284
return lstat(zPath, pStatBuf);
83068285
#endif
83078286
}
83088287
@@ -16808,11 +16787,11 @@
1680816787
case SQLITE_FCNTL_POWERSAFE_OVERWRITE: zOp = "POWERSAFE_OVERWRITE"; break;
1680916788
case SQLITE_FCNTL_PRAGMA: {
1681016789
const char *const* a = (const char*const*)pArg;
1681116790
if( a[1] && strcmp(a[1],"vfstrace")==0 && a[2] ){
1681216791
const u8 *zArg = (const u8*)a[2];
16813
- if( zArg[0]>='0' && zArg[0]<=9 ){
16792
+ if( zArg[0]>='0' && zArg[0]<='9' ){
1681416793
pInfo->mTrace = (sqlite3_uint64)strtoll(a[2], 0, 0);
1681516794
}else{
1681616795
static const struct {
1681716796
const char *z;
1681816797
unsigned int m;
@@ -18709,10 +18688,13 @@
1870918688
rc = sqlite3_create_module(db, "sqlite_dbptr", &dbdata_module, (void*)1);
1871018689
}
1871118690
return rc;
1871218691
}
1871318692
18693
+#ifdef _WIN32
18694
+
18695
+#endif
1871418696
int sqlite3_dbdata_init(
1871518697
sqlite3 *db,
1871618698
char **pzErrMsg,
1871718699
const sqlite3_api_routines *pApi
1871818700
){
@@ -25592,107 +25574,108 @@
2559225574
" --plain Show results as text/plain, not as HTML",
2559325575
#endif
2559425576
};
2559525577
2559625578
/*
25597
-** Output help text.
25579
+** Output help text for commands that match zPattern.
25580
+**
25581
+** * If zPattern is NULL, then show all documented commands, but
25582
+** only give a one-line summary of each.
25583
+**
25584
+** * If zPattern is "-a" or "-all" or "--all" then show all help text
25585
+** for all commands except undocumented commands.
25586
+**
25587
+** * If zPattern is "0" then show all help for undocumented commands.
25588
+** Undocumented commands begin with "," instead of "." in the azHelp[]
25589
+** array.
25590
+**
25591
+** * If zPattern is a prefix for one or more documented commands, then
25592
+** show help for those commands. If only a single command matches the
25593
+** prefix, show the full text of the help. If multiple commands match,
25594
+** Only show just the first line of each.
2559825595
**
25599
-** zPattern describes the set of commands for which help text is provided.
25600
-** If zPattern is NULL, then show all commands, but only give a one-line
25601
-** description of each.
25596
+** * Otherwise, show the complete text of any documented command for which
25597
+** zPattern is a LIKE match for any text within that command help
25598
+** text.
2560225599
**
25603
-** Return the number of matches.
25600
+** Return the number commands that match zPattern.
2560425601
*/
2560525602
static int showHelp(FILE *out, const char *zPattern){
2560625603
int i = 0;
2560725604
int j = 0;
2560825605
int n = 0;
2560925606
char *zPat;
25610
- if( zPattern==0
25611
- || zPattern[0]=='0'
25612
- || cli_strcmp(zPattern,"-a")==0
25613
- || cli_strcmp(zPattern,"-all")==0
25614
- || cli_strcmp(zPattern,"--all")==0
25615
- ){
25616
- enum HelpWanted { HW_NoCull = 0, HW_SummaryOnly = 1, HW_Undoc = 2 };
25617
- enum HelpHave { HH_Undoc = 2, HH_Summary = 1, HH_More = 0 };
25618
- /* Show all or most commands
25619
- ** *zPattern==0 => summary of documented commands only
25620
- ** *zPattern=='0' => whole help for undocumented commands
25621
- ** Otherwise => whole help for documented commands
25622
- */
25623
- enum HelpWanted hw = HW_SummaryOnly;
25624
- enum HelpHave hh = HH_More;
25625
- if( zPattern!=0 ){
25626
- hw = (*zPattern=='0')? HW_NoCull|HW_Undoc : HW_NoCull;
25627
- }
25628
- for(i=0; i<ArraySize(azHelp); i++){
25629
- switch( azHelp[i][0] ){
25630
- case ',':
25631
- hh = HH_Summary|HH_Undoc;
25632
- break;
25633
- case '.':
25634
- hh = HH_Summary;
25635
- break;
25636
- default:
25637
- hh &= ~HH_Summary;
25638
- break;
25639
- }
25640
- if( ((hw^hh)&HH_Undoc)==0 ){
25641
- if( (hh&HH_Summary)!=0 ){
25642
- sqlite3_fprintf(out, ".%s\n", azHelp[i]+1);
25643
- ++n;
25644
- }else if( (hw&HW_SummaryOnly)==0 ){
25645
- sqlite3_fprintf(out, "%s\n", azHelp[i]);
25646
- }
25647
- }
25648
- }
25649
- }else{
25650
- /* Seek documented commands for which zPattern is an exact prefix */
25651
- zPat = sqlite3_mprintf(".%s*", zPattern);
25652
- shell_check_oom(zPat);
25653
- for(i=0; i<ArraySize(azHelp); i++){
25654
- if( sqlite3_strglob(zPat, azHelp[i])==0 ){
25655
- sqlite3_fprintf(out, "%s\n", azHelp[i]);
25656
- j = i+1;
25657
- n++;
25658
- }
25659
- }
25660
- sqlite3_free(zPat);
25661
- if( n ){
25662
- if( n==1 ){
25663
- /* when zPattern is a prefix of exactly one command, then include
25664
- ** the details of that command, which should begin at offset j */
25665
- while( j<ArraySize(azHelp)-1 && azHelp[j][0]==' ' ){
25666
- sqlite3_fprintf(out, "%s\n", azHelp[j]);
25667
- j++;
25668
- }
25669
- }
25670
- return n;
25671
- }
25672
- /* Look for documented commands that contain zPattern anywhere.
25673
- ** Show complete text of all documented commands that match. */
25674
- zPat = sqlite3_mprintf("%%%s%%", zPattern);
25675
- shell_check_oom(zPat);
25676
- for(i=0; i<ArraySize(azHelp); i++){
25677
- if( azHelp[i][0]==',' ){
25678
- while( i<ArraySize(azHelp)-1 && azHelp[i+1][0]==' ' ) ++i;
25679
- continue;
25680
- }
25681
- if( azHelp[i][0]=='.' ) j = i;
25682
- if( sqlite3_strlike(zPat, azHelp[i], 0)==0 ){
25683
- sqlite3_fprintf(out, "%s\n", azHelp[j]);
25684
- while( j<ArraySize(azHelp)-1 && azHelp[j+1][0]==' ' ){
25685
- j++;
25686
- sqlite3_fprintf(out, "%s\n", azHelp[j]);
25687
- }
25688
- i = j;
25689
- n++;
25690
- }
25691
- }
25692
- sqlite3_free(zPat);
25693
- }
25607
+ if( zPattern==0 ){
25608
+ /* Show just the first line for all help topics */
25609
+ zPattern = "[a-z]";
25610
+ }else if( cli_strcmp(zPattern,"-a")==0
25611
+ || cli_strcmp(zPattern,"-all")==0
25612
+ || cli_strcmp(zPattern,"--all")==0
25613
+ ){
25614
+ /* Show everything except undocumented commands */
25615
+ zPattern = ".";
25616
+ }else if( cli_strcmp(zPattern,"0")==0 ){
25617
+ /* Show complete help text of undocumented commands */
25618
+ int show = 0;
25619
+ for(i=0; i<ArraySize(azHelp); i++){
25620
+ if( azHelp[i][0]=='.' ){
25621
+ show = 0;
25622
+ }else if( azHelp[i][0]==',' ){
25623
+ show = 1;
25624
+ sqlite3_fprintf(out, ".%s\n", &azHelp[i][1]);
25625
+ n++;
25626
+ }else if( show ){
25627
+ sqlite3_fprintf(out, "%s\n", azHelp[i]);
25628
+ }
25629
+ }
25630
+ return n;
25631
+ }
25632
+
25633
+ /* Seek documented commands for which zPattern is an exact prefix */
25634
+ zPat = sqlite3_mprintf(".%s*", zPattern);
25635
+ shell_check_oom(zPat);
25636
+ for(i=0; i<ArraySize(azHelp); i++){
25637
+ if( sqlite3_strglob(zPat, azHelp[i])==0 ){
25638
+ sqlite3_fprintf(out, "%s\n", azHelp[i]);
25639
+ j = i+1;
25640
+ n++;
25641
+ }
25642
+ }
25643
+ sqlite3_free(zPat);
25644
+ if( n ){
25645
+ if( n==1 ){
25646
+ /* when zPattern is a prefix of exactly one command, then include
25647
+ ** the details of that command, which should begin at offset j */
25648
+ while( j<ArraySize(azHelp)-1 && azHelp[j][0]==' ' ){
25649
+ sqlite3_fprintf(out, "%s\n", azHelp[j]);
25650
+ j++;
25651
+ }
25652
+ }
25653
+ return n;
25654
+ }
25655
+
25656
+ /* Look for documented commands that contain zPattern anywhere.
25657
+ ** Show complete text of all documented commands that match. */
25658
+ zPat = sqlite3_mprintf("%%%s%%", zPattern);
25659
+ shell_check_oom(zPat);
25660
+ for(i=0; i<ArraySize(azHelp); i++){
25661
+ if( azHelp[i][0]==',' ){
25662
+ while( i<ArraySize(azHelp)-1 && azHelp[i+1][0]==' ' ) ++i;
25663
+ continue;
25664
+ }
25665
+ if( azHelp[i][0]=='.' ) j = i;
25666
+ if( sqlite3_strlike(zPat, azHelp[i], 0)==0 ){
25667
+ sqlite3_fprintf(out, "%s\n", azHelp[j]);
25668
+ while( j<ArraySize(azHelp)-1 && azHelp[j+1][0]==' ' ){
25669
+ j++;
25670
+ sqlite3_fprintf(out, "%s\n", azHelp[j]);
25671
+ }
25672
+ i = j;
25673
+ n++;
25674
+ }
25675
+ }
25676
+ sqlite3_free(zPat);
2569425677
return n;
2569525678
}
2569625679
2569725680
/* Forward reference */
2569825681
static int process_input(ShellState *p);
@@ -25937,10 +25920,43 @@
2593725920
int sleep = sqlite3_value_int(argv[0]);
2593825921
(void)argcUnused;
2593925922
sqlite3_sleep(sleep/1000);
2594025923
sqlite3_result_int(context, sleep);
2594125924
}
25925
+
25926
+/*
25927
+** SQL function: shell_module_schema(X)
25928
+**
25929
+** Return a fake schema for the table-valued function or eponymous virtual
25930
+** table X.
25931
+*/
25932
+static void shellModuleSchema(
25933
+ sqlite3_context *pCtx,
25934
+ int nVal,
25935
+ sqlite3_value **apVal
25936
+){
25937
+ const char *zName;
25938
+ char *zFake;
25939
+ ShellState *p = (ShellState*)sqlite3_user_data(pCtx);
25940
+ FILE *pSavedLog = p->pLog;
25941
+ UNUSED_PARAMETER(nVal);
25942
+ zName = (const char*)sqlite3_value_text(apVal[0]);
25943
+
25944
+ /* Temporarily disable the ".log" when calling shellFakeSchema() because
25945
+ ** shellFakeSchema() might generate failures for some ephemeral virtual
25946
+ ** tables due to missing arguments. Example: fts4aux.
25947
+ ** https://sqlite.org/forum/forumpost/42fe6520b803be51 */
25948
+ p->pLog = 0;
25949
+ zFake = zName? shellFakeSchema(sqlite3_context_db_handle(pCtx), 0, zName) : 0;
25950
+ p->pLog = pSavedLog;
25951
+
25952
+ if( zFake ){
25953
+ sqlite3_result_text(pCtx, sqlite3_mprintf("/* %s */", zFake),
25954
+ -1, sqlite3_free);
25955
+ free(zFake);
25956
+ }
25957
+}
2594225958
2594325959
/* Flags for open_db().
2594425960
**
2594525961
** The default behavior of open_db() is to exit(1) if the database fails to
2594625962
** open. The OPEN_DB_KEEPALIVE flag changes that so that it prints an error
@@ -26081,11 +26097,11 @@
2608126097
shellDtostr, 0, 0);
2608226098
sqlite3_create_function(p->db, "dtostr", 2, SQLITE_UTF8, 0,
2608326099
shellDtostr, 0, 0);
2608426100
sqlite3_create_function(p->db, "shell_add_schema", 3, SQLITE_UTF8, 0,
2608526101
shellAddSchemaName, 0, 0);
26086
- sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8, 0,
26102
+ sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8, p,
2608726103
shellModuleSchema, 0, 0);
2608826104
sqlite3_create_function(p->db, "shell_putsnl", 1, SQLITE_UTF8, p,
2608926105
shellPutsFunc, 0, 0);
2609026106
sqlite3_create_function(p->db, "usleep",1,SQLITE_UTF8,0,
2609126107
shellUSleepFunc, 0, 0);
2609226108
--- extsrc/shell.c
+++ extsrc/shell.c
@@ -1622,34 +1622,10 @@
1622 if( n>350 ) n = 350;
1623 sqlite3_snprintf(sizeof(z), z, "%#+.*e", n, r);
1624 sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT);
1625 }
1626
1627
1628 /*
1629 ** SQL function: shell_module_schema(X)
1630 **
1631 ** Return a fake schema for the table-valued function or eponymous virtual
1632 ** table X.
1633 */
1634 static void shellModuleSchema(
1635 sqlite3_context *pCtx,
1636 int nVal,
1637 sqlite3_value **apVal
1638 ){
1639 const char *zName;
1640 char *zFake;
1641 UNUSED_PARAMETER(nVal);
1642 zName = (const char*)sqlite3_value_text(apVal[0]);
1643 zFake = zName? shellFakeSchema(sqlite3_context_db_handle(pCtx), 0, zName) : 0;
1644 if( zFake ){
1645 sqlite3_result_text(pCtx, sqlite3_mprintf("/* %s */", zFake),
1646 -1, sqlite3_free);
1647 free(zFake);
1648 }
1649 }
1650
1651 /*
1652 ** SQL function: shell_add_schema(S,X)
1653 **
1654 ** Add the schema name X to the CREATE statement in S and return the result.
1655 ** Examples:
@@ -1820,10 +1796,11 @@
1820 # ifdef FILENAME_MAX
1821 # define NAME_MAX (FILENAME_MAX)
1822 # else
1823 # define NAME_MAX (260)
1824 # endif
 
1825 #endif
1826
1827 /*
1828 ** We need to define "NULL_INTPTR_T" and "BAD_INTPTR_T".
1829 */
@@ -1863,12 +1840,11 @@
1863 #endif
1864
1865 /*
1866 ** Provide a macro, for use by the implementation, to determine if a
1867 ** particular directory entry should be skipped over when searching for
1868 ** the next directory entry that should be returned by the readdir() or
1869 ** readdir_r() functions.
1870 */
1871
1872 #ifndef is_filtered
1873 # define is_filtered(a) ((((a).attrib)&_A_HIDDEN) || (((a).attrib)&_A_SYSTEM))
1874 #endif
@@ -1880,16 +1856,15 @@
1880
1881 extern const char *windirent_getenv(const char *name);
1882
1883 /*
1884 ** Finally, we can provide the function prototypes for the opendir(),
1885 ** readdir(), readdir_r(), and closedir() POSIX functions.
1886 */
1887
1888 extern LPDIR opendir(const char *dirname);
1889 extern LPDIRENT readdir(LPDIR dirp);
1890 extern INT readdir_r(LPDIR dirp, LPDIRENT entry, LPDIRENT *result);
1891 extern INT closedir(LPDIR dirp);
1892
1893 #endif /* defined(WIN32) && defined(_MSC_VER) */
1894
1895 /************************* End test_windirent.h ********************/
@@ -1942,27 +1917,45 @@
1942
1943 /*
1944 ** Implementation of the POSIX opendir() function using the MSVCRT.
1945 */
1946 LPDIR opendir(
1947 const char *dirname
1948 ){
1949 struct _finddata_t data;
1950 LPDIR dirp = (LPDIR)sqlite3_malloc(sizeof(DIR));
1951 SIZE_T namesize = sizeof(data.name) / sizeof(data.name[0]);
 
 
1952
1953 if( dirp==NULL ) return NULL;
1954 memset(dirp, 0, sizeof(DIR));
1955
1956 /* TODO: Remove this if Unix-style root paths are not used. */
1957 if( sqlite3_stricmp(dirname, "/")==0 ){
1958 dirname = windirent_getenv("SystemDrive");
1959 }
1960
1961 memset(&data, 0, sizeof(struct _finddata_t));
1962 _snprintf(data.name, namesize, "%s\\*", dirname);
1963 dirp->d_handle = _findfirst(data.name, &data);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1964
1965 if( dirp->d_handle==BAD_INTPTR_T ){
1966 closedir(dirp);
1967 return NULL;
1968 }
@@ -1969,34 +1962,33 @@
1969
1970 /* TODO: Remove this block to allow hidden and/or system files. */
1971 if( is_filtered(data) ){
1972 next:
1973
1974 memset(&data, 0, sizeof(struct _finddata_t));
1975 if( _findnext(dirp->d_handle, &data)==-1 ){
1976 closedir(dirp);
1977 return NULL;
1978 }
1979
1980 /* TODO: Remove this block to allow hidden and/or system files. */
1981 if( is_filtered(data) ) goto next;
1982 }
1983
1984 dirp->d_first.d_attributes = data.attrib;
1985 strncpy(dirp->d_first.d_name, data.name, NAME_MAX);
1986 dirp->d_first.d_name[NAME_MAX] = '\0';
1987
1988 return dirp;
1989 }
1990
1991 /*
1992 ** Implementation of the POSIX readdir() function using the MSVCRT.
1993 */
1994 LPDIRENT readdir(
1995 LPDIR dirp
1996 ){
1997 struct _finddata_t data;
1998
1999 if( dirp==NULL ) return NULL;
2000
2001 if( dirp->d_first.d_ino==0 ){
2002 dirp->d_first.d_ino++;
@@ -2005,69 +1997,23 @@
2005 return &dirp->d_first;
2006 }
2007
2008 next:
2009
2010 memset(&data, 0, sizeof(struct _finddata_t));
2011 if( _findnext(dirp->d_handle, &data)==-1 ) return NULL;
2012
2013 /* TODO: Remove this block to allow hidden and/or system files. */
2014 if( is_filtered(data) ) goto next;
2015
2016 dirp->d_next.d_ino++;
2017 dirp->d_next.d_attributes = data.attrib;
2018 strncpy(dirp->d_next.d_name, data.name, NAME_MAX);
2019 dirp->d_next.d_name[NAME_MAX] = '\0';
2020
2021 return &dirp->d_next;
2022 }
2023
2024 /*
2025 ** Implementation of the POSIX readdir_r() function using the MSVCRT.
2026 */
2027 INT readdir_r(
2028 LPDIR dirp,
2029 LPDIRENT entry,
2030 LPDIRENT *result
2031 ){
2032 struct _finddata_t data;
2033
2034 if( dirp==NULL ) return EBADF;
2035
2036 if( dirp->d_first.d_ino==0 ){
2037 dirp->d_first.d_ino++;
2038 dirp->d_next.d_ino++;
2039
2040 entry->d_ino = dirp->d_first.d_ino;
2041 entry->d_attributes = dirp->d_first.d_attributes;
2042 strncpy(entry->d_name, dirp->d_first.d_name, NAME_MAX);
2043 entry->d_name[NAME_MAX] = '\0';
2044
2045 *result = entry;
2046 return 0;
2047 }
2048
2049 next:
2050
2051 memset(&data, 0, sizeof(struct _finddata_t));
2052 if( _findnext(dirp->d_handle, &data)==-1 ){
2053 *result = NULL;
2054 return ENOENT;
2055 }
2056
2057 /* TODO: Remove this block to allow hidden and/or system files. */
2058 if( is_filtered(data) ) goto next;
2059
2060 entry->d_ino = (ino_t)-1; /* not available */
2061 entry->d_attributes = data.attrib;
2062 strncpy(entry->d_name, data.name, NAME_MAX);
2063 entry->d_name[NAME_MAX] = '\0';
2064
2065 *result = entry;
2066 return 0;
2067 }
2068
2069 /*
2070 ** Implementation of the POSIX closedir() function using the MSVCRT.
2071 */
2072 INT closedir(
2073 LPDIR dirp
@@ -8085,18 +8031,13 @@
8085 # include "windows.h"
8086 # include <io.h>
8087 # include <direct.h>
8088 /* # include "test_windirent.h" */
8089 # define dirent DIRENT
8090 # ifndef chmod
8091 # define chmod _chmod
8092 # endif
8093 # ifndef stat
8094 # define stat _stat
8095 # endif
8096 # define mkdir(path,mode) _mkdir(path)
8097 # define lstat(path,buf) stat(path,buf)
8098 #endif
8099 #include <time.h>
8100 #include <errno.h>
8101
8102 /* When used as part of the CLI, the sqlite3_stdio.h module will have
@@ -8117,10 +8058,44 @@
8117 #define FSDIR_COLUMN_MTIME 2 /* Last modification time */
8118 #define FSDIR_COLUMN_DATA 3 /* File content */
8119 #define FSDIR_COLUMN_PATH 4 /* Path to top of search */
8120 #define FSDIR_COLUMN_DIR 5 /* Path is relative to this directory */
8121
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8122
8123 /*
8124 ** Set the result stored by context ctx to a blob containing the
8125 ** contents of file zName. Or, leave the result unchanged (NULL)
8126 ** if the file does not exist or is unreadable.
@@ -8278,11 +8253,17 @@
8278 static int fileStat(
8279 const char *zPath,
8280 struct stat *pStatBuf
8281 ){
8282 #if defined(_WIN32)
8283 int rc = stat(zPath, pStatBuf);
 
 
 
 
 
 
8284 if( rc==0 ) statTimesToUtc(zPath, pStatBuf);
8285 return rc;
8286 #else
8287 return stat(zPath, pStatBuf);
8288 #endif
@@ -8296,13 +8277,11 @@
8296 static int fileLinkStat(
8297 const char *zPath,
8298 struct stat *pStatBuf
8299 ){
8300 #if defined(_WIN32)
8301 int rc = lstat(zPath, pStatBuf);
8302 if( rc==0 ) statTimesToUtc(zPath, pStatBuf);
8303 return rc;
8304 #else
8305 return lstat(zPath, pStatBuf);
8306 #endif
8307 }
8308
@@ -16808,11 +16787,11 @@
16808 case SQLITE_FCNTL_POWERSAFE_OVERWRITE: zOp = "POWERSAFE_OVERWRITE"; break;
16809 case SQLITE_FCNTL_PRAGMA: {
16810 const char *const* a = (const char*const*)pArg;
16811 if( a[1] && strcmp(a[1],"vfstrace")==0 && a[2] ){
16812 const u8 *zArg = (const u8*)a[2];
16813 if( zArg[0]>='0' && zArg[0]<=9 ){
16814 pInfo->mTrace = (sqlite3_uint64)strtoll(a[2], 0, 0);
16815 }else{
16816 static const struct {
16817 const char *z;
16818 unsigned int m;
@@ -18709,10 +18688,13 @@
18709 rc = sqlite3_create_module(db, "sqlite_dbptr", &dbdata_module, (void*)1);
18710 }
18711 return rc;
18712 }
18713
 
 
 
18714 int sqlite3_dbdata_init(
18715 sqlite3 *db,
18716 char **pzErrMsg,
18717 const sqlite3_api_routines *pApi
18718 ){
@@ -25592,107 +25574,108 @@
25592 " --plain Show results as text/plain, not as HTML",
25593 #endif
25594 };
25595
25596 /*
25597 ** Output help text.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25598 **
25599 ** zPattern describes the set of commands for which help text is provided.
25600 ** If zPattern is NULL, then show all commands, but only give a one-line
25601 ** description of each.
25602 **
25603 ** Return the number of matches.
25604 */
25605 static int showHelp(FILE *out, const char *zPattern){
25606 int i = 0;
25607 int j = 0;
25608 int n = 0;
25609 char *zPat;
25610 if( zPattern==0
25611 || zPattern[0]=='0'
25612 || cli_strcmp(zPattern,"-a")==0
25613 || cli_strcmp(zPattern,"-all")==0
25614 || cli_strcmp(zPattern,"--all")==0
25615 ){
25616 enum HelpWanted { HW_NoCull = 0, HW_SummaryOnly = 1, HW_Undoc = 2 };
25617 enum HelpHave { HH_Undoc = 2, HH_Summary = 1, HH_More = 0 };
25618 /* Show all or most commands
25619 ** *zPattern==0 => summary of documented commands only
25620 ** *zPattern=='0' => whole help for undocumented commands
25621 ** Otherwise => whole help for documented commands
25622 */
25623 enum HelpWanted hw = HW_SummaryOnly;
25624 enum HelpHave hh = HH_More;
25625 if( zPattern!=0 ){
25626 hw = (*zPattern=='0')? HW_NoCull|HW_Undoc : HW_NoCull;
25627 }
25628 for(i=0; i<ArraySize(azHelp); i++){
25629 switch( azHelp[i][0] ){
25630 case ',':
25631 hh = HH_Summary|HH_Undoc;
25632 break;
25633 case '.':
25634 hh = HH_Summary;
25635 break;
25636 default:
25637 hh &= ~HH_Summary;
25638 break;
25639 }
25640 if( ((hw^hh)&HH_Undoc)==0 ){
25641 if( (hh&HH_Summary)!=0 ){
25642 sqlite3_fprintf(out, ".%s\n", azHelp[i]+1);
25643 ++n;
25644 }else if( (hw&HW_SummaryOnly)==0 ){
25645 sqlite3_fprintf(out, "%s\n", azHelp[i]);
25646 }
25647 }
25648 }
25649 }else{
25650 /* Seek documented commands for which zPattern is an exact prefix */
25651 zPat = sqlite3_mprintf(".%s*", zPattern);
25652 shell_check_oom(zPat);
25653 for(i=0; i<ArraySize(azHelp); i++){
25654 if( sqlite3_strglob(zPat, azHelp[i])==0 ){
25655 sqlite3_fprintf(out, "%s\n", azHelp[i]);
25656 j = i+1;
25657 n++;
25658 }
25659 }
25660 sqlite3_free(zPat);
25661 if( n ){
25662 if( n==1 ){
25663 /* when zPattern is a prefix of exactly one command, then include
25664 ** the details of that command, which should begin at offset j */
25665 while( j<ArraySize(azHelp)-1 && azHelp[j][0]==' ' ){
25666 sqlite3_fprintf(out, "%s\n", azHelp[j]);
25667 j++;
25668 }
25669 }
25670 return n;
25671 }
25672 /* Look for documented commands that contain zPattern anywhere.
25673 ** Show complete text of all documented commands that match. */
25674 zPat = sqlite3_mprintf("%%%s%%", zPattern);
25675 shell_check_oom(zPat);
25676 for(i=0; i<ArraySize(azHelp); i++){
25677 if( azHelp[i][0]==',' ){
25678 while( i<ArraySize(azHelp)-1 && azHelp[i+1][0]==' ' ) ++i;
25679 continue;
25680 }
25681 if( azHelp[i][0]=='.' ) j = i;
25682 if( sqlite3_strlike(zPat, azHelp[i], 0)==0 ){
25683 sqlite3_fprintf(out, "%s\n", azHelp[j]);
25684 while( j<ArraySize(azHelp)-1 && azHelp[j+1][0]==' ' ){
25685 j++;
25686 sqlite3_fprintf(out, "%s\n", azHelp[j]);
25687 }
25688 i = j;
25689 n++;
25690 }
25691 }
25692 sqlite3_free(zPat);
25693 }
25694 return n;
25695 }
25696
25697 /* Forward reference */
25698 static int process_input(ShellState *p);
@@ -25937,10 +25920,43 @@
25937 int sleep = sqlite3_value_int(argv[0]);
25938 (void)argcUnused;
25939 sqlite3_sleep(sleep/1000);
25940 sqlite3_result_int(context, sleep);
25941 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25942
25943 /* Flags for open_db().
25944 **
25945 ** The default behavior of open_db() is to exit(1) if the database fails to
25946 ** open. The OPEN_DB_KEEPALIVE flag changes that so that it prints an error
@@ -26081,11 +26097,11 @@
26081 shellDtostr, 0, 0);
26082 sqlite3_create_function(p->db, "dtostr", 2, SQLITE_UTF8, 0,
26083 shellDtostr, 0, 0);
26084 sqlite3_create_function(p->db, "shell_add_schema", 3, SQLITE_UTF8, 0,
26085 shellAddSchemaName, 0, 0);
26086 sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8, 0,
26087 shellModuleSchema, 0, 0);
26088 sqlite3_create_function(p->db, "shell_putsnl", 1, SQLITE_UTF8, p,
26089 shellPutsFunc, 0, 0);
26090 sqlite3_create_function(p->db, "usleep",1,SQLITE_UTF8,0,
26091 shellUSleepFunc, 0, 0);
26092
--- extsrc/shell.c
+++ extsrc/shell.c
@@ -1622,34 +1622,10 @@
1622 if( n>350 ) n = 350;
1623 sqlite3_snprintf(sizeof(z), z, "%#+.*e", n, r);
1624 sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT);
1625 }
1626
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1627 /*
1628 ** SQL function: shell_add_schema(S,X)
1629 **
1630 ** Add the schema name X to the CREATE statement in S and return the result.
1631 ** Examples:
@@ -1820,10 +1796,11 @@
1796 # ifdef FILENAME_MAX
1797 # define NAME_MAX (FILENAME_MAX)
1798 # else
1799 # define NAME_MAX (260)
1800 # endif
1801 # define DIRENT_NAME_MAX (NAME_MAX)
1802 #endif
1803
1804 /*
1805 ** We need to define "NULL_INTPTR_T" and "BAD_INTPTR_T".
1806 */
@@ -1863,12 +1840,11 @@
1840 #endif
1841
1842 /*
1843 ** Provide a macro, for use by the implementation, to determine if a
1844 ** particular directory entry should be skipped over when searching for
1845 ** the next directory entry that should be returned by the readdir().
 
1846 */
1847
1848 #ifndef is_filtered
1849 # define is_filtered(a) ((((a).attrib)&_A_HIDDEN) || (((a).attrib)&_A_SYSTEM))
1850 #endif
@@ -1880,16 +1856,15 @@
1856
1857 extern const char *windirent_getenv(const char *name);
1858
1859 /*
1860 ** Finally, we can provide the function prototypes for the opendir(),
1861 ** readdir(), and closedir() POSIX functions.
1862 */
1863
1864 extern LPDIR opendir(const char *dirname);
1865 extern LPDIRENT readdir(LPDIR dirp);
 
1866 extern INT closedir(LPDIR dirp);
1867
1868 #endif /* defined(WIN32) && defined(_MSC_VER) */
1869
1870 /************************* End test_windirent.h ********************/
@@ -1942,27 +1917,45 @@
1917
1918 /*
1919 ** Implementation of the POSIX opendir() function using the MSVCRT.
1920 */
1921 LPDIR opendir(
1922 const char *dirname /* Directory name, UTF8 encoding */
1923 ){
1924 struct _wfinddata_t data;
1925 LPDIR dirp = (LPDIR)sqlite3_malloc(sizeof(DIR));
1926 SIZE_T namesize = sizeof(data.name) / sizeof(data.name[0]);
1927 wchar_t *b1;
1928 sqlite3_int64 sz;
1929
1930 if( dirp==NULL ) return NULL;
1931 memset(dirp, 0, sizeof(DIR));
1932
1933 /* TODO: Remove this if Unix-style root paths are not used. */
1934 if( sqlite3_stricmp(dirname, "/")==0 ){
1935 dirname = windirent_getenv("SystemDrive");
1936 }
1937
1938 memset(&data, 0, sizeof(data));
1939 sz = strlen(dirname);
1940 b1 = sqlite3_malloc64( (sz+3)*sizeof(b1[0]) );
1941 if( b1==0 ){
1942 closedir(dirp);
1943 return NULL;
1944 }
1945 sz = MultiByteToWideChar(CP_UTF8, 0, dirname, sz, b1, sz);
1946 b1[sz++] = '\\';
1947 b1[sz++] = '*';
1948 b1[sz] = 0;
1949 if( sz+1>(sqlite3_int64)namesize ){
1950 closedir(dirp);
1951 sqlite3_free(b1);
1952 return NULL;
1953 }
1954 memcpy(data.name, b1, (sz+1)*sizeof(b1[0]));
1955 sqlite3_free(b1);
1956 dirp->d_handle = _wfindfirst(data.name, &data);
1957
1958 if( dirp->d_handle==BAD_INTPTR_T ){
1959 closedir(dirp);
1960 return NULL;
1961 }
@@ -1969,34 +1962,33 @@
1962
1963 /* TODO: Remove this block to allow hidden and/or system files. */
1964 if( is_filtered(data) ){
1965 next:
1966
1967 memset(&data, 0, sizeof(data));
1968 if( _wfindnext(dirp->d_handle, &data)==-1 ){
1969 closedir(dirp);
1970 return NULL;
1971 }
1972
1973 /* TODO: Remove this block to allow hidden and/or system files. */
1974 if( is_filtered(data) ) goto next;
1975 }
1976
1977 dirp->d_first.d_attributes = data.attrib;
1978 WideCharToMultiByte(CP_UTF8, 0, data.name, -1,
1979 dirp->d_first.d_name, DIRENT_NAME_MAX, 0, 0);
 
1980 return dirp;
1981 }
1982
1983 /*
1984 ** Implementation of the POSIX readdir() function using the MSVCRT.
1985 */
1986 LPDIRENT readdir(
1987 LPDIR dirp
1988 ){
1989 struct _wfinddata_t data;
1990
1991 if( dirp==NULL ) return NULL;
1992
1993 if( dirp->d_first.d_ino==0 ){
1994 dirp->d_first.d_ino++;
@@ -2005,69 +1997,23 @@
1997 return &dirp->d_first;
1998 }
1999
2000 next:
2001
2002 memset(&data, 0, sizeof(data));
2003 if( _wfindnext(dirp->d_handle, &data)==-1 ) return NULL;
2004
2005 /* TODO: Remove this block to allow hidden and/or system files. */
2006 if( is_filtered(data) ) goto next;
2007
2008 dirp->d_next.d_ino++;
2009 dirp->d_next.d_attributes = data.attrib;
2010 WideCharToMultiByte(CP_UTF8, 0, data.name, -1,
2011 dirp->d_next.d_name, DIRENT_NAME_MAX, 0, 0);
 
2012 return &dirp->d_next;
2013 }
2014
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2015 /*
2016 ** Implementation of the POSIX closedir() function using the MSVCRT.
2017 */
2018 INT closedir(
2019 LPDIR dirp
@@ -8085,18 +8031,13 @@
8031 # include "windows.h"
8032 # include <io.h>
8033 # include <direct.h>
8034 /* # include "test_windirent.h" */
8035 # define dirent DIRENT
8036 # define stat _stat
8037 # define chmod(path,mode) fileio_chmod(path,mode)
8038 # define mkdir(path,mode) fileio_mkdir(path)
 
 
 
 
 
8039 #endif
8040 #include <time.h>
8041 #include <errno.h>
8042
8043 /* When used as part of the CLI, the sqlite3_stdio.h module will have
@@ -8117,10 +8058,44 @@
8058 #define FSDIR_COLUMN_MTIME 2 /* Last modification time */
8059 #define FSDIR_COLUMN_DATA 3 /* File content */
8060 #define FSDIR_COLUMN_PATH 4 /* Path to top of search */
8061 #define FSDIR_COLUMN_DIR 5 /* Path is relative to this directory */
8062
8063 /*
8064 ** UTF8 chmod() function for Windows
8065 */
8066 #if defined(_WIN32) || defined(WIN32)
8067 static int fileio_chmod(const char *zPath, int pmode){
8068 sqlite3_int64 sz = strlen(zPath);
8069 wchar_t *b1 = sqlite3_malloc64( (sz+1)*sizeof(b1[0]) );
8070 int rc;
8071 if( b1==0 ) return -1;
8072 sz = MultiByteToWideChar(CP_UTF8, 0, zPath, sz, b1, sz);
8073 b1[sz] = 0;
8074 rc = _wchmod(b1, pmode);
8075 sqlite3_free(b1);
8076 return rc;
8077 }
8078 #endif
8079
8080 /*
8081 ** UTF8 mkdir() function for Windows
8082 */
8083 #if defined(_WIN32) || defined(WIN32)
8084 static int fileio_mkdir(const char *zPath){
8085 sqlite3_int64 sz = strlen(zPath);
8086 wchar_t *b1 = sqlite3_malloc64( (sz+1)*sizeof(b1[0]) );
8087 int rc;
8088 if( b1==0 ) return -1;
8089 sz = MultiByteToWideChar(CP_UTF8, 0, zPath, sz, b1, sz);
8090 b1[sz] = 0;
8091 rc = _wmkdir(b1);
8092 sqlite3_free(b1);
8093 return rc;
8094 }
8095 #endif
8096
8097
8098 /*
8099 ** Set the result stored by context ctx to a blob containing the
8100 ** contents of file zName. Or, leave the result unchanged (NULL)
8101 ** if the file does not exist or is unreadable.
@@ -8278,11 +8253,17 @@
8253 static int fileStat(
8254 const char *zPath,
8255 struct stat *pStatBuf
8256 ){
8257 #if defined(_WIN32)
8258 sqlite3_int64 sz = strlen(zPath);
8259 wchar_t *b1 = sqlite3_malloc64( (sz+1)*sizeof(b1[0]) );
8260 int rc;
8261 if( b1==0 ) return 1;
8262 sz = MultiByteToWideChar(CP_UTF8, 0, zPath, sz, b1, sz);
8263 b1[sz] = 0;
8264 rc = _wstat(b1, pStatBuf);
8265 if( rc==0 ) statTimesToUtc(zPath, pStatBuf);
8266 return rc;
8267 #else
8268 return stat(zPath, pStatBuf);
8269 #endif
@@ -8296,13 +8277,11 @@
8277 static int fileLinkStat(
8278 const char *zPath,
8279 struct stat *pStatBuf
8280 ){
8281 #if defined(_WIN32)
8282 return fileStat(zPath, pStatBuf);
 
 
8283 #else
8284 return lstat(zPath, pStatBuf);
8285 #endif
8286 }
8287
@@ -16808,11 +16787,11 @@
16787 case SQLITE_FCNTL_POWERSAFE_OVERWRITE: zOp = "POWERSAFE_OVERWRITE"; break;
16788 case SQLITE_FCNTL_PRAGMA: {
16789 const char *const* a = (const char*const*)pArg;
16790 if( a[1] && strcmp(a[1],"vfstrace")==0 && a[2] ){
16791 const u8 *zArg = (const u8*)a[2];
16792 if( zArg[0]>='0' && zArg[0]<='9' ){
16793 pInfo->mTrace = (sqlite3_uint64)strtoll(a[2], 0, 0);
16794 }else{
16795 static const struct {
16796 const char *z;
16797 unsigned int m;
@@ -18709,10 +18688,13 @@
18688 rc = sqlite3_create_module(db, "sqlite_dbptr", &dbdata_module, (void*)1);
18689 }
18690 return rc;
18691 }
18692
18693 #ifdef _WIN32
18694
18695 #endif
18696 int sqlite3_dbdata_init(
18697 sqlite3 *db,
18698 char **pzErrMsg,
18699 const sqlite3_api_routines *pApi
18700 ){
@@ -25592,107 +25574,108 @@
25574 " --plain Show results as text/plain, not as HTML",
25575 #endif
25576 };
25577
25578 /*
25579 ** Output help text for commands that match zPattern.
25580 **
25581 ** * If zPattern is NULL, then show all documented commands, but
25582 ** only give a one-line summary of each.
25583 **
25584 ** * If zPattern is "-a" or "-all" or "--all" then show all help text
25585 ** for all commands except undocumented commands.
25586 **
25587 ** * If zPattern is "0" then show all help for undocumented commands.
25588 ** Undocumented commands begin with "," instead of "." in the azHelp[]
25589 ** array.
25590 **
25591 ** * If zPattern is a prefix for one or more documented commands, then
25592 ** show help for those commands. If only a single command matches the
25593 ** prefix, show the full text of the help. If multiple commands match,
25594 ** Only show just the first line of each.
25595 **
25596 ** * Otherwise, show the complete text of any documented command for which
25597 ** zPattern is a LIKE match for any text within that command help
25598 ** text.
25599 **
25600 ** Return the number commands that match zPattern.
25601 */
25602 static int showHelp(FILE *out, const char *zPattern){
25603 int i = 0;
25604 int j = 0;
25605 int n = 0;
25606 char *zPat;
25607 if( zPattern==0 ){
25608 /* Show just the first line for all help topics */
25609 zPattern = "[a-z]";
25610 }else if( cli_strcmp(zPattern,"-a")==0
25611 || cli_strcmp(zPattern,"-all")==0
25612 || cli_strcmp(zPattern,"--all")==0
25613 ){
25614 /* Show everything except undocumented commands */
25615 zPattern = ".";
25616 }else if( cli_strcmp(zPattern,"0")==0 ){
25617 /* Show complete help text of undocumented commands */
25618 int show = 0;
25619 for(i=0; i<ArraySize(azHelp); i++){
25620 if( azHelp[i][0]=='.' ){
25621 show = 0;
25622 }else if( azHelp[i][0]==',' ){
25623 show = 1;
25624 sqlite3_fprintf(out, ".%s\n", &azHelp[i][1]);
25625 n++;
25626 }else if( show ){
25627 sqlite3_fprintf(out, "%s\n", azHelp[i]);
25628 }
25629 }
25630 return n;
25631 }
25632
25633 /* Seek documented commands for which zPattern is an exact prefix */
25634 zPat = sqlite3_mprintf(".%s*", zPattern);
25635 shell_check_oom(zPat);
25636 for(i=0; i<ArraySize(azHelp); i++){
25637 if( sqlite3_strglob(zPat, azHelp[i])==0 ){
25638 sqlite3_fprintf(out, "%s\n", azHelp[i]);
25639 j = i+1;
25640 n++;
25641 }
25642 }
25643 sqlite3_free(zPat);
25644 if( n ){
25645 if( n==1 ){
25646 /* when zPattern is a prefix of exactly one command, then include
25647 ** the details of that command, which should begin at offset j */
25648 while( j<ArraySize(azHelp)-1 && azHelp[j][0]==' ' ){
25649 sqlite3_fprintf(out, "%s\n", azHelp[j]);
25650 j++;
25651 }
25652 }
25653 return n;
25654 }
25655
25656 /* Look for documented commands that contain zPattern anywhere.
25657 ** Show complete text of all documented commands that match. */
25658 zPat = sqlite3_mprintf("%%%s%%", zPattern);
25659 shell_check_oom(zPat);
25660 for(i=0; i<ArraySize(azHelp); i++){
25661 if( azHelp[i][0]==',' ){
25662 while( i<ArraySize(azHelp)-1 && azHelp[i+1][0]==' ' ) ++i;
25663 continue;
25664 }
25665 if( azHelp[i][0]=='.' ) j = i;
25666 if( sqlite3_strlike(zPat, azHelp[i], 0)==0 ){
25667 sqlite3_fprintf(out, "%s\n", azHelp[j]);
25668 while( j<ArraySize(azHelp)-1 && azHelp[j+1][0]==' ' ){
25669 j++;
25670 sqlite3_fprintf(out, "%s\n", azHelp[j]);
25671 }
25672 i = j;
25673 n++;
25674 }
25675 }
25676 sqlite3_free(zPat);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25677 return n;
25678 }
25679
25680 /* Forward reference */
25681 static int process_input(ShellState *p);
@@ -25937,10 +25920,43 @@
25920 int sleep = sqlite3_value_int(argv[0]);
25921 (void)argcUnused;
25922 sqlite3_sleep(sleep/1000);
25923 sqlite3_result_int(context, sleep);
25924 }
25925
25926 /*
25927 ** SQL function: shell_module_schema(X)
25928 **
25929 ** Return a fake schema for the table-valued function or eponymous virtual
25930 ** table X.
25931 */
25932 static void shellModuleSchema(
25933 sqlite3_context *pCtx,
25934 int nVal,
25935 sqlite3_value **apVal
25936 ){
25937 const char *zName;
25938 char *zFake;
25939 ShellState *p = (ShellState*)sqlite3_user_data(pCtx);
25940 FILE *pSavedLog = p->pLog;
25941 UNUSED_PARAMETER(nVal);
25942 zName = (const char*)sqlite3_value_text(apVal[0]);
25943
25944 /* Temporarily disable the ".log" when calling shellFakeSchema() because
25945 ** shellFakeSchema() might generate failures for some ephemeral virtual
25946 ** tables due to missing arguments. Example: fts4aux.
25947 ** https://sqlite.org/forum/forumpost/42fe6520b803be51 */
25948 p->pLog = 0;
25949 zFake = zName? shellFakeSchema(sqlite3_context_db_handle(pCtx), 0, zName) : 0;
25950 p->pLog = pSavedLog;
25951
25952 if( zFake ){
25953 sqlite3_result_text(pCtx, sqlite3_mprintf("/* %s */", zFake),
25954 -1, sqlite3_free);
25955 free(zFake);
25956 }
25957 }
25958
25959 /* Flags for open_db().
25960 **
25961 ** The default behavior of open_db() is to exit(1) if the database fails to
25962 ** open. The OPEN_DB_KEEPALIVE flag changes that so that it prints an error
@@ -26081,11 +26097,11 @@
26097 shellDtostr, 0, 0);
26098 sqlite3_create_function(p->db, "dtostr", 2, SQLITE_UTF8, 0,
26099 shellDtostr, 0, 0);
26100 sqlite3_create_function(p->db, "shell_add_schema", 3, SQLITE_UTF8, 0,
26101 shellAddSchemaName, 0, 0);
26102 sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8, p,
26103 shellModuleSchema, 0, 0);
26104 sqlite3_create_function(p->db, "shell_putsnl", 1, SQLITE_UTF8, p,
26105 shellPutsFunc, 0, 0);
26106 sqlite3_create_function(p->db, "usleep",1,SQLITE_UTF8,0,
26107 shellUSleepFunc, 0, 0);
26108
+204 -142
--- extsrc/sqlite3.c
+++ extsrc/sqlite3.c
@@ -16,11 +16,11 @@
1616
** if you want a wrapper to interface SQLite with your choice of programming
1717
** language. The code for the "sqlite3" command-line shell is also in a
1818
** separate file. This file contains only code for the core SQLite library.
1919
**
2020
** The content in this amalgamation comes from Fossil check-in
21
-** d22475b81c4e26ccc50f3b5626d43b32f7a2 with changes in files:
21
+** 336ceeccc6f85bd78f4a26648af7edf9056d with changes in files:
2222
**
2323
**
2424
*/
2525
#ifndef SQLITE_AMALGAMATION
2626
#define SQLITE_CORE 1
@@ -465,11 +465,11 @@
465465
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
466466
** [sqlite_version()] and [sqlite_source_id()].
467467
*/
468468
#define SQLITE_VERSION "3.50.0"
469469
#define SQLITE_VERSION_NUMBER 3050000
470
-#define SQLITE_SOURCE_ID "2025-04-15 21:59:38 d22475b81c4e26ccc50f3b5626d43b32f7a2de34e5a764539554665bdda735d5"
470
+#define SQLITE_SOURCE_ID "2025-05-15 11:20:54 336ceeccc6f85bd78f4a26648af7edf9056d569a767b4120f125a02b2090a349"
471471
472472
/*
473473
** CAPI3REF: Run-Time Library Version Numbers
474474
** KEYWORDS: sqlite3_version sqlite3_sourceid
475475
**
@@ -11872,13 +11872,14 @@
1187211872
** This may appear to have some counter-intuitive effects if a single row
1187311873
** is written to more than once during a session. For example, if a row
1187411874
** is inserted while a session object is enabled, then later deleted while
1187511875
** the same session object is disabled, no INSERT record will appear in the
1187611876
** changeset, even though the delete took place while the session was disabled.
11877
-** Or, if one field of a row is updated while a session is disabled, and
11878
-** another field of the same row is updated while the session is enabled, the
11879
-** resulting changeset will contain an UPDATE change that updates both fields.
11877
+** Or, if one field of a row is updated while a session is enabled, and
11878
+** then another field of the same row is updated while the session is disabled,
11879
+** the resulting changeset will contain an UPDATE change that updates both
11880
+** fields.
1188011881
*/
1188111882
SQLITE_API int sqlite3session_changeset(
1188211883
sqlite3_session *pSession, /* Session object */
1188311884
int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */
1188411885
void **ppChangeset /* OUT: Buffer containing changeset */
@@ -12083,11 +12084,11 @@
1208312084
** CAPI3REF: Flags for sqlite3changeset_start_v2
1208412085
**
1208512086
** The following flags may passed via the 4th parameter to
1208612087
** [sqlite3changeset_start_v2] and [sqlite3changeset_start_v2_strm]:
1208712088
**
12088
-** <dt>SQLITE_CHANGESETAPPLY_INVERT <dd>
12089
+** <dt>SQLITE_CHANGESETSTART_INVERT <dd>
1208912090
** Invert the changeset while iterating through it. This is equivalent to
1209012091
** inverting a changeset using sqlite3changeset_invert() before applying it.
1209112092
** It is an error to specify this flag with a patchset.
1209212093
*/
1209312094
#define SQLITE_CHANGESETSTART_INVERT 0x0002
@@ -19160,11 +19161,10 @@
1916019161
unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */
1916119162
unsigned isResized:1; /* True if resizeIndexObject() has been called */
1916219163
unsigned isCovering:1; /* True if this is a covering index */
1916319164
unsigned noSkipScan:1; /* Do not try to use skip-scan if true */
1916419165
unsigned hasStat1:1; /* aiRowLogEst values come from sqlite_stat1 */
19165
- unsigned bLowQual:1; /* sqlite_stat1 says this is a low-quality index */
1916619166
unsigned bNoQuery:1; /* Do not use this index to optimize queries */
1916719167
unsigned bAscKeyBug:1; /* True if the bba7b69f9849b5bf bug applies */
1916819168
unsigned bIdxRowid:1; /* One or more of the index keys is the ROWID */
1916919169
unsigned bHasVCol:1; /* Index references one or more VIRTUAL columns */
1917019170
unsigned bHasExpr:1; /* Index contains an expression, either a literal
@@ -22424,10 +22424,13 @@
2242422424
#ifdef SQLITE_BITMASK_TYPE
2242522425
"BITMASK_TYPE=" CTIMEOPT_VAL(SQLITE_BITMASK_TYPE),
2242622426
#endif
2242722427
#ifdef SQLITE_BUG_COMPATIBLE_20160819
2242822428
"BUG_COMPATIBLE_20160819",
22429
+#endif
22430
+#ifdef SQLITE_BUG_COMPATIBLE_20250510
22431
+ "BUG_COMPATIBLE_20250510",
2242922432
#endif
2243022433
#ifdef SQLITE_CASE_SENSITIVE_LIKE
2243122434
"CASE_SENSITIVE_LIKE",
2243222435
#endif
2243322436
#ifdef SQLITE_CHECK_PAGES
@@ -32987,10 +32990,19 @@
3298732990
va_end(ap);
3298832991
zBuf[acc.nChar] = 0;
3298932992
return zBuf;
3299032993
}
3299132994
32995
+/* Maximum size of an sqlite3_log() message. */
32996
+#if defined(SQLITE_MAX_LOG_MESSAGE)
32997
+ /* Leave the definition as supplied */
32998
+#elif SQLITE_PRINT_BUF_SIZE*10>10000
32999
+# define SQLITE_MAX_LOG_MESSAGE 10000
33000
+#else
33001
+# define SQLITE_MAX_LOG_MESSAGE (SQLITE_PRINT_BUF_SIZE*10)
33002
+#endif
33003
+
3299233004
/*
3299333005
** This is the routine that actually formats the sqlite3_log() message.
3299433006
** We house it in a separate routine from sqlite3_log() to avoid using
3299533007
** stack space on small-stack systems when logging is disabled.
3299633008
**
@@ -33003,11 +33015,11 @@
3300333015
** Care must be taken that any sqlite3_log() calls that occur while the
3300433016
** memory mutex is held do not use these mechanisms.
3300533017
*/
3300633018
static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){
3300733019
StrAccum acc; /* String accumulator */
33008
- char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */
33020
+ char zMsg[SQLITE_MAX_LOG_MESSAGE]; /* Complete log message */
3300933021
3301033022
sqlite3StrAccumInit(&acc, 0, zMsg, sizeof(zMsg), 0);
3301133023
sqlite3_str_vappendf(&acc, zFormat, ap);
3301233024
sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode,
3301333025
sqlite3StrAccumFinish(&acc));
@@ -87262,10 +87274,13 @@
8726287274
** into register iDest, then add the OPFLAG_TYPEOFARG flag to that
8726387275
** opcode.
8726487276
*/
8726587277
SQLITE_PRIVATE void sqlite3VdbeTypeofColumn(Vdbe *p, int iDest){
8726687278
VdbeOp *pOp = sqlite3VdbeGetLastOp(p);
87279
+#ifdef SQLITE_DEBUG
87280
+ while( pOp->opcode==OP_ReleaseReg ) pOp--;
87281
+#endif
8726787282
if( pOp->p3==iDest && pOp->opcode==OP_Column ){
8726887283
pOp->p5 |= OPFLAG_TYPEOFARG;
8726987284
}
8727087285
}
8727187286
@@ -95716,11 +95731,11 @@
9571695731
}
9571795732
}else{
9571895733
sqlite3VdbeError(p, "%s", pOp->p4.z);
9571995734
}
9572095735
pcx = (int)(pOp - aOp);
95721
- sqlite3_log(pOp->p1, "abort at %d in [%s]: %s", pcx, p->zSql, p->zErrMsg);
95736
+ sqlite3_log(pOp->p1, "abort at %d: %s; [%s]", pcx, p->zErrMsg, p->zSql);
9572295737
}
9572395738
rc = sqlite3VdbeHalt(p);
9572495739
assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR );
9572595740
if( rc==SQLITE_BUSY ){
9572695741
p->rc = SQLITE_BUSY;
@@ -97042,11 +97057,11 @@
9704297057
pOut->u.i = ~sqlite3VdbeIntValue(pIn1);
9704397058
}
9704497059
break;
9704597060
}
9704697061
97047
-/* Opcode: Once P1 P2 * * *
97062
+/* Opcode: Once P1 P2 P3 * *
9704897063
**
9704997064
** Fall through to the next instruction the first time this opcode is
9705097065
** encountered on each invocation of the byte-code program. Jump to P2
9705197066
** on the second and all subsequent encounters during the same invocation.
9705297067
**
@@ -97058,10 +97073,16 @@
9705897073
**
9705997074
** For subprograms, there is a bitmask in the VdbeFrame that determines
9706097075
** whether or not the jump should be taken. The bitmask is necessary
9706197076
** because the self-altering code trick does not work for recursive
9706297077
** triggers.
97078
+**
97079
+** The P3 operand is not used directly by this opcode. However P3 is
97080
+** used by the code generator as follows: If this opcode is the start
97081
+** of a subroutine and that subroutine uses a Bloom filter, then P3 will
97082
+** be the register that holds that Bloom filter. See tag-202407032019
97083
+** in the source code for implementation details.
9706397084
*/
9706497085
case OP_Once: { /* jump */
9706597086
u32 iAddr; /* Address of this instruction */
9706697087
assert( p->aOp[0].opcode==OP_Init );
9706797088
if( p->pFrame ){
@@ -98103,10 +98124,11 @@
9810398124
}
9810498125
}else{
9810598126
zHdr += sqlite3PutVarint(zHdr, serial_type);
9810698127
if( pRec->n ){
9810798128
assert( pRec->z!=0 );
98129
+ assert( pRec->z!=(const char*)sqlite3CtypeMap );
9810898130
memcpy(zPayload, pRec->z, pRec->n);
9810998131
zPayload += pRec->n;
9811098132
}
9811198133
}
9811298134
if( pRec==pLast ) break;
@@ -103551,12 +103573,12 @@
103551103573
sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc));
103552103574
}
103553103575
p->rc = rc;
103554103576
sqlite3SystemError(db, rc);
103555103577
testcase( sqlite3GlobalConfig.xLog!=0 );
103556
- sqlite3_log(rc, "statement aborts at %d: [%s] %s",
103557
- (int)(pOp - aOp), p->zSql, p->zErrMsg);
103578
+ sqlite3_log(rc, "statement aborts at %d: %s; [%s]",
103579
+ (int)(pOp - aOp), p->zErrMsg, p->zSql);
103558103580
if( p->eVdbeState==VDBE_RUN_STATE ) sqlite3VdbeHalt(p);
103559103581
if( rc==SQLITE_IOERR_NOMEM ) sqlite3OomFault(db);
103560103582
if( rc==SQLITE_CORRUPT && db->autoCommit==0 ){
103561103583
db->flags |= SQLITE_CorruptRdOnly;
103562103584
}
@@ -109287,17 +109309,16 @@
109287109309
/* Clearly non-deterministic functions like random(), but also
109288109310
** date/time functions that use 'now', and other functions like
109289109311
** sqlite_version() that might change over time cannot be used
109290109312
** in an index or generated column. Curiously, they can be used
109291109313
** in a CHECK constraint. SQLServer, MySQL, and PostgreSQL all
109292
- ** all this. */
109314
+ ** allow this. */
109293109315
sqlite3ResolveNotValid(pParse, pNC, "non-deterministic functions",
109294109316
NC_IdxExpr|NC_PartIdx|NC_GenCol, 0, pExpr);
109295109317
}else{
109296109318
assert( (NC_SelfRef & 0xff)==NC_SelfRef ); /* Must fit in 8 bits */
109297109319
pExpr->op2 = pNC->ncFlags & NC_SelfRef;
109298
- if( pNC->ncFlags & NC_FromDDL ) ExprSetProperty(pExpr, EP_FromDDL);
109299109320
}
109300109321
if( (pDef->funcFlags & SQLITE_FUNC_INTERNAL)!=0
109301109322
&& pParse->nested==0
109302109323
&& (pParse->db->mDbFlags & DBFLAG_InternalFunc)==0
109303109324
){
@@ -109309,10 +109330,11 @@
109309109330
pDef = 0;
109310109331
}else
109311109332
if( (pDef->funcFlags & (SQLITE_FUNC_DIRECT|SQLITE_FUNC_UNSAFE))!=0
109312109333
&& !IN_RENAME_OBJECT
109313109334
){
109335
+ if( pNC->ncFlags & NC_FromDDL ) ExprSetProperty(pExpr, EP_FromDDL);
109314109336
sqlite3ExprFunctionUsable(pParse, pExpr, pDef);
109315109337
}
109316109338
}
109317109339
109318109340
if( 0==IN_RENAME_OBJECT ){
@@ -114022,15 +114044,16 @@
114022114044
pCopy = sqlite3SelectDup(pParse->db, pSelect, 0);
114023114045
rc = pParse->db->mallocFailed ? 1 :sqlite3Select(pParse, pCopy, &dest);
114024114046
sqlite3SelectDelete(pParse->db, pCopy);
114025114047
sqlite3DbFree(pParse->db, dest.zAffSdst);
114026114048
if( addrBloom ){
114049
+ /* Remember that location of the Bloom filter in the P3 operand
114050
+ ** of the OP_Once that began this subroutine. tag-202407032019 */
114027114051
sqlite3VdbeGetOp(v, addrOnce)->p3 = dest.iSDParm2;
114028114052
if( dest.iSDParm2==0 ){
114029
- sqlite3VdbeChangeToNoop(v, addrBloom);
114030
- }else{
114031
- sqlite3VdbeGetOp(v, addrOnce)->p3 = dest.iSDParm2;
114053
+ /* If the Bloom filter won't actually be used, keep it small */
114054
+ sqlite3VdbeGetOp(v, addrBloom)->p1 = 10;
114032114055
}
114033114056
}
114034114057
if( rc ){
114035114058
sqlite3KeyInfoUnref(pKeyInfo);
114036114059
return;
@@ -114473,11 +114496,11 @@
114473114496
if( destIfFalse==destIfNull ){
114474114497
/* Combine Step 3 and Step 5 into a single opcode */
114475114498
if( ExprHasProperty(pExpr, EP_Subrtn) ){
114476114499
const VdbeOp *pOp = sqlite3VdbeGetOp(v, pExpr->y.sub.iAddr);
114477114500
assert( pOp->opcode==OP_Once || pParse->nErr );
114478
- if( pOp->opcode==OP_Once && pOp->p3>0 ){
114501
+ if( pOp->opcode==OP_Once && pOp->p3>0 ){ /* tag-202407032019 */
114479114502
assert( OptimizationEnabled(pParse->db, SQLITE_BloomFilter) );
114480114503
sqlite3VdbeAddOp4Int(v, OP_Filter, pOp->p3, destIfFalse,
114481114504
rLhs, nVector); VdbeCoverage(v);
114482114505
}
114483114506
}
@@ -116322,15 +116345,15 @@
116322116345
case TK_ISNULL:
116323116346
case TK_NOTNULL: {
116324116347
assert( TK_ISNULL==OP_IsNull ); testcase( op==TK_ISNULL );
116325116348
assert( TK_NOTNULL==OP_NotNull ); testcase( op==TK_NOTNULL );
116326116349
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
116327
- sqlite3VdbeTypeofColumn(v, r1);
116350
+ assert( regFree1==0 || regFree1==r1 );
116351
+ if( regFree1 ) sqlite3VdbeTypeofColumn(v, r1);
116328116352
sqlite3VdbeAddOp2(v, op, r1, dest);
116329116353
VdbeCoverageIf(v, op==TK_ISNULL);
116330116354
VdbeCoverageIf(v, op==TK_NOTNULL);
116331
- testcase( regFree1==0 );
116332116355
break;
116333116356
}
116334116357
case TK_BETWEEN: {
116335116358
testcase( jumpIfNull==0 );
116336116359
exprCodeBetween(pParse, pExpr, dest, sqlite3ExprIfTrue, jumpIfNull);
@@ -116497,15 +116520,15 @@
116497116520
break;
116498116521
}
116499116522
case TK_ISNULL:
116500116523
case TK_NOTNULL: {
116501116524
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
116502
- sqlite3VdbeTypeofColumn(v, r1);
116525
+ assert( regFree1==0 || regFree1==r1 );
116526
+ if( regFree1 ) sqlite3VdbeTypeofColumn(v, r1);
116503116527
sqlite3VdbeAddOp2(v, op, r1, dest);
116504116528
testcase( op==TK_ISNULL ); VdbeCoverageIf(v, op==TK_ISNULL);
116505116529
testcase( op==TK_NOTNULL ); VdbeCoverageIf(v, op==TK_NOTNULL);
116506
- testcase( regFree1==0 );
116507116530
break;
116508116531
}
116509116532
case TK_BETWEEN: {
116510116533
testcase( jumpIfNull==0 );
116511116534
exprCodeBetween(pParse, pExpr, dest, sqlite3ExprIfFalse, jumpIfNull);
@@ -121683,20 +121706,10 @@
121683121706
}
121684121707
#endif
121685121708
while( z[0]!=0 && z[0]!=' ' ) z++;
121686121709
while( z[0]==' ' ) z++;
121687121710
}
121688
-
121689
- /* Set the bLowQual flag if the peak number of rows obtained
121690
- ** from a full equality match is so large that a full table scan
121691
- ** seems likely to be faster than using the index.
121692
- */
121693
- if( aLog[0] > 66 /* Index has more than 100 rows */
121694
- && aLog[0] <= aLog[nOut-1] /* And only a single value seen */
121695
- ){
121696
- pIndex->bLowQual = 1;
121697
- }
121698121711
}
121699121712
}
121700121713
121701121714
/*
121702121715
** This callback is invoked once for each index when reading the
@@ -124091,11 +124104,11 @@
124091124104
*/
124092124105
SQLITE_PRIVATE int sqlite3TableColumnToIndex(Index *pIdx, int iCol){
124093124106
int i;
124094124107
i16 iCol16;
124095124108
assert( iCol>=(-1) && iCol<=SQLITE_MAX_COLUMN );
124096
- assert( pIdx->nColumn<=SQLITE_MAX_COLUMN );
124109
+ assert( pIdx->nColumn<=SQLITE_MAX_COLUMN+1 );
124097124110
iCol16 = iCol;
124098124111
for(i=0; i<pIdx->nColumn; i++){
124099124112
if( iCol16==pIdx->aiColumn[i] ){
124100124113
return i;
124101124114
}
@@ -167620,15 +167633,12 @@
167620167633
opMask = WO_LT|WO_LE;
167621167634
}else{
167622167635
assert( pNew->u.btree.nBtm==0 );
167623167636
opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE|WO_ISNULL|WO_IS;
167624167637
}
167625
- if( pProbe->bUnordered || pProbe->bLowQual ){
167626
- if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE);
167627
- if( pProbe->bLowQual && pSrc->fg.isIndexedBy==0 ){
167628
- opMask &= ~(WO_EQ|WO_IN|WO_IS);
167629
- }
167638
+ if( pProbe->bUnordered ){
167639
+ opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE);
167630167640
}
167631167641
167632167642
assert( pNew->u.btree.nEq<pProbe->nColumn );
167633167643
assert( pNew->u.btree.nEq<pProbe->nKeyCol
167634167644
|| pProbe->idxType!=SQLITE_IDXTYPE_PRIMARYKEY );
@@ -168561,11 +168571,11 @@
168561168571
}
168562168572
}else if( m==0
168563168573
&& (HasRowid(pTab) || pWInfo->pSelect!=0 || sqlite3FaultSim(700))
168564168574
){
168565168575
WHERETRACE(0x200,
168566
- ("-> %s a covering index according to bitmasks\n",
168576
+ ("-> %s is a covering index according to bitmasks\n",
168567168577
pProbe->zName, m==0 ? "is" : "is not"));
168568168578
pNew->wsFlags = WHERE_IDX_ONLY | WHERE_INDEXED;
168569168579
}
168570168580
}
168571168581
@@ -207968,60 +207978,113 @@
207968207978
** Growing our own isspace() routine this way is twice as fast as
207969207979
** the library isspace() function, resulting in a 7% overall performance
207970207980
** increase for the text-JSON parser. (Ubuntu14.10 gcc 4.8.4 x64 with -Os).
207971207981
*/
207972207982
static const char jsonIsSpace[] = {
207973
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0,
207974
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
207975
- 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
207976
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
207977
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
207978
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
207979
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
207980
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
207981
-
207982
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
207983
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
207984
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
207985
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
207986
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
207987
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
207988
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
207989
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
207983
+#ifdef SQLITE_ASCII
207984
+/*0 1 2 3 4 5 6 7 8 9 a b c d e f */
207985
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, /* 0 */
207986
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1 */
207987
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2 */
207988
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 3 */
207989
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4 */
207990
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 5 */
207991
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6 */
207992
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7 */
207993
+
207994
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 8 */
207995
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9 */
207996
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* a */
207997
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* b */
207998
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* c */
207999
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* d */
208000
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* e */
208001
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* f */
208002
+#endif
208003
+#ifdef SQLITE_EBCDIC
208004
+/*0 1 2 3 4 5 6 7 8 9 a b c d e f */
208005
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, /* 0 */
208006
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1 */
208007
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2 */
208008
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 3 */
208009
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4 */
208010
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 5 */
208011
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6 */
208012
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7 */
208013
+
208014
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 8 */
208015
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9 */
208016
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* a */
208017
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* b */
208018
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* c */
208019
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* d */
208020
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* e */
208021
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* f */
208022
+#endif
208023
+
207990208024
};
207991208025
#define jsonIsspace(x) (jsonIsSpace[(unsigned char)x])
207992208026
207993208027
/*
207994208028
** The set of all space characters recognized by jsonIsspace().
207995208029
** Useful as the second argument to strspn().
207996208030
*/
208031
+#ifdef SQLITE_ASCII
207997208032
static const char jsonSpaces[] = "\011\012\015\040";
208033
+#endif
208034
+#ifdef SQLITE_EBCDIC
208035
+static const char jsonSpaces[] = "\005\045\015\100";
208036
+#endif
208037
+
207998208038
207999208039
/*
208000208040
** Characters that are special to JSON. Control characters,
208001208041
** '"' and '\\' and '\''. Actually, '\'' is not special to
208002208042
** canonical JSON, but it is special in JSON-5, so we include
208003208043
** it in the set of special characters.
208004208044
*/
208005208045
static const char jsonIsOk[256] = {
208006
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
208007
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
208008
- 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
208009
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
208010
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
208011
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
208012
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
208013
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
208014
-
208015
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
208016
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
208017
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
208018
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
208019
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
208020
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
208021
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
208022
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
208046
+#ifdef SQLITE_ASCII
208047
+/*0 1 2 3 4 5 6 7 8 9 a b c d e f */
208048
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0 */
208049
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1 */
208050
+ 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, /* 2 */
208051
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 3 */
208052
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4 */
208053
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, /* 5 */
208054
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6 */
208055
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 7 */
208056
+
208057
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 8 */
208058
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 9 */
208059
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* a */
208060
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* b */
208061
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* c */
208062
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* d */
208063
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* e */
208064
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 /* f */
208065
+#endif
208066
+#ifdef SQLITE_EBCDIC
208067
+/*0 1 2 3 4 5 6 7 8 9 a b c d e f */
208068
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0 */
208069
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1 */
208070
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2 */
208071
+ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, /* 3 */
208072
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4 */
208073
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 5 */
208074
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6 */
208075
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, /* 7 */
208076
+
208077
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 8 */
208078
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 9 */
208079
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* a */
208080
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* b */
208081
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* c */
208082
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* d */
208083
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* e */
208084
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 /* f */
208085
+#endif
208023208086
};
208024208087
208025208088
/* Objects */
208026208089
typedef struct JsonCache JsonCache;
208027208090
typedef struct JsonString JsonString;
@@ -208162,11 +208225,11 @@
208162208225
208163208226
/**************************************************************************
208164208227
** Forward references
208165208228
**************************************************************************/
208166208229
static void jsonReturnStringAsBlob(JsonString*);
208167
-static int jsonFuncArgMightBeBinary(sqlite3_value *pJson);
208230
+static int jsonArgIsJsonb(sqlite3_value *pJson, JsonParse *p);
208168208231
static u32 jsonTranslateBlobToText(const JsonParse*,u32,JsonString*);
208169208232
static void jsonReturnParse(sqlite3_context*,JsonParse*);
208170208233
static JsonParse *jsonParseFuncArg(sqlite3_context*,sqlite3_value*,u32);
208171208234
static void jsonParseFree(JsonParse*);
208172208235
static u32 jsonbPayloadSize(const JsonParse*, u32, u32*);
@@ -208580,15 +208643,13 @@
208580208643
jsonAppendString(p, z, n);
208581208644
}
208582208645
break;
208583208646
}
208584208647
default: {
208585
- if( jsonFuncArgMightBeBinary(pValue) ){
208586
- JsonParse px;
208587
- memset(&px, 0, sizeof(px));
208588
- px.aBlob = (u8*)sqlite3_value_blob(pValue);
208589
- px.nBlob = sqlite3_value_bytes(pValue);
208648
+ JsonParse px;
208649
+ memset(&px, 0, sizeof(px));
208650
+ if( jsonArgIsJsonb(pValue, &px) ){
208590208651
jsonTranslateBlobToText(&px, 0, p);
208591208652
}else if( p->eErr==0 ){
208592208653
sqlite3_result_error(p->pCtx, "JSON cannot hold BLOB values", -1);
208593208654
p->eErr = JSTRING_ERR;
208594208655
jsonStringReset(p);
@@ -209522,11 +209583,16 @@
209522209583
c = z[++j];
209523209584
if( c=='"' || c=='\\' || c=='/' || c=='b' || c=='f'
209524209585
|| c=='n' || c=='r' || c=='t'
209525209586
|| (c=='u' && jsonIs4Hex(&z[j+1])) ){
209526209587
if( opcode==JSONB_TEXT ) opcode = JSONB_TEXTJ;
209527
- }else if( c=='\'' || c=='0' || c=='v' || c=='\n'
209588
+ }else if( c=='\'' || c=='v' || c=='\n'
209589
+#ifdef SQLITE_BUG_COMPATIBLE_20250510
209590
+ || (c=='0') /* Legacy bug compatible */
209591
+#else
209592
+ || (c=='0' && !sqlite3Isdigit(z[j+1])) /* Correct implementation */
209593
+#endif
209528209594
|| (0xe2==(u8)c && 0x80==(u8)z[j+1]
209529209595
&& (0xa8==(u8)z[j+2] || 0xa9==(u8)z[j+2]))
209530209596
|| (c=='x' && jsonIs2Hex(&z[j+1])) ){
209531209597
opcode = JSONB_TEXT5;
209532209598
pParse->hasNonstd = 1;
@@ -209909,11 +209975,11 @@
209909209975
|| pParse->aBlob[i+4]!=0
209910209976
){
209911209977
*pSz = 0;
209912209978
return 0;
209913209979
}
209914
- sz = (pParse->aBlob[i+5]<<24) + (pParse->aBlob[i+6]<<16) +
209980
+ sz = ((u32)pParse->aBlob[i+5]<<24) + (pParse->aBlob[i+6]<<16) +
209915209981
(pParse->aBlob[i+7]<<8) + pParse->aBlob[i+8];
209916209982
n = 9;
209917209983
}
209918209984
if( (i64)i+sz+n > pParse->nBlob
209919209985
&& (i64)i+sz+n > pParse->nBlob-pParse->delta
@@ -210258,37 +210324,10 @@
210258210324
}
210259210325
}
210260210326
return i;
210261210327
}
210262210328
210263
-
210264
-/* Return true if the input pJson
210265
-**
210266
-** For performance reasons, this routine does not do a detailed check of the
210267
-** input BLOB to ensure that it is well-formed. Hence, false positives are
210268
-** possible. False negatives should never occur, however.
210269
-*/
210270
-static int jsonFuncArgMightBeBinary(sqlite3_value *pJson){
210271
- u32 sz, n;
210272
- const u8 *aBlob;
210273
- int nBlob;
210274
- JsonParse s;
210275
- if( sqlite3_value_type(pJson)!=SQLITE_BLOB ) return 0;
210276
- aBlob = sqlite3_value_blob(pJson);
210277
- nBlob = sqlite3_value_bytes(pJson);
210278
- if( nBlob<1 ) return 0;
210279
- if( NEVER(aBlob==0) || (aBlob[0] & 0x0f)>JSONB_OBJECT ) return 0;
210280
- memset(&s, 0, sizeof(s));
210281
- s.aBlob = (u8*)aBlob;
210282
- s.nBlob = nBlob;
210283
- n = jsonbPayloadSize(&s, 0, &sz);
210284
- if( n==0 ) return 0;
210285
- if( sz+n!=(u32)nBlob ) return 0;
210286
- if( (aBlob[0] & 0x0f)<=JSONB_FALSE && sz>0 ) return 0;
210287
- return sz+n==(u32)nBlob;
210288
-}
210289
-
210290210329
/*
210291210330
** Given that a JSONB_ARRAY object starts at offset i, return
210292210331
** the number of entries in that array.
210293210332
*/
210294210333
static u32 jsonbArrayCount(JsonParse *pParse, u32 iRoot){
@@ -210517,11 +210556,25 @@
210517210556
case 'f': { *piOut = '\f'; return 2; }
210518210557
case 'n': { *piOut = '\n'; return 2; }
210519210558
case 'r': { *piOut = '\r'; return 2; }
210520210559
case 't': { *piOut = '\t'; return 2; }
210521210560
case 'v': { *piOut = '\v'; return 2; }
210522
- case '0': { *piOut = 0; return 2; }
210561
+ case '0': {
210562
+ /* JSON5 requires that the \0 escape not be followed by a digit.
210563
+ ** But SQLite did not enforce this restriction in versions 3.42.0
210564
+ ** through 3.49.2. That was a bug. But some applications might have
210565
+ ** come to depend on that bug. Use the SQLITE_BUG_COMPATIBLE_20250510
210566
+ ** option to restore the old buggy behavior. */
210567
+#ifdef SQLITE_BUG_COMPATIBLE_20250510
210568
+ /* Legacy bug-compatible behavior */
210569
+ *piOut = 0;
210570
+#else
210571
+ /* Correct behavior */
210572
+ *piOut = (n>2 && sqlite3Isdigit(z[2])) ? JSON_INVALID_CHAR : 0;
210573
+#endif
210574
+ return 2;
210575
+ }
210523210576
case '\'':
210524210577
case '"':
210525210578
case '/':
210526210579
case '\\':{ *piOut = z[1]; return 2; }
210527210580
case 'x': {
@@ -211112,14 +211165,11 @@
211112211165
pParse->aBlob = aNull;
211113211166
pParse->nBlob = 1;
211114211167
return 0;
211115211168
}
211116211169
case SQLITE_BLOB: {
211117
- if( jsonFuncArgMightBeBinary(pArg) ){
211118
- pParse->aBlob = (u8*)sqlite3_value_blob(pArg);
211119
- pParse->nBlob = sqlite3_value_bytes(pArg);
211120
- }else{
211170
+ if( !jsonArgIsJsonb(pArg, pParse) ){
211121211171
sqlite3_result_error(ctx, "JSON cannot hold BLOB values", -1);
211122211172
return 1;
211123211173
}
211124211174
break;
211125211175
}
@@ -211266,31 +211316,50 @@
211266211316
}
211267211317
211268211318
/*
211269211319
** If pArg is a blob that seems like a JSONB blob, then initialize
211270211320
** p to point to that JSONB and return TRUE. If pArg does not seem like
211271
-** a JSONB blob, then return FALSE;
211321
+** a JSONB blob, then return FALSE.
211272211322
**
211273
-** This routine is only called if it is already known that pArg is a
211274
-** blob. The only open question is whether or not the blob appears
211275
-** to be a JSONB blob.
211323
+** For small BLOBs (having no more than 7 bytes of payload) a full
211324
+** validity check is done. So for small BLOBs this routine only returns
211325
+** true if the value is guaranteed to be a valid JSONB. For larger BLOBs
211326
+** (8 byte or more of payload) only the size of the outermost element is
211327
+** checked to verify that the BLOB is superficially valid JSONB.
211328
+**
211329
+** A full JSONB validation is done on smaller BLOBs because those BLOBs might
211330
+** also be text JSON that has been incorrectly cast into a BLOB.
211331
+** (See tag-20240123-a and https://sqlite.org/forum/forumpost/012136abd5)
211332
+** If the BLOB is 9 bytes are larger, then it is not possible for the
211333
+** superficial size check done here to pass if the input is really text
211334
+** JSON so we do not need to look deeper in that case.
211335
+**
211336
+** Why we only need to do full JSONB validation for smaller BLOBs:
211337
+**
211338
+** The first byte of valid JSON text must be one of: '{', '[', '"', ' ', '\n',
211339
+** '\r', '\t', '-', or a digit '0' through '9'. Of these, only a subset
211340
+** can also be the first byte of JSONB: '{', '[', and digits '3'
211341
+** through '9'. In every one of those cases, the payload size is 7 bytes
211342
+** or less. So if we do full JSONB validation for every BLOB where the
211343
+** payload is less than 7 bytes, we will never get a false positive for
211344
+** JSONB on an input that is really text JSON.
211276211345
*/
211277211346
static int jsonArgIsJsonb(sqlite3_value *pArg, JsonParse *p){
211278211347
u32 n, sz = 0;
211348
+ u8 c;
211349
+ if( sqlite3_value_type(pArg)!=SQLITE_BLOB ) return 0;
211279211350
p->aBlob = (u8*)sqlite3_value_blob(pArg);
211280211351
p->nBlob = (u32)sqlite3_value_bytes(pArg);
211281
- if( p->nBlob==0 ){
211282
- p->aBlob = 0;
211283
- return 0;
211284
- }
211285
- if( NEVER(p->aBlob==0) ){
211286
- return 0;
211287
- }
211288
- if( (p->aBlob[0] & 0x0f)<=JSONB_OBJECT
211352
+ if( p->nBlob>0
211353
+ && ALWAYS(p->aBlob!=0)
211354
+ && ((c = p->aBlob[0]) & 0x0f)<=JSONB_OBJECT
211289211355
&& (n = jsonbPayloadSize(p, 0, &sz))>0
211290211356
&& sz+n==p->nBlob
211291
- && ((p->aBlob[0] & 0x0f)>JSONB_FALSE || sz==0)
211357
+ && ((c & 0x0f)>JSONB_FALSE || sz==0)
211358
+ && (sz>7
211359
+ || (c!=0x7b && c!=0x5b && !sqlite3Isdigit(c))
211360
+ || jsonbValidityCheck(p, 0, p->nBlob, 1)==0)
211292211361
){
211293211362
return 1;
211294211363
}
211295211364
p->aBlob = 0;
211296211365
p->nBlob = 0;
@@ -212379,25 +212448,21 @@
212379212448
sqlite3_result_int(ctx, 0);
212380212449
#endif
212381212450
return;
212382212451
}
212383212452
case SQLITE_BLOB: {
212384
- if( jsonFuncArgMightBeBinary(argv[0]) ){
212453
+ JsonParse py;
212454
+ memset(&py, 0, sizeof(py));
212455
+ if( jsonArgIsJsonb(argv[0], &py) ){
212385212456
if( flags & 0x04 ){
212386212457
/* Superficial checking only - accomplished by the
212387
- ** jsonFuncArgMightBeBinary() call above. */
212458
+ ** jsonArgIsJsonb() call above. */
212388212459
res = 1;
212389212460
}else if( flags & 0x08 ){
212390212461
/* Strict checking. Check by translating BLOB->TEXT->BLOB. If
212391212462
** no errors occur, call that a "strict check". */
212392
- JsonParse px;
212393
- u32 iErr;
212394
- memset(&px, 0, sizeof(px));
212395
- px.aBlob = (u8*)sqlite3_value_blob(argv[0]);
212396
- px.nBlob = sqlite3_value_bytes(argv[0]);
212397
- iErr = jsonbValidityCheck(&px, 0, px.nBlob, 1);
212398
- res = iErr==0;
212463
+ res = 0==jsonbValidityCheck(&py, 0, py.nBlob, 1);
212399212464
}
212400212465
break;
212401212466
}
212402212467
/* Fall through into interpreting the input as text. See note
212403212468
** above at tag-20240123-a. */
@@ -212451,13 +212516,11 @@
212451212516
212452212517
assert( argc==1 );
212453212518
UNUSED_PARAMETER(argc);
212454212519
memset(&s, 0, sizeof(s));
212455212520
s.db = sqlite3_context_db_handle(ctx);
212456
- if( jsonFuncArgMightBeBinary(argv[0]) ){
212457
- s.aBlob = (u8*)sqlite3_value_blob(argv[0]);
212458
- s.nBlob = sqlite3_value_bytes(argv[0]);
212521
+ if( jsonArgIsJsonb(argv[0], &s) ){
212459212522
iErrPos = (i64)jsonbValidityCheck(&s, 0, s.nBlob, 1);
212460212523
}else{
212461212524
s.zJson = (char*)sqlite3_value_text(argv[0]);
212462212525
if( s.zJson==0 ) return; /* NULL input or OOM */
212463212526
s.nJson = sqlite3_value_bytes(argv[0]);
@@ -213138,13 +213201,12 @@
213138213201
jsonEachCursorReset(p);
213139213202
if( idxNum==0 ) return SQLITE_OK;
213140213203
memset(&p->sParse, 0, sizeof(p->sParse));
213141213204
p->sParse.nJPRef = 1;
213142213205
p->sParse.db = p->db;
213143
- if( jsonFuncArgMightBeBinary(argv[0]) ){
213144
- p->sParse.nBlob = sqlite3_value_bytes(argv[0]);
213145
- p->sParse.aBlob = (u8*)sqlite3_value_blob(argv[0]);
213206
+ if( jsonArgIsJsonb(argv[0], &p->sParse) ){
213207
+ /* We have JSONB */
213146213208
}else{
213147213209
p->sParse.zJson = (char*)sqlite3_value_text(argv[0]);
213148213210
p->sParse.nJson = sqlite3_value_bytes(argv[0]);
213149213211
if( p->sParse.zJson==0 ){
213150213212
p->i = p->iEnd = 0;
@@ -257213,11 +257275,11 @@
257213257275
int nArg, /* Number of args */
257214257276
sqlite3_value **apUnused /* Function arguments */
257215257277
){
257216257278
assert( nArg==0 );
257217257279
UNUSED_PARAM2(nArg, apUnused);
257218
- sqlite3_result_text(pCtx, "fts5: 2025-04-15 21:59:38 d22475b81c4e26ccc50f3b5626d43b32f7a2de34e5a764539554665bdda735d5", -1, SQLITE_TRANSIENT);
257280
+ sqlite3_result_text(pCtx, "fts5: 2025-05-15 11:20:54 336ceeccc6f85bd78f4a26648af7edf9056d569a767b4120f125a02b2090a349", -1, SQLITE_TRANSIENT);
257219257281
}
257220257282
257221257283
/*
257222257284
** Implementation of fts5_locale(LOCALE, TEXT) function.
257223257285
**
257224257286
--- extsrc/sqlite3.c
+++ extsrc/sqlite3.c
@@ -16,11 +16,11 @@
16 ** if you want a wrapper to interface SQLite with your choice of programming
17 ** language. The code for the "sqlite3" command-line shell is also in a
18 ** separate file. This file contains only code for the core SQLite library.
19 **
20 ** The content in this amalgamation comes from Fossil check-in
21 ** d22475b81c4e26ccc50f3b5626d43b32f7a2 with changes in files:
22 **
23 **
24 */
25 #ifndef SQLITE_AMALGAMATION
26 #define SQLITE_CORE 1
@@ -465,11 +465,11 @@
465 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
466 ** [sqlite_version()] and [sqlite_source_id()].
467 */
468 #define SQLITE_VERSION "3.50.0"
469 #define SQLITE_VERSION_NUMBER 3050000
470 #define SQLITE_SOURCE_ID "2025-04-15 21:59:38 d22475b81c4e26ccc50f3b5626d43b32f7a2de34e5a764539554665bdda735d5"
471
472 /*
473 ** CAPI3REF: Run-Time Library Version Numbers
474 ** KEYWORDS: sqlite3_version sqlite3_sourceid
475 **
@@ -11872,13 +11872,14 @@
11872 ** This may appear to have some counter-intuitive effects if a single row
11873 ** is written to more than once during a session. For example, if a row
11874 ** is inserted while a session object is enabled, then later deleted while
11875 ** the same session object is disabled, no INSERT record will appear in the
11876 ** changeset, even though the delete took place while the session was disabled.
11877 ** Or, if one field of a row is updated while a session is disabled, and
11878 ** another field of the same row is updated while the session is enabled, the
11879 ** resulting changeset will contain an UPDATE change that updates both fields.
 
11880 */
11881 SQLITE_API int sqlite3session_changeset(
11882 sqlite3_session *pSession, /* Session object */
11883 int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */
11884 void **ppChangeset /* OUT: Buffer containing changeset */
@@ -12083,11 +12084,11 @@
12083 ** CAPI3REF: Flags for sqlite3changeset_start_v2
12084 **
12085 ** The following flags may passed via the 4th parameter to
12086 ** [sqlite3changeset_start_v2] and [sqlite3changeset_start_v2_strm]:
12087 **
12088 ** <dt>SQLITE_CHANGESETAPPLY_INVERT <dd>
12089 ** Invert the changeset while iterating through it. This is equivalent to
12090 ** inverting a changeset using sqlite3changeset_invert() before applying it.
12091 ** It is an error to specify this flag with a patchset.
12092 */
12093 #define SQLITE_CHANGESETSTART_INVERT 0x0002
@@ -19160,11 +19161,10 @@
19160 unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */
19161 unsigned isResized:1; /* True if resizeIndexObject() has been called */
19162 unsigned isCovering:1; /* True if this is a covering index */
19163 unsigned noSkipScan:1; /* Do not try to use skip-scan if true */
19164 unsigned hasStat1:1; /* aiRowLogEst values come from sqlite_stat1 */
19165 unsigned bLowQual:1; /* sqlite_stat1 says this is a low-quality index */
19166 unsigned bNoQuery:1; /* Do not use this index to optimize queries */
19167 unsigned bAscKeyBug:1; /* True if the bba7b69f9849b5bf bug applies */
19168 unsigned bIdxRowid:1; /* One or more of the index keys is the ROWID */
19169 unsigned bHasVCol:1; /* Index references one or more VIRTUAL columns */
19170 unsigned bHasExpr:1; /* Index contains an expression, either a literal
@@ -22424,10 +22424,13 @@
22424 #ifdef SQLITE_BITMASK_TYPE
22425 "BITMASK_TYPE=" CTIMEOPT_VAL(SQLITE_BITMASK_TYPE),
22426 #endif
22427 #ifdef SQLITE_BUG_COMPATIBLE_20160819
22428 "BUG_COMPATIBLE_20160819",
 
 
 
22429 #endif
22430 #ifdef SQLITE_CASE_SENSITIVE_LIKE
22431 "CASE_SENSITIVE_LIKE",
22432 #endif
22433 #ifdef SQLITE_CHECK_PAGES
@@ -32987,10 +32990,19 @@
32987 va_end(ap);
32988 zBuf[acc.nChar] = 0;
32989 return zBuf;
32990 }
32991
 
 
 
 
 
 
 
 
 
32992 /*
32993 ** This is the routine that actually formats the sqlite3_log() message.
32994 ** We house it in a separate routine from sqlite3_log() to avoid using
32995 ** stack space on small-stack systems when logging is disabled.
32996 **
@@ -33003,11 +33015,11 @@
33003 ** Care must be taken that any sqlite3_log() calls that occur while the
33004 ** memory mutex is held do not use these mechanisms.
33005 */
33006 static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){
33007 StrAccum acc; /* String accumulator */
33008 char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */
33009
33010 sqlite3StrAccumInit(&acc, 0, zMsg, sizeof(zMsg), 0);
33011 sqlite3_str_vappendf(&acc, zFormat, ap);
33012 sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode,
33013 sqlite3StrAccumFinish(&acc));
@@ -87262,10 +87274,13 @@
87262 ** into register iDest, then add the OPFLAG_TYPEOFARG flag to that
87263 ** opcode.
87264 */
87265 SQLITE_PRIVATE void sqlite3VdbeTypeofColumn(Vdbe *p, int iDest){
87266 VdbeOp *pOp = sqlite3VdbeGetLastOp(p);
 
 
 
87267 if( pOp->p3==iDest && pOp->opcode==OP_Column ){
87268 pOp->p5 |= OPFLAG_TYPEOFARG;
87269 }
87270 }
87271
@@ -95716,11 +95731,11 @@
95716 }
95717 }else{
95718 sqlite3VdbeError(p, "%s", pOp->p4.z);
95719 }
95720 pcx = (int)(pOp - aOp);
95721 sqlite3_log(pOp->p1, "abort at %d in [%s]: %s", pcx, p->zSql, p->zErrMsg);
95722 }
95723 rc = sqlite3VdbeHalt(p);
95724 assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR );
95725 if( rc==SQLITE_BUSY ){
95726 p->rc = SQLITE_BUSY;
@@ -97042,11 +97057,11 @@
97042 pOut->u.i = ~sqlite3VdbeIntValue(pIn1);
97043 }
97044 break;
97045 }
97046
97047 /* Opcode: Once P1 P2 * * *
97048 **
97049 ** Fall through to the next instruction the first time this opcode is
97050 ** encountered on each invocation of the byte-code program. Jump to P2
97051 ** on the second and all subsequent encounters during the same invocation.
97052 **
@@ -97058,10 +97073,16 @@
97058 **
97059 ** For subprograms, there is a bitmask in the VdbeFrame that determines
97060 ** whether or not the jump should be taken. The bitmask is necessary
97061 ** because the self-altering code trick does not work for recursive
97062 ** triggers.
 
 
 
 
 
 
97063 */
97064 case OP_Once: { /* jump */
97065 u32 iAddr; /* Address of this instruction */
97066 assert( p->aOp[0].opcode==OP_Init );
97067 if( p->pFrame ){
@@ -98103,10 +98124,11 @@
98103 }
98104 }else{
98105 zHdr += sqlite3PutVarint(zHdr, serial_type);
98106 if( pRec->n ){
98107 assert( pRec->z!=0 );
 
98108 memcpy(zPayload, pRec->z, pRec->n);
98109 zPayload += pRec->n;
98110 }
98111 }
98112 if( pRec==pLast ) break;
@@ -103551,12 +103573,12 @@
103551 sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc));
103552 }
103553 p->rc = rc;
103554 sqlite3SystemError(db, rc);
103555 testcase( sqlite3GlobalConfig.xLog!=0 );
103556 sqlite3_log(rc, "statement aborts at %d: [%s] %s",
103557 (int)(pOp - aOp), p->zSql, p->zErrMsg);
103558 if( p->eVdbeState==VDBE_RUN_STATE ) sqlite3VdbeHalt(p);
103559 if( rc==SQLITE_IOERR_NOMEM ) sqlite3OomFault(db);
103560 if( rc==SQLITE_CORRUPT && db->autoCommit==0 ){
103561 db->flags |= SQLITE_CorruptRdOnly;
103562 }
@@ -109287,17 +109309,16 @@
109287 /* Clearly non-deterministic functions like random(), but also
109288 ** date/time functions that use 'now', and other functions like
109289 ** sqlite_version() that might change over time cannot be used
109290 ** in an index or generated column. Curiously, they can be used
109291 ** in a CHECK constraint. SQLServer, MySQL, and PostgreSQL all
109292 ** all this. */
109293 sqlite3ResolveNotValid(pParse, pNC, "non-deterministic functions",
109294 NC_IdxExpr|NC_PartIdx|NC_GenCol, 0, pExpr);
109295 }else{
109296 assert( (NC_SelfRef & 0xff)==NC_SelfRef ); /* Must fit in 8 bits */
109297 pExpr->op2 = pNC->ncFlags & NC_SelfRef;
109298 if( pNC->ncFlags & NC_FromDDL ) ExprSetProperty(pExpr, EP_FromDDL);
109299 }
109300 if( (pDef->funcFlags & SQLITE_FUNC_INTERNAL)!=0
109301 && pParse->nested==0
109302 && (pParse->db->mDbFlags & DBFLAG_InternalFunc)==0
109303 ){
@@ -109309,10 +109330,11 @@
109309 pDef = 0;
109310 }else
109311 if( (pDef->funcFlags & (SQLITE_FUNC_DIRECT|SQLITE_FUNC_UNSAFE))!=0
109312 && !IN_RENAME_OBJECT
109313 ){
 
109314 sqlite3ExprFunctionUsable(pParse, pExpr, pDef);
109315 }
109316 }
109317
109318 if( 0==IN_RENAME_OBJECT ){
@@ -114022,15 +114044,16 @@
114022 pCopy = sqlite3SelectDup(pParse->db, pSelect, 0);
114023 rc = pParse->db->mallocFailed ? 1 :sqlite3Select(pParse, pCopy, &dest);
114024 sqlite3SelectDelete(pParse->db, pCopy);
114025 sqlite3DbFree(pParse->db, dest.zAffSdst);
114026 if( addrBloom ){
 
 
114027 sqlite3VdbeGetOp(v, addrOnce)->p3 = dest.iSDParm2;
114028 if( dest.iSDParm2==0 ){
114029 sqlite3VdbeChangeToNoop(v, addrBloom);
114030 }else{
114031 sqlite3VdbeGetOp(v, addrOnce)->p3 = dest.iSDParm2;
114032 }
114033 }
114034 if( rc ){
114035 sqlite3KeyInfoUnref(pKeyInfo);
114036 return;
@@ -114473,11 +114496,11 @@
114473 if( destIfFalse==destIfNull ){
114474 /* Combine Step 3 and Step 5 into a single opcode */
114475 if( ExprHasProperty(pExpr, EP_Subrtn) ){
114476 const VdbeOp *pOp = sqlite3VdbeGetOp(v, pExpr->y.sub.iAddr);
114477 assert( pOp->opcode==OP_Once || pParse->nErr );
114478 if( pOp->opcode==OP_Once && pOp->p3>0 ){
114479 assert( OptimizationEnabled(pParse->db, SQLITE_BloomFilter) );
114480 sqlite3VdbeAddOp4Int(v, OP_Filter, pOp->p3, destIfFalse,
114481 rLhs, nVector); VdbeCoverage(v);
114482 }
114483 }
@@ -116322,15 +116345,15 @@
116322 case TK_ISNULL:
116323 case TK_NOTNULL: {
116324 assert( TK_ISNULL==OP_IsNull ); testcase( op==TK_ISNULL );
116325 assert( TK_NOTNULL==OP_NotNull ); testcase( op==TK_NOTNULL );
116326 r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
116327 sqlite3VdbeTypeofColumn(v, r1);
 
116328 sqlite3VdbeAddOp2(v, op, r1, dest);
116329 VdbeCoverageIf(v, op==TK_ISNULL);
116330 VdbeCoverageIf(v, op==TK_NOTNULL);
116331 testcase( regFree1==0 );
116332 break;
116333 }
116334 case TK_BETWEEN: {
116335 testcase( jumpIfNull==0 );
116336 exprCodeBetween(pParse, pExpr, dest, sqlite3ExprIfTrue, jumpIfNull);
@@ -116497,15 +116520,15 @@
116497 break;
116498 }
116499 case TK_ISNULL:
116500 case TK_NOTNULL: {
116501 r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
116502 sqlite3VdbeTypeofColumn(v, r1);
 
116503 sqlite3VdbeAddOp2(v, op, r1, dest);
116504 testcase( op==TK_ISNULL ); VdbeCoverageIf(v, op==TK_ISNULL);
116505 testcase( op==TK_NOTNULL ); VdbeCoverageIf(v, op==TK_NOTNULL);
116506 testcase( regFree1==0 );
116507 break;
116508 }
116509 case TK_BETWEEN: {
116510 testcase( jumpIfNull==0 );
116511 exprCodeBetween(pParse, pExpr, dest, sqlite3ExprIfFalse, jumpIfNull);
@@ -121683,20 +121706,10 @@
121683 }
121684 #endif
121685 while( z[0]!=0 && z[0]!=' ' ) z++;
121686 while( z[0]==' ' ) z++;
121687 }
121688
121689 /* Set the bLowQual flag if the peak number of rows obtained
121690 ** from a full equality match is so large that a full table scan
121691 ** seems likely to be faster than using the index.
121692 */
121693 if( aLog[0] > 66 /* Index has more than 100 rows */
121694 && aLog[0] <= aLog[nOut-1] /* And only a single value seen */
121695 ){
121696 pIndex->bLowQual = 1;
121697 }
121698 }
121699 }
121700
121701 /*
121702 ** This callback is invoked once for each index when reading the
@@ -124091,11 +124104,11 @@
124091 */
124092 SQLITE_PRIVATE int sqlite3TableColumnToIndex(Index *pIdx, int iCol){
124093 int i;
124094 i16 iCol16;
124095 assert( iCol>=(-1) && iCol<=SQLITE_MAX_COLUMN );
124096 assert( pIdx->nColumn<=SQLITE_MAX_COLUMN );
124097 iCol16 = iCol;
124098 for(i=0; i<pIdx->nColumn; i++){
124099 if( iCol16==pIdx->aiColumn[i] ){
124100 return i;
124101 }
@@ -167620,15 +167633,12 @@
167620 opMask = WO_LT|WO_LE;
167621 }else{
167622 assert( pNew->u.btree.nBtm==0 );
167623 opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE|WO_ISNULL|WO_IS;
167624 }
167625 if( pProbe->bUnordered || pProbe->bLowQual ){
167626 if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE);
167627 if( pProbe->bLowQual && pSrc->fg.isIndexedBy==0 ){
167628 opMask &= ~(WO_EQ|WO_IN|WO_IS);
167629 }
167630 }
167631
167632 assert( pNew->u.btree.nEq<pProbe->nColumn );
167633 assert( pNew->u.btree.nEq<pProbe->nKeyCol
167634 || pProbe->idxType!=SQLITE_IDXTYPE_PRIMARYKEY );
@@ -168561,11 +168571,11 @@
168561 }
168562 }else if( m==0
168563 && (HasRowid(pTab) || pWInfo->pSelect!=0 || sqlite3FaultSim(700))
168564 ){
168565 WHERETRACE(0x200,
168566 ("-> %s a covering index according to bitmasks\n",
168567 pProbe->zName, m==0 ? "is" : "is not"));
168568 pNew->wsFlags = WHERE_IDX_ONLY | WHERE_INDEXED;
168569 }
168570 }
168571
@@ -207968,60 +207978,113 @@
207968 ** Growing our own isspace() routine this way is twice as fast as
207969 ** the library isspace() function, resulting in a 7% overall performance
207970 ** increase for the text-JSON parser. (Ubuntu14.10 gcc 4.8.4 x64 with -Os).
207971 */
207972 static const char jsonIsSpace[] = {
207973 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0,
207974 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
207975 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
207976 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
207977 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
207978 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
207979 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
207980 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
207981
207982 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
207983 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
207984 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
207985 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
207986 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
207987 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
207988 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
207989 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
207990 };
207991 #define jsonIsspace(x) (jsonIsSpace[(unsigned char)x])
207992
207993 /*
207994 ** The set of all space characters recognized by jsonIsspace().
207995 ** Useful as the second argument to strspn().
207996 */
 
207997 static const char jsonSpaces[] = "\011\012\015\040";
 
 
 
 
 
207998
207999 /*
208000 ** Characters that are special to JSON. Control characters,
208001 ** '"' and '\\' and '\''. Actually, '\'' is not special to
208002 ** canonical JSON, but it is special in JSON-5, so we include
208003 ** it in the set of special characters.
208004 */
208005 static const char jsonIsOk[256] = {
208006 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
208007 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
208008 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
208009 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
208010 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
208011 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
208012 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
208013 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
208014
208015 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
208016 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
208017 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
208018 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
208019 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
208020 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
208021 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
208022 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
208023 };
208024
208025 /* Objects */
208026 typedef struct JsonCache JsonCache;
208027 typedef struct JsonString JsonString;
@@ -208162,11 +208225,11 @@
208162
208163 /**************************************************************************
208164 ** Forward references
208165 **************************************************************************/
208166 static void jsonReturnStringAsBlob(JsonString*);
208167 static int jsonFuncArgMightBeBinary(sqlite3_value *pJson);
208168 static u32 jsonTranslateBlobToText(const JsonParse*,u32,JsonString*);
208169 static void jsonReturnParse(sqlite3_context*,JsonParse*);
208170 static JsonParse *jsonParseFuncArg(sqlite3_context*,sqlite3_value*,u32);
208171 static void jsonParseFree(JsonParse*);
208172 static u32 jsonbPayloadSize(const JsonParse*, u32, u32*);
@@ -208580,15 +208643,13 @@
208580 jsonAppendString(p, z, n);
208581 }
208582 break;
208583 }
208584 default: {
208585 if( jsonFuncArgMightBeBinary(pValue) ){
208586 JsonParse px;
208587 memset(&px, 0, sizeof(px));
208588 px.aBlob = (u8*)sqlite3_value_blob(pValue);
208589 px.nBlob = sqlite3_value_bytes(pValue);
208590 jsonTranslateBlobToText(&px, 0, p);
208591 }else if( p->eErr==0 ){
208592 sqlite3_result_error(p->pCtx, "JSON cannot hold BLOB values", -1);
208593 p->eErr = JSTRING_ERR;
208594 jsonStringReset(p);
@@ -209522,11 +209583,16 @@
209522 c = z[++j];
209523 if( c=='"' || c=='\\' || c=='/' || c=='b' || c=='f'
209524 || c=='n' || c=='r' || c=='t'
209525 || (c=='u' && jsonIs4Hex(&z[j+1])) ){
209526 if( opcode==JSONB_TEXT ) opcode = JSONB_TEXTJ;
209527 }else if( c=='\'' || c=='0' || c=='v' || c=='\n'
 
 
 
 
 
209528 || (0xe2==(u8)c && 0x80==(u8)z[j+1]
209529 && (0xa8==(u8)z[j+2] || 0xa9==(u8)z[j+2]))
209530 || (c=='x' && jsonIs2Hex(&z[j+1])) ){
209531 opcode = JSONB_TEXT5;
209532 pParse->hasNonstd = 1;
@@ -209909,11 +209975,11 @@
209909 || pParse->aBlob[i+4]!=0
209910 ){
209911 *pSz = 0;
209912 return 0;
209913 }
209914 sz = (pParse->aBlob[i+5]<<24) + (pParse->aBlob[i+6]<<16) +
209915 (pParse->aBlob[i+7]<<8) + pParse->aBlob[i+8];
209916 n = 9;
209917 }
209918 if( (i64)i+sz+n > pParse->nBlob
209919 && (i64)i+sz+n > pParse->nBlob-pParse->delta
@@ -210258,37 +210324,10 @@
210258 }
210259 }
210260 return i;
210261 }
210262
210263
210264 /* Return true if the input pJson
210265 **
210266 ** For performance reasons, this routine does not do a detailed check of the
210267 ** input BLOB to ensure that it is well-formed. Hence, false positives are
210268 ** possible. False negatives should never occur, however.
210269 */
210270 static int jsonFuncArgMightBeBinary(sqlite3_value *pJson){
210271 u32 sz, n;
210272 const u8 *aBlob;
210273 int nBlob;
210274 JsonParse s;
210275 if( sqlite3_value_type(pJson)!=SQLITE_BLOB ) return 0;
210276 aBlob = sqlite3_value_blob(pJson);
210277 nBlob = sqlite3_value_bytes(pJson);
210278 if( nBlob<1 ) return 0;
210279 if( NEVER(aBlob==0) || (aBlob[0] & 0x0f)>JSONB_OBJECT ) return 0;
210280 memset(&s, 0, sizeof(s));
210281 s.aBlob = (u8*)aBlob;
210282 s.nBlob = nBlob;
210283 n = jsonbPayloadSize(&s, 0, &sz);
210284 if( n==0 ) return 0;
210285 if( sz+n!=(u32)nBlob ) return 0;
210286 if( (aBlob[0] & 0x0f)<=JSONB_FALSE && sz>0 ) return 0;
210287 return sz+n==(u32)nBlob;
210288 }
210289
210290 /*
210291 ** Given that a JSONB_ARRAY object starts at offset i, return
210292 ** the number of entries in that array.
210293 */
210294 static u32 jsonbArrayCount(JsonParse *pParse, u32 iRoot){
@@ -210517,11 +210556,25 @@
210517 case 'f': { *piOut = '\f'; return 2; }
210518 case 'n': { *piOut = '\n'; return 2; }
210519 case 'r': { *piOut = '\r'; return 2; }
210520 case 't': { *piOut = '\t'; return 2; }
210521 case 'v': { *piOut = '\v'; return 2; }
210522 case '0': { *piOut = 0; return 2; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
210523 case '\'':
210524 case '"':
210525 case '/':
210526 case '\\':{ *piOut = z[1]; return 2; }
210527 case 'x': {
@@ -211112,14 +211165,11 @@
211112 pParse->aBlob = aNull;
211113 pParse->nBlob = 1;
211114 return 0;
211115 }
211116 case SQLITE_BLOB: {
211117 if( jsonFuncArgMightBeBinary(pArg) ){
211118 pParse->aBlob = (u8*)sqlite3_value_blob(pArg);
211119 pParse->nBlob = sqlite3_value_bytes(pArg);
211120 }else{
211121 sqlite3_result_error(ctx, "JSON cannot hold BLOB values", -1);
211122 return 1;
211123 }
211124 break;
211125 }
@@ -211266,31 +211316,50 @@
211266 }
211267
211268 /*
211269 ** If pArg is a blob that seems like a JSONB blob, then initialize
211270 ** p to point to that JSONB and return TRUE. If pArg does not seem like
211271 ** a JSONB blob, then return FALSE;
211272 **
211273 ** This routine is only called if it is already known that pArg is a
211274 ** blob. The only open question is whether or not the blob appears
211275 ** to be a JSONB blob.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
211276 */
211277 static int jsonArgIsJsonb(sqlite3_value *pArg, JsonParse *p){
211278 u32 n, sz = 0;
 
 
211279 p->aBlob = (u8*)sqlite3_value_blob(pArg);
211280 p->nBlob = (u32)sqlite3_value_bytes(pArg);
211281 if( p->nBlob==0 ){
211282 p->aBlob = 0;
211283 return 0;
211284 }
211285 if( NEVER(p->aBlob==0) ){
211286 return 0;
211287 }
211288 if( (p->aBlob[0] & 0x0f)<=JSONB_OBJECT
211289 && (n = jsonbPayloadSize(p, 0, &sz))>0
211290 && sz+n==p->nBlob
211291 && ((p->aBlob[0] & 0x0f)>JSONB_FALSE || sz==0)
 
 
 
211292 ){
211293 return 1;
211294 }
211295 p->aBlob = 0;
211296 p->nBlob = 0;
@@ -212379,25 +212448,21 @@
212379 sqlite3_result_int(ctx, 0);
212380 #endif
212381 return;
212382 }
212383 case SQLITE_BLOB: {
212384 if( jsonFuncArgMightBeBinary(argv[0]) ){
 
 
212385 if( flags & 0x04 ){
212386 /* Superficial checking only - accomplished by the
212387 ** jsonFuncArgMightBeBinary() call above. */
212388 res = 1;
212389 }else if( flags & 0x08 ){
212390 /* Strict checking. Check by translating BLOB->TEXT->BLOB. If
212391 ** no errors occur, call that a "strict check". */
212392 JsonParse px;
212393 u32 iErr;
212394 memset(&px, 0, sizeof(px));
212395 px.aBlob = (u8*)sqlite3_value_blob(argv[0]);
212396 px.nBlob = sqlite3_value_bytes(argv[0]);
212397 iErr = jsonbValidityCheck(&px, 0, px.nBlob, 1);
212398 res = iErr==0;
212399 }
212400 break;
212401 }
212402 /* Fall through into interpreting the input as text. See note
212403 ** above at tag-20240123-a. */
@@ -212451,13 +212516,11 @@
212451
212452 assert( argc==1 );
212453 UNUSED_PARAMETER(argc);
212454 memset(&s, 0, sizeof(s));
212455 s.db = sqlite3_context_db_handle(ctx);
212456 if( jsonFuncArgMightBeBinary(argv[0]) ){
212457 s.aBlob = (u8*)sqlite3_value_blob(argv[0]);
212458 s.nBlob = sqlite3_value_bytes(argv[0]);
212459 iErrPos = (i64)jsonbValidityCheck(&s, 0, s.nBlob, 1);
212460 }else{
212461 s.zJson = (char*)sqlite3_value_text(argv[0]);
212462 if( s.zJson==0 ) return; /* NULL input or OOM */
212463 s.nJson = sqlite3_value_bytes(argv[0]);
@@ -213138,13 +213201,12 @@
213138 jsonEachCursorReset(p);
213139 if( idxNum==0 ) return SQLITE_OK;
213140 memset(&p->sParse, 0, sizeof(p->sParse));
213141 p->sParse.nJPRef = 1;
213142 p->sParse.db = p->db;
213143 if( jsonFuncArgMightBeBinary(argv[0]) ){
213144 p->sParse.nBlob = sqlite3_value_bytes(argv[0]);
213145 p->sParse.aBlob = (u8*)sqlite3_value_blob(argv[0]);
213146 }else{
213147 p->sParse.zJson = (char*)sqlite3_value_text(argv[0]);
213148 p->sParse.nJson = sqlite3_value_bytes(argv[0]);
213149 if( p->sParse.zJson==0 ){
213150 p->i = p->iEnd = 0;
@@ -257213,11 +257275,11 @@
257213 int nArg, /* Number of args */
257214 sqlite3_value **apUnused /* Function arguments */
257215 ){
257216 assert( nArg==0 );
257217 UNUSED_PARAM2(nArg, apUnused);
257218 sqlite3_result_text(pCtx, "fts5: 2025-04-15 21:59:38 d22475b81c4e26ccc50f3b5626d43b32f7a2de34e5a764539554665bdda735d5", -1, SQLITE_TRANSIENT);
257219 }
257220
257221 /*
257222 ** Implementation of fts5_locale(LOCALE, TEXT) function.
257223 **
257224
--- extsrc/sqlite3.c
+++ extsrc/sqlite3.c
@@ -16,11 +16,11 @@
16 ** if you want a wrapper to interface SQLite with your choice of programming
17 ** language. The code for the "sqlite3" command-line shell is also in a
18 ** separate file. This file contains only code for the core SQLite library.
19 **
20 ** The content in this amalgamation comes from Fossil check-in
21 ** 336ceeccc6f85bd78f4a26648af7edf9056d with changes in files:
22 **
23 **
24 */
25 #ifndef SQLITE_AMALGAMATION
26 #define SQLITE_CORE 1
@@ -465,11 +465,11 @@
465 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
466 ** [sqlite_version()] and [sqlite_source_id()].
467 */
468 #define SQLITE_VERSION "3.50.0"
469 #define SQLITE_VERSION_NUMBER 3050000
470 #define SQLITE_SOURCE_ID "2025-05-15 11:20:54 336ceeccc6f85bd78f4a26648af7edf9056d569a767b4120f125a02b2090a349"
471
472 /*
473 ** CAPI3REF: Run-Time Library Version Numbers
474 ** KEYWORDS: sqlite3_version sqlite3_sourceid
475 **
@@ -11872,13 +11872,14 @@
11872 ** This may appear to have some counter-intuitive effects if a single row
11873 ** is written to more than once during a session. For example, if a row
11874 ** is inserted while a session object is enabled, then later deleted while
11875 ** the same session object is disabled, no INSERT record will appear in the
11876 ** changeset, even though the delete took place while the session was disabled.
11877 ** Or, if one field of a row is updated while a session is enabled, and
11878 ** then another field of the same row is updated while the session is disabled,
11879 ** the resulting changeset will contain an UPDATE change that updates both
11880 ** fields.
11881 */
11882 SQLITE_API int sqlite3session_changeset(
11883 sqlite3_session *pSession, /* Session object */
11884 int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */
11885 void **ppChangeset /* OUT: Buffer containing changeset */
@@ -12083,11 +12084,11 @@
12084 ** CAPI3REF: Flags for sqlite3changeset_start_v2
12085 **
12086 ** The following flags may passed via the 4th parameter to
12087 ** [sqlite3changeset_start_v2] and [sqlite3changeset_start_v2_strm]:
12088 **
12089 ** <dt>SQLITE_CHANGESETSTART_INVERT <dd>
12090 ** Invert the changeset while iterating through it. This is equivalent to
12091 ** inverting a changeset using sqlite3changeset_invert() before applying it.
12092 ** It is an error to specify this flag with a patchset.
12093 */
12094 #define SQLITE_CHANGESETSTART_INVERT 0x0002
@@ -19160,11 +19161,10 @@
19161 unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */
19162 unsigned isResized:1; /* True if resizeIndexObject() has been called */
19163 unsigned isCovering:1; /* True if this is a covering index */
19164 unsigned noSkipScan:1; /* Do not try to use skip-scan if true */
19165 unsigned hasStat1:1; /* aiRowLogEst values come from sqlite_stat1 */
 
19166 unsigned bNoQuery:1; /* Do not use this index to optimize queries */
19167 unsigned bAscKeyBug:1; /* True if the bba7b69f9849b5bf bug applies */
19168 unsigned bIdxRowid:1; /* One or more of the index keys is the ROWID */
19169 unsigned bHasVCol:1; /* Index references one or more VIRTUAL columns */
19170 unsigned bHasExpr:1; /* Index contains an expression, either a literal
@@ -22424,10 +22424,13 @@
22424 #ifdef SQLITE_BITMASK_TYPE
22425 "BITMASK_TYPE=" CTIMEOPT_VAL(SQLITE_BITMASK_TYPE),
22426 #endif
22427 #ifdef SQLITE_BUG_COMPATIBLE_20160819
22428 "BUG_COMPATIBLE_20160819",
22429 #endif
22430 #ifdef SQLITE_BUG_COMPATIBLE_20250510
22431 "BUG_COMPATIBLE_20250510",
22432 #endif
22433 #ifdef SQLITE_CASE_SENSITIVE_LIKE
22434 "CASE_SENSITIVE_LIKE",
22435 #endif
22436 #ifdef SQLITE_CHECK_PAGES
@@ -32987,10 +32990,19 @@
32990 va_end(ap);
32991 zBuf[acc.nChar] = 0;
32992 return zBuf;
32993 }
32994
32995 /* Maximum size of an sqlite3_log() message. */
32996 #if defined(SQLITE_MAX_LOG_MESSAGE)
32997 /* Leave the definition as supplied */
32998 #elif SQLITE_PRINT_BUF_SIZE*10>10000
32999 # define SQLITE_MAX_LOG_MESSAGE 10000
33000 #else
33001 # define SQLITE_MAX_LOG_MESSAGE (SQLITE_PRINT_BUF_SIZE*10)
33002 #endif
33003
33004 /*
33005 ** This is the routine that actually formats the sqlite3_log() message.
33006 ** We house it in a separate routine from sqlite3_log() to avoid using
33007 ** stack space on small-stack systems when logging is disabled.
33008 **
@@ -33003,11 +33015,11 @@
33015 ** Care must be taken that any sqlite3_log() calls that occur while the
33016 ** memory mutex is held do not use these mechanisms.
33017 */
33018 static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){
33019 StrAccum acc; /* String accumulator */
33020 char zMsg[SQLITE_MAX_LOG_MESSAGE]; /* Complete log message */
33021
33022 sqlite3StrAccumInit(&acc, 0, zMsg, sizeof(zMsg), 0);
33023 sqlite3_str_vappendf(&acc, zFormat, ap);
33024 sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode,
33025 sqlite3StrAccumFinish(&acc));
@@ -87262,10 +87274,13 @@
87274 ** into register iDest, then add the OPFLAG_TYPEOFARG flag to that
87275 ** opcode.
87276 */
87277 SQLITE_PRIVATE void sqlite3VdbeTypeofColumn(Vdbe *p, int iDest){
87278 VdbeOp *pOp = sqlite3VdbeGetLastOp(p);
87279 #ifdef SQLITE_DEBUG
87280 while( pOp->opcode==OP_ReleaseReg ) pOp--;
87281 #endif
87282 if( pOp->p3==iDest && pOp->opcode==OP_Column ){
87283 pOp->p5 |= OPFLAG_TYPEOFARG;
87284 }
87285 }
87286
@@ -95716,11 +95731,11 @@
95731 }
95732 }else{
95733 sqlite3VdbeError(p, "%s", pOp->p4.z);
95734 }
95735 pcx = (int)(pOp - aOp);
95736 sqlite3_log(pOp->p1, "abort at %d: %s; [%s]", pcx, p->zErrMsg, p->zSql);
95737 }
95738 rc = sqlite3VdbeHalt(p);
95739 assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR );
95740 if( rc==SQLITE_BUSY ){
95741 p->rc = SQLITE_BUSY;
@@ -97042,11 +97057,11 @@
97057 pOut->u.i = ~sqlite3VdbeIntValue(pIn1);
97058 }
97059 break;
97060 }
97061
97062 /* Opcode: Once P1 P2 P3 * *
97063 **
97064 ** Fall through to the next instruction the first time this opcode is
97065 ** encountered on each invocation of the byte-code program. Jump to P2
97066 ** on the second and all subsequent encounters during the same invocation.
97067 **
@@ -97058,10 +97073,16 @@
97073 **
97074 ** For subprograms, there is a bitmask in the VdbeFrame that determines
97075 ** whether or not the jump should be taken. The bitmask is necessary
97076 ** because the self-altering code trick does not work for recursive
97077 ** triggers.
97078 **
97079 ** The P3 operand is not used directly by this opcode. However P3 is
97080 ** used by the code generator as follows: If this opcode is the start
97081 ** of a subroutine and that subroutine uses a Bloom filter, then P3 will
97082 ** be the register that holds that Bloom filter. See tag-202407032019
97083 ** in the source code for implementation details.
97084 */
97085 case OP_Once: { /* jump */
97086 u32 iAddr; /* Address of this instruction */
97087 assert( p->aOp[0].opcode==OP_Init );
97088 if( p->pFrame ){
@@ -98103,10 +98124,11 @@
98124 }
98125 }else{
98126 zHdr += sqlite3PutVarint(zHdr, serial_type);
98127 if( pRec->n ){
98128 assert( pRec->z!=0 );
98129 assert( pRec->z!=(const char*)sqlite3CtypeMap );
98130 memcpy(zPayload, pRec->z, pRec->n);
98131 zPayload += pRec->n;
98132 }
98133 }
98134 if( pRec==pLast ) break;
@@ -103551,12 +103573,12 @@
103573 sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc));
103574 }
103575 p->rc = rc;
103576 sqlite3SystemError(db, rc);
103577 testcase( sqlite3GlobalConfig.xLog!=0 );
103578 sqlite3_log(rc, "statement aborts at %d: %s; [%s]",
103579 (int)(pOp - aOp), p->zErrMsg, p->zSql);
103580 if( p->eVdbeState==VDBE_RUN_STATE ) sqlite3VdbeHalt(p);
103581 if( rc==SQLITE_IOERR_NOMEM ) sqlite3OomFault(db);
103582 if( rc==SQLITE_CORRUPT && db->autoCommit==0 ){
103583 db->flags |= SQLITE_CorruptRdOnly;
103584 }
@@ -109287,17 +109309,16 @@
109309 /* Clearly non-deterministic functions like random(), but also
109310 ** date/time functions that use 'now', and other functions like
109311 ** sqlite_version() that might change over time cannot be used
109312 ** in an index or generated column. Curiously, they can be used
109313 ** in a CHECK constraint. SQLServer, MySQL, and PostgreSQL all
109314 ** allow this. */
109315 sqlite3ResolveNotValid(pParse, pNC, "non-deterministic functions",
109316 NC_IdxExpr|NC_PartIdx|NC_GenCol, 0, pExpr);
109317 }else{
109318 assert( (NC_SelfRef & 0xff)==NC_SelfRef ); /* Must fit in 8 bits */
109319 pExpr->op2 = pNC->ncFlags & NC_SelfRef;
 
109320 }
109321 if( (pDef->funcFlags & SQLITE_FUNC_INTERNAL)!=0
109322 && pParse->nested==0
109323 && (pParse->db->mDbFlags & DBFLAG_InternalFunc)==0
109324 ){
@@ -109309,10 +109330,11 @@
109330 pDef = 0;
109331 }else
109332 if( (pDef->funcFlags & (SQLITE_FUNC_DIRECT|SQLITE_FUNC_UNSAFE))!=0
109333 && !IN_RENAME_OBJECT
109334 ){
109335 if( pNC->ncFlags & NC_FromDDL ) ExprSetProperty(pExpr, EP_FromDDL);
109336 sqlite3ExprFunctionUsable(pParse, pExpr, pDef);
109337 }
109338 }
109339
109340 if( 0==IN_RENAME_OBJECT ){
@@ -114022,15 +114044,16 @@
114044 pCopy = sqlite3SelectDup(pParse->db, pSelect, 0);
114045 rc = pParse->db->mallocFailed ? 1 :sqlite3Select(pParse, pCopy, &dest);
114046 sqlite3SelectDelete(pParse->db, pCopy);
114047 sqlite3DbFree(pParse->db, dest.zAffSdst);
114048 if( addrBloom ){
114049 /* Remember that location of the Bloom filter in the P3 operand
114050 ** of the OP_Once that began this subroutine. tag-202407032019 */
114051 sqlite3VdbeGetOp(v, addrOnce)->p3 = dest.iSDParm2;
114052 if( dest.iSDParm2==0 ){
114053 /* If the Bloom filter won't actually be used, keep it small */
114054 sqlite3VdbeGetOp(v, addrBloom)->p1 = 10;
 
114055 }
114056 }
114057 if( rc ){
114058 sqlite3KeyInfoUnref(pKeyInfo);
114059 return;
@@ -114473,11 +114496,11 @@
114496 if( destIfFalse==destIfNull ){
114497 /* Combine Step 3 and Step 5 into a single opcode */
114498 if( ExprHasProperty(pExpr, EP_Subrtn) ){
114499 const VdbeOp *pOp = sqlite3VdbeGetOp(v, pExpr->y.sub.iAddr);
114500 assert( pOp->opcode==OP_Once || pParse->nErr );
114501 if( pOp->opcode==OP_Once && pOp->p3>0 ){ /* tag-202407032019 */
114502 assert( OptimizationEnabled(pParse->db, SQLITE_BloomFilter) );
114503 sqlite3VdbeAddOp4Int(v, OP_Filter, pOp->p3, destIfFalse,
114504 rLhs, nVector); VdbeCoverage(v);
114505 }
114506 }
@@ -116322,15 +116345,15 @@
116345 case TK_ISNULL:
116346 case TK_NOTNULL: {
116347 assert( TK_ISNULL==OP_IsNull ); testcase( op==TK_ISNULL );
116348 assert( TK_NOTNULL==OP_NotNull ); testcase( op==TK_NOTNULL );
116349 r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
116350 assert( regFree1==0 || regFree1==r1 );
116351 if( regFree1 ) sqlite3VdbeTypeofColumn(v, r1);
116352 sqlite3VdbeAddOp2(v, op, r1, dest);
116353 VdbeCoverageIf(v, op==TK_ISNULL);
116354 VdbeCoverageIf(v, op==TK_NOTNULL);
 
116355 break;
116356 }
116357 case TK_BETWEEN: {
116358 testcase( jumpIfNull==0 );
116359 exprCodeBetween(pParse, pExpr, dest, sqlite3ExprIfTrue, jumpIfNull);
@@ -116497,15 +116520,15 @@
116520 break;
116521 }
116522 case TK_ISNULL:
116523 case TK_NOTNULL: {
116524 r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
116525 assert( regFree1==0 || regFree1==r1 );
116526 if( regFree1 ) sqlite3VdbeTypeofColumn(v, r1);
116527 sqlite3VdbeAddOp2(v, op, r1, dest);
116528 testcase( op==TK_ISNULL ); VdbeCoverageIf(v, op==TK_ISNULL);
116529 testcase( op==TK_NOTNULL ); VdbeCoverageIf(v, op==TK_NOTNULL);
 
116530 break;
116531 }
116532 case TK_BETWEEN: {
116533 testcase( jumpIfNull==0 );
116534 exprCodeBetween(pParse, pExpr, dest, sqlite3ExprIfFalse, jumpIfNull);
@@ -121683,20 +121706,10 @@
121706 }
121707 #endif
121708 while( z[0]!=0 && z[0]!=' ' ) z++;
121709 while( z[0]==' ' ) z++;
121710 }
 
 
 
 
 
 
 
 
 
 
121711 }
121712 }
121713
121714 /*
121715 ** This callback is invoked once for each index when reading the
@@ -124091,11 +124104,11 @@
124104 */
124105 SQLITE_PRIVATE int sqlite3TableColumnToIndex(Index *pIdx, int iCol){
124106 int i;
124107 i16 iCol16;
124108 assert( iCol>=(-1) && iCol<=SQLITE_MAX_COLUMN );
124109 assert( pIdx->nColumn<=SQLITE_MAX_COLUMN+1 );
124110 iCol16 = iCol;
124111 for(i=0; i<pIdx->nColumn; i++){
124112 if( iCol16==pIdx->aiColumn[i] ){
124113 return i;
124114 }
@@ -167620,15 +167633,12 @@
167633 opMask = WO_LT|WO_LE;
167634 }else{
167635 assert( pNew->u.btree.nBtm==0 );
167636 opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE|WO_ISNULL|WO_IS;
167637 }
167638 if( pProbe->bUnordered ){
167639 opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE);
 
 
 
167640 }
167641
167642 assert( pNew->u.btree.nEq<pProbe->nColumn );
167643 assert( pNew->u.btree.nEq<pProbe->nKeyCol
167644 || pProbe->idxType!=SQLITE_IDXTYPE_PRIMARYKEY );
@@ -168561,11 +168571,11 @@
168571 }
168572 }else if( m==0
168573 && (HasRowid(pTab) || pWInfo->pSelect!=0 || sqlite3FaultSim(700))
168574 ){
168575 WHERETRACE(0x200,
168576 ("-> %s is a covering index according to bitmasks\n",
168577 pProbe->zName, m==0 ? "is" : "is not"));
168578 pNew->wsFlags = WHERE_IDX_ONLY | WHERE_INDEXED;
168579 }
168580 }
168581
@@ -207968,60 +207978,113 @@
207978 ** Growing our own isspace() routine this way is twice as fast as
207979 ** the library isspace() function, resulting in a 7% overall performance
207980 ** increase for the text-JSON parser. (Ubuntu14.10 gcc 4.8.4 x64 with -Os).
207981 */
207982 static const char jsonIsSpace[] = {
207983 #ifdef SQLITE_ASCII
207984 /*0 1 2 3 4 5 6 7 8 9 a b c d e f */
207985 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, /* 0 */
207986 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1 */
207987 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2 */
207988 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 3 */
207989 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4 */
207990 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 5 */
207991 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6 */
207992 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7 */
207993
207994 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 8 */
207995 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9 */
207996 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* a */
207997 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* b */
207998 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* c */
207999 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* d */
208000 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* e */
208001 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* f */
208002 #endif
208003 #ifdef SQLITE_EBCDIC
208004 /*0 1 2 3 4 5 6 7 8 9 a b c d e f */
208005 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, /* 0 */
208006 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1 */
208007 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2 */
208008 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 3 */
208009 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4 */
208010 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 5 */
208011 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6 */
208012 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7 */
208013
208014 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 8 */
208015 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9 */
208016 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* a */
208017 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* b */
208018 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* c */
208019 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* d */
208020 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* e */
208021 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* f */
208022 #endif
208023
208024 };
208025 #define jsonIsspace(x) (jsonIsSpace[(unsigned char)x])
208026
208027 /*
208028 ** The set of all space characters recognized by jsonIsspace().
208029 ** Useful as the second argument to strspn().
208030 */
208031 #ifdef SQLITE_ASCII
208032 static const char jsonSpaces[] = "\011\012\015\040";
208033 #endif
208034 #ifdef SQLITE_EBCDIC
208035 static const char jsonSpaces[] = "\005\045\015\100";
208036 #endif
208037
208038
208039 /*
208040 ** Characters that are special to JSON. Control characters,
208041 ** '"' and '\\' and '\''. Actually, '\'' is not special to
208042 ** canonical JSON, but it is special in JSON-5, so we include
208043 ** it in the set of special characters.
208044 */
208045 static const char jsonIsOk[256] = {
208046 #ifdef SQLITE_ASCII
208047 /*0 1 2 3 4 5 6 7 8 9 a b c d e f */
208048 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0 */
208049 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1 */
208050 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, /* 2 */
208051 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 3 */
208052 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4 */
208053 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, /* 5 */
208054 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6 */
208055 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 7 */
208056
208057 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 8 */
208058 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 9 */
208059 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* a */
208060 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* b */
208061 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* c */
208062 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* d */
208063 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* e */
208064 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 /* f */
208065 #endif
208066 #ifdef SQLITE_EBCDIC
208067 /*0 1 2 3 4 5 6 7 8 9 a b c d e f */
208068 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0 */
208069 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1 */
208070 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2 */
208071 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, /* 3 */
208072 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4 */
208073 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 5 */
208074 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6 */
208075 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, /* 7 */
208076
208077 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 8 */
208078 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 9 */
208079 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* a */
208080 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* b */
208081 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* c */
208082 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* d */
208083 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* e */
208084 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 /* f */
208085 #endif
208086 };
208087
208088 /* Objects */
208089 typedef struct JsonCache JsonCache;
208090 typedef struct JsonString JsonString;
@@ -208162,11 +208225,11 @@
208225
208226 /**************************************************************************
208227 ** Forward references
208228 **************************************************************************/
208229 static void jsonReturnStringAsBlob(JsonString*);
208230 static int jsonArgIsJsonb(sqlite3_value *pJson, JsonParse *p);
208231 static u32 jsonTranslateBlobToText(const JsonParse*,u32,JsonString*);
208232 static void jsonReturnParse(sqlite3_context*,JsonParse*);
208233 static JsonParse *jsonParseFuncArg(sqlite3_context*,sqlite3_value*,u32);
208234 static void jsonParseFree(JsonParse*);
208235 static u32 jsonbPayloadSize(const JsonParse*, u32, u32*);
@@ -208580,15 +208643,13 @@
208643 jsonAppendString(p, z, n);
208644 }
208645 break;
208646 }
208647 default: {
208648 JsonParse px;
208649 memset(&px, 0, sizeof(px));
208650 if( jsonArgIsJsonb(pValue, &px) ){
 
 
208651 jsonTranslateBlobToText(&px, 0, p);
208652 }else if( p->eErr==0 ){
208653 sqlite3_result_error(p->pCtx, "JSON cannot hold BLOB values", -1);
208654 p->eErr = JSTRING_ERR;
208655 jsonStringReset(p);
@@ -209522,11 +209583,16 @@
209583 c = z[++j];
209584 if( c=='"' || c=='\\' || c=='/' || c=='b' || c=='f'
209585 || c=='n' || c=='r' || c=='t'
209586 || (c=='u' && jsonIs4Hex(&z[j+1])) ){
209587 if( opcode==JSONB_TEXT ) opcode = JSONB_TEXTJ;
209588 }else if( c=='\'' || c=='v' || c=='\n'
209589 #ifdef SQLITE_BUG_COMPATIBLE_20250510
209590 || (c=='0') /* Legacy bug compatible */
209591 #else
209592 || (c=='0' && !sqlite3Isdigit(z[j+1])) /* Correct implementation */
209593 #endif
209594 || (0xe2==(u8)c && 0x80==(u8)z[j+1]
209595 && (0xa8==(u8)z[j+2] || 0xa9==(u8)z[j+2]))
209596 || (c=='x' && jsonIs2Hex(&z[j+1])) ){
209597 opcode = JSONB_TEXT5;
209598 pParse->hasNonstd = 1;
@@ -209909,11 +209975,11 @@
209975 || pParse->aBlob[i+4]!=0
209976 ){
209977 *pSz = 0;
209978 return 0;
209979 }
209980 sz = ((u32)pParse->aBlob[i+5]<<24) + (pParse->aBlob[i+6]<<16) +
209981 (pParse->aBlob[i+7]<<8) + pParse->aBlob[i+8];
209982 n = 9;
209983 }
209984 if( (i64)i+sz+n > pParse->nBlob
209985 && (i64)i+sz+n > pParse->nBlob-pParse->delta
@@ -210258,37 +210324,10 @@
210324 }
210325 }
210326 return i;
210327 }
210328
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
210329 /*
210330 ** Given that a JSONB_ARRAY object starts at offset i, return
210331 ** the number of entries in that array.
210332 */
210333 static u32 jsonbArrayCount(JsonParse *pParse, u32 iRoot){
@@ -210517,11 +210556,25 @@
210556 case 'f': { *piOut = '\f'; return 2; }
210557 case 'n': { *piOut = '\n'; return 2; }
210558 case 'r': { *piOut = '\r'; return 2; }
210559 case 't': { *piOut = '\t'; return 2; }
210560 case 'v': { *piOut = '\v'; return 2; }
210561 case '0': {
210562 /* JSON5 requires that the \0 escape not be followed by a digit.
210563 ** But SQLite did not enforce this restriction in versions 3.42.0
210564 ** through 3.49.2. That was a bug. But some applications might have
210565 ** come to depend on that bug. Use the SQLITE_BUG_COMPATIBLE_20250510
210566 ** option to restore the old buggy behavior. */
210567 #ifdef SQLITE_BUG_COMPATIBLE_20250510
210568 /* Legacy bug-compatible behavior */
210569 *piOut = 0;
210570 #else
210571 /* Correct behavior */
210572 *piOut = (n>2 && sqlite3Isdigit(z[2])) ? JSON_INVALID_CHAR : 0;
210573 #endif
210574 return 2;
210575 }
210576 case '\'':
210577 case '"':
210578 case '/':
210579 case '\\':{ *piOut = z[1]; return 2; }
210580 case 'x': {
@@ -211112,14 +211165,11 @@
211165 pParse->aBlob = aNull;
211166 pParse->nBlob = 1;
211167 return 0;
211168 }
211169 case SQLITE_BLOB: {
211170 if( !jsonArgIsJsonb(pArg, pParse) ){
 
 
 
211171 sqlite3_result_error(ctx, "JSON cannot hold BLOB values", -1);
211172 return 1;
211173 }
211174 break;
211175 }
@@ -211266,31 +211316,50 @@
211316 }
211317
211318 /*
211319 ** If pArg is a blob that seems like a JSONB blob, then initialize
211320 ** p to point to that JSONB and return TRUE. If pArg does not seem like
211321 ** a JSONB blob, then return FALSE.
211322 **
211323 ** For small BLOBs (having no more than 7 bytes of payload) a full
211324 ** validity check is done. So for small BLOBs this routine only returns
211325 ** true if the value is guaranteed to be a valid JSONB. For larger BLOBs
211326 ** (8 byte or more of payload) only the size of the outermost element is
211327 ** checked to verify that the BLOB is superficially valid JSONB.
211328 **
211329 ** A full JSONB validation is done on smaller BLOBs because those BLOBs might
211330 ** also be text JSON that has been incorrectly cast into a BLOB.
211331 ** (See tag-20240123-a and https://sqlite.org/forum/forumpost/012136abd5)
211332 ** If the BLOB is 9 bytes are larger, then it is not possible for the
211333 ** superficial size check done here to pass if the input is really text
211334 ** JSON so we do not need to look deeper in that case.
211335 **
211336 ** Why we only need to do full JSONB validation for smaller BLOBs:
211337 **
211338 ** The first byte of valid JSON text must be one of: '{', '[', '"', ' ', '\n',
211339 ** '\r', '\t', '-', or a digit '0' through '9'. Of these, only a subset
211340 ** can also be the first byte of JSONB: '{', '[', and digits '3'
211341 ** through '9'. In every one of those cases, the payload size is 7 bytes
211342 ** or less. So if we do full JSONB validation for every BLOB where the
211343 ** payload is less than 7 bytes, we will never get a false positive for
211344 ** JSONB on an input that is really text JSON.
211345 */
211346 static int jsonArgIsJsonb(sqlite3_value *pArg, JsonParse *p){
211347 u32 n, sz = 0;
211348 u8 c;
211349 if( sqlite3_value_type(pArg)!=SQLITE_BLOB ) return 0;
211350 p->aBlob = (u8*)sqlite3_value_blob(pArg);
211351 p->nBlob = (u32)sqlite3_value_bytes(pArg);
211352 if( p->nBlob>0
211353 && ALWAYS(p->aBlob!=0)
211354 && ((c = p->aBlob[0]) & 0x0f)<=JSONB_OBJECT
 
 
 
 
 
211355 && (n = jsonbPayloadSize(p, 0, &sz))>0
211356 && sz+n==p->nBlob
211357 && ((c & 0x0f)>JSONB_FALSE || sz==0)
211358 && (sz>7
211359 || (c!=0x7b && c!=0x5b && !sqlite3Isdigit(c))
211360 || jsonbValidityCheck(p, 0, p->nBlob, 1)==0)
211361 ){
211362 return 1;
211363 }
211364 p->aBlob = 0;
211365 p->nBlob = 0;
@@ -212379,25 +212448,21 @@
212448 sqlite3_result_int(ctx, 0);
212449 #endif
212450 return;
212451 }
212452 case SQLITE_BLOB: {
212453 JsonParse py;
212454 memset(&py, 0, sizeof(py));
212455 if( jsonArgIsJsonb(argv[0], &py) ){
212456 if( flags & 0x04 ){
212457 /* Superficial checking only - accomplished by the
212458 ** jsonArgIsJsonb() call above. */
212459 res = 1;
212460 }else if( flags & 0x08 ){
212461 /* Strict checking. Check by translating BLOB->TEXT->BLOB. If
212462 ** no errors occur, call that a "strict check". */
212463 res = 0==jsonbValidityCheck(&py, 0, py.nBlob, 1);
 
 
 
 
 
 
212464 }
212465 break;
212466 }
212467 /* Fall through into interpreting the input as text. See note
212468 ** above at tag-20240123-a. */
@@ -212451,13 +212516,11 @@
212516
212517 assert( argc==1 );
212518 UNUSED_PARAMETER(argc);
212519 memset(&s, 0, sizeof(s));
212520 s.db = sqlite3_context_db_handle(ctx);
212521 if( jsonArgIsJsonb(argv[0], &s) ){
 
 
212522 iErrPos = (i64)jsonbValidityCheck(&s, 0, s.nBlob, 1);
212523 }else{
212524 s.zJson = (char*)sqlite3_value_text(argv[0]);
212525 if( s.zJson==0 ) return; /* NULL input or OOM */
212526 s.nJson = sqlite3_value_bytes(argv[0]);
@@ -213138,13 +213201,12 @@
213201 jsonEachCursorReset(p);
213202 if( idxNum==0 ) return SQLITE_OK;
213203 memset(&p->sParse, 0, sizeof(p->sParse));
213204 p->sParse.nJPRef = 1;
213205 p->sParse.db = p->db;
213206 if( jsonArgIsJsonb(argv[0], &p->sParse) ){
213207 /* We have JSONB */
 
213208 }else{
213209 p->sParse.zJson = (char*)sqlite3_value_text(argv[0]);
213210 p->sParse.nJson = sqlite3_value_bytes(argv[0]);
213211 if( p->sParse.zJson==0 ){
213212 p->i = p->iEnd = 0;
@@ -257213,11 +257275,11 @@
257275 int nArg, /* Number of args */
257276 sqlite3_value **apUnused /* Function arguments */
257277 ){
257278 assert( nArg==0 );
257279 UNUSED_PARAM2(nArg, apUnused);
257280 sqlite3_result_text(pCtx, "fts5: 2025-05-15 11:20:54 336ceeccc6f85bd78f4a26648af7edf9056d569a767b4120f125a02b2090a349", -1, SQLITE_TRANSIENT);
257281 }
257282
257283 /*
257284 ** Implementation of fts5_locale(LOCALE, TEXT) function.
257285 **
257286
--- extsrc/sqlite3.h
+++ extsrc/sqlite3.h
@@ -146,11 +146,11 @@
146146
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
147147
** [sqlite_version()] and [sqlite_source_id()].
148148
*/
149149
#define SQLITE_VERSION "3.50.0"
150150
#define SQLITE_VERSION_NUMBER 3050000
151
-#define SQLITE_SOURCE_ID "2025-04-15 21:59:38 d22475b81c4e26ccc50f3b5626d43b32f7a2de34e5a764539554665bdda735d5"
151
+#define SQLITE_SOURCE_ID "2025-05-15 11:20:54 336ceeccc6f85bd78f4a26648af7edf9056d569a767b4120f125a02b2090a349"
152152
153153
/*
154154
** CAPI3REF: Run-Time Library Version Numbers
155155
** KEYWORDS: sqlite3_version sqlite3_sourceid
156156
**
@@ -11553,13 +11553,14 @@
1155311553
** This may appear to have some counter-intuitive effects if a single row
1155411554
** is written to more than once during a session. For example, if a row
1155511555
** is inserted while a session object is enabled, then later deleted while
1155611556
** the same session object is disabled, no INSERT record will appear in the
1155711557
** changeset, even though the delete took place while the session was disabled.
11558
-** Or, if one field of a row is updated while a session is disabled, and
11559
-** another field of the same row is updated while the session is enabled, the
11560
-** resulting changeset will contain an UPDATE change that updates both fields.
11558
+** Or, if one field of a row is updated while a session is enabled, and
11559
+** then another field of the same row is updated while the session is disabled,
11560
+** the resulting changeset will contain an UPDATE change that updates both
11561
+** fields.
1156111562
*/
1156211563
SQLITE_API int sqlite3session_changeset(
1156311564
sqlite3_session *pSession, /* Session object */
1156411565
int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */
1156511566
void **ppChangeset /* OUT: Buffer containing changeset */
@@ -11764,11 +11765,11 @@
1176411765
** CAPI3REF: Flags for sqlite3changeset_start_v2
1176511766
**
1176611767
** The following flags may passed via the 4th parameter to
1176711768
** [sqlite3changeset_start_v2] and [sqlite3changeset_start_v2_strm]:
1176811769
**
11769
-** <dt>SQLITE_CHANGESETAPPLY_INVERT <dd>
11770
+** <dt>SQLITE_CHANGESETSTART_INVERT <dd>
1177011771
** Invert the changeset while iterating through it. This is equivalent to
1177111772
** inverting a changeset using sqlite3changeset_invert() before applying it.
1177211773
** It is an error to specify this flag with a patchset.
1177311774
*/
1177411775
#define SQLITE_CHANGESETSTART_INVERT 0x0002
1177511776
--- extsrc/sqlite3.h
+++ extsrc/sqlite3.h
@@ -146,11 +146,11 @@
146 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
147 ** [sqlite_version()] and [sqlite_source_id()].
148 */
149 #define SQLITE_VERSION "3.50.0"
150 #define SQLITE_VERSION_NUMBER 3050000
151 #define SQLITE_SOURCE_ID "2025-04-15 21:59:38 d22475b81c4e26ccc50f3b5626d43b32f7a2de34e5a764539554665bdda735d5"
152
153 /*
154 ** CAPI3REF: Run-Time Library Version Numbers
155 ** KEYWORDS: sqlite3_version sqlite3_sourceid
156 **
@@ -11553,13 +11553,14 @@
11553 ** This may appear to have some counter-intuitive effects if a single row
11554 ** is written to more than once during a session. For example, if a row
11555 ** is inserted while a session object is enabled, then later deleted while
11556 ** the same session object is disabled, no INSERT record will appear in the
11557 ** changeset, even though the delete took place while the session was disabled.
11558 ** Or, if one field of a row is updated while a session is disabled, and
11559 ** another field of the same row is updated while the session is enabled, the
11560 ** resulting changeset will contain an UPDATE change that updates both fields.
 
11561 */
11562 SQLITE_API int sqlite3session_changeset(
11563 sqlite3_session *pSession, /* Session object */
11564 int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */
11565 void **ppChangeset /* OUT: Buffer containing changeset */
@@ -11764,11 +11765,11 @@
11764 ** CAPI3REF: Flags for sqlite3changeset_start_v2
11765 **
11766 ** The following flags may passed via the 4th parameter to
11767 ** [sqlite3changeset_start_v2] and [sqlite3changeset_start_v2_strm]:
11768 **
11769 ** <dt>SQLITE_CHANGESETAPPLY_INVERT <dd>
11770 ** Invert the changeset while iterating through it. This is equivalent to
11771 ** inverting a changeset using sqlite3changeset_invert() before applying it.
11772 ** It is an error to specify this flag with a patchset.
11773 */
11774 #define SQLITE_CHANGESETSTART_INVERT 0x0002
11775
--- extsrc/sqlite3.h
+++ extsrc/sqlite3.h
@@ -146,11 +146,11 @@
146 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
147 ** [sqlite_version()] and [sqlite_source_id()].
148 */
149 #define SQLITE_VERSION "3.50.0"
150 #define SQLITE_VERSION_NUMBER 3050000
151 #define SQLITE_SOURCE_ID "2025-05-15 11:20:54 336ceeccc6f85bd78f4a26648af7edf9056d569a767b4120f125a02b2090a349"
152
153 /*
154 ** CAPI3REF: Run-Time Library Version Numbers
155 ** KEYWORDS: sqlite3_version sqlite3_sourceid
156 **
@@ -11553,13 +11553,14 @@
11553 ** This may appear to have some counter-intuitive effects if a single row
11554 ** is written to more than once during a session. For example, if a row
11555 ** is inserted while a session object is enabled, then later deleted while
11556 ** the same session object is disabled, no INSERT record will appear in the
11557 ** changeset, even though the delete took place while the session was disabled.
11558 ** Or, if one field of a row is updated while a session is enabled, and
11559 ** then another field of the same row is updated while the session is disabled,
11560 ** the resulting changeset will contain an UPDATE change that updates both
11561 ** fields.
11562 */
11563 SQLITE_API int sqlite3session_changeset(
11564 sqlite3_session *pSession, /* Session object */
11565 int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */
11566 void **ppChangeset /* OUT: Buffer containing changeset */
@@ -11764,11 +11765,11 @@
11765 ** CAPI3REF: Flags for sqlite3changeset_start_v2
11766 **
11767 ** The following flags may passed via the 4th parameter to
11768 ** [sqlite3changeset_start_v2] and [sqlite3changeset_start_v2_strm]:
11769 **
11770 ** <dt>SQLITE_CHANGESETSTART_INVERT <dd>
11771 ** Invert the changeset while iterating through it. This is equivalent to
11772 ** inverting a changeset using sqlite3changeset_invert() before applying it.
11773 ** It is an error to specify this flag with a patchset.
11774 */
11775 #define SQLITE_CHANGESETSTART_INVERT 0x0002
11776
+1 -1
--- src/ajax.c
+++ src/ajax.c
@@ -307,11 +307,11 @@
307307
Blob content = empty_blob;
308308
const char * zRenderMode = 0;
309309
310310
ajax_get_fnci_args( &zFilename, 0 );
311311
312
- if(!ajax_route_bootstrap(1,1)){
312
+ if(!ajax_route_bootstrap(0,1)){
313313
return;
314314
}
315315
if(zFilename==0){
316316
/* The filename is only used for mimetype determination,
317317
** so we can default it... */
318318
--- src/ajax.c
+++ src/ajax.c
@@ -307,11 +307,11 @@
307 Blob content = empty_blob;
308 const char * zRenderMode = 0;
309
310 ajax_get_fnci_args( &zFilename, 0 );
311
312 if(!ajax_route_bootstrap(1,1)){
313 return;
314 }
315 if(zFilename==0){
316 /* The filename is only used for mimetype determination,
317 ** so we can default it... */
318
--- src/ajax.c
+++ src/ajax.c
@@ -307,11 +307,11 @@
307 Blob content = empty_blob;
308 const char * zRenderMode = 0;
309
310 ajax_get_fnci_args( &zFilename, 0 );
311
312 if(!ajax_route_bootstrap(0,1)){
313 return;
314 }
315 if(zFilename==0){
316 /* The filename is only used for mimetype determination,
317 ** so we can default it... */
318
+1 -1
--- src/cgi.c
+++ src/cgi.c
@@ -2661,11 +2661,11 @@
26612661
listen4 = socket(AF_INET, SOCK_STREAM, 0);
26622662
if( listen4>0 ){
26632663
setsockopt(listen4, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
26642664
rc = bind(listen4, (struct sockaddr*)&inaddr4, sizeof(inaddr4));
26652665
if( rc<0 ){
2666
- close(listen6);
2666
+ close(listen4);
26672667
listen4 = -1;
26682668
}
26692669
}
26702670
if( listen4<0 ){
26712671
fossil_fatal("cannot open a listening socket on %s:%d",
26722672
--- src/cgi.c
+++ src/cgi.c
@@ -2661,11 +2661,11 @@
2661 listen4 = socket(AF_INET, SOCK_STREAM, 0);
2662 if( listen4>0 ){
2663 setsockopt(listen4, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
2664 rc = bind(listen4, (struct sockaddr*)&inaddr4, sizeof(inaddr4));
2665 if( rc<0 ){
2666 close(listen6);
2667 listen4 = -1;
2668 }
2669 }
2670 if( listen4<0 ){
2671 fossil_fatal("cannot open a listening socket on %s:%d",
2672
--- src/cgi.c
+++ src/cgi.c
@@ -2661,11 +2661,11 @@
2661 listen4 = socket(AF_INET, SOCK_STREAM, 0);
2662 if( listen4>0 ){
2663 setsockopt(listen4, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
2664 rc = bind(listen4, (struct sockaddr*)&inaddr4, sizeof(inaddr4));
2665 if( rc<0 ){
2666 close(listen4);
2667 listen4 = -1;
2668 }
2669 }
2670 if( listen4<0 ){
2671 fossil_fatal("cannot open a listening socket on %s:%d",
2672
+4 -2
--- src/clone.c
+++ src/clone.c
@@ -430,12 +430,14 @@
430430
const char *zNm = db_get("short-project-name","download");
431431
char *zUrl = href("%R/zip/%t/%t.zip", zDLTag, zNm);
432432
@ <p>ZIP Archive: %z(zUrl)%h(zNm).zip</a>
433433
zUrl = href("%R/tarball/%t/%t.tar.gz", zDLTag, zNm);
434434
@ <p>Tarball: %z(zUrl)%h(zNm).tar.gz</a>
435
- zUrl = href("%R/sqlar/%t/%t.sqlar", zDLTag, zNm);
436
- @ <p>SQLite Archive: %z(zUrl)%h(zNm).sqlar</a>
435
+ if( g.zLogin!=0 ){
436
+ zUrl = href("%R/sqlar/%t/%t.sqlar", zDLTag, zNm);
437
+ @ <p>SQLite Archive: %z(zUrl)%h(zNm).sqlar</a>
438
+ }
437439
}
438440
if( !g.perm.Clone ){
439441
@ <p>You are not authorized to clone this repository.
440442
if( g.zLogin==0 || g.zLogin[0]==0 ){
441443
@ Maybe you would be able to clone if you
442444
--- src/clone.c
+++ src/clone.c
@@ -430,12 +430,14 @@
430 const char *zNm = db_get("short-project-name","download");
431 char *zUrl = href("%R/zip/%t/%t.zip", zDLTag, zNm);
432 @ <p>ZIP Archive: %z(zUrl)%h(zNm).zip</a>
433 zUrl = href("%R/tarball/%t/%t.tar.gz", zDLTag, zNm);
434 @ <p>Tarball: %z(zUrl)%h(zNm).tar.gz</a>
435 zUrl = href("%R/sqlar/%t/%t.sqlar", zDLTag, zNm);
436 @ <p>SQLite Archive: %z(zUrl)%h(zNm).sqlar</a>
 
 
437 }
438 if( !g.perm.Clone ){
439 @ <p>You are not authorized to clone this repository.
440 if( g.zLogin==0 || g.zLogin[0]==0 ){
441 @ Maybe you would be able to clone if you
442
--- src/clone.c
+++ src/clone.c
@@ -430,12 +430,14 @@
430 const char *zNm = db_get("short-project-name","download");
431 char *zUrl = href("%R/zip/%t/%t.zip", zDLTag, zNm);
432 @ <p>ZIP Archive: %z(zUrl)%h(zNm).zip</a>
433 zUrl = href("%R/tarball/%t/%t.tar.gz", zDLTag, zNm);
434 @ <p>Tarball: %z(zUrl)%h(zNm).tar.gz</a>
435 if( g.zLogin!=0 ){
436 zUrl = href("%R/sqlar/%t/%t.sqlar", zDLTag, zNm);
437 @ <p>SQLite Archive: %z(zUrl)%h(zNm).sqlar</a>
438 }
439 }
440 if( !g.perm.Clone ){
441 @ <p>You are not authorized to clone this repository.
442 if( g.zLogin==0 || g.zLogin[0]==0 ){
443 @ Maybe you would be able to clone if you
444
+1 -1
--- src/db.c
+++ src/db.c
@@ -4758,11 +4758,11 @@
47584758
** SETTING: comment-format width=16 default=1
47594759
** Set the algorithm for printing timeline comments to the console.
47604760
**
47614761
** Possible values are:
47624762
** 1 Use the original comment printing algorithm:
4763
-** * Leading and trialing whitespace is removed
4763
+** * Leading and trailing whitespace is removed
47644764
** * Internal whitespace is converted into a single space (0x20)
47654765
** * Line breaks occurs at whitespace or hyphens if possible
47664766
** This is the recommended value and the default.
47674767
**
47684768
** Or a bitwise combination of the following flags:
47694769
--- src/db.c
+++ src/db.c
@@ -4758,11 +4758,11 @@
4758 ** SETTING: comment-format width=16 default=1
4759 ** Set the algorithm for printing timeline comments to the console.
4760 **
4761 ** Possible values are:
4762 ** 1 Use the original comment printing algorithm:
4763 ** * Leading and trialing whitespace is removed
4764 ** * Internal whitespace is converted into a single space (0x20)
4765 ** * Line breaks occurs at whitespace or hyphens if possible
4766 ** This is the recommended value and the default.
4767 **
4768 ** Or a bitwise combination of the following flags:
4769
--- src/db.c
+++ src/db.c
@@ -4758,11 +4758,11 @@
4758 ** SETTING: comment-format width=16 default=1
4759 ** Set the algorithm for printing timeline comments to the console.
4760 **
4761 ** Possible values are:
4762 ** 1 Use the original comment printing algorithm:
4763 ** * Leading and trailing whitespace is removed
4764 ** * Internal whitespace is converted into a single space (0x20)
4765 ** * Line breaks occurs at whitespace or hyphens if possible
4766 ** This is the recommended value and the default.
4767 **
4768 ** Or a bitwise combination of the following flags:
4769
+7 -1
--- src/diff.tcl
+++ src/diff.tcl
@@ -500,10 +500,12 @@
500500
if {$fn==""} return
501501
set out [open $fn wb]
502502
puts $out "#!/usr/bin/tclsh\n#\n# Run this script using 'tclsh' or 'wish'"
503503
puts $out "# to see the graphical diff.\n#"
504504
puts $out "set fossilcmd {}"
505
+ puts $out "set darkmode $::darkmode"
506
+ puts $out "set debug $::debug"
505507
puts $out "set prog [list $::prog]"
506508
puts $out "set difftxt \173"
507509
foreach e $::difftxt {puts $out [list $e]}
508510
puts $out "\175"
509511
puts $out "eval \$prog"
@@ -606,11 +608,15 @@
606608
::ttk::button .bb.quit -text {Quit} -command exit
607609
::ttk::button .bb.reload -text {Reload} -command reloadDiff
608610
::ttk::button .bb.invert -text {Invert} -command invertDiff
609611
::ttk::button .bb.save -text {Save As...} -command saveDiff
610612
::ttk::button .bb.search -text {Search} -command searchOnOff
611
-pack .bb.quit .bb.reload .bb.invert -side left
613
+pack .bb.quit -side left
614
+if {$fossilcmd ne ""} {
615
+ pack .bb.reload -side left
616
+}
617
+pack .bb.invert -side left
612618
if {$fossilcmd!=""} {pack .bb.save -side left}
613619
pack .bb.files .bb.search -side left
614620
grid rowconfigure . 1 -weight 1
615621
grid columnconfigure . 1 -weight 1
616622
grid columnconfigure . 4 -weight 1
617623
--- src/diff.tcl
+++ src/diff.tcl
@@ -500,10 +500,12 @@
500 if {$fn==""} return
501 set out [open $fn wb]
502 puts $out "#!/usr/bin/tclsh\n#\n# Run this script using 'tclsh' or 'wish'"
503 puts $out "# to see the graphical diff.\n#"
504 puts $out "set fossilcmd {}"
 
 
505 puts $out "set prog [list $::prog]"
506 puts $out "set difftxt \173"
507 foreach e $::difftxt {puts $out [list $e]}
508 puts $out "\175"
509 puts $out "eval \$prog"
@@ -606,11 +608,15 @@
606 ::ttk::button .bb.quit -text {Quit} -command exit
607 ::ttk::button .bb.reload -text {Reload} -command reloadDiff
608 ::ttk::button .bb.invert -text {Invert} -command invertDiff
609 ::ttk::button .bb.save -text {Save As...} -command saveDiff
610 ::ttk::button .bb.search -text {Search} -command searchOnOff
611 pack .bb.quit .bb.reload .bb.invert -side left
 
 
 
 
612 if {$fossilcmd!=""} {pack .bb.save -side left}
613 pack .bb.files .bb.search -side left
614 grid rowconfigure . 1 -weight 1
615 grid columnconfigure . 1 -weight 1
616 grid columnconfigure . 4 -weight 1
617
--- src/diff.tcl
+++ src/diff.tcl
@@ -500,10 +500,12 @@
500 if {$fn==""} return
501 set out [open $fn wb]
502 puts $out "#!/usr/bin/tclsh\n#\n# Run this script using 'tclsh' or 'wish'"
503 puts $out "# to see the graphical diff.\n#"
504 puts $out "set fossilcmd {}"
505 puts $out "set darkmode $::darkmode"
506 puts $out "set debug $::debug"
507 puts $out "set prog [list $::prog]"
508 puts $out "set difftxt \173"
509 foreach e $::difftxt {puts $out [list $e]}
510 puts $out "\175"
511 puts $out "eval \$prog"
@@ -606,11 +608,15 @@
608 ::ttk::button .bb.quit -text {Quit} -command exit
609 ::ttk::button .bb.reload -text {Reload} -command reloadDiff
610 ::ttk::button .bb.invert -text {Invert} -command invertDiff
611 ::ttk::button .bb.save -text {Save As...} -command saveDiff
612 ::ttk::button .bb.search -text {Search} -command searchOnOff
613 pack .bb.quit -side left
614 if {$fossilcmd ne ""} {
615 pack .bb.reload -side left
616 }
617 pack .bb.invert -side left
618 if {$fossilcmd!=""} {pack .bb.save -side left}
619 pack .bb.files .bb.search -side left
620 grid rowconfigure . 1 -weight 1
621 grid columnconfigure . 1 -weight 1
622 grid columnconfigure . 4 -weight 1
623
+2 -1
--- src/http.c
+++ src/http.c
@@ -52,11 +52,12 @@
5252
** Construct the "login" card with the client credentials.
5353
**
5454
** login LOGIN NONCE SIGNATURE
5555
**
5656
** The LOGIN is the user id of the client. NONCE is the sha1 checksum
57
-** of all payload that follows the login card. SIGNATURE is the sha1
57
+** of all payload that follows the login card. Randomness for the NONCE
58
+** must be provided in the payload (in xfer.c). SIGNATURE is the sha1
5859
** checksum of the nonce followed by the user password.
5960
**
6061
** Write the constructed login card into pLogin. pLogin is initialized
6162
** by this routine.
6263
*/
6364
--- src/http.c
+++ src/http.c
@@ -52,11 +52,12 @@
52 ** Construct the "login" card with the client credentials.
53 **
54 ** login LOGIN NONCE SIGNATURE
55 **
56 ** The LOGIN is the user id of the client. NONCE is the sha1 checksum
57 ** of all payload that follows the login card. SIGNATURE is the sha1
 
58 ** checksum of the nonce followed by the user password.
59 **
60 ** Write the constructed login card into pLogin. pLogin is initialized
61 ** by this routine.
62 */
63
--- src/http.c
+++ src/http.c
@@ -52,11 +52,12 @@
52 ** Construct the "login" card with the client credentials.
53 **
54 ** login LOGIN NONCE SIGNATURE
55 **
56 ** The LOGIN is the user id of the client. NONCE is the sha1 checksum
57 ** of all payload that follows the login card. Randomness for the NONCE
58 ** must be provided in the payload (in xfer.c). SIGNATURE is the sha1
59 ** checksum of the nonce followed by the user password.
60 **
61 ** Write the constructed login card into pLogin. pLogin is initialized
62 ** by this routine.
63 */
64
+6 -2
--- src/info.c
+++ src/info.c
@@ -993,12 +993,14 @@
993993
}
994994
zUrl = mprintf("%R/tarball/%S/%t-%S.tar.gz", zUuid, zPJ, zUuid);
995995
@ <tr><th>Downloads:</th><td>
996996
@ %z(href("%s",zUrl))Tarball</a>
997997
@ | %z(href("%R/zip/%S/%t-%S.zip",zUuid, zPJ,zUuid))ZIP archive</a>
998
- @ | %z(href("%R/sqlar/%S/%t-%S.sqlar",zUuid,zPJ,zUuid))\
999
- @ SQL archive</a></td></tr>
998
+ if( g.zLogin!=0 ){
999
+ @ | %z(href("%R/sqlar/%S/%t-%S.sqlar",zUuid,zPJ,zUuid))\
1000
+ @ SQL archive</a></td></tr>
1001
+ }
10001002
fossil_free(zUrl);
10011003
blob_reset(&projName);
10021004
}
10031005
10041006
@ <tr><th>Timelines:</th><td>
@@ -3930,10 +3932,11 @@
39303932
** --cancel TAG Cancel TAG from this check-in
39313933
** --close Mark this "leaf" as closed
39323934
** --date DATETIME Make DATETIME the check-in time
39333935
** --date-override DATETIME Set the change time on the control artifact
39343936
** -e|--edit-comment Launch editor to revise comment
3937
+** --editor NAME Text editor to use for check-in comment
39353938
** --hide Hide branch starting from this check-in
39363939
** -m|--comment COMMENT Make COMMENT the check-in comment
39373940
** -M|--message-file FILE Read the amended comment from FILE
39383941
** -n|--dry-run Print control artifact, but make no changes
39393942
** --no-verify-comment Do not validate the check-in comment
@@ -4003,10 +4006,11 @@
40034006
if( zChngTime==0 ) zChngTime = find_option("chngtime",0,1);
40044007
zUserOvrd = find_option("user-override",0,1);
40054008
noVerifyCom = find_option("no-verify-comment",0,0)!=0;
40064009
db_find_and_open_repository(0,0);
40074010
user_select();
4011
+ (void)fossil_text_editor();
40084012
verify_all_options();
40094013
if( g.argc<3 || g.argc>=4 ) usage(AMEND_USAGE_STMT);
40104014
rid = name_to_typed_rid(g.argv[2], "ci");
40114015
if( rid==0 && !is_a_version(rid) ) fossil_fatal("no such check-in");
40124016
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
40134017
--- src/info.c
+++ src/info.c
@@ -993,12 +993,14 @@
993 }
994 zUrl = mprintf("%R/tarball/%S/%t-%S.tar.gz", zUuid, zPJ, zUuid);
995 @ <tr><th>Downloads:</th><td>
996 @ %z(href("%s",zUrl))Tarball</a>
997 @ | %z(href("%R/zip/%S/%t-%S.zip",zUuid, zPJ,zUuid))ZIP archive</a>
998 @ | %z(href("%R/sqlar/%S/%t-%S.sqlar",zUuid,zPJ,zUuid))\
999 @ SQL archive</a></td></tr>
 
 
1000 fossil_free(zUrl);
1001 blob_reset(&projName);
1002 }
1003
1004 @ <tr><th>Timelines:</th><td>
@@ -3930,10 +3932,11 @@
3930 ** --cancel TAG Cancel TAG from this check-in
3931 ** --close Mark this "leaf" as closed
3932 ** --date DATETIME Make DATETIME the check-in time
3933 ** --date-override DATETIME Set the change time on the control artifact
3934 ** -e|--edit-comment Launch editor to revise comment
 
3935 ** --hide Hide branch starting from this check-in
3936 ** -m|--comment COMMENT Make COMMENT the check-in comment
3937 ** -M|--message-file FILE Read the amended comment from FILE
3938 ** -n|--dry-run Print control artifact, but make no changes
3939 ** --no-verify-comment Do not validate the check-in comment
@@ -4003,10 +4006,11 @@
4003 if( zChngTime==0 ) zChngTime = find_option("chngtime",0,1);
4004 zUserOvrd = find_option("user-override",0,1);
4005 noVerifyCom = find_option("no-verify-comment",0,0)!=0;
4006 db_find_and_open_repository(0,0);
4007 user_select();
 
4008 verify_all_options();
4009 if( g.argc<3 || g.argc>=4 ) usage(AMEND_USAGE_STMT);
4010 rid = name_to_typed_rid(g.argv[2], "ci");
4011 if( rid==0 && !is_a_version(rid) ) fossil_fatal("no such check-in");
4012 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
4013
--- src/info.c
+++ src/info.c
@@ -993,12 +993,14 @@
993 }
994 zUrl = mprintf("%R/tarball/%S/%t-%S.tar.gz", zUuid, zPJ, zUuid);
995 @ <tr><th>Downloads:</th><td>
996 @ %z(href("%s",zUrl))Tarball</a>
997 @ | %z(href("%R/zip/%S/%t-%S.zip",zUuid, zPJ,zUuid))ZIP archive</a>
998 if( g.zLogin!=0 ){
999 @ | %z(href("%R/sqlar/%S/%t-%S.sqlar",zUuid,zPJ,zUuid))\
1000 @ SQL archive</a></td></tr>
1001 }
1002 fossil_free(zUrl);
1003 blob_reset(&projName);
1004 }
1005
1006 @ <tr><th>Timelines:</th><td>
@@ -3930,10 +3932,11 @@
3932 ** --cancel TAG Cancel TAG from this check-in
3933 ** --close Mark this "leaf" as closed
3934 ** --date DATETIME Make DATETIME the check-in time
3935 ** --date-override DATETIME Set the change time on the control artifact
3936 ** -e|--edit-comment Launch editor to revise comment
3937 ** --editor NAME Text editor to use for check-in comment
3938 ** --hide Hide branch starting from this check-in
3939 ** -m|--comment COMMENT Make COMMENT the check-in comment
3940 ** -M|--message-file FILE Read the amended comment from FILE
3941 ** -n|--dry-run Print control artifact, but make no changes
3942 ** --no-verify-comment Do not validate the check-in comment
@@ -4003,10 +4006,11 @@
4006 if( zChngTime==0 ) zChngTime = find_option("chngtime",0,1);
4007 zUserOvrd = find_option("user-override",0,1);
4008 noVerifyCom = find_option("no-verify-comment",0,0)!=0;
4009 db_find_and_open_repository(0,0);
4010 user_select();
4011 (void)fossil_text_editor();
4012 verify_all_options();
4013 if( g.argc<3 || g.argc>=4 ) usage(AMEND_USAGE_STMT);
4014 rid = name_to_typed_rid(g.argv[2], "ci");
4015 if( rid==0 && !is_a_version(rid) ) fossil_fatal("no such check-in");
4016 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
4017
+15 -7
--- src/main.mk
+++ src/main.mk
@@ -579,39 +579,41 @@
579579
$(OBJDIR)/winfile.o \
580580
$(OBJDIR)/winhttp.o \
581581
$(OBJDIR)/xfer.o \
582582
$(OBJDIR)/xfersetup.o \
583583
$(OBJDIR)/zip.o
584
-all: $(OBJDIR) $(APPNAME)
584
+all: $(APPNAME)
585585
586586
install: all
587587
mkdir -p $(INSTALLDIR)
588588
cp $(APPNAME) $(INSTALLDIR)
589589
590590
codecheck: $(TRANS_SRC) $(OBJDIR)/codecheck1
591591
$(OBJDIR)/codecheck1 $(TRANS_SRC)
592592
593
-$(OBJDIR):
594
- -mkdir $(OBJDIR)
595
-
596593
$(OBJDIR)/translate: $(SRCDIR_tools)/translate.c
597594
-mkdir -p $(OBJDIR)
598595
$(XBCC) -o $(OBJDIR)/translate $(SRCDIR_tools)/translate.c
599596
600597
$(OBJDIR)/makeheaders: $(SRCDIR_tools)/makeheaders.c
598
+ -mkdir -p $(OBJDIR)
601599
$(XBCC) -o $(OBJDIR)/makeheaders $(SRCDIR_tools)/makeheaders.c
602600
603601
$(OBJDIR)/mkindex: $(SRCDIR_tools)/mkindex.c
602
+ -mkdir -p $(OBJDIR)
604603
$(XBCC) -o $(OBJDIR)/mkindex $(SRCDIR_tools)/mkindex.c
605604
606605
$(OBJDIR)/mkbuiltin: $(SRCDIR_tools)/mkbuiltin.c
606
+ -mkdir -p $(OBJDIR)
607607
$(XBCC) -o $(OBJDIR)/mkbuiltin $(SRCDIR_tools)/mkbuiltin.c
608608
609609
$(OBJDIR)/mkversion: $(SRCDIR_tools)/mkversion.c
610
+ -mkdir -p $(OBJDIR)
610611
$(XBCC) -o $(OBJDIR)/mkversion $(SRCDIR_tools)/mkversion.c
611612
612613
$(OBJDIR)/codecheck1: $(SRCDIR_tools)/codecheck1.c
614
+ -mkdir -p $(OBJDIR)
613615
$(XBCC) -o $(OBJDIR)/codecheck1 $(SRCDIR_tools)/codecheck1.c
614616
615617
# Run the test suite.
616618
# Other flags that can be included in TESTFLAGS are:
617619
#
@@ -623,11 +625,11 @@
623625
# -strict Treat known bugs as failures
624626
#
625627
# TESTFLAGS can also include names of specific test files to limit
626628
# the run to just those test cases.
627629
#
628
-test: $(OBJDIR) $(APPNAME)
630
+test: $(APPNAME)
629631
$(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) $(TESTFLAGS)
630632
631633
$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion $(OBJDIR)/phony.h
632634
$(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid \
633635
$(SRCDIR)/../manifest \
@@ -2120,23 +2122,29 @@
21202122
21212123
$(OBJDIR)/linenoise.o: $(SRCDIR_extsrc)/linenoise.c $(SRCDIR_extsrc)/linenoise.h
21222124
$(XTCC) -c $(SRCDIR_extsrc)/linenoise.c -o $@
21232125
21242126
$(OBJDIR)/th.o: $(SRCDIR)/th.c
2127
+ -mkdir -p $(OBJDIR)
2128
+
21252129
$(XTCC) -c $(SRCDIR)/th.c -o $@
21262130
21272131
$(OBJDIR)/th_lang.o: $(SRCDIR)/th_lang.c
2132
+ -mkdir -p $(OBJDIR)
2133
+
21282134
$(XTCC) -c $(SRCDIR)/th_lang.c -o $@
21292135
21302136
$(OBJDIR)/th_tcl.o: $(SRCDIR)/th_tcl.c
2137
+ -mkdir -p $(OBJDIR)
2138
+
21312139
$(XTCC) -c $(SRCDIR)/th_tcl.c -o $@
21322140
21332141
2134
-$(OBJDIR)/pikchr.o: $(SRCDIR_extsrc)/pikchr.c
2142
+$(OBJDIR)/pikchr.o: $(SRCDIR_extsrc)/pikchr.c $(OBJDIR)/mkversion
21352143
$(XTCC) $(PIKCHR_OPTIONS) -c $(SRCDIR_extsrc)/pikchr.c -o $@
21362144
2137
-$(OBJDIR)/cson_amalgamation.o: $(SRCDIR_extsrc)/cson_amalgamation.c
2145
+$(OBJDIR)/cson_amalgamation.o: $(SRCDIR_extsrc)/cson_amalgamation.c $(OBJDIR)/mkversion
21382146
$(XTCC) -c $(SRCDIR_extsrc)/cson_amalgamation.c -o $@
21392147
21402148
$(SRCDIR_extsrc)/pikchr.js: $(SRCDIR_extsrc)/pikchr.c $(MAKEFILE_LIST)
21412149
$(EMCC_WRAPPER) -o $@ $(EMCC_OPT) --no-entry \
21422150
-sEXPORTED_RUNTIME_METHODS=cwrap,ccall,setValue,getValue,stackSave,stackAlloc,stackRestore \
21432151
--- src/main.mk
+++ src/main.mk
@@ -579,39 +579,41 @@
579 $(OBJDIR)/winfile.o \
580 $(OBJDIR)/winhttp.o \
581 $(OBJDIR)/xfer.o \
582 $(OBJDIR)/xfersetup.o \
583 $(OBJDIR)/zip.o
584 all: $(OBJDIR) $(APPNAME)
585
586 install: all
587 mkdir -p $(INSTALLDIR)
588 cp $(APPNAME) $(INSTALLDIR)
589
590 codecheck: $(TRANS_SRC) $(OBJDIR)/codecheck1
591 $(OBJDIR)/codecheck1 $(TRANS_SRC)
592
593 $(OBJDIR):
594 -mkdir $(OBJDIR)
595
596 $(OBJDIR)/translate: $(SRCDIR_tools)/translate.c
597 -mkdir -p $(OBJDIR)
598 $(XBCC) -o $(OBJDIR)/translate $(SRCDIR_tools)/translate.c
599
600 $(OBJDIR)/makeheaders: $(SRCDIR_tools)/makeheaders.c
 
601 $(XBCC) -o $(OBJDIR)/makeheaders $(SRCDIR_tools)/makeheaders.c
602
603 $(OBJDIR)/mkindex: $(SRCDIR_tools)/mkindex.c
 
604 $(XBCC) -o $(OBJDIR)/mkindex $(SRCDIR_tools)/mkindex.c
605
606 $(OBJDIR)/mkbuiltin: $(SRCDIR_tools)/mkbuiltin.c
 
607 $(XBCC) -o $(OBJDIR)/mkbuiltin $(SRCDIR_tools)/mkbuiltin.c
608
609 $(OBJDIR)/mkversion: $(SRCDIR_tools)/mkversion.c
 
610 $(XBCC) -o $(OBJDIR)/mkversion $(SRCDIR_tools)/mkversion.c
611
612 $(OBJDIR)/codecheck1: $(SRCDIR_tools)/codecheck1.c
 
613 $(XBCC) -o $(OBJDIR)/codecheck1 $(SRCDIR_tools)/codecheck1.c
614
615 # Run the test suite.
616 # Other flags that can be included in TESTFLAGS are:
617 #
@@ -623,11 +625,11 @@
623 # -strict Treat known bugs as failures
624 #
625 # TESTFLAGS can also include names of specific test files to limit
626 # the run to just those test cases.
627 #
628 test: $(OBJDIR) $(APPNAME)
629 $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) $(TESTFLAGS)
630
631 $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion $(OBJDIR)/phony.h
632 $(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid \
633 $(SRCDIR)/../manifest \
@@ -2120,23 +2122,29 @@
2120
2121 $(OBJDIR)/linenoise.o: $(SRCDIR_extsrc)/linenoise.c $(SRCDIR_extsrc)/linenoise.h
2122 $(XTCC) -c $(SRCDIR_extsrc)/linenoise.c -o $@
2123
2124 $(OBJDIR)/th.o: $(SRCDIR)/th.c
 
 
2125 $(XTCC) -c $(SRCDIR)/th.c -o $@
2126
2127 $(OBJDIR)/th_lang.o: $(SRCDIR)/th_lang.c
 
 
2128 $(XTCC) -c $(SRCDIR)/th_lang.c -o $@
2129
2130 $(OBJDIR)/th_tcl.o: $(SRCDIR)/th_tcl.c
 
 
2131 $(XTCC) -c $(SRCDIR)/th_tcl.c -o $@
2132
2133
2134 $(OBJDIR)/pikchr.o: $(SRCDIR_extsrc)/pikchr.c
2135 $(XTCC) $(PIKCHR_OPTIONS) -c $(SRCDIR_extsrc)/pikchr.c -o $@
2136
2137 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR_extsrc)/cson_amalgamation.c
2138 $(XTCC) -c $(SRCDIR_extsrc)/cson_amalgamation.c -o $@
2139
2140 $(SRCDIR_extsrc)/pikchr.js: $(SRCDIR_extsrc)/pikchr.c $(MAKEFILE_LIST)
2141 $(EMCC_WRAPPER) -o $@ $(EMCC_OPT) --no-entry \
2142 -sEXPORTED_RUNTIME_METHODS=cwrap,ccall,setValue,getValue,stackSave,stackAlloc,stackRestore \
2143
--- src/main.mk
+++ src/main.mk
@@ -579,39 +579,41 @@
579 $(OBJDIR)/winfile.o \
580 $(OBJDIR)/winhttp.o \
581 $(OBJDIR)/xfer.o \
582 $(OBJDIR)/xfersetup.o \
583 $(OBJDIR)/zip.o
584 all: $(APPNAME)
585
586 install: all
587 mkdir -p $(INSTALLDIR)
588 cp $(APPNAME) $(INSTALLDIR)
589
590 codecheck: $(TRANS_SRC) $(OBJDIR)/codecheck1
591 $(OBJDIR)/codecheck1 $(TRANS_SRC)
592
 
 
 
593 $(OBJDIR)/translate: $(SRCDIR_tools)/translate.c
594 -mkdir -p $(OBJDIR)
595 $(XBCC) -o $(OBJDIR)/translate $(SRCDIR_tools)/translate.c
596
597 $(OBJDIR)/makeheaders: $(SRCDIR_tools)/makeheaders.c
598 -mkdir -p $(OBJDIR)
599 $(XBCC) -o $(OBJDIR)/makeheaders $(SRCDIR_tools)/makeheaders.c
600
601 $(OBJDIR)/mkindex: $(SRCDIR_tools)/mkindex.c
602 -mkdir -p $(OBJDIR)
603 $(XBCC) -o $(OBJDIR)/mkindex $(SRCDIR_tools)/mkindex.c
604
605 $(OBJDIR)/mkbuiltin: $(SRCDIR_tools)/mkbuiltin.c
606 -mkdir -p $(OBJDIR)
607 $(XBCC) -o $(OBJDIR)/mkbuiltin $(SRCDIR_tools)/mkbuiltin.c
608
609 $(OBJDIR)/mkversion: $(SRCDIR_tools)/mkversion.c
610 -mkdir -p $(OBJDIR)
611 $(XBCC) -o $(OBJDIR)/mkversion $(SRCDIR_tools)/mkversion.c
612
613 $(OBJDIR)/codecheck1: $(SRCDIR_tools)/codecheck1.c
614 -mkdir -p $(OBJDIR)
615 $(XBCC) -o $(OBJDIR)/codecheck1 $(SRCDIR_tools)/codecheck1.c
616
617 # Run the test suite.
618 # Other flags that can be included in TESTFLAGS are:
619 #
@@ -623,11 +625,11 @@
625 # -strict Treat known bugs as failures
626 #
627 # TESTFLAGS can also include names of specific test files to limit
628 # the run to just those test cases.
629 #
630 test: $(APPNAME)
631 $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) $(TESTFLAGS)
632
633 $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion $(OBJDIR)/phony.h
634 $(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid \
635 $(SRCDIR)/../manifest \
@@ -2120,23 +2122,29 @@
2122
2123 $(OBJDIR)/linenoise.o: $(SRCDIR_extsrc)/linenoise.c $(SRCDIR_extsrc)/linenoise.h
2124 $(XTCC) -c $(SRCDIR_extsrc)/linenoise.c -o $@
2125
2126 $(OBJDIR)/th.o: $(SRCDIR)/th.c
2127 -mkdir -p $(OBJDIR)
2128
2129 $(XTCC) -c $(SRCDIR)/th.c -o $@
2130
2131 $(OBJDIR)/th_lang.o: $(SRCDIR)/th_lang.c
2132 -mkdir -p $(OBJDIR)
2133
2134 $(XTCC) -c $(SRCDIR)/th_lang.c -o $@
2135
2136 $(OBJDIR)/th_tcl.o: $(SRCDIR)/th_tcl.c
2137 -mkdir -p $(OBJDIR)
2138
2139 $(XTCC) -c $(SRCDIR)/th_tcl.c -o $@
2140
2141
2142 $(OBJDIR)/pikchr.o: $(SRCDIR_extsrc)/pikchr.c $(OBJDIR)/mkversion
2143 $(XTCC) $(PIKCHR_OPTIONS) -c $(SRCDIR_extsrc)/pikchr.c -o $@
2144
2145 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR_extsrc)/cson_amalgamation.c $(OBJDIR)/mkversion
2146 $(XTCC) -c $(SRCDIR_extsrc)/cson_amalgamation.c -o $@
2147
2148 $(SRCDIR_extsrc)/pikchr.js: $(SRCDIR_extsrc)/pikchr.c $(MAKEFILE_LIST)
2149 $(EMCC_WRAPPER) -o $@ $(EMCC_OPT) --no-entry \
2150 -sEXPORTED_RUNTIME_METHODS=cwrap,ccall,setValue,getValue,stackSave,stackAlloc,stackRestore \
2151
+15 -7
--- src/main.mk
+++ src/main.mk
@@ -579,39 +579,41 @@
579579
$(OBJDIR)/winfile.o \
580580
$(OBJDIR)/winhttp.o \
581581
$(OBJDIR)/xfer.o \
582582
$(OBJDIR)/xfersetup.o \
583583
$(OBJDIR)/zip.o
584
-all: $(OBJDIR) $(APPNAME)
584
+all: $(APPNAME)
585585
586586
install: all
587587
mkdir -p $(INSTALLDIR)
588588
cp $(APPNAME) $(INSTALLDIR)
589589
590590
codecheck: $(TRANS_SRC) $(OBJDIR)/codecheck1
591591
$(OBJDIR)/codecheck1 $(TRANS_SRC)
592592
593
-$(OBJDIR):
594
- -mkdir $(OBJDIR)
595
-
596593
$(OBJDIR)/translate: $(SRCDIR_tools)/translate.c
597594
-mkdir -p $(OBJDIR)
598595
$(XBCC) -o $(OBJDIR)/translate $(SRCDIR_tools)/translate.c
599596
600597
$(OBJDIR)/makeheaders: $(SRCDIR_tools)/makeheaders.c
598
+ -mkdir -p $(OBJDIR)
601599
$(XBCC) -o $(OBJDIR)/makeheaders $(SRCDIR_tools)/makeheaders.c
602600
603601
$(OBJDIR)/mkindex: $(SRCDIR_tools)/mkindex.c
602
+ -mkdir -p $(OBJDIR)
604603
$(XBCC) -o $(OBJDIR)/mkindex $(SRCDIR_tools)/mkindex.c
605604
606605
$(OBJDIR)/mkbuiltin: $(SRCDIR_tools)/mkbuiltin.c
606
+ -mkdir -p $(OBJDIR)
607607
$(XBCC) -o $(OBJDIR)/mkbuiltin $(SRCDIR_tools)/mkbuiltin.c
608608
609609
$(OBJDIR)/mkversion: $(SRCDIR_tools)/mkversion.c
610
+ -mkdir -p $(OBJDIR)
610611
$(XBCC) -o $(OBJDIR)/mkversion $(SRCDIR_tools)/mkversion.c
611612
612613
$(OBJDIR)/codecheck1: $(SRCDIR_tools)/codecheck1.c
614
+ -mkdir -p $(OBJDIR)
613615
$(XBCC) -o $(OBJDIR)/codecheck1 $(SRCDIR_tools)/codecheck1.c
614616
615617
# Run the test suite.
616618
# Other flags that can be included in TESTFLAGS are:
617619
#
@@ -623,11 +625,11 @@
623625
# -strict Treat known bugs as failures
624626
#
625627
# TESTFLAGS can also include names of specific test files to limit
626628
# the run to just those test cases.
627629
#
628
-test: $(OBJDIR) $(APPNAME)
630
+test: $(APPNAME)
629631
$(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) $(TESTFLAGS)
630632
631633
$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion $(OBJDIR)/phony.h
632634
$(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid \
633635
$(SRCDIR)/../manifest \
@@ -2120,23 +2122,29 @@
21202122
21212123
$(OBJDIR)/linenoise.o: $(SRCDIR_extsrc)/linenoise.c $(SRCDIR_extsrc)/linenoise.h
21222124
$(XTCC) -c $(SRCDIR_extsrc)/linenoise.c -o $@
21232125
21242126
$(OBJDIR)/th.o: $(SRCDIR)/th.c
2127
+ -mkdir -p $(OBJDIR)
2128
+
21252129
$(XTCC) -c $(SRCDIR)/th.c -o $@
21262130
21272131
$(OBJDIR)/th_lang.o: $(SRCDIR)/th_lang.c
2132
+ -mkdir -p $(OBJDIR)
2133
+
21282134
$(XTCC) -c $(SRCDIR)/th_lang.c -o $@
21292135
21302136
$(OBJDIR)/th_tcl.o: $(SRCDIR)/th_tcl.c
2137
+ -mkdir -p $(OBJDIR)
2138
+
21312139
$(XTCC) -c $(SRCDIR)/th_tcl.c -o $@
21322140
21332141
2134
-$(OBJDIR)/pikchr.o: $(SRCDIR_extsrc)/pikchr.c
2142
+$(OBJDIR)/pikchr.o: $(SRCDIR_extsrc)/pikchr.c $(OBJDIR)/mkversion
21352143
$(XTCC) $(PIKCHR_OPTIONS) -c $(SRCDIR_extsrc)/pikchr.c -o $@
21362144
2137
-$(OBJDIR)/cson_amalgamation.o: $(SRCDIR_extsrc)/cson_amalgamation.c
2145
+$(OBJDIR)/cson_amalgamation.o: $(SRCDIR_extsrc)/cson_amalgamation.c $(OBJDIR)/mkversion
21382146
$(XTCC) -c $(SRCDIR_extsrc)/cson_amalgamation.c -o $@
21392147
21402148
$(SRCDIR_extsrc)/pikchr.js: $(SRCDIR_extsrc)/pikchr.c $(MAKEFILE_LIST)
21412149
$(EMCC_WRAPPER) -o $@ $(EMCC_OPT) --no-entry \
21422150
-sEXPORTED_RUNTIME_METHODS=cwrap,ccall,setValue,getValue,stackSave,stackAlloc,stackRestore \
21432151
--- src/main.mk
+++ src/main.mk
@@ -579,39 +579,41 @@
579 $(OBJDIR)/winfile.o \
580 $(OBJDIR)/winhttp.o \
581 $(OBJDIR)/xfer.o \
582 $(OBJDIR)/xfersetup.o \
583 $(OBJDIR)/zip.o
584 all: $(OBJDIR) $(APPNAME)
585
586 install: all
587 mkdir -p $(INSTALLDIR)
588 cp $(APPNAME) $(INSTALLDIR)
589
590 codecheck: $(TRANS_SRC) $(OBJDIR)/codecheck1
591 $(OBJDIR)/codecheck1 $(TRANS_SRC)
592
593 $(OBJDIR):
594 -mkdir $(OBJDIR)
595
596 $(OBJDIR)/translate: $(SRCDIR_tools)/translate.c
597 -mkdir -p $(OBJDIR)
598 $(XBCC) -o $(OBJDIR)/translate $(SRCDIR_tools)/translate.c
599
600 $(OBJDIR)/makeheaders: $(SRCDIR_tools)/makeheaders.c
 
601 $(XBCC) -o $(OBJDIR)/makeheaders $(SRCDIR_tools)/makeheaders.c
602
603 $(OBJDIR)/mkindex: $(SRCDIR_tools)/mkindex.c
 
604 $(XBCC) -o $(OBJDIR)/mkindex $(SRCDIR_tools)/mkindex.c
605
606 $(OBJDIR)/mkbuiltin: $(SRCDIR_tools)/mkbuiltin.c
 
607 $(XBCC) -o $(OBJDIR)/mkbuiltin $(SRCDIR_tools)/mkbuiltin.c
608
609 $(OBJDIR)/mkversion: $(SRCDIR_tools)/mkversion.c
 
610 $(XBCC) -o $(OBJDIR)/mkversion $(SRCDIR_tools)/mkversion.c
611
612 $(OBJDIR)/codecheck1: $(SRCDIR_tools)/codecheck1.c
 
613 $(XBCC) -o $(OBJDIR)/codecheck1 $(SRCDIR_tools)/codecheck1.c
614
615 # Run the test suite.
616 # Other flags that can be included in TESTFLAGS are:
617 #
@@ -623,11 +625,11 @@
623 # -strict Treat known bugs as failures
624 #
625 # TESTFLAGS can also include names of specific test files to limit
626 # the run to just those test cases.
627 #
628 test: $(OBJDIR) $(APPNAME)
629 $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) $(TESTFLAGS)
630
631 $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion $(OBJDIR)/phony.h
632 $(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid \
633 $(SRCDIR)/../manifest \
@@ -2120,23 +2122,29 @@
2120
2121 $(OBJDIR)/linenoise.o: $(SRCDIR_extsrc)/linenoise.c $(SRCDIR_extsrc)/linenoise.h
2122 $(XTCC) -c $(SRCDIR_extsrc)/linenoise.c -o $@
2123
2124 $(OBJDIR)/th.o: $(SRCDIR)/th.c
 
 
2125 $(XTCC) -c $(SRCDIR)/th.c -o $@
2126
2127 $(OBJDIR)/th_lang.o: $(SRCDIR)/th_lang.c
 
 
2128 $(XTCC) -c $(SRCDIR)/th_lang.c -o $@
2129
2130 $(OBJDIR)/th_tcl.o: $(SRCDIR)/th_tcl.c
 
 
2131 $(XTCC) -c $(SRCDIR)/th_tcl.c -o $@
2132
2133
2134 $(OBJDIR)/pikchr.o: $(SRCDIR_extsrc)/pikchr.c
2135 $(XTCC) $(PIKCHR_OPTIONS) -c $(SRCDIR_extsrc)/pikchr.c -o $@
2136
2137 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR_extsrc)/cson_amalgamation.c
2138 $(XTCC) -c $(SRCDIR_extsrc)/cson_amalgamation.c -o $@
2139
2140 $(SRCDIR_extsrc)/pikchr.js: $(SRCDIR_extsrc)/pikchr.c $(MAKEFILE_LIST)
2141 $(EMCC_WRAPPER) -o $@ $(EMCC_OPT) --no-entry \
2142 -sEXPORTED_RUNTIME_METHODS=cwrap,ccall,setValue,getValue,stackSave,stackAlloc,stackRestore \
2143
--- src/main.mk
+++ src/main.mk
@@ -579,39 +579,41 @@
579 $(OBJDIR)/winfile.o \
580 $(OBJDIR)/winhttp.o \
581 $(OBJDIR)/xfer.o \
582 $(OBJDIR)/xfersetup.o \
583 $(OBJDIR)/zip.o
584 all: $(APPNAME)
585
586 install: all
587 mkdir -p $(INSTALLDIR)
588 cp $(APPNAME) $(INSTALLDIR)
589
590 codecheck: $(TRANS_SRC) $(OBJDIR)/codecheck1
591 $(OBJDIR)/codecheck1 $(TRANS_SRC)
592
 
 
 
593 $(OBJDIR)/translate: $(SRCDIR_tools)/translate.c
594 -mkdir -p $(OBJDIR)
595 $(XBCC) -o $(OBJDIR)/translate $(SRCDIR_tools)/translate.c
596
597 $(OBJDIR)/makeheaders: $(SRCDIR_tools)/makeheaders.c
598 -mkdir -p $(OBJDIR)
599 $(XBCC) -o $(OBJDIR)/makeheaders $(SRCDIR_tools)/makeheaders.c
600
601 $(OBJDIR)/mkindex: $(SRCDIR_tools)/mkindex.c
602 -mkdir -p $(OBJDIR)
603 $(XBCC) -o $(OBJDIR)/mkindex $(SRCDIR_tools)/mkindex.c
604
605 $(OBJDIR)/mkbuiltin: $(SRCDIR_tools)/mkbuiltin.c
606 -mkdir -p $(OBJDIR)
607 $(XBCC) -o $(OBJDIR)/mkbuiltin $(SRCDIR_tools)/mkbuiltin.c
608
609 $(OBJDIR)/mkversion: $(SRCDIR_tools)/mkversion.c
610 -mkdir -p $(OBJDIR)
611 $(XBCC) -o $(OBJDIR)/mkversion $(SRCDIR_tools)/mkversion.c
612
613 $(OBJDIR)/codecheck1: $(SRCDIR_tools)/codecheck1.c
614 -mkdir -p $(OBJDIR)
615 $(XBCC) -o $(OBJDIR)/codecheck1 $(SRCDIR_tools)/codecheck1.c
616
617 # Run the test suite.
618 # Other flags that can be included in TESTFLAGS are:
619 #
@@ -623,11 +625,11 @@
625 # -strict Treat known bugs as failures
626 #
627 # TESTFLAGS can also include names of specific test files to limit
628 # the run to just those test cases.
629 #
630 test: $(APPNAME)
631 $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) $(TESTFLAGS)
632
633 $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion $(OBJDIR)/phony.h
634 $(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid \
635 $(SRCDIR)/../manifest \
@@ -2120,23 +2122,29 @@
2122
2123 $(OBJDIR)/linenoise.o: $(SRCDIR_extsrc)/linenoise.c $(SRCDIR_extsrc)/linenoise.h
2124 $(XTCC) -c $(SRCDIR_extsrc)/linenoise.c -o $@
2125
2126 $(OBJDIR)/th.o: $(SRCDIR)/th.c
2127 -mkdir -p $(OBJDIR)
2128
2129 $(XTCC) -c $(SRCDIR)/th.c -o $@
2130
2131 $(OBJDIR)/th_lang.o: $(SRCDIR)/th_lang.c
2132 -mkdir -p $(OBJDIR)
2133
2134 $(XTCC) -c $(SRCDIR)/th_lang.c -o $@
2135
2136 $(OBJDIR)/th_tcl.o: $(SRCDIR)/th_tcl.c
2137 -mkdir -p $(OBJDIR)
2138
2139 $(XTCC) -c $(SRCDIR)/th_tcl.c -o $@
2140
2141
2142 $(OBJDIR)/pikchr.o: $(SRCDIR_extsrc)/pikchr.c $(OBJDIR)/mkversion
2143 $(XTCC) $(PIKCHR_OPTIONS) -c $(SRCDIR_extsrc)/pikchr.c -o $@
2144
2145 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR_extsrc)/cson_amalgamation.c $(OBJDIR)/mkversion
2146 $(XTCC) -c $(SRCDIR_extsrc)/cson_amalgamation.c -o $@
2147
2148 $(SRCDIR_extsrc)/pikchr.js: $(SRCDIR_extsrc)/pikchr.c $(MAKEFILE_LIST)
2149 $(EMCC_WRAPPER) -o $@ $(EMCC_OPT) --no-entry \
2150 -sEXPORTED_RUNTIME_METHODS=cwrap,ccall,setValue,getValue,stackSave,stackAlloc,stackRestore \
2151
+2 -2
--- src/manifest.c
+++ src/manifest.c
@@ -3024,11 +3024,11 @@
30243024
CARD_STR2(K, p->zTicketUuid);
30253025
CARD_STR2(L, p->zWikiTitle);
30263026
ISA( CFTYPE_CLUSTER ){
30273027
CARD_LETTER(M);
30283028
blob_append_char(b, '[');
3029
- for( int i = 0; i < p->nCChild; ++i ){
3029
+ for( i = 0; i < p->nCChild; ++i ){
30303030
if( i>0 ) blob_append_char(b, ',');
30313031
blob_appendf(b, "%!j", p->azCChild[i]);
30323032
}
30333033
blob_append_char(b, ']');
30343034
}
@@ -3059,11 +3059,11 @@
30593059
}
30603060
CARD_STR2(R, p->zRepoCksum);
30613061
if( p->nTag ){
30623062
CARD_LETTER(T);
30633063
blob_append_char(b, '[');
3064
- for( int i = 0; i < p->nTag; ++i ){
3064
+ for( i = 0; i < p->nTag; ++i ){
30653065
const char *zName = p->aTag[i].zName;
30663066
if( i>0 ) blob_append_char(b, ',');
30673067
blob_append_char(b, '{');
30683068
blob_appendf(b, "\"type\":\"%c\"", *zName);
30693069
KVP_STR(1, name, &zName[1]);
30703070
--- src/manifest.c
+++ src/manifest.c
@@ -3024,11 +3024,11 @@
3024 CARD_STR2(K, p->zTicketUuid);
3025 CARD_STR2(L, p->zWikiTitle);
3026 ISA( CFTYPE_CLUSTER ){
3027 CARD_LETTER(M);
3028 blob_append_char(b, '[');
3029 for( int i = 0; i < p->nCChild; ++i ){
3030 if( i>0 ) blob_append_char(b, ',');
3031 blob_appendf(b, "%!j", p->azCChild[i]);
3032 }
3033 blob_append_char(b, ']');
3034 }
@@ -3059,11 +3059,11 @@
3059 }
3060 CARD_STR2(R, p->zRepoCksum);
3061 if( p->nTag ){
3062 CARD_LETTER(T);
3063 blob_append_char(b, '[');
3064 for( int i = 0; i < p->nTag; ++i ){
3065 const char *zName = p->aTag[i].zName;
3066 if( i>0 ) blob_append_char(b, ',');
3067 blob_append_char(b, '{');
3068 blob_appendf(b, "\"type\":\"%c\"", *zName);
3069 KVP_STR(1, name, &zName[1]);
3070
--- src/manifest.c
+++ src/manifest.c
@@ -3024,11 +3024,11 @@
3024 CARD_STR2(K, p->zTicketUuid);
3025 CARD_STR2(L, p->zWikiTitle);
3026 ISA( CFTYPE_CLUSTER ){
3027 CARD_LETTER(M);
3028 blob_append_char(b, '[');
3029 for( i = 0; i < p->nCChild; ++i ){
3030 if( i>0 ) blob_append_char(b, ',');
3031 blob_appendf(b, "%!j", p->azCChild[i]);
3032 }
3033 blob_append_char(b, ']');
3034 }
@@ -3059,11 +3059,11 @@
3059 }
3060 CARD_STR2(R, p->zRepoCksum);
3061 if( p->nTag ){
3062 CARD_LETTER(T);
3063 blob_append_char(b, '[');
3064 for( i = 0; i < p->nTag; ++i ){
3065 const char *zName = p->aTag[i].zName;
3066 if( i>0 ) blob_append_char(b, ',');
3067 blob_append_char(b, '{');
3068 blob_appendf(b, "\"type\":\"%c\"", *zName);
3069 KVP_STR(1, name, &zName[1]);
3070
--- src/markdown_html.c
+++ src/markdown_html.c
@@ -278,11 +278,11 @@
278278
struct Blob *head_row,
279279
struct Blob *rows,
280280
void *opaque
281281
){
282282
INTER_BLOCK(ob);
283
- blob_append_literal(ob, "<table>\n");
283
+ blob_append_literal(ob, "<table class='md-table'>\n");
284284
if( head_row && blob_size(head_row)>0 ){
285285
blob_append_literal(ob, "<thead>\n");
286286
blob_appendb(ob, head_row);
287287
blob_append_literal(ob, "</thead>\n<tbody>\n");
288288
}
@@ -696,11 +696,11 @@
696696
){
697697
blob_appendf(&bSrc, "fontscale = %.13g\n", rPikVar);
698698
}
699699
blob_append(&bSrc, zSrc, nSrc)
700700
/*have to dup input to ensure a NUL-terminated source string */;
701
- pikchr_process(blob_str(&bSrc), pikFlags, 0, ob);
701
+ pikchr_process(blob_str(&bSrc), pikFlags, ob);
702702
blob_reset(&bSrc);
703703
}
704704
705705
/* Invoked for `...` blocks where there are nSep grave accents in a
706706
** row that serve as the delimiter. According to CommonMark:
707707
--- src/markdown_html.c
+++ src/markdown_html.c
@@ -278,11 +278,11 @@
278 struct Blob *head_row,
279 struct Blob *rows,
280 void *opaque
281 ){
282 INTER_BLOCK(ob);
283 blob_append_literal(ob, "<table>\n");
284 if( head_row && blob_size(head_row)>0 ){
285 blob_append_literal(ob, "<thead>\n");
286 blob_appendb(ob, head_row);
287 blob_append_literal(ob, "</thead>\n<tbody>\n");
288 }
@@ -696,11 +696,11 @@
696 ){
697 blob_appendf(&bSrc, "fontscale = %.13g\n", rPikVar);
698 }
699 blob_append(&bSrc, zSrc, nSrc)
700 /*have to dup input to ensure a NUL-terminated source string */;
701 pikchr_process(blob_str(&bSrc), pikFlags, 0, ob);
702 blob_reset(&bSrc);
703 }
704
705 /* Invoked for `...` blocks where there are nSep grave accents in a
706 ** row that serve as the delimiter. According to CommonMark:
707
--- src/markdown_html.c
+++ src/markdown_html.c
@@ -278,11 +278,11 @@
278 struct Blob *head_row,
279 struct Blob *rows,
280 void *opaque
281 ){
282 INTER_BLOCK(ob);
283 blob_append_literal(ob, "<table class='md-table'>\n");
284 if( head_row && blob_size(head_row)>0 ){
285 blob_append_literal(ob, "<thead>\n");
286 blob_appendb(ob, head_row);
287 blob_append_literal(ob, "</thead>\n<tbody>\n");
288 }
@@ -696,11 +696,11 @@
696 ){
697 blob_appendf(&bSrc, "fontscale = %.13g\n", rPikVar);
698 }
699 blob_append(&bSrc, zSrc, nSrc)
700 /*have to dup input to ensure a NUL-terminated source string */;
701 pikchr_process(blob_str(&bSrc), pikFlags, ob);
702 blob_reset(&bSrc);
703 }
704
705 /* Invoked for `...` blocks where there are nSep grave accents in a
706 ** row that serve as the delimiter. According to CommonMark:
707
+89 -182
--- src/pikchrshow.c
+++ src/pikchrshow.c
@@ -27,12 +27,10 @@
2727
/* The first two must match the values from pikchr.c */
2828
#define PIKCHR_PROCESS_PLAINTEXT_ERRORS 0x0001
2929
#define PIKCHR_PROCESS_DARK_MODE 0x0002
3030
/* end of flags supported directly by pikchr() */
3131
#define PIKCHR_PROCESS_PASSTHROUGH 0x0003 /* Pass through these flags */
32
-#define PIKCHR_PROCESS_TH1 0x0004
33
-#define PIKCHR_PROCESS_TH1_NOSVG 0x0008
3432
#define PIKCHR_PROCESS_NONCE 0x0010
3533
#define PIKCHR_PROCESS_ERR_PRE 0x0020
3634
#define PIKCHR_PROCESS_SRC 0x0040
3735
#define PIKCHR_PROCESS_DIV 0x0080
3836
#define PIKCHR_PROCESS_DIV_INDENT 0x0100
@@ -43,36 +41,20 @@
4341
#define PIKCHR_PROCESS_DIV_SOURCE 0x2000
4442
#define PIKCHR_PROCESS_DIV_SOURCE_INLINE 0x4000
4543
#endif
4644
4745
/*
48
-** Processes a pikchr script, optionally with embedded TH1, and
49
-** produces HTML code for it. zIn is the NUL-terminated input
46
+** Processes a pikchr script. zIn is the NUL-terminated input
5047
** script. pikFlags may be a bitmask of any of the PIKCHR_PROCESS_xxx
51
-** flags documented below. thFlags may be a bitmask of any of the
52
-** TH_INIT_xxx and/or TH_R2B_xxx flags. Output is sent to pOut,
53
-** appending to it without modifying any prior contents.
48
+** flags documented below. Output is sent to pOut,
5449
**
55
-** Returns 0 on success, 1 if TH1 processing failed, or 2 if pikchr
56
-** processing failed. In either case, the error message (if any) from
57
-** TH1 or pikchr will be appended to pOut.
50
+** Returns 0 on success, or non-zero if pikchr processing failed.
51
+** In either case, the error message (if any) from pikchr will be
52
+** appended to pOut.
5853
**
5954
** pikFlags flag descriptions:
6055
**
61
-** - PIKCHR_PROCESS_TH1 means to run zIn through TH1, using the TH1
62
-** init flags specified in the 3rd argument. If thFlags is non-0 then
63
-** this flag is assumed even if it is not specified.
64
-**
65
-** - PIKCHR_PROCESS_TH1_NOSVG means that processing stops after the
66
-** TH1 eval step, thus the output will be (presumably) a
67
-** TH1-generated/processed pikchr script (or whatever else the TH1
68
-** outputs). If this flag is set, PIKCHR_PROCESS_TH1 is assumed even
69
-** if it is not specified.
70
-**
71
-** All of the remaining flags listed below are ignored if
72
-** PIKCHR_PROCESS_TH1_NOSVG is specified!
73
-**
7456
** - PIKCHR_PROCESS_DIV: if set, the SVG result is wrapped in a DIV
7557
** element which specifies a max-width style value based on the SVG's
7658
** calculated size. This flag has multiple mutually exclusive forms:
7759
**
7860
** - PIKCHR_PROCESS_DIV uses default element alignment.
@@ -116,14 +98,14 @@
11698
**
11799
** - PIKCHR_PROCESS_ERR_PRE: if set and pikchr() fails, the resulting
118100
** error report is wrapped in a PRE element, else it is retained
119101
** as-is (intended only for console output).
120102
*/
121
-int pikchr_process(const char * zIn, int pikFlags, int thFlags,
122
- Blob * pOut){
123
- Blob bIn = empty_blob;
103
+int pikchr_process(const char *zIn, int pikFlags, Blob * pOut){
124104
int isErr = 0;
105
+ int w = 0, h = 0;
106
+ char *zOut;
125107
const char *zNonce = (PIKCHR_PROCESS_NONCE & pikFlags)
126108
? safe_html_nonce(1) : 0;
127109
128110
if(!(PIKCHR_PROCESS_DIV & pikFlags)
129111
/* If any DIV_xxx flags are set, set DIV */
@@ -135,115 +117,87 @@
135117
| PIKCHR_PROCESS_DIV_SOURCE_INLINE
136118
| PIKCHR_PROCESS_DIV_TOGGLE
137119
) & pikFlags){
138120
pikFlags |= PIKCHR_PROCESS_DIV;
139121
}
140
- if(!(PIKCHR_PROCESS_TH1 & pikFlags)
141
- /* If any TH1_xxx flags are set, set TH1 */
142
- && (PIKCHR_PROCESS_TH1_NOSVG & pikFlags || thFlags!=0)){
143
- pikFlags |= PIKCHR_PROCESS_TH1;
144
- }
145
- if(zNonce){
146
- blob_appendf(pOut, "%s\n", zNonce);
147
- }
148
- if(PIKCHR_PROCESS_TH1 & pikFlags){
149
- Blob out = empty_blob;
150
- isErr = Th_RenderToBlob(zIn, &out, thFlags)
151
- ? 1 : 0;
152
- if(isErr){
153
- blob_append(pOut, blob_str(&out), blob_size(&out));
154
- blob_reset(&out);
155
- }else{
156
- bIn = out;
157
- }
158
- }else{
159
- blob_init(&bIn, zIn, -1);
160
- }
161
- if(!isErr){
162
- if(PIKCHR_PROCESS_TH1_NOSVG & pikFlags){
163
- blob_append(pOut, blob_str(&bIn), blob_size(&bIn));
164
- }else{
165
- int w = 0, h = 0;
166
- const char * zContent = blob_str(&bIn);
167
- char *zOut;
168
- zOut = pikchr(zContent, "pikchr",
169
- 0x01 | (pikFlags&PIKCHR_PROCESS_PASSTHROUGH),
170
- &w, &h);
171
- if( w>0 && h>0 ){
172
- const char * zClassToggle = "";
173
- const char * zClassSource = "";
174
- const char * zWrapperClass = "";
175
- if(PIKCHR_PROCESS_DIV & pikFlags){
176
- if(PIKCHR_PROCESS_DIV_CENTER & pikFlags){
177
- zWrapperClass = " center";
178
- }else if(PIKCHR_PROCESS_DIV_INDENT & pikFlags){
179
- zWrapperClass = " indent";
180
- }else if(PIKCHR_PROCESS_DIV_FLOAT_LEFT & pikFlags){
181
- zWrapperClass = " float-left";
182
- }else if(PIKCHR_PROCESS_DIV_FLOAT_RIGHT & pikFlags){
183
- zWrapperClass = " float-right";
184
- }
185
- if(PIKCHR_PROCESS_DIV_TOGGLE & pikFlags){
186
- zClassToggle = " toggle";
187
- }
188
- if(PIKCHR_PROCESS_DIV_SOURCE_INLINE & pikFlags){
189
- if(PIKCHR_PROCESS_DIV_SOURCE & pikFlags){
190
- zClassSource = " source source-inline";
191
- }else{
192
- zClassSource = " source-inline";
193
- }
194
- pikFlags |= PIKCHR_PROCESS_SRC;
195
- }else if(PIKCHR_PROCESS_DIV_SOURCE & pikFlags){
196
- zClassSource = " source";
197
- pikFlags |= PIKCHR_PROCESS_SRC;
198
- }
199
- blob_appendf(pOut,"<div class='pikchr-wrapper"
200
- "%s%s%s'>"
201
- "<div class=\"pikchr-svg\" "
202
- "style=\"max-width:%dpx\">\n",
203
- zWrapperClass/*safe-for-%s*/,
204
- zClassToggle/*safe-for-%s*/,
205
- zClassSource/*safe-for-%s*/, w);
206
- }
207
- blob_append(pOut, zOut, -1);
208
- if(PIKCHR_PROCESS_DIV & pikFlags){
209
- blob_append(pOut, "</div>\n", 7);
210
- }
211
- if(PIKCHR_PROCESS_SRC & pikFlags){
212
- static int counter = 0;
213
- ++counter;
214
- blob_appendf(pOut, "<div class='pikchr-src'>"
215
- "<pre id='pikchr-src-%d'>%h</pre>"
216
- "<span class='hidden'>"
217
- "<a href='%R/pikchrshow?fromSession' "
218
- "class='pikchr-src-pikchrshow' target='_new-%d' "
219
- "data-pikchrid='pikchr-src-%d' "
220
- "title='Open this pikchr in /pikchrshow'"
221
- ">&rarr; /pikchrshow</a></span>"
222
- "</div>\n",
223
- counter, blob_str(&bIn), counter, counter);
224
- }
225
- if(PIKCHR_PROCESS_DIV & pikFlags){
226
- blob_append(pOut, "</div>\n", 7);
227
- }
228
- }else{
229
- isErr = 2;
230
- if(PIKCHR_PROCESS_ERR_PRE & pikFlags){
231
- blob_append(pOut, "<pre class='error'>\n", 20);
232
- }
233
- blob_appendf(pOut, "%h", zOut);
234
- if(PIKCHR_PROCESS_ERR_PRE & pikFlags){
235
- blob_append(pOut, "\n</pre>\n", 8);
236
- }
237
- }
238
- fossil_free(zOut);
239
- }
240
- }
241
- if(zNonce){
242
- blob_appendf(pOut, "%s\n", zNonce);
243
- }
244
- blob_reset(&bIn);
122
+ if(zNonce){
123
+ blob_appendf(pOut, "%s\n", zNonce);
124
+ }
125
+ zOut = pikchr(zIn, "pikchr",
126
+ 0x01 | (pikFlags&PIKCHR_PROCESS_PASSTHROUGH),
127
+ &w, &h);
128
+ if( w>0 && h>0 ){
129
+ const char * zClassToggle = "";
130
+ const char * zClassSource = "";
131
+ const char * zWrapperClass = "";
132
+ if(PIKCHR_PROCESS_DIV & pikFlags){
133
+ if(PIKCHR_PROCESS_DIV_CENTER & pikFlags){
134
+ zWrapperClass = " center";
135
+ }else if(PIKCHR_PROCESS_DIV_INDENT & pikFlags){
136
+ zWrapperClass = " indent";
137
+ }else if(PIKCHR_PROCESS_DIV_FLOAT_LEFT & pikFlags){
138
+ zWrapperClass = " float-left";
139
+ }else if(PIKCHR_PROCESS_DIV_FLOAT_RIGHT & pikFlags){
140
+ zWrapperClass = " float-right";
141
+ }
142
+ if(PIKCHR_PROCESS_DIV_TOGGLE & pikFlags){
143
+ zClassToggle = " toggle";
144
+ }
145
+ if(PIKCHR_PROCESS_DIV_SOURCE_INLINE & pikFlags){
146
+ if(PIKCHR_PROCESS_DIV_SOURCE & pikFlags){
147
+ zClassSource = " source source-inline";
148
+ }else{
149
+ zClassSource = " source-inline";
150
+ }
151
+ pikFlags |= PIKCHR_PROCESS_SRC;
152
+ }else if(PIKCHR_PROCESS_DIV_SOURCE & pikFlags){
153
+ zClassSource = " source";
154
+ pikFlags |= PIKCHR_PROCESS_SRC;
155
+ }
156
+ blob_appendf(pOut,"<div class='pikchr-wrapper"
157
+ "%s%s%s'>"
158
+ "<div class=\"pikchr-svg\" "
159
+ "style=\"max-width:%dpx\">\n",
160
+ zWrapperClass/*safe-for-%s*/,
161
+ zClassToggle/*safe-for-%s*/,
162
+ zClassSource/*safe-for-%s*/, w);
163
+ }
164
+ blob_append(pOut, zOut, -1);
165
+ if(PIKCHR_PROCESS_DIV & pikFlags){
166
+ blob_append(pOut, "</div>\n", 7);
167
+ }
168
+ if(PIKCHR_PROCESS_SRC & pikFlags){
169
+ static int counter = 0;
170
+ ++counter;
171
+ blob_appendf(pOut, "<div class='pikchr-src'>"
172
+ "<pre id='pikchr-src-%d'>%h</pre>"
173
+ "<span class='hidden'>"
174
+ "<a href='%R/pikchrshow?fromSession' "
175
+ "class='pikchr-src-pikchrshow' target='_new-%d' "
176
+ "data-pikchrid='pikchr-src-%d' "
177
+ "title='Open this pikchr in /pikchrshow'"
178
+ ">&rarr; /pikchrshow</a></span>"
179
+ "</div>\n",
180
+ counter, zIn, counter, counter);
181
+ }
182
+ if(PIKCHR_PROCESS_DIV & pikFlags){
183
+ blob_append(pOut, "</div>\n", 7);
184
+ }
185
+ }else{
186
+ isErr = 2;
187
+ if(PIKCHR_PROCESS_ERR_PRE & pikFlags){
188
+ blob_append(pOut, "<pre class='error'>\n", 20);
189
+ }
190
+ blob_appendf(pOut, "%h", zOut);
191
+ if(PIKCHR_PROCESS_ERR_PRE & pikFlags){
192
+ blob_append(pOut, "\n</pre>\n", 8);
193
+ }
194
+ }
195
+ fossil_free(zOut);
196
+ if(zNonce){
197
+ blob_appendf(pOut, "%s\n", zNonce);
198
+ }
245199
return isErr;
246200
}
247201
248202
/*
249203
** Legacy impl of /pikchrshow. pikchrshow_page() will delegate to
@@ -279,11 +233,11 @@
279233
TODO: respond with JSON instead.*/
280234
cgi_set_content_type("text/html");
281235
if(zContent && *zContent){
282236
Blob out = empty_blob;
283237
const int isErr =
284
- pikchr_process(zContent, pikFlags, 0, &out);
238
+ pikchr_process(zContent, pikFlags, &out);
285239
if(isErr){
286240
cgi_printf_header("x-pikchrshow-is-error: %d\r\n", isErr);
287241
}
288242
CX("%b", &out);
289243
blob_reset(&out);
@@ -384,11 +338,11 @@
384338
/* Reminder: Firefox does not properly flexbox a LEGEND
385339
element, always flowing it in column mode. */);
386340
CX("<div id='pikchrshow-output'>");
387341
if(*zContent){
388342
Blob out = empty_blob;
389
- pikchr_process(zContent, pikFlags, 0, &out);
343
+ pikchr_process(zContent, pikFlags, &out);
390344
CX("%b", &out);
391345
blob_reset(&out);
392346
} CX("</div>"/*#pikchrshow-output*/);
393347
} CX("</fieldset>"/*#pikchrshow-output-wrapper*/);
394348
} CX("</div>"/*sbs-wrapper*/);
@@ -561,60 +515,23 @@
561515
**
562516
** -src Store the input pikchr's source code in the output as
563517
** a separate element adjacent to the SVG one. Implied
564518
** by -div-source.
565519
**
566
-**
567
-** -th Process the input using TH1 before passing it to pikchr
568
-**
569
-** -th-novar Disable $var and $<var> TH1 processing. Use this if the
570
-** pikchr script uses '$' for its own purposes and that
571
-** causes issues. This only affects parsing of '$' outside
572
-** of TH1 script blocks. Code in such blocks is unaffected.
573
-**
574
-** -th-nosvg When using -th, output the post-TH1'd script
575
-** instead of the pikchr-rendered output
576
-**
577
-** -th-trace Trace TH1 execution (for debugging purposes)
578
-**
579520
** -dark Change pikchr colors to assume a dark-mode theme.
580521
**
581522
**
582523
** The -div-indent/center/left/right flags may not be combined.
583
-**
584
-** TH1-related Notes and Caveats:
585
-**
586
-** If the -th flag is used, this command must open a fossil database
587
-** for certain functionality to work (via a check-out or the -R REPO
588
-** flag). If opening a db fails, execution will continue but any TH1
589
-** commands which require a db will trigger a fatal error.
590
-**
591
-** In Fossil skins, TH1 variables in the form $varName are expanded
592
-** as-is and those in the form $<varName> are htmlized in the
593
-** resulting output. This processor disables the htmlizing step, so $x
594
-** and $<x> are equivalent unless the TH1-processed pikchr script
595
-** invokes the TH1 command [enable_htmlify 1] to enable it. Normally
596
-** that option will interfere with pikchr output, however, e.g. by
597
-** HTML-encoding double-quotes.
598
-**
599
-** Many of the fossil-installed TH1 functions simply do not make any
600
-** sense for pikchr scripts.
601524
*/
602525
void pikchr_cmd(void){
603526
Blob bIn = empty_blob;
604527
Blob bOut = empty_blob;
605528
const char * zInfile = "-";
606529
const char * zOutfile = "-";
607
- const int fTh1 = find_option("th",0,0)!=0;
608
- const int fNosvg = find_option("th-nosvg",0,0)!=0;
609530
int isErr = 0;
610531
int pikFlags = find_option("src",0,0)!=0
611532
? PIKCHR_PROCESS_SRC : 0;
612
- u32 fThFlags = TH_INIT_NO_ENCODE
613
- | (find_option("th-novar",0,0)!=0 ? TH_R2B_NO_VARS : 0);
614
-
615
- Th_InitTraceLog()/*processes -th-trace flag*/;
616533
617534
if(find_option("div",0,0)!=0){
618535
pikFlags |= PIKCHR_PROCESS_DIV;
619536
}else if(find_option("div-indent",0,0)!=0){
620537
pikFlags |= PIKCHR_PROCESS_DIV_INDENT;
@@ -644,24 +561,14 @@
644561
}
645562
if(g.argc>3){
646563
zOutfile = g.argv[3];
647564
}
648565
blob_read_from_file(&bIn, zInfile, ExtFILE);
649
- if(fTh1){
650
- db_find_and_open_repository(OPEN_ANY_SCHEMA | OPEN_OK_NOT_FOUND, 0)
651
- /* ^^^ needed for certain TH1 functions to work */;
652
- pikFlags |= PIKCHR_PROCESS_TH1;
653
- if(fNosvg) pikFlags |= PIKCHR_PROCESS_TH1_NOSVG;
654
- }
655
- isErr = pikchr_process(blob_str(&bIn), pikFlags,
656
- fTh1 ? fThFlags : 0, &bOut);
566
+ isErr = pikchr_process(blob_str(&bIn), pikFlags, &bOut);
657567
if(isErr){
658
- fossil_fatal("%s ERROR:%c%b", 1==isErr ? "TH1" : "pikchr",
659
- 1==isErr ? ' ' : '\n',
660
- &bOut);
568
+ fossil_fatal("pikchr ERROR: %b", &bOut);
661569
}else{
662570
blob_write_to_file(&bOut, zOutfile);
663571
}
664
- Th_PrintTraceLog();
665572
blob_reset(&bIn);
666573
blob_reset(&bOut);
667574
}
668575
--- src/pikchrshow.c
+++ src/pikchrshow.c
@@ -27,12 +27,10 @@
27 /* The first two must match the values from pikchr.c */
28 #define PIKCHR_PROCESS_PLAINTEXT_ERRORS 0x0001
29 #define PIKCHR_PROCESS_DARK_MODE 0x0002
30 /* end of flags supported directly by pikchr() */
31 #define PIKCHR_PROCESS_PASSTHROUGH 0x0003 /* Pass through these flags */
32 #define PIKCHR_PROCESS_TH1 0x0004
33 #define PIKCHR_PROCESS_TH1_NOSVG 0x0008
34 #define PIKCHR_PROCESS_NONCE 0x0010
35 #define PIKCHR_PROCESS_ERR_PRE 0x0020
36 #define PIKCHR_PROCESS_SRC 0x0040
37 #define PIKCHR_PROCESS_DIV 0x0080
38 #define PIKCHR_PROCESS_DIV_INDENT 0x0100
@@ -43,36 +41,20 @@
43 #define PIKCHR_PROCESS_DIV_SOURCE 0x2000
44 #define PIKCHR_PROCESS_DIV_SOURCE_INLINE 0x4000
45 #endif
46
47 /*
48 ** Processes a pikchr script, optionally with embedded TH1, and
49 ** produces HTML code for it. zIn is the NUL-terminated input
50 ** script. pikFlags may be a bitmask of any of the PIKCHR_PROCESS_xxx
51 ** flags documented below. thFlags may be a bitmask of any of the
52 ** TH_INIT_xxx and/or TH_R2B_xxx flags. Output is sent to pOut,
53 ** appending to it without modifying any prior contents.
54 **
55 ** Returns 0 on success, 1 if TH1 processing failed, or 2 if pikchr
56 ** processing failed. In either case, the error message (if any) from
57 ** TH1 or pikchr will be appended to pOut.
58 **
59 ** pikFlags flag descriptions:
60 **
61 ** - PIKCHR_PROCESS_TH1 means to run zIn through TH1, using the TH1
62 ** init flags specified in the 3rd argument. If thFlags is non-0 then
63 ** this flag is assumed even if it is not specified.
64 **
65 ** - PIKCHR_PROCESS_TH1_NOSVG means that processing stops after the
66 ** TH1 eval step, thus the output will be (presumably) a
67 ** TH1-generated/processed pikchr script (or whatever else the TH1
68 ** outputs). If this flag is set, PIKCHR_PROCESS_TH1 is assumed even
69 ** if it is not specified.
70 **
71 ** All of the remaining flags listed below are ignored if
72 ** PIKCHR_PROCESS_TH1_NOSVG is specified!
73 **
74 ** - PIKCHR_PROCESS_DIV: if set, the SVG result is wrapped in a DIV
75 ** element which specifies a max-width style value based on the SVG's
76 ** calculated size. This flag has multiple mutually exclusive forms:
77 **
78 ** - PIKCHR_PROCESS_DIV uses default element alignment.
@@ -116,14 +98,14 @@
116 **
117 ** - PIKCHR_PROCESS_ERR_PRE: if set and pikchr() fails, the resulting
118 ** error report is wrapped in a PRE element, else it is retained
119 ** as-is (intended only for console output).
120 */
121 int pikchr_process(const char * zIn, int pikFlags, int thFlags,
122 Blob * pOut){
123 Blob bIn = empty_blob;
124 int isErr = 0;
 
 
125 const char *zNonce = (PIKCHR_PROCESS_NONCE & pikFlags)
126 ? safe_html_nonce(1) : 0;
127
128 if(!(PIKCHR_PROCESS_DIV & pikFlags)
129 /* If any DIV_xxx flags are set, set DIV */
@@ -135,115 +117,87 @@
135 | PIKCHR_PROCESS_DIV_SOURCE_INLINE
136 | PIKCHR_PROCESS_DIV_TOGGLE
137 ) & pikFlags){
138 pikFlags |= PIKCHR_PROCESS_DIV;
139 }
140 if(!(PIKCHR_PROCESS_TH1 & pikFlags)
141 /* If any TH1_xxx flags are set, set TH1 */
142 && (PIKCHR_PROCESS_TH1_NOSVG & pikFlags || thFlags!=0)){
143 pikFlags |= PIKCHR_PROCESS_TH1;
144 }
145 if(zNonce){
146 blob_appendf(pOut, "%s\n", zNonce);
147 }
148 if(PIKCHR_PROCESS_TH1 & pikFlags){
149 Blob out = empty_blob;
150 isErr = Th_RenderToBlob(zIn, &out, thFlags)
151 ? 1 : 0;
152 if(isErr){
153 blob_append(pOut, blob_str(&out), blob_size(&out));
154 blob_reset(&out);
155 }else{
156 bIn = out;
157 }
158 }else{
159 blob_init(&bIn, zIn, -1);
160 }
161 if(!isErr){
162 if(PIKCHR_PROCESS_TH1_NOSVG & pikFlags){
163 blob_append(pOut, blob_str(&bIn), blob_size(&bIn));
164 }else{
165 int w = 0, h = 0;
166 const char * zContent = blob_str(&bIn);
167 char *zOut;
168 zOut = pikchr(zContent, "pikchr",
169 0x01 | (pikFlags&PIKCHR_PROCESS_PASSTHROUGH),
170 &w, &h);
171 if( w>0 && h>0 ){
172 const char * zClassToggle = "";
173 const char * zClassSource = "";
174 const char * zWrapperClass = "";
175 if(PIKCHR_PROCESS_DIV & pikFlags){
176 if(PIKCHR_PROCESS_DIV_CENTER & pikFlags){
177 zWrapperClass = " center";
178 }else if(PIKCHR_PROCESS_DIV_INDENT & pikFlags){
179 zWrapperClass = " indent";
180 }else if(PIKCHR_PROCESS_DIV_FLOAT_LEFT & pikFlags){
181 zWrapperClass = " float-left";
182 }else if(PIKCHR_PROCESS_DIV_FLOAT_RIGHT & pikFlags){
183 zWrapperClass = " float-right";
184 }
185 if(PIKCHR_PROCESS_DIV_TOGGLE & pikFlags){
186 zClassToggle = " toggle";
187 }
188 if(PIKCHR_PROCESS_DIV_SOURCE_INLINE & pikFlags){
189 if(PIKCHR_PROCESS_DIV_SOURCE & pikFlags){
190 zClassSource = " source source-inline";
191 }else{
192 zClassSource = " source-inline";
193 }
194 pikFlags |= PIKCHR_PROCESS_SRC;
195 }else if(PIKCHR_PROCESS_DIV_SOURCE & pikFlags){
196 zClassSource = " source";
197 pikFlags |= PIKCHR_PROCESS_SRC;
198 }
199 blob_appendf(pOut,"<div class='pikchr-wrapper"
200 "%s%s%s'>"
201 "<div class=\"pikchr-svg\" "
202 "style=\"max-width:%dpx\">\n",
203 zWrapperClass/*safe-for-%s*/,
204 zClassToggle/*safe-for-%s*/,
205 zClassSource/*safe-for-%s*/, w);
206 }
207 blob_append(pOut, zOut, -1);
208 if(PIKCHR_PROCESS_DIV & pikFlags){
209 blob_append(pOut, "</div>\n", 7);
210 }
211 if(PIKCHR_PROCESS_SRC & pikFlags){
212 static int counter = 0;
213 ++counter;
214 blob_appendf(pOut, "<div class='pikchr-src'>"
215 "<pre id='pikchr-src-%d'>%h</pre>"
216 "<span class='hidden'>"
217 "<a href='%R/pikchrshow?fromSession' "
218 "class='pikchr-src-pikchrshow' target='_new-%d' "
219 "data-pikchrid='pikchr-src-%d' "
220 "title='Open this pikchr in /pikchrshow'"
221 ">&rarr; /pikchrshow</a></span>"
222 "</div>\n",
223 counter, blob_str(&bIn), counter, counter);
224 }
225 if(PIKCHR_PROCESS_DIV & pikFlags){
226 blob_append(pOut, "</div>\n", 7);
227 }
228 }else{
229 isErr = 2;
230 if(PIKCHR_PROCESS_ERR_PRE & pikFlags){
231 blob_append(pOut, "<pre class='error'>\n", 20);
232 }
233 blob_appendf(pOut, "%h", zOut);
234 if(PIKCHR_PROCESS_ERR_PRE & pikFlags){
235 blob_append(pOut, "\n</pre>\n", 8);
236 }
237 }
238 fossil_free(zOut);
239 }
240 }
241 if(zNonce){
242 blob_appendf(pOut, "%s\n", zNonce);
243 }
244 blob_reset(&bIn);
245 return isErr;
246 }
247
248 /*
249 ** Legacy impl of /pikchrshow. pikchrshow_page() will delegate to
@@ -279,11 +233,11 @@
279 TODO: respond with JSON instead.*/
280 cgi_set_content_type("text/html");
281 if(zContent && *zContent){
282 Blob out = empty_blob;
283 const int isErr =
284 pikchr_process(zContent, pikFlags, 0, &out);
285 if(isErr){
286 cgi_printf_header("x-pikchrshow-is-error: %d\r\n", isErr);
287 }
288 CX("%b", &out);
289 blob_reset(&out);
@@ -384,11 +338,11 @@
384 /* Reminder: Firefox does not properly flexbox a LEGEND
385 element, always flowing it in column mode. */);
386 CX("<div id='pikchrshow-output'>");
387 if(*zContent){
388 Blob out = empty_blob;
389 pikchr_process(zContent, pikFlags, 0, &out);
390 CX("%b", &out);
391 blob_reset(&out);
392 } CX("</div>"/*#pikchrshow-output*/);
393 } CX("</fieldset>"/*#pikchrshow-output-wrapper*/);
394 } CX("</div>"/*sbs-wrapper*/);
@@ -561,60 +515,23 @@
561 **
562 ** -src Store the input pikchr's source code in the output as
563 ** a separate element adjacent to the SVG one. Implied
564 ** by -div-source.
565 **
566 **
567 ** -th Process the input using TH1 before passing it to pikchr
568 **
569 ** -th-novar Disable $var and $<var> TH1 processing. Use this if the
570 ** pikchr script uses '$' for its own purposes and that
571 ** causes issues. This only affects parsing of '$' outside
572 ** of TH1 script blocks. Code in such blocks is unaffected.
573 **
574 ** -th-nosvg When using -th, output the post-TH1'd script
575 ** instead of the pikchr-rendered output
576 **
577 ** -th-trace Trace TH1 execution (for debugging purposes)
578 **
579 ** -dark Change pikchr colors to assume a dark-mode theme.
580 **
581 **
582 ** The -div-indent/center/left/right flags may not be combined.
583 **
584 ** TH1-related Notes and Caveats:
585 **
586 ** If the -th flag is used, this command must open a fossil database
587 ** for certain functionality to work (via a check-out or the -R REPO
588 ** flag). If opening a db fails, execution will continue but any TH1
589 ** commands which require a db will trigger a fatal error.
590 **
591 ** In Fossil skins, TH1 variables in the form $varName are expanded
592 ** as-is and those in the form $<varName> are htmlized in the
593 ** resulting output. This processor disables the htmlizing step, so $x
594 ** and $<x> are equivalent unless the TH1-processed pikchr script
595 ** invokes the TH1 command [enable_htmlify 1] to enable it. Normally
596 ** that option will interfere with pikchr output, however, e.g. by
597 ** HTML-encoding double-quotes.
598 **
599 ** Many of the fossil-installed TH1 functions simply do not make any
600 ** sense for pikchr scripts.
601 */
602 void pikchr_cmd(void){
603 Blob bIn = empty_blob;
604 Blob bOut = empty_blob;
605 const char * zInfile = "-";
606 const char * zOutfile = "-";
607 const int fTh1 = find_option("th",0,0)!=0;
608 const int fNosvg = find_option("th-nosvg",0,0)!=0;
609 int isErr = 0;
610 int pikFlags = find_option("src",0,0)!=0
611 ? PIKCHR_PROCESS_SRC : 0;
612 u32 fThFlags = TH_INIT_NO_ENCODE
613 | (find_option("th-novar",0,0)!=0 ? TH_R2B_NO_VARS : 0);
614
615 Th_InitTraceLog()/*processes -th-trace flag*/;
616
617 if(find_option("div",0,0)!=0){
618 pikFlags |= PIKCHR_PROCESS_DIV;
619 }else if(find_option("div-indent",0,0)!=0){
620 pikFlags |= PIKCHR_PROCESS_DIV_INDENT;
@@ -644,24 +561,14 @@
644 }
645 if(g.argc>3){
646 zOutfile = g.argv[3];
647 }
648 blob_read_from_file(&bIn, zInfile, ExtFILE);
649 if(fTh1){
650 db_find_and_open_repository(OPEN_ANY_SCHEMA | OPEN_OK_NOT_FOUND, 0)
651 /* ^^^ needed for certain TH1 functions to work */;
652 pikFlags |= PIKCHR_PROCESS_TH1;
653 if(fNosvg) pikFlags |= PIKCHR_PROCESS_TH1_NOSVG;
654 }
655 isErr = pikchr_process(blob_str(&bIn), pikFlags,
656 fTh1 ? fThFlags : 0, &bOut);
657 if(isErr){
658 fossil_fatal("%s ERROR:%c%b", 1==isErr ? "TH1" : "pikchr",
659 1==isErr ? ' ' : '\n',
660 &bOut);
661 }else{
662 blob_write_to_file(&bOut, zOutfile);
663 }
664 Th_PrintTraceLog();
665 blob_reset(&bIn);
666 blob_reset(&bOut);
667 }
668
--- src/pikchrshow.c
+++ src/pikchrshow.c
@@ -27,12 +27,10 @@
27 /* The first two must match the values from pikchr.c */
28 #define PIKCHR_PROCESS_PLAINTEXT_ERRORS 0x0001
29 #define PIKCHR_PROCESS_DARK_MODE 0x0002
30 /* end of flags supported directly by pikchr() */
31 #define PIKCHR_PROCESS_PASSTHROUGH 0x0003 /* Pass through these flags */
 
 
32 #define PIKCHR_PROCESS_NONCE 0x0010
33 #define PIKCHR_PROCESS_ERR_PRE 0x0020
34 #define PIKCHR_PROCESS_SRC 0x0040
35 #define PIKCHR_PROCESS_DIV 0x0080
36 #define PIKCHR_PROCESS_DIV_INDENT 0x0100
@@ -43,36 +41,20 @@
41 #define PIKCHR_PROCESS_DIV_SOURCE 0x2000
42 #define PIKCHR_PROCESS_DIV_SOURCE_INLINE 0x4000
43 #endif
44
45 /*
46 ** Processes a pikchr script. zIn is the NUL-terminated input
 
47 ** script. pikFlags may be a bitmask of any of the PIKCHR_PROCESS_xxx
48 ** flags documented below. Output is sent to pOut,
 
 
49 **
50 ** Returns 0 on success, or non-zero if pikchr processing failed.
51 ** In either case, the error message (if any) from pikchr will be
52 ** appended to pOut.
53 **
54 ** pikFlags flag descriptions:
55 **
 
 
 
 
 
 
 
 
 
 
 
 
 
56 ** - PIKCHR_PROCESS_DIV: if set, the SVG result is wrapped in a DIV
57 ** element which specifies a max-width style value based on the SVG's
58 ** calculated size. This flag has multiple mutually exclusive forms:
59 **
60 ** - PIKCHR_PROCESS_DIV uses default element alignment.
@@ -116,14 +98,14 @@
98 **
99 ** - PIKCHR_PROCESS_ERR_PRE: if set and pikchr() fails, the resulting
100 ** error report is wrapped in a PRE element, else it is retained
101 ** as-is (intended only for console output).
102 */
103 int pikchr_process(const char *zIn, int pikFlags, Blob * pOut){
 
 
104 int isErr = 0;
105 int w = 0, h = 0;
106 char *zOut;
107 const char *zNonce = (PIKCHR_PROCESS_NONCE & pikFlags)
108 ? safe_html_nonce(1) : 0;
109
110 if(!(PIKCHR_PROCESS_DIV & pikFlags)
111 /* If any DIV_xxx flags are set, set DIV */
@@ -135,115 +117,87 @@
117 | PIKCHR_PROCESS_DIV_SOURCE_INLINE
118 | PIKCHR_PROCESS_DIV_TOGGLE
119 ) & pikFlags){
120 pikFlags |= PIKCHR_PROCESS_DIV;
121 }
122 if(zNonce){
123 blob_appendf(pOut, "%s\n", zNonce);
124 }
125 zOut = pikchr(zIn, "pikchr",
126 0x01 | (pikFlags&PIKCHR_PROCESS_PASSTHROUGH),
127 &w, &h);
128 if( w>0 && h>0 ){
129 const char * zClassToggle = "";
130 const char * zClassSource = "";
131 const char * zWrapperClass = "";
132 if(PIKCHR_PROCESS_DIV & pikFlags){
133 if(PIKCHR_PROCESS_DIV_CENTER & pikFlags){
134 zWrapperClass = " center";
135 }else if(PIKCHR_PROCESS_DIV_INDENT & pikFlags){
136 zWrapperClass = " indent";
137 }else if(PIKCHR_PROCESS_DIV_FLOAT_LEFT & pikFlags){
138 zWrapperClass = " float-left";
139 }else if(PIKCHR_PROCESS_DIV_FLOAT_RIGHT & pikFlags){
140 zWrapperClass = " float-right";
141 }
142 if(PIKCHR_PROCESS_DIV_TOGGLE & pikFlags){
143 zClassToggle = " toggle";
144 }
145 if(PIKCHR_PROCESS_DIV_SOURCE_INLINE & pikFlags){
146 if(PIKCHR_PROCESS_DIV_SOURCE & pikFlags){
147 zClassSource = " source source-inline";
148 }else{
149 zClassSource = " source-inline";
150 }
151 pikFlags |= PIKCHR_PROCESS_SRC;
152 }else if(PIKCHR_PROCESS_DIV_SOURCE & pikFlags){
153 zClassSource = " source";
154 pikFlags |= PIKCHR_PROCESS_SRC;
155 }
156 blob_appendf(pOut,"<div class='pikchr-wrapper"
157 "%s%s%s'>"
158 "<div class=\"pikchr-svg\" "
159 "style=\"max-width:%dpx\">\n",
160 zWrapperClass/*safe-for-%s*/,
161 zClassToggle/*safe-for-%s*/,
162 zClassSource/*safe-for-%s*/, w);
163 }
164 blob_append(pOut, zOut, -1);
165 if(PIKCHR_PROCESS_DIV & pikFlags){
166 blob_append(pOut, "</div>\n", 7);
167 }
168 if(PIKCHR_PROCESS_SRC & pikFlags){
169 static int counter = 0;
170 ++counter;
171 blob_appendf(pOut, "<div class='pikchr-src'>"
172 "<pre id='pikchr-src-%d'>%h</pre>"
173 "<span class='hidden'>"
174 "<a href='%R/pikchrshow?fromSession' "
175 "class='pikchr-src-pikchrshow' target='_new-%d' "
176 "data-pikchrid='pikchr-src-%d' "
177 "title='Open this pikchr in /pikchrshow'"
178 ">&rarr; /pikchrshow</a></span>"
179 "</div>\n",
180 counter, zIn, counter, counter);
181 }
182 if(PIKCHR_PROCESS_DIV & pikFlags){
183 blob_append(pOut, "</div>\n", 7);
184 }
185 }else{
186 isErr = 2;
187 if(PIKCHR_PROCESS_ERR_PRE & pikFlags){
188 blob_append(pOut, "<pre class='error'>\n", 20);
189 }
190 blob_appendf(pOut, "%h", zOut);
191 if(PIKCHR_PROCESS_ERR_PRE & pikFlags){
192 blob_append(pOut, "\n</pre>\n", 8);
193 }
194 }
195 fossil_free(zOut);
196 if(zNonce){
197 blob_appendf(pOut, "%s\n", zNonce);
198 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
199 return isErr;
200 }
201
202 /*
203 ** Legacy impl of /pikchrshow. pikchrshow_page() will delegate to
@@ -279,11 +233,11 @@
233 TODO: respond with JSON instead.*/
234 cgi_set_content_type("text/html");
235 if(zContent && *zContent){
236 Blob out = empty_blob;
237 const int isErr =
238 pikchr_process(zContent, pikFlags, &out);
239 if(isErr){
240 cgi_printf_header("x-pikchrshow-is-error: %d\r\n", isErr);
241 }
242 CX("%b", &out);
243 blob_reset(&out);
@@ -384,11 +338,11 @@
338 /* Reminder: Firefox does not properly flexbox a LEGEND
339 element, always flowing it in column mode. */);
340 CX("<div id='pikchrshow-output'>");
341 if(*zContent){
342 Blob out = empty_blob;
343 pikchr_process(zContent, pikFlags, &out);
344 CX("%b", &out);
345 blob_reset(&out);
346 } CX("</div>"/*#pikchrshow-output*/);
347 } CX("</fieldset>"/*#pikchrshow-output-wrapper*/);
348 } CX("</div>"/*sbs-wrapper*/);
@@ -561,60 +515,23 @@
515 **
516 ** -src Store the input pikchr's source code in the output as
517 ** a separate element adjacent to the SVG one. Implied
518 ** by -div-source.
519 **
 
 
 
 
 
 
 
 
 
 
 
 
 
520 ** -dark Change pikchr colors to assume a dark-mode theme.
521 **
522 **
523 ** The -div-indent/center/left/right flags may not be combined.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
524 */
525 void pikchr_cmd(void){
526 Blob bIn = empty_blob;
527 Blob bOut = empty_blob;
528 const char * zInfile = "-";
529 const char * zOutfile = "-";
 
 
530 int isErr = 0;
531 int pikFlags = find_option("src",0,0)!=0
532 ? PIKCHR_PROCESS_SRC : 0;
 
 
 
 
533
534 if(find_option("div",0,0)!=0){
535 pikFlags |= PIKCHR_PROCESS_DIV;
536 }else if(find_option("div-indent",0,0)!=0){
537 pikFlags |= PIKCHR_PROCESS_DIV_INDENT;
@@ -644,24 +561,14 @@
561 }
562 if(g.argc>3){
563 zOutfile = g.argv[3];
564 }
565 blob_read_from_file(&bIn, zInfile, ExtFILE);
566 isErr = pikchr_process(blob_str(&bIn), pikFlags, &bOut);
 
 
 
 
 
 
 
567 if(isErr){
568 fossil_fatal("pikchr ERROR: %b", &bOut);
 
 
569 }else{
570 blob_write_to_file(&bOut, zOutfile);
571 }
 
572 blob_reset(&bIn);
573 blob_reset(&bOut);
574 }
575
+1 -22
--- src/repolist.c
+++ src/repolist.c
@@ -101,25 +101,10 @@
101101
finish_repo_list:
102102
g.dbIgnoreErrors--;
103103
sqlite3_close(db);
104104
}
105105
106
-/*
107
-** SETTING: show-repolist-desc boolean default=off
108
-**
109
-** If the value of this setting is "1" globally, then the repository-list
110
-** page will show the description of each repository. This setting only
111
-** has effect when it is in the global setting database.
112
-*/
113
-/*
114
-** SETTING: show-repolist-lg boolean default=off
115
-**
116
-** If the value of this setting is "1" globally, then the repository-list
117
-** page will show the login-group for each repository. This setting only
118
-** has effect when it is in the global setting database.
119
-*/
120
-
121106
/*
122107
** Generate a web-page that lists all repositories located under the
123108
** g.zRepositoryName directory and return non-zero.
124109
**
125110
** For the special case when g.zRepositoryName is a non-chroot-jail "/",
@@ -151,17 +136,10 @@
151136
assert( g.db==0 );
152137
zShow = P("FOSSIL_REPOLIST_SHOW");
153138
if( zShow ){
154139
bShowDesc = strstr(zShow,"description")!=0;
155140
bShowLg = strstr(zShow,"login-group")!=0;
156
- }else if( db_open_config(1, 1)
157
- && db_table_exists("configdb", "global_config")
158
- ){
159
- bShowDesc = db_int(bShowDesc, "SELECT value FROM global_config"
160
- " WHERE name='show-repolist-desc'");
161
- bShowLg = db_int(bShowLg, "SELECT value FROM global_config"
162
- " WHERE name='show-repolist-lg'");
163141
}
164142
blob_init(&html, 0, 0);
165143
if( fossil_strcmp(g.zRepositoryName,"/")==0 && !g.fJail ){
166144
/* For the special case of the "repository directory" being "/",
167145
** show all of the repositories named in the ~/.fossil database.
@@ -169,10 +147,11 @@
169147
** On unix systems, then entries are of the form "repo:/home/..."
170148
** and on Windows systems they are like on unix, starting with a "/"
171149
** or they can begin with a drive letter: "repo:C:/Users/...". In either
172150
** case, we want returned path to omit any initial "/".
173151
*/
152
+ db_open_config(1, 0);
174153
db_multi_exec(
175154
"CREATE TEMP VIEW sfile AS"
176155
" SELECT ltrim(substr(name,6),'/') AS 'pathname' FROM global_config"
177156
" WHERE name GLOB 'repo:*'"
178157
);
179158
--- src/repolist.c
+++ src/repolist.c
@@ -101,25 +101,10 @@
101 finish_repo_list:
102 g.dbIgnoreErrors--;
103 sqlite3_close(db);
104 }
105
106 /*
107 ** SETTING: show-repolist-desc boolean default=off
108 **
109 ** If the value of this setting is "1" globally, then the repository-list
110 ** page will show the description of each repository. This setting only
111 ** has effect when it is in the global setting database.
112 */
113 /*
114 ** SETTING: show-repolist-lg boolean default=off
115 **
116 ** If the value of this setting is "1" globally, then the repository-list
117 ** page will show the login-group for each repository. This setting only
118 ** has effect when it is in the global setting database.
119 */
120
121 /*
122 ** Generate a web-page that lists all repositories located under the
123 ** g.zRepositoryName directory and return non-zero.
124 **
125 ** For the special case when g.zRepositoryName is a non-chroot-jail "/",
@@ -151,17 +136,10 @@
151 assert( g.db==0 );
152 zShow = P("FOSSIL_REPOLIST_SHOW");
153 if( zShow ){
154 bShowDesc = strstr(zShow,"description")!=0;
155 bShowLg = strstr(zShow,"login-group")!=0;
156 }else if( db_open_config(1, 1)
157 && db_table_exists("configdb", "global_config")
158 ){
159 bShowDesc = db_int(bShowDesc, "SELECT value FROM global_config"
160 " WHERE name='show-repolist-desc'");
161 bShowLg = db_int(bShowLg, "SELECT value FROM global_config"
162 " WHERE name='show-repolist-lg'");
163 }
164 blob_init(&html, 0, 0);
165 if( fossil_strcmp(g.zRepositoryName,"/")==0 && !g.fJail ){
166 /* For the special case of the "repository directory" being "/",
167 ** show all of the repositories named in the ~/.fossil database.
@@ -169,10 +147,11 @@
169 ** On unix systems, then entries are of the form "repo:/home/..."
170 ** and on Windows systems they are like on unix, starting with a "/"
171 ** or they can begin with a drive letter: "repo:C:/Users/...". In either
172 ** case, we want returned path to omit any initial "/".
173 */
 
174 db_multi_exec(
175 "CREATE TEMP VIEW sfile AS"
176 " SELECT ltrim(substr(name,6),'/') AS 'pathname' FROM global_config"
177 " WHERE name GLOB 'repo:*'"
178 );
179
--- src/repolist.c
+++ src/repolist.c
@@ -101,25 +101,10 @@
101 finish_repo_list:
102 g.dbIgnoreErrors--;
103 sqlite3_close(db);
104 }
105
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
106 /*
107 ** Generate a web-page that lists all repositories located under the
108 ** g.zRepositoryName directory and return non-zero.
109 **
110 ** For the special case when g.zRepositoryName is a non-chroot-jail "/",
@@ -151,17 +136,10 @@
136 assert( g.db==0 );
137 zShow = P("FOSSIL_REPOLIST_SHOW");
138 if( zShow ){
139 bShowDesc = strstr(zShow,"description")!=0;
140 bShowLg = strstr(zShow,"login-group")!=0;
 
 
 
 
 
 
 
141 }
142 blob_init(&html, 0, 0);
143 if( fossil_strcmp(g.zRepositoryName,"/")==0 && !g.fJail ){
144 /* For the special case of the "repository directory" being "/",
145 ** show all of the repositories named in the ~/.fossil database.
@@ -169,10 +147,11 @@
147 ** On unix systems, then entries are of the form "repo:/home/..."
148 ** and on Windows systems they are like on unix, starting with a "/"
149 ** or they can begin with a drive letter: "repo:C:/Users/...". In either
150 ** case, we want returned path to omit any initial "/".
151 */
152 db_open_config(1, 0);
153 db_multi_exec(
154 "CREATE TEMP VIEW sfile AS"
155 " SELECT ltrim(substr(name,6),'/') AS 'pathname' FROM global_config"
156 " WHERE name GLOB 'repo:*'"
157 );
158
+1 -22
--- src/repolist.c
+++ src/repolist.c
@@ -101,25 +101,10 @@
101101
finish_repo_list:
102102
g.dbIgnoreErrors--;
103103
sqlite3_close(db);
104104
}
105105
106
-/*
107
-** SETTING: show-repolist-desc boolean default=off
108
-**
109
-** If the value of this setting is "1" globally, then the repository-list
110
-** page will show the description of each repository. This setting only
111
-** has effect when it is in the global setting database.
112
-*/
113
-/*
114
-** SETTING: show-repolist-lg boolean default=off
115
-**
116
-** If the value of this setting is "1" globally, then the repository-list
117
-** page will show the login-group for each repository. This setting only
118
-** has effect when it is in the global setting database.
119
-*/
120
-
121106
/*
122107
** Generate a web-page that lists all repositories located under the
123108
** g.zRepositoryName directory and return non-zero.
124109
**
125110
** For the special case when g.zRepositoryName is a non-chroot-jail "/",
@@ -151,17 +136,10 @@
151136
assert( g.db==0 );
152137
zShow = P("FOSSIL_REPOLIST_SHOW");
153138
if( zShow ){
154139
bShowDesc = strstr(zShow,"description")!=0;
155140
bShowLg = strstr(zShow,"login-group")!=0;
156
- }else if( db_open_config(1, 1)
157
- && db_table_exists("configdb", "global_config")
158
- ){
159
- bShowDesc = db_int(bShowDesc, "SELECT value FROM global_config"
160
- " WHERE name='show-repolist-desc'");
161
- bShowLg = db_int(bShowLg, "SELECT value FROM global_config"
162
- " WHERE name='show-repolist-lg'");
163141
}
164142
blob_init(&html, 0, 0);
165143
if( fossil_strcmp(g.zRepositoryName,"/")==0 && !g.fJail ){
166144
/* For the special case of the "repository directory" being "/",
167145
** show all of the repositories named in the ~/.fossil database.
@@ -169,10 +147,11 @@
169147
** On unix systems, then entries are of the form "repo:/home/..."
170148
** and on Windows systems they are like on unix, starting with a "/"
171149
** or they can begin with a drive letter: "repo:C:/Users/...". In either
172150
** case, we want returned path to omit any initial "/".
173151
*/
152
+ db_open_config(1, 0);
174153
db_multi_exec(
175154
"CREATE TEMP VIEW sfile AS"
176155
" SELECT ltrim(substr(name,6),'/') AS 'pathname' FROM global_config"
177156
" WHERE name GLOB 'repo:*'"
178157
);
179158
--- src/repolist.c
+++ src/repolist.c
@@ -101,25 +101,10 @@
101 finish_repo_list:
102 g.dbIgnoreErrors--;
103 sqlite3_close(db);
104 }
105
106 /*
107 ** SETTING: show-repolist-desc boolean default=off
108 **
109 ** If the value of this setting is "1" globally, then the repository-list
110 ** page will show the description of each repository. This setting only
111 ** has effect when it is in the global setting database.
112 */
113 /*
114 ** SETTING: show-repolist-lg boolean default=off
115 **
116 ** If the value of this setting is "1" globally, then the repository-list
117 ** page will show the login-group for each repository. This setting only
118 ** has effect when it is in the global setting database.
119 */
120
121 /*
122 ** Generate a web-page that lists all repositories located under the
123 ** g.zRepositoryName directory and return non-zero.
124 **
125 ** For the special case when g.zRepositoryName is a non-chroot-jail "/",
@@ -151,17 +136,10 @@
151 assert( g.db==0 );
152 zShow = P("FOSSIL_REPOLIST_SHOW");
153 if( zShow ){
154 bShowDesc = strstr(zShow,"description")!=0;
155 bShowLg = strstr(zShow,"login-group")!=0;
156 }else if( db_open_config(1, 1)
157 && db_table_exists("configdb", "global_config")
158 ){
159 bShowDesc = db_int(bShowDesc, "SELECT value FROM global_config"
160 " WHERE name='show-repolist-desc'");
161 bShowLg = db_int(bShowLg, "SELECT value FROM global_config"
162 " WHERE name='show-repolist-lg'");
163 }
164 blob_init(&html, 0, 0);
165 if( fossil_strcmp(g.zRepositoryName,"/")==0 && !g.fJail ){
166 /* For the special case of the "repository directory" being "/",
167 ** show all of the repositories named in the ~/.fossil database.
@@ -169,10 +147,11 @@
169 ** On unix systems, then entries are of the form "repo:/home/..."
170 ** and on Windows systems they are like on unix, starting with a "/"
171 ** or they can begin with a drive letter: "repo:C:/Users/...". In either
172 ** case, we want returned path to omit any initial "/".
173 */
 
174 db_multi_exec(
175 "CREATE TEMP VIEW sfile AS"
176 " SELECT ltrim(substr(name,6),'/') AS 'pathname' FROM global_config"
177 " WHERE name GLOB 'repo:*'"
178 );
179
--- src/repolist.c
+++ src/repolist.c
@@ -101,25 +101,10 @@
101 finish_repo_list:
102 g.dbIgnoreErrors--;
103 sqlite3_close(db);
104 }
105
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
106 /*
107 ** Generate a web-page that lists all repositories located under the
108 ** g.zRepositoryName directory and return non-zero.
109 **
110 ** For the special case when g.zRepositoryName is a non-chroot-jail "/",
@@ -151,17 +136,10 @@
136 assert( g.db==0 );
137 zShow = P("FOSSIL_REPOLIST_SHOW");
138 if( zShow ){
139 bShowDesc = strstr(zShow,"description")!=0;
140 bShowLg = strstr(zShow,"login-group")!=0;
 
 
 
 
 
 
 
141 }
142 blob_init(&html, 0, 0);
143 if( fossil_strcmp(g.zRepositoryName,"/")==0 && !g.fJail ){
144 /* For the special case of the "repository directory" being "/",
145 ** show all of the repositories named in the ~/.fossil database.
@@ -169,10 +147,11 @@
147 ** On unix systems, then entries are of the form "repo:/home/..."
148 ** and on Windows systems they are like on unix, starting with a "/"
149 ** or they can begin with a drive letter: "repo:C:/Users/...". In either
150 ** case, we want returned path to omit any initial "/".
151 */
152 db_open_config(1, 0);
153 db_multi_exec(
154 "CREATE TEMP VIEW sfile AS"
155 " SELECT ltrim(substr(name,6),'/') AS 'pathname' FROM global_config"
156 " WHERE name GLOB 'repo:*'"
157 );
158
+1 -1
--- src/tag.c
+++ src/tag.c
@@ -412,11 +412,11 @@
412412
** non-CHECK-IN artifacts.
413413
** --user-override USER Name USER when adding the tag
414414
**
415415
** The --date-override and --user-override options support
416416
** importing history from other SCM systems. DATETIME has
417
-** the form 'YYYY-MMM-DD HH:MM:SS'.
417
+** the form 'YYYY-MM-DD HH:MM:SS'.
418418
**
419419
** Note that fossil uses some tag prefixes internally and this
420420
** command will reject tags with these prefixes to avoid
421421
** causing problems or confusion: "wiki-", "tkt-", "event-".
422422
**
423423
--- src/tag.c
+++ src/tag.c
@@ -412,11 +412,11 @@
412 ** non-CHECK-IN artifacts.
413 ** --user-override USER Name USER when adding the tag
414 **
415 ** The --date-override and --user-override options support
416 ** importing history from other SCM systems. DATETIME has
417 ** the form 'YYYY-MMM-DD HH:MM:SS'.
418 **
419 ** Note that fossil uses some tag prefixes internally and this
420 ** command will reject tags with these prefixes to avoid
421 ** causing problems or confusion: "wiki-", "tkt-", "event-".
422 **
423
--- src/tag.c
+++ src/tag.c
@@ -412,11 +412,11 @@
412 ** non-CHECK-IN artifacts.
413 ** --user-override USER Name USER when adding the tag
414 **
415 ** The --date-override and --user-override options support
416 ** importing history from other SCM systems. DATETIME has
417 ** the form 'YYYY-MM-DD HH:MM:SS'.
418 **
419 ** Note that fossil uses some tag prefixes internally and this
420 ** command will reject tags with these prefixes to avoid
421 ** causing problems or confusion: "wiki-", "tkt-", "event-".
422 **
423
+3 -51
--- src/th_main.c
+++ src/th_main.c
@@ -31,13 +31,11 @@
3131
#define TH_INIT_NEED_CONFIG ((u32)0x00000001) /* Open configuration first? */
3232
#define TH_INIT_FORCE_TCL ((u32)0x00000002) /* Force Tcl to be enabled? */
3333
#define TH_INIT_FORCE_RESET ((u32)0x00000004) /* Force TH1 commands re-added? */
3434
#define TH_INIT_FORCE_SETUP ((u32)0x00000008) /* Force eval of setup script? */
3535
#define TH_INIT_NO_REPO ((u32)0x00000010) /* Skip opening repository. */
36
-#define TH_INIT_NO_ENCODE ((u32)0x00000020) /* Do not html-encode sendText()*/
37
- /* output. */
38
-#define TH_INIT_MASK ((u32)0x0000003F) /* All possible init flags. */
36
+#define TH_INIT_MASK ((u32)0x0000001F) /* All possible init flags. */
3937
4038
/*
4139
** Useful and/or "well-known" combinations of flag values.
4240
*/
4341
#define TH_INIT_DEFAULT (TH_INIT_NONE) /* Default flags. */
@@ -297,50 +295,10 @@
297295
TH1_LEN(argl[1]),argv[1],enableOutput);
298296
}
299297
return rc;
300298
}
301299
302
-/*
303
-** TH1 command: enable_htmlify ?BOOLEAN?
304
-**
305
-** Enable or disable the HTML escaping done by all output which
306
-** originates from TH1 (via sendText()).
307
-**
308
-** If passed no arguments it instead returns 0 or 1 to indicate the
309
-** current state.
310
-*/
311
-static int enableHtmlifyCmd(
312
- Th_Interp *interp,
313
- void *p,
314
- int argc,
315
- const char **argv,
316
- int *argl
317
-){
318
- int rc = 0, buul;
319
- if( argc>3 ){
320
- return Th_WrongNumArgs(interp,
321
- "enable_htmlify [TRACE_LABEL] ?BOOLEAN?");
322
- }
323
- buul = (TH_INIT_NO_ENCODE & g.th1Flags) ? 0 : 1;
324
- Th_SetResultInt(g.interp, buul);
325
- if(argc>1){
326
- if( g.thTrace ){
327
- Th_Trace("enable_htmlify {%.*s} -> %d<br>\n",
328
- TH1_LEN(argl[1]),argv[1],buul);
329
- }
330
- rc = Th_ToInt(interp, argv[argc-1], argl[argc-1], &buul);
331
- if(!rc){
332
- if(buul){
333
- g.th1Flags &= ~TH_INIT_NO_ENCODE;
334
- }else{
335
- g.th1Flags |= TH_INIT_NO_ENCODE;
336
- }
337
- }
338
- }
339
- return rc;
340
-}
341
-
342300
/*
343301
** Returns a name for a TH1 return code.
344302
*/
345303
const char *Th_ReturnCodeName(int rc, int nullIfOk){
346304
static char zRc[32];
@@ -376,23 +334,19 @@
376334
377335
/*
378336
** Send text to the appropriate output: If pOut is not NULL, it is
379337
** appended there, else to the console or to the CGI reply buffer.
380338
** Escape all characters with special meaning to HTML if the encode
381
-** parameter is true, with the exception that that flag is ignored if
382
-** g.th1Flags has the TH_INIT_NO_ENCODE flag.
339
+** parameter is true.
383340
**
384341
** If pOut is NULL and the global pThOut is not then that blob
385342
** is used for output.
386343
*/
387344
static void sendText(Blob *pOut, const char *z, int n, int encode){
388345
if(0==pOut && pThOut!=0){
389346
pOut = pThOut;
390347
}
391
- if(TH_INIT_NO_ENCODE & g.th1Flags){
392
- encode = 0;
393
- }
394348
if( enableOutput && n ){
395349
if( n<0 ){
396350
n = strlen(z);
397351
}else{
398352
n = TH1_LEN(n);
@@ -2429,11 +2383,10 @@
24292383
{"copybtn", copybtnCmd, 0},
24302384
{"date", dateCmd, 0},
24312385
{"decorate", wikiCmd, (void*)&aFlags[2]},
24322386
{"defHeader", defHeaderCmd, 0},
24332387
{"dir", dirCmd, 0},
2434
- {"enable_htmlify",enableHtmlifyCmd, 0},
24352388
{"enable_output", enableOutputCmd, 0},
24362389
{"encode64", encode64Cmd, 0},
24372390
{"getParameter", getParameterCmd, 0},
24382391
{"glob_match", globMatchCmd, 0},
24392392
{"globalState", globalStateCmd, 0},
@@ -3047,12 +3000,11 @@
30473000
** e.g. via the "render" script function binding, need to use the
30483001
** pThOut blob in order to avoid out-of-order output if
30493002
** Th_SetOutputBlob() has been called. If it has not been called,
30503003
** pThOut will be 0, which will redirect the output to CGI/stdout,
30513004
** as appropriate. We need to pass on g.th1Flags for the case of
3052
- ** recursive calls, so that, e.g., TH_INIT_NO_ENCODE does not get
3053
- ** inadvertently toggled off by a recursive call.
3005
+ ** recursive calls.
30543006
*/;
30553007
}
30563008
30573009
/*
30583010
** SETTING: vuln-report width=8 default=log
30593011
--- src/th_main.c
+++ src/th_main.c
@@ -31,13 +31,11 @@
31 #define TH_INIT_NEED_CONFIG ((u32)0x00000001) /* Open configuration first? */
32 #define TH_INIT_FORCE_TCL ((u32)0x00000002) /* Force Tcl to be enabled? */
33 #define TH_INIT_FORCE_RESET ((u32)0x00000004) /* Force TH1 commands re-added? */
34 #define TH_INIT_FORCE_SETUP ((u32)0x00000008) /* Force eval of setup script? */
35 #define TH_INIT_NO_REPO ((u32)0x00000010) /* Skip opening repository. */
36 #define TH_INIT_NO_ENCODE ((u32)0x00000020) /* Do not html-encode sendText()*/
37 /* output. */
38 #define TH_INIT_MASK ((u32)0x0000003F) /* All possible init flags. */
39
40 /*
41 ** Useful and/or "well-known" combinations of flag values.
42 */
43 #define TH_INIT_DEFAULT (TH_INIT_NONE) /* Default flags. */
@@ -297,50 +295,10 @@
297 TH1_LEN(argl[1]),argv[1],enableOutput);
298 }
299 return rc;
300 }
301
302 /*
303 ** TH1 command: enable_htmlify ?BOOLEAN?
304 **
305 ** Enable or disable the HTML escaping done by all output which
306 ** originates from TH1 (via sendText()).
307 **
308 ** If passed no arguments it instead returns 0 or 1 to indicate the
309 ** current state.
310 */
311 static int enableHtmlifyCmd(
312 Th_Interp *interp,
313 void *p,
314 int argc,
315 const char **argv,
316 int *argl
317 ){
318 int rc = 0, buul;
319 if( argc>3 ){
320 return Th_WrongNumArgs(interp,
321 "enable_htmlify [TRACE_LABEL] ?BOOLEAN?");
322 }
323 buul = (TH_INIT_NO_ENCODE & g.th1Flags) ? 0 : 1;
324 Th_SetResultInt(g.interp, buul);
325 if(argc>1){
326 if( g.thTrace ){
327 Th_Trace("enable_htmlify {%.*s} -> %d<br>\n",
328 TH1_LEN(argl[1]),argv[1],buul);
329 }
330 rc = Th_ToInt(interp, argv[argc-1], argl[argc-1], &buul);
331 if(!rc){
332 if(buul){
333 g.th1Flags &= ~TH_INIT_NO_ENCODE;
334 }else{
335 g.th1Flags |= TH_INIT_NO_ENCODE;
336 }
337 }
338 }
339 return rc;
340 }
341
342 /*
343 ** Returns a name for a TH1 return code.
344 */
345 const char *Th_ReturnCodeName(int rc, int nullIfOk){
346 static char zRc[32];
@@ -376,23 +334,19 @@
376
377 /*
378 ** Send text to the appropriate output: If pOut is not NULL, it is
379 ** appended there, else to the console or to the CGI reply buffer.
380 ** Escape all characters with special meaning to HTML if the encode
381 ** parameter is true, with the exception that that flag is ignored if
382 ** g.th1Flags has the TH_INIT_NO_ENCODE flag.
383 **
384 ** If pOut is NULL and the global pThOut is not then that blob
385 ** is used for output.
386 */
387 static void sendText(Blob *pOut, const char *z, int n, int encode){
388 if(0==pOut && pThOut!=0){
389 pOut = pThOut;
390 }
391 if(TH_INIT_NO_ENCODE & g.th1Flags){
392 encode = 0;
393 }
394 if( enableOutput && n ){
395 if( n<0 ){
396 n = strlen(z);
397 }else{
398 n = TH1_LEN(n);
@@ -2429,11 +2383,10 @@
2429 {"copybtn", copybtnCmd, 0},
2430 {"date", dateCmd, 0},
2431 {"decorate", wikiCmd, (void*)&aFlags[2]},
2432 {"defHeader", defHeaderCmd, 0},
2433 {"dir", dirCmd, 0},
2434 {"enable_htmlify",enableHtmlifyCmd, 0},
2435 {"enable_output", enableOutputCmd, 0},
2436 {"encode64", encode64Cmd, 0},
2437 {"getParameter", getParameterCmd, 0},
2438 {"glob_match", globMatchCmd, 0},
2439 {"globalState", globalStateCmd, 0},
@@ -3047,12 +3000,11 @@
3047 ** e.g. via the "render" script function binding, need to use the
3048 ** pThOut blob in order to avoid out-of-order output if
3049 ** Th_SetOutputBlob() has been called. If it has not been called,
3050 ** pThOut will be 0, which will redirect the output to CGI/stdout,
3051 ** as appropriate. We need to pass on g.th1Flags for the case of
3052 ** recursive calls, so that, e.g., TH_INIT_NO_ENCODE does not get
3053 ** inadvertently toggled off by a recursive call.
3054 */;
3055 }
3056
3057 /*
3058 ** SETTING: vuln-report width=8 default=log
3059
--- src/th_main.c
+++ src/th_main.c
@@ -31,13 +31,11 @@
31 #define TH_INIT_NEED_CONFIG ((u32)0x00000001) /* Open configuration first? */
32 #define TH_INIT_FORCE_TCL ((u32)0x00000002) /* Force Tcl to be enabled? */
33 #define TH_INIT_FORCE_RESET ((u32)0x00000004) /* Force TH1 commands re-added? */
34 #define TH_INIT_FORCE_SETUP ((u32)0x00000008) /* Force eval of setup script? */
35 #define TH_INIT_NO_REPO ((u32)0x00000010) /* Skip opening repository. */
36 #define TH_INIT_MASK ((u32)0x0000001F) /* All possible init flags. */
 
 
37
38 /*
39 ** Useful and/or "well-known" combinations of flag values.
40 */
41 #define TH_INIT_DEFAULT (TH_INIT_NONE) /* Default flags. */
@@ -297,50 +295,10 @@
295 TH1_LEN(argl[1]),argv[1],enableOutput);
296 }
297 return rc;
298 }
299
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
300 /*
301 ** Returns a name for a TH1 return code.
302 */
303 const char *Th_ReturnCodeName(int rc, int nullIfOk){
304 static char zRc[32];
@@ -376,23 +334,19 @@
334
335 /*
336 ** Send text to the appropriate output: If pOut is not NULL, it is
337 ** appended there, else to the console or to the CGI reply buffer.
338 ** Escape all characters with special meaning to HTML if the encode
339 ** parameter is true.
 
340 **
341 ** If pOut is NULL and the global pThOut is not then that blob
342 ** is used for output.
343 */
344 static void sendText(Blob *pOut, const char *z, int n, int encode){
345 if(0==pOut && pThOut!=0){
346 pOut = pThOut;
347 }
 
 
 
348 if( enableOutput && n ){
349 if( n<0 ){
350 n = strlen(z);
351 }else{
352 n = TH1_LEN(n);
@@ -2429,11 +2383,10 @@
2383 {"copybtn", copybtnCmd, 0},
2384 {"date", dateCmd, 0},
2385 {"decorate", wikiCmd, (void*)&aFlags[2]},
2386 {"defHeader", defHeaderCmd, 0},
2387 {"dir", dirCmd, 0},
 
2388 {"enable_output", enableOutputCmd, 0},
2389 {"encode64", encode64Cmd, 0},
2390 {"getParameter", getParameterCmd, 0},
2391 {"glob_match", globMatchCmd, 0},
2392 {"globalState", globalStateCmd, 0},
@@ -3047,12 +3000,11 @@
3000 ** e.g. via the "render" script function binding, need to use the
3001 ** pThOut blob in order to avoid out-of-order output if
3002 ** Th_SetOutputBlob() has been called. If it has not been called,
3003 ** pThOut will be 0, which will redirect the output to CGI/stdout,
3004 ** as appropriate. We need to pass on g.th1Flags for the case of
3005 ** recursive calls.
 
3006 */;
3007 }
3008
3009 /*
3010 ** SETTING: vuln-report width=8 default=log
3011
--- src/th_tcl.c
+++ src/th_tcl.c
@@ -24,10 +24,14 @@
2424
2525
#include "sqlite3.h"
2626
#include "th.h"
2727
#include "tcl.h"
2828
29
+#if TCL_MAJOR_VERSION<9 && !defined(Tcl_Size)
30
+# define Tcl_Size int
31
+#endif
32
+
2933
/*
3034
** This macro is used to verify that the header version of Tcl meets some
3135
** minimum requirement.
3236
*/
3337
#define MINIMUM_TCL_VERSION(major, minor) \
@@ -183,11 +187,15 @@
183187
** the only Tcl API functions that MUST be called prior to being able to call
184188
** Tcl_InitStubs (i.e. because it requires a Tcl interpreter). For complete
185189
** cleanup if the Tcl stubs initialization fails somehow, the Tcl_DeleteInterp
186190
** and Tcl_Finalize function types are also required.
187191
*/
192
+#if TCL_MAJOR_VERSION>=9
188193
typedef const char *(tcl_FindExecutableProc) (const char *);
194
+#else
195
+typedef void (tcl_FindExecutableProc) (const char *);
196
+#endif
189197
typedef Tcl_Interp *(tcl_CreateInterpProc) (void);
190198
typedef void (tcl_DeleteInterpProc) (Tcl_Interp *);
191199
typedef void (tcl_FinalizeProc) (void);
192200
193201
/*
194202
--- src/th_tcl.c
+++ src/th_tcl.c
@@ -24,10 +24,14 @@
24
25 #include "sqlite3.h"
26 #include "th.h"
27 #include "tcl.h"
28
 
 
 
 
29 /*
30 ** This macro is used to verify that the header version of Tcl meets some
31 ** minimum requirement.
32 */
33 #define MINIMUM_TCL_VERSION(major, minor) \
@@ -183,11 +187,15 @@
183 ** the only Tcl API functions that MUST be called prior to being able to call
184 ** Tcl_InitStubs (i.e. because it requires a Tcl interpreter). For complete
185 ** cleanup if the Tcl stubs initialization fails somehow, the Tcl_DeleteInterp
186 ** and Tcl_Finalize function types are also required.
187 */
 
188 typedef const char *(tcl_FindExecutableProc) (const char *);
 
 
 
189 typedef Tcl_Interp *(tcl_CreateInterpProc) (void);
190 typedef void (tcl_DeleteInterpProc) (Tcl_Interp *);
191 typedef void (tcl_FinalizeProc) (void);
192
193 /*
194
--- src/th_tcl.c
+++ src/th_tcl.c
@@ -24,10 +24,14 @@
24
25 #include "sqlite3.h"
26 #include "th.h"
27 #include "tcl.h"
28
29 #if TCL_MAJOR_VERSION<9 && !defined(Tcl_Size)
30 # define Tcl_Size int
31 #endif
32
33 /*
34 ** This macro is used to verify that the header version of Tcl meets some
35 ** minimum requirement.
36 */
37 #define MINIMUM_TCL_VERSION(major, minor) \
@@ -183,11 +187,15 @@
187 ** the only Tcl API functions that MUST be called prior to being able to call
188 ** Tcl_InitStubs (i.e. because it requires a Tcl interpreter). For complete
189 ** cleanup if the Tcl stubs initialization fails somehow, the Tcl_DeleteInterp
190 ** and Tcl_Finalize function types are also required.
191 */
192 #if TCL_MAJOR_VERSION>=9
193 typedef const char *(tcl_FindExecutableProc) (const char *);
194 #else
195 typedef void (tcl_FindExecutableProc) (const char *);
196 #endif
197 typedef Tcl_Interp *(tcl_CreateInterpProc) (void);
198 typedef void (tcl_DeleteInterpProc) (Tcl_Interp *);
199 typedef void (tcl_FinalizeProc) (void);
200
201 /*
202
+47 -11
--- src/timeline.c
+++ src/timeline.c
@@ -1273,11 +1273,11 @@
12731273
*/
12741274
static void addFileGlobExclusion(
12751275
const char *zChng, /* The filename GLOB list */
12761276
Blob *pSql /* The SELECT statement under construction */
12771277
){
1278
- if( zChng==0 || zChng[0]==0 ) return;
1278
+ if( zChng==0 ) return;
12791279
blob_append_sql(pSql," AND event.objid IN ("
12801280
"SELECT mlink.mid FROM mlink, filename\n"
12811281
" WHERE mlink.fnid=filename.fnid\n"
12821282
" AND %s)",
12831283
glob_expr("filename.name", mprintf("\"%s\"", zChng)));
@@ -1284,14 +1284,33 @@
12841284
}
12851285
static void addFileGlobDescription(
12861286
const char *zChng, /* The filename GLOB list */
12871287
Blob *pDescription /* Result description */
12881288
){
1289
- if( zChng==0 || zChng[0]==0 ) return;
1289
+ if( zChng==0 ) return;
12901290
blob_appendf(pDescription, " that include changes to files matching '%h'",
12911291
zChng);
12921292
}
1293
+
1294
+/*
1295
+** If zChng is not NULL, then use it as a comma-separated list of
1296
+** glob patterns for filenames, and remove from the "ok" table any
1297
+** check-ins that do not modify one or more of the files identified
1298
+** by zChng.
1299
+*/
1300
+static void removeFileGlobFromOk(
1301
+ const char *zChng /* The filename GLOB list */
1302
+){
1303
+ if( zChng==0 ) return;
1304
+ db_multi_exec(
1305
+ "DELETE FROM ok WHERE rid NOT IN (\n"
1306
+ " SELECT mlink.mid FROM mlink, filename\n"
1307
+ " WHERE mlink.fnid=filename.fnid\n"
1308
+ " AND %z);\n",
1309
+ glob_expr("filename.name", zChng)
1310
+ );
1311
+}
12931312
12941313
/*
12951314
** Similar to fossil_expand_datetime()
12961315
**
12971316
** Add missing "-" characters into a date/time. Examples:
@@ -1777,10 +1796,11 @@
17771796
nEntry = 0;
17781797
useDividers = 0;
17791798
cgi_replace_query_parameter("d",fossil_strdup(z));
17801799
zDPNameD = zDPNameP = z;
17811800
}
1801
+ if( zChng && zChng[0]==0 ) zChng = 0;
17821802
17831803
/* Undocumented query parameter to set JS mode */
17841804
builtin_set_js_delivery_mode(P("jsmode"),1);
17851805
17861806
secondaryRid = name_to_typed_rid(P("sel2"),"ci");
@@ -2175,11 +2195,11 @@
21752195
}
21762196
db_multi_exec("INSERT OR IGNORE INTO pathnode SELECT x FROM related");
21772197
}
21782198
add_extra_rids("pathnode",P("x"));
21792199
blob_append_sql(&sql, " AND event.objid IN pathnode");
2180
- if( zChng && zChng[0] ){
2200
+ if( zChng ){
21812201
db_multi_exec(
21822202
"DELETE FROM pathnode\n"
21832203
" WHERE NOT EXISTS(SELECT 1 FROM mlink, filename\n"
21842204
" WHERE mlink.mid=x\n"
21852205
" AND mlink.fnid=filename.fnid\n"
@@ -2299,14 +2319,16 @@
22992319
db_multi_exec(
23002320
"INSERT INTO ok_d SELECT rid FROM ok;"
23012321
"DELETE FROM ok;"
23022322
);
23032323
}else{
2324
+ removeFileGlobFromOk(zChng);
23042325
nd = db_int(0, "SELECT count(*)-1 FROM ok");
23052326
if( nd>=0 ) db_multi_exec("%s", blob_sql_text(&sql));
23062327
if( nd>0 || p_rid==0 ){
2307
- blob_appendf(&desc, "%d descendant%s", nd,(1==nd)?"":"s");
2328
+ blob_appendf(&desc, "%d descendant%s",
2329
+ nd>=0 ? nd : 0,(1==nd)?"":"s");
23082330
}
23092331
if( useDividers && !selectedRid ) selectedRid = d_rid;
23102332
db_multi_exec("DELETE FROM ok");
23112333
}
23122334
}
@@ -2335,30 +2357,34 @@
23352357
db_multi_exec("INSERT OR IGNORE INTO ok VALUES(%d)", ridBackTo);
23362358
bBackAdded = 1;
23372359
}
23382360
if( bSeparateDandP ){
23392361
db_multi_exec("DELETE FROM ok WHERE rid NOT IN ok_d;");
2362
+ removeFileGlobFromOk(zChng);
23402363
db_multi_exec("%s", blob_sql_text(&sql));
23412364
}else{
2365
+ removeFileGlobFromOk(zChng);
23422366
np = db_int(0, "SELECT count(*)-1 FROM ok");
23432367
if( np>0 || nd==0 ){
23442368
if( nd>0 ) blob_appendf(&desc, " and ");
2345
- blob_appendf(&desc, "%d ancestor%s", np, (1==np)?"":"s");
2369
+ blob_appendf(&desc, "%d ancestor%s",
2370
+ np>=0 ? np : 0, (1==np)?"":"s");
23462371
db_multi_exec("%s", blob_sql_text(&sql));
23472372
}
23482373
if( useDividers && !selectedRid ) selectedRid = p_rid;
23492374
}
23502375
}
2376
+
23512377
if( bSeparateDandP ){
23522378
int n = db_int(0, "SELECT count(*) FROM ok");
23532379
blob_reset(&desc);
23542380
blob_appendf(&desc,
2355
- "%d check-ins that are both ancestors of %z%h</a>"
2356
- " and descendants of %z%h</a>",
2381
+ "%d check-ins that are derived from %z%h</a>"
2382
+ " and contribute to %z%h</a>",
23572383
n,
2358
- href("%R/info?name=%h",zDPNameP),zDPNameP,
2359
- href("%R/info?name=%h",zDPNameD),zDPNameD
2384
+ href("%R/info?name=%h",zDPNameD),zDPNameD,
2385
+ href("%R/info?name=%h",zDPNameP),zDPNameP
23602386
);
23612387
ridBackTo = 0;
23622388
ridFwdTo = 0;
23632389
}else{
23642390
blob_appendf(&desc, " of %z%h</a>",
@@ -2392,10 +2418,14 @@
23922418
blob_appendf(&desc, " up to %z%h</a>%s",
23932419
href("%R/info?name=%h",zFwdTo), zFwdTo,
23942420
bFwdAdded ? " (not a direct descendant)":"");
23952421
}
23962422
}
2423
+ if( zChng ){
2424
+ if( strstr(blob_str(&desc)," that ") ) blob_appendf(&desc, " and");
2425
+ blob_appendf(&desc, " that make changes to files matching \"%h\"", zChng);
2426
+ }
23972427
if( advancedMenu ){
23982428
style_submenu_checkbox("v", "Files", (zType[0]!='a' && zType[0]!='c'),0);
23992429
}
24002430
style_submenu_entry("n","Max:",4,0);
24012431
timeline_y_submenu(1);
@@ -3816,13 +3846,19 @@
38163846
" AND (tagxref.value IS NULL OR tagxref.value='%q')",
38173847
zBr, zBr, zBr, TAG_BRANCH, zBr, zBr);
38183848
}
38193849
38203850
if( mode==TIMELINE_MODE_AFTER ){
3851
+ int lim = n;
3852
+ if( n == 0 ){
3853
+ lim = -1; /* 0 means no limit */
3854
+ }else if( n < 0 ){
3855
+ lim = -n;
3856
+ }
38213857
/* Complete the above outer select. */
38223858
blob_append_sql(&sql,
3823
- "\nORDER BY event.mtime LIMIT abs(%d)) t ORDER BY t.mDateTime DESC;", n);
3859
+ "\nORDER BY event.mtime LIMIT %d) t ORDER BY t.mDateTime DESC;", lim);
38243860
}else{
38253861
blob_append_sql(&sql, "\nORDER BY event.mtime DESC");
38263862
}
38273863
if( iOffset>0 ){
38283864
/* Don't handle LIMIT here, otherwise print_timeline()
@@ -3847,11 +3883,11 @@
38473883
** Query parameters:
38483884
**
38493885
** today=DATE Use DATE as today's date
38503886
*/
38513887
void thisdayinhistory_page(void){
3852
- static int aYearsAgo[] = { 1, 2, 3, 4, 5, 10, 15, 20, 30, 40, 50, 75, 100 };
3888
+ static int aYearsAgo[] = { 1,2,3,4,5,10,15,20,25,30,40,50,75,100 };
38533889
const char *zToday;
38543890
char *zStartOfProject;
38553891
int i;
38563892
Stmt q;
38573893
char *z;
38583894
--- src/timeline.c
+++ src/timeline.c
@@ -1273,11 +1273,11 @@
1273 */
1274 static void addFileGlobExclusion(
1275 const char *zChng, /* The filename GLOB list */
1276 Blob *pSql /* The SELECT statement under construction */
1277 ){
1278 if( zChng==0 || zChng[0]==0 ) return;
1279 blob_append_sql(pSql," AND event.objid IN ("
1280 "SELECT mlink.mid FROM mlink, filename\n"
1281 " WHERE mlink.fnid=filename.fnid\n"
1282 " AND %s)",
1283 glob_expr("filename.name", mprintf("\"%s\"", zChng)));
@@ -1284,14 +1284,33 @@
1284 }
1285 static void addFileGlobDescription(
1286 const char *zChng, /* The filename GLOB list */
1287 Blob *pDescription /* Result description */
1288 ){
1289 if( zChng==0 || zChng[0]==0 ) return;
1290 blob_appendf(pDescription, " that include changes to files matching '%h'",
1291 zChng);
1292 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1293
1294 /*
1295 ** Similar to fossil_expand_datetime()
1296 **
1297 ** Add missing "-" characters into a date/time. Examples:
@@ -1777,10 +1796,11 @@
1777 nEntry = 0;
1778 useDividers = 0;
1779 cgi_replace_query_parameter("d",fossil_strdup(z));
1780 zDPNameD = zDPNameP = z;
1781 }
 
1782
1783 /* Undocumented query parameter to set JS mode */
1784 builtin_set_js_delivery_mode(P("jsmode"),1);
1785
1786 secondaryRid = name_to_typed_rid(P("sel2"),"ci");
@@ -2175,11 +2195,11 @@
2175 }
2176 db_multi_exec("INSERT OR IGNORE INTO pathnode SELECT x FROM related");
2177 }
2178 add_extra_rids("pathnode",P("x"));
2179 blob_append_sql(&sql, " AND event.objid IN pathnode");
2180 if( zChng && zChng[0] ){
2181 db_multi_exec(
2182 "DELETE FROM pathnode\n"
2183 " WHERE NOT EXISTS(SELECT 1 FROM mlink, filename\n"
2184 " WHERE mlink.mid=x\n"
2185 " AND mlink.fnid=filename.fnid\n"
@@ -2299,14 +2319,16 @@
2299 db_multi_exec(
2300 "INSERT INTO ok_d SELECT rid FROM ok;"
2301 "DELETE FROM ok;"
2302 );
2303 }else{
 
2304 nd = db_int(0, "SELECT count(*)-1 FROM ok");
2305 if( nd>=0 ) db_multi_exec("%s", blob_sql_text(&sql));
2306 if( nd>0 || p_rid==0 ){
2307 blob_appendf(&desc, "%d descendant%s", nd,(1==nd)?"":"s");
 
2308 }
2309 if( useDividers && !selectedRid ) selectedRid = d_rid;
2310 db_multi_exec("DELETE FROM ok");
2311 }
2312 }
@@ -2335,30 +2357,34 @@
2335 db_multi_exec("INSERT OR IGNORE INTO ok VALUES(%d)", ridBackTo);
2336 bBackAdded = 1;
2337 }
2338 if( bSeparateDandP ){
2339 db_multi_exec("DELETE FROM ok WHERE rid NOT IN ok_d;");
 
2340 db_multi_exec("%s", blob_sql_text(&sql));
2341 }else{
 
2342 np = db_int(0, "SELECT count(*)-1 FROM ok");
2343 if( np>0 || nd==0 ){
2344 if( nd>0 ) blob_appendf(&desc, " and ");
2345 blob_appendf(&desc, "%d ancestor%s", np, (1==np)?"":"s");
 
2346 db_multi_exec("%s", blob_sql_text(&sql));
2347 }
2348 if( useDividers && !selectedRid ) selectedRid = p_rid;
2349 }
2350 }
 
2351 if( bSeparateDandP ){
2352 int n = db_int(0, "SELECT count(*) FROM ok");
2353 blob_reset(&desc);
2354 blob_appendf(&desc,
2355 "%d check-ins that are both ancestors of %z%h</a>"
2356 " and descendants of %z%h</a>",
2357 n,
2358 href("%R/info?name=%h",zDPNameP),zDPNameP,
2359 href("%R/info?name=%h",zDPNameD),zDPNameD
2360 );
2361 ridBackTo = 0;
2362 ridFwdTo = 0;
2363 }else{
2364 blob_appendf(&desc, " of %z%h</a>",
@@ -2392,10 +2418,14 @@
2392 blob_appendf(&desc, " up to %z%h</a>%s",
2393 href("%R/info?name=%h",zFwdTo), zFwdTo,
2394 bFwdAdded ? " (not a direct descendant)":"");
2395 }
2396 }
 
 
 
 
2397 if( advancedMenu ){
2398 style_submenu_checkbox("v", "Files", (zType[0]!='a' && zType[0]!='c'),0);
2399 }
2400 style_submenu_entry("n","Max:",4,0);
2401 timeline_y_submenu(1);
@@ -3816,13 +3846,19 @@
3816 " AND (tagxref.value IS NULL OR tagxref.value='%q')",
3817 zBr, zBr, zBr, TAG_BRANCH, zBr, zBr);
3818 }
3819
3820 if( mode==TIMELINE_MODE_AFTER ){
 
 
 
 
 
 
3821 /* Complete the above outer select. */
3822 blob_append_sql(&sql,
3823 "\nORDER BY event.mtime LIMIT abs(%d)) t ORDER BY t.mDateTime DESC;", n);
3824 }else{
3825 blob_append_sql(&sql, "\nORDER BY event.mtime DESC");
3826 }
3827 if( iOffset>0 ){
3828 /* Don't handle LIMIT here, otherwise print_timeline()
@@ -3847,11 +3883,11 @@
3847 ** Query parameters:
3848 **
3849 ** today=DATE Use DATE as today's date
3850 */
3851 void thisdayinhistory_page(void){
3852 static int aYearsAgo[] = { 1, 2, 3, 4, 5, 10, 15, 20, 30, 40, 50, 75, 100 };
3853 const char *zToday;
3854 char *zStartOfProject;
3855 int i;
3856 Stmt q;
3857 char *z;
3858
--- src/timeline.c
+++ src/timeline.c
@@ -1273,11 +1273,11 @@
1273 */
1274 static void addFileGlobExclusion(
1275 const char *zChng, /* The filename GLOB list */
1276 Blob *pSql /* The SELECT statement under construction */
1277 ){
1278 if( zChng==0 ) return;
1279 blob_append_sql(pSql," AND event.objid IN ("
1280 "SELECT mlink.mid FROM mlink, filename\n"
1281 " WHERE mlink.fnid=filename.fnid\n"
1282 " AND %s)",
1283 glob_expr("filename.name", mprintf("\"%s\"", zChng)));
@@ -1284,14 +1284,33 @@
1284 }
1285 static void addFileGlobDescription(
1286 const char *zChng, /* The filename GLOB list */
1287 Blob *pDescription /* Result description */
1288 ){
1289 if( zChng==0 ) return;
1290 blob_appendf(pDescription, " that include changes to files matching '%h'",
1291 zChng);
1292 }
1293
1294 /*
1295 ** If zChng is not NULL, then use it as a comma-separated list of
1296 ** glob patterns for filenames, and remove from the "ok" table any
1297 ** check-ins that do not modify one or more of the files identified
1298 ** by zChng.
1299 */
1300 static void removeFileGlobFromOk(
1301 const char *zChng /* The filename GLOB list */
1302 ){
1303 if( zChng==0 ) return;
1304 db_multi_exec(
1305 "DELETE FROM ok WHERE rid NOT IN (\n"
1306 " SELECT mlink.mid FROM mlink, filename\n"
1307 " WHERE mlink.fnid=filename.fnid\n"
1308 " AND %z);\n",
1309 glob_expr("filename.name", zChng)
1310 );
1311 }
1312
1313 /*
1314 ** Similar to fossil_expand_datetime()
1315 **
1316 ** Add missing "-" characters into a date/time. Examples:
@@ -1777,10 +1796,11 @@
1796 nEntry = 0;
1797 useDividers = 0;
1798 cgi_replace_query_parameter("d",fossil_strdup(z));
1799 zDPNameD = zDPNameP = z;
1800 }
1801 if( zChng && zChng[0]==0 ) zChng = 0;
1802
1803 /* Undocumented query parameter to set JS mode */
1804 builtin_set_js_delivery_mode(P("jsmode"),1);
1805
1806 secondaryRid = name_to_typed_rid(P("sel2"),"ci");
@@ -2175,11 +2195,11 @@
2195 }
2196 db_multi_exec("INSERT OR IGNORE INTO pathnode SELECT x FROM related");
2197 }
2198 add_extra_rids("pathnode",P("x"));
2199 blob_append_sql(&sql, " AND event.objid IN pathnode");
2200 if( zChng ){
2201 db_multi_exec(
2202 "DELETE FROM pathnode\n"
2203 " WHERE NOT EXISTS(SELECT 1 FROM mlink, filename\n"
2204 " WHERE mlink.mid=x\n"
2205 " AND mlink.fnid=filename.fnid\n"
@@ -2299,14 +2319,16 @@
2319 db_multi_exec(
2320 "INSERT INTO ok_d SELECT rid FROM ok;"
2321 "DELETE FROM ok;"
2322 );
2323 }else{
2324 removeFileGlobFromOk(zChng);
2325 nd = db_int(0, "SELECT count(*)-1 FROM ok");
2326 if( nd>=0 ) db_multi_exec("%s", blob_sql_text(&sql));
2327 if( nd>0 || p_rid==0 ){
2328 blob_appendf(&desc, "%d descendant%s",
2329 nd>=0 ? nd : 0,(1==nd)?"":"s");
2330 }
2331 if( useDividers && !selectedRid ) selectedRid = d_rid;
2332 db_multi_exec("DELETE FROM ok");
2333 }
2334 }
@@ -2335,30 +2357,34 @@
2357 db_multi_exec("INSERT OR IGNORE INTO ok VALUES(%d)", ridBackTo);
2358 bBackAdded = 1;
2359 }
2360 if( bSeparateDandP ){
2361 db_multi_exec("DELETE FROM ok WHERE rid NOT IN ok_d;");
2362 removeFileGlobFromOk(zChng);
2363 db_multi_exec("%s", blob_sql_text(&sql));
2364 }else{
2365 removeFileGlobFromOk(zChng);
2366 np = db_int(0, "SELECT count(*)-1 FROM ok");
2367 if( np>0 || nd==0 ){
2368 if( nd>0 ) blob_appendf(&desc, " and ");
2369 blob_appendf(&desc, "%d ancestor%s",
2370 np>=0 ? np : 0, (1==np)?"":"s");
2371 db_multi_exec("%s", blob_sql_text(&sql));
2372 }
2373 if( useDividers && !selectedRid ) selectedRid = p_rid;
2374 }
2375 }
2376
2377 if( bSeparateDandP ){
2378 int n = db_int(0, "SELECT count(*) FROM ok");
2379 blob_reset(&desc);
2380 blob_appendf(&desc,
2381 "%d check-ins that are derived from %z%h</a>"
2382 " and contribute to %z%h</a>",
2383 n,
2384 href("%R/info?name=%h",zDPNameD),zDPNameD,
2385 href("%R/info?name=%h",zDPNameP),zDPNameP
2386 );
2387 ridBackTo = 0;
2388 ridFwdTo = 0;
2389 }else{
2390 blob_appendf(&desc, " of %z%h</a>",
@@ -2392,10 +2418,14 @@
2418 blob_appendf(&desc, " up to %z%h</a>%s",
2419 href("%R/info?name=%h",zFwdTo), zFwdTo,
2420 bFwdAdded ? " (not a direct descendant)":"");
2421 }
2422 }
2423 if( zChng ){
2424 if( strstr(blob_str(&desc)," that ") ) blob_appendf(&desc, " and");
2425 blob_appendf(&desc, " that make changes to files matching \"%h\"", zChng);
2426 }
2427 if( advancedMenu ){
2428 style_submenu_checkbox("v", "Files", (zType[0]!='a' && zType[0]!='c'),0);
2429 }
2430 style_submenu_entry("n","Max:",4,0);
2431 timeline_y_submenu(1);
@@ -3816,13 +3846,19 @@
3846 " AND (tagxref.value IS NULL OR tagxref.value='%q')",
3847 zBr, zBr, zBr, TAG_BRANCH, zBr, zBr);
3848 }
3849
3850 if( mode==TIMELINE_MODE_AFTER ){
3851 int lim = n;
3852 if( n == 0 ){
3853 lim = -1; /* 0 means no limit */
3854 }else if( n < 0 ){
3855 lim = -n;
3856 }
3857 /* Complete the above outer select. */
3858 blob_append_sql(&sql,
3859 "\nORDER BY event.mtime LIMIT %d) t ORDER BY t.mDateTime DESC;", lim);
3860 }else{
3861 blob_append_sql(&sql, "\nORDER BY event.mtime DESC");
3862 }
3863 if( iOffset>0 ){
3864 /* Don't handle LIMIT here, otherwise print_timeline()
@@ -3847,11 +3883,11 @@
3883 ** Query parameters:
3884 **
3885 ** today=DATE Use DATE as today's date
3886 */
3887 void thisdayinhistory_page(void){
3888 static int aYearsAgo[] = { 1,2,3,4,5,10,15,20,25,30,40,50,75,100 };
3889 const char *zToday;
3890 char *zStartOfProject;
3891 int i;
3892 Stmt q;
3893 char *z;
3894
-4
--- src/tkt.c
+++ src/tkt.c
@@ -776,14 +776,10 @@
776776
style_submenu_element("Timeline", "%R/info/%T", zUuid);
777777
}
778778
zFullName = db_text(0,
779779
"SELECT tkt_uuid FROM ticket"
780780
" WHERE tkt_uuid GLOB '%q*'", zUuid);
781
- if( g.perm.WrWiki && g.perm.WrTkt ){
782
- style_submenu_element("Edit Description",
783
- "%R/wikiedit?name=ticket/%T", zFullName);
784
- }
785781
if( g.thTrace ) Th_Trace("BEGIN_TKTVIEW<br>\n", -1);
786782
ticket_init();
787783
initializeVariablesFromCGI();
788784
getAllTicketFields();
789785
initializeVariablesFromDb();
790786
--- src/tkt.c
+++ src/tkt.c
@@ -776,14 +776,10 @@
776 style_submenu_element("Timeline", "%R/info/%T", zUuid);
777 }
778 zFullName = db_text(0,
779 "SELECT tkt_uuid FROM ticket"
780 " WHERE tkt_uuid GLOB '%q*'", zUuid);
781 if( g.perm.WrWiki && g.perm.WrTkt ){
782 style_submenu_element("Edit Description",
783 "%R/wikiedit?name=ticket/%T", zFullName);
784 }
785 if( g.thTrace ) Th_Trace("BEGIN_TKTVIEW<br>\n", -1);
786 ticket_init();
787 initializeVariablesFromCGI();
788 getAllTicketFields();
789 initializeVariablesFromDb();
790
--- src/tkt.c
+++ src/tkt.c
@@ -776,14 +776,10 @@
776 style_submenu_element("Timeline", "%R/info/%T", zUuid);
777 }
778 zFullName = db_text(0,
779 "SELECT tkt_uuid FROM ticket"
780 " WHERE tkt_uuid GLOB '%q*'", zUuid);
 
 
 
 
781 if( g.thTrace ) Th_Trace("BEGIN_TKTVIEW<br>\n", -1);
782 ticket_init();
783 initializeVariablesFromCGI();
784 getAllTicketFields();
785 initializeVariablesFromDb();
786
--- src/tktsetup.c
+++ src/tktsetup.c
@@ -496,10 +496,13 @@
496496
@ }
497497
@
498498
@ if {[capexpr {n}]} {
499499
@ submenu link "Copy Ticket" /tktnew/$tkt_uuid
500500
@ }
501
+@ if {[capexpr {nk}]} {
502
+@ submenu link "Edit Wiki" /wikiedit?name=ticket/$tkt_uuid
503
+@ }
501504
@ </th1>
502505
@ <tr><td class="tktDspLabel">Title:</td>
503506
@ <td class="tktDspValue" colspan="3">
504507
@ $<title>
505508
@ </td></tr>
506509
--- src/tktsetup.c
+++ src/tktsetup.c
@@ -496,10 +496,13 @@
496 @ }
497 @
498 @ if {[capexpr {n}]} {
499 @ submenu link "Copy Ticket" /tktnew/$tkt_uuid
500 @ }
 
 
 
501 @ </th1>
502 @ <tr><td class="tktDspLabel">Title:</td>
503 @ <td class="tktDspValue" colspan="3">
504 @ $<title>
505 @ </td></tr>
506
--- src/tktsetup.c
+++ src/tktsetup.c
@@ -496,10 +496,13 @@
496 @ }
497 @
498 @ if {[capexpr {n}]} {
499 @ submenu link "Copy Ticket" /tktnew/$tkt_uuid
500 @ }
501 @ if {[capexpr {nk}]} {
502 @ submenu link "Edit Wiki" /wikiedit?name=ticket/$tkt_uuid
503 @ }
504 @ </th1>
505 @ <tr><td class="tktDspLabel">Title:</td>
506 @ <td class="tktDspValue" colspan="3">
507 @ $<title>
508 @ </td></tr>
509
+34 -19
--- src/winfile.c
+++ src/winfile.c
@@ -304,39 +304,47 @@
304304
*/
305305
int win32_filenames_equal_nocase(
306306
const wchar_t *fn1,
307307
const wchar_t *fn2
308308
){
309
- static FARPROC fnCompareStringOrdinal;
310
- static FARPROC fnRtlInitUnicodeString;
311
- static FARPROC fnRtlEqualUnicodeString;
309
+ /* ---- Data types used by dynamically loaded API functions. -------------- */
310
+ typedef struct { /* UNICODE_STRING from <ntdef.h> */
311
+ USHORT Length;
312
+ USHORT MaximumLength;
313
+ PWSTR Buffer;
314
+ } MY_UNICODE_STRING;
315
+ /* ---- Prototypes for dynamically loaded API functions. ------------------ */
316
+ typedef int (WINAPI *FNCOMPARESTRINGORDINAL)(LPCWCH,int,LPCWCH,int,BOOL);
317
+ typedef VOID (NTAPI *FNRTLINITUNICODESTRING)(MY_UNICODE_STRING*,PCWSTR);
318
+ typedef BOOLEAN (NTAPI *FNRTLEQUALUNICODESTRING)
319
+ (MY_UNICODE_STRING*,MY_UNICODE_STRING*,BOOLEAN);
320
+ /* ------------------------------------------------------------------------ */
321
+ static FNCOMPARESTRINGORDINAL fnCompareStringOrdinal;
322
+ static FNRTLINITUNICODESTRING fnRtlInitUnicodeString;
323
+ static FNRTLEQUALUNICODESTRING fnRtlEqualUnicodeString;
312324
static int loaded_CompareStringOrdinal;
313325
static int loaded_RtlUnicodeStringAPIs;
314326
if( !loaded_CompareStringOrdinal ){
315
- fnCompareStringOrdinal =
327
+ fnCompareStringOrdinal = (FNCOMPARESTRINGORDINAL)
316328
GetProcAddress(GetModuleHandleA("kernel32"),"CompareStringOrdinal");
317329
loaded_CompareStringOrdinal = 1;
318330
}
319331
if( fnCompareStringOrdinal ){
320332
return fnCompareStringOrdinal(fn1,-1,fn2,-1,1)-2==0;
321333
}
322334
if( !loaded_RtlUnicodeStringAPIs ){
323
- fnRtlInitUnicodeString =
335
+ fnRtlInitUnicodeString = (FNRTLINITUNICODESTRING)
324336
GetProcAddress(GetModuleHandleA("ntdll"),"RtlInitUnicodeString");
325
- fnRtlEqualUnicodeString =
337
+ fnRtlEqualUnicodeString = (FNRTLEQUALUNICODESTRING)
326338
GetProcAddress(GetModuleHandleA("ntdll"),"RtlEqualUnicodeString");
327339
loaded_RtlUnicodeStringAPIs = 1;
328340
}
329341
if( fnRtlInitUnicodeString && fnRtlEqualUnicodeString ){
330
- struct { /* UNICODE_STRING from <ntdef.h> */
331
- unsigned short Length;
332
- unsigned short MaximumLength;
333
- wchar_t *Buffer;
334
- } u1, u2;
342
+ MY_UNICODE_STRING u1, u2;
335343
fnRtlInitUnicodeString(&u1,fn1);
336344
fnRtlInitUnicodeString(&u2,fn2);
337
- return (unsigned char)fnRtlEqualUnicodeString(&u1,&u2,1);
345
+ return (BOOLEAN/*unsigned char*/)fnRtlEqualUnicodeString(&u1,&u2,1);
338346
}
339347
/* In what kind of strange parallel universe are we? */
340348
return lstrcmpiW(fn1,fn2)==0;
341349
}
342350
@@ -461,11 +469,20 @@
461469
** is allocated by mprintf(), or NULL on failure.
462470
*/
463471
char *win32_file_id(
464472
const char *zFileName
465473
){
466
- static FARPROC fnGetFileInformationByHandleEx;
474
+ /* ---- Data types used by dynamically loaded API functions. -------------- */
475
+ typedef struct { /* FILE_ID_INFO from <winbase.h> */
476
+ ULONGLONG VolumeSerialNumber;
477
+ BYTE FileId[16];
478
+ } MY_FILE_ID_INFO;
479
+ /* ---- Prototypes for dynamically loaded API functions. ------------------ */
480
+ typedef int (WINAPI *FNGETFILEINFORMATIONBYHANDLEEX)
481
+ (HANDLE,int/*enum*/,MY_FILE_ID_INFO*,DWORD);
482
+ /* ------------------------------------------------------------------------ */
483
+ static FNGETFILEINFORMATIONBYHANDLEEX fnGetFileInformationByHandleEx;
467484
static int loaded_fnGetFileInformationByHandleEx;
468485
wchar_t *wzFileName = fossil_utf8_to_path(zFileName,0);
469486
HANDLE hFile;
470487
char *zFileId = 0;
471488
hFile = CreateFileW(
@@ -476,17 +493,15 @@
476493
OPEN_EXISTING,
477494
FILE_FLAG_BACKUP_SEMANTICS,
478495
NULL);
479496
if( hFile!=INVALID_HANDLE_VALUE ){
480497
BY_HANDLE_FILE_INFORMATION fi;
481
- struct { /* FILE_ID_INFO from <winbase.h> */
482
- u64 VolumeSerialNumber;
483
- unsigned char FileId[16];
484
- } fi2;
498
+ MY_FILE_ID_INFO fi2;
485499
if( !loaded_fnGetFileInformationByHandleEx ){
486
- fnGetFileInformationByHandleEx = GetProcAddress(
487
- GetModuleHandleA("kernel32"),"GetFileInformationByHandleEx");
500
+ fnGetFileInformationByHandleEx = (FNGETFILEINFORMATIONBYHANDLEEX)
501
+ GetProcAddress(
502
+ GetModuleHandleA("kernel32"),"GetFileInformationByHandleEx");
488503
loaded_fnGetFileInformationByHandleEx = 1;
489504
}
490505
if( fnGetFileInformationByHandleEx ){
491506
if( fnGetFileInformationByHandleEx(
492507
hFile,/*FileIdInfo*/0x12,&fi2,sizeof(fi2)) ){
493508
--- src/winfile.c
+++ src/winfile.c
@@ -304,39 +304,47 @@
304 */
305 int win32_filenames_equal_nocase(
306 const wchar_t *fn1,
307 const wchar_t *fn2
308 ){
309 static FARPROC fnCompareStringOrdinal;
310 static FARPROC fnRtlInitUnicodeString;
311 static FARPROC fnRtlEqualUnicodeString;
 
 
 
 
 
 
 
 
 
 
 
 
312 static int loaded_CompareStringOrdinal;
313 static int loaded_RtlUnicodeStringAPIs;
314 if( !loaded_CompareStringOrdinal ){
315 fnCompareStringOrdinal =
316 GetProcAddress(GetModuleHandleA("kernel32"),"CompareStringOrdinal");
317 loaded_CompareStringOrdinal = 1;
318 }
319 if( fnCompareStringOrdinal ){
320 return fnCompareStringOrdinal(fn1,-1,fn2,-1,1)-2==0;
321 }
322 if( !loaded_RtlUnicodeStringAPIs ){
323 fnRtlInitUnicodeString =
324 GetProcAddress(GetModuleHandleA("ntdll"),"RtlInitUnicodeString");
325 fnRtlEqualUnicodeString =
326 GetProcAddress(GetModuleHandleA("ntdll"),"RtlEqualUnicodeString");
327 loaded_RtlUnicodeStringAPIs = 1;
328 }
329 if( fnRtlInitUnicodeString && fnRtlEqualUnicodeString ){
330 struct { /* UNICODE_STRING from <ntdef.h> */
331 unsigned short Length;
332 unsigned short MaximumLength;
333 wchar_t *Buffer;
334 } u1, u2;
335 fnRtlInitUnicodeString(&u1,fn1);
336 fnRtlInitUnicodeString(&u2,fn2);
337 return (unsigned char)fnRtlEqualUnicodeString(&u1,&u2,1);
338 }
339 /* In what kind of strange parallel universe are we? */
340 return lstrcmpiW(fn1,fn2)==0;
341 }
342
@@ -461,11 +469,20 @@
461 ** is allocated by mprintf(), or NULL on failure.
462 */
463 char *win32_file_id(
464 const char *zFileName
465 ){
466 static FARPROC fnGetFileInformationByHandleEx;
 
 
 
 
 
 
 
 
 
467 static int loaded_fnGetFileInformationByHandleEx;
468 wchar_t *wzFileName = fossil_utf8_to_path(zFileName,0);
469 HANDLE hFile;
470 char *zFileId = 0;
471 hFile = CreateFileW(
@@ -476,17 +493,15 @@
476 OPEN_EXISTING,
477 FILE_FLAG_BACKUP_SEMANTICS,
478 NULL);
479 if( hFile!=INVALID_HANDLE_VALUE ){
480 BY_HANDLE_FILE_INFORMATION fi;
481 struct { /* FILE_ID_INFO from <winbase.h> */
482 u64 VolumeSerialNumber;
483 unsigned char FileId[16];
484 } fi2;
485 if( !loaded_fnGetFileInformationByHandleEx ){
486 fnGetFileInformationByHandleEx = GetProcAddress(
487 GetModuleHandleA("kernel32"),"GetFileInformationByHandleEx");
 
488 loaded_fnGetFileInformationByHandleEx = 1;
489 }
490 if( fnGetFileInformationByHandleEx ){
491 if( fnGetFileInformationByHandleEx(
492 hFile,/*FileIdInfo*/0x12,&fi2,sizeof(fi2)) ){
493
--- src/winfile.c
+++ src/winfile.c
@@ -304,39 +304,47 @@
304 */
305 int win32_filenames_equal_nocase(
306 const wchar_t *fn1,
307 const wchar_t *fn2
308 ){
309 /* ---- Data types used by dynamically loaded API functions. -------------- */
310 typedef struct { /* UNICODE_STRING from <ntdef.h> */
311 USHORT Length;
312 USHORT MaximumLength;
313 PWSTR Buffer;
314 } MY_UNICODE_STRING;
315 /* ---- Prototypes for dynamically loaded API functions. ------------------ */
316 typedef int (WINAPI *FNCOMPARESTRINGORDINAL)(LPCWCH,int,LPCWCH,int,BOOL);
317 typedef VOID (NTAPI *FNRTLINITUNICODESTRING)(MY_UNICODE_STRING*,PCWSTR);
318 typedef BOOLEAN (NTAPI *FNRTLEQUALUNICODESTRING)
319 (MY_UNICODE_STRING*,MY_UNICODE_STRING*,BOOLEAN);
320 /* ------------------------------------------------------------------------ */
321 static FNCOMPARESTRINGORDINAL fnCompareStringOrdinal;
322 static FNRTLINITUNICODESTRING fnRtlInitUnicodeString;
323 static FNRTLEQUALUNICODESTRING fnRtlEqualUnicodeString;
324 static int loaded_CompareStringOrdinal;
325 static int loaded_RtlUnicodeStringAPIs;
326 if( !loaded_CompareStringOrdinal ){
327 fnCompareStringOrdinal = (FNCOMPARESTRINGORDINAL)
328 GetProcAddress(GetModuleHandleA("kernel32"),"CompareStringOrdinal");
329 loaded_CompareStringOrdinal = 1;
330 }
331 if( fnCompareStringOrdinal ){
332 return fnCompareStringOrdinal(fn1,-1,fn2,-1,1)-2==0;
333 }
334 if( !loaded_RtlUnicodeStringAPIs ){
335 fnRtlInitUnicodeString = (FNRTLINITUNICODESTRING)
336 GetProcAddress(GetModuleHandleA("ntdll"),"RtlInitUnicodeString");
337 fnRtlEqualUnicodeString = (FNRTLEQUALUNICODESTRING)
338 GetProcAddress(GetModuleHandleA("ntdll"),"RtlEqualUnicodeString");
339 loaded_RtlUnicodeStringAPIs = 1;
340 }
341 if( fnRtlInitUnicodeString && fnRtlEqualUnicodeString ){
342 MY_UNICODE_STRING u1, u2;
 
 
 
 
343 fnRtlInitUnicodeString(&u1,fn1);
344 fnRtlInitUnicodeString(&u2,fn2);
345 return (BOOLEAN/*unsigned char*/)fnRtlEqualUnicodeString(&u1,&u2,1);
346 }
347 /* In what kind of strange parallel universe are we? */
348 return lstrcmpiW(fn1,fn2)==0;
349 }
350
@@ -461,11 +469,20 @@
469 ** is allocated by mprintf(), or NULL on failure.
470 */
471 char *win32_file_id(
472 const char *zFileName
473 ){
474 /* ---- Data types used by dynamically loaded API functions. -------------- */
475 typedef struct { /* FILE_ID_INFO from <winbase.h> */
476 ULONGLONG VolumeSerialNumber;
477 BYTE FileId[16];
478 } MY_FILE_ID_INFO;
479 /* ---- Prototypes for dynamically loaded API functions. ------------------ */
480 typedef int (WINAPI *FNGETFILEINFORMATIONBYHANDLEEX)
481 (HANDLE,int/*enum*/,MY_FILE_ID_INFO*,DWORD);
482 /* ------------------------------------------------------------------------ */
483 static FNGETFILEINFORMATIONBYHANDLEEX fnGetFileInformationByHandleEx;
484 static int loaded_fnGetFileInformationByHandleEx;
485 wchar_t *wzFileName = fossil_utf8_to_path(zFileName,0);
486 HANDLE hFile;
487 char *zFileId = 0;
488 hFile = CreateFileW(
@@ -476,17 +493,15 @@
493 OPEN_EXISTING,
494 FILE_FLAG_BACKUP_SEMANTICS,
495 NULL);
496 if( hFile!=INVALID_HANDLE_VALUE ){
497 BY_HANDLE_FILE_INFORMATION fi;
498 MY_FILE_ID_INFO fi2;
 
 
 
499 if( !loaded_fnGetFileInformationByHandleEx ){
500 fnGetFileInformationByHandleEx = (FNGETFILEINFORMATIONBYHANDLEEX)
501 GetProcAddress(
502 GetModuleHandleA("kernel32"),"GetFileInformationByHandleEx");
503 loaded_fnGetFileInformationByHandleEx = 1;
504 }
505 if( fnGetFileInformationByHandleEx ){
506 if( fnGetFileInformationByHandleEx(
507 hFile,/*FileIdInfo*/0x12,&fi2,sizeof(fi2)) ){
508
+2 -2
--- src/xfer.c
+++ src/xfer.c
@@ -2382,17 +2382,17 @@
23822382
if( nCycle==0 && db_is_writeable("repository") ){
23832383
xfer_syncwith(g.url.canonical, 0);
23842384
}
23852385
23862386
/* Output current stats */
2387
+ nRoundtrip++;
2388
+ nArtifactSent += xfer.nFileSent + xfer.nDeltaSent;
23872389
if( syncFlags & SYNC_VERBOSE ){
23882390
fossil_print(zValueFormat /*works-like:"%s%d%d%d%d"*/, "Sent:",
23892391
blob_size(&send), nCardSent+xfer.nGimmeSent+xfer.nIGotSent,
23902392
xfer.nFileSent, xfer.nDeltaSent);
23912393
}else{
2392
- nRoundtrip++;
2393
- nArtifactSent += xfer.nFileSent + xfer.nDeltaSent;
23942394
if( bOutIsTty!=0 ){
23952395
fossil_print(zBriefFormat /*works-like:"%d%d%d"*/,
23962396
nRoundtrip, nArtifactSent, nArtifactRcvd);
23972397
}
23982398
}
23992399
--- src/xfer.c
+++ src/xfer.c
@@ -2382,17 +2382,17 @@
2382 if( nCycle==0 && db_is_writeable("repository") ){
2383 xfer_syncwith(g.url.canonical, 0);
2384 }
2385
2386 /* Output current stats */
 
 
2387 if( syncFlags & SYNC_VERBOSE ){
2388 fossil_print(zValueFormat /*works-like:"%s%d%d%d%d"*/, "Sent:",
2389 blob_size(&send), nCardSent+xfer.nGimmeSent+xfer.nIGotSent,
2390 xfer.nFileSent, xfer.nDeltaSent);
2391 }else{
2392 nRoundtrip++;
2393 nArtifactSent += xfer.nFileSent + xfer.nDeltaSent;
2394 if( bOutIsTty!=0 ){
2395 fossil_print(zBriefFormat /*works-like:"%d%d%d"*/,
2396 nRoundtrip, nArtifactSent, nArtifactRcvd);
2397 }
2398 }
2399
--- src/xfer.c
+++ src/xfer.c
@@ -2382,17 +2382,17 @@
2382 if( nCycle==0 && db_is_writeable("repository") ){
2383 xfer_syncwith(g.url.canonical, 0);
2384 }
2385
2386 /* Output current stats */
2387 nRoundtrip++;
2388 nArtifactSent += xfer.nFileSent + xfer.nDeltaSent;
2389 if( syncFlags & SYNC_VERBOSE ){
2390 fossil_print(zValueFormat /*works-like:"%s%d%d%d%d"*/, "Sent:",
2391 blob_size(&send), nCardSent+xfer.nGimmeSent+xfer.nIGotSent,
2392 xfer.nFileSent, xfer.nDeltaSent);
2393 }else{
 
 
2394 if( bOutIsTty!=0 ){
2395 fossil_print(zBriefFormat /*works-like:"%d%d%d"*/,
2396 nRoundtrip, nArtifactSent, nArtifactRcvd);
2397 }
2398 }
2399
+3
--- src/zip.c
+++ src/zip.c
@@ -927,10 +927,13 @@
927927
login_check_credentials();
928928
if( !g.perm.Zip ){ login_needed(g.anon.Zip); return; }
929929
if( fossil_strcmp(g.zPath, "sqlar")==0 ){
930930
eType = ARCHIVE_SQLAR;
931931
zType = "SQL";
932
+ /* For some reason, SQL-archives are like catnip for robots. So
933
+ ** don't allow them to be downloaded by user "nobody" */
934
+ if( g.zLogin==0 ){ login_needed(g.anon.Zip); return; }
932935
}else{
933936
eType = ARCHIVE_ZIP;
934937
zType = "ZIP";
935938
}
936939
fossil_nice_default();
937940
--- src/zip.c
+++ src/zip.c
@@ -927,10 +927,13 @@
927 login_check_credentials();
928 if( !g.perm.Zip ){ login_needed(g.anon.Zip); return; }
929 if( fossil_strcmp(g.zPath, "sqlar")==0 ){
930 eType = ARCHIVE_SQLAR;
931 zType = "SQL";
 
 
 
932 }else{
933 eType = ARCHIVE_ZIP;
934 zType = "ZIP";
935 }
936 fossil_nice_default();
937
--- src/zip.c
+++ src/zip.c
@@ -927,10 +927,13 @@
927 login_check_credentials();
928 if( !g.perm.Zip ){ login_needed(g.anon.Zip); return; }
929 if( fossil_strcmp(g.zPath, "sqlar")==0 ){
930 eType = ARCHIVE_SQLAR;
931 zType = "SQL";
932 /* For some reason, SQL-archives are like catnip for robots. So
933 ** don't allow them to be downloaded by user "nobody" */
934 if( g.zLogin==0 ){ login_needed(g.anon.Zip); return; }
935 }else{
936 eType = ARCHIVE_ZIP;
937 zType = "ZIP";
938 }
939 fossil_nice_default();
940
--- test/tester.tcl
+++ test/tester.tcl
@@ -366,12 +366,10 @@
366366
robot-restrict \
367367
robots-txt \
368368
safe-html \
369369
self-pw-reset \
370370
self-register \
371
- show-repolist-desc \
372
- show-repolist-lg \
373371
sitemap-extra \
374372
ssh-command \
375373
ssl-ca-location \
376374
ssl-identity \
377375
tclsh \
378376
--- test/tester.tcl
+++ test/tester.tcl
@@ -366,12 +366,10 @@
366 robot-restrict \
367 robots-txt \
368 safe-html \
369 self-pw-reset \
370 self-register \
371 show-repolist-desc \
372 show-repolist-lg \
373 sitemap-extra \
374 ssh-command \
375 ssl-ca-location \
376 ssl-identity \
377 tclsh \
378
--- test/tester.tcl
+++ test/tester.tcl
@@ -366,12 +366,10 @@
366 robot-restrict \
367 robots-txt \
368 safe-html \
369 self-pw-reset \
370 self-register \
 
 
371 sitemap-extra \
372 ssh-command \
373 ssl-ca-location \
374 ssl-identity \
375 tclsh \
376
+1 -1
--- test/th1.test
+++ test/th1.test
@@ -1061,11 +1061,11 @@
10611061
#fossil test-th-eval "info commands"
10621062
#set sorted_result [lsort $RESULT]
10631063
#protOut "Sorted: $sorted_result"
10641064
#set base_commands {anoncap anycap array artifact break breakpoint \
10651065
# builtin_request_js capexpr captureTh1 catch cgiHeaderLine checkout \
1066
-# combobox continue copybtn date decorate defHeader dir enable_htmlify \
1066
+# combobox continue copybtn date decorate defHeader dir \
10671067
# enable_output encode64 error expr for foreach getParameter glob_match \
10681068
# globalState hascap hasfeature html htmlize http httpize if info \
10691069
# insertCsrf lappend lindex linecount list llength lsearch markdown nonce \
10701070
# proc puts query randhex redirect regexp reinitialize rename render \
10711071
# repository return searchable set setParameter setting stime string \
10721072
--- test/th1.test
+++ test/th1.test
@@ -1061,11 +1061,11 @@
1061 #fossil test-th-eval "info commands"
1062 #set sorted_result [lsort $RESULT]
1063 #protOut "Sorted: $sorted_result"
1064 #set base_commands {anoncap anycap array artifact break breakpoint \
1065 # builtin_request_js capexpr captureTh1 catch cgiHeaderLine checkout \
1066 # combobox continue copybtn date decorate defHeader dir enable_htmlify \
1067 # enable_output encode64 error expr for foreach getParameter glob_match \
1068 # globalState hascap hasfeature html htmlize http httpize if info \
1069 # insertCsrf lappend lindex linecount list llength lsearch markdown nonce \
1070 # proc puts query randhex redirect regexp reinitialize rename render \
1071 # repository return searchable set setParameter setting stime string \
1072
--- test/th1.test
+++ test/th1.test
@@ -1061,11 +1061,11 @@
1061 #fossil test-th-eval "info commands"
1062 #set sorted_result [lsort $RESULT]
1063 #protOut "Sorted: $sorted_result"
1064 #set base_commands {anoncap anycap array artifact break breakpoint \
1065 # builtin_request_js capexpr captureTh1 catch cgiHeaderLine checkout \
1066 # combobox continue copybtn date decorate defHeader dir \
1067 # enable_output encode64 error expr for foreach getParameter glob_match \
1068 # globalState hascap hasfeature html htmlize http httpize if info \
1069 # insertCsrf lappend lindex linecount list llength lsearch markdown nonce \
1070 # proc puts query randhex redirect regexp reinitialize rename render \
1071 # repository return searchable set setParameter setting stime string \
1072
--- tools/makemake.tcl
+++ tools/makemake.tcl
@@ -368,39 +368,41 @@
368368
writeln [string map [list \
369369
<<<SQLITE_OPTIONS>>> [join $SQLITE_OPTIONS " \\\n "] \
370370
<<<SHELL_OPTIONS>>> [join $SHELL_OPTIONS " \\\n "] \
371371
<<<PIKCHR_OPTIONS>>> [join $PIKCHR_OPTIONS " \\\n "] \
372372
<<<NEXT_LINE>>> \\] {
373
-all: $(OBJDIR) $(APPNAME)
373
+all: $(APPNAME)
374374
375375
install: all
376376
mkdir -p $(INSTALLDIR)
377377
cp $(APPNAME) $(INSTALLDIR)
378378
379379
codecheck: $(TRANS_SRC) $(OBJDIR)/codecheck1
380380
$(OBJDIR)/codecheck1 $(TRANS_SRC)
381381
382
-$(OBJDIR):
383
- -mkdir $(OBJDIR)
384
-
385382
$(OBJDIR)/translate: $(SRCDIR_tools)/translate.c
386383
-mkdir -p $(OBJDIR)
387384
$(XBCC) -o $(OBJDIR)/translate $(SRCDIR_tools)/translate.c
388385
389386
$(OBJDIR)/makeheaders: $(SRCDIR_tools)/makeheaders.c
387
+ -mkdir -p $(OBJDIR)
390388
$(XBCC) -o $(OBJDIR)/makeheaders $(SRCDIR_tools)/makeheaders.c
391389
392390
$(OBJDIR)/mkindex: $(SRCDIR_tools)/mkindex.c
391
+ -mkdir -p $(OBJDIR)
393392
$(XBCC) -o $(OBJDIR)/mkindex $(SRCDIR_tools)/mkindex.c
394393
395394
$(OBJDIR)/mkbuiltin: $(SRCDIR_tools)/mkbuiltin.c
395
+ -mkdir -p $(OBJDIR)
396396
$(XBCC) -o $(OBJDIR)/mkbuiltin $(SRCDIR_tools)/mkbuiltin.c
397397
398398
$(OBJDIR)/mkversion: $(SRCDIR_tools)/mkversion.c
399
+ -mkdir -p $(OBJDIR)
399400
$(XBCC) -o $(OBJDIR)/mkversion $(SRCDIR_tools)/mkversion.c
400401
401402
$(OBJDIR)/codecheck1: $(SRCDIR_tools)/codecheck1.c
403
+ -mkdir -p $(OBJDIR)
402404
$(XBCC) -o $(OBJDIR)/codecheck1 $(SRCDIR_tools)/codecheck1.c
403405
404406
# Run the test suite.
405407
# Other flags that can be included in TESTFLAGS are:
406408
#
@@ -412,11 +414,11 @@
412414
# -strict Treat known bugs as failures
413415
#
414416
# TESTFLAGS can also include names of specific test files to limit
415417
# the run to just those test cases.
416418
#
417
-test: $(OBJDIR) $(APPNAME)
419
+test: $(APPNAME)
418420
$(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) $(TESTFLAGS)
419421
420422
$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion $(OBJDIR)/phony.h
421423
$(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid <<<NEXT_LINE>>>
422424
$(SRCDIR)/../manifest <<<NEXT_LINE>>>
@@ -552,23 +554,26 @@
552554
553555
writeln "\$(OBJDIR)/linenoise.o:\t\$(SRCDIR_extsrc)/linenoise.c \$(SRCDIR_extsrc)/linenoise.h"
554556
writeln "\t\$(XTCC) -c \$(SRCDIR_extsrc)/linenoise.c -o \$@\n"
555557
556558
writeln "\$(OBJDIR)/th.o:\t\$(SRCDIR)/th.c"
559
+writeln "\t-mkdir -p \$(OBJDIR)\n"
557560
writeln "\t\$(XTCC) -c \$(SRCDIR)/th.c -o \$@\n"
558561
559562
writeln "\$(OBJDIR)/th_lang.o:\t\$(SRCDIR)/th_lang.c"
563
+writeln "\t-mkdir -p \$(OBJDIR)\n"
560564
writeln "\t\$(XTCC) -c \$(SRCDIR)/th_lang.c -o \$@\n"
561565
562566
writeln "\$(OBJDIR)/th_tcl.o:\t\$(SRCDIR)/th_tcl.c"
567
+writeln "\t-mkdir -p \$(OBJDIR)\n"
563568
writeln "\t\$(XTCC) -c \$(SRCDIR)/th_tcl.c -o \$@\n"
564569
565570
writeln [string map [list <<<NEXT_LINE>>> \\] {
566
-$(OBJDIR)/pikchr.o: $(SRCDIR_extsrc)/pikchr.c
571
+$(OBJDIR)/pikchr.o: $(SRCDIR_extsrc)/pikchr.c $(OBJDIR)/mkversion
567572
$(XTCC) $(PIKCHR_OPTIONS) -c $(SRCDIR_extsrc)/pikchr.c -o $@
568573
569
-$(OBJDIR)/cson_amalgamation.o: $(SRCDIR_extsrc)/cson_amalgamation.c
574
+$(OBJDIR)/cson_amalgamation.o: $(SRCDIR_extsrc)/cson_amalgamation.c $(OBJDIR)/mkversion
570575
$(XTCC) -c $(SRCDIR_extsrc)/cson_amalgamation.c -o $@
571576
572577
$(SRCDIR_extsrc)/pikchr.js: $(SRCDIR_extsrc)/pikchr.c $(MAKEFILE_LIST)
573578
$(EMCC_WRAPPER) -o $@ $(EMCC_OPT) --no-entry <<<NEXT_LINE>>>
574579
-sEXPORTED_RUNTIME_METHODS=cwrap,ccall,setValue,getValue,stackSave,stackAlloc,stackRestore <<<NEXT_LINE>>>
575580
--- tools/makemake.tcl
+++ tools/makemake.tcl
@@ -368,39 +368,41 @@
368 writeln [string map [list \
369 <<<SQLITE_OPTIONS>>> [join $SQLITE_OPTIONS " \\\n "] \
370 <<<SHELL_OPTIONS>>> [join $SHELL_OPTIONS " \\\n "] \
371 <<<PIKCHR_OPTIONS>>> [join $PIKCHR_OPTIONS " \\\n "] \
372 <<<NEXT_LINE>>> \\] {
373 all: $(OBJDIR) $(APPNAME)
374
375 install: all
376 mkdir -p $(INSTALLDIR)
377 cp $(APPNAME) $(INSTALLDIR)
378
379 codecheck: $(TRANS_SRC) $(OBJDIR)/codecheck1
380 $(OBJDIR)/codecheck1 $(TRANS_SRC)
381
382 $(OBJDIR):
383 -mkdir $(OBJDIR)
384
385 $(OBJDIR)/translate: $(SRCDIR_tools)/translate.c
386 -mkdir -p $(OBJDIR)
387 $(XBCC) -o $(OBJDIR)/translate $(SRCDIR_tools)/translate.c
388
389 $(OBJDIR)/makeheaders: $(SRCDIR_tools)/makeheaders.c
 
390 $(XBCC) -o $(OBJDIR)/makeheaders $(SRCDIR_tools)/makeheaders.c
391
392 $(OBJDIR)/mkindex: $(SRCDIR_tools)/mkindex.c
 
393 $(XBCC) -o $(OBJDIR)/mkindex $(SRCDIR_tools)/mkindex.c
394
395 $(OBJDIR)/mkbuiltin: $(SRCDIR_tools)/mkbuiltin.c
 
396 $(XBCC) -o $(OBJDIR)/mkbuiltin $(SRCDIR_tools)/mkbuiltin.c
397
398 $(OBJDIR)/mkversion: $(SRCDIR_tools)/mkversion.c
 
399 $(XBCC) -o $(OBJDIR)/mkversion $(SRCDIR_tools)/mkversion.c
400
401 $(OBJDIR)/codecheck1: $(SRCDIR_tools)/codecheck1.c
 
402 $(XBCC) -o $(OBJDIR)/codecheck1 $(SRCDIR_tools)/codecheck1.c
403
404 # Run the test suite.
405 # Other flags that can be included in TESTFLAGS are:
406 #
@@ -412,11 +414,11 @@
412 # -strict Treat known bugs as failures
413 #
414 # TESTFLAGS can also include names of specific test files to limit
415 # the run to just those test cases.
416 #
417 test: $(OBJDIR) $(APPNAME)
418 $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) $(TESTFLAGS)
419
420 $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion $(OBJDIR)/phony.h
421 $(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid <<<NEXT_LINE>>>
422 $(SRCDIR)/../manifest <<<NEXT_LINE>>>
@@ -552,23 +554,26 @@
552
553 writeln "\$(OBJDIR)/linenoise.o:\t\$(SRCDIR_extsrc)/linenoise.c \$(SRCDIR_extsrc)/linenoise.h"
554 writeln "\t\$(XTCC) -c \$(SRCDIR_extsrc)/linenoise.c -o \$@\n"
555
556 writeln "\$(OBJDIR)/th.o:\t\$(SRCDIR)/th.c"
 
557 writeln "\t\$(XTCC) -c \$(SRCDIR)/th.c -o \$@\n"
558
559 writeln "\$(OBJDIR)/th_lang.o:\t\$(SRCDIR)/th_lang.c"
 
560 writeln "\t\$(XTCC) -c \$(SRCDIR)/th_lang.c -o \$@\n"
561
562 writeln "\$(OBJDIR)/th_tcl.o:\t\$(SRCDIR)/th_tcl.c"
 
563 writeln "\t\$(XTCC) -c \$(SRCDIR)/th_tcl.c -o \$@\n"
564
565 writeln [string map [list <<<NEXT_LINE>>> \\] {
566 $(OBJDIR)/pikchr.o: $(SRCDIR_extsrc)/pikchr.c
567 $(XTCC) $(PIKCHR_OPTIONS) -c $(SRCDIR_extsrc)/pikchr.c -o $@
568
569 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR_extsrc)/cson_amalgamation.c
570 $(XTCC) -c $(SRCDIR_extsrc)/cson_amalgamation.c -o $@
571
572 $(SRCDIR_extsrc)/pikchr.js: $(SRCDIR_extsrc)/pikchr.c $(MAKEFILE_LIST)
573 $(EMCC_WRAPPER) -o $@ $(EMCC_OPT) --no-entry <<<NEXT_LINE>>>
574 -sEXPORTED_RUNTIME_METHODS=cwrap,ccall,setValue,getValue,stackSave,stackAlloc,stackRestore <<<NEXT_LINE>>>
575
--- tools/makemake.tcl
+++ tools/makemake.tcl
@@ -368,39 +368,41 @@
368 writeln [string map [list \
369 <<<SQLITE_OPTIONS>>> [join $SQLITE_OPTIONS " \\\n "] \
370 <<<SHELL_OPTIONS>>> [join $SHELL_OPTIONS " \\\n "] \
371 <<<PIKCHR_OPTIONS>>> [join $PIKCHR_OPTIONS " \\\n "] \
372 <<<NEXT_LINE>>> \\] {
373 all: $(APPNAME)
374
375 install: all
376 mkdir -p $(INSTALLDIR)
377 cp $(APPNAME) $(INSTALLDIR)
378
379 codecheck: $(TRANS_SRC) $(OBJDIR)/codecheck1
380 $(OBJDIR)/codecheck1 $(TRANS_SRC)
381
 
 
 
382 $(OBJDIR)/translate: $(SRCDIR_tools)/translate.c
383 -mkdir -p $(OBJDIR)
384 $(XBCC) -o $(OBJDIR)/translate $(SRCDIR_tools)/translate.c
385
386 $(OBJDIR)/makeheaders: $(SRCDIR_tools)/makeheaders.c
387 -mkdir -p $(OBJDIR)
388 $(XBCC) -o $(OBJDIR)/makeheaders $(SRCDIR_tools)/makeheaders.c
389
390 $(OBJDIR)/mkindex: $(SRCDIR_tools)/mkindex.c
391 -mkdir -p $(OBJDIR)
392 $(XBCC) -o $(OBJDIR)/mkindex $(SRCDIR_tools)/mkindex.c
393
394 $(OBJDIR)/mkbuiltin: $(SRCDIR_tools)/mkbuiltin.c
395 -mkdir -p $(OBJDIR)
396 $(XBCC) -o $(OBJDIR)/mkbuiltin $(SRCDIR_tools)/mkbuiltin.c
397
398 $(OBJDIR)/mkversion: $(SRCDIR_tools)/mkversion.c
399 -mkdir -p $(OBJDIR)
400 $(XBCC) -o $(OBJDIR)/mkversion $(SRCDIR_tools)/mkversion.c
401
402 $(OBJDIR)/codecheck1: $(SRCDIR_tools)/codecheck1.c
403 -mkdir -p $(OBJDIR)
404 $(XBCC) -o $(OBJDIR)/codecheck1 $(SRCDIR_tools)/codecheck1.c
405
406 # Run the test suite.
407 # Other flags that can be included in TESTFLAGS are:
408 #
@@ -412,11 +414,11 @@
414 # -strict Treat known bugs as failures
415 #
416 # TESTFLAGS can also include names of specific test files to limit
417 # the run to just those test cases.
418 #
419 test: $(APPNAME)
420 $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) $(TESTFLAGS)
421
422 $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion $(OBJDIR)/phony.h
423 $(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid <<<NEXT_LINE>>>
424 $(SRCDIR)/../manifest <<<NEXT_LINE>>>
@@ -552,23 +554,26 @@
554
555 writeln "\$(OBJDIR)/linenoise.o:\t\$(SRCDIR_extsrc)/linenoise.c \$(SRCDIR_extsrc)/linenoise.h"
556 writeln "\t\$(XTCC) -c \$(SRCDIR_extsrc)/linenoise.c -o \$@\n"
557
558 writeln "\$(OBJDIR)/th.o:\t\$(SRCDIR)/th.c"
559 writeln "\t-mkdir -p \$(OBJDIR)\n"
560 writeln "\t\$(XTCC) -c \$(SRCDIR)/th.c -o \$@\n"
561
562 writeln "\$(OBJDIR)/th_lang.o:\t\$(SRCDIR)/th_lang.c"
563 writeln "\t-mkdir -p \$(OBJDIR)\n"
564 writeln "\t\$(XTCC) -c \$(SRCDIR)/th_lang.c -o \$@\n"
565
566 writeln "\$(OBJDIR)/th_tcl.o:\t\$(SRCDIR)/th_tcl.c"
567 writeln "\t-mkdir -p \$(OBJDIR)\n"
568 writeln "\t\$(XTCC) -c \$(SRCDIR)/th_tcl.c -o \$@\n"
569
570 writeln [string map [list <<<NEXT_LINE>>> \\] {
571 $(OBJDIR)/pikchr.o: $(SRCDIR_extsrc)/pikchr.c $(OBJDIR)/mkversion
572 $(XTCC) $(PIKCHR_OPTIONS) -c $(SRCDIR_extsrc)/pikchr.c -o $@
573
574 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR_extsrc)/cson_amalgamation.c $(OBJDIR)/mkversion
575 $(XTCC) -c $(SRCDIR_extsrc)/cson_amalgamation.c -o $@
576
577 $(SRCDIR_extsrc)/pikchr.js: $(SRCDIR_extsrc)/pikchr.c $(MAKEFILE_LIST)
578 $(EMCC_WRAPPER) -o $@ $(EMCC_OPT) --no-entry <<<NEXT_LINE>>>
579 -sEXPORTED_RUNTIME_METHODS=cwrap,ccall,setValue,getValue,stackSave,stackAlloc,stackRestore <<<NEXT_LINE>>>
580
+2 -3
--- www/cgi.wiki
+++ www/cgi.wiki
@@ -81,13 +81,12 @@
8181
the page title taken from the <tt>FOSSIL_REPOLIST_TITLE</tt>
8282
environment variable. The variable can be defined in the CGI
8383
control file using the [#setenv|<tt>setenv:</tt>] statement.
8484
8585
The "Project Description" and "Login-Group" columns on the repolist page
86
-are optional. They are hidden by default. Show them by putting value "1"
87
-in the global settings "show-repolist-desc" and "show-repolist-lg", or
88
-by setting the <tt>FOSSIL_REPOLIST_SHOW</tt> environment variable to
86
+are optional. They are hidden by default. Show them by
87
+etting the <tt>FOSSIL_REPOLIST_SHOW</tt> environment variable to
8988
a string that contains substrings "description" and/or "login-group".
9089
9190
The repolist-generated page recurses into subdirectories and will list
9291
all <tt>*.fossil</tt> files found, with the following exceptions:
9392
9493
--- www/cgi.wiki
+++ www/cgi.wiki
@@ -81,13 +81,12 @@
81 the page title taken from the <tt>FOSSIL_REPOLIST_TITLE</tt>
82 environment variable. The variable can be defined in the CGI
83 control file using the [#setenv|<tt>setenv:</tt>] statement.
84
85 The "Project Description" and "Login-Group" columns on the repolist page
86 are optional. They are hidden by default. Show them by putting value "1"
87 in the global settings "show-repolist-desc" and "show-repolist-lg", or
88 by setting the <tt>FOSSIL_REPOLIST_SHOW</tt> environment variable to
89 a string that contains substrings "description" and/or "login-group".
90
91 The repolist-generated page recurses into subdirectories and will list
92 all <tt>*.fossil</tt> files found, with the following exceptions:
93
94
--- www/cgi.wiki
+++ www/cgi.wiki
@@ -81,13 +81,12 @@
81 the page title taken from the <tt>FOSSIL_REPOLIST_TITLE</tt>
82 environment variable. The variable can be defined in the CGI
83 control file using the [#setenv|<tt>setenv:</tt>] statement.
84
85 The "Project Description" and "Login-Group" columns on the repolist page
86 are optional. They are hidden by default. Show them by
87 etting the <tt>FOSSIL_REPOLIST_SHOW</tt> environment variable to
 
88 a string that contains substrings "description" and/or "login-group".
89
90 The repolist-generated page recurses into subdirectories and will list
91 all <tt>*.fossil</tt> files found, with the following exceptions:
92
93
+37 -18
--- www/changes.wiki
+++ www/changes.wiki
@@ -1,12 +1,17 @@
11
<title>Change Log</title>
22
3
-<h2 id='v2_26'>Changes for version 2.26 (pending)</h2><ol>
3
+<h2 id='v2_27'>Changes for version 2.27 (pending)</h2>
4
+
5
+ * Enhance the chng= query parameter on the [/help?cmd=/timeline|timeline page]
6
+ so that it work with other query parameters like p=, d=, from=, and to=.
7
+
8
+<h2 id='v2_26'>Changes for version 2.26 (2025-04-30)</h2><ol>
49
<li>Enhancements to [/help?cmd=diff|fossil diff] and similar:
510
<ol type="a">
6
- <li> The --from can optionally accept a directory name as its argument,
7
- and uses files under that directory as the baseline for the diff.
11
+ <li> The argument to the --from option can be a directory name, causing
12
+ Fossil to use files under that directory as the baseline for the diff.
813
<li> For "gdiff", if no [/help?cmd=gdiff-command|gdiff-command setting]
914
is defined, Fossil tries to do a --tk diff if "tclsh" and "wish"
1015
are available, or a --by diff if not.
1116
<li> The "Reload" button is added to --tk diffs, to bring the displayed
1217
diff up to date with the latest changes on disk.
@@ -84,13 +89,13 @@
8489
<li> Accept the "Z" (Zulu-time) suffix on date arguments for the
8590
"ymd" and "yw" query parameters.
8691
<li> The new "min" query parameter, when added to a from=,to= query,
8792
collapses long runs of check-ins on the same branch into just
8893
end-points.
89
- <li> The p= and d= parameters an reference different check-ins, which
90
- case the timeline shows those check-ins that are both ancestors
91
- of p= and descendants of d=.
94
+ <li> The p= and d= parameters can now reference different check-ins,
95
+ in which case the timeline shows those check-ins that are both
96
+ ancestors of p= and descendants of d=.
9297
<li> The saturation and intensity of user-specified checkin and branch
9398
background colors are automatically adjusted to keep the colors
9499
compatible with the current skin, unless the
95100
[/help?cmd=raw-bgcolor|raw-bgcolor setting] is turned on.
96101
</ol>
@@ -119,11 +124,11 @@
119124
COMMAND argument and only shows results for the specified
120125
subcommand, not the entire command.
121126
<li> The -u (--usage) option shows only the command-line syntax
122127
<li> The -o (--options) option shows only the command-line options
123128
</ol>
124
- <li>Enhancements to the ticket system:
129
+ <li>Enhancements to the [./tickets.wiki|ticket system]:
125130
<ol type="a">
126131
<li> Added the ability to attach wiki pages to a ticket for extended
127132
descriptions.
128133
<li> Added submenu to the 'View Ticket' page, to use it as
129134
template for a new ticket.
@@ -136,22 +141,37 @@
136141
<li>Added the "hash" query parameter to the
137142
[/help?cmd=/whatis|/whatis webpage].
138143
<li>Add a "user permissions changes" [/doc/trunk/www/alerts.md|subscription]
139144
which alerts subscribers when an admin creates a new user or
140145
when a user's permissions change.
141
- <li>Show project description on repository list.
146
+ <li>If the FOSSIL_REPOLIST_SHOW environment variable exists and contains
147
+ the substring "description", then the project description for each repository
148
+ is shown on the repository list page. The login-group for each project is
149
+ now only shown if the FOSSIL_REPOLIST_SHOW environment variable exists and
150
+ contains the substring "login-group". ([./cgi.wiki#repolist|More information])
151
+ <li>The [/doc/trunk/www/th1.md|TH1 script language] is enhanced for improved
152
+ security:
153
+ <ol type="a">
154
+ <li> TH1 now makes a distinction between
155
+ [/doc/trunk/www/th1.md#taint|tainted and untainted string values].
156
+ This makes it more difficult to write custom TH1 scripts that
157
+ contain XSS or SQL-injection bugs. The
158
+ [/help?cmd=vuln-report|vuln-report] setting was added to control
159
+ what Fossil does when it encounters a potential TH1
160
+ security problem.
161
+ <li> The "--th" option was removed from the [/help?cmd=pikchr|fossil pikchr]
162
+ command.
163
+ <li> The "enable_htmlify" TH1 command was removed.
164
+ </ol>
142165
<li>Make [/help?cmd=/chat|/chat] better-behaved during server outages, reducing
143166
the frequency of reconnection attempts over time and providing feedback
144167
to the user when the connection is down.
145
- <li>The [/doc/trunk/www/th1.md|TH1 script language] now makes a distinction
146
- between [/doc/trunk/www/th1.md#taint|tainted and untainted string values].
147
- This is a security enhancement that makes it more difficult to write
148
- custom TH1 scripts that contain XSS or SQL-injection bugs. As part of
149
- this enhancement, the [/help?cmd=vuln-report|vuln-report] setting was
150
- added to control what Fossil does when it encounters a potential TH1
151
- security problem.
152
- <li>Diverse minor fixes and additions.
168
+ <li>The [/help?cmd=/sqlar|/sqlar] page does not work for users who are not logged
169
+ in, nor are links to that page displayed to users who are not logged in. Being
170
+ logged in as "anonymous" is sufficient to overcome this restriction, assuming
171
+ that "anonymous" can download tarballs and ZIP archives.
172
+ <li>Many other minor fixes and additions.
153173
</ol>
154174
155175
<h2 id='v2_25'>Changes for version 2.25 (2024-11-06)</h2>
156176
157177
* The "[/help?cmd=ui|fossil ui /]" command now works even for repositories
@@ -1169,12 +1189,11 @@
11691189
of rows in a timeline) are held in a cookie and thus persist
11701190
across multiple pages.
11711191
* Rework the skin editing process so that changes are implemented
11721192
on one of nine /draft pages, evaluated, then merged back to the
11731193
default.
1174
- * Added the [https://fossil-scm.org/skins/ardoise/timeline|Ardoise]
1175
- skin.
1194
+ * Added the [/timeline?skin=ardoise&once|Ardoise] skin.
11761195
* Fix the "fossil server" command on Unix to be much more responsive
11771196
to multiple simultaneous web requests.
11781197
* Use the IPv6 stack for the "fossil ui" and "fossil server"
11791198
commands on Windows.
11801199
* Support for [https://sqlite.org/sqlar|SQL Archives] as a download
11811200
--- www/changes.wiki
+++ www/changes.wiki
@@ -1,12 +1,17 @@
1 <title>Change Log</title>
2
3 <h2 id='v2_26'>Changes for version 2.26 (pending)</h2><ol>
 
 
 
 
 
4 <li>Enhancements to [/help?cmd=diff|fossil diff] and similar:
5 <ol type="a">
6 <li> The --from can optionally accept a directory name as its argument,
7 and uses files under that directory as the baseline for the diff.
8 <li> For "gdiff", if no [/help?cmd=gdiff-command|gdiff-command setting]
9 is defined, Fossil tries to do a --tk diff if "tclsh" and "wish"
10 are available, or a --by diff if not.
11 <li> The "Reload" button is added to --tk diffs, to bring the displayed
12 diff up to date with the latest changes on disk.
@@ -84,13 +89,13 @@
84 <li> Accept the "Z" (Zulu-time) suffix on date arguments for the
85 "ymd" and "yw" query parameters.
86 <li> The new "min" query parameter, when added to a from=,to= query,
87 collapses long runs of check-ins on the same branch into just
88 end-points.
89 <li> The p= and d= parameters an reference different check-ins, which
90 case the timeline shows those check-ins that are both ancestors
91 of p= and descendants of d=.
92 <li> The saturation and intensity of user-specified checkin and branch
93 background colors are automatically adjusted to keep the colors
94 compatible with the current skin, unless the
95 [/help?cmd=raw-bgcolor|raw-bgcolor setting] is turned on.
96 </ol>
@@ -119,11 +124,11 @@
119 COMMAND argument and only shows results for the specified
120 subcommand, not the entire command.
121 <li> The -u (--usage) option shows only the command-line syntax
122 <li> The -o (--options) option shows only the command-line options
123 </ol>
124 <li>Enhancements to the ticket system:
125 <ol type="a">
126 <li> Added the ability to attach wiki pages to a ticket for extended
127 descriptions.
128 <li> Added submenu to the 'View Ticket' page, to use it as
129 template for a new ticket.
@@ -136,22 +141,37 @@
136 <li>Added the "hash" query parameter to the
137 [/help?cmd=/whatis|/whatis webpage].
138 <li>Add a "user permissions changes" [/doc/trunk/www/alerts.md|subscription]
139 which alerts subscribers when an admin creates a new user or
140 when a user's permissions change.
141 <li>Show project description on repository list.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142 <li>Make [/help?cmd=/chat|/chat] better-behaved during server outages, reducing
143 the frequency of reconnection attempts over time and providing feedback
144 to the user when the connection is down.
145 <li>The [/doc/trunk/www/th1.md|TH1 script language] now makes a distinction
146 between [/doc/trunk/www/th1.md#taint|tainted and untainted string values].
147 This is a security enhancement that makes it more difficult to write
148 custom TH1 scripts that contain XSS or SQL-injection bugs. As part of
149 this enhancement, the [/help?cmd=vuln-report|vuln-report] setting was
150 added to control what Fossil does when it encounters a potential TH1
151 security problem.
152 <li>Diverse minor fixes and additions.
153 </ol>
154
155 <h2 id='v2_25'>Changes for version 2.25 (2024-11-06)</h2>
156
157 * The "[/help?cmd=ui|fossil ui /]" command now works even for repositories
@@ -1169,12 +1189,11 @@
1169 of rows in a timeline) are held in a cookie and thus persist
1170 across multiple pages.
1171 * Rework the skin editing process so that changes are implemented
1172 on one of nine /draft pages, evaluated, then merged back to the
1173 default.
1174 * Added the [https://fossil-scm.org/skins/ardoise/timeline|Ardoise]
1175 skin.
1176 * Fix the "fossil server" command on Unix to be much more responsive
1177 to multiple simultaneous web requests.
1178 * Use the IPv6 stack for the "fossil ui" and "fossil server"
1179 commands on Windows.
1180 * Support for [https://sqlite.org/sqlar|SQL Archives] as a download
1181
--- www/changes.wiki
+++ www/changes.wiki
@@ -1,12 +1,17 @@
1 <title>Change Log</title>
2
3 <h2 id='v2_27'>Changes for version 2.27 (pending)</h2>
4
5 * Enhance the chng= query parameter on the [/help?cmd=/timeline|timeline page]
6 so that it work with other query parameters like p=, d=, from=, and to=.
7
8 <h2 id='v2_26'>Changes for version 2.26 (2025-04-30)</h2><ol>
9 <li>Enhancements to [/help?cmd=diff|fossil diff] and similar:
10 <ol type="a">
11 <li> The argument to the --from option can be a directory name, causing
12 Fossil to use files under that directory as the baseline for the diff.
13 <li> For "gdiff", if no [/help?cmd=gdiff-command|gdiff-command setting]
14 is defined, Fossil tries to do a --tk diff if "tclsh" and "wish"
15 are available, or a --by diff if not.
16 <li> The "Reload" button is added to --tk diffs, to bring the displayed
17 diff up to date with the latest changes on disk.
@@ -84,13 +89,13 @@
89 <li> Accept the "Z" (Zulu-time) suffix on date arguments for the
90 "ymd" and "yw" query parameters.
91 <li> The new "min" query parameter, when added to a from=,to= query,
92 collapses long runs of check-ins on the same branch into just
93 end-points.
94 <li> The p= and d= parameters can now reference different check-ins,
95 in which case the timeline shows those check-ins that are both
96 ancestors of p= and descendants of d=.
97 <li> The saturation and intensity of user-specified checkin and branch
98 background colors are automatically adjusted to keep the colors
99 compatible with the current skin, unless the
100 [/help?cmd=raw-bgcolor|raw-bgcolor setting] is turned on.
101 </ol>
@@ -119,11 +124,11 @@
124 COMMAND argument and only shows results for the specified
125 subcommand, not the entire command.
126 <li> The -u (--usage) option shows only the command-line syntax
127 <li> The -o (--options) option shows only the command-line options
128 </ol>
129 <li>Enhancements to the [./tickets.wiki|ticket system]:
130 <ol type="a">
131 <li> Added the ability to attach wiki pages to a ticket for extended
132 descriptions.
133 <li> Added submenu to the 'View Ticket' page, to use it as
134 template for a new ticket.
@@ -136,22 +141,37 @@
141 <li>Added the "hash" query parameter to the
142 [/help?cmd=/whatis|/whatis webpage].
143 <li>Add a "user permissions changes" [/doc/trunk/www/alerts.md|subscription]
144 which alerts subscribers when an admin creates a new user or
145 when a user's permissions change.
146 <li>If the FOSSIL_REPOLIST_SHOW environment variable exists and contains
147 the substring "description", then the project description for each repository
148 is shown on the repository list page. The login-group for each project is
149 now only shown if the FOSSIL_REPOLIST_SHOW environment variable exists and
150 contains the substring "login-group". ([./cgi.wiki#repolist|More information])
151 <li>The [/doc/trunk/www/th1.md|TH1 script language] is enhanced for improved
152 security:
153 <ol type="a">
154 <li> TH1 now makes a distinction between
155 [/doc/trunk/www/th1.md#taint|tainted and untainted string values].
156 This makes it more difficult to write custom TH1 scripts that
157 contain XSS or SQL-injection bugs. The
158 [/help?cmd=vuln-report|vuln-report] setting was added to control
159 what Fossil does when it encounters a potential TH1
160 security problem.
161 <li> The "--th" option was removed from the [/help?cmd=pikchr|fossil pikchr]
162 command.
163 <li> The "enable_htmlify" TH1 command was removed.
164 </ol>
165 <li>Make [/help?cmd=/chat|/chat] better-behaved during server outages, reducing
166 the frequency of reconnection attempts over time and providing feedback
167 to the user when the connection is down.
168 <li>The [/help?cmd=/sqlar|/sqlar] page does not work for users who are not logged
169 in, nor are links to that page displayed to users who are not logged in. Being
170 logged in as "anonymous" is sufficient to overcome this restriction, assuming
171 that "anonymous" can download tarballs and ZIP archives.
172 <li>Many other minor fixes and additions.
 
 
 
173 </ol>
174
175 <h2 id='v2_25'>Changes for version 2.25 (2024-11-06)</h2>
176
177 * The "[/help?cmd=ui|fossil ui /]" command now works even for repositories
@@ -1169,12 +1189,11 @@
1189 of rows in a timeline) are held in a cookie and thus persist
1190 across multiple pages.
1191 * Rework the skin editing process so that changes are implemented
1192 on one of nine /draft pages, evaluated, then merged back to the
1193 default.
1194 * Added the [/timeline?skin=ardoise&once|Ardoise] skin.
 
1195 * Fix the "fossil server" command on Unix to be much more responsive
1196 to multiple simultaneous web requests.
1197 * Use the IPv6 stack for the "fossil ui" and "fossil server"
1198 commands on Windows.
1199 * Support for [https://sqlite.org/sqlar|SQL Archives] as a download
1200
--- www/containers.md
+++ www/containers.md
@@ -670,11 +670,11 @@
670670
671671
[pmmac]: https://podman.io/getting-started/installation.html#macos
672672
[pmwin]: https://github.com/containers/podman/blob/main/docs/tutorials/podman-for-windows.md
673673
[Podman]: https://podman.io/
674674
[rl]: https://github.com/containers/podman/blob/main/docs/tutorials/rootless_tutorial.md
675
-[whatis]: https://podman.io/whatis.html
675
+[whatis]: https://docs.podman.io/en/latest/index.html
676676
677677
678678
### 6.3 <a id="nspawn"></a>`systemd-container`
679679
680680
If even the Podman stack is too big for you, the next-best option I’m
681681
--- www/containers.md
+++ www/containers.md
@@ -670,11 +670,11 @@
670
671 [pmmac]: https://podman.io/getting-started/installation.html#macos
672 [pmwin]: https://github.com/containers/podman/blob/main/docs/tutorials/podman-for-windows.md
673 [Podman]: https://podman.io/
674 [rl]: https://github.com/containers/podman/blob/main/docs/tutorials/rootless_tutorial.md
675 [whatis]: https://podman.io/whatis.html
676
677
678 ### 6.3 <a id="nspawn"></a>`systemd-container`
679
680 If even the Podman stack is too big for you, the next-best option I’m
681
--- www/containers.md
+++ www/containers.md
@@ -670,11 +670,11 @@
670
671 [pmmac]: https://podman.io/getting-started/installation.html#macos
672 [pmwin]: https://github.com/containers/podman/blob/main/docs/tutorials/podman-for-windows.md
673 [Podman]: https://podman.io/
674 [rl]: https://github.com/containers/podman/blob/main/docs/tutorials/rootless_tutorial.md
675 [whatis]: https://docs.podman.io/en/latest/index.html
676
677
678 ### 6.3 <a id="nspawn"></a>`systemd-container`
679
680 If even the Podman stack is too big for you, the next-best option I’m
681
--- www/customskin.md
+++ www/customskin.md
@@ -310,10 +310,11 @@
310310
with the "--skin ./newskin" option. If the argument to the --skin
311311
option contains a "/" character, then the five control files are
312312
read out of the directory named. You can then edit the control
313313
files in the ./newskin folder using you favorite text editor, and
314314
press "Reload" on your browser to see the effects.
315
+
315316
316317
### Disabling The Web Browser Cache During Development
317318
318319
Fossil is aggressive about asking the web browser to cache
319320
resources. While developing a new skin, it is often helpful to
@@ -526,11 +527,46 @@
526527
Iterate until the desired look is achieved.
527528
528529
4. Copy/paste the resulting css.txt, details.txt,
529530
header.txt, and footer.txt files
530531
into the CSS, details, header, and footer configuration screens
531
- under the Admin/Skins menu.
532
+ under the Admin/Skins menu. Alternately, import them using the
533
+ process described below.
534
+
535
+An alternative to step 4 is to convert the skin files into a form
536
+which can be imported into a repository using `fossil config import`.
537
+It requires compiling [a small tool from the fossil source
538
+tree](/file/tools/skintxt2config.c):
539
+
540
+>
541
+```
542
+$ cc -o s2c /path/to/fossil/checkout/tools/skintxt2config.c
543
+```
544
+
545
+With that in place, the custom skin files can be converted with:
546
+
547
+>
548
+```
549
+$ ./s2c yourskin/*.txt > skin.config
550
+```
551
+
552
+It can be imported into an arbitrary fossil repository with:
553
+
554
+>
555
+```
556
+$ fossil config import skin.config
557
+```
558
+
559
+And it can be pushed to a remote repository with:
560
+
561
+>
562
+```
563
+$ fossil config push skin
564
+```
565
+
566
+That approach has proven to be an effective way to locally develop
567
+skin changes then push them to a "live" site.
532568
533569
534570
## See Also
535571
536572
* [Customizing the Timeline Graph](customgraph.md)
537573
--- www/customskin.md
+++ www/customskin.md
@@ -310,10 +310,11 @@
310 with the "--skin ./newskin" option. If the argument to the --skin
311 option contains a "/" character, then the five control files are
312 read out of the directory named. You can then edit the control
313 files in the ./newskin folder using you favorite text editor, and
314 press "Reload" on your browser to see the effects.
 
315
316 ### Disabling The Web Browser Cache During Development
317
318 Fossil is aggressive about asking the web browser to cache
319 resources. While developing a new skin, it is often helpful to
@@ -526,11 +527,46 @@
526 Iterate until the desired look is achieved.
527
528 4. Copy/paste the resulting css.txt, details.txt,
529 header.txt, and footer.txt files
530 into the CSS, details, header, and footer configuration screens
531 under the Admin/Skins menu.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
532
533
534 ## See Also
535
536 * [Customizing the Timeline Graph](customgraph.md)
537
--- www/customskin.md
+++ www/customskin.md
@@ -310,10 +310,11 @@
310 with the "--skin ./newskin" option. If the argument to the --skin
311 option contains a "/" character, then the five control files are
312 read out of the directory named. You can then edit the control
313 files in the ./newskin folder using you favorite text editor, and
314 press "Reload" on your browser to see the effects.
315
316
317 ### Disabling The Web Browser Cache During Development
318
319 Fossil is aggressive about asking the web browser to cache
320 resources. While developing a new skin, it is often helpful to
@@ -526,11 +527,46 @@
527 Iterate until the desired look is achieved.
528
529 4. Copy/paste the resulting css.txt, details.txt,
530 header.txt, and footer.txt files
531 into the CSS, details, header, and footer configuration screens
532 under the Admin/Skins menu. Alternately, import them using the
533 process described below.
534
535 An alternative to step 4 is to convert the skin files into a form
536 which can be imported into a repository using `fossil config import`.
537 It requires compiling [a small tool from the fossil source
538 tree](/file/tools/skintxt2config.c):
539
540 >
541 ```
542 $ cc -o s2c /path/to/fossil/checkout/tools/skintxt2config.c
543 ```
544
545 With that in place, the custom skin files can be converted with:
546
547 >
548 ```
549 $ ./s2c yourskin/*.txt > skin.config
550 ```
551
552 It can be imported into an arbitrary fossil repository with:
553
554 >
555 ```
556 $ fossil config import skin.config
557 ```
558
559 And it can be pushed to a remote repository with:
560
561 >
562 ```
563 $ fossil config push skin
564 ```
565
566 That approach has proven to be an effective way to locally develop
567 skin changes then push them to a "live" site.
568
569
570 ## See Also
571
572 * [Customizing the Timeline Graph](customgraph.md)
573
--- www/fossil-v-git.wiki
+++ www/fossil-v-git.wiki
@@ -342,11 +342,11 @@
342342
Fossil isn't entirely C and SQL code. Its web UI [./javascript.md |
343343
uses JavaScript where
344344
necessary]. The server-side
345345
UI scripting uses a custom minimal
346346
[https://en.wikipedia.org/wiki/Tcl|Tcl] dialect called
347
-[https://fossil-scm.org/xfer/doc/trunk/www/th1.md|TH1], which is
347
+[./th1.md|TH1], which is
348348
embedded into Fossil itself. Fossil's build system and test suite are
349349
largely based on Tcl.⁵ All of this is quite portable.
350350
351351
About half of Git's code is POSIX C, and about a third is POSIX shell
352352
code. This is largely why the so-called "Git for Windows" distributions
353353
--- www/fossil-v-git.wiki
+++ www/fossil-v-git.wiki
@@ -342,11 +342,11 @@
342 Fossil isn't entirely C and SQL code. Its web UI [./javascript.md |
343 uses JavaScript where
344 necessary]. The server-side
345 UI scripting uses a custom minimal
346 [https://en.wikipedia.org/wiki/Tcl|Tcl] dialect called
347 [https://fossil-scm.org/xfer/doc/trunk/www/th1.md|TH1], which is
348 embedded into Fossil itself. Fossil's build system and test suite are
349 largely based on Tcl.⁵ All of this is quite portable.
350
351 About half of Git's code is POSIX C, and about a third is POSIX shell
352 code. This is largely why the so-called "Git for Windows" distributions
353
--- www/fossil-v-git.wiki
+++ www/fossil-v-git.wiki
@@ -342,11 +342,11 @@
342 Fossil isn't entirely C and SQL code. Its web UI [./javascript.md |
343 uses JavaScript where
344 necessary]. The server-side
345 UI scripting uses a custom minimal
346 [https://en.wikipedia.org/wiki/Tcl|Tcl] dialect called
347 [./th1.md|TH1], which is
348 embedded into Fossil itself. Fossil's build system and test suite are
349 largely based on Tcl.⁵ All of this is quite portable.
350
351 About half of Git's code is POSIX C, and about a third is POSIX shell
352 code. This is largely why the so-called "Git for Windows" distributions
353
--- www/gsoc-ideas.md
+++ www/gsoc-ideas.md
@@ -24,11 +24,11 @@
2424
# UI, Look and Feel
2525
2626
Tasks for those interested in graphic/web design:
2727
2828
* Add a quote button to the Forum, such as [discussed in this thread](https://fossil-scm.org/forum/forumpost/7ad03cd73d)
29
-* Improve the documentation history-browsing page to enable selection of 2 arbitrary versions to diff, similar to the [Mediawiki history feature enabled on Wikipedia](https://en.wikipedia.org/w/index.php?title=Fossil_(software)&action=history)
29
+* Improve the documentation history-browsing page to enable selection of 2 arbitrary versions to diff, similar to the [Mediawiki history feature enabled on Wikipedia](https://en.wikipedia.org/w/index.php?title=Fossil_\(software\)&action=history)
3030
* Allow diffing of Forum posts
3131
* General touch-ups in the existing skins. This may, depending on how deep one
3232
cares to dig, require digging into C code to find, and potentially modify, how
3333
the HTML is generated.
3434
* Creation of one or more new skins. This does not specifically require any C
3535
--- www/gsoc-ideas.md
+++ www/gsoc-ideas.md
@@ -24,11 +24,11 @@
24 # UI, Look and Feel
25
26 Tasks for those interested in graphic/web design:
27
28 * Add a quote button to the Forum, such as [discussed in this thread](https://fossil-scm.org/forum/forumpost/7ad03cd73d)
29 * Improve the documentation history-browsing page to enable selection of 2 arbitrary versions to diff, similar to the [Mediawiki history feature enabled on Wikipedia](https://en.wikipedia.org/w/index.php?title=Fossil_(software)&action=history)
30 * Allow diffing of Forum posts
31 * General touch-ups in the existing skins. This may, depending on how deep one
32 cares to dig, require digging into C code to find, and potentially modify, how
33 the HTML is generated.
34 * Creation of one or more new skins. This does not specifically require any C
35
--- www/gsoc-ideas.md
+++ www/gsoc-ideas.md
@@ -24,11 +24,11 @@
24 # UI, Look and Feel
25
26 Tasks for those interested in graphic/web design:
27
28 * Add a quote button to the Forum, such as [discussed in this thread](https://fossil-scm.org/forum/forumpost/7ad03cd73d)
29 * Improve the documentation history-browsing page to enable selection of 2 arbitrary versions to diff, similar to the [Mediawiki history feature enabled on Wikipedia](https://en.wikipedia.org/w/index.php?title=Fossil_\(software\)&action=history)
30 * Allow diffing of Forum posts
31 * General touch-ups in the existing skins. This may, depending on how deep one
32 cares to dig, require digging into C code to find, and potentially modify, how
33 the HTML is generated.
34 * Creation of one or more new skins. This does not specifically require any C
35
+4 -4
--- www/index.wiki
+++ www/index.wiki
@@ -84,16 +84,16 @@
8484
the repository are consistent prior to each commit.
8585
8686
8. <b>Free and Open-Source</b> — [../COPYRIGHT-BSD2.txt|2-clause BSD license].
8787
8888
<hr>
89
-<h3>Latest Release: 2.25 ([/timeline?c=version-2.25|2024-11-06])</h3>
89
+<h3>Latest Release: 2.26 ([/timeline?c=version-2.26|2025-04-30])</h3>
9090
9191
* [/uv/download.html|Download]
92
- * [./changes.wiki#v2_25|Change Summary]
93
- * [/timeline?p=version-2.25&bt=version-2.24&y=ci|Check-ins in version 2.25]
94
- * [/timeline?df=version-2.25&y=ci|Check-ins derived from the 2.25 release]
92
+ * [./changes.wiki#v2_26|Change Summary]
93
+ * [/timeline?p=version-2.26&d=version-2.25&y=ci|Check-ins in version 2.26]
94
+ * [/timeline?df=version-2.26&y=ci|Check-ins derived from the 2.26 release]
9595
* [/timeline?t=release|Timeline of all past releases]
9696
9797
<hr>
9898
<h3>Quick Start</h3>
9999
100100
--- www/index.wiki
+++ www/index.wiki
@@ -84,16 +84,16 @@
84 the repository are consistent prior to each commit.
85
86 8. <b>Free and Open-Source</b> — [../COPYRIGHT-BSD2.txt|2-clause BSD license].
87
88 <hr>
89 <h3>Latest Release: 2.25 ([/timeline?c=version-2.25|2024-11-06])</h3>
90
91 * [/uv/download.html|Download]
92 * [./changes.wiki#v2_25|Change Summary]
93 * [/timeline?p=version-2.25&bt=version-2.24&y=ci|Check-ins in version 2.25]
94 * [/timeline?df=version-2.25&y=ci|Check-ins derived from the 2.25 release]
95 * [/timeline?t=release|Timeline of all past releases]
96
97 <hr>
98 <h3>Quick Start</h3>
99
100
--- www/index.wiki
+++ www/index.wiki
@@ -84,16 +84,16 @@
84 the repository are consistent prior to each commit.
85
86 8. <b>Free and Open-Source</b> — [../COPYRIGHT-BSD2.txt|2-clause BSD license].
87
88 <hr>
89 <h3>Latest Release: 2.26 ([/timeline?c=version-2.26|2025-04-30])</h3>
90
91 * [/uv/download.html|Download]
92 * [./changes.wiki#v2_26|Change Summary]
93 * [/timeline?p=version-2.26&d=version-2.25&y=ci|Check-ins in version 2.26]
94 * [/timeline?df=version-2.26&y=ci|Check-ins derived from the 2.26 release]
95 * [/timeline?t=release|Timeline of all past releases]
96
97 <hr>
98 <h3>Quick Start</h3>
99
100
+16 -18
--- www/reviews.wiki
+++ www/reviews.wiki
@@ -35,33 +35,31 @@
3535
</div>
3636
3737
<b>Stephan Beal writes on 2009-01-11:</b>
3838
3939
<div class="indent">
40
-Sometime in late 2007 I came across a link to fossil on
41
-<a href="http://www.sqlite.org/">sqlite.org</a>. It
42
-was a good thing I bookmarked it, because I was never able to find the
43
-link again (it might have been in a bug report or something). The
44
-reasons I first took a close look at it were (A) it stemmed from the
45
-sqlite project, which I've held in high regards for years (e.g. I
46
-wrote JavaScript bindings for it:
47
-<a href="http://spiderape.sourceforge.net/plugins/sqlite/">
48
-http://spiderape.sourceforge.net/plugins/sqlite/</a>), and (B) it could
49
-run as a CGI. That second point might seem a bit archaic, but in
50
-practice CGI is the only way most hosted sites can set up a shared
51
-source repository with multiple user IDs. (i'm not about to give out
52
-my only account password or SSH key for my hosted sites, no matter how
53
-much I trust the other developers, and none of my hosters allow me to
54
-run standalone servers or add Apache modules.)
40
+Sometime in late 2007 I came across a link to fossil on <a
41
+href="https://sqlite.org/">sqlite.org</a>. It was a good thing I
42
+bookmarked it, because I was never able to find the link again (it
43
+might have been in a bug report or something). The reasons I first
44
+took a close look at it were (A) it stemmed from the sqlite project,
45
+which I've held in high regards for years (e.g. I wrote bindings for
46
+it for Mozilla's SpiderMonkey JavaScript engine), and (B) it could run
47
+as a CGI. That second point might seem a bit archaic, but in practice
48
+CGI is the only way most hosted sites can set up a shared source
49
+repository with multiple user IDs. (i'm not about to give out my only
50
+account password or SSH key for my hosted sites, no matter how much I
51
+trust the other developers, and none of my hosters allow me to run
52
+standalone servers or add Apache modules.)
5553
5654
So I tried it out. The thing which bugged me most about it was having
5755
to type "commit" or "com" instead of "ci" for checking in (as is
5856
custom in all other systems I've used), despite the fact that fossil
5957
uses "ci" as a filter in things like the timeline view. Looking back
6058
now, I have used fossil for about about 95% of my work in the past
61
-year (<a href="http://blog.s11n.net/?p=71"><i>dead link</i></a>), in
62
-over 15 source trees, and I now get tripped up when I have to use svn or cvs.
59
+year, in over 15 source trees, and I now get tripped up when I have to
60
+use svn or cvs.
6361
6462
So, having got over typing "fossil com -m ...", here's why I love it so much...
6563
6664
Point #1: CGI
6765
@@ -70,11 +68,11 @@
7068
(they don't belong to those projects), which I cannot host in google
7169
code (because google code doesn't allow/recognize Public Domain as a
7270
license, and I refuse to relicense just to accommodate them), and for
7371
which SourceForge is overkill (and way too slow). With fossil I can
7472
create a new repo, have it installed on my hoster
75
-(http://fossil.wanderinghorse.net), and be commiting code to it within
73
+(https://fossil.wanderinghorse.net), and be commiting code to it within
7674
5 minutes.
7775
7876
Point #2: Wiki
7977
8078
I hate wikis. I really do. Always have. They all have a different
8179
--- www/reviews.wiki
+++ www/reviews.wiki
@@ -35,33 +35,31 @@
35 </div>
36
37 <b>Stephan Beal writes on 2009-01-11:</b>
38
39 <div class="indent">
40 Sometime in late 2007 I came across a link to fossil on
41 <a href="http://www.sqlite.org/">sqlite.org</a>. It
42 was a good thing I bookmarked it, because I was never able to find the
43 link again (it might have been in a bug report or something). The
44 reasons I first took a close look at it were (A) it stemmed from the
45 sqlite project, which I've held in high regards for years (e.g. I
46 wrote JavaScript bindings for it:
47 <a href="http://spiderape.sourceforge.net/plugins/sqlite/">
48 http://spiderape.sourceforge.net/plugins/sqlite/</a>), and (B) it could
49 run as a CGI. That second point might seem a bit archaic, but in
50 practice CGI is the only way most hosted sites can set up a shared
51 source repository with multiple user IDs. (i'm not about to give out
52 my only account password or SSH key for my hosted sites, no matter how
53 much I trust the other developers, and none of my hosters allow me to
54 run standalone servers or add Apache modules.)
55
56 So I tried it out. The thing which bugged me most about it was having
57 to type "commit" or "com" instead of "ci" for checking in (as is
58 custom in all other systems I've used), despite the fact that fossil
59 uses "ci" as a filter in things like the timeline view. Looking back
60 now, I have used fossil for about about 95% of my work in the past
61 year (<a href="http://blog.s11n.net/?p=71"><i>dead link</i></a>), in
62 over 15 source trees, and I now get tripped up when I have to use svn or cvs.
63
64 So, having got over typing "fossil com -m ...", here's why I love it so much...
65
66 Point #1: CGI
67
@@ -70,11 +68,11 @@
70 (they don't belong to those projects), which I cannot host in google
71 code (because google code doesn't allow/recognize Public Domain as a
72 license, and I refuse to relicense just to accommodate them), and for
73 which SourceForge is overkill (and way too slow). With fossil I can
74 create a new repo, have it installed on my hoster
75 (http://fossil.wanderinghorse.net), and be commiting code to it within
76 5 minutes.
77
78 Point #2: Wiki
79
80 I hate wikis. I really do. Always have. They all have a different
81
--- www/reviews.wiki
+++ www/reviews.wiki
@@ -35,33 +35,31 @@
35 </div>
36
37 <b>Stephan Beal writes on 2009-01-11:</b>
38
39 <div class="indent">
40 Sometime in late 2007 I came across a link to fossil on <a
41 href="https://sqlite.org/">sqlite.org</a>. It was a good thing I
42 bookmarked it, because I was never able to find the link again (it
43 might have been in a bug report or something). The reasons I first
44 took a close look at it were (A) it stemmed from the sqlite project,
45 which I've held in high regards for years (e.g. I wrote bindings for
46 it for Mozilla's SpiderMonkey JavaScript engine), and (B) it could run
47 as a CGI. That second point might seem a bit archaic, but in practice
48 CGI is the only way most hosted sites can set up a shared source
49 repository with multiple user IDs. (i'm not about to give out my only
50 account password or SSH key for my hosted sites, no matter how much I
51 trust the other developers, and none of my hosters allow me to run
52 standalone servers or add Apache modules.)
 
 
53
54 So I tried it out. The thing which bugged me most about it was having
55 to type "commit" or "com" instead of "ci" for checking in (as is
56 custom in all other systems I've used), despite the fact that fossil
57 uses "ci" as a filter in things like the timeline view. Looking back
58 now, I have used fossil for about about 95% of my work in the past
59 year, in over 15 source trees, and I now get tripped up when I have to
60 use svn or cvs.
61
62 So, having got over typing "fossil com -m ...", here's why I love it so much...
63
64 Point #1: CGI
65
@@ -70,11 +68,11 @@
68 (they don't belong to those projects), which I cannot host in google
69 code (because google code doesn't allow/recognize Public Domain as a
70 license, and I refuse to relicense just to accommodate them), and for
71 which SourceForge is overkill (and way too slow). With fossil I can
72 create a new repo, have it installed on my hoster
73 (https://fossil.wanderinghorse.net), and be commiting code to it within
74 5 minutes.
75
76 Point #2: Wiki
77
78 I hate wikis. I really do. Always have. They all have a different
79
+21 -24
--- www/th1.md
+++ www/th1.md
@@ -12,29 +12,43 @@
1212
time all of the test cases for SQLite were written in Tcl and Tcl could not
1313
be easily compiled on the SymbianOS. So TH1 was developed as a cut-down
1414
version of Tcl that would facilitate running the SQLite test scripts on
1515
SymbianOS.
1616
17
-Fossil was first being designed at about the same time that TH1 was
18
-being developed for testing SQLite on SymbianOS.
17
+Fossil was first being designed at about the same time.
1918
Early prototypes of Fossil were written in pure Tcl. But as the development
2019
shifted toward the use of C-code, the need arose to have a Tcl-like
2120
scripting language to help with code generation. TH1 was small and
2221
light-weight and used minimal resources and seemed ideally suited for the
2322
task.
2423
25
-The name "TH1" stands "Test Harness 1", since that was its original purpose.
24
+The name "TH1" stands for "Test Harness 1",
25
+since its original purpose was to serve as testing harness
26
+for SQLite.
2627
27
-Overview
---------
28
+Where TH1 Is Used In Fossil
29
+---------------------------
30
+
31
+ * In the header and footer for [skins](./customskin.md)
32
+ text within `<th1>...</th1>` is run as a TH1 script.
33
+ ([example](/builtin/skins/default/header.txt))
34
+
35
+ * This display of [tickets](./bugtheory.wiki) is controlled by TH1
36
+ scripts, so that the ticket format can be customized for each
37
+ project. Administrators can visit the <b>/tktsetup</b> page in
38
+ their repositories to view and customize these scripts.
39
+ ([example usage](./custom_ticket.wiki))
40
+
41
+Overview Of The Tcl/TH1 Language
42
+--------------------------------
2843
2944
TH1 is a string-processing language. All values are strings. Any numerical
3045
operations are accomplished by converting from string to numeric, performing
3146
the computation, then converting the result back into a string. (This might
3247
seem inefficient, but it is faster than people imagine, and numeric
3348
computations do not come up very often for the kinds of work that TH1 does,
34
-so it has never been a factor.)
49
+so it has never been an issue.)
3550
3651
A TH1 script consists of a sequence of commands.
3752
Each command is terminated by the first *unescaped* newline or ";" character.
3853
The text of the command (excluding the newline or semicolon terminator)
3954
is broken into space-separated tokens. The first token is the command
@@ -126,11 +140,11 @@
126140
custom TH1 scripts for headers or footers or tickets are added to a
127141
repository. Note that the tainted/untainted distinction in strings does
128142
not make it impossible to introduce XSS and SQL-injections vulnerabilities
129143
using poorly-written TH1 scripts; it just makes it more difficult and
130144
less likely to happen by accident. Developers must still consider the
131
-security implications TH1 customizations they add to Fossil, and take
145
+security implications of TH1 customizations they add to Fossil, and take
132146
appropriate precautions when writing custom TH1. Peer review of TH1
133147
script changes is encouraged.
134148
135149
In Fossil version 2.26, if the vuln-report setting is set to "block"
136150
or "fatal", the [html](#html) and [query](#query) TH1 commands will
@@ -224,11 +238,10 @@
224238
* [copybtn](#copybtn)
225239
* [date](#date)
226240
* [decorate](#decorate)
227241
* [defHeader](#defHeader)
228242
* [dir](#dir)
229
- * [enable\_htmlify](#enable_htmlify)
230243
* [enable\_output](#enable_output)
231244
* [encode64](#encode64)
232245
* [getParameter](#getParameter)
233246
* [glob\_match](#glob_match)
234247
* [globalState](#globalState)
@@ -457,28 +470,10 @@
457470
the files matching the pattern GLOB within CHECKIN will be returned.
458471
If DETAILS is non-zero, the result will be a list-of-lists, with each
459472
element containing at least three elements: the file name, the file
460473
size (in bytes), and the file last modification time (relative to the
461474
time zone configured for the repository).
462
-
463
-<a id="enable_htmlify"></a>TH1 enable\_htmlify Command
-------------------------------------------------------
464
-
465
- * enable\_htmlify
466
- * enable\_htmlify ?TRACE-LABEL? BOOLEAN
467
-
468
-By default, certain output from `puts` and similar commands is escaped
469
-for HTML. The first call form returns the current state of that
470
-feature: `1` for on and `0` for off. The second call form enables
471
-(non-0) or disables (0) that feature and returns the *pre-call* state
472
-of that feature (so that a second call can pass that value to restore
473
-it to its previous state). The optional `TRACE-LABEL` argument causes
474
-the TH1 tracing output (if enabled) to add a marker when the second
475
-form of this command is invoked, and includes that label and the
476
-boolean argument's value in the trace. If tracing is disabled, that
477
-argument has no effect.
478
-
479475
480476
<a id="enable_output"></a>TH1 enable\_output Command
481477
------------------------------------------------------
482478
483479
* enable\_output BOOLEAN
484480
--- www/th1.md
+++ www/th1.md
@@ -12,29 +12,43 @@
12 time all of the test cases for SQLite were written in Tcl and Tcl could not
13 be easily compiled on the SymbianOS. So TH1 was developed as a cut-down
14 version of Tcl that would facilitate running the SQLite test scripts on
15 SymbianOS.
16
17 Fossil was first being designed at about the same time that TH1 was
18 being developed for testing SQLite on SymbianOS.
19 Early prototypes of Fossil were written in pure Tcl. But as the development
20 shifted toward the use of C-code, the need arose to have a Tcl-like
21 scripting language to help with code generation. TH1 was small and
22 light-weight and used minimal resources and seemed ideally suited for the
23 task.
24
25 The name "TH1" stands "Test Harness 1", since that was its original purpose.
 
 
26
27 Overview
---------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
29 TH1 is a string-processing language. All values are strings. Any numerical
30 operations are accomplished by converting from string to numeric, performing
31 the computation, then converting the result back into a string. (This might
32 seem inefficient, but it is faster than people imagine, and numeric
33 computations do not come up very often for the kinds of work that TH1 does,
34 so it has never been a factor.)
35
36 A TH1 script consists of a sequence of commands.
37 Each command is terminated by the first *unescaped* newline or ";" character.
38 The text of the command (excluding the newline or semicolon terminator)
39 is broken into space-separated tokens. The first token is the command
@@ -126,11 +140,11 @@
126 custom TH1 scripts for headers or footers or tickets are added to a
127 repository. Note that the tainted/untainted distinction in strings does
128 not make it impossible to introduce XSS and SQL-injections vulnerabilities
129 using poorly-written TH1 scripts; it just makes it more difficult and
130 less likely to happen by accident. Developers must still consider the
131 security implications TH1 customizations they add to Fossil, and take
132 appropriate precautions when writing custom TH1. Peer review of TH1
133 script changes is encouraged.
134
135 In Fossil version 2.26, if the vuln-report setting is set to "block"
136 or "fatal", the [html](#html) and [query](#query) TH1 commands will
@@ -224,11 +238,10 @@
224 * [copybtn](#copybtn)
225 * [date](#date)
226 * [decorate](#decorate)
227 * [defHeader](#defHeader)
228 * [dir](#dir)
229 * [enable\_htmlify](#enable_htmlify)
230 * [enable\_output](#enable_output)
231 * [encode64](#encode64)
232 * [getParameter](#getParameter)
233 * [glob\_match](#glob_match)
234 * [globalState](#globalState)
@@ -457,28 +470,10 @@
457 the files matching the pattern GLOB within CHECKIN will be returned.
458 If DETAILS is non-zero, the result will be a list-of-lists, with each
459 element containing at least three elements: the file name, the file
460 size (in bytes), and the file last modification time (relative to the
461 time zone configured for the repository).
462
463 <a id="enable_htmlify"></a>TH1 enable\_htmlify Command
-------------------------------------------------------
464
465 * enable\_htmlify
466 * enable\_htmlify ?TRACE-LABEL? BOOLEAN
467
468 By default, certain output from `puts` and similar commands is escaped
469 for HTML. The first call form returns the current state of that
470 feature: `1` for on and `0` for off. The second call form enables
471 (non-0) or disables (0) that feature and returns the *pre-call* state
472 of that feature (so that a second call can pass that value to restore
473 it to its previous state). The optional `TRACE-LABEL` argument causes
474 the TH1 tracing output (if enabled) to add a marker when the second
475 form of this command is invoked, and includes that label and the
476 boolean argument's value in the trace. If tracing is disabled, that
477 argument has no effect.
478
479
480 <a id="enable_output"></a>TH1 enable\_output Command
481 ------------------------------------------------------
482
483 * enable\_output BOOLEAN
484
--- www/th1.md
+++ www/th1.md
@@ -12,29 +12,43 @@
12 time all of the test cases for SQLite were written in Tcl and Tcl could not
13 be easily compiled on the SymbianOS. So TH1 was developed as a cut-down
14 version of Tcl that would facilitate running the SQLite test scripts on
15 SymbianOS.
16
17 Fossil was first being designed at about the same time.
 
18 Early prototypes of Fossil were written in pure Tcl. But as the development
19 shifted toward the use of C-code, the need arose to have a Tcl-like
20 scripting language to help with code generation. TH1 was small and
21 light-weight and used minimal resources and seemed ideally suited for the
22 task.
23
24 The name "TH1" stands for "Test Harness 1",
25 since its original purpose was to serve as testing harness
26 for SQLite.
27
 
---------
28 Where TH1 Is Used In Fossil
29 ---------------------------
30
31 * In the header and footer for [skins](./customskin.md)
32 text within `<th1>...</th1>` is run as a TH1 script.
33 ([example](/builtin/skins/default/header.txt))
34
35 * This display of [tickets](./bugtheory.wiki) is controlled by TH1
36 scripts, so that the ticket format can be customized for each
37 project. Administrators can visit the <b>/tktsetup</b> page in
38 their repositories to view and customize these scripts.
39 ([example usage](./custom_ticket.wiki))
40
41 Overview Of The Tcl/TH1 Language
42 --------------------------------
43
44 TH1 is a string-processing language. All values are strings. Any numerical
45 operations are accomplished by converting from string to numeric, performing
46 the computation, then converting the result back into a string. (This might
47 seem inefficient, but it is faster than people imagine, and numeric
48 computations do not come up very often for the kinds of work that TH1 does,
49 so it has never been an issue.)
50
51 A TH1 script consists of a sequence of commands.
52 Each command is terminated by the first *unescaped* newline or ";" character.
53 The text of the command (excluding the newline or semicolon terminator)
54 is broken into space-separated tokens. The first token is the command
@@ -126,11 +140,11 @@
140 custom TH1 scripts for headers or footers or tickets are added to a
141 repository. Note that the tainted/untainted distinction in strings does
142 not make it impossible to introduce XSS and SQL-injections vulnerabilities
143 using poorly-written TH1 scripts; it just makes it more difficult and
144 less likely to happen by accident. Developers must still consider the
145 security implications of TH1 customizations they add to Fossil, and take
146 appropriate precautions when writing custom TH1. Peer review of TH1
147 script changes is encouraged.
148
149 In Fossil version 2.26, if the vuln-report setting is set to "block"
150 or "fatal", the [html](#html) and [query](#query) TH1 commands will
@@ -224,11 +238,10 @@
238 * [copybtn](#copybtn)
239 * [date](#date)
240 * [decorate](#decorate)
241 * [defHeader](#defHeader)
242 * [dir](#dir)
 
243 * [enable\_output](#enable_output)
244 * [encode64](#encode64)
245 * [getParameter](#getParameter)
246 * [glob\_match](#glob_match)
247 * [globalState](#globalState)
@@ -457,28 +470,10 @@
470 the files matching the pattern GLOB within CHECKIN will be returned.
471 If DETAILS is non-zero, the result will be a list-of-lists, with each
472 element containing at least three elements: the file name, the file
473 size (in bytes), and the file last modification time (relative to the
474 time zone configured for the repository).
 
 
-------------------------------------------------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
475
476 <a id="enable_output"></a>TH1 enable\_output Command
477 ------------------------------------------------------
478
479 * enable\_output BOOLEAN
480

Keyboard Shortcuts

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