Fossil SCM

Merge in trunk.

ashepilko 2020-05-19 18:31 revert-dir merge
Commit 0ad3e06bd2eff6b3cb6628e9e3cad5976e7ca8653c32baaeb2efb0addeec1d6b
--- skins/default/header.txt
+++ skins/default/header.txt
@@ -17,17 +17,18 @@
1717
html "<a href='$home$url' class='active $cls'>$name</a>\n"
1818
} else {
1919
html "<a href='$home$url' class='$cls'>$name</a>\n"
2020
}
2121
}
22
-html "<a id='hbbtn' href='$home/sitemap'>&#9776;</a>"
22
+html "<a id='hbbtn' href='$home/sitemap' aria-label='Site Map'>&#9776;</a>"
2323
menulink $index_page Home {}
2424
if {[anycap jor]} {
2525
menulink /timeline Timeline {}
2626
}
2727
if {[hascap oh]} {
28
- menulink /dir?ci=tip Files desktoponly
28
+ if {![info exists current_checkin]} {set current_checkin tip}
29
+ menulink /dir?ci=$current_checkin Files desktoponly
2930
}
3031
if {[hascap o]} {
3132
menulink /brlist Branches desktoponly
3233
menulink /taglist Tags wideonly
3334
}
3435
--- skins/default/header.txt
+++ skins/default/header.txt
@@ -17,17 +17,18 @@
17 html "<a href='$home$url' class='active $cls'>$name</a>\n"
18 } else {
19 html "<a href='$home$url' class='$cls'>$name</a>\n"
20 }
21 }
22 html "<a id='hbbtn' href='$home/sitemap'>&#9776;</a>"
23 menulink $index_page Home {}
24 if {[anycap jor]} {
25 menulink /timeline Timeline {}
26 }
27 if {[hascap oh]} {
28 menulink /dir?ci=tip Files desktoponly
 
29 }
30 if {[hascap o]} {
31 menulink /brlist Branches desktoponly
32 menulink /taglist Tags wideonly
33 }
34
--- skins/default/header.txt
+++ skins/default/header.txt
@@ -17,17 +17,18 @@
17 html "<a href='$home$url' class='active $cls'>$name</a>\n"
18 } else {
19 html "<a href='$home$url' class='$cls'>$name</a>\n"
20 }
21 }
22 html "<a id='hbbtn' href='$home/sitemap' aria-label='Site Map'>&#9776;</a>"
23 menulink $index_page Home {}
24 if {[anycap jor]} {
25 menulink /timeline Timeline {}
26 }
27 if {[hascap oh]} {
28 if {![info exists current_checkin]} {set current_checkin tip}
29 menulink /dir?ci=$current_checkin Files desktoponly
30 }
31 if {[hascap o]} {
32 menulink /brlist Branches desktoponly
33 menulink /taglist Tags wideonly
34 }
35
--- src/allrepo.c
+++ src/allrepo.c
@@ -283,11 +283,13 @@
283283
}else if( strncmp(zCmd, "sync", n)==0 ){
284284
zCmd = "sync -autourl -R";
285285
collect_argument(&extra, "verbose","v");
286286
collect_argument(&extra, "unversioned","u");
287287
}else if( strncmp(zCmd, "test-integrity", n)==0 ){
288
+ collect_argument(&extra, "db-only", "d");
288289
collect_argument(&extra, "parse", 0);
290
+ collect_argument(&extra, "quick", "q");
289291
zCmd = "test-integrity";
290292
}else if( strncmp(zCmd, "test-orphans", n)==0 ){
291293
zCmd = "test-orphans -R";
292294
}else if( strncmp(zCmd, "test-missing", n)==0 ){
293295
zCmd = "test-missing -q -R";
294296
--- src/allrepo.c
+++ src/allrepo.c
@@ -283,11 +283,13 @@
283 }else if( strncmp(zCmd, "sync", n)==0 ){
284 zCmd = "sync -autourl -R";
285 collect_argument(&extra, "verbose","v");
286 collect_argument(&extra, "unversioned","u");
287 }else if( strncmp(zCmd, "test-integrity", n)==0 ){
 
288 collect_argument(&extra, "parse", 0);
 
289 zCmd = "test-integrity";
290 }else if( strncmp(zCmd, "test-orphans", n)==0 ){
291 zCmd = "test-orphans -R";
292 }else if( strncmp(zCmd, "test-missing", n)==0 ){
293 zCmd = "test-missing -q -R";
294
--- src/allrepo.c
+++ src/allrepo.c
@@ -283,11 +283,13 @@
283 }else if( strncmp(zCmd, "sync", n)==0 ){
284 zCmd = "sync -autourl -R";
285 collect_argument(&extra, "verbose","v");
286 collect_argument(&extra, "unversioned","u");
287 }else if( strncmp(zCmd, "test-integrity", n)==0 ){
288 collect_argument(&extra, "db-only", "d");
289 collect_argument(&extra, "parse", 0);
290 collect_argument(&extra, "quick", "q");
291 zCmd = "test-integrity";
292 }else if( strncmp(zCmd, "test-orphans", n)==0 ){
293 zCmd = "test-orphans -R";
294 }else if( strncmp(zCmd, "test-missing", n)==0 ){
295 zCmd = "test-missing -q -R";
296
+14
--- src/branch.c
+++ src/branch.c
@@ -18,10 +18,24 @@
1818
** This file contains code used to create new branches within a repository.
1919
*/
2020
#include "config.h"
2121
#include "branch.h"
2222
#include <assert.h>
23
+
24
+/*
25
+** Return true if zBr is the branch name associated with check-in with
26
+** blob.uuid value of zUuid
27
+*/
28
+int branch_includes_uuid(const char *zBr, const char *zUuid){
29
+ return db_exists(
30
+ "SELECT 1 FROM tagxref, blob"
31
+ " WHERE blob.uuid=%Q AND tagxref.rid=blob.rid"
32
+ " AND tagxref.value=%Q AND tagxref.tagtype>0"
33
+ " AND tagxref.tagid=%d",
34
+ zUuid, zBr, TAG_BRANCH
35
+ );
36
+}
2337
2438
/*
2539
** If RID refers to a check-in, return the name of the branch for that
2640
** check-in.
2741
**
2842
--- src/branch.c
+++ src/branch.c
@@ -18,10 +18,24 @@
18 ** This file contains code used to create new branches within a repository.
19 */
20 #include "config.h"
21 #include "branch.h"
22 #include <assert.h>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
24 /*
25 ** If RID refers to a check-in, return the name of the branch for that
26 ** check-in.
27 **
28
--- src/branch.c
+++ src/branch.c
@@ -18,10 +18,24 @@
18 ** This file contains code used to create new branches within a repository.
19 */
20 #include "config.h"
21 #include "branch.h"
22 #include <assert.h>
23
24 /*
25 ** Return true if zBr is the branch name associated with check-in with
26 ** blob.uuid value of zUuid
27 */
28 int branch_includes_uuid(const char *zBr, const char *zUuid){
29 return db_exists(
30 "SELECT 1 FROM tagxref, blob"
31 " WHERE blob.uuid=%Q AND tagxref.rid=blob.rid"
32 " AND tagxref.value=%Q AND tagxref.tagtype>0"
33 " AND tagxref.tagid=%d",
34 zUuid, zBr, TAG_BRANCH
35 );
36 }
37
38 /*
39 ** If RID refers to a check-in, return the name of the branch for that
40 ** check-in.
41 **
42
+121 -79
--- src/browse.c
+++ src/browse.c
@@ -59,10 +59,18 @@
5959
zOut = sqlite3_mprintf("/%.*s", i-n, &z[n]);
6060
sqlite3_result_text(context, zOut, i-n+1, sqlite3_free);
6161
}
6262
}
6363
64
+/*
65
+** Flag arguments for hyperlinked_path()
66
+*/
67
+#if INTERFACE
68
+# define LINKPATH_FINFO 0x0001 /* Link final term to /finfo */
69
+# define LINKPATH_FILE 0x0002 /* Link final term to /file */
70
+#endif
71
+
6472
/*
6573
** Given a pathname which is a relative path from the root of
6674
** the repository to a file or directory, compute a string which
6775
** is an HTML rendering of that path with hyperlinks on each
6876
** directory component of the path where the hyperlink redirects
@@ -76,29 +84,36 @@
7684
void hyperlinked_path(
7785
const char *zPath, /* Path to render */
7886
Blob *pOut, /* Write into this blob */
7987
const char *zCI, /* check-in name, or NULL */
8088
const char *zURI, /* "dir" or "tree" */
81
- const char *zREx /* Extra query parameters */
89
+ const char *zREx, /* Extra query parameters */
90
+ unsigned int mFlags /* Extra flags */
8291
){
8392
int i, j;
8493
char *zSep = "";
8594
8695
for(i=0; zPath[i]; i=j){
8796
for(j=i; zPath[j] && zPath[j]!='/'; j++){}
88
- if( zPath[j] && g.perm.Hyperlink ){
89
- if( zCI ){
90
- char *zLink = href("%R/%s?name=%#T%s&ci=%!S", zURI, j, zPath, zREx,zCI);
91
- blob_appendf(pOut, "%s%z%#h</a>",
92
- zSep, zLink, j-i, &zPath[i]);
93
- }else{
94
- char *zLink = href("%R/%s?name=%#T%s", zURI, j, zPath, zREx);
95
- blob_appendf(pOut, "%s%z%#h</a>",
96
- zSep, zLink, j-i, &zPath[i]);
97
- }
98
- }else{
99
- blob_appendf(pOut, "%s%#h", zSep, j-i, &zPath[i]);
97
+ if( zPath[j]==0 ){
98
+ if( mFlags & LINKPATH_FILE ){
99
+ zURI = "file";
100
+ }else if( mFlags & LINKPATH_FINFO ){
101
+ zURI = "finfo";
102
+ }else{
103
+ blob_appendf(pOut, "/%h", zPath+i);
104
+ break;
105
+ }
106
+ }
107
+ if( zCI ){
108
+ char *zLink = href("%R/%s?name=%#T%s&ci=%T", zURI, j, zPath, zREx,zCI);
109
+ blob_appendf(pOut, "%s%z%#h</a>",
110
+ zSep, zLink, j-i, &zPath[i]);
111
+ }else{
112
+ char *zLink = href("%R/%s?name=%#T%s", zURI, j, zPath, zREx);
113
+ blob_appendf(pOut, "%s%z%#h</a>",
114
+ zSep, zLink, j-i, &zPath[i]);
100115
}
101116
zSep = "/";
102117
while( zPath[j]=='/' ){ j++; }
103118
}
104119
}
@@ -127,17 +142,17 @@
127142
char *zPrefix;
128143
Stmt q;
129144
const char *zCI = P("ci");
130145
int rid = 0;
131146
char *zUuid = 0;
132
- Blob dirname;
133147
Manifest *pM = 0;
134148
const char *zSubdirLink;
135149
int linkTrunk = 1;
136150
int linkTip = 1;
137151
HQuery sURI;
138152
int isSymbolicCI = 0; /* ci= is symbolic name, not a hash prefix */
153
+ int isBranchCI = 0; /* True if ci= refers to a branch name */
139154
char *zHeader = 0;
140155
141156
if( zCI && strlen(zCI)==0 ){ zCI = 0; }
142157
if( strcmp(PD("type","flat"),"tree")==0 ){ page_tree(); return; }
143158
login_check_credentials();
@@ -157,22 +172,30 @@
157172
int trunkRid = symbolic_name_to_rid("tag:trunk", "ci");
158173
linkTrunk = trunkRid && rid != trunkRid;
159174
linkTip = rid != symbolic_name_to_rid("tip", "ci");
160175
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
161176
isSymbolicCI = (sqlite3_strnicmp(zUuid, zCI, strlen(zCI))!=0);
177
+ isBranchCI = branch_includes_uuid(zCI, zUuid);
178
+ Th_Store("current_checkin", zCI);
162179
}else{
163180
zCI = 0;
164181
}
165182
}
166183
167184
assert( isSymbolicCI==0 || (zCI!=0 && zCI[0]!=0) );
168
- if( isSymbolicCI ) {
169
- zHeader = mprintf("%s at %s", (zD ? zD : "Files"), zCI);
170
- }else if( zUuid && strlen(zUuid) ){
171
- zHeader = mprintf("%s at [%S]", (zD ? zD : "Files"), zUuid);
185
+ if( zD==0 ){
186
+ if( zCI ){
187
+ zHeader = mprintf("Top-level Files of %s", zCI);
188
+ }else{
189
+ zHeader = mprintf("All Top-level Files");
190
+ }
172191
}else{
173
- zHeader = mprintf("%s", (zD ? zD : "All Files"));
192
+ if( zCI ){
193
+ zHeader = mprintf("Files in %s/ of %s", zD, zCI);
194
+ }else{
195
+ zHeader = mprintf("All File in %s/", zD);
196
+ }
174197
}
175198
style_header("%s", zHeader);
176199
fossil_free(zHeader);
177200
style_adunit_config(ADUNIT_RIGHT_OK);
178201
sqlite3_create_function(g.db, "pathelement", 2, SQLITE_UTF8, 0,
@@ -179,47 +202,49 @@
179202
pathelementFunc, 0, 0);
180203
url_initialize(&sURI, "dir");
181204
cgi_query_parameters_to_url(&sURI);
182205
183206
/* Compute the title of the page */
184
- blob_zero(&dirname);
185207
if( zD ){
186
- blob_append(&dirname, "in directory ", -1);
187
- hyperlinked_path(zD, &dirname, zCI, "dir", "");
208
+ Blob dirname;
209
+ blob_init(&dirname, 0, 0);
210
+ hyperlinked_path(zD, &dirname, zCI, "dir", "", 0);
211
+ @ <h2>Files in directory %s(blob_str(&dirname)) \
212
+ blob_reset(&dirname);
188213
zPrefix = mprintf("%s/", zD);
189214
style_submenu_element("Top-Level", "%s",
190215
url_render(&sURI, "name", 0, 0, 0));
191216
}else{
192
- blob_append(&dirname, "in the top-level directory", -1);
217
+ @ <h2>Files in the top-level directory \
193218
zPrefix = "";
194219
}
220
+ if( zCI ){
221
+ if( fossil_strcmp(zCI,"tip")==0 ){
222
+ @ from the %z(href("%R/info?name=%T",zCI))latest check-in</a></h2>
223
+ }else if( isBranchCI ){
224
+ @ from the %z(href("%R/info?name=%T",zCI))latest check-in</a> \
225
+ @ of branch %z(href("%R/timeline?r=%T",zCI))%h(zCI)</a></h2>
226
+ }else {
227
+ @ of check-in %z(href("%R/info?name=%T",zCI))%h(zCI)</a></h2>
228
+ }
229
+ zSubdirLink = mprintf("%R/dir?ci=%T&name=%T", zCI, zPrefix);
230
+ if( nD==0 ){
231
+ style_submenu_element("File Ages", "%R/fileage?name=%T", zCI);
232
+ }
233
+ }else{
234
+ @ in any check-in</h2>
235
+ zSubdirLink = mprintf("%R/dir?name=%T", zPrefix);
236
+ }
195237
if( linkTrunk ){
196238
style_submenu_element("Trunk", "%s",
197239
url_render(&sURI, "ci", "trunk", 0, 0));
198240
}
199241
if( linkTip ){
200242
style_submenu_element("Tip", "%s", url_render(&sURI, "ci", "tip", 0, 0));
201243
}
202
- if( zCI ){
203
- @ <h2>Files at check-in [%z(href("vinfo?name=%!S",zUuid))%S(zUuid)</a>]
204
- @ %s(blob_str(&dirname))
205
- if( zD ){
206
- @ &nbsp;&nbsp;%z(href("%R/timeline?chng=%T/*", zD))[history]</a>
207
- }
208
- @ </h2>
209
- zSubdirLink = mprintf("%R/dir?ci=%!S&name=%T", zUuid, zPrefix);
210
- if( nD==0 ){
211
- style_submenu_element("File Ages", "%R/fileage?name=%!S", zUuid);
212
- }
213
- }else{
214
- @ <h2>All files known in the repository
215
- @ %s(blob_str(&dirname))
216
- if( zD ){
217
- @ &nbsp;&nbsp;%z(href("%R/timeline?chng=%T/*", zD))[history]</a>
218
- }
219
- @ </h2>
220
- zSubdirLink = mprintf("%R/dir?name=%T", zPrefix);
244
+ if( zD ){
245
+ style_submenu_element("History","%R/timeline?chng=%T/*", zD);
221246
}
222247
style_submenu_element("All", "%s", url_render(&sURI, "ci", 0, 0, 0));
223248
style_submenu_element("Tree-View", "%s",
224249
url_render(&sURI, "type", "tree", 0, 0));
225250
@@ -296,11 +321,11 @@
296321
zFN++;
297322
@ <li class="dir">%z(href("%s%T",zSubdirLink,zFN))%h(zFN)</a></li>
298323
}else{
299324
const char *zLink;
300325
if( zCI ){
301
- zLink = href("%R/file?name=%T%T&ci=%!S",zPrefix,zFN,zCI);
326
+ zLink = href("%R/file?name=%T%T&ci=%T",zPrefix,zFN,zCI);
302327
}else{
303328
zLink = href("%R/finfo?name=%T%T",zPrefix,zFN);
304329
}
305330
@ <li class="%z(fileext_class(zFN))">%z(zLink)%h(zFN)</a></li>
306331
}
@@ -626,10 +651,11 @@
626651
int startExpanded; /* True to start out with the tree expanded */
627652
int showDirOnly; /* Show directories only. Omit files */
628653
int nDir = 0; /* Number of directories. Used for ID attributes */
629654
char *zProjectName = db_get("project-name", 0);
630655
int isSymbolicCI = 0; /* ci= is a symbolic name, not a hash prefix */
656
+ int isBranchCI = 0; /* ci= refers to a branch name */
631657
char *zHeader = 0;
632658
633659
if( zCI && strlen(zCI)==0 ){ zCI = 0; }
634660
if( strcmp(PD("type","flat"),"flat")==0 ){ page_dir(); return; }
635661
memset(&sTree, 0, sizeof(sTree));
@@ -675,10 +701,12 @@
675701
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
676702
rNow = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid);
677703
zNow = db_text("", "SELECT datetime(mtime,toLocal())"
678704
" FROM event WHERE objid=%d", rid);
679705
isSymbolicCI = (sqlite3_strnicmp(zUuid, zCI, strlen(zCI)) != 0);
706
+ isBranchCI = branch_includes_uuid(zCI, zUuid);
707
+ Th_Store("current_checkin", zCI);
680708
}else{
681709
zCI = 0;
682710
}
683711
}
684712
if( zCI==0 ){
@@ -685,41 +713,42 @@
685713
rNow = db_double(0.0, "SELECT max(mtime) FROM event");
686714
zNow = db_text("", "SELECT datetime(max(mtime),toLocal()) FROM event");
687715
}
688716
689717
assert( isSymbolicCI==0 || (zCI!=0 && zCI[0]!=0) );
690
- if( isSymbolicCI ) {
691
- zHeader = mprintf("%s at %s",
692
- (zD ? zD : (showDirOnly ? "Folder Hierarchy" : "Tree-View")), zCI);
693
- }else if( zUuid && strlen(zUuid) ){
694
- zHeader = mprintf("%s at [%S]",
695
- (zD ? zD : (showDirOnly ? "Folder Hierarchy" : "Tree-View")), zUuid);
718
+ if( zD==0 ){
719
+ if( zCI ){
720
+ zHeader = mprintf("Top-level Files of %s", zCI);
721
+ }else{
722
+ zHeader = mprintf("All Top-level Files");
723
+ }
696724
}else{
697
- zHeader = mprintf("%s",
698
- (zD ? zD : (showDirOnly ?"All Folders Hierarchy":"All Files Tree-View")));
725
+ if( zCI ){
726
+ zHeader = mprintf("Files in %s/ of %s", zD, zCI);
727
+ }else{
728
+ zHeader = mprintf("All File in %s/", zD);
729
+ }
699730
}
700731
style_header("%s", zHeader);
701732
fossil_free(zHeader);
702733
703734
/* Compute the title of the page */
704735
blob_zero(&dirname);
705736
if( zD ){
706737
blob_append(&dirname, "within directory ", -1);
707
- hyperlinked_path(zD, &dirname, zCI, "tree", zREx);
738
+ hyperlinked_path(zD, &dirname, zCI, "tree", zREx, 0);
708739
if( zRE ) blob_appendf(&dirname, " matching \"%s\"", zRE);
709740
style_submenu_element("Top-Level", "%s",
710741
url_render(&sURI, "name", 0, 0, 0));
711
- }else{
712
- if( zRE ){
713
- blob_appendf(&dirname, "matching \"%s\"", zRE);
714
- }
742
+ }else if( zRE ){
743
+ blob_appendf(&dirname, "matching \"%s\"", zRE);
715744
}
716745
style_submenu_binary("mtime","Sort By Time","Sort By Filename", 0);
717746
if( zCI ){
718747
style_submenu_element("All", "%s", url_render(&sURI, "ci", 0, 0, 0));
719748
if( nD==0 && !showDirOnly ){
720
- style_submenu_element("File Ages", "%R/fileage?name=%s", zUuid);
749
+ style_submenu_element("File Ages", "%R/fileage?name=%T", zCI);
721750
}
722751
}
723752
if( linkTrunk ){
724753
style_submenu_element("Trunk", "%s",
725754
url_render(&sURI, "ci", "trunk", 0, 0));
@@ -774,10 +803,11 @@
774803
tree_add_node(&sTree, zName, zUuid, mtime);
775804
nFile++;
776805
}
777806
db_finalize(&q);
778807
}
808
+ style_submenu_checkbox("nofiles", "Folders Only", 0, 0);
779809
780810
if( showDirOnly ){
781811
for(nFile=0, p=sTree.pFirst; p; p=p->pNext){
782812
if( p->pChild!=0 && p->nFullName>nD ) nFile++;
783813
}
@@ -784,18 +814,24 @@
784814
zObjType = "Folders";
785815
}else{
786816
zObjType = "Files";
787817
}
788818
789
- style_submenu_checkbox("nofiles", "Folders Only", 0, 0);
790
-
791
- if( zCI ){
792
- @ <h2>%s(zObjType) at check-in
793
- if( sqlite3_strnicmp(zCI, zUuid, (int)strlen(zCI))!=0 ){
794
- @ "%h(zCI)"
795
- }
796
- @ [%z(href("vinfo?name=%!S",zUuid))%S(zUuid)</a>] %s(blob_str(&dirname))
819
+ if( zCI && strcmp(zCI,"tip")==0 ){
820
+ @ <h2>%s(zObjType) in the %z(href("%R/info?name=tip"))latest check-in</a>
821
+ }else if( isBranchCI ){
822
+ @ <h2>%s(zObjType) in the %z(href("%R/info?name=%T",zCI))latest check-in\
823
+ @ </a> for branch %z(href("%R/timeline?r=%T",zCI))%h(zCI)</a>
824
+ if( blob_size(&dirname) ){
825
+ @ and %s(blob_str(&dirname))</h2>
826
+ }
827
+ }else if( zCI ){
828
+ @ <h2>%s(zObjType) for check-in \
829
+ @ %z(href("%R/info?name=%T",zCI))%h(zCI)</a></h2>
830
+ if( blob_size(&dirname) ){
831
+ @ and %s(blob_str(&dirname))</h2>
832
+ }
797833
}else{
798834
int n = db_int(0, "SELECT count(*) FROM plink");
799835
@ <h2>%s(zObjType) from all %d(n) check-ins %s(blob_str(&dirname))
800836
}
801837
if( useMtime ){
@@ -853,11 +889,11 @@
853889
nDir++;
854890
}else if( !showDirOnly ){
855891
const char *zFileClass = fileext_class(p->zName);
856892
char *zLink;
857893
if( zCI ){
858
- zLink = href("%R/file?name=%T&ci=%!S",p->zFullName,zCI);
894
+ zLink = href("%R/file?name=%T&ci=%T",p->zFullName,zCI);
859895
}else{
860896
zLink = href("%R/finfo?name=%T",p->zFullName);
861897
}
862898
@ <li class="%z(zFileClass)%s(zLastClass)"><div class="filetreeline">
863899
@ %z(zLink)%h(p->zName)</a>
@@ -1030,10 +1066,11 @@
10301066
int rid;
10311067
const char *zName;
10321068
const char *zGlob;
10331069
const char *zUuid;
10341070
const char *zNow; /* Time of check-in */
1071
+ int isBranchCI; /* name= is a branch name */
10351072
int showId = PB("showid");
10361073
Stmt q1, q2;
10371074
double baseTime;
10381075
login_check_credentials();
10391076
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
@@ -1043,28 +1080,34 @@
10431080
rid = symbolic_name_to_rid(zName, "ci");
10441081
if( rid==0 ){
10451082
fossil_fatal("not a valid check-in: %s", zName);
10461083
}
10471084
zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
1085
+ isBranchCI = branch_includes_uuid(zName,zUuid);
10481086
baseTime = db_double(0.0,"SELECT mtime FROM event WHERE objid=%d", rid);
10491087
zNow = db_text("", "SELECT datetime(mtime,toLocal()) FROM event"
10501088
" WHERE objid=%d", rid);
10511089
style_submenu_element("Tree-View", "%R/tree?ci=%T&mtime=1&type=tree", zName);
10521090
style_header("File Ages");
10531091
zGlob = P("glob");
10541092
compute_fileage(rid,zGlob);
10551093
db_multi_exec("CREATE INDEX fileage_ix1 ON fileage(mid,pathname);");
10561094
1057
- @ <h1>Files in
1058
- @ %z(href("%R/info/%!S",zUuid))[%S(zUuid)]</a>
1095
+ if( fossil_strcmp(zName,"tip")==0 ){
1096
+ @ <h1>Files in the %z(href("%R/info?name=tip"))latest check-in</a>
1097
+ }else if( isBranchCI ){
1098
+ @ <h1>Files in the %z(href("%R/info?name=%T",zName))latest check-in</a>
1099
+ @ of branch %z(href("%R/timeline?r=%T",zName))%h(zName)</a>
1100
+ }else{
1101
+ @ <h1>Files in check-in %z(href("%R/info?name=%T",zName))%h(zName)</a>
1102
+ }
10591103
if( zGlob && zGlob[0] ){
10601104
@ that match "%h(zGlob)"
10611105
}
10621106
@ ordered by age</h1>
10631107
@
1064
- @ <p>File ages are expressed relative to the
1065
- @ %z(href("%R/ci/%!S",zUuid))[%S(zUuid)]</a> check-in time of
1108
+ @ <p>File ages are expressed relative to the check-in time of
10661109
@ %z(href("%R/timeline?c=%t",zNow))%s(zNow)</a>.</p>
10671110
@
10681111
@ <div class='fileage'><table>
10691112
@ <tr><th>Age</th><th>Files</th><th>Check-in</th></tr>
10701113
db_prepare(&q1,
@@ -1079,14 +1122,13 @@
10791122
" AND blob.rid=event.objid\n"
10801123
" ORDER BY event.mtime DESC;",
10811124
TAG_BRANCH
10821125
);
10831126
db_prepare(&q2,
1084
- "SELECT blob.uuid, filename.name, fileage.fid\n"
1085
- " FROM fileage, blob, filename\n"
1127
+ "SELECT filename.name, fileage.fid\n"
1128
+ " FROM fileage, filename\n"
10861129
" WHERE fileage.mid=:mid AND filename.fnid=fileage.fnid"
1087
- " AND blob.rid=fileage.fid;"
10881130
);
10891131
while( db_step(&q1)==SQLITE_ROW ){
10901132
double age = baseTime - db_column_double(&q1, 0);
10911133
int mid = db_column_int(&q1, 1);
10921134
const char *zUuid = db_column_text(&q1, 2);
@@ -1096,24 +1138,24 @@
10961138
char *zAge = human_readable_age(age);
10971139
@ <tr><td>%s(zAge)</td>
10981140
@ <td>
10991141
db_bind_int(&q2, ":mid", mid);
11001142
while( db_step(&q2)==SQLITE_ROW ){
1101
- const char *zFUuid = db_column_text(&q2,0);
1102
- const char *zFile = db_column_text(&q2,1);
1103
- int fid = db_column_int(&q2,2);
1143
+ const char *zFile = db_column_text(&q2,0);
1144
+ @ %z(href("%R/file?name=%T&ci=%!S",zFile,zUuid))%h(zFile)</a> \
11041145
if( showId ){
1105
- @ %z(href("%R/artifact/%!S",zFUuid))%h(zFile)</a> (%d(fid))<br />
1146
+ int fid = db_column_int(&q2,1);
1147
+ @ (%d(fid))<br />
11061148
}else{
1107
- @ %z(href("%R/artifact/%!S",zFUuid))%h(zFile)</a><br />
1149
+ @ </a><br />
11081150
}
11091151
}
11101152
db_reset(&q2);
11111153
@ </td>
11121154
@ <td>
11131155
@ %W(zComment)
1114
- @ (check-in:&nbsp;%z(href("%R/ci/%!S",zUuid))%S(zUuid)</a>,
1156
+ @ (check-in:&nbsp;%z(href("%R/info/%!S",zUuid))%S(zUuid)</a>,
11151157
if( showId ){
11161158
@ id: %d(mid)
11171159
}
11181160
@ user:&nbsp;%z(href("%R/timeline?u=%t&c=%!S&nd",zUser,zUuid))%h(zUser)</a>,
11191161
@ branch:&nbsp;\
11201162
--- src/browse.c
+++ src/browse.c
@@ -59,10 +59,18 @@
59 zOut = sqlite3_mprintf("/%.*s", i-n, &z[n]);
60 sqlite3_result_text(context, zOut, i-n+1, sqlite3_free);
61 }
62 }
63
 
 
 
 
 
 
 
 
64 /*
65 ** Given a pathname which is a relative path from the root of
66 ** the repository to a file or directory, compute a string which
67 ** is an HTML rendering of that path with hyperlinks on each
68 ** directory component of the path where the hyperlink redirects
@@ -76,29 +84,36 @@
76 void hyperlinked_path(
77 const char *zPath, /* Path to render */
78 Blob *pOut, /* Write into this blob */
79 const char *zCI, /* check-in name, or NULL */
80 const char *zURI, /* "dir" or "tree" */
81 const char *zREx /* Extra query parameters */
 
82 ){
83 int i, j;
84 char *zSep = "";
85
86 for(i=0; zPath[i]; i=j){
87 for(j=i; zPath[j] && zPath[j]!='/'; j++){}
88 if( zPath[j] && g.perm.Hyperlink ){
89 if( zCI ){
90 char *zLink = href("%R/%s?name=%#T%s&ci=%!S", zURI, j, zPath, zREx,zCI);
91 blob_appendf(pOut, "%s%z%#h</a>",
92 zSep, zLink, j-i, &zPath[i]);
93 }else{
94 char *zLink = href("%R/%s?name=%#T%s", zURI, j, zPath, zREx);
95 blob_appendf(pOut, "%s%z%#h</a>",
96 zSep, zLink, j-i, &zPath[i]);
97 }
98 }else{
99 blob_appendf(pOut, "%s%#h", zSep, j-i, &zPath[i]);
 
 
 
 
 
 
100 }
101 zSep = "/";
102 while( zPath[j]=='/' ){ j++; }
103 }
104 }
@@ -127,17 +142,17 @@
127 char *zPrefix;
128 Stmt q;
129 const char *zCI = P("ci");
130 int rid = 0;
131 char *zUuid = 0;
132 Blob dirname;
133 Manifest *pM = 0;
134 const char *zSubdirLink;
135 int linkTrunk = 1;
136 int linkTip = 1;
137 HQuery sURI;
138 int isSymbolicCI = 0; /* ci= is symbolic name, not a hash prefix */
 
139 char *zHeader = 0;
140
141 if( zCI && strlen(zCI)==0 ){ zCI = 0; }
142 if( strcmp(PD("type","flat"),"tree")==0 ){ page_tree(); return; }
143 login_check_credentials();
@@ -157,22 +172,30 @@
157 int trunkRid = symbolic_name_to_rid("tag:trunk", "ci");
158 linkTrunk = trunkRid && rid != trunkRid;
159 linkTip = rid != symbolic_name_to_rid("tip", "ci");
160 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
161 isSymbolicCI = (sqlite3_strnicmp(zUuid, zCI, strlen(zCI))!=0);
 
 
162 }else{
163 zCI = 0;
164 }
165 }
166
167 assert( isSymbolicCI==0 || (zCI!=0 && zCI[0]!=0) );
168 if( isSymbolicCI ) {
169 zHeader = mprintf("%s at %s", (zD ? zD : "Files"), zCI);
170 }else if( zUuid && strlen(zUuid) ){
171 zHeader = mprintf("%s at [%S]", (zD ? zD : "Files"), zUuid);
 
 
172 }else{
173 zHeader = mprintf("%s", (zD ? zD : "All Files"));
 
 
 
 
174 }
175 style_header("%s", zHeader);
176 fossil_free(zHeader);
177 style_adunit_config(ADUNIT_RIGHT_OK);
178 sqlite3_create_function(g.db, "pathelement", 2, SQLITE_UTF8, 0,
@@ -179,47 +202,49 @@
179 pathelementFunc, 0, 0);
180 url_initialize(&sURI, "dir");
181 cgi_query_parameters_to_url(&sURI);
182
183 /* Compute the title of the page */
184 blob_zero(&dirname);
185 if( zD ){
186 blob_append(&dirname, "in directory ", -1);
187 hyperlinked_path(zD, &dirname, zCI, "dir", "");
 
 
 
188 zPrefix = mprintf("%s/", zD);
189 style_submenu_element("Top-Level", "%s",
190 url_render(&sURI, "name", 0, 0, 0));
191 }else{
192 blob_append(&dirname, "in the top-level directory", -1);
193 zPrefix = "";
194 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
195 if( linkTrunk ){
196 style_submenu_element("Trunk", "%s",
197 url_render(&sURI, "ci", "trunk", 0, 0));
198 }
199 if( linkTip ){
200 style_submenu_element("Tip", "%s", url_render(&sURI, "ci", "tip", 0, 0));
201 }
202 if( zCI ){
203 @ <h2>Files at check-in [%z(href("vinfo?name=%!S",zUuid))%S(zUuid)</a>]
204 @ %s(blob_str(&dirname))
205 if( zD ){
206 @ &nbsp;&nbsp;%z(href("%R/timeline?chng=%T/*", zD))[history]</a>
207 }
208 @ </h2>
209 zSubdirLink = mprintf("%R/dir?ci=%!S&name=%T", zUuid, zPrefix);
210 if( nD==0 ){
211 style_submenu_element("File Ages", "%R/fileage?name=%!S", zUuid);
212 }
213 }else{
214 @ <h2>All files known in the repository
215 @ %s(blob_str(&dirname))
216 if( zD ){
217 @ &nbsp;&nbsp;%z(href("%R/timeline?chng=%T/*", zD))[history]</a>
218 }
219 @ </h2>
220 zSubdirLink = mprintf("%R/dir?name=%T", zPrefix);
221 }
222 style_submenu_element("All", "%s", url_render(&sURI, "ci", 0, 0, 0));
223 style_submenu_element("Tree-View", "%s",
224 url_render(&sURI, "type", "tree", 0, 0));
225
@@ -296,11 +321,11 @@
296 zFN++;
297 @ <li class="dir">%z(href("%s%T",zSubdirLink,zFN))%h(zFN)</a></li>
298 }else{
299 const char *zLink;
300 if( zCI ){
301 zLink = href("%R/file?name=%T%T&ci=%!S",zPrefix,zFN,zCI);
302 }else{
303 zLink = href("%R/finfo?name=%T%T",zPrefix,zFN);
304 }
305 @ <li class="%z(fileext_class(zFN))">%z(zLink)%h(zFN)</a></li>
306 }
@@ -626,10 +651,11 @@
626 int startExpanded; /* True to start out with the tree expanded */
627 int showDirOnly; /* Show directories only. Omit files */
628 int nDir = 0; /* Number of directories. Used for ID attributes */
629 char *zProjectName = db_get("project-name", 0);
630 int isSymbolicCI = 0; /* ci= is a symbolic name, not a hash prefix */
 
631 char *zHeader = 0;
632
633 if( zCI && strlen(zCI)==0 ){ zCI = 0; }
634 if( strcmp(PD("type","flat"),"flat")==0 ){ page_dir(); return; }
635 memset(&sTree, 0, sizeof(sTree));
@@ -675,10 +701,12 @@
675 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
676 rNow = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid);
677 zNow = db_text("", "SELECT datetime(mtime,toLocal())"
678 " FROM event WHERE objid=%d", rid);
679 isSymbolicCI = (sqlite3_strnicmp(zUuid, zCI, strlen(zCI)) != 0);
 
 
680 }else{
681 zCI = 0;
682 }
683 }
684 if( zCI==0 ){
@@ -685,41 +713,42 @@
685 rNow = db_double(0.0, "SELECT max(mtime) FROM event");
686 zNow = db_text("", "SELECT datetime(max(mtime),toLocal()) FROM event");
687 }
688
689 assert( isSymbolicCI==0 || (zCI!=0 && zCI[0]!=0) );
690 if( isSymbolicCI ) {
691 zHeader = mprintf("%s at %s",
692 (zD ? zD : (showDirOnly ? "Folder Hierarchy" : "Tree-View")), zCI);
693 }else if( zUuid && strlen(zUuid) ){
694 zHeader = mprintf("%s at [%S]",
695 (zD ? zD : (showDirOnly ? "Folder Hierarchy" : "Tree-View")), zUuid);
696 }else{
697 zHeader = mprintf("%s",
698 (zD ? zD : (showDirOnly ?"All Folders Hierarchy":"All Files Tree-View")));
 
 
 
699 }
700 style_header("%s", zHeader);
701 fossil_free(zHeader);
702
703 /* Compute the title of the page */
704 blob_zero(&dirname);
705 if( zD ){
706 blob_append(&dirname, "within directory ", -1);
707 hyperlinked_path(zD, &dirname, zCI, "tree", zREx);
708 if( zRE ) blob_appendf(&dirname, " matching \"%s\"", zRE);
709 style_submenu_element("Top-Level", "%s",
710 url_render(&sURI, "name", 0, 0, 0));
711 }else{
712 if( zRE ){
713 blob_appendf(&dirname, "matching \"%s\"", zRE);
714 }
715 }
716 style_submenu_binary("mtime","Sort By Time","Sort By Filename", 0);
717 if( zCI ){
718 style_submenu_element("All", "%s", url_render(&sURI, "ci", 0, 0, 0));
719 if( nD==0 && !showDirOnly ){
720 style_submenu_element("File Ages", "%R/fileage?name=%s", zUuid);
721 }
722 }
723 if( linkTrunk ){
724 style_submenu_element("Trunk", "%s",
725 url_render(&sURI, "ci", "trunk", 0, 0));
@@ -774,10 +803,11 @@
774 tree_add_node(&sTree, zName, zUuid, mtime);
775 nFile++;
776 }
777 db_finalize(&q);
778 }
 
779
780 if( showDirOnly ){
781 for(nFile=0, p=sTree.pFirst; p; p=p->pNext){
782 if( p->pChild!=0 && p->nFullName>nD ) nFile++;
783 }
@@ -784,18 +814,24 @@
784 zObjType = "Folders";
785 }else{
786 zObjType = "Files";
787 }
788
789 style_submenu_checkbox("nofiles", "Folders Only", 0, 0);
790
791 if( zCI ){
792 @ <h2>%s(zObjType) at check-in
793 if( sqlite3_strnicmp(zCI, zUuid, (int)strlen(zCI))!=0 ){
794 @ "%h(zCI)"
795 }
796 @ [%z(href("vinfo?name=%!S",zUuid))%S(zUuid)</a>] %s(blob_str(&dirname))
 
 
 
 
 
 
797 }else{
798 int n = db_int(0, "SELECT count(*) FROM plink");
799 @ <h2>%s(zObjType) from all %d(n) check-ins %s(blob_str(&dirname))
800 }
801 if( useMtime ){
@@ -853,11 +889,11 @@
853 nDir++;
854 }else if( !showDirOnly ){
855 const char *zFileClass = fileext_class(p->zName);
856 char *zLink;
857 if( zCI ){
858 zLink = href("%R/file?name=%T&ci=%!S",p->zFullName,zCI);
859 }else{
860 zLink = href("%R/finfo?name=%T",p->zFullName);
861 }
862 @ <li class="%z(zFileClass)%s(zLastClass)"><div class="filetreeline">
863 @ %z(zLink)%h(p->zName)</a>
@@ -1030,10 +1066,11 @@
1030 int rid;
1031 const char *zName;
1032 const char *zGlob;
1033 const char *zUuid;
1034 const char *zNow; /* Time of check-in */
 
1035 int showId = PB("showid");
1036 Stmt q1, q2;
1037 double baseTime;
1038 login_check_credentials();
1039 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
@@ -1043,28 +1080,34 @@
1043 rid = symbolic_name_to_rid(zName, "ci");
1044 if( rid==0 ){
1045 fossil_fatal("not a valid check-in: %s", zName);
1046 }
1047 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
 
1048 baseTime = db_double(0.0,"SELECT mtime FROM event WHERE objid=%d", rid);
1049 zNow = db_text("", "SELECT datetime(mtime,toLocal()) FROM event"
1050 " WHERE objid=%d", rid);
1051 style_submenu_element("Tree-View", "%R/tree?ci=%T&mtime=1&type=tree", zName);
1052 style_header("File Ages");
1053 zGlob = P("glob");
1054 compute_fileage(rid,zGlob);
1055 db_multi_exec("CREATE INDEX fileage_ix1 ON fileage(mid,pathname);");
1056
1057 @ <h1>Files in
1058 @ %z(href("%R/info/%!S",zUuid))[%S(zUuid)]</a>
 
 
 
 
 
 
1059 if( zGlob && zGlob[0] ){
1060 @ that match "%h(zGlob)"
1061 }
1062 @ ordered by age</h1>
1063 @
1064 @ <p>File ages are expressed relative to the
1065 @ %z(href("%R/ci/%!S",zUuid))[%S(zUuid)]</a> check-in time of
1066 @ %z(href("%R/timeline?c=%t",zNow))%s(zNow)</a>.</p>
1067 @
1068 @ <div class='fileage'><table>
1069 @ <tr><th>Age</th><th>Files</th><th>Check-in</th></tr>
1070 db_prepare(&q1,
@@ -1079,14 +1122,13 @@
1079 " AND blob.rid=event.objid\n"
1080 " ORDER BY event.mtime DESC;",
1081 TAG_BRANCH
1082 );
1083 db_prepare(&q2,
1084 "SELECT blob.uuid, filename.name, fileage.fid\n"
1085 " FROM fileage, blob, filename\n"
1086 " WHERE fileage.mid=:mid AND filename.fnid=fileage.fnid"
1087 " AND blob.rid=fileage.fid;"
1088 );
1089 while( db_step(&q1)==SQLITE_ROW ){
1090 double age = baseTime - db_column_double(&q1, 0);
1091 int mid = db_column_int(&q1, 1);
1092 const char *zUuid = db_column_text(&q1, 2);
@@ -1096,24 +1138,24 @@
1096 char *zAge = human_readable_age(age);
1097 @ <tr><td>%s(zAge)</td>
1098 @ <td>
1099 db_bind_int(&q2, ":mid", mid);
1100 while( db_step(&q2)==SQLITE_ROW ){
1101 const char *zFUuid = db_column_text(&q2,0);
1102 const char *zFile = db_column_text(&q2,1);
1103 int fid = db_column_int(&q2,2);
1104 if( showId ){
1105 @ %z(href("%R/artifact/%!S",zFUuid))%h(zFile)</a> (%d(fid))<br />
 
1106 }else{
1107 @ %z(href("%R/artifact/%!S",zFUuid))%h(zFile)</a><br />
1108 }
1109 }
1110 db_reset(&q2);
1111 @ </td>
1112 @ <td>
1113 @ %W(zComment)
1114 @ (check-in:&nbsp;%z(href("%R/ci/%!S",zUuid))%S(zUuid)</a>,
1115 if( showId ){
1116 @ id: %d(mid)
1117 }
1118 @ user:&nbsp;%z(href("%R/timeline?u=%t&c=%!S&nd",zUser,zUuid))%h(zUser)</a>,
1119 @ branch:&nbsp;\
1120
--- src/browse.c
+++ src/browse.c
@@ -59,10 +59,18 @@
59 zOut = sqlite3_mprintf("/%.*s", i-n, &z[n]);
60 sqlite3_result_text(context, zOut, i-n+1, sqlite3_free);
61 }
62 }
63
64 /*
65 ** Flag arguments for hyperlinked_path()
66 */
67 #if INTERFACE
68 # define LINKPATH_FINFO 0x0001 /* Link final term to /finfo */
69 # define LINKPATH_FILE 0x0002 /* Link final term to /file */
70 #endif
71
72 /*
73 ** Given a pathname which is a relative path from the root of
74 ** the repository to a file or directory, compute a string which
75 ** is an HTML rendering of that path with hyperlinks on each
76 ** directory component of the path where the hyperlink redirects
@@ -76,29 +84,36 @@
84 void hyperlinked_path(
85 const char *zPath, /* Path to render */
86 Blob *pOut, /* Write into this blob */
87 const char *zCI, /* check-in name, or NULL */
88 const char *zURI, /* "dir" or "tree" */
89 const char *zREx, /* Extra query parameters */
90 unsigned int mFlags /* Extra flags */
91 ){
92 int i, j;
93 char *zSep = "";
94
95 for(i=0; zPath[i]; i=j){
96 for(j=i; zPath[j] && zPath[j]!='/'; j++){}
97 if( zPath[j]==0 ){
98 if( mFlags & LINKPATH_FILE ){
99 zURI = "file";
100 }else if( mFlags & LINKPATH_FINFO ){
101 zURI = "finfo";
102 }else{
103 blob_appendf(pOut, "/%h", zPath+i);
104 break;
105 }
106 }
107 if( zCI ){
108 char *zLink = href("%R/%s?name=%#T%s&ci=%T", zURI, j, zPath, zREx,zCI);
109 blob_appendf(pOut, "%s%z%#h</a>",
110 zSep, zLink, j-i, &zPath[i]);
111 }else{
112 char *zLink = href("%R/%s?name=%#T%s", zURI, j, zPath, zREx);
113 blob_appendf(pOut, "%s%z%#h</a>",
114 zSep, zLink, j-i, &zPath[i]);
115 }
116 zSep = "/";
117 while( zPath[j]=='/' ){ j++; }
118 }
119 }
@@ -127,17 +142,17 @@
142 char *zPrefix;
143 Stmt q;
144 const char *zCI = P("ci");
145 int rid = 0;
146 char *zUuid = 0;
 
147 Manifest *pM = 0;
148 const char *zSubdirLink;
149 int linkTrunk = 1;
150 int linkTip = 1;
151 HQuery sURI;
152 int isSymbolicCI = 0; /* ci= is symbolic name, not a hash prefix */
153 int isBranchCI = 0; /* True if ci= refers to a branch name */
154 char *zHeader = 0;
155
156 if( zCI && strlen(zCI)==0 ){ zCI = 0; }
157 if( strcmp(PD("type","flat"),"tree")==0 ){ page_tree(); return; }
158 login_check_credentials();
@@ -157,22 +172,30 @@
172 int trunkRid = symbolic_name_to_rid("tag:trunk", "ci");
173 linkTrunk = trunkRid && rid != trunkRid;
174 linkTip = rid != symbolic_name_to_rid("tip", "ci");
175 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
176 isSymbolicCI = (sqlite3_strnicmp(zUuid, zCI, strlen(zCI))!=0);
177 isBranchCI = branch_includes_uuid(zCI, zUuid);
178 Th_Store("current_checkin", zCI);
179 }else{
180 zCI = 0;
181 }
182 }
183
184 assert( isSymbolicCI==0 || (zCI!=0 && zCI[0]!=0) );
185 if( zD==0 ){
186 if( zCI ){
187 zHeader = mprintf("Top-level Files of %s", zCI);
188 }else{
189 zHeader = mprintf("All Top-level Files");
190 }
191 }else{
192 if( zCI ){
193 zHeader = mprintf("Files in %s/ of %s", zD, zCI);
194 }else{
195 zHeader = mprintf("All File in %s/", zD);
196 }
197 }
198 style_header("%s", zHeader);
199 fossil_free(zHeader);
200 style_adunit_config(ADUNIT_RIGHT_OK);
201 sqlite3_create_function(g.db, "pathelement", 2, SQLITE_UTF8, 0,
@@ -179,47 +202,49 @@
202 pathelementFunc, 0, 0);
203 url_initialize(&sURI, "dir");
204 cgi_query_parameters_to_url(&sURI);
205
206 /* Compute the title of the page */
 
207 if( zD ){
208 Blob dirname;
209 blob_init(&dirname, 0, 0);
210 hyperlinked_path(zD, &dirname, zCI, "dir", "", 0);
211 @ <h2>Files in directory %s(blob_str(&dirname)) \
212 blob_reset(&dirname);
213 zPrefix = mprintf("%s/", zD);
214 style_submenu_element("Top-Level", "%s",
215 url_render(&sURI, "name", 0, 0, 0));
216 }else{
217 @ <h2>Files in the top-level directory \
218 zPrefix = "";
219 }
220 if( zCI ){
221 if( fossil_strcmp(zCI,"tip")==0 ){
222 @ from the %z(href("%R/info?name=%T",zCI))latest check-in</a></h2>
223 }else if( isBranchCI ){
224 @ from the %z(href("%R/info?name=%T",zCI))latest check-in</a> \
225 @ of branch %z(href("%R/timeline?r=%T",zCI))%h(zCI)</a></h2>
226 }else {
227 @ of check-in %z(href("%R/info?name=%T",zCI))%h(zCI)</a></h2>
228 }
229 zSubdirLink = mprintf("%R/dir?ci=%T&name=%T", zCI, zPrefix);
230 if( nD==0 ){
231 style_submenu_element("File Ages", "%R/fileage?name=%T", zCI);
232 }
233 }else{
234 @ in any check-in</h2>
235 zSubdirLink = mprintf("%R/dir?name=%T", zPrefix);
236 }
237 if( linkTrunk ){
238 style_submenu_element("Trunk", "%s",
239 url_render(&sURI, "ci", "trunk", 0, 0));
240 }
241 if( linkTip ){
242 style_submenu_element("Tip", "%s", url_render(&sURI, "ci", "tip", 0, 0));
243 }
244 if( zD ){
245 style_submenu_element("History","%R/timeline?chng=%T/*", zD);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
246 }
247 style_submenu_element("All", "%s", url_render(&sURI, "ci", 0, 0, 0));
248 style_submenu_element("Tree-View", "%s",
249 url_render(&sURI, "type", "tree", 0, 0));
250
@@ -296,11 +321,11 @@
321 zFN++;
322 @ <li class="dir">%z(href("%s%T",zSubdirLink,zFN))%h(zFN)</a></li>
323 }else{
324 const char *zLink;
325 if( zCI ){
326 zLink = href("%R/file?name=%T%T&ci=%T",zPrefix,zFN,zCI);
327 }else{
328 zLink = href("%R/finfo?name=%T%T",zPrefix,zFN);
329 }
330 @ <li class="%z(fileext_class(zFN))">%z(zLink)%h(zFN)</a></li>
331 }
@@ -626,10 +651,11 @@
651 int startExpanded; /* True to start out with the tree expanded */
652 int showDirOnly; /* Show directories only. Omit files */
653 int nDir = 0; /* Number of directories. Used for ID attributes */
654 char *zProjectName = db_get("project-name", 0);
655 int isSymbolicCI = 0; /* ci= is a symbolic name, not a hash prefix */
656 int isBranchCI = 0; /* ci= refers to a branch name */
657 char *zHeader = 0;
658
659 if( zCI && strlen(zCI)==0 ){ zCI = 0; }
660 if( strcmp(PD("type","flat"),"flat")==0 ){ page_dir(); return; }
661 memset(&sTree, 0, sizeof(sTree));
@@ -675,10 +701,12 @@
701 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
702 rNow = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid);
703 zNow = db_text("", "SELECT datetime(mtime,toLocal())"
704 " FROM event WHERE objid=%d", rid);
705 isSymbolicCI = (sqlite3_strnicmp(zUuid, zCI, strlen(zCI)) != 0);
706 isBranchCI = branch_includes_uuid(zCI, zUuid);
707 Th_Store("current_checkin", zCI);
708 }else{
709 zCI = 0;
710 }
711 }
712 if( zCI==0 ){
@@ -685,41 +713,42 @@
713 rNow = db_double(0.0, "SELECT max(mtime) FROM event");
714 zNow = db_text("", "SELECT datetime(max(mtime),toLocal()) FROM event");
715 }
716
717 assert( isSymbolicCI==0 || (zCI!=0 && zCI[0]!=0) );
718 if( zD==0 ){
719 if( zCI ){
720 zHeader = mprintf("Top-level Files of %s", zCI);
721 }else{
722 zHeader = mprintf("All Top-level Files");
723 }
724 }else{
725 if( zCI ){
726 zHeader = mprintf("Files in %s/ of %s", zD, zCI);
727 }else{
728 zHeader = mprintf("All File in %s/", zD);
729 }
730 }
731 style_header("%s", zHeader);
732 fossil_free(zHeader);
733
734 /* Compute the title of the page */
735 blob_zero(&dirname);
736 if( zD ){
737 blob_append(&dirname, "within directory ", -1);
738 hyperlinked_path(zD, &dirname, zCI, "tree", zREx, 0);
739 if( zRE ) blob_appendf(&dirname, " matching \"%s\"", zRE);
740 style_submenu_element("Top-Level", "%s",
741 url_render(&sURI, "name", 0, 0, 0));
742 }else if( zRE ){
743 blob_appendf(&dirname, "matching \"%s\"", zRE);
 
 
744 }
745 style_submenu_binary("mtime","Sort By Time","Sort By Filename", 0);
746 if( zCI ){
747 style_submenu_element("All", "%s", url_render(&sURI, "ci", 0, 0, 0));
748 if( nD==0 && !showDirOnly ){
749 style_submenu_element("File Ages", "%R/fileage?name=%T", zCI);
750 }
751 }
752 if( linkTrunk ){
753 style_submenu_element("Trunk", "%s",
754 url_render(&sURI, "ci", "trunk", 0, 0));
@@ -774,10 +803,11 @@
803 tree_add_node(&sTree, zName, zUuid, mtime);
804 nFile++;
805 }
806 db_finalize(&q);
807 }
808 style_submenu_checkbox("nofiles", "Folders Only", 0, 0);
809
810 if( showDirOnly ){
811 for(nFile=0, p=sTree.pFirst; p; p=p->pNext){
812 if( p->pChild!=0 && p->nFullName>nD ) nFile++;
813 }
@@ -784,18 +814,24 @@
814 zObjType = "Folders";
815 }else{
816 zObjType = "Files";
817 }
818
819 if( zCI && strcmp(zCI,"tip")==0 ){
820 @ <h2>%s(zObjType) in the %z(href("%R/info?name=tip"))latest check-in</a>
821 }else if( isBranchCI ){
822 @ <h2>%s(zObjType) in the %z(href("%R/info?name=%T",zCI))latest check-in\
823 @ </a> for branch %z(href("%R/timeline?r=%T",zCI))%h(zCI)</a>
824 if( blob_size(&dirname) ){
825 @ and %s(blob_str(&dirname))</h2>
826 }
827 }else if( zCI ){
828 @ <h2>%s(zObjType) for check-in \
829 @ %z(href("%R/info?name=%T",zCI))%h(zCI)</a></h2>
830 if( blob_size(&dirname) ){
831 @ and %s(blob_str(&dirname))</h2>
832 }
833 }else{
834 int n = db_int(0, "SELECT count(*) FROM plink");
835 @ <h2>%s(zObjType) from all %d(n) check-ins %s(blob_str(&dirname))
836 }
837 if( useMtime ){
@@ -853,11 +889,11 @@
889 nDir++;
890 }else if( !showDirOnly ){
891 const char *zFileClass = fileext_class(p->zName);
892 char *zLink;
893 if( zCI ){
894 zLink = href("%R/file?name=%T&ci=%T",p->zFullName,zCI);
895 }else{
896 zLink = href("%R/finfo?name=%T",p->zFullName);
897 }
898 @ <li class="%z(zFileClass)%s(zLastClass)"><div class="filetreeline">
899 @ %z(zLink)%h(p->zName)</a>
@@ -1030,10 +1066,11 @@
1066 int rid;
1067 const char *zName;
1068 const char *zGlob;
1069 const char *zUuid;
1070 const char *zNow; /* Time of check-in */
1071 int isBranchCI; /* name= is a branch name */
1072 int showId = PB("showid");
1073 Stmt q1, q2;
1074 double baseTime;
1075 login_check_credentials();
1076 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
@@ -1043,28 +1080,34 @@
1080 rid = symbolic_name_to_rid(zName, "ci");
1081 if( rid==0 ){
1082 fossil_fatal("not a valid check-in: %s", zName);
1083 }
1084 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
1085 isBranchCI = branch_includes_uuid(zName,zUuid);
1086 baseTime = db_double(0.0,"SELECT mtime FROM event WHERE objid=%d", rid);
1087 zNow = db_text("", "SELECT datetime(mtime,toLocal()) FROM event"
1088 " WHERE objid=%d", rid);
1089 style_submenu_element("Tree-View", "%R/tree?ci=%T&mtime=1&type=tree", zName);
1090 style_header("File Ages");
1091 zGlob = P("glob");
1092 compute_fileage(rid,zGlob);
1093 db_multi_exec("CREATE INDEX fileage_ix1 ON fileage(mid,pathname);");
1094
1095 if( fossil_strcmp(zName,"tip")==0 ){
1096 @ <h1>Files in the %z(href("%R/info?name=tip"))latest check-in</a>
1097 }else if( isBranchCI ){
1098 @ <h1>Files in the %z(href("%R/info?name=%T",zName))latest check-in</a>
1099 @ of branch %z(href("%R/timeline?r=%T",zName))%h(zName)</a>
1100 }else{
1101 @ <h1>Files in check-in %z(href("%R/info?name=%T",zName))%h(zName)</a>
1102 }
1103 if( zGlob && zGlob[0] ){
1104 @ that match "%h(zGlob)"
1105 }
1106 @ ordered by age</h1>
1107 @
1108 @ <p>File ages are expressed relative to the check-in time of
 
1109 @ %z(href("%R/timeline?c=%t",zNow))%s(zNow)</a>.</p>
1110 @
1111 @ <div class='fileage'><table>
1112 @ <tr><th>Age</th><th>Files</th><th>Check-in</th></tr>
1113 db_prepare(&q1,
@@ -1079,14 +1122,13 @@
1122 " AND blob.rid=event.objid\n"
1123 " ORDER BY event.mtime DESC;",
1124 TAG_BRANCH
1125 );
1126 db_prepare(&q2,
1127 "SELECT filename.name, fileage.fid\n"
1128 " FROM fileage, filename\n"
1129 " WHERE fileage.mid=:mid AND filename.fnid=fileage.fnid"
 
1130 );
1131 while( db_step(&q1)==SQLITE_ROW ){
1132 double age = baseTime - db_column_double(&q1, 0);
1133 int mid = db_column_int(&q1, 1);
1134 const char *zUuid = db_column_text(&q1, 2);
@@ -1096,24 +1138,24 @@
1138 char *zAge = human_readable_age(age);
1139 @ <tr><td>%s(zAge)</td>
1140 @ <td>
1141 db_bind_int(&q2, ":mid", mid);
1142 while( db_step(&q2)==SQLITE_ROW ){
1143 const char *zFile = db_column_text(&q2,0);
1144 @ %z(href("%R/file?name=%T&ci=%!S",zFile,zUuid))%h(zFile)</a> \
 
1145 if( showId ){
1146 int fid = db_column_int(&q2,1);
1147 @ (%d(fid))<br />
1148 }else{
1149 @ </a><br />
1150 }
1151 }
1152 db_reset(&q2);
1153 @ </td>
1154 @ <td>
1155 @ %W(zComment)
1156 @ (check-in:&nbsp;%z(href("%R/info/%!S",zUuid))%S(zUuid)</a>,
1157 if( showId ){
1158 @ id: %d(mid)
1159 }
1160 @ user:&nbsp;%z(href("%R/timeline?u=%t&c=%!S&nd",zUser,zUuid))%h(zUser)</a>,
1161 @ branch:&nbsp;\
1162
--- src/capabilities.c
+++ src/capabilities.c
@@ -239,11 +239,11 @@
239239
char *zOneLiner; /* One-line summary */
240240
} aCap[] = {
241241
{ 'a', CAPCLASS_SUPER, 0,
242242
"Admin", "Create and delete users" },
243243
{ 'b', CAPCLASS_WIKI|CAPCLASS_TKT, 0,
244
- "Attach", "Add attchments to wiki or tickets" },
244
+ "Attach", "Add attachments to wiki or tickets" },
245245
{ 'c', CAPCLASS_TKT, 0,
246246
"Append-Tkt", "Append to existing tickets" },
247247
/*
248248
** d unused since fork from CVSTrac;
249249
** see https://fossil-scm.org/forum/forumpost/43c78f4bef
250250
--- src/capabilities.c
+++ src/capabilities.c
@@ -239,11 +239,11 @@
239 char *zOneLiner; /* One-line summary */
240 } aCap[] = {
241 { 'a', CAPCLASS_SUPER, 0,
242 "Admin", "Create and delete users" },
243 { 'b', CAPCLASS_WIKI|CAPCLASS_TKT, 0,
244 "Attach", "Add attchments to wiki or tickets" },
245 { 'c', CAPCLASS_TKT, 0,
246 "Append-Tkt", "Append to existing tickets" },
247 /*
248 ** d unused since fork from CVSTrac;
249 ** see https://fossil-scm.org/forum/forumpost/43c78f4bef
250
--- src/capabilities.c
+++ src/capabilities.c
@@ -239,11 +239,11 @@
239 char *zOneLiner; /* One-line summary */
240 } aCap[] = {
241 { 'a', CAPCLASS_SUPER, 0,
242 "Admin", "Create and delete users" },
243 { 'b', CAPCLASS_WIKI|CAPCLASS_TKT, 0,
244 "Attach", "Add attachments to wiki or tickets" },
245 { 'c', CAPCLASS_TKT, 0,
246 "Append-Tkt", "Append to existing tickets" },
247 /*
248 ** d unused since fork from CVSTrac;
249 ** see https://fossil-scm.org/forum/forumpost/43c78f4bef
250
+2 -1
--- src/captcha.c
+++ src/captcha.c
@@ -558,11 +558,12 @@
558558
/*
559559
** Add a "Speak the captcha" button.
560560
*/
561561
void captcha_speakit_button(unsigned int uSeed, const char *zMsg){
562562
if( zMsg==0 ) zMsg = "Speak the text";
563
- @ <input type="button" value="%h(zMsg)" id="speakthetext">
563
+ @ <input aria-label="%h(zMsg)" type="button" value="%h(zMsg)" \
564
+ @ id="speakthetext">
564565
@ <script nonce="%h(style_nonce())">
565566
@ document.getElementById("speakthetext").onclick = function(){
566567
@ var audio = window.fossilAudioCaptcha \
567568
@ || new Audio("%R/captcha-audio/%u(uSeed)");
568569
@ window.fossilAudioCaptcha = audio;
569570
--- src/captcha.c
+++ src/captcha.c
@@ -558,11 +558,12 @@
558 /*
559 ** Add a "Speak the captcha" button.
560 */
561 void captcha_speakit_button(unsigned int uSeed, const char *zMsg){
562 if( zMsg==0 ) zMsg = "Speak the text";
563 @ <input type="button" value="%h(zMsg)" id="speakthetext">
 
564 @ <script nonce="%h(style_nonce())">
565 @ document.getElementById("speakthetext").onclick = function(){
566 @ var audio = window.fossilAudioCaptcha \
567 @ || new Audio("%R/captcha-audio/%u(uSeed)");
568 @ window.fossilAudioCaptcha = audio;
569
--- src/captcha.c
+++ src/captcha.c
@@ -558,11 +558,12 @@
558 /*
559 ** Add a "Speak the captcha" button.
560 */
561 void captcha_speakit_button(unsigned int uSeed, const char *zMsg){
562 if( zMsg==0 ) zMsg = "Speak the text";
563 @ <input aria-label="%h(zMsg)" type="button" value="%h(zMsg)" \
564 @ id="speakthetext">
565 @ <script nonce="%h(style_nonce())">
566 @ document.getElementById("speakthetext").onclick = function(){
567 @ var audio = window.fossilAudioCaptcha \
568 @ || new Audio("%R/captcha-audio/%u(uSeed)");
569 @ window.fossilAudioCaptcha = audio;
570
--- src/content.c
+++ src/content.c
@@ -944,13 +944,19 @@
944944
** Verify that all content can be extracted from the BLOB table correctly.
945945
** If the BLOB table is correct, then the repository can always be
946946
** successfully reconstructed using "fossil rebuild".
947947
**
948948
** Options:
949
+**
950
+** -d|--db-only Run "PRAGMA integrity_check" on the database only.
951
+** No other validation is performed.
949952
**
950953
** --parse Parse all manifests, wikis, tickets, events, and
951954
** so forth, reporting any errors found.
955
+**
956
+** -q|--quick Run "PRAGMA quick_check" on the database only.
957
+** No other validation is performed.
952958
*/
953959
void test_integrity(void){
954960
Stmt q;
955961
Blob content;
956962
int n1 = 0;
@@ -958,11 +964,25 @@
958964
int nErr = 0;
959965
int total;
960966
int nCA = 0;
961967
int anCA[10];
962968
int bParse = find_option("parse",0,0)!=0;
969
+ int bDbOnly = find_option("db-only","d",0)!=0;
970
+ int bQuick = find_option("quick","q",0)!=0;
963971
db_find_and_open_repository(OPEN_ANY_SCHEMA, 2);
972
+ if( bDbOnly || bQuick ){
973
+ const char *zType = bQuick ? "quick" : "integrity";
974
+ char *zRes;
975
+ zRes = db_text(0,"PRAGMA repository.%s_check", zType/*safe-for-%s*/);
976
+ if( fossil_strcmp(zRes,"ok")!=0 ){
977
+ fossil_print("%s_check failed!\n", zType);
978
+ exit(1);
979
+ }else{
980
+ fossil_print("ok\n");
981
+ }
982
+ return;
983
+ }
964984
memset(anCA, 0, sizeof(anCA));
965985
966986
/* Make sure no public artifact is a delta from a private artifact */
967987
db_prepare(&q,
968988
"SELECT "
969989
--- src/content.c
+++ src/content.c
@@ -944,13 +944,19 @@
944 ** Verify that all content can be extracted from the BLOB table correctly.
945 ** If the BLOB table is correct, then the repository can always be
946 ** successfully reconstructed using "fossil rebuild".
947 **
948 ** Options:
 
 
 
949 **
950 ** --parse Parse all manifests, wikis, tickets, events, and
951 ** so forth, reporting any errors found.
 
 
 
952 */
953 void test_integrity(void){
954 Stmt q;
955 Blob content;
956 int n1 = 0;
@@ -958,11 +964,25 @@
958 int nErr = 0;
959 int total;
960 int nCA = 0;
961 int anCA[10];
962 int bParse = find_option("parse",0,0)!=0;
 
 
963 db_find_and_open_repository(OPEN_ANY_SCHEMA, 2);
 
 
 
 
 
 
 
 
 
 
 
 
964 memset(anCA, 0, sizeof(anCA));
965
966 /* Make sure no public artifact is a delta from a private artifact */
967 db_prepare(&q,
968 "SELECT "
969
--- src/content.c
+++ src/content.c
@@ -944,13 +944,19 @@
944 ** Verify that all content can be extracted from the BLOB table correctly.
945 ** If the BLOB table is correct, then the repository can always be
946 ** successfully reconstructed using "fossil rebuild".
947 **
948 ** Options:
949 **
950 ** -d|--db-only Run "PRAGMA integrity_check" on the database only.
951 ** No other validation is performed.
952 **
953 ** --parse Parse all manifests, wikis, tickets, events, and
954 ** so forth, reporting any errors found.
955 **
956 ** -q|--quick Run "PRAGMA quick_check" on the database only.
957 ** No other validation is performed.
958 */
959 void test_integrity(void){
960 Stmt q;
961 Blob content;
962 int n1 = 0;
@@ -958,11 +964,25 @@
964 int nErr = 0;
965 int total;
966 int nCA = 0;
967 int anCA[10];
968 int bParse = find_option("parse",0,0)!=0;
969 int bDbOnly = find_option("db-only","d",0)!=0;
970 int bQuick = find_option("quick","q",0)!=0;
971 db_find_and_open_repository(OPEN_ANY_SCHEMA, 2);
972 if( bDbOnly || bQuick ){
973 const char *zType = bQuick ? "quick" : "integrity";
974 char *zRes;
975 zRes = db_text(0,"PRAGMA repository.%s_check", zType/*safe-for-%s*/);
976 if( fossil_strcmp(zRes,"ok")!=0 ){
977 fossil_print("%s_check failed!\n", zType);
978 exit(1);
979 }else{
980 fossil_print("ok\n");
981 }
982 return;
983 }
984 memset(anCA, 0, sizeof(anCA));
985
986 /* Make sure no public artifact is a delta from a private artifact */
987 db_prepare(&q,
988 "SELECT "
989
+19 -14
--- src/doc.c
+++ src/doc.c
@@ -810,11 +810,11 @@
810810
** WEBPAGE: doc
811811
** URL: /uv/FILE
812812
** URL: /doc/CHECKIN/FILE
813813
**
814814
** CHECKIN can be either tag or hash prefix or timestamp identifying a
815
-** particular check, or the name of a branch (meaning the most recent
815
+** particular check-in, or the name of a branch (meaning the most recent
816816
** check-in on that branch) or one of various magic words:
817817
**
818818
** "tip" means the most recent check-in
819819
**
820820
** "ckout" means the current check-out, if the server is run from
@@ -824,11 +824,12 @@
824824
** regardless of what branch it occurs on.
825825
**
826826
** FILE is the name of a file to delivered up as a webpage. FILE is relative
827827
** to the root of the source tree of the repository. The FILE must
828828
** be a part of CHECKIN, except when CHECKIN=="ckout" when FILE is read
829
-** directly from disk and need not be a managed file.
829
+** directly from disk and need not be a managed file. For /uv, FILE
830
+** can also be the hash of the unversioned file.
830831
**
831832
** The "ckout" CHECKIN is intended for development - to provide a mechanism
832833
** for looking at what a file will look like using the /doc webpage after
833834
** it gets checked in.
834835
**
@@ -931,22 +932,26 @@
931932
goto doc_not_found;
932933
}
933934
}
934935
if( isUV ){
935936
if( db_table_exists("repository","unversioned") ){
936
- Stmt q;
937
- db_prepare(&q, "SELECT hash, mtime FROM unversioned"
938
- " WHERE name=%Q", zName);
939
- if( db_step(&q)==SQLITE_ROW ){
940
- etag_check(ETAG_HASH, db_column_text(&q,0));
941
- etag_last_modified(db_column_int64(&q,1));
942
- }
943
- db_finalize(&q);
944
- if( unversioned_content(zName, &filebody)==0 ){
945
- rid = 1;
946
- zDfltTitle = zName;
947
- }
937
+ rid = unversioned_content(zName, &filebody);
938
+ if( rid==1 ){
939
+ Stmt q;
940
+ db_prepare(&q, "SELECT hash, mtime FROM unversioned"
941
+ " WHERE name=%Q", zName);
942
+ if( db_step(&q)==SQLITE_ROW ){
943
+ etag_check(ETAG_HASH, db_column_text(&q,0));
944
+ etag_last_modified(db_column_int64(&q,1));
945
+ }
946
+ db_finalize(&q);
947
+ }else if( rid==2 ){
948
+ zName = db_text(zName,
949
+ "SELECT name FROM unversioned WHERE hash=%Q", zName);
950
+ g.isConst = 1;
951
+ }
952
+ zDfltTitle = zName;
948953
}
949954
}else if( fossil_strcmp(zCheckin,"ckout")==0 ){
950955
/* Read from the local checkout */
951956
char *zFullpath;
952957
db_must_be_within_tree();
953958
--- src/doc.c
+++ src/doc.c
@@ -810,11 +810,11 @@
810 ** WEBPAGE: doc
811 ** URL: /uv/FILE
812 ** URL: /doc/CHECKIN/FILE
813 **
814 ** CHECKIN can be either tag or hash prefix or timestamp identifying a
815 ** particular check, or the name of a branch (meaning the most recent
816 ** check-in on that branch) or one of various magic words:
817 **
818 ** "tip" means the most recent check-in
819 **
820 ** "ckout" means the current check-out, if the server is run from
@@ -824,11 +824,12 @@
824 ** regardless of what branch it occurs on.
825 **
826 ** FILE is the name of a file to delivered up as a webpage. FILE is relative
827 ** to the root of the source tree of the repository. The FILE must
828 ** be a part of CHECKIN, except when CHECKIN=="ckout" when FILE is read
829 ** directly from disk and need not be a managed file.
 
830 **
831 ** The "ckout" CHECKIN is intended for development - to provide a mechanism
832 ** for looking at what a file will look like using the /doc webpage after
833 ** it gets checked in.
834 **
@@ -931,22 +932,26 @@
931 goto doc_not_found;
932 }
933 }
934 if( isUV ){
935 if( db_table_exists("repository","unversioned") ){
936 Stmt q;
937 db_prepare(&q, "SELECT hash, mtime FROM unversioned"
938 " WHERE name=%Q", zName);
939 if( db_step(&q)==SQLITE_ROW ){
940 etag_check(ETAG_HASH, db_column_text(&q,0));
941 etag_last_modified(db_column_int64(&q,1));
942 }
943 db_finalize(&q);
944 if( unversioned_content(zName, &filebody)==0 ){
945 rid = 1;
946 zDfltTitle = zName;
947 }
 
 
 
 
948 }
949 }else if( fossil_strcmp(zCheckin,"ckout")==0 ){
950 /* Read from the local checkout */
951 char *zFullpath;
952 db_must_be_within_tree();
953
--- src/doc.c
+++ src/doc.c
@@ -810,11 +810,11 @@
810 ** WEBPAGE: doc
811 ** URL: /uv/FILE
812 ** URL: /doc/CHECKIN/FILE
813 **
814 ** CHECKIN can be either tag or hash prefix or timestamp identifying a
815 ** particular check-in, or the name of a branch (meaning the most recent
816 ** check-in on that branch) or one of various magic words:
817 **
818 ** "tip" means the most recent check-in
819 **
820 ** "ckout" means the current check-out, if the server is run from
@@ -824,11 +824,12 @@
824 ** regardless of what branch it occurs on.
825 **
826 ** FILE is the name of a file to delivered up as a webpage. FILE is relative
827 ** to the root of the source tree of the repository. The FILE must
828 ** be a part of CHECKIN, except when CHECKIN=="ckout" when FILE is read
829 ** directly from disk and need not be a managed file. For /uv, FILE
830 ** can also be the hash of the unversioned file.
831 **
832 ** The "ckout" CHECKIN is intended for development - to provide a mechanism
833 ** for looking at what a file will look like using the /doc webpage after
834 ** it gets checked in.
835 **
@@ -931,22 +932,26 @@
932 goto doc_not_found;
933 }
934 }
935 if( isUV ){
936 if( db_table_exists("repository","unversioned") ){
937 rid = unversioned_content(zName, &filebody);
938 if( rid==1 ){
939 Stmt q;
940 db_prepare(&q, "SELECT hash, mtime FROM unversioned"
941 " WHERE name=%Q", zName);
942 if( db_step(&q)==SQLITE_ROW ){
943 etag_check(ETAG_HASH, db_column_text(&q,0));
944 etag_last_modified(db_column_int64(&q,1));
945 }
946 db_finalize(&q);
947 }else if( rid==2 ){
948 zName = db_text(zName,
949 "SELECT name FROM unversioned WHERE hash=%Q", zName);
950 g.isConst = 1;
951 }
952 zDfltTitle = zName;
953 }
954 }else if( fossil_strcmp(zCheckin,"ckout")==0 ){
955 /* Read from the local checkout */
956 char *zFullpath;
957 db_must_be_within_tree();
958
+4 -3
--- src/finfo.c
+++ src/finfo.c
@@ -438,12 +438,13 @@
438438
}else if( n>0 ){
439439
blob_appendf(&title, "First %d ancestors of file ", n);
440440
}else{
441441
blob_appendf(&title, "Ancestors of file ");
442442
}
443
- blob_appendf(&title,"<a href='%R/finfo?name=%T'>%h</a>",
444
- zFilename, zFilename);
443
+ blob_appendf(&title,"%z%h</a>",
444
+ href("%R/file?name=%T&ci=%!S", zFilename, zUuid),
445
+ zFilename);
445446
if( fShowId ) blob_appendf(&title, " (%d)", fnid);
446447
blob_append(&title, origCheckin ? " between " : " from ", -1);
447448
blob_appendf(&title, "check-in %z%S</a>", zLink, zUuid);
448449
if( fShowId ) blob_appendf(&title, " (%d)", baseCheckin);
449450
fossil_free(zUuid);
@@ -453,11 +454,11 @@
453454
blob_appendf(&title, " and check-in %z%S</a>", zLink, zUuid);
454455
fossil_free(zUuid);
455456
}
456457
}else{
457458
blob_appendf(&title, "History for ");
458
- hyperlinked_path(zFilename, &title, 0, "tree", "");
459
+ hyperlinked_path(zFilename, &title, 0, "tree", "", LINKPATH_FILE);
459460
if( fShowId ) blob_appendf(&title, " (%d)", fnid);
460461
}
461462
if( uBg ){
462463
blob_append(&title, " (color-coded by user)", -1);
463464
}
464465
--- src/finfo.c
+++ src/finfo.c
@@ -438,12 +438,13 @@
438 }else if( n>0 ){
439 blob_appendf(&title, "First %d ancestors of file ", n);
440 }else{
441 blob_appendf(&title, "Ancestors of file ");
442 }
443 blob_appendf(&title,"<a href='%R/finfo?name=%T'>%h</a>",
444 zFilename, zFilename);
 
445 if( fShowId ) blob_appendf(&title, " (%d)", fnid);
446 blob_append(&title, origCheckin ? " between " : " from ", -1);
447 blob_appendf(&title, "check-in %z%S</a>", zLink, zUuid);
448 if( fShowId ) blob_appendf(&title, " (%d)", baseCheckin);
449 fossil_free(zUuid);
@@ -453,11 +454,11 @@
453 blob_appendf(&title, " and check-in %z%S</a>", zLink, zUuid);
454 fossil_free(zUuid);
455 }
456 }else{
457 blob_appendf(&title, "History for ");
458 hyperlinked_path(zFilename, &title, 0, "tree", "");
459 if( fShowId ) blob_appendf(&title, " (%d)", fnid);
460 }
461 if( uBg ){
462 blob_append(&title, " (color-coded by user)", -1);
463 }
464
--- src/finfo.c
+++ src/finfo.c
@@ -438,12 +438,13 @@
438 }else if( n>0 ){
439 blob_appendf(&title, "First %d ancestors of file ", n);
440 }else{
441 blob_appendf(&title, "Ancestors of file ");
442 }
443 blob_appendf(&title,"%z%h</a>",
444 href("%R/file?name=%T&ci=%!S", zFilename, zUuid),
445 zFilename);
446 if( fShowId ) blob_appendf(&title, " (%d)", fnid);
447 blob_append(&title, origCheckin ? " between " : " from ", -1);
448 blob_appendf(&title, "check-in %z%S</a>", zLink, zUuid);
449 if( fShowId ) blob_appendf(&title, " (%d)", baseCheckin);
450 fossil_free(zUuid);
@@ -453,11 +454,11 @@
454 blob_appendf(&title, " and check-in %z%S</a>", zLink, zUuid);
455 fossil_free(zUuid);
456 }
457 }else{
458 blob_appendf(&title, "History for ");
459 hyperlinked_path(zFilename, &title, 0, "tree", "", LINKPATH_FILE);
460 if( fShowId ) blob_appendf(&title, " (%d)", fnid);
461 }
462 if( uBg ){
463 blob_append(&title, " (color-coded by user)", -1);
464 }
465
+5 -4
--- src/forum.c
+++ src/forum.c
@@ -1013,12 +1013,12 @@
10131013
@ Title: <input type="input" name="title" value="%h(zTitle)" size="50"
10141014
@ maxlength="125"><br>
10151015
}
10161016
@ %z(href("%R/markup_help"))Markup style</a>:
10171017
mimetype_option_menu(zMimetype);
1018
- @ <br><textarea name="content" class="wikiedit" cols="80" \
1019
- @ rows="25" wrap="virtual">%h(zContent)</textarea><br>
1018
+ @ <br><textarea aria-label="Content:" name="content" class="wikiedit" \
1019
+ @ cols="80" rows="25" wrap="virtual">%h(zContent)</textarea><br>
10201020
}
10211021
10221022
/*
10231023
** WEBPAGE: forumnew
10241024
** WEBPAGE: forumedit
@@ -1119,11 +1119,12 @@
11191119
@ <input type="submit" name="submit" value="Submit">
11201120
}else{
11211121
@ <input type="submit" name="submit" value="Submit" disabled>
11221122
}
11231123
if( g.perm.Debug ){
1124
- /* For the test-forumnew page add these extra debugging controls */
1124
+ /* Give extra control over the post to users with the special
1125
+ * Debug capability, which includes Admin and Setup users */
11251126
@ <div class="debug">
11261127
@ <label><input type="checkbox" name="dryrun" %s(PCK("dryrun"))> \
11271128
@ Dry run</label>
11281129
@ <br><label><input type="checkbox" name="domod" %s(PCK("domod"))> \
11291130
@ Require moderator approval</label>
@@ -1235,11 +1236,11 @@
12351236
@ <input type="hidden" name="fpid" value="%h(P("fpid"))">
12361237
@ <input type="hidden" name="nullout" value="1">
12371238
@ <input type="hidden" name="mimetype" value="%h(zMimetype)">
12381239
@ <input type="hidden" name="content" value="%h(zContent)">
12391240
if( zTitle ){
1240
- @ <input type="hidden" name="title" value="%h(zTitle)">
1241
+ @ <input aria-label="Title" type="hidden" name="title" value="%h(zTitle)">
12411242
}
12421243
}else if( P("edit") ){
12431244
/* Provide an edit to the fpid post */
12441245
zMimetype = P("mimetype");
12451246
zContent = PT("content");
12461247
--- src/forum.c
+++ src/forum.c
@@ -1013,12 +1013,12 @@
1013 @ Title: <input type="input" name="title" value="%h(zTitle)" size="50"
1014 @ maxlength="125"><br>
1015 }
1016 @ %z(href("%R/markup_help"))Markup style</a>:
1017 mimetype_option_menu(zMimetype);
1018 @ <br><textarea name="content" class="wikiedit" cols="80" \
1019 @ rows="25" wrap="virtual">%h(zContent)</textarea><br>
1020 }
1021
1022 /*
1023 ** WEBPAGE: forumnew
1024 ** WEBPAGE: forumedit
@@ -1119,11 +1119,12 @@
1119 @ <input type="submit" name="submit" value="Submit">
1120 }else{
1121 @ <input type="submit" name="submit" value="Submit" disabled>
1122 }
1123 if( g.perm.Debug ){
1124 /* For the test-forumnew page add these extra debugging controls */
 
1125 @ <div class="debug">
1126 @ <label><input type="checkbox" name="dryrun" %s(PCK("dryrun"))> \
1127 @ Dry run</label>
1128 @ <br><label><input type="checkbox" name="domod" %s(PCK("domod"))> \
1129 @ Require moderator approval</label>
@@ -1235,11 +1236,11 @@
1235 @ <input type="hidden" name="fpid" value="%h(P("fpid"))">
1236 @ <input type="hidden" name="nullout" value="1">
1237 @ <input type="hidden" name="mimetype" value="%h(zMimetype)">
1238 @ <input type="hidden" name="content" value="%h(zContent)">
1239 if( zTitle ){
1240 @ <input type="hidden" name="title" value="%h(zTitle)">
1241 }
1242 }else if( P("edit") ){
1243 /* Provide an edit to the fpid post */
1244 zMimetype = P("mimetype");
1245 zContent = PT("content");
1246
--- src/forum.c
+++ src/forum.c
@@ -1013,12 +1013,12 @@
1013 @ Title: <input type="input" name="title" value="%h(zTitle)" size="50"
1014 @ maxlength="125"><br>
1015 }
1016 @ %z(href("%R/markup_help"))Markup style</a>:
1017 mimetype_option_menu(zMimetype);
1018 @ <br><textarea aria-label="Content:" name="content" class="wikiedit" \
1019 @ cols="80" rows="25" wrap="virtual">%h(zContent)</textarea><br>
1020 }
1021
1022 /*
1023 ** WEBPAGE: forumnew
1024 ** WEBPAGE: forumedit
@@ -1119,11 +1119,12 @@
1119 @ <input type="submit" name="submit" value="Submit">
1120 }else{
1121 @ <input type="submit" name="submit" value="Submit" disabled>
1122 }
1123 if( g.perm.Debug ){
1124 /* Give extra control over the post to users with the special
1125 * Debug capability, which includes Admin and Setup users */
1126 @ <div class="debug">
1127 @ <label><input type="checkbox" name="dryrun" %s(PCK("dryrun"))> \
1128 @ Dry run</label>
1129 @ <br><label><input type="checkbox" name="domod" %s(PCK("domod"))> \
1130 @ Require moderator approval</label>
@@ -1235,11 +1236,11 @@
1236 @ <input type="hidden" name="fpid" value="%h(P("fpid"))">
1237 @ <input type="hidden" name="nullout" value="1">
1238 @ <input type="hidden" name="mimetype" value="%h(zMimetype)">
1239 @ <input type="hidden" name="content" value="%h(zContent)">
1240 if( zTitle ){
1241 @ <input aria-label="Title" type="hidden" name="title" value="%h(zTitle)">
1242 }
1243 }else if( P("edit") ){
1244 /* Provide an edit to the fpid post */
1245 zMimetype = P("mimetype");
1246 zContent = PT("content");
1247
+14 -6
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -24,19 +24,19 @@
2424
** SSL support is abstracted out into this module because Fossil can
2525
** be compiled without SSL support (which requires OpenSSL library)
2626
*/
2727
2828
#include "config.h"
29
+#include "http_ssl.h"
2930
3031
#ifdef FOSSIL_ENABLE_SSL
3132
3233
#include <openssl/bio.h>
3334
#include <openssl/ssl.h>
3435
#include <openssl/err.h>
3536
#include <openssl/x509.h>
3637
37
-#include "http_ssl.h"
3838
#include <assert.h>
3939
#include <sys/types.h>
4040
4141
/*
4242
** There can only be a single OpenSSL IO connection open at a time.
@@ -328,10 +328,11 @@
328328
ssl_close();
329329
return 1;
330330
}
331331
332332
if( !sslNoCertVerify && SSL_get_verify_result(ssl)!=X509_V_OK ){
333
+ int x;
333334
char *desc, *prompt;
334335
Blob ans;
335336
char cReply;
336337
BIO *mem;
337338
unsigned char md[32];
@@ -338,11 +339,17 @@
338339
char zHash[32*2+1];
339340
unsigned int mdLength = (int)sizeof(md);
340341
341342
memset(md, 0, sizeof(md));
342343
zHash[0] = 0;
343
- if( X509_digest(cert, EVP_sha256(), md, &mdLength) ){
344
+ /* MMNNFFPPS */
345
+#if OPENSSL_VERSION_NUMBER >= 0x010000000
346
+ x = X509_digest(cert, EVP_sha256(), md, &mdLength);
347
+#else
348
+ x = X509_digest(cert, EVP_sha1(), md, &mdLength);
349
+#endif
350
+ if( x ){
344351
int j;
345352
for(j=0; j<mdLength && j*2+1<sizeof(zHash); ++j){
346353
zHash[j*2] = "0123456789abcdef"[md[j]>>4];
347354
zHash[j*2+1] = "0123456789abcdef"[md[j]&0xf];
348355
}
@@ -518,25 +525,26 @@
518525
** for the domains listed. Or if
519526
** the --all option is specified,
520527
** remove all TLS cert exceptions.
521528
*/
522529
void test_tlsconfig_info(void){
523
- const char *zCmd;
524
- size_t nCmd;
525
- int nHit = 0;
526530
#if !defined(FOSSIL_ENABLE_SSL)
527531
fossil_print("TLS disabled in this build\n");
528532
#else
533
+ const char *zCmd;
534
+ size_t nCmd;
535
+ int nHit = 0;
529536
db_find_and_open_repository(OPEN_OK_NOT_FOUND|OPEN_SUBSTITUTE,0);
530537
db_open_config(1,0);
531538
zCmd = g.argc>=3 ? g.argv[2] : "show";
532539
nCmd = strlen(zCmd);
533540
if( strncmp("show",zCmd,nCmd)==0 ){
534541
const char *zName, *zValue;
535542
size_t nName;
536543
Stmt q;
537
- fossil_print("OpenSSL-version: %s\n", SSLeay_version(SSLEAY_VERSION));
544
+ fossil_print("OpenSSL-version: %s (0x%09x)\n",
545
+ SSLeay_version(SSLEAY_VERSION), OPENSSL_VERSION_NUMBER);
538546
fossil_print("OpenSSL-cert-file: %s\n", X509_get_default_cert_file());
539547
fossil_print("OpenSSL-cert-dir: %s\n", X509_get_default_cert_dir());
540548
zName = X509_get_default_cert_file_env();
541549
zValue = fossil_getenv(zName);
542550
if( zValue==0 ) zValue = "";
543551
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -24,19 +24,19 @@
24 ** SSL support is abstracted out into this module because Fossil can
25 ** be compiled without SSL support (which requires OpenSSL library)
26 */
27
28 #include "config.h"
 
29
30 #ifdef FOSSIL_ENABLE_SSL
31
32 #include <openssl/bio.h>
33 #include <openssl/ssl.h>
34 #include <openssl/err.h>
35 #include <openssl/x509.h>
36
37 #include "http_ssl.h"
38 #include <assert.h>
39 #include <sys/types.h>
40
41 /*
42 ** There can only be a single OpenSSL IO connection open at a time.
@@ -328,10 +328,11 @@
328 ssl_close();
329 return 1;
330 }
331
332 if( !sslNoCertVerify && SSL_get_verify_result(ssl)!=X509_V_OK ){
 
333 char *desc, *prompt;
334 Blob ans;
335 char cReply;
336 BIO *mem;
337 unsigned char md[32];
@@ -338,11 +339,17 @@
338 char zHash[32*2+1];
339 unsigned int mdLength = (int)sizeof(md);
340
341 memset(md, 0, sizeof(md));
342 zHash[0] = 0;
343 if( X509_digest(cert, EVP_sha256(), md, &mdLength) ){
 
 
 
 
 
 
344 int j;
345 for(j=0; j<mdLength && j*2+1<sizeof(zHash); ++j){
346 zHash[j*2] = "0123456789abcdef"[md[j]>>4];
347 zHash[j*2+1] = "0123456789abcdef"[md[j]&0xf];
348 }
@@ -518,25 +525,26 @@
518 ** for the domains listed. Or if
519 ** the --all option is specified,
520 ** remove all TLS cert exceptions.
521 */
522 void test_tlsconfig_info(void){
523 const char *zCmd;
524 size_t nCmd;
525 int nHit = 0;
526 #if !defined(FOSSIL_ENABLE_SSL)
527 fossil_print("TLS disabled in this build\n");
528 #else
 
 
 
529 db_find_and_open_repository(OPEN_OK_NOT_FOUND|OPEN_SUBSTITUTE,0);
530 db_open_config(1,0);
531 zCmd = g.argc>=3 ? g.argv[2] : "show";
532 nCmd = strlen(zCmd);
533 if( strncmp("show",zCmd,nCmd)==0 ){
534 const char *zName, *zValue;
535 size_t nName;
536 Stmt q;
537 fossil_print("OpenSSL-version: %s\n", SSLeay_version(SSLEAY_VERSION));
 
538 fossil_print("OpenSSL-cert-file: %s\n", X509_get_default_cert_file());
539 fossil_print("OpenSSL-cert-dir: %s\n", X509_get_default_cert_dir());
540 zName = X509_get_default_cert_file_env();
541 zValue = fossil_getenv(zName);
542 if( zValue==0 ) zValue = "";
543
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -24,19 +24,19 @@
24 ** SSL support is abstracted out into this module because Fossil can
25 ** be compiled without SSL support (which requires OpenSSL library)
26 */
27
28 #include "config.h"
29 #include "http_ssl.h"
30
31 #ifdef FOSSIL_ENABLE_SSL
32
33 #include <openssl/bio.h>
34 #include <openssl/ssl.h>
35 #include <openssl/err.h>
36 #include <openssl/x509.h>
37
 
38 #include <assert.h>
39 #include <sys/types.h>
40
41 /*
42 ** There can only be a single OpenSSL IO connection open at a time.
@@ -328,10 +328,11 @@
328 ssl_close();
329 return 1;
330 }
331
332 if( !sslNoCertVerify && SSL_get_verify_result(ssl)!=X509_V_OK ){
333 int x;
334 char *desc, *prompt;
335 Blob ans;
336 char cReply;
337 BIO *mem;
338 unsigned char md[32];
@@ -338,11 +339,17 @@
339 char zHash[32*2+1];
340 unsigned int mdLength = (int)sizeof(md);
341
342 memset(md, 0, sizeof(md));
343 zHash[0] = 0;
344 /* MMNNFFPPS */
345 #if OPENSSL_VERSION_NUMBER >= 0x010000000
346 x = X509_digest(cert, EVP_sha256(), md, &mdLength);
347 #else
348 x = X509_digest(cert, EVP_sha1(), md, &mdLength);
349 #endif
350 if( x ){
351 int j;
352 for(j=0; j<mdLength && j*2+1<sizeof(zHash); ++j){
353 zHash[j*2] = "0123456789abcdef"[md[j]>>4];
354 zHash[j*2+1] = "0123456789abcdef"[md[j]&0xf];
355 }
@@ -518,25 +525,26 @@
525 ** for the domains listed. Or if
526 ** the --all option is specified,
527 ** remove all TLS cert exceptions.
528 */
529 void test_tlsconfig_info(void){
 
 
 
530 #if !defined(FOSSIL_ENABLE_SSL)
531 fossil_print("TLS disabled in this build\n");
532 #else
533 const char *zCmd;
534 size_t nCmd;
535 int nHit = 0;
536 db_find_and_open_repository(OPEN_OK_NOT_FOUND|OPEN_SUBSTITUTE,0);
537 db_open_config(1,0);
538 zCmd = g.argc>=3 ? g.argv[2] : "show";
539 nCmd = strlen(zCmd);
540 if( strncmp("show",zCmd,nCmd)==0 ){
541 const char *zName, *zValue;
542 size_t nName;
543 Stmt q;
544 fossil_print("OpenSSL-version: %s (0x%09x)\n",
545 SSLeay_version(SSLEAY_VERSION), OPENSSL_VERSION_NUMBER);
546 fossil_print("OpenSSL-cert-file: %s\n", X509_get_default_cert_file());
547 fossil_print("OpenSSL-cert-dir: %s\n", X509_get_default_cert_dir());
548 zName = X509_get_default_cert_file_env();
549 zValue = fossil_getenv(zName);
550 if( zValue==0 ) zValue = "";
551
+147 -147
--- src/info.c
+++ src/info.c
@@ -666,10 +666,11 @@
666666
const char *zOrigDate;
667667
int okWiki = 0;
668668
Blob wiki_read_links = BLOB_INITIALIZER;
669669
Blob wiki_add_links = BLOB_INITIALIZER;
670670
671
+ Th_Store("current_checkin", zName);
671672
style_header("Check-in [%S]", zUuid);
672673
login_anonymous_available();
673674
zEUser = db_text(0,
674675
"SELECT value FROM tagxref"
675676
" WHERE tagid=%d AND rid=%d AND tagtype>0",
@@ -1661,12 +1662,12 @@
16611662
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
16621663
cookie_link_parameter("diff","diff","2");
16631664
diffType = atoi(PD("diff","2"));
16641665
cookie_render();
16651666
if( P("from") && P("to") ){
1666
- v1 = artifact_from_ci_and_filename(0, "from");
1667
- v2 = artifact_from_ci_and_filename(0, "to");
1667
+ v1 = artifact_from_ci_and_filename("from");
1668
+ v2 = artifact_from_ci_and_filename("to");
16681669
}else{
16691670
Stmt q;
16701671
v1 = name_to_rid_www("v1");
16711672
v2 = name_to_rid_www("v2");
16721673
@@ -1763,12 +1764,12 @@
17631764
*/
17641765
void rawartifact_page(void){
17651766
int rid = 0;
17661767
char *zUuid;
17671768
1768
- if( P("ci") && P("filename") ){
1769
- rid = artifact_from_ci_and_filename(0, 0);
1769
+ if( P("ci") ){
1770
+ rid = artifact_from_ci_and_filename(0);
17701771
}
17711772
if( rid==0 ){
17721773
rid = name_to_rid_www("name");
17731774
}
17741775
login_check_credentials();
@@ -1942,59 +1943,53 @@
19421943
19431944
/*
19441945
** Look for "ci" and "filename" query parameters. If found, try to
19451946
** use them to extract the record ID of an artifact for the file.
19461947
**
1947
-** Also look for "fn" as an alias for "filename". If either "filename"
1948
-** or "fn" is present but "ci" is missing, use "tip" as a default value
1949
-** for "ci".
1950
-**
1951
-** If zNameParam is not NULL, this use that parameter as the filename
1952
-** rather than "fn" or "filename".
1953
-**
1954
-** If pUrl is not NULL, then record the "ci" and "filename" values in
1955
-** pUrl.
1956
-**
1957
-** At least one of pUrl or zNameParam must be NULL.
1948
+** Also look for "fn" and "name" as an aliases for "filename". If any
1949
+** "filename" or "fn" or "name" are present but "ci" is missing, then
1950
+** use "tip" as the default value for "ci".
1951
+**
1952
+** If zNameParam is not NULL, then use that parameter as the filename
1953
+** rather than "fn" or "filename" or "name". the zNameParam is used
1954
+** for the from= and to= query parameters of /fdiff.
19581955
*/
1959
-int artifact_from_ci_and_filename(HQuery *pUrl, const char *zNameParam){
1956
+int artifact_from_ci_and_filename(const char *zNameParam){
19601957
const char *zFilename;
19611958
const char *zCI;
19621959
int cirid;
19631960
Manifest *pManifest;
19641961
ManifestFile *pFile;
1962
+ int rid = 0;
19651963
19661964
if( zNameParam ){
19671965
zFilename = P(zNameParam);
19681966
}else{
19691967
zFilename = P("filename");
19701968
if( zFilename==0 ){
19711969
zFilename = P("fn");
19721970
}
1971
+ if( zFilename==0 ){
1972
+ zFilename = P("name");
1973
+ }
19731974
}
19741975
if( zFilename==0 ) return 0;
19751976
1976
- zCI = P("ci");
1977
- cirid = name_to_typed_rid(zCI ? zCI : "tip", "ci");
1977
+ zCI = PD("ci", "tip");
1978
+ cirid = name_to_typed_rid(zCI, "ci");
19781979
if( cirid<=0 ) return 0;
19791980
pManifest = manifest_get(cirid, CFTYPE_MANIFEST, 0);
19801981
if( pManifest==0 ) return 0;
19811982
manifest_file_rewind(pManifest);
19821983
while( (pFile = manifest_file_next(pManifest,0))!=0 ){
19831984
if( fossil_strcmp(zFilename, pFile->zName)==0 ){
1984
- int rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", pFile->zUuid);
1985
- manifest_destroy(pManifest);
1986
- if( pUrl ){
1987
- assert( zNameParam==0 );
1988
- url_add_parameter(pUrl, "fn", zFilename);
1989
- if( zCI ) url_add_parameter(pUrl, "ci", zCI);
1990
- }
1991
- return rid;
1985
+ rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", pFile->zUuid);
1986
+ break;
19921987
}
19931988
}
19941989
manifest_destroy(pManifest);
1995
- return 0;
1990
+ return rid;
19961991
}
19971992
19981993
/*
19991994
** The "z" argument is a string that contains the text of a source code
20001995
** file. This routine appends that text to the HTTP reply with line numbering.
@@ -2096,21 +2091,31 @@
20962091
** ln=N - highlight line number N
20972092
** ln=M-N - highlight lines M through N inclusive
20982093
** ln=M-N+Y-Z - highlight lines M through N and Y through Z (inclusive)
20992094
** verbose - show more detail in the description
21002095
** download - redirect to the download (artifact page only)
2101
-** name=NAME - Provide filename or hash as a query parameter
2096
+** name=NAME - filename or hash as a query parameter
21022097
** filename=NAME - alternative spelling for "name="
21032098
** fn=NAME - alternative spelling for "name="
2104
-** ci=VERSION - The specific check-in to use for "filename=".
2099
+** ci=VERSION - The specific check-in to use with "name=" to
2100
+** identify the file.
21052101
**
21062102
** The /artifact page show the complete content of a file
2107
-** identified by HASH as preformatted text. The
2108
-** /whatis page shows only a description of the file. The /file
2109
-** page shows the most recent version of the file or directory
2110
-** called NAME, or a list of the top-level directory if NAME is
2111
-** omitted.
2103
+** identified by HASH. The /whatis page shows only a description
2104
+** of how the artifact is used. The /file page shows the most recent
2105
+** version of the file or directory called NAME, or a list of the
2106
+** top-level directory if NAME is omitted.
2107
+**
2108
+** For /artifact and /whatis, the name= query parameter can refer to
2109
+** either the name of a file, or an artifact hash. If the ci= query
2110
+** parameter is also present, then name= must refer to a file name.
2111
+** If ci= is omitted, then the hash interpretation is preferred but
2112
+** if name= cannot be understood as a hash, a default "tip" value is
2113
+** used for ci=.
2114
+**
2115
+** For /file, name= can only be interpreted as a filename. As before,
2116
+** a default value of "tip" is used for ci= if ci= is omitted.
21122117
*/
21132118
void artifact_page(void){
21142119
int rid = 0;
21152120
Blob content;
21162121
const char *zMime;
@@ -2125,143 +2130,138 @@
21252130
int isFile = fossil_strcmp(g.zPath,"file")==0;
21262131
const char *zLn = P("ln");
21272132
const char *zName = P("name");
21282133
const char *zCI = P("ci");
21292134
HQuery url;
2130
- Blob dirname;
2131
- char *zCIUuid = 0;
2132
- int isSymbolicCI = 0; /* ci= exists and is a symbolic name, not a hash */
2133
- char *zHeader = 0;
2134
-
2135
- login_check_credentials();
2136
- if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
2137
- url_initialize(&url, g.zPath);
2138
- if( zName==0 ){
2139
- zName = P("filename");
2140
- if( zName==0 ) zName = P("fn");
2141
- }
2142
- if( zCI && strlen(zCI)==0 ){ zCI = 0; }
2143
- if( zCI && zName ){
2144
- blob_zero(&dirname);
2145
- hyperlinked_path(zName, &dirname, zCI, "dir", "");
2146
- blob_reset(&dirname);
2147
-
2148
- if( name_to_uuid2(zCI, "ci", &zCIUuid) ){
2149
- isSymbolicCI = (sqlite3_strnicmp(zCIUuid, zCI, strlen(zCI)) != 0);
2150
- }
2151
- }
2152
- if( isFile && zName ) {
2153
- rid = artifact_from_ci_and_filename(0, "name");
2154
- }else{
2155
- rid = artifact_from_ci_and_filename(&url, 0);
2156
- }
2157
- if( rid==0 ){
2158
- url_add_parameter(&url, "name", zName);
2159
- if( isFile ){
2160
- int isUnknownAtCI = 0;
2161
-
2162
- /* Do a top-level directory listing in /file mode if no argument
2163
- ** specified */
2164
- if( zName==0 || zName[0]==0 ){
2165
- if( P("ci")==0 ) cgi_set_query_parameter("ci","tip");
2166
- page_tree();
2167
- return;
2168
- }
2169
- /* Look for a single file with the given name */
2170
- rid = db_int(0,
2171
- "SELECT fid FROM filename, mlink, event"
2172
- " WHERE name=%Q"
2173
- " AND mlink.fnid=filename.fnid"
2174
- " AND event.objid=mlink.mid"
2175
- " ORDER BY event.mtime DESC LIMIT 1",
2176
- zName
2177
- );
2178
- /* If found only by the name, then the file is unknown in the check-in.
2179
- ** Possibly, the file was renamed/deleted.
2180
- */
2181
- if( rid && zCIUuid ){
2182
- rid = 0;
2183
- isUnknownAtCI = 1;
2184
- }
2185
- /* If no file called NAME exists, instead look for a directory
2186
- ** with that name, and do a directory listing */
2187
- if( rid==0 ){
2188
- int nName = (int)strlen(zName);
2189
- if( nName && zName[nName-1]=='/' ) nName--;
2190
- if( db_exists(
2191
- "SELECT 1 FROM filename"
2192
- " WHERE name GLOB '%.*q/*' AND substr(name,1,%d)=='%.*q/';",
2193
- nName, zName, nName+1, nName, zName
2194
- ) ){
2195
- if( P("ci")==0 ) cgi_set_query_parameter("ci","tip");
2196
- page_tree();
2197
- return;
2198
- }
2199
- }
2200
- /* If no file or directory called NAME: issue an error */
2201
- if( rid==0 ){
2202
- if( isUnknownAtCI ){
2203
- if( isSymbolicCI ){
2204
- zHeader = mprintf("No such file at %s", zCI);
2205
- }else{
2206
- zHeader = mprintf("No such file at [%S]", zCIUuid);
2207
- }
2208
- style_header("%s", zHeader);
2209
- fossil_free(zHeader);
2210
- @ File %z(href("%R/finfo?name=%T",zName))%h(zName)</a> is not known
2211
- @ at check-in [%z(href("/info/%!S",zCIUuid))%S(zCIUuid)</a>].
2212
- }else{
2213
- style_header("No such file");
2214
- @ File '%h(zName)' is not known in this repository.
2215
- }
2216
- style_footer();
2217
- return;
2218
- }
2219
- }else{
2220
- rid = name_to_rid_www("name");
2221
- }
2222
- }
2223
-
2224
- if( rid==0 ){
2225
- style_header("No such artifact");
2226
- @ Artifact '%h(zName)' does not exist in this repository.
2227
- style_footer();
2228
- return;
2229
- }
2135
+ char *zCIUuid = 0;
2136
+ int isSymbolicCI = 0; /* ci= exists and is a symbolic name, not a hash */
2137
+ int isBranchCI = 0; /* ci= refers to a branch name */
2138
+ char *zHeader = 0;
2139
+
2140
+ login_check_credentials();
2141
+ if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
2142
+
2143
+ /* Capture and normalize the name= and ci= query parameters */
2144
+ if( zName==0 ){
2145
+ zName = P("filename");
2146
+ if( zName==0 ){
2147
+ zName = P("fn");
2148
+ }
2149
+ }
2150
+ if( zCI && strlen(zCI)==0 ){ zCI = 0; }
2151
+ if( zCI
2152
+ && name_to_uuid2(zCI, "ci", &zCIUuid)
2153
+ && sqlite3_strnicmp(zCIUuid, zCI, strlen(zCI))!=0
2154
+ ){
2155
+ isSymbolicCI = 1;
2156
+ isBranchCI = branch_includes_uuid(zCI, zCIUuid);
2157
+ }
2158
+
2159
+ /* The name= query parameter (or at least one of its alternative
2160
+ ** spellings) is required. Except for /file, show a top-level
2161
+ ** directory listing if name= is omitted.
2162
+ */
2163
+ if( zName==0 ){
2164
+ if( isFile ){
2165
+ if( P("ci")==0 ) cgi_set_query_parameter("ci","tip");
2166
+ page_tree();
2167
+ return;
2168
+ }
2169
+ style_header("Missing name= query parameter");
2170
+ @ The name= query parameter is missing
2171
+ style_footer();
2172
+ return;
2173
+ }
2174
+
2175
+ url_initialize(&url, g.zPath);
2176
+ url_add_parameter(&url, "name", zName);
2177
+ url_add_parameter(&url, "ci", zCI);
2178
+
2179
+ if( zCI==0 && !isFile ){
2180
+ /* If there is no ci= query parameter, then prefer to interpret
2181
+ ** name= as a hash for /artifact and /whatis. But for not for /file.
2182
+ ** For /file, a name= without a ci= while prefer to use the default
2183
+ ** "tip" value for ci=. */
2184
+ rid = name_to_rid(zName);
2185
+ }
2186
+ if( rid==0 ){
2187
+ rid = artifact_from_ci_and_filename(0);
2188
+ }
2189
+
2190
+ if( rid==0 ){ /* Artifact not found */
2191
+ if( isFile ){
2192
+ /* For /file, also check to see if name= refers to a directory,
2193
+ ** and if so, do a listing for that directory */
2194
+ int nName = (int)strlen(zName);
2195
+ if( nName && zName[nName-1]=='/' ) nName--;
2196
+ if( db_exists(
2197
+ "SELECT 1 FROM filename"
2198
+ " WHERE name GLOB '%.*q/*' AND substr(name,1,%d)=='%.*q/';",
2199
+ nName, zName, nName+1, nName, zName
2200
+ ) ){
2201
+ if( P("ci")==0 ) cgi_set_query_parameter("ci","tip");
2202
+ page_tree();
2203
+ return;
2204
+ }
2205
+ style_header("No such file");
2206
+ @ File '%h(zName)' does not exist in this repository.
2207
+ }else{
2208
+ style_header("No such artifact");
2209
+ @ Artifact '%h(zName)' does not exist in this repository.
2210
+ }
2211
+ style_footer();
2212
+ return;
2213
+ }
2214
+
22302215
if( descOnly || P("verbose")!=0 ){
22312216
url_add_parameter(&url, "verbose", "1");
22322217
objdescFlags |= OBJDESC_DETAIL;
22332218
}
22342219
zUuid = db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid);
22352220
2221
+ asText = P("txt")!=0;
22362222
if( isFile ){
2237
- if( zCI ){
2223
+ if( zCI==0 || fossil_strcmp(zCI,"tip")==0 ){
2224
+ zCI = "tip";
2225
+ @ <h2>File %z(href("%R/finfo?name=%T&m=tip",zName))%h(zName)</a>
2226
+ @ from the %z(href("%R/info/tip"))latest check-in</a></h2>
2227
+ }else{
22382228
const char *zPath;
22392229
Blob path;
22402230
blob_zero(&path);
2241
- hyperlinked_path(zName, &path, zCI, "dir", "");
2231
+ hyperlinked_path(zName, &path, zCI, "dir", "", LINKPATH_FINFO);
22422232
zPath = blob_str(&path);
2243
- @ <h2>File %s(zPath) at check-in [%z(href("/info/%!S",zCIUuid))%S(zCIUuid)</a>]
2244
- @ </h2>
2233
+ @ <h2>File %s(zPath) \
2234
+ if( isBranchCI ){
2235
+ @ on branch %z(href("%R/timeline?r=%T",zCI))%h(zCI)</a></h2>
2236
+ }else if( isSymbolicCI ){
2237
+ @ as of check-in %z(href("%R/info/%!S",zCIUuid))%s(zCI)</a></h2>
2238
+ }else{
2239
+ @ as of check-in [%z(href("%R/info/%!S",zCIUuid))%S(zCIUuid)</a>]</h2>
2240
+ }
22452241
blob_reset(&path);
2246
- }else{
2247
- @ <h2>Latest version of file '%h(zName)':</h2>
22482242
}
22492243
style_submenu_element("Artifact", "%R/artifact/%S", zUuid);
2244
+ style_submenu_element("Annotate", "%R/annotate?filename=%T&checkin=%T",
2245
+ zName, zCI);
2246
+ style_submenu_element("Blame", "%R/blame?filename=%T&checkin=%T",
2247
+ zName, zCI);
2248
+ blob_init(&downloadName, zName, -1);
2249
+ objType = OBJTYPE_CONTENT;
22502250
}else{
22512251
@ <h2>Artifact
22522252
style_copy_button(1, "hash-ar", 0, 2, "%s", zUuid);
22532253
if( g.perm.Setup ){
22542254
@ (%d(rid)):</h2>
22552255
}else{
22562256
@ :</h2>
22572257
}
2258
+ blob_zero(&downloadName);
2259
+ if( asText ) objdescFlags &= ~OBJDESC_BASE;
2260
+ objType = object_description(rid, objdescFlags,
2261
+ (isFile?zName:0), &downloadName);
22582262
}
2259
- blob_zero(&downloadName);
2260
- asText = P("txt")!=0;
2261
- if( asText ) objdescFlags &= ~OBJDESC_BASE;
2262
- objType = object_description(rid, objdescFlags, (isFile ? zName : 0),&downloadName);
22632263
if( !descOnly && P("download")!=0 ){
22642264
cgi_redirectf("%R/raw/%T?name=%s", blob_str(&downloadName),
22652265
db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid));
22662266
/*NOTREACHED*/
22672267
}
@@ -2289,11 +2289,11 @@
22892289
zHeader = mprintf("Artifact [%S]", zUuid);
22902290
}
22912291
style_header("%s", zHeader);
22922292
fossil_free(zCIUuid);
22932293
fossil_free(zHeader);
2294
- if( g.perm.Admin ){
2294
+ if( !isFile && g.perm.Admin ){
22952295
Stmt q;
22962296
db_prepare(&q,
22972297
"SELECT coalesce(user.login,rcvfrom.uid),"
22982298
" datetime(rcvfrom.mtime,toLocal()), rcvfrom.ipaddr"
22992299
" FROM blob, rcvfrom LEFT JOIN user ON user.uid=rcvfrom.uid"
@@ -2769,15 +2769,15 @@
27692769
**
27702770
** Edit a check-in. (Check-ins are immutable and do not really change.
27712771
** This page really creates supplemental tags that affect the display
27722772
** of the check-in.)
27732773
**
2774
-** Query parmeters:
2774
+** Query parameters:
27752775
**
27762776
** rid=INTEGER Record ID of the check-in to edit (REQUIRED)
27772777
**
2778
-** POST parameters after pressing "Perview", "Cancel", or "Apply":
2778
+** POST parameters after pressing "Preview", "Cancel", or "Apply":
27792779
**
27802780
** c=TEXT New check-in comment
27812781
** u=TEXT New user name
27822782
** newclr Apply a background color
27832783
** clr=TEXT New background color (only if newclr)
27842784
--- src/info.c
+++ src/info.c
@@ -666,10 +666,11 @@
666 const char *zOrigDate;
667 int okWiki = 0;
668 Blob wiki_read_links = BLOB_INITIALIZER;
669 Blob wiki_add_links = BLOB_INITIALIZER;
670
 
671 style_header("Check-in [%S]", zUuid);
672 login_anonymous_available();
673 zEUser = db_text(0,
674 "SELECT value FROM tagxref"
675 " WHERE tagid=%d AND rid=%d AND tagtype>0",
@@ -1661,12 +1662,12 @@
1661 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1662 cookie_link_parameter("diff","diff","2");
1663 diffType = atoi(PD("diff","2"));
1664 cookie_render();
1665 if( P("from") && P("to") ){
1666 v1 = artifact_from_ci_and_filename(0, "from");
1667 v2 = artifact_from_ci_and_filename(0, "to");
1668 }else{
1669 Stmt q;
1670 v1 = name_to_rid_www("v1");
1671 v2 = name_to_rid_www("v2");
1672
@@ -1763,12 +1764,12 @@
1763 */
1764 void rawartifact_page(void){
1765 int rid = 0;
1766 char *zUuid;
1767
1768 if( P("ci") && P("filename") ){
1769 rid = artifact_from_ci_and_filename(0, 0);
1770 }
1771 if( rid==0 ){
1772 rid = name_to_rid_www("name");
1773 }
1774 login_check_credentials();
@@ -1942,59 +1943,53 @@
1942
1943 /*
1944 ** Look for "ci" and "filename" query parameters. If found, try to
1945 ** use them to extract the record ID of an artifact for the file.
1946 **
1947 ** Also look for "fn" as an alias for "filename". If either "filename"
1948 ** or "fn" is present but "ci" is missing, use "tip" as a default value
1949 ** for "ci".
1950 **
1951 ** If zNameParam is not NULL, this use that parameter as the filename
1952 ** rather than "fn" or "filename".
1953 **
1954 ** If pUrl is not NULL, then record the "ci" and "filename" values in
1955 ** pUrl.
1956 **
1957 ** At least one of pUrl or zNameParam must be NULL.
1958 */
1959 int artifact_from_ci_and_filename(HQuery *pUrl, const char *zNameParam){
1960 const char *zFilename;
1961 const char *zCI;
1962 int cirid;
1963 Manifest *pManifest;
1964 ManifestFile *pFile;
 
1965
1966 if( zNameParam ){
1967 zFilename = P(zNameParam);
1968 }else{
1969 zFilename = P("filename");
1970 if( zFilename==0 ){
1971 zFilename = P("fn");
1972 }
 
 
 
1973 }
1974 if( zFilename==0 ) return 0;
1975
1976 zCI = P("ci");
1977 cirid = name_to_typed_rid(zCI ? zCI : "tip", "ci");
1978 if( cirid<=0 ) return 0;
1979 pManifest = manifest_get(cirid, CFTYPE_MANIFEST, 0);
1980 if( pManifest==0 ) return 0;
1981 manifest_file_rewind(pManifest);
1982 while( (pFile = manifest_file_next(pManifest,0))!=0 ){
1983 if( fossil_strcmp(zFilename, pFile->zName)==0 ){
1984 int rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", pFile->zUuid);
1985 manifest_destroy(pManifest);
1986 if( pUrl ){
1987 assert( zNameParam==0 );
1988 url_add_parameter(pUrl, "fn", zFilename);
1989 if( zCI ) url_add_parameter(pUrl, "ci", zCI);
1990 }
1991 return rid;
1992 }
1993 }
1994 manifest_destroy(pManifest);
1995 return 0;
1996 }
1997
1998 /*
1999 ** The "z" argument is a string that contains the text of a source code
2000 ** file. This routine appends that text to the HTTP reply with line numbering.
@@ -2096,21 +2091,31 @@
2096 ** ln=N - highlight line number N
2097 ** ln=M-N - highlight lines M through N inclusive
2098 ** ln=M-N+Y-Z - highlight lines M through N and Y through Z (inclusive)
2099 ** verbose - show more detail in the description
2100 ** download - redirect to the download (artifact page only)
2101 ** name=NAME - Provide filename or hash as a query parameter
2102 ** filename=NAME - alternative spelling for "name="
2103 ** fn=NAME - alternative spelling for "name="
2104 ** ci=VERSION - The specific check-in to use for "filename=".
 
2105 **
2106 ** The /artifact page show the complete content of a file
2107 ** identified by HASH as preformatted text. The
2108 ** /whatis page shows only a description of the file. The /file
2109 ** page shows the most recent version of the file or directory
2110 ** called NAME, or a list of the top-level directory if NAME is
2111 ** omitted.
 
 
 
 
 
 
 
 
 
2112 */
2113 void artifact_page(void){
2114 int rid = 0;
2115 Blob content;
2116 const char *zMime;
@@ -2125,143 +2130,138 @@
2125 int isFile = fossil_strcmp(g.zPath,"file")==0;
2126 const char *zLn = P("ln");
2127 const char *zName = P("name");
2128 const char *zCI = P("ci");
2129 HQuery url;
2130 Blob dirname;
2131 char *zCIUuid = 0;
2132 int isSymbolicCI = 0; /* ci= exists and is a symbolic name, not a hash */
2133 char *zHeader = 0;
2134
2135 login_check_credentials();
2136 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
2137 url_initialize(&url, g.zPath);
2138 if( zName==0 ){
2139 zName = P("filename");
2140 if( zName==0 ) zName = P("fn");
2141 }
2142 if( zCI && strlen(zCI)==0 ){ zCI = 0; }
2143 if( zCI && zName ){
2144 blob_zero(&dirname);
2145 hyperlinked_path(zName, &dirname, zCI, "dir", "");
2146 blob_reset(&dirname);
2147
2148 if( name_to_uuid2(zCI, "ci", &zCIUuid) ){
2149 isSymbolicCI = (sqlite3_strnicmp(zCIUuid, zCI, strlen(zCI)) != 0);
2150 }
2151 }
2152 if( isFile && zName ) {
2153 rid = artifact_from_ci_and_filename(0, "name");
2154 }else{
2155 rid = artifact_from_ci_and_filename(&url, 0);
2156 }
2157 if( rid==0 ){
2158 url_add_parameter(&url, "name", zName);
2159 if( isFile ){
2160 int isUnknownAtCI = 0;
2161
2162 /* Do a top-level directory listing in /file mode if no argument
2163 ** specified */
2164 if( zName==0 || zName[0]==0 ){
2165 if( P("ci")==0 ) cgi_set_query_parameter("ci","tip");
2166 page_tree();
2167 return;
2168 }
2169 /* Look for a single file with the given name */
2170 rid = db_int(0,
2171 "SELECT fid FROM filename, mlink, event"
2172 " WHERE name=%Q"
2173 " AND mlink.fnid=filename.fnid"
2174 " AND event.objid=mlink.mid"
2175 " ORDER BY event.mtime DESC LIMIT 1",
2176 zName
2177 );
2178 /* If found only by the name, then the file is unknown in the check-in.
2179 ** Possibly, the file was renamed/deleted.
2180 */
2181 if( rid && zCIUuid ){
2182 rid = 0;
2183 isUnknownAtCI = 1;
2184 }
2185 /* If no file called NAME exists, instead look for a directory
2186 ** with that name, and do a directory listing */
2187 if( rid==0 ){
2188 int nName = (int)strlen(zName);
2189 if( nName && zName[nName-1]=='/' ) nName--;
2190 if( db_exists(
2191 "SELECT 1 FROM filename"
2192 " WHERE name GLOB '%.*q/*' AND substr(name,1,%d)=='%.*q/';",
2193 nName, zName, nName+1, nName, zName
2194 ) ){
2195 if( P("ci")==0 ) cgi_set_query_parameter("ci","tip");
2196 page_tree();
2197 return;
2198 }
2199 }
2200 /* If no file or directory called NAME: issue an error */
2201 if( rid==0 ){
2202 if( isUnknownAtCI ){
2203 if( isSymbolicCI ){
2204 zHeader = mprintf("No such file at %s", zCI);
2205 }else{
2206 zHeader = mprintf("No such file at [%S]", zCIUuid);
2207 }
2208 style_header("%s", zHeader);
2209 fossil_free(zHeader);
2210 @ File %z(href("%R/finfo?name=%T",zName))%h(zName)</a> is not known
2211 @ at check-in [%z(href("/info/%!S",zCIUuid))%S(zCIUuid)</a>].
2212 }else{
2213 style_header("No such file");
2214 @ File '%h(zName)' is not known in this repository.
2215 }
2216 style_footer();
2217 return;
2218 }
2219 }else{
2220 rid = name_to_rid_www("name");
2221 }
2222 }
2223
2224 if( rid==0 ){
2225 style_header("No such artifact");
2226 @ Artifact '%h(zName)' does not exist in this repository.
2227 style_footer();
2228 return;
2229 }
2230 if( descOnly || P("verbose")!=0 ){
2231 url_add_parameter(&url, "verbose", "1");
2232 objdescFlags |= OBJDESC_DETAIL;
2233 }
2234 zUuid = db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid);
2235
 
2236 if( isFile ){
2237 if( zCI ){
 
 
 
 
2238 const char *zPath;
2239 Blob path;
2240 blob_zero(&path);
2241 hyperlinked_path(zName, &path, zCI, "dir", "");
2242 zPath = blob_str(&path);
2243 @ <h2>File %s(zPath) at check-in [%z(href("/info/%!S",zCIUuid))%S(zCIUuid)</a>]
2244 @ </h2>
 
 
 
 
 
 
2245 blob_reset(&path);
2246 }else{
2247 @ <h2>Latest version of file '%h(zName)':</h2>
2248 }
2249 style_submenu_element("Artifact", "%R/artifact/%S", zUuid);
 
 
 
 
 
 
2250 }else{
2251 @ <h2>Artifact
2252 style_copy_button(1, "hash-ar", 0, 2, "%s", zUuid);
2253 if( g.perm.Setup ){
2254 @ (%d(rid)):</h2>
2255 }else{
2256 @ :</h2>
2257 }
 
 
 
 
2258 }
2259 blob_zero(&downloadName);
2260 asText = P("txt")!=0;
2261 if( asText ) objdescFlags &= ~OBJDESC_BASE;
2262 objType = object_description(rid, objdescFlags, (isFile ? zName : 0),&downloadName);
2263 if( !descOnly && P("download")!=0 ){
2264 cgi_redirectf("%R/raw/%T?name=%s", blob_str(&downloadName),
2265 db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid));
2266 /*NOTREACHED*/
2267 }
@@ -2289,11 +2289,11 @@
2289 zHeader = mprintf("Artifact [%S]", zUuid);
2290 }
2291 style_header("%s", zHeader);
2292 fossil_free(zCIUuid);
2293 fossil_free(zHeader);
2294 if( g.perm.Admin ){
2295 Stmt q;
2296 db_prepare(&q,
2297 "SELECT coalesce(user.login,rcvfrom.uid),"
2298 " datetime(rcvfrom.mtime,toLocal()), rcvfrom.ipaddr"
2299 " FROM blob, rcvfrom LEFT JOIN user ON user.uid=rcvfrom.uid"
@@ -2769,15 +2769,15 @@
2769 **
2770 ** Edit a check-in. (Check-ins are immutable and do not really change.
2771 ** This page really creates supplemental tags that affect the display
2772 ** of the check-in.)
2773 **
2774 ** Query parmeters:
2775 **
2776 ** rid=INTEGER Record ID of the check-in to edit (REQUIRED)
2777 **
2778 ** POST parameters after pressing "Perview", "Cancel", or "Apply":
2779 **
2780 ** c=TEXT New check-in comment
2781 ** u=TEXT New user name
2782 ** newclr Apply a background color
2783 ** clr=TEXT New background color (only if newclr)
2784
--- src/info.c
+++ src/info.c
@@ -666,10 +666,11 @@
666 const char *zOrigDate;
667 int okWiki = 0;
668 Blob wiki_read_links = BLOB_INITIALIZER;
669 Blob wiki_add_links = BLOB_INITIALIZER;
670
671 Th_Store("current_checkin", zName);
672 style_header("Check-in [%S]", zUuid);
673 login_anonymous_available();
674 zEUser = db_text(0,
675 "SELECT value FROM tagxref"
676 " WHERE tagid=%d AND rid=%d AND tagtype>0",
@@ -1661,12 +1662,12 @@
1662 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1663 cookie_link_parameter("diff","diff","2");
1664 diffType = atoi(PD("diff","2"));
1665 cookie_render();
1666 if( P("from") && P("to") ){
1667 v1 = artifact_from_ci_and_filename("from");
1668 v2 = artifact_from_ci_and_filename("to");
1669 }else{
1670 Stmt q;
1671 v1 = name_to_rid_www("v1");
1672 v2 = name_to_rid_www("v2");
1673
@@ -1763,12 +1764,12 @@
1764 */
1765 void rawartifact_page(void){
1766 int rid = 0;
1767 char *zUuid;
1768
1769 if( P("ci") ){
1770 rid = artifact_from_ci_and_filename(0);
1771 }
1772 if( rid==0 ){
1773 rid = name_to_rid_www("name");
1774 }
1775 login_check_credentials();
@@ -1942,59 +1943,53 @@
1943
1944 /*
1945 ** Look for "ci" and "filename" query parameters. If found, try to
1946 ** use them to extract the record ID of an artifact for the file.
1947 **
1948 ** Also look for "fn" and "name" as an aliases for "filename". If any
1949 ** "filename" or "fn" or "name" are present but "ci" is missing, then
1950 ** use "tip" as the default value for "ci".
1951 **
1952 ** If zNameParam is not NULL, then use that parameter as the filename
1953 ** rather than "fn" or "filename" or "name". the zNameParam is used
1954 ** for the from= and to= query parameters of /fdiff.
 
 
 
 
1955 */
1956 int artifact_from_ci_and_filename(const char *zNameParam){
1957 const char *zFilename;
1958 const char *zCI;
1959 int cirid;
1960 Manifest *pManifest;
1961 ManifestFile *pFile;
1962 int rid = 0;
1963
1964 if( zNameParam ){
1965 zFilename = P(zNameParam);
1966 }else{
1967 zFilename = P("filename");
1968 if( zFilename==0 ){
1969 zFilename = P("fn");
1970 }
1971 if( zFilename==0 ){
1972 zFilename = P("name");
1973 }
1974 }
1975 if( zFilename==0 ) return 0;
1976
1977 zCI = PD("ci", "tip");
1978 cirid = name_to_typed_rid(zCI, "ci");
1979 if( cirid<=0 ) return 0;
1980 pManifest = manifest_get(cirid, CFTYPE_MANIFEST, 0);
1981 if( pManifest==0 ) return 0;
1982 manifest_file_rewind(pManifest);
1983 while( (pFile = manifest_file_next(pManifest,0))!=0 ){
1984 if( fossil_strcmp(zFilename, pFile->zName)==0 ){
1985 rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", pFile->zUuid);
1986 break;
 
 
 
 
 
 
1987 }
1988 }
1989 manifest_destroy(pManifest);
1990 return rid;
1991 }
1992
1993 /*
1994 ** The "z" argument is a string that contains the text of a source code
1995 ** file. This routine appends that text to the HTTP reply with line numbering.
@@ -2096,21 +2091,31 @@
2091 ** ln=N - highlight line number N
2092 ** ln=M-N - highlight lines M through N inclusive
2093 ** ln=M-N+Y-Z - highlight lines M through N and Y through Z (inclusive)
2094 ** verbose - show more detail in the description
2095 ** download - redirect to the download (artifact page only)
2096 ** name=NAME - filename or hash as a query parameter
2097 ** filename=NAME - alternative spelling for "name="
2098 ** fn=NAME - alternative spelling for "name="
2099 ** ci=VERSION - The specific check-in to use with "name=" to
2100 ** identify the file.
2101 **
2102 ** The /artifact page show the complete content of a file
2103 ** identified by HASH. The /whatis page shows only a description
2104 ** of how the artifact is used. The /file page shows the most recent
2105 ** version of the file or directory called NAME, or a list of the
2106 ** top-level directory if NAME is omitted.
2107 **
2108 ** For /artifact and /whatis, the name= query parameter can refer to
2109 ** either the name of a file, or an artifact hash. If the ci= query
2110 ** parameter is also present, then name= must refer to a file name.
2111 ** If ci= is omitted, then the hash interpretation is preferred but
2112 ** if name= cannot be understood as a hash, a default "tip" value is
2113 ** used for ci=.
2114 **
2115 ** For /file, name= can only be interpreted as a filename. As before,
2116 ** a default value of "tip" is used for ci= if ci= is omitted.
2117 */
2118 void artifact_page(void){
2119 int rid = 0;
2120 Blob content;
2121 const char *zMime;
@@ -2125,143 +2130,138 @@
2130 int isFile = fossil_strcmp(g.zPath,"file")==0;
2131 const char *zLn = P("ln");
2132 const char *zName = P("name");
2133 const char *zCI = P("ci");
2134 HQuery url;
2135 char *zCIUuid = 0;
2136 int isSymbolicCI = 0; /* ci= exists and is a symbolic name, not a hash */
2137 int isBranchCI = 0; /* ci= refers to a branch name */
2138 char *zHeader = 0;
2139
2140 login_check_credentials();
2141 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
2142
2143 /* Capture and normalize the name= and ci= query parameters */
2144 if( zName==0 ){
2145 zName = P("filename");
2146 if( zName==0 ){
2147 zName = P("fn");
2148 }
2149 }
2150 if( zCI && strlen(zCI)==0 ){ zCI = 0; }
2151 if( zCI
2152 && name_to_uuid2(zCI, "ci", &zCIUuid)
2153 && sqlite3_strnicmp(zCIUuid, zCI, strlen(zCI))!=0
2154 ){
2155 isSymbolicCI = 1;
2156 isBranchCI = branch_includes_uuid(zCI, zCIUuid);
2157 }
2158
2159 /* The name= query parameter (or at least one of its alternative
2160 ** spellings) is required. Except for /file, show a top-level
2161 ** directory listing if name= is omitted.
2162 */
2163 if( zName==0 ){
2164 if( isFile ){
2165 if( P("ci")==0 ) cgi_set_query_parameter("ci","tip");
2166 page_tree();
2167 return;
2168 }
2169 style_header("Missing name= query parameter");
2170 @ The name= query parameter is missing
2171 style_footer();
2172 return;
2173 }
2174
2175 url_initialize(&url, g.zPath);
2176 url_add_parameter(&url, "name", zName);
2177 url_add_parameter(&url, "ci", zCI);
2178
2179 if( zCI==0 && !isFile ){
2180 /* If there is no ci= query parameter, then prefer to interpret
2181 ** name= as a hash for /artifact and /whatis. But for not for /file.
2182 ** For /file, a name= without a ci= while prefer to use the default
2183 ** "tip" value for ci=. */
2184 rid = name_to_rid(zName);
2185 }
2186 if( rid==0 ){
2187 rid = artifact_from_ci_and_filename(0);
2188 }
2189
2190 if( rid==0 ){ /* Artifact not found */
2191 if( isFile ){
2192 /* For /file, also check to see if name= refers to a directory,
2193 ** and if so, do a listing for that directory */
2194 int nName = (int)strlen(zName);
2195 if( nName && zName[nName-1]=='/' ) nName--;
2196 if( db_exists(
2197 "SELECT 1 FROM filename"
2198 " WHERE name GLOB '%.*q/*' AND substr(name,1,%d)=='%.*q/';",
2199 nName, zName, nName+1, nName, zName
2200 ) ){
2201 if( P("ci")==0 ) cgi_set_query_parameter("ci","tip");
2202 page_tree();
2203 return;
2204 }
2205 style_header("No such file");
2206 @ File '%h(zName)' does not exist in this repository.
2207 }else{
2208 style_header("No such artifact");
2209 @ Artifact '%h(zName)' does not exist in this repository.
2210 }
2211 style_footer();
2212 return;
2213 }
2214
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2215 if( descOnly || P("verbose")!=0 ){
2216 url_add_parameter(&url, "verbose", "1");
2217 objdescFlags |= OBJDESC_DETAIL;
2218 }
2219 zUuid = db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid);
2220
2221 asText = P("txt")!=0;
2222 if( isFile ){
2223 if( zCI==0 || fossil_strcmp(zCI,"tip")==0 ){
2224 zCI = "tip";
2225 @ <h2>File %z(href("%R/finfo?name=%T&m=tip",zName))%h(zName)</a>
2226 @ from the %z(href("%R/info/tip"))latest check-in</a></h2>
2227 }else{
2228 const char *zPath;
2229 Blob path;
2230 blob_zero(&path);
2231 hyperlinked_path(zName, &path, zCI, "dir", "", LINKPATH_FINFO);
2232 zPath = blob_str(&path);
2233 @ <h2>File %s(zPath) \
2234 if( isBranchCI ){
2235 @ on branch %z(href("%R/timeline?r=%T",zCI))%h(zCI)</a></h2>
2236 }else if( isSymbolicCI ){
2237 @ as of check-in %z(href("%R/info/%!S",zCIUuid))%s(zCI)</a></h2>
2238 }else{
2239 @ as of check-in [%z(href("%R/info/%!S",zCIUuid))%S(zCIUuid)</a>]</h2>
2240 }
2241 blob_reset(&path);
 
 
2242 }
2243 style_submenu_element("Artifact", "%R/artifact/%S", zUuid);
2244 style_submenu_element("Annotate", "%R/annotate?filename=%T&checkin=%T",
2245 zName, zCI);
2246 style_submenu_element("Blame", "%R/blame?filename=%T&checkin=%T",
2247 zName, zCI);
2248 blob_init(&downloadName, zName, -1);
2249 objType = OBJTYPE_CONTENT;
2250 }else{
2251 @ <h2>Artifact
2252 style_copy_button(1, "hash-ar", 0, 2, "%s", zUuid);
2253 if( g.perm.Setup ){
2254 @ (%d(rid)):</h2>
2255 }else{
2256 @ :</h2>
2257 }
2258 blob_zero(&downloadName);
2259 if( asText ) objdescFlags &= ~OBJDESC_BASE;
2260 objType = object_description(rid, objdescFlags,
2261 (isFile?zName:0), &downloadName);
2262 }
 
 
 
 
2263 if( !descOnly && P("download")!=0 ){
2264 cgi_redirectf("%R/raw/%T?name=%s", blob_str(&downloadName),
2265 db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid));
2266 /*NOTREACHED*/
2267 }
@@ -2289,11 +2289,11 @@
2289 zHeader = mprintf("Artifact [%S]", zUuid);
2290 }
2291 style_header("%s", zHeader);
2292 fossil_free(zCIUuid);
2293 fossil_free(zHeader);
2294 if( !isFile && g.perm.Admin ){
2295 Stmt q;
2296 db_prepare(&q,
2297 "SELECT coalesce(user.login,rcvfrom.uid),"
2298 " datetime(rcvfrom.mtime,toLocal()), rcvfrom.ipaddr"
2299 " FROM blob, rcvfrom LEFT JOIN user ON user.uid=rcvfrom.uid"
@@ -2769,15 +2769,15 @@
2769 **
2770 ** Edit a check-in. (Check-ins are immutable and do not really change.
2771 ** This page really creates supplemental tags that affect the display
2772 ** of the check-in.)
2773 **
2774 ** Query parameters:
2775 **
2776 ** rid=INTEGER Record ID of the check-in to edit (REQUIRED)
2777 **
2778 ** POST parameters after pressing "Preview", "Cancel", or "Apply":
2779 **
2780 ** c=TEXT New check-in comment
2781 ** u=TEXT New user name
2782 ** newclr Apply a background color
2783 ** clr=TEXT New background color (only if newclr)
2784
+34 -28
--- src/login.c
+++ src/login.c
@@ -678,20 +678,18 @@
678678
}else{
679679
zAnonPw = 0;
680680
}
681681
@ <table class="login_out">
682682
@ <tr>
683
- @ <td class="form_label">User ID:</td>
684
- if( anonFlag ){
685
- @ <td><input type="text" id="u" name="u" value="anonymous" size="30"></td>
686
- }else{
687
- @ <td><input type="text" id="u" name="u" value="" size="30" /></td>
688
- }
683
+ @ <td class="form_label" id="userlabel1">User ID:</td>
684
+ @ <td><input type="text" id="u" aria-labelledby="userlabel1" name="u" \
685
+ @ size="30" value="%s(anonFlag?"anonymous":"")"></td>
689686
@ </tr>
690687
@ <tr>
691
- @ <td class="form_label">Password:</td>
692
- @ <td><input type="password" id="p" name="p" value="" size="30" />\
688
+ @ <td class="form_label" id="pswdlabel">Password:</td>
689
+ @ <td><input aria-labelledby="pswdlabel" type="password" id="p" \
690
+ @ name="p" value="" size="30" />\
693691
if( zAnonPw && !noAnon ){
694692
captcha_speakit_button(uSeed, "Speak password for \"anonymous\"");
695693
}
696694
@ </td>
697695
@ </tr>
@@ -750,16 +748,19 @@
750748
if( g.perm.Password ){
751749
@ <hr>
752750
@ <p>Change Password for user <b>%h(g.zLogin)</b>:</p>
753751
form_begin(0, "%R/login");
754752
@ <table>
755
- @ <tr><td class="form_label">Old Password:</td>
756
- @ <td><input type="password" name="p" size="30" /></td></tr>
757
- @ <tr><td class="form_label">New Password:</td>
758
- @ <td><input type="password" name="n1" size="30" /></td></tr>
759
- @ <tr><td class="form_label">Repeat New Password:</td>
760
- @ <td><input type="password" name="n2" size="30" /></td></tr>
753
+ @ <tr><td class="form_label" id="oldpw">Old Password:</td>
754
+ @ <td><input aria-labelledby="oldpw" type="password" name="p" \
755
+ @ size="30"/></td></tr>
756
+ @ <tr><td class="form_label" id="newpw">New Password:</td>
757
+ @ <td><input aria-labelledby="newpw" type="password" name="n1" \
758
+ @ size="30" /></td></tr>
759
+ @ <tr><td class="form_label" id="reppw">Repeat New Password:</td>
760
+ @ <td><input aria-labledby="reppw" type="password" name="n2" \
761
+ @ size="30" /></td></tr>
761762
@ <tr><td></td>
762763
@ <td><input type="submit" value="Change Password" /></td></tr>
763764
@ </table>
764765
@ </form>
765766
}
@@ -1690,57 +1691,62 @@
16901691
@ <input type="hidden" name="g" value="%h(P("g"))" />
16911692
}
16921693
@ <p><input type="hidden" name="captchaseed" value="%u(uSeed)" />
16931694
@ <table class="login_out">
16941695
@ <tr>
1695
- @ <td class="form_label" align="right">User ID:</td>
1696
- @ <td><input type="text" name="u" value="%h(zUserID)" size="30"></td>
1696
+ @ <td class="form_label" align="right" id="uid">User ID:</td>
1697
+ @ <td><input aria-labelledby="uid" type="text" name="u" \
1698
+ @ value="%h(zUserID)" size="30"></td>
16971699
@
16981700
if( iErrLine==1 ){
16991701
@ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
17001702
}
17011703
@ <tr>
1702
- @ <td class="form_label" align="right">Display Name:</td>
1703
- @ <td><input type="text" name="dn" value="%h(zDName)" size="30"></td>
1704
+ @ <td class="form_label" align="right" id="dpyname">Display Name:</td>
1705
+ @ <td><input aria-labelledby="dpyname" type="text" name="dn" \
1706
+ @ value="%h(zDName)" size="30"></td>
17041707
@ </tr>
17051708
if( iErrLine==2 ){
17061709
@ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
17071710
}
17081711
@ </tr>
17091712
@ <tr>
1710
- @ <td class="form_label" align="right">Email Address:</td>
1711
- @ <td><input type="text" name="ea" value="%h(zEAddr)" size="30"></td>
1713
+ @ <td class="form_label" align="right" id="emaddr">Email Address:</td>
1714
+ @ <td><input aria-labelledby="emaddr" type="text" name="ea" \
1715
+ @ value="%h(zEAddr)" size="30"></td>
17121716
@ </tr>
17131717
if( iErrLine==3 ){
17141718
@ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
17151719
}
17161720
if( canDoAlerts ){
17171721
int a = atoi(PD("alerts","1"));
17181722
@ <tr>
1719
- @ <td class="form_label" align="right">Email&nbsp;Alerts?</td>
1720
- @ <td><select size='1' name='alerts'>
1723
+ @ <td class="form_label" align="right" id="emalrt">Email&nbsp;Alerts?</td>
1724
+ @ <td><select aria-labelledby="emalrt" size='1' name='alerts'>
17211725
@ <option value="1" %s(a?"selected":"")>Yes</option>
17221726
@ <option value="0" %s(!a?"selected":"")>No</option>
17231727
@ </select></td></tr>
17241728
}
17251729
@ <tr>
1726
- @ <td class="form_label" align="right">Password:</td>
1727
- @ <td><input type="password" name="p" value="%h(zPasswd)" size="30"></td>
1730
+ @ <td class="form_label" align="right" id="pswd">Password:</td>
1731
+ @ <td><input aria-labelledby="pswd" type="password" name="p" \
1732
+ @ value="%h(zPasswd)" size="30"></td>
17281733
@ <tr>
17291734
if( iErrLine==4 ){
17301735
@ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
17311736
}
17321737
@ <tr>
1733
- @ <td class="form_label" align="right">Confirm:</td>
1734
- @ <td><input type="password" name="cp" value="%h(zConfirm)" size="30"></td>
1738
+ @ <td class="form_label" align="right" id="pwcfrm">Confirm:</td>
1739
+ @ <td><input aria-labelledby="pwcfrm" type="password" name="cp" \
1740
+ @ value="%h(zConfirm)" size="30"></td>
17351741
@ </tr>
17361742
if( iErrLine==5 ){
17371743
@ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
17381744
}
17391745
@ <tr>
1740
- @ <td class="form_label" align="right">Captcha:</td>
1741
- @ <td><input type="text" name="captcha" \
1746
+ @ <td class="form_label" align="right" id="cptcha">Captcha:</td>
1747
+ @ <td><input type="text" name="captcha" aria-labelledby="cptcha" \
17421748
@ value="%h(captchaIsCorrect?zDecoded:"")" size="30">
17431749
captcha_speakit_button(uSeed, "Speak the captcha text");
17441750
@ </td>
17451751
@ </tr>
17461752
if( iErrLine==6 ){
17471753
--- src/login.c
+++ src/login.c
@@ -678,20 +678,18 @@
678 }else{
679 zAnonPw = 0;
680 }
681 @ <table class="login_out">
682 @ <tr>
683 @ <td class="form_label">User ID:</td>
684 if( anonFlag ){
685 @ <td><input type="text" id="u" name="u" value="anonymous" size="30"></td>
686 }else{
687 @ <td><input type="text" id="u" name="u" value="" size="30" /></td>
688 }
689 @ </tr>
690 @ <tr>
691 @ <td class="form_label">Password:</td>
692 @ <td><input type="password" id="p" name="p" value="" size="30" />\
 
693 if( zAnonPw && !noAnon ){
694 captcha_speakit_button(uSeed, "Speak password for \"anonymous\"");
695 }
696 @ </td>
697 @ </tr>
@@ -750,16 +748,19 @@
750 if( g.perm.Password ){
751 @ <hr>
752 @ <p>Change Password for user <b>%h(g.zLogin)</b>:</p>
753 form_begin(0, "%R/login");
754 @ <table>
755 @ <tr><td class="form_label">Old Password:</td>
756 @ <td><input type="password" name="p" size="30" /></td></tr>
757 @ <tr><td class="form_label">New Password:</td>
758 @ <td><input type="password" name="n1" size="30" /></td></tr>
759 @ <tr><td class="form_label">Repeat New Password:</td>
760 @ <td><input type="password" name="n2" size="30" /></td></tr>
 
 
 
761 @ <tr><td></td>
762 @ <td><input type="submit" value="Change Password" /></td></tr>
763 @ </table>
764 @ </form>
765 }
@@ -1690,57 +1691,62 @@
1690 @ <input type="hidden" name="g" value="%h(P("g"))" />
1691 }
1692 @ <p><input type="hidden" name="captchaseed" value="%u(uSeed)" />
1693 @ <table class="login_out">
1694 @ <tr>
1695 @ <td class="form_label" align="right">User ID:</td>
1696 @ <td><input type="text" name="u" value="%h(zUserID)" size="30"></td>
 
1697 @
1698 if( iErrLine==1 ){
1699 @ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
1700 }
1701 @ <tr>
1702 @ <td class="form_label" align="right">Display Name:</td>
1703 @ <td><input type="text" name="dn" value="%h(zDName)" size="30"></td>
 
1704 @ </tr>
1705 if( iErrLine==2 ){
1706 @ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
1707 }
1708 @ </tr>
1709 @ <tr>
1710 @ <td class="form_label" align="right">Email Address:</td>
1711 @ <td><input type="text" name="ea" value="%h(zEAddr)" size="30"></td>
 
1712 @ </tr>
1713 if( iErrLine==3 ){
1714 @ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
1715 }
1716 if( canDoAlerts ){
1717 int a = atoi(PD("alerts","1"));
1718 @ <tr>
1719 @ <td class="form_label" align="right">Email&nbsp;Alerts?</td>
1720 @ <td><select size='1' name='alerts'>
1721 @ <option value="1" %s(a?"selected":"")>Yes</option>
1722 @ <option value="0" %s(!a?"selected":"")>No</option>
1723 @ </select></td></tr>
1724 }
1725 @ <tr>
1726 @ <td class="form_label" align="right">Password:</td>
1727 @ <td><input type="password" name="p" value="%h(zPasswd)" size="30"></td>
 
1728 @ <tr>
1729 if( iErrLine==4 ){
1730 @ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
1731 }
1732 @ <tr>
1733 @ <td class="form_label" align="right">Confirm:</td>
1734 @ <td><input type="password" name="cp" value="%h(zConfirm)" size="30"></td>
 
1735 @ </tr>
1736 if( iErrLine==5 ){
1737 @ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
1738 }
1739 @ <tr>
1740 @ <td class="form_label" align="right">Captcha:</td>
1741 @ <td><input type="text" name="captcha" \
1742 @ value="%h(captchaIsCorrect?zDecoded:"")" size="30">
1743 captcha_speakit_button(uSeed, "Speak the captcha text");
1744 @ </td>
1745 @ </tr>
1746 if( iErrLine==6 ){
1747
--- src/login.c
+++ src/login.c
@@ -678,20 +678,18 @@
678 }else{
679 zAnonPw = 0;
680 }
681 @ <table class="login_out">
682 @ <tr>
683 @ <td class="form_label" id="userlabel1">User ID:</td>
684 @ <td><input type="text" id="u" aria-labelledby="userlabel1" name="u" \
685 @ size="30" value="%s(anonFlag?"anonymous":"")"></td>
 
 
 
686 @ </tr>
687 @ <tr>
688 @ <td class="form_label" id="pswdlabel">Password:</td>
689 @ <td><input aria-labelledby="pswdlabel" type="password" id="p" \
690 @ name="p" value="" size="30" />\
691 if( zAnonPw && !noAnon ){
692 captcha_speakit_button(uSeed, "Speak password for \"anonymous\"");
693 }
694 @ </td>
695 @ </tr>
@@ -750,16 +748,19 @@
748 if( g.perm.Password ){
749 @ <hr>
750 @ <p>Change Password for user <b>%h(g.zLogin)</b>:</p>
751 form_begin(0, "%R/login");
752 @ <table>
753 @ <tr><td class="form_label" id="oldpw">Old Password:</td>
754 @ <td><input aria-labelledby="oldpw" type="password" name="p" \
755 @ size="30"/></td></tr>
756 @ <tr><td class="form_label" id="newpw">New Password:</td>
757 @ <td><input aria-labelledby="newpw" type="password" name="n1" \
758 @ size="30" /></td></tr>
759 @ <tr><td class="form_label" id="reppw">Repeat New Password:</td>
760 @ <td><input aria-labledby="reppw" type="password" name="n2" \
761 @ size="30" /></td></tr>
762 @ <tr><td></td>
763 @ <td><input type="submit" value="Change Password" /></td></tr>
764 @ </table>
765 @ </form>
766 }
@@ -1690,57 +1691,62 @@
1691 @ <input type="hidden" name="g" value="%h(P("g"))" />
1692 }
1693 @ <p><input type="hidden" name="captchaseed" value="%u(uSeed)" />
1694 @ <table class="login_out">
1695 @ <tr>
1696 @ <td class="form_label" align="right" id="uid">User ID:</td>
1697 @ <td><input aria-labelledby="uid" type="text" name="u" \
1698 @ value="%h(zUserID)" size="30"></td>
1699 @
1700 if( iErrLine==1 ){
1701 @ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
1702 }
1703 @ <tr>
1704 @ <td class="form_label" align="right" id="dpyname">Display Name:</td>
1705 @ <td><input aria-labelledby="dpyname" type="text" name="dn" \
1706 @ value="%h(zDName)" size="30"></td>
1707 @ </tr>
1708 if( iErrLine==2 ){
1709 @ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
1710 }
1711 @ </tr>
1712 @ <tr>
1713 @ <td class="form_label" align="right" id="emaddr">Email Address:</td>
1714 @ <td><input aria-labelledby="emaddr" type="text" name="ea" \
1715 @ value="%h(zEAddr)" size="30"></td>
1716 @ </tr>
1717 if( iErrLine==3 ){
1718 @ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
1719 }
1720 if( canDoAlerts ){
1721 int a = atoi(PD("alerts","1"));
1722 @ <tr>
1723 @ <td class="form_label" align="right" id="emalrt">Email&nbsp;Alerts?</td>
1724 @ <td><select aria-labelledby="emalrt" size='1' name='alerts'>
1725 @ <option value="1" %s(a?"selected":"")>Yes</option>
1726 @ <option value="0" %s(!a?"selected":"")>No</option>
1727 @ </select></td></tr>
1728 }
1729 @ <tr>
1730 @ <td class="form_label" align="right" id="pswd">Password:</td>
1731 @ <td><input aria-labelledby="pswd" type="password" name="p" \
1732 @ value="%h(zPasswd)" size="30"></td>
1733 @ <tr>
1734 if( iErrLine==4 ){
1735 @ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
1736 }
1737 @ <tr>
1738 @ <td class="form_label" align="right" id="pwcfrm">Confirm:</td>
1739 @ <td><input aria-labelledby="pwcfrm" type="password" name="cp" \
1740 @ value="%h(zConfirm)" size="30"></td>
1741 @ </tr>
1742 if( iErrLine==5 ){
1743 @ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
1744 }
1745 @ <tr>
1746 @ <td class="form_label" align="right" id="cptcha">Captcha:</td>
1747 @ <td><input type="text" name="captcha" aria-labelledby="cptcha" \
1748 @ value="%h(captchaIsCorrect?zDecoded:"")" size="30">
1749 captcha_speakit_button(uSeed, "Speak the captcha text");
1750 @ </td>
1751 @ </tr>
1752 if( iErrLine==6 ){
1753
+3 -3
--- src/printf.c
+++ src/printf.c
@@ -34,11 +34,11 @@
3434
** The following macros help determine those lengths. FOSSIL_HASH_DIGITS
3535
** is the default number of digits to display to humans. This value can
3636
** be overridden using the hash-digits setting. FOSSIL_HASH_DIGITS_URL
3737
** is the minimum number of digits to be used in URLs. The number used
3838
** will always be at least 6 more than the number used for human output,
39
-** or 40 if the number of digits in human output is 34 or more.
39
+** or HNAME_MAX, whichever is least.
4040
*/
4141
#ifndef FOSSIL_HASH_DIGITS
4242
# define FOSSIL_HASH_DIGITS 10 /* For %S (human display) */
4343
#endif
4444
#ifndef FOSSIL_HASH_DIGITS_URL
@@ -54,14 +54,14 @@
5454
static int nDigitHuman = 0;
5555
static int nDigitUrl = 0;
5656
if( nDigitHuman==0 ){
5757
nDigitHuman = db_get_int("hash-digits", FOSSIL_HASH_DIGITS);
5858
if( nDigitHuman < 6 ) nDigitHuman = 6;
59
- if( nDigitHuman > 40 ) nDigitHuman = 40;
59
+ if( nDigitHuman > HNAME_MAX ) nDigitHuman = HNAME_MAX;
6060
nDigitUrl = nDigitHuman + 6;
6161
if( nDigitUrl < FOSSIL_HASH_DIGITS_URL ) nDigitUrl = FOSSIL_HASH_DIGITS_URL;
62
- if( nDigitUrl > 40 ) nDigitUrl = 40;
62
+ if( nDigitUrl > HNAME_MAX ) nDigitUrl = HNAME_MAX;
6363
}
6464
return bForUrl ? nDigitUrl : nDigitHuman;
6565
}
6666
6767
/*
6868
--- src/printf.c
+++ src/printf.c
@@ -34,11 +34,11 @@
34 ** The following macros help determine those lengths. FOSSIL_HASH_DIGITS
35 ** is the default number of digits to display to humans. This value can
36 ** be overridden using the hash-digits setting. FOSSIL_HASH_DIGITS_URL
37 ** is the minimum number of digits to be used in URLs. The number used
38 ** will always be at least 6 more than the number used for human output,
39 ** or 40 if the number of digits in human output is 34 or more.
40 */
41 #ifndef FOSSIL_HASH_DIGITS
42 # define FOSSIL_HASH_DIGITS 10 /* For %S (human display) */
43 #endif
44 #ifndef FOSSIL_HASH_DIGITS_URL
@@ -54,14 +54,14 @@
54 static int nDigitHuman = 0;
55 static int nDigitUrl = 0;
56 if( nDigitHuman==0 ){
57 nDigitHuman = db_get_int("hash-digits", FOSSIL_HASH_DIGITS);
58 if( nDigitHuman < 6 ) nDigitHuman = 6;
59 if( nDigitHuman > 40 ) nDigitHuman = 40;
60 nDigitUrl = nDigitHuman + 6;
61 if( nDigitUrl < FOSSIL_HASH_DIGITS_URL ) nDigitUrl = FOSSIL_HASH_DIGITS_URL;
62 if( nDigitUrl > 40 ) nDigitUrl = 40;
63 }
64 return bForUrl ? nDigitUrl : nDigitHuman;
65 }
66
67 /*
68
--- src/printf.c
+++ src/printf.c
@@ -34,11 +34,11 @@
34 ** The following macros help determine those lengths. FOSSIL_HASH_DIGITS
35 ** is the default number of digits to display to humans. This value can
36 ** be overridden using the hash-digits setting. FOSSIL_HASH_DIGITS_URL
37 ** is the minimum number of digits to be used in URLs. The number used
38 ** will always be at least 6 more than the number used for human output,
39 ** or HNAME_MAX, whichever is least.
40 */
41 #ifndef FOSSIL_HASH_DIGITS
42 # define FOSSIL_HASH_DIGITS 10 /* For %S (human display) */
43 #endif
44 #ifndef FOSSIL_HASH_DIGITS_URL
@@ -54,14 +54,14 @@
54 static int nDigitHuman = 0;
55 static int nDigitUrl = 0;
56 if( nDigitHuman==0 ){
57 nDigitHuman = db_get_int("hash-digits", FOSSIL_HASH_DIGITS);
58 if( nDigitHuman < 6 ) nDigitHuman = 6;
59 if( nDigitHuman > HNAME_MAX ) nDigitHuman = HNAME_MAX;
60 nDigitUrl = nDigitHuman + 6;
61 if( nDigitUrl < FOSSIL_HASH_DIGITS_URL ) nDigitUrl = FOSSIL_HASH_DIGITS_URL;
62 if( nDigitUrl > HNAME_MAX ) nDigitUrl = HNAME_MAX;
63 }
64 return bForUrl ? nDigitUrl : nDigitHuman;
65 }
66
67 /*
68
+32 -25
--- src/setup.c
+++ src/setup.c
@@ -201,16 +201,17 @@
201201
admin_log("Set option [%q] to [%q].",
202202
zVar, iQ ? "on" : "off");
203203
iVal = iQ;
204204
}
205205
}
206
- @ <label><input type="checkbox" name="%s(zQParm)"
206
+ @ <label><input type="checkbox" name="%s(zQParm)" \
207
+ @ aria-label="%s(zLabel[0]?zLabel:zQParm)" \
207208
if( iVal ){
208
- @ checked="checked"
209
+ @ checked="checked" \
209210
}
210211
if( disabled ){
211
- @ disabled="disabled"
212
+ @ disabled="disabled" \
212213
}
213214
@ /> <b>%s(zLabel)</b></label>
214215
}
215216
216217
/*
@@ -232,12 +233,12 @@
232233
db_set(zVar, zQ, 0);
233234
admin_log("Set entry_attribute %Q to: %.*s%s",
234235
zVar, 20, zQ, (nZQ>20 ? "..." : ""));
235236
zVal = zQ;
236237
}
237
- @ <input type="text" id="%s(zQParm)" name="%s(zQParm)" value="%h(zVal)" \
238
- @ size="%d(width)" \
238
+ @ <input aria-label="%h(zLabel[0]?zLabel:zQParm)" type="text" \
239
+ @ id="%s(zQParm)" name="%s(zQParm)" value="%h(zVal)" size="%d(width)" \
239240
if( disabled ){
240241
@ disabled="disabled" \
241242
}
242243
@ /> <b>%s(zLabel)</b>
243244
}
@@ -263,16 +264,17 @@
263264
admin_log("Set textarea_attribute %Q to: %.*s%s",
264265
zVar, 20, zQ, (nZQ>20 ? "..." : ""));
265266
z = zQ;
266267
}
267268
if( rows>0 && cols>0 ){
268
- @ <textarea id="id%s(zQP)" name="%s(zQP)" rows="%d(rows)"
269
+ @ <textarea id="id%s(zQP)" name="%s(zQP)" rows="%d(rows)" \
270
+ @ aria-label="%h(zLabel[0]?zLabel:zQP)" \
269271
if( disabled ){
270
- @ disabled="disabled"
272
+ @ disabled="disabled" \
271273
}
272274
@ cols="%d(cols)">%h(z)</textarea>
273
- if( zLabel && *zLabel ){
275
+ if( *zLabel ){
274276
@ <span class="textareaLabel">%s(zLabel)</span>
275277
}
276278
}
277279
return z;
278280
}
@@ -297,11 +299,11 @@
297299
db_set(zVar, zQ, 0);
298300
admin_log("Set multiple_choice_attribute %Q to: %.*s%s",
299301
zVar, 20, zQ, (nZQ>20 ? "..." : ""));
300302
z = zQ;
301303
}
302
- @ <select size="1" name="%s(zQP)" id="id%s(zQP)">
304
+ @ <select aria-label="%h(zLabel)" size="1" name="%s(zQP)" id="id%s(zQP)">
303305
for(i=0; i<nChoice*2; i+=2){
304306
const char *zSel = fossil_strcmp(azChoice[i],z)==0 ? " selected" : "";
305307
@ <option value="%h(azChoice[i])"%s(zSel)>%h(azChoice[i+1])</option>
306308
}
307309
@ </select> <b>%h(zLabel)</b>
@@ -398,11 +400,11 @@
398400
@ <hr />
399401
onoff_attribute("Allow HTTP_AUTHENTICATION authentication",
400402
"http_authentication_ok", "http_authentication_ok", 0, 0);
401403
@ <p>When enabled, allow the use of the HTTP_AUTHENTICATION environment
402404
@ variable or the "Authentication:" HTTP header to find the username and
403
- @ password. This is another way of supporting Basic Authenitication.
405
+ @ password. This is another way of supporting Basic Authentication.
404406
@ (Property: "http_authentication_ok")
405407
@ </p>
406408
@
407409
@ <hr />
408410
entry_attribute("Login expiration time", 6, "cookie-expire", "cex",
@@ -606,25 +608,30 @@
606608
@
607609
@ <form action="%s(g.zTop)/setup_login_group" method="post"><div>
608610
login_insert_csrf_secret();
609611
@ <blockquote><table border="0">
610612
@
611
- @ <tr><th align="right">Repository filename in group to join:</th>
612
- @ <td width="5"></td><td>
613
- @ <input type="text" size="50" value="%h(zRepo)" name="repo"></td></tr>
614
- @
615
- @ <tr><th align="right">Login on the above repo:</th>
616
- @ <td width="5"></td><td>
617
- @ <input type="text" size="20" value="%h(zLogin)" name="login"></td></tr>
618
- @
619
- @ <tr><th align="right">Password:</th>
620
- @ <td width="5"></td><td>
621
- @ <input type="password" size="20" name="pw"></td></tr>
622
- @
623
- @ <tr><th align="right">Name of login-group:</th>
624
- @ <td width="5"></td><td>
625
- @ <input type="text" size="30" value="%h(zNewName)" name="newname">
613
+ @ <tr><th align="right" id="rfigtj">Repository filename \
614
+ @ in group to join:</th>
615
+ @ <td width="5"></td><td>
616
+ @ <input aria-labelledby="rfigtj" type="text" size="50" \
617
+ @ value="%h(zRepo)" name="repo"></td></tr>
618
+ @
619
+ @ <tr><th align="right" id="lotar">Login on the above repo:</th>
620
+ @ <td width="5"></td><td>
621
+ @ <input aria-labelledby="lotar" type="text" size="20" \
622
+ @ value="%h(zLogin)" name="login"></td></tr>
623
+ @
624
+ @ <tr><th align="right" id="lgpw">Password:</th>
625
+ @ <td width="5"></td><td>
626
+ @ <input aria-labelledby="lgpw" type="password" size="20" name="pw">\
627
+ @ </td></tr>
628
+ @
629
+ @ <tr><th align="right" id="nolg">Name of login-group:</th>
630
+ @ <td width="5"></td><td>
631
+ @ <input aria-labelledby="nolg" type="text" size="30" \
632
+ @ value="%h(zNewName)" name="newname">
626633
@ (only used if creating a new login-group).</td></tr>
627634
@
628635
@ <tr><td colspan="3" align="center">
629636
@ <input type="submit" value="Join" name="join"></td></tr>
630637
@ </table></blockquote></div></form>
631638
--- src/setup.c
+++ src/setup.c
@@ -201,16 +201,17 @@
201 admin_log("Set option [%q] to [%q].",
202 zVar, iQ ? "on" : "off");
203 iVal = iQ;
204 }
205 }
206 @ <label><input type="checkbox" name="%s(zQParm)"
 
207 if( iVal ){
208 @ checked="checked"
209 }
210 if( disabled ){
211 @ disabled="disabled"
212 }
213 @ /> <b>%s(zLabel)</b></label>
214 }
215
216 /*
@@ -232,12 +233,12 @@
232 db_set(zVar, zQ, 0);
233 admin_log("Set entry_attribute %Q to: %.*s%s",
234 zVar, 20, zQ, (nZQ>20 ? "..." : ""));
235 zVal = zQ;
236 }
237 @ <input type="text" id="%s(zQParm)" name="%s(zQParm)" value="%h(zVal)" \
238 @ size="%d(width)" \
239 if( disabled ){
240 @ disabled="disabled" \
241 }
242 @ /> <b>%s(zLabel)</b>
243 }
@@ -263,16 +264,17 @@
263 admin_log("Set textarea_attribute %Q to: %.*s%s",
264 zVar, 20, zQ, (nZQ>20 ? "..." : ""));
265 z = zQ;
266 }
267 if( rows>0 && cols>0 ){
268 @ <textarea id="id%s(zQP)" name="%s(zQP)" rows="%d(rows)"
 
269 if( disabled ){
270 @ disabled="disabled"
271 }
272 @ cols="%d(cols)">%h(z)</textarea>
273 if( zLabel && *zLabel ){
274 @ <span class="textareaLabel">%s(zLabel)</span>
275 }
276 }
277 return z;
278 }
@@ -297,11 +299,11 @@
297 db_set(zVar, zQ, 0);
298 admin_log("Set multiple_choice_attribute %Q to: %.*s%s",
299 zVar, 20, zQ, (nZQ>20 ? "..." : ""));
300 z = zQ;
301 }
302 @ <select size="1" name="%s(zQP)" id="id%s(zQP)">
303 for(i=0; i<nChoice*2; i+=2){
304 const char *zSel = fossil_strcmp(azChoice[i],z)==0 ? " selected" : "";
305 @ <option value="%h(azChoice[i])"%s(zSel)>%h(azChoice[i+1])</option>
306 }
307 @ </select> <b>%h(zLabel)</b>
@@ -398,11 +400,11 @@
398 @ <hr />
399 onoff_attribute("Allow HTTP_AUTHENTICATION authentication",
400 "http_authentication_ok", "http_authentication_ok", 0, 0);
401 @ <p>When enabled, allow the use of the HTTP_AUTHENTICATION environment
402 @ variable or the "Authentication:" HTTP header to find the username and
403 @ password. This is another way of supporting Basic Authenitication.
404 @ (Property: "http_authentication_ok")
405 @ </p>
406 @
407 @ <hr />
408 entry_attribute("Login expiration time", 6, "cookie-expire", "cex",
@@ -606,25 +608,30 @@
606 @
607 @ <form action="%s(g.zTop)/setup_login_group" method="post"><div>
608 login_insert_csrf_secret();
609 @ <blockquote><table border="0">
610 @
611 @ <tr><th align="right">Repository filename in group to join:</th>
612 @ <td width="5"></td><td>
613 @ <input type="text" size="50" value="%h(zRepo)" name="repo"></td></tr>
614 @
615 @ <tr><th align="right">Login on the above repo:</th>
616 @ <td width="5"></td><td>
617 @ <input type="text" size="20" value="%h(zLogin)" name="login"></td></tr>
618 @
619 @ <tr><th align="right">Password:</th>
620 @ <td width="5"></td><td>
621 @ <input type="password" size="20" name="pw"></td></tr>
622 @
623 @ <tr><th align="right">Name of login-group:</th>
624 @ <td width="5"></td><td>
625 @ <input type="text" size="30" value="%h(zNewName)" name="newname">
 
 
 
 
 
626 @ (only used if creating a new login-group).</td></tr>
627 @
628 @ <tr><td colspan="3" align="center">
629 @ <input type="submit" value="Join" name="join"></td></tr>
630 @ </table></blockquote></div></form>
631
--- src/setup.c
+++ src/setup.c
@@ -201,16 +201,17 @@
201 admin_log("Set option [%q] to [%q].",
202 zVar, iQ ? "on" : "off");
203 iVal = iQ;
204 }
205 }
206 @ <label><input type="checkbox" name="%s(zQParm)" \
207 @ aria-label="%s(zLabel[0]?zLabel:zQParm)" \
208 if( iVal ){
209 @ checked="checked" \
210 }
211 if( disabled ){
212 @ disabled="disabled" \
213 }
214 @ /> <b>%s(zLabel)</b></label>
215 }
216
217 /*
@@ -232,12 +233,12 @@
233 db_set(zVar, zQ, 0);
234 admin_log("Set entry_attribute %Q to: %.*s%s",
235 zVar, 20, zQ, (nZQ>20 ? "..." : ""));
236 zVal = zQ;
237 }
238 @ <input aria-label="%h(zLabel[0]?zLabel:zQParm)" type="text" \
239 @ id="%s(zQParm)" name="%s(zQParm)" value="%h(zVal)" size="%d(width)" \
240 if( disabled ){
241 @ disabled="disabled" \
242 }
243 @ /> <b>%s(zLabel)</b>
244 }
@@ -263,16 +264,17 @@
264 admin_log("Set textarea_attribute %Q to: %.*s%s",
265 zVar, 20, zQ, (nZQ>20 ? "..." : ""));
266 z = zQ;
267 }
268 if( rows>0 && cols>0 ){
269 @ <textarea id="id%s(zQP)" name="%s(zQP)" rows="%d(rows)" \
270 @ aria-label="%h(zLabel[0]?zLabel:zQP)" \
271 if( disabled ){
272 @ disabled="disabled" \
273 }
274 @ cols="%d(cols)">%h(z)</textarea>
275 if( *zLabel ){
276 @ <span class="textareaLabel">%s(zLabel)</span>
277 }
278 }
279 return z;
280 }
@@ -297,11 +299,11 @@
299 db_set(zVar, zQ, 0);
300 admin_log("Set multiple_choice_attribute %Q to: %.*s%s",
301 zVar, 20, zQ, (nZQ>20 ? "..." : ""));
302 z = zQ;
303 }
304 @ <select aria-label="%h(zLabel)" size="1" name="%s(zQP)" id="id%s(zQP)">
305 for(i=0; i<nChoice*2; i+=2){
306 const char *zSel = fossil_strcmp(azChoice[i],z)==0 ? " selected" : "";
307 @ <option value="%h(azChoice[i])"%s(zSel)>%h(azChoice[i+1])</option>
308 }
309 @ </select> <b>%h(zLabel)</b>
@@ -398,11 +400,11 @@
400 @ <hr />
401 onoff_attribute("Allow HTTP_AUTHENTICATION authentication",
402 "http_authentication_ok", "http_authentication_ok", 0, 0);
403 @ <p>When enabled, allow the use of the HTTP_AUTHENTICATION environment
404 @ variable or the "Authentication:" HTTP header to find the username and
405 @ password. This is another way of supporting Basic Authentication.
406 @ (Property: "http_authentication_ok")
407 @ </p>
408 @
409 @ <hr />
410 entry_attribute("Login expiration time", 6, "cookie-expire", "cex",
@@ -606,25 +608,30 @@
608 @
609 @ <form action="%s(g.zTop)/setup_login_group" method="post"><div>
610 login_insert_csrf_secret();
611 @ <blockquote><table border="0">
612 @
613 @ <tr><th align="right" id="rfigtj">Repository filename \
614 @ in group to join:</th>
615 @ <td width="5"></td><td>
616 @ <input aria-labelledby="rfigtj" type="text" size="50" \
617 @ value="%h(zRepo)" name="repo"></td></tr>
618 @
619 @ <tr><th align="right" id="lotar">Login on the above repo:</th>
620 @ <td width="5"></td><td>
621 @ <input aria-labelledby="lotar" type="text" size="20" \
622 @ value="%h(zLogin)" name="login"></td></tr>
623 @
624 @ <tr><th align="right" id="lgpw">Password:</th>
625 @ <td width="5"></td><td>
626 @ <input aria-labelledby="lgpw" type="password" size="20" name="pw">\
627 @ </td></tr>
628 @
629 @ <tr><th align="right" id="nolg">Name of login-group:</th>
630 @ <td width="5"></td><td>
631 @ <input aria-labelledby="nolg" type="text" size="30" \
632 @ value="%h(zNewName)" name="newname">
633 @ (only used if creating a new login-group).</td></tr>
634 @
635 @ <tr><td colspan="3" align="center">
636 @ <input type="submit" value="Join" name="join"></td></tr>
637 @ </table></blockquote></div></form>
638
+16 -12
--- src/setupuser.c
+++ src/setupuser.c
@@ -534,24 +534,27 @@
534534
@ <input type="hidden" name="pw" value="*">
535535
}
536536
@ <input type="hidden" name="referer" value="%h(cgi_referer("setup_ulist"))">
537537
@ <table width="100%%">
538538
@ <tr>
539
- @ <td class="usetupEditLabel">User ID:</td>
539
+ @ <td class="usetupEditLabel" id="suuid">User ID:</td>
540540
if( uid ){
541
- @ <td>%d(uid) <input type="hidden" name="id" value="%d(uid)" />\
541
+ @ <td>%d(uid) <input aria-labelledby="suuid" type="hidden" \
542
+ @ name="id" value="%d(uid)"/>\
542543
@ </td>
543544
}else{
544
- @ <td>(new user)<input type="hidden" name="id" value="0" /></td>
545
+ @ <td>(new user)<input aria-labelledby="suuid" type="hidden" name="id" \
546
+ @ value="0" /></td>
545547
}
546548
@ </tr>
547549
@ <tr>
548
- @ <td class="usetupEditLabel">Login:</td>
550
+ @ <td class="usetupEditLabel" id="sulgn">Login:</td>
549551
if( login_is_special(zLogin) ){
550552
@ <td><b>%h(zLogin)</b></td>
551553
}else{
552
- @ <td><input type="text" name="login" value="%h(zLogin)" />\
554
+ @ <td><input aria-labelledby="sulgn" type="text" name="login" \
555
+ @ value="%h(zLogin)" />
553556
if( alert_tables_exist() ){
554557
int sid;
555558
sid = db_int(0, "SELECT subscriberId FROM subscriber"
556559
" WHERE suname=%Q", zLogin);
557560
if( sid>0 ){
@@ -559,12 +562,13 @@
559562
@ (subscription info for %h(zLogin))</a>\
560563
}
561564
}
562565
@ </td></tr>
563566
@ <tr>
564
- @ <td class="usetupEditLabel">Contact&nbsp;Info:</td>
565
- @ <td><textarea name="info" cols="40" rows="2">%h(zInfo)</textarea></td>
567
+ @ <td class="usetupEditLabel" id="sucnfo">Contact&nbsp;Info:</td>
568
+ @ <td><textarea aria-labelledby="sucnfo" name="info" cols="40" \
569
+ @ rows="2">%h(zInfo)</textarea></td>
566570
}
567571
@ </tr>
568572
@ <tr>
569573
@ <td class="usetupEditLabel">Capabilities:</td>
570574
@ <td width="100%%">
@@ -653,19 +657,19 @@
653657
@ <a href="%R/setup_ucap_list">(key)</a>
654658
@ </td>
655659
@ </tr>
656660
if( !login_is_special(zLogin) ){
657661
@ <tr>
658
- @ <td align="right">Password:</td>
662
+ @ <td align="right" id="supw">Password:</td>
659663
if( zPw[0] ){
660664
/* Obscure the password for all users */
661
- @ <td><input type="password" autocomplete="off" name="pw"\
662
- @ value="**********" /></td>
665
+ @ <td><input aria-labelledby="supw" type="password" autocomplete="off" \
666
+ @ name="pw" value="**********" /></td>
663667
}else{
664668
/* Show an empty password as an empty input field */
665
- @ <td><input type="password" autocomplete="off" name="pw"\
666
- @ value="" /></td>
669
+ @ <td><input aria-labelledby="supw" type="password" name="pw" \
670
+ @ autocomplete="off" value="" /></td>
667671
}
668672
@ </tr>
669673
}
670674
zGroup = login_group_name();
671675
if( zGroup ){
672676
--- src/setupuser.c
+++ src/setupuser.c
@@ -534,24 +534,27 @@
534 @ <input type="hidden" name="pw" value="*">
535 }
536 @ <input type="hidden" name="referer" value="%h(cgi_referer("setup_ulist"))">
537 @ <table width="100%%">
538 @ <tr>
539 @ <td class="usetupEditLabel">User ID:</td>
540 if( uid ){
541 @ <td>%d(uid) <input type="hidden" name="id" value="%d(uid)" />\
 
542 @ </td>
543 }else{
544 @ <td>(new user)<input type="hidden" name="id" value="0" /></td>
 
545 }
546 @ </tr>
547 @ <tr>
548 @ <td class="usetupEditLabel">Login:</td>
549 if( login_is_special(zLogin) ){
550 @ <td><b>%h(zLogin)</b></td>
551 }else{
552 @ <td><input type="text" name="login" value="%h(zLogin)" />\
 
553 if( alert_tables_exist() ){
554 int sid;
555 sid = db_int(0, "SELECT subscriberId FROM subscriber"
556 " WHERE suname=%Q", zLogin);
557 if( sid>0 ){
@@ -559,12 +562,13 @@
559 @ (subscription info for %h(zLogin))</a>\
560 }
561 }
562 @ </td></tr>
563 @ <tr>
564 @ <td class="usetupEditLabel">Contact&nbsp;Info:</td>
565 @ <td><textarea name="info" cols="40" rows="2">%h(zInfo)</textarea></td>
 
566 }
567 @ </tr>
568 @ <tr>
569 @ <td class="usetupEditLabel">Capabilities:</td>
570 @ <td width="100%%">
@@ -653,19 +657,19 @@
653 @ <a href="%R/setup_ucap_list">(key)</a>
654 @ </td>
655 @ </tr>
656 if( !login_is_special(zLogin) ){
657 @ <tr>
658 @ <td align="right">Password:</td>
659 if( zPw[0] ){
660 /* Obscure the password for all users */
661 @ <td><input type="password" autocomplete="off" name="pw"\
662 @ value="**********" /></td>
663 }else{
664 /* Show an empty password as an empty input field */
665 @ <td><input type="password" autocomplete="off" name="pw"\
666 @ value="" /></td>
667 }
668 @ </tr>
669 }
670 zGroup = login_group_name();
671 if( zGroup ){
672
--- src/setupuser.c
+++ src/setupuser.c
@@ -534,24 +534,27 @@
534 @ <input type="hidden" name="pw" value="*">
535 }
536 @ <input type="hidden" name="referer" value="%h(cgi_referer("setup_ulist"))">
537 @ <table width="100%%">
538 @ <tr>
539 @ <td class="usetupEditLabel" id="suuid">User ID:</td>
540 if( uid ){
541 @ <td>%d(uid) <input aria-labelledby="suuid" type="hidden" \
542 @ name="id" value="%d(uid)"/>\
543 @ </td>
544 }else{
545 @ <td>(new user)<input aria-labelledby="suuid" type="hidden" name="id" \
546 @ value="0" /></td>
547 }
548 @ </tr>
549 @ <tr>
550 @ <td class="usetupEditLabel" id="sulgn">Login:</td>
551 if( login_is_special(zLogin) ){
552 @ <td><b>%h(zLogin)</b></td>
553 }else{
554 @ <td><input aria-labelledby="sulgn" type="text" name="login" \
555 @ value="%h(zLogin)" />
556 if( alert_tables_exist() ){
557 int sid;
558 sid = db_int(0, "SELECT subscriberId FROM subscriber"
559 " WHERE suname=%Q", zLogin);
560 if( sid>0 ){
@@ -559,12 +562,13 @@
562 @ (subscription info for %h(zLogin))</a>\
563 }
564 }
565 @ </td></tr>
566 @ <tr>
567 @ <td class="usetupEditLabel" id="sucnfo">Contact&nbsp;Info:</td>
568 @ <td><textarea aria-labelledby="sucnfo" name="info" cols="40" \
569 @ rows="2">%h(zInfo)</textarea></td>
570 }
571 @ </tr>
572 @ <tr>
573 @ <td class="usetupEditLabel">Capabilities:</td>
574 @ <td width="100%%">
@@ -653,19 +657,19 @@
657 @ <a href="%R/setup_ucap_list">(key)</a>
658 @ </td>
659 @ </tr>
660 if( !login_is_special(zLogin) ){
661 @ <tr>
662 @ <td align="right" id="supw">Password:</td>
663 if( zPw[0] ){
664 /* Obscure the password for all users */
665 @ <td><input aria-labelledby="supw" type="password" autocomplete="off" \
666 @ name="pw" value="**********" /></td>
667 }else{
668 /* Show an empty password as an empty input field */
669 @ <td><input aria-labelledby="supw" type="password" name="pw" \
670 @ autocomplete="off" value="" /></td>
671 }
672 @ </tr>
673 }
674 zGroup = login_group_name();
675 if( zGroup ){
676
+5 -2
--- src/shell.c
+++ src/shell.c
@@ -7998,13 +7998,16 @@
79987998
while( rc==SQLITE_OK && sqlite3_step(pExplain)==SQLITE_ROW ){
79997999
/* int iId = sqlite3_column_int(pExplain, 0); */
80008000
/* int iParent = sqlite3_column_int(pExplain, 1); */
80018001
/* int iNotUsed = sqlite3_column_int(pExplain, 2); */
80028002
const char *zDetail = (const char*)sqlite3_column_text(pExplain, 3);
8003
- int nDetail = STRLEN(zDetail);
8003
+ int nDetail;
80048004
int i;
80058005
8006
+ if( !zDetail ) continue;
8007
+ nDetail = STRLEN(zDetail);
8008
+
80068009
for(i=0; i<nDetail; i++){
80078010
const char *zIdx = 0;
80088011
if( memcmp(&zDetail[i], " USING INDEX ", 13)==0 ){
80098012
zIdx = &zDetail[i+13];
80108013
}else if( memcmp(&zDetail[i], " USING COVERING INDEX ", 22)==0 ){
@@ -8820,11 +8823,11 @@
88208823
sqlite3_free(p->zCandidates);
88218824
sqlite3_free(p);
88228825
}
88238826
}
88248827
8825
-#endif /* ifndef SQLITE_OMIT_VIRTUAL_TABLE */
8828
+#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
88268829
88278830
/************************* End ../ext/expert/sqlite3expert.c ********************/
88288831
88298832
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
88308833
/************************* Begin ../ext/misc/dbdata.c ******************/
88318834
--- src/shell.c
+++ src/shell.c
@@ -7998,13 +7998,16 @@
7998 while( rc==SQLITE_OK && sqlite3_step(pExplain)==SQLITE_ROW ){
7999 /* int iId = sqlite3_column_int(pExplain, 0); */
8000 /* int iParent = sqlite3_column_int(pExplain, 1); */
8001 /* int iNotUsed = sqlite3_column_int(pExplain, 2); */
8002 const char *zDetail = (const char*)sqlite3_column_text(pExplain, 3);
8003 int nDetail = STRLEN(zDetail);
8004 int i;
8005
 
 
 
8006 for(i=0; i<nDetail; i++){
8007 const char *zIdx = 0;
8008 if( memcmp(&zDetail[i], " USING INDEX ", 13)==0 ){
8009 zIdx = &zDetail[i+13];
8010 }else if( memcmp(&zDetail[i], " USING COVERING INDEX ", 22)==0 ){
@@ -8820,11 +8823,11 @@
8820 sqlite3_free(p->zCandidates);
8821 sqlite3_free(p);
8822 }
8823 }
8824
8825 #endif /* ifndef SQLITE_OMIT_VIRTUAL_TABLE */
8826
8827 /************************* End ../ext/expert/sqlite3expert.c ********************/
8828
8829 #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
8830 /************************* Begin ../ext/misc/dbdata.c ******************/
8831
--- src/shell.c
+++ src/shell.c
@@ -7998,13 +7998,16 @@
7998 while( rc==SQLITE_OK && sqlite3_step(pExplain)==SQLITE_ROW ){
7999 /* int iId = sqlite3_column_int(pExplain, 0); */
8000 /* int iParent = sqlite3_column_int(pExplain, 1); */
8001 /* int iNotUsed = sqlite3_column_int(pExplain, 2); */
8002 const char *zDetail = (const char*)sqlite3_column_text(pExplain, 3);
8003 int nDetail;
8004 int i;
8005
8006 if( !zDetail ) continue;
8007 nDetail = STRLEN(zDetail);
8008
8009 for(i=0; i<nDetail; i++){
8010 const char *zIdx = 0;
8011 if( memcmp(&zDetail[i], " USING INDEX ", 13)==0 ){
8012 zIdx = &zDetail[i+13];
8013 }else if( memcmp(&zDetail[i], " USING COVERING INDEX ", 22)==0 ){
@@ -8820,11 +8823,11 @@
8823 sqlite3_free(p->zCandidates);
8824 sqlite3_free(p);
8825 }
8826 }
8827
8828 #endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
8829
8830 /************************* End ../ext/expert/sqlite3expert.c ********************/
8831
8832 #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
8833 /************************* Begin ../ext/misc/dbdata.c ******************/
8834
+2 -2
--- src/shun.c
+++ src/shun.c
@@ -187,11 +187,11 @@
187187
@ sight - set the "hidden" tag on such artifacts instead.</p>
188188
@
189189
@ <blockquote>
190190
@ <form method="post" action="%s(g.zTop)/%s(g.zPath)"><div>
191191
login_insert_csrf_secret();
192
- @ <textarea class="fullsize-text" cols="50" rows="%d(numRows)" name="uuid">
192
+ @ <textarea class="fullsize-text" cols="70" rows="%d(numRows)" name="uuid">
193193
if( zShun ){
194194
if( strlen(zShun) ){
195195
@ %h(zShun)
196196
}else if( nRcvid ){
197197
db_prepare(&q, "SELECT uuid FROM blob WHERE rcvid=%d", nRcvid);
@@ -214,11 +214,11 @@
214214
@ operations.</p>
215215
@
216216
@ <blockquote>
217217
@ <form method="post" action="%s(g.zTop)/%s(g.zPath)"><div>
218218
login_insert_csrf_secret();
219
- @ <textarea class="fullsize-text" cols="50" rows="%d(numRows)" name="uuid">
219
+ @ <textarea class="fullsize-text" cols="70" rows="%d(numRows)" name="uuid">
220220
if( zAccept ){
221221
if( strlen(zAccept) ){
222222
@ %h(zAccept)
223223
}else if( nRcvid ){
224224
db_prepare(&q, "SELECT uuid FROM blob WHERE rcvid=%d", nRcvid);
225225
--- src/shun.c
+++ src/shun.c
@@ -187,11 +187,11 @@
187 @ sight - set the "hidden" tag on such artifacts instead.</p>
188 @
189 @ <blockquote>
190 @ <form method="post" action="%s(g.zTop)/%s(g.zPath)"><div>
191 login_insert_csrf_secret();
192 @ <textarea class="fullsize-text" cols="50" rows="%d(numRows)" name="uuid">
193 if( zShun ){
194 if( strlen(zShun) ){
195 @ %h(zShun)
196 }else if( nRcvid ){
197 db_prepare(&q, "SELECT uuid FROM blob WHERE rcvid=%d", nRcvid);
@@ -214,11 +214,11 @@
214 @ operations.</p>
215 @
216 @ <blockquote>
217 @ <form method="post" action="%s(g.zTop)/%s(g.zPath)"><div>
218 login_insert_csrf_secret();
219 @ <textarea class="fullsize-text" cols="50" rows="%d(numRows)" name="uuid">
220 if( zAccept ){
221 if( strlen(zAccept) ){
222 @ %h(zAccept)
223 }else if( nRcvid ){
224 db_prepare(&q, "SELECT uuid FROM blob WHERE rcvid=%d", nRcvid);
225
--- src/shun.c
+++ src/shun.c
@@ -187,11 +187,11 @@
187 @ sight - set the "hidden" tag on such artifacts instead.</p>
188 @
189 @ <blockquote>
190 @ <form method="post" action="%s(g.zTop)/%s(g.zPath)"><div>
191 login_insert_csrf_secret();
192 @ <textarea class="fullsize-text" cols="70" rows="%d(numRows)" name="uuid">
193 if( zShun ){
194 if( strlen(zShun) ){
195 @ %h(zShun)
196 }else if( nRcvid ){
197 db_prepare(&q, "SELECT uuid FROM blob WHERE rcvid=%d", nRcvid);
@@ -214,11 +214,11 @@
214 @ operations.</p>
215 @
216 @ <blockquote>
217 @ <form method="post" action="%s(g.zTop)/%s(g.zPath)"><div>
218 login_insert_csrf_secret();
219 @ <textarea class="fullsize-text" cols="70" rows="%d(numRows)" name="uuid">
220 if( zAccept ){
221 if( strlen(zAccept) ){
222 @ %h(zAccept)
223 }else if( nRcvid ){
224 db_prepare(&q, "SELECT uuid FROM blob WHERE rcvid=%d", nRcvid);
225
+7 -2
--- src/skins.c
+++ src/skins.c
@@ -281,10 +281,13 @@
281281
** Return an identifier that is (probably) different for every skin
282282
** but that is (probably) the same if the skin is unchanged. This
283283
** identifier can be attached to resource URLs to force reloading when
284284
** the resources change but allow the resources to be read from cache
285285
** as long as they are unchanged.
286
+**
287
+** The zResource argument is the name of a CONFIG setting that
288
+** defines the resource. Examples: "css", "logo-image".
286289
*/
287290
unsigned int skin_id(const char *zResource){
288291
unsigned int h = 0;
289292
if( zAltSkinDir ){
290293
h = skin_hash(0, zAltSkinDir);
@@ -293,11 +296,13 @@
293296
}else{
294297
char *zMTime = db_get_mtime(zResource, 0, 0);
295298
h = skin_hash(0, zMTime);
296299
fossil_free(zMTime);
297300
}
298
- h = skin_hash(h, MANIFEST_UUID);
301
+
302
+ /* Change the ID every time Fossil is recompiled */
303
+ h = skin_hash(h, fossil_exe_id());
299304
return h;
300305
}
301306
302307
/*
303308
** For a skin named zSkinName, compute the name of the CONFIG table
@@ -1117,11 +1122,11 @@
11171122
if( !g.perm.Admin ){
11181123
@ <p>Only administrators are allowed to publish draft skins. Contact
11191124
@ an administrator to get this "draft%d(iSkin)" skin published.</p>
11201125
}else{
11211126
@ <p>When the draft%d(iSkin) skin is ready for production use,
1122
- @ make it the default scan by clicking the acknowledgements and
1127
+ @ make it the default skin by clicking the acknowledgements and
11231128
@ pressing the button below:</p>
11241129
@
11251130
@ <form method='POST' action='%R/setup_skin#step7'>
11261131
@ <p class='skinInput'>
11271132
@ <input type='hidden' name='sk' value='%d(iSkin)'>
11281133
--- src/skins.c
+++ src/skins.c
@@ -281,10 +281,13 @@
281 ** Return an identifier that is (probably) different for every skin
282 ** but that is (probably) the same if the skin is unchanged. This
283 ** identifier can be attached to resource URLs to force reloading when
284 ** the resources change but allow the resources to be read from cache
285 ** as long as they are unchanged.
 
 
 
286 */
287 unsigned int skin_id(const char *zResource){
288 unsigned int h = 0;
289 if( zAltSkinDir ){
290 h = skin_hash(0, zAltSkinDir);
@@ -293,11 +296,13 @@
293 }else{
294 char *zMTime = db_get_mtime(zResource, 0, 0);
295 h = skin_hash(0, zMTime);
296 fossil_free(zMTime);
297 }
298 h = skin_hash(h, MANIFEST_UUID);
 
 
299 return h;
300 }
301
302 /*
303 ** For a skin named zSkinName, compute the name of the CONFIG table
@@ -1117,11 +1122,11 @@
1117 if( !g.perm.Admin ){
1118 @ <p>Only administrators are allowed to publish draft skins. Contact
1119 @ an administrator to get this "draft%d(iSkin)" skin published.</p>
1120 }else{
1121 @ <p>When the draft%d(iSkin) skin is ready for production use,
1122 @ make it the default scan by clicking the acknowledgements and
1123 @ pressing the button below:</p>
1124 @
1125 @ <form method='POST' action='%R/setup_skin#step7'>
1126 @ <p class='skinInput'>
1127 @ <input type='hidden' name='sk' value='%d(iSkin)'>
1128
--- src/skins.c
+++ src/skins.c
@@ -281,10 +281,13 @@
281 ** Return an identifier that is (probably) different for every skin
282 ** but that is (probably) the same if the skin is unchanged. This
283 ** identifier can be attached to resource URLs to force reloading when
284 ** the resources change but allow the resources to be read from cache
285 ** as long as they are unchanged.
286 **
287 ** The zResource argument is the name of a CONFIG setting that
288 ** defines the resource. Examples: "css", "logo-image".
289 */
290 unsigned int skin_id(const char *zResource){
291 unsigned int h = 0;
292 if( zAltSkinDir ){
293 h = skin_hash(0, zAltSkinDir);
@@ -293,11 +296,13 @@
296 }else{
297 char *zMTime = db_get_mtime(zResource, 0, 0);
298 h = skin_hash(0, zMTime);
299 fossil_free(zMTime);
300 }
301
302 /* Change the ID every time Fossil is recompiled */
303 h = skin_hash(h, fossil_exe_id());
304 return h;
305 }
306
307 /*
308 ** For a skin named zSkinName, compute the name of the CONFIG table
@@ -1117,11 +1122,11 @@
1122 if( !g.perm.Admin ){
1123 @ <p>Only administrators are allowed to publish draft skins. Contact
1124 @ an administrator to get this "draft%d(iSkin)" skin published.</p>
1125 }else{
1126 @ <p>When the draft%d(iSkin) skin is ready for production use,
1127 @ make it the default skin by clicking the acknowledgements and
1128 @ pressing the button below:</p>
1129 @
1130 @ <form method='POST' action='%R/setup_skin#step7'>
1131 @ <p class='skinInput'>
1132 @ <input type='hidden' name='sk' value='%d(iSkin)'>
1133
+175 -92
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -1162,11 +1162,11 @@
11621162
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
11631163
** [sqlite_version()] and [sqlite_source_id()].
11641164
*/
11651165
#define SQLITE_VERSION "3.32.0"
11661166
#define SQLITE_VERSION_NUMBER 3032000
1167
-#define SQLITE_SOURCE_ID "2020-05-08 19:02:21 3a16c0ce4d8851f79f670d94786032c8007619154ece44647dc9cc5b1f9654ff"
1167
+#define SQLITE_SOURCE_ID "2020-05-19 15:51:10 3117c1b5a9e348fd8d16ba9d03fdafaad8514567fb3403f72b86d6162ad40bde"
11681168
11691169
/*
11701170
** CAPI3REF: Run-Time Library Version Numbers
11711171
** KEYWORDS: sqlite3_version sqlite3_sourceid
11721172
**
@@ -6532,11 +6532,11 @@
65326532
** when first called if N is less than or equal to zero or if a memory
65336533
** allocate error occurs.
65346534
**
65356535
** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is
65366536
** determined by the N parameter on first successful call. Changing the
6537
-** value of N in any subsequents call to sqlite3_aggregate_context() within
6537
+** value of N in any subsequent call to sqlite3_aggregate_context() within
65386538
** the same aggregate function instance will not resize the memory
65396539
** allocation.)^ Within the xFinal callback, it is customary to set
65406540
** N=0 in calls to sqlite3_aggregate_context(C,N) so that no
65416541
** pointless memory allocations occur.
65426542
**
@@ -17119,11 +17119,11 @@
1711917119
#define SQLITE_FUNC_EPHEM 0x0010 /* Ephemeral. Delete with VDBE */
1712017120
#define SQLITE_FUNC_NEEDCOLL 0x0020 /* sqlite3GetFuncCollSeq() might be called*/
1712117121
#define SQLITE_FUNC_LENGTH 0x0040 /* Built-in length() function */
1712217122
#define SQLITE_FUNC_TYPEOF 0x0080 /* Built-in typeof() function */
1712317123
#define SQLITE_FUNC_COUNT 0x0100 /* Built-in count(*) aggregate */
17124
-#define SQLITE_FUNC_COALESCE 0x0200 /* Built-in coalesce() or ifnull() */
17124
+/* 0x0200 -- available for reuse */
1712517125
#define SQLITE_FUNC_UNLIKELY 0x0400 /* Built-in unlikely() function */
1712617126
#define SQLITE_FUNC_CONSTANT 0x0800 /* Constant inputs give a constant output */
1712717127
#define SQLITE_FUNC_MINMAX 0x1000 /* True for min() and max() aggregates */
1712817128
#define SQLITE_FUNC_SLOCHNG 0x2000 /* "Slow Change". Value constant during a
1712917129
** single query - might change over time */
@@ -17140,10 +17140,11 @@
1714017140
#define INLINEFUNC_coalesce 0
1714117141
#define INLINEFUNC_implies_nonnull_row 1
1714217142
#define INLINEFUNC_expr_implies_expr 2
1714317143
#define INLINEFUNC_expr_compare 3
1714417144
#define INLINEFUNC_affinity 4
17145
+#define INLINEFUNC_iif 5
1714517146
#define INLINEFUNC_unlikely 99 /* Default case */
1714617147
1714717148
/*
1714817149
** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
1714917150
** used to create the initializers for the FuncDef structures.
@@ -20064,12 +20065,14 @@
2006420065
# define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0)
2006520066
#endif
2006620067
SQLITE_PRIVATE int sqlite3ReadOnlyShadowTables(sqlite3 *db);
2006720068
#ifndef SQLITE_OMIT_VIRTUALTABLE
2006820069
SQLITE_PRIVATE int sqlite3ShadowTableName(sqlite3 *db, const char *zName);
20070
+SQLITE_PRIVATE int sqlite3IsShadowTableOf(sqlite3*,Table*,const char*);
2006920071
#else
2007020072
# define sqlite3ShadowTableName(A,B) 0
20073
+# define sqlite3IsShadowTableOf(A,B,C) 0
2007120074
#endif
2007220075
SQLITE_PRIVATE int sqlite3VtabEponymousTableInit(Parse*,Module*);
2007320076
SQLITE_PRIVATE void sqlite3VtabEponymousTableClear(sqlite3*,Module*);
2007420077
SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse*,Table*);
2007520078
SQLITE_PRIVATE void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*, int);
@@ -27924,11 +27927,11 @@
2792427927
}
2792527928
}else{
2792627929
assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
2792727930
assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
2792827931
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
27929
- pNew = sqlite3_realloc64(p, n);
27932
+ pNew = sqlite3Realloc(p, n);
2793027933
if( !pNew ){
2793127934
sqlite3OomFault(db);
2793227935
}
2793327936
sqlite3MemdebugSetType(pNew,
2793427937
(db->lookaside.bDisable==0 ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
@@ -29001,11 +29004,11 @@
2900129004
p->nAlloc = (int)szNew;
2900229005
}
2900329006
if( p->db ){
2900429007
zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc);
2900529008
}else{
29006
- zNew = sqlite3_realloc64(zOld, p->nAlloc);
29009
+ zNew = sqlite3Realloc(zOld, p->nAlloc);
2900729010
}
2900829011
if( zNew ){
2900929012
assert( p->zText!=0 || p->nChar==0 );
2901029013
if( !isMalloced(p) && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
2901129014
p->zText = zNew;
@@ -29343,11 +29346,11 @@
2934329346
** and segfaults if you give it a long long int.
2934429347
*/
2934529348
SQLITE_PRIVATE void sqlite3DebugPrintf(const char *zFormat, ...){
2934629349
va_list ap;
2934729350
StrAccum acc;
29348
- char zBuf[500];
29351
+ char zBuf[SQLITE_PRINT_BUF_SIZE*10];
2934929352
sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
2935029353
va_start(ap,zFormat);
2935129354
sqlite3_str_vappendf(&acc, zFormat, ap);
2935229355
va_end(ap);
2935329356
sqlite3StrAccumFinish(&acc);
@@ -45048,10 +45051,11 @@
4504845051
}
4504945052
4505045053
/* Forward references to VFS helper methods used for temporary files */
4505145054
static int winGetTempname(sqlite3_vfs *, char **);
4505245055
static int winIsDir(const void *);
45056
+static BOOL winIsLongPathPrefix(const char *);
4505345057
static BOOL winIsDriveLetterAndColon(const char *);
4505445058
4505545059
/*
4505645060
** Control and query of the open file handle.
4505745061
*/
@@ -46817,11 +46821,13 @@
4681746821
pFile->pVfs = pVfs;
4681846822
pFile->h = h;
4681946823
if( isReadonly ){
4682046824
pFile->ctrlFlags |= WINFILE_RDONLY;
4682146825
}
46822
- if( sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) ){
46826
+ if( (flags & SQLITE_OPEN_MAIN_DB)
46827
+ && sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE)
46828
+ ){
4682346829
pFile->ctrlFlags |= WINFILE_PSOW;
4682446830
}
4682546831
pFile->lastErrno = NO_ERROR;
4682646832
pFile->zPath = zName;
4682746833
#if SQLITE_MAX_MMAP_SIZE>0
@@ -47026,10 +47032,21 @@
4702647032
*pResOut = rc;
4702747033
OSTRACE(("ACCESS name=%s, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n",
4702847034
zFilename, pResOut, *pResOut));
4702947035
return SQLITE_OK;
4703047036
}
47037
+
47038
+/*
47039
+** Returns non-zero if the specified path name starts with the "long path"
47040
+** prefix.
47041
+*/
47042
+static BOOL winIsLongPathPrefix(
47043
+ const char *zPathname
47044
+){
47045
+ return ( zPathname[0]=='\\' && zPathname[1]=='\\'
47046
+ && zPathname[2]=='?' && zPathname[3]=='\\' );
47047
+}
4703147048
4703247049
/*
4703347050
** Returns non-zero if the specified path name starts with a drive letter
4703447051
** followed by a colon character.
4703547052
*/
@@ -47091,14 +47108,15 @@
4709147108
DWORD nByte;
4709247109
void *zConverted;
4709347110
char *zOut;
4709447111
#endif
4709547112
47096
- /* If this path name begins with "/X:", where "X" is any alphabetic
47097
- ** character, discard the initial "/" from the pathname.
47113
+ /* If this path name begins with "/X:" or "\\?\", where "X" is any
47114
+ ** alphabetic character, discard the initial "/" from the pathname.
4709847115
*/
47099
- if( zRelative[0]=='/' && winIsDriveLetterAndColon(zRelative+1) ){
47116
+ if( zRelative[0]=='/' && (winIsDriveLetterAndColon(zRelative+1)
47117
+ || winIsLongPathPrefix(zRelative+1)) ){
4710047118
zRelative++;
4710147119
}
4710247120
4710347121
#if defined(__CYGWIN__)
4710447122
SimulateIOError( return SQLITE_ERROR );
@@ -47850,11 +47868,11 @@
4785047868
if( newSz>p->szMax ){
4785147869
return SQLITE_FULL;
4785247870
}
4785347871
newSz *= 2;
4785447872
if( newSz>p->szMax ) newSz = p->szMax;
47855
- pNew = sqlite3_realloc64(p->aData, newSz);
47873
+ pNew = sqlite3Realloc(p->aData, newSz);
4785647874
if( pNew==0 ) return SQLITE_NOMEM;
4785747875
p->aData = pNew;
4785847876
p->szAlloc = newSz;
4785947877
return SQLITE_OK;
4786047878
}
@@ -59820,11 +59838,11 @@
5982059838
5982159839
/* Enlarge the pWal->apWiData[] array if required */
5982259840
if( pWal->nWiData<=iPage ){
5982359841
sqlite3_int64 nByte = sizeof(u32*)*(iPage+1);
5982459842
volatile u32 **apNew;
59825
- apNew = (volatile u32 **)sqlite3_realloc64((void *)pWal->apWiData, nByte);
59843
+ apNew = (volatile u32 **)sqlite3Realloc((void *)pWal->apWiData, nByte);
5982659844
if( !apNew ){
5982759845
*ppPage = 0;
5982859846
return SQLITE_NOMEM_BKPT;
5982959847
}
5983059848
memset((void*)&apNew[pWal->nWiData], 0,
@@ -59941,29 +59959,47 @@
5994159959
5994259960
aOut[0] = s1;
5994359961
aOut[1] = s2;
5994459962
}
5994559963
59964
+/*
59965
+** If there is the possibility of concurrent access to the SHM file
59966
+** from multiple threads and/or processes, then do a memory barrier.
59967
+*/
5994659968
static void walShmBarrier(Wal *pWal){
5994759969
if( pWal->exclusiveMode!=WAL_HEAPMEMORY_MODE ){
5994859970
sqlite3OsShmBarrier(pWal->pDbFd);
5994959971
}
5995059972
}
5995159973
59974
+/*
59975
+** Add the SQLITE_NO_TSAN as part of the return-type of a function
59976
+** definition as a hint that the function contains constructs that
59977
+** might give false-positive TSAN warnings.
59978
+**
59979
+** See tag-20200519-1.
59980
+*/
59981
+#if defined(__clang__) && !defined(SQLITE_NO_TSAN)
59982
+# define SQLITE_NO_TSAN __attribute__((no_sanitize_thread))
59983
+#else
59984
+# define SQLITE_NO_TSAN
59985
+#endif
59986
+
5995259987
/*
5995359988
** Write the header information in pWal->hdr into the wal-index.
5995459989
**
5995559990
** The checksum on pWal->hdr is updated before it is written.
5995659991
*/
59957
-static void walIndexWriteHdr(Wal *pWal){
59992
+static SQLITE_NO_TSAN void walIndexWriteHdr(Wal *pWal){
5995859993
volatile WalIndexHdr *aHdr = walIndexHdr(pWal);
5995959994
const int nCksum = offsetof(WalIndexHdr, aCksum);
5996059995
5996159996
assert( pWal->writeLock );
5996259997
pWal->hdr.isInit = 1;
5996359998
pWal->hdr.iVersion = WALINDEX_MAX_VERSION;
5996459999
walChecksumBytes(1, (u8*)&pWal->hdr, nCksum, 0, pWal->hdr.aCksum);
60000
+ /* Possible TSAN false-positive. See tag-20200519-1 */
5996560001
memcpy((void*)&aHdr[1], (const void*)&pWal->hdr, sizeof(WalIndexHdr));
5996660002
walShmBarrier(pWal);
5996760003
memcpy((void*)&aHdr[0], (const void*)&pWal->hdr, sizeof(WalIndexHdr));
5996860004
}
5996960005
@@ -61074,11 +61110,11 @@
6107461110
pWal->nCkpt++;
6107561111
pWal->hdr.mxFrame = 0;
6107661112
sqlite3Put4byte((u8*)&aSalt[0], 1 + sqlite3Get4byte((u8*)&aSalt[0]));
6107761113
memcpy(&pWal->hdr.aSalt[1], &salt1, 4);
6107861114
walIndexWriteHdr(pWal);
61079
- pInfo->nBackfill = 0;
61115
+ AtomicStore(&pInfo->nBackfill, 0);
6108061116
pInfo->nBackfillAttempted = 0;
6108161117
pInfo->aReadMark[1] = 0;
6108261118
for(i=2; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED;
6108361119
assert( pInfo->aReadMark[0]==0 );
6108461120
}
@@ -61149,36 +61185,17 @@
6114961185
** cannot be backfilled from the WAL.
6115061186
*/
6115161187
mxSafeFrame = pWal->hdr.mxFrame;
6115261188
mxPage = pWal->hdr.nPage;
6115361189
for(i=1; i<WAL_NREADER; i++){
61154
- /* Thread-sanitizer reports that the following is an unsafe read,
61155
- ** as some other thread may be in the process of updating the value
61156
- ** of the aReadMark[] slot. The assumption here is that if that is
61157
- ** happening, the other client may only be increasing the value,
61158
- ** not decreasing it. So assuming either that either the "old" or
61159
- ** "new" version of the value is read, and not some arbitrary value
61160
- ** that would never be written by a real client, things are still
61161
- ** safe.
61162
- **
61163
- ** Astute readers have pointed out that the assumption stated in the
61164
- ** last sentence of the previous paragraph is not guaranteed to be
61165
- ** true for all conforming systems. However, the assumption is true
61166
- ** for all compilers and architectures in common use today (circa
61167
- ** 2019-11-27) and the alternatives are both slow and complex, and
61168
- ** so we will continue to go with the current design for now. If this
61169
- ** bothers you, or if you really are running on a system where aligned
61170
- ** 32-bit reads and writes are not atomic, then you can simply avoid
61171
- ** the use of WAL mode, or only use WAL mode together with
61172
- ** PRAGMA locking_mode=EXCLUSIVE and all will be well.
61173
- */
61174
- u32 y = pInfo->aReadMark[i];
61190
+ u32 y = AtomicLoad(pInfo->aReadMark+i);
6117561191
if( mxSafeFrame>y ){
6117661192
assert( y<=pWal->hdr.mxFrame );
6117761193
rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1);
6117861194
if( rc==SQLITE_OK ){
61179
- pInfo->aReadMark[i] = (i==1 ? mxSafeFrame : READMARK_NOT_USED);
61195
+ u32 iMark = (i==1 ? mxSafeFrame : READMARK_NOT_USED);
61196
+ AtomicStore(pInfo->aReadMark+i, iMark);
6118061197
walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
6118161198
}else if( rc==SQLITE_BUSY ){
6118261199
mxSafeFrame = y;
6118361200
xBusy = 0;
6118461201
}else{
@@ -61192,11 +61209,11 @@
6119261209
rc = walIteratorInit(pWal, pInfo->nBackfill, &pIter);
6119361210
assert( rc==SQLITE_OK || pIter==0 );
6119461211
}
6119561212
6119661213
if( pIter
61197
- && (rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(0),1))==SQLITE_OK
61214
+ && (rc = walBusyLock(pWal,xBusy,pBusyArg,WAL_READ_LOCK(0),1))==SQLITE_OK
6119861215
){
6119961216
u32 nBackfill = pInfo->nBackfill;
6120061217
6120161218
pInfo->nBackfillAttempted = mxSafeFrame;
6120261219
@@ -61248,11 +61265,11 @@
6124861265
if( rc==SQLITE_OK ){
6124961266
rc = sqlite3OsSync(pWal->pDbFd, CKPT_SYNC_FLAGS(sync_flags));
6125061267
}
6125161268
}
6125261269
if( rc==SQLITE_OK ){
61253
- pInfo->nBackfill = mxSafeFrame;
61270
+ AtomicStore(&pInfo->nBackfill, mxSafeFrame);
6125461271
}
6125561272
}
6125661273
6125761274
/* Release the reader lock held while backfilling */
6125861275
walUnlockExclusive(pWal, WAL_READ_LOCK(0), 1);
@@ -61407,11 +61424,11 @@
6140761424
** and *pChanged is set to 1.
6140861425
**
6140961426
** If the checksum cannot be verified return non-zero. If the header
6141061427
** is read successfully and the checksum verified, return zero.
6141161428
*/
61412
-static int walIndexTryHdr(Wal *pWal, int *pChanged){
61429
+static SQLITE_NO_TSAN int walIndexTryHdr(Wal *pWal, int *pChanged){
6141361430
u32 aCksum[2]; /* Checksum on the header content */
6141461431
WalIndexHdr h1, h2; /* Two copies of the header content */
6141561432
WalIndexHdr volatile *aHdr; /* Header in shared memory */
6141661433
6141761434
/* The first page of the wal-index must be mapped at this point. */
@@ -61420,17 +61437,23 @@
6142061437
/* Read the header. This might happen concurrently with a write to the
6142161438
** same area of shared memory on a different CPU in a SMP,
6142261439
** meaning it is possible that an inconsistent snapshot is read
6142361440
** from the file. If this happens, return non-zero.
6142461441
**
61442
+ ** tag-20200519-1:
6142561443
** There are two copies of the header at the beginning of the wal-index.
6142661444
** When reading, read [0] first then [1]. Writes are in the reverse order.
6142761445
** Memory barriers are used to prevent the compiler or the hardware from
61428
- ** reordering the reads and writes.
61446
+ ** reordering the reads and writes. TSAN and similar tools can sometimes
61447
+ ** give false-positive warnings about these accesses because the tools do not
61448
+ ** account for the double-read and the memory barrier. The use of mutexes
61449
+ ** here would be problematic as the memory being accessed is potentially
61450
+ ** shared among multiple processes and not all mutex implementions work
61451
+ ** reliably in that environment.
6142961452
*/
6143061453
aHdr = walIndexHdr(pWal);
61431
- memcpy(&h1, (void *)&aHdr[0], sizeof(h1));
61454
+ memcpy(&h1, (void *)&aHdr[0], sizeof(h1)); /* Possible TSAN false-positive */
6143261455
walShmBarrier(pWal);
6143361456
memcpy(&h2, (void *)&aHdr[1], sizeof(h2));
6143461457
6143561458
if( memcmp(&h1, &h2, sizeof(h1))!=0 ){
6143661459
return 1; /* Dirty read */
@@ -61871,11 +61894,11 @@
6187161894
}
6187261895
6187361896
assert( pWal->nWiData>0 );
6187461897
assert( pWal->apWiData[0]!=0 );
6187561898
pInfo = walCkptInfo(pWal);
61876
- if( !useWal && pInfo->nBackfill==pWal->hdr.mxFrame
61899
+ if( !useWal && AtomicLoad(&pInfo->nBackfill)==pWal->hdr.mxFrame
6187761900
#ifdef SQLITE_ENABLE_SNAPSHOT
6187861901
&& (pWal->pSnapshot==0 || pWal->hdr.mxFrame==0)
6187961902
#endif
6188061903
){
6188161904
/* The WAL has been completely backfilled (or it is empty).
@@ -62038,11 +62061,11 @@
6203862061
void *pBuf2 = sqlite3_malloc(szPage);
6203962062
if( pBuf1==0 || pBuf2==0 ){
6204062063
rc = SQLITE_NOMEM;
6204162064
}else{
6204262065
u32 i = pInfo->nBackfillAttempted;
62043
- for(i=pInfo->nBackfillAttempted; i>pInfo->nBackfill; i--){
62066
+ for(i=pInfo->nBackfillAttempted; i>AtomicLoad(&pInfo->nBackfill); i--){
6204462067
WalHashLoc sLoc; /* Hash table location */
6204562068
u32 pgno; /* Page number in db file */
6204662069
i64 iDbOff; /* Offset of db file entry */
6204762070
i64 iWalOff; /* Offset of wal file entry */
6204862071
@@ -62267,26 +62290,28 @@
6226762290
for(iHash=walFramePage(iLast); iHash>=iMinHash; iHash--){
6226862291
WalHashLoc sLoc; /* Hash table location */
6226962292
int iKey; /* Hash slot index */
6227062293
int nCollide; /* Number of hash collisions remaining */
6227162294
int rc; /* Error code */
62295
+ u32 iH;
6227262296
6227362297
rc = walHashGet(pWal, iHash, &sLoc);
6227462298
if( rc!=SQLITE_OK ){
6227562299
return rc;
6227662300
}
6227762301
nCollide = HASHTABLE_NSLOT;
62278
- for(iKey=walHash(pgno); sLoc.aHash[iKey]; iKey=walNextHash(iKey)){
62279
- u32 iH = sLoc.aHash[iKey];
62302
+ iKey = walHash(pgno);
62303
+ while( (iH = AtomicLoad(&sLoc.aHash[iKey]))!=0 ){
6228062304
u32 iFrame = iH + sLoc.iZero;
6228162305
if( iFrame<=iLast && iFrame>=pWal->minFrame && sLoc.aPgno[iH]==pgno ){
6228262306
assert( iFrame>iRead || CORRUPT_DB );
6228362307
iRead = iFrame;
6228462308
}
6228562309
if( (nCollide--)==0 ){
6228662310
return SQLITE_CORRUPT_BKPT;
6228762311
}
62312
+ iKey = walNextHash(iKey);
6228862313
}
6228962314
if( iRead ) break;
6229062315
}
6229162316
6229262317
#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
@@ -79307,10 +79332,11 @@
7930779332
char *zP4;
7930879333
char *zCom;
7930979334
sqlite3 dummyDb;
7931079335
static const char *zFormat1 = "%4d %-13s %4d %4d %4d %-13s %.2X %s\n";
7931179336
if( pOut==0 ) pOut = stdout;
79337
+ sqlite3BeginBenignMalloc();
7931279338
dummyDb.mallocFailed = 1;
7931379339
zP4 = sqlite3VdbeDisplayP4(&dummyDb, pOp);
7931479340
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
7931579341
zCom = sqlite3VdbeDisplayComment(0, pOp, zP4);
7931679342
#else
@@ -79325,10 +79351,11 @@
7932579351
zCom ? zCom : ""
7932679352
);
7932779353
fflush(pOut);
7932879354
sqlite3_free(zP4);
7932979355
sqlite3_free(zCom);
79356
+ sqlite3EndBenignMalloc();
7933079357
}
7933179358
#endif
7933279359
7933379360
/*
7933479361
** Initialize an array of N Mem element.
@@ -84066,11 +84093,11 @@
8406684093
p->db->errCode = SQLITE_OK;
8406784094
8406884095
/* If the bit corresponding to this variable in Vdbe.expmask is set, then
8406984096
** binding a new value to this variable invalidates the current query plan.
8407084097
**
84071
- ** IMPLEMENTATION-OF: R-48440-37595 If the specific value bound to host
84098
+ ** IMPLEMENTATION-OF: R-57496-20354 If the specific value bound to a host
8407284099
** parameter in the WHERE clause might influence the choice of query plan
8407384100
** for a statement, then the statement will be automatically recompiled,
8407484101
** as if there had been a schema change, on the first sqlite3_step() call
8407584102
** following any change to the bindings of that parameter.
8407684103
*/
@@ -96365,12 +96392,12 @@
9636596392
*************************************************************************
9636696393
**
9636796394
** This file implements virtual-tables for examining the bytecode content
9636896395
** of a prepared statement.
9636996396
*/
96370
-#ifdef SQLITE_ENABLE_BYTECODE_VTAB
9637196397
/* #include "sqliteInt.h" */
96398
+#if defined(SQLITE_ENABLE_BYTECODE_VTAB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
9637296399
/* #include "vdbeInt.h" */
9637396400
9637496401
/* An instance of the bytecode() table-valued function.
9637596402
*/
9637696403
typedef struct bytecodevtab bytecodevtab;
@@ -96771,10 +96798,12 @@
9677196798
if( rc==SQLITE_OK ){
9677296799
rc = sqlite3_create_module(db, "tables_used", &bytecodevtabModule, &db);
9677396800
}
9677496801
return rc;
9677596802
}
96803
+#elif defined(SQLITE_ENABLE_BYTECODE_VTAB)
96804
+SQLITE_PRIVATE int sqlite3VdbeBytecodeVtabInit(sqlite3 *db){ return SQLITE_OK; }
9677696805
#endif /* SQLITE_ENABLE_BYTECODE_VTAB */
9677796806
9677896807
/************** End of vdbevtab.c ********************************************/
9677996808
/************** Begin file memjournal.c **************************************/
9678096809
/*
@@ -103075,10 +103104,17 @@
103075103104
}
103076103105
setDoNotMergeFlagOnCopy(v);
103077103106
sqlite3VdbeResolveLabel(v, endCoalesce);
103078103107
break;
103079103108
}
103109
+ case INLINEFUNC_iif: {
103110
+ Expr caseExpr;
103111
+ memset(&caseExpr, 0, sizeof(caseExpr));
103112
+ caseExpr.op = TK_CASE;
103113
+ caseExpr.x.pList = pFarg;
103114
+ return sqlite3ExprCodeTarget(pParse, &caseExpr, target);
103115
+ }
103080103116
103081103117
default: {
103082103118
/* The UNLIKELY() function is a no-op. The result is the value
103083103119
** of the first argument.
103084103120
*/
@@ -105497,11 +105533,14 @@
105497105533
if( !zName ) goto exit_rename_table;
105498105534
105499105535
/* Check that a table or index named 'zName' does not already exist
105500105536
** in database iDb. If so, this is an error.
105501105537
*/
105502
- if( sqlite3FindTable(db, zName, zDb) || sqlite3FindIndex(db, zName, zDb) ){
105538
+ if( sqlite3FindTable(db, zName, zDb)
105539
+ || sqlite3FindIndex(db, zName, zDb)
105540
+ || sqlite3IsShadowTableOf(db, pTab, zName)
105541
+ ){
105503105542
sqlite3ErrorMsg(pParse,
105504105543
"there is already another table or index with this name: %s", zName);
105505105544
goto exit_rename_table;
105506105545
}
105507105546
@@ -110244,26 +110283,43 @@
110244110283
** exists */
110245110284
if( db->auth.authLevel<UAUTH_Admin && sqlite3UserAuthTable(zName)!=0 ){
110246110285
return 0;
110247110286
}
110248110287
#endif
110249
- while(1){
110250
- for(i=OMIT_TEMPDB; i<db->nDb; i++){
110251
- int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
110252
- if( zDatabase==0 || sqlite3DbIsNamed(db, j, zDatabase) ){
110253
- assert( sqlite3SchemaMutexHeld(db, j, 0) );
110254
- p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName);
110255
- if( p ) return p;
110256
- }
110257
- }
110258
- /* Not found. If the name we were looking for was temp.sqlite_master
110259
- ** then change the name to sqlite_temp_master and try again. */
110260
- if( sqlite3StrICmp(zName, MASTER_NAME)!=0 ) break;
110261
- if( sqlite3_stricmp(zDatabase, db->aDb[1].zDbSName)!=0 ) break;
110262
- zName = TEMP_MASTER_NAME;
110263
- }
110264
- return 0;
110288
+ if( zDatabase ){
110289
+ for(i=0; i<db->nDb; i++){
110290
+ if( sqlite3StrICmp(zDatabase, db->aDb[i].zDbSName)==0 ) break;
110291
+ }
110292
+ if( i>=db->nDb ){
110293
+ /* No match against the official names. But always match "main"
110294
+ ** to schema 0 as a legacy fallback. */
110295
+ if( sqlite3StrICmp(zDatabase,"main")==0 ){
110296
+ i = 0;
110297
+ }else{
110298
+ return 0;
110299
+ }
110300
+ }
110301
+ p = sqlite3HashFind(&db->aDb[i].pSchema->tblHash, zName);
110302
+ if( p==0 && i==1 && sqlite3StrICmp(zName, MASTER_NAME)==0 ){
110303
+ /* All temp.sqlite_master to be an alias for sqlite_temp_master */
110304
+ p = sqlite3HashFind(&db->aDb[1].pSchema->tblHash, TEMP_MASTER_NAME);
110305
+ }
110306
+ }else{
110307
+ /* Match against TEMP first */
110308
+ p = sqlite3HashFind(&db->aDb[1].pSchema->tblHash, zName);
110309
+ if( p ) return p;
110310
+ /* The main database is second */
110311
+ p = sqlite3HashFind(&db->aDb[0].pSchema->tblHash, zName);
110312
+ if( p ) return p;
110313
+ /* Attached databases are in order of attachment */
110314
+ for(i=2; i<db->nDb; i++){
110315
+ assert( sqlite3SchemaMutexHeld(db, i, 0) );
110316
+ p = sqlite3HashFind(&db->aDb[i].pSchema->tblHash, zName);
110317
+ if( p ) break;
110318
+ }
110319
+ }
110320
+ return p;
110265110321
}
110266110322
110267110323
/*
110268110324
** Locate the in-memory structure that describes a particular database
110269110325
** table given the name of that table and (optionally) the name of the
@@ -112063,10 +112119,32 @@
112063112119
assert( pPk->nColumn==j );
112064112120
assert( pTab->nNVCol<=j );
112065112121
recomputeColumnsNotIndexed(pPk);
112066112122
}
112067112123
112124
+
112125
+#ifndef SQLITE_OMIT_VIRTUALTABLE
112126
+/*
112127
+** Return true if pTab is a virtual table and zName is a shadow table name
112128
+** for that virtual table.
112129
+*/
112130
+SQLITE_PRIVATE int sqlite3IsShadowTableOf(sqlite3 *db, Table *pTab, const char *zName){
112131
+ int nName; /* Length of zName */
112132
+ Module *pMod; /* Module for the virtual table */
112133
+
112134
+ if( !IsVirtual(pTab) ) return 0;
112135
+ nName = sqlite3Strlen30(pTab->zName);
112136
+ if( sqlite3_strnicmp(zName, pTab->zName, nName)!=0 ) return 0;
112137
+ if( zName[nName]!='_' ) return 0;
112138
+ pMod = (Module*)sqlite3HashFind(&db->aModule, pTab->azModuleArg[0]);
112139
+ if( pMod==0 ) return 0;
112140
+ if( pMod->pModule->iVersion<3 ) return 0;
112141
+ if( pMod->pModule->xShadowName==0 ) return 0;
112142
+ return pMod->pModule->xShadowName(zName+nName+1);
112143
+}
112144
+#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
112145
+
112068112146
#ifndef SQLITE_OMIT_VIRTUALTABLE
112069112147
/*
112070112148
** Return true if zName is a shadow table name in the current database
112071112149
** connection.
112072112150
**
@@ -112074,26 +112152,21 @@
112074112152
** restored to its original value prior to this routine returning.
112075112153
*/
112076112154
SQLITE_PRIVATE int sqlite3ShadowTableName(sqlite3 *db, const char *zName){
112077112155
char *zTail; /* Pointer to the last "_" in zName */
112078112156
Table *pTab; /* Table that zName is a shadow of */
112079
- Module *pMod; /* Module for the virtual table */
112080
-
112081112157
zTail = strrchr(zName, '_');
112082112158
if( zTail==0 ) return 0;
112083112159
*zTail = 0;
112084112160
pTab = sqlite3FindTable(db, zName, 0);
112085112161
*zTail = '_';
112086112162
if( pTab==0 ) return 0;
112087112163
if( !IsVirtual(pTab) ) return 0;
112088
- pMod = (Module*)sqlite3HashFind(&db->aModule, pTab->azModuleArg[0]);
112089
- if( pMod==0 ) return 0;
112090
- if( pMod->pModule->iVersion<3 ) return 0;
112091
- if( pMod->pModule->xShadowName==0 ) return 0;
112092
- return pMod->pModule->xShadowName(zTail+1);
112164
+ return sqlite3IsShadowTableOf(db, pTab, zName);
112093112165
}
112094112166
#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
112167
+
112095112168
112096112169
#ifdef SQLITE_DEBUG
112097112170
/*
112098112171
** Mark all nodes of an expression as EP_Immutable, indicating that
112099112172
** they should not be changed. Expressions attached to a table or
@@ -117780,11 +117853,11 @@
117780117853
if( (cntExpand&(cntExpand-1))==0 ){
117781117854
/* Grow the size of the output buffer only on substitutions
117782117855
** whose index is a power of two: 1, 2, 4, 8, 16, 32, ... */
117783117856
u8 *zOld;
117784117857
zOld = zOut;
117785
- zOut = sqlite3_realloc64(zOut, (int)nOut + (nOut - nStr - 1));
117858
+ zOut = sqlite3Realloc(zOut, (int)nOut + (nOut - nStr - 1));
117786117859
if( zOut==0 ){
117787117860
sqlite3_result_error_nomem(context);
117788117861
sqlite3_free(zOld);
117789117862
return;
117790117863
}
@@ -118477,11 +118550,11 @@
118477118550
FUNCTION(round, 2, 0, 0, roundFunc ),
118478118551
#endif
118479118552
FUNCTION(upper, 1, 0, 0, upperFunc ),
118480118553
FUNCTION(lower, 1, 0, 0, lowerFunc ),
118481118554
FUNCTION(hex, 1, 0, 0, hexFunc ),
118482
- INLINE_FUNC(ifnull, 2, INLINEFUNC_coalesce, SQLITE_FUNC_COALESCE),
118555
+ INLINE_FUNC(ifnull, 2, INLINEFUNC_coalesce, 0 ),
118483118556
VFUNCTION(random, 0, 0, 0, randomFunc ),
118484118557
VFUNCTION(randomblob, 1, 0, 0, randomBlob ),
118485118558
FUNCTION(nullif, 2, 0, 1, nullifFunc ),
118486118559
DFUNCTION(sqlite_version, 0, 0, 0, versionFunc ),
118487118560
DFUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ),
@@ -118517,11 +118590,12 @@
118517118590
#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
118518118591
FUNCTION(unknown, -1, 0, 0, unknownFunc ),
118519118592
#endif
118520118593
FUNCTION(coalesce, 1, 0, 0, 0 ),
118521118594
FUNCTION(coalesce, 0, 0, 0, 0 ),
118522
- INLINE_FUNC(coalesce, -1, INLINEFUNC_coalesce, SQLITE_FUNC_COALESCE),
118595
+ INLINE_FUNC(coalesce, -1, INLINEFUNC_coalesce, 0 ),
118596
+ INLINE_FUNC(iif, 3, INLINEFUNC_iif, 0 ),
118523118597
};
118524118598
#ifndef SQLITE_OMIT_ALTERTABLE
118525118599
sqlite3AlterFunctions();
118526118600
#endif
118527118601
sqlite3WindowFunctions();
@@ -135570,11 +135644,11 @@
135570135644
need = nCol;
135571135645
}
135572135646
if( p->nData + need > p->nAlloc ){
135573135647
char **azNew;
135574135648
p->nAlloc = p->nAlloc*2 + need;
135575
- azNew = sqlite3_realloc64( p->azResult, sizeof(char*)*p->nAlloc );
135649
+ azNew = sqlite3Realloc( p->azResult, sizeof(char*)*p->nAlloc );
135576135650
if( azNew==0 ) goto malloc_failed;
135577135651
p->azResult = azNew;
135578135652
}
135579135653
135580135654
/* If this is the first row, then generate an extra row containing
@@ -135679,11 +135753,11 @@
135679135753
sqlite3_free_table(&res.azResult[1]);
135680135754
return rc;
135681135755
}
135682135756
if( res.nAlloc>res.nData ){
135683135757
char **azNew;
135684
- azNew = sqlite3_realloc64( res.azResult, sizeof(char*)*res.nData );
135758
+ azNew = sqlite3Realloc( res.azResult, sizeof(char*)*res.nData );
135685135759
if( azNew==0 ){
135686135760
sqlite3_free_table(&res.azResult[1]);
135687135761
db->errCode = SQLITE_NOMEM;
135688135762
return SQLITE_NOMEM_BKPT;
135689135763
}
@@ -136969,14 +137043,14 @@
136969137043
** Therefore, the P4 parameter is only required if the default value for
136970137044
** the column is a literal number, string or null. The sqlite3ValueFromExpr()
136971137045
** function is capable of transforming these types of expressions into
136972137046
** sqlite3_value objects.
136973137047
**
136974
-** If parameter iReg is not negative, code an OP_RealAffinity instruction
136975
-** on register iReg. This is used when an equivalent integer value is
136976
-** stored in place of an 8-byte floating point value in order to save
136977
-** space.
137048
+** If column as REAL affinity and the table is an ordinary b-tree table
137049
+** (not a virtual table) then the value might have been stored as an
137050
+** integer. In that case, add an OP_RealAffinity opcode to make sure
137051
+** it has been converted into REAL.
136978137052
*/
136979137053
SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){
136980137054
assert( pTab!=0 );
136981137055
if( !pTab->pSelect ){
136982137056
sqlite3_value *pValue = 0;
@@ -136989,11 +137063,11 @@
136989137063
if( pValue ){
136990137064
sqlite3VdbeAppendP4(v, pValue, P4_MEM);
136991137065
}
136992137066
}
136993137067
#ifndef SQLITE_OMIT_FLOATING_POINT
136994
- if( pTab->aCol[i].affinity==SQLITE_AFF_REAL ){
137068
+ if( pTab->aCol[i].affinity==SQLITE_AFF_REAL && !IsVirtual(pTab) ){
136995137069
sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg);
136996137070
}
136997137071
#endif
136998137072
}
136999137073
@@ -139838,11 +139912,11 @@
139838139912
assert( IsVirtual(pTab) );
139839139913
for(i=0; i<pToplevel->nVtabLock; i++){
139840139914
if( pTab==pToplevel->apVtabLock[i] ) return;
139841139915
}
139842139916
n = (pToplevel->nVtabLock+1)*sizeof(pToplevel->apVtabLock[0]);
139843
- apVtabLock = sqlite3_realloc64(pToplevel->apVtabLock, n);
139917
+ apVtabLock = sqlite3Realloc(pToplevel->apVtabLock, n);
139844139918
if( apVtabLock ){
139845139919
pToplevel->apVtabLock = apVtabLock;
139846139920
pToplevel->apVtabLock[pToplevel->nVtabLock++] = pTab;
139847139921
}else{
139848139922
sqlite3OomFault(pToplevel->db);
@@ -151130,17 +151204,23 @@
151130151204
){
151131151205
if( pAppend ){
151132151206
int i;
151133151207
int nInit = pList ? pList->nExpr : 0;
151134151208
for(i=0; i<pAppend->nExpr; i++){
151135
- int iDummy;
151136151209
Expr *pDup = sqlite3ExprDup(pParse->db, pAppend->a[i].pExpr, 0);
151137151210
assert( pDup==0 || !ExprHasProperty(pDup, EP_MemToken) );
151138
- if( bIntToNull && pDup && sqlite3ExprIsInteger(pDup, &iDummy) ){
151139
- pDup->op = TK_NULL;
151140
- pDup->flags &= ~(EP_IntValue|EP_IsTrue|EP_IsFalse);
151141
- pDup->u.zToken = 0;
151211
+ if( bIntToNull && pDup ){
151212
+ int iDummy;
151213
+ Expr *pSub;
151214
+ for(pSub=pDup; ExprHasProperty(pSub, EP_Skip); pSub=pSub->pLeft){
151215
+ assert( pSub );
151216
+ }
151217
+ if( sqlite3ExprIsInteger(pSub, &iDummy) ){
151218
+ pSub->op = TK_NULL;
151219
+ pSub->flags &= ~(EP_IntValue|EP_IsTrue|EP_IsFalse);
151220
+ pSub->u.zToken = 0;
151221
+ }
151142151222
}
151143151223
pList = sqlite3ExprListAppend(pParse, pList, pDup);
151144151224
if( pList ) pList->a[nInit+i].sortFlags = pAppend->a[i].sortFlags;
151145151225
}
151146151226
}
@@ -160322,10 +160402,11 @@
160322160402
}
160323160403
#endif
160324160404
if( rc==SQLITE_OK ){
160325160405
sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage,
160326160406
sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage);
160407
+ sqlite3MemoryBarrier();
160327160408
sqlite3GlobalConfig.isInit = 1;
160328160409
#ifdef SQLITE_EXTRA_INIT
160329160410
bRunExtraInit = 1;
160330160411
#endif
160331160412
}
@@ -163270,11 +163351,11 @@
163270163351
assert( SQLITE_OPEN_CREATE == 0x04 );
163271163352
testcase( (1<<(flags&7))==0x02 ); /* READONLY */
163272163353
testcase( (1<<(flags&7))==0x04 ); /* READWRITE */
163273163354
testcase( (1<<(flags&7))==0x40 ); /* READWRITE | CREATE */
163274163355
if( ((1<<(flags&7)) & 0x46)==0 ){
163275
- rc = SQLITE_MISUSE_BKPT; /* IMP: R-65497-44594 */
163356
+ rc = SQLITE_MISUSE_BKPT; /* IMP: R-18321-05872 */
163276163357
}else{
163277163358
rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg);
163278163359
}
163279163360
if( rc!=SQLITE_OK ){
163280163361
if( rc==SQLITE_NOMEM ) sqlite3OomFault(db);
@@ -171194,10 +171275,11 @@
171194171275
while( *pRc==SQLITE_OK && pLeft->bEof==0 ){
171195171276
memset(pDl->pList, 0, pDl->nList);
171196171277
fts3EvalNextRow(pCsr, pLeft, pRc);
171197171278
}
171198171279
}
171280
+ pRight->bEof = pLeft->bEof = 1;
171199171281
}
171200171282
}
171201171283
break;
171202171284
}
171203171285
@@ -182739,11 +182821,11 @@
182739182821
iStart = pExpr->iPhrase * p->nCol;
182740182822
}else{
182741182823
iStart = pExpr->iPhrase * ((p->nCol + 31) / 32);
182742182824
}
182743182825
182744
- while( 1 ){
182826
+ if( pIter ) while( 1 ){
182745182827
int nHit = fts3ColumnlistCount(&pIter);
182746182828
if( (pPhrase->iColumn>=pTab->nColumn || pPhrase->iColumn==iCol) ){
182747182829
if( p->flag==FTS3_MATCHINFO_LHITS ){
182748182830
p->aMatchinfo[iStart + iCol] = (u32)nHit;
182749182831
}else if( nHit ){
@@ -184653,10 +184735,11 @@
184653184735
}
184654184736
184655184737
/* Append N bytes from zIn onto the end of the JsonString string.
184656184738
*/
184657184739
static void jsonAppendRaw(JsonString *p, const char *zIn, u32 N){
184740
+ if( N==0 ) return;
184658184741
if( (N+p->nUsed >= p->nAlloc) && jsonGrow(p,N)!=0 ) return;
184659184742
memcpy(p->zBuf+p->nUsed, zIn, N);
184660184743
p->nUsed += N;
184661184744
}
184662184745
@@ -224664,11 +224747,11 @@
224664224747
int nArg, /* Number of args */
224665224748
sqlite3_value **apUnused /* Function arguments */
224666224749
){
224667224750
assert( nArg==0 );
224668224751
UNUSED_PARAM2(nArg, apUnused);
224669
- sqlite3_result_text(pCtx, "fts5: 2020-05-08 19:02:21 3a16c0ce4d8851f79f670d94786032c8007619154ece44647dc9cc5b1f9654ff", -1, SQLITE_TRANSIENT);
224752
+ sqlite3_result_text(pCtx, "fts5: 2020-05-19 15:51:10 3117c1b5a9e348fd8d16ba9d03fdafaad8514567fb3403f72b86d6162ad40bde", -1, SQLITE_TRANSIENT);
224670224753
}
224671224754
224672224755
/*
224673224756
** Return true if zName is the extension on one of the shadow tables used
224674224757
** by this module.
@@ -229447,12 +229530,12 @@
229447229530
}
229448229531
#endif /* SQLITE_CORE */
229449229532
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
229450229533
229451229534
/************** End of stmt.c ************************************************/
229452
-#if __LINE__!=229452
229535
+#if __LINE__!=229535
229453229536
#undef SQLITE_SOURCE_ID
229454
-#define SQLITE_SOURCE_ID "2020-05-08 19:02:21 3a16c0ce4d8851f79f670d94786032c8007619154ece44647dc9cc5b1f96alt2"
229537
+#define SQLITE_SOURCE_ID "2020-05-19 15:51:10 3117c1b5a9e348fd8d16ba9d03fdafaad8514567fb3403f72b86d6162ad4alt2"
229455229538
#endif
229456229539
/* Return the source-id for this library */
229457229540
SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
229458229541
/************************** End of sqlite3.c ******************************/
229459229542
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -1162,11 +1162,11 @@
1162 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
1163 ** [sqlite_version()] and [sqlite_source_id()].
1164 */
1165 #define SQLITE_VERSION "3.32.0"
1166 #define SQLITE_VERSION_NUMBER 3032000
1167 #define SQLITE_SOURCE_ID "2020-05-08 19:02:21 3a16c0ce4d8851f79f670d94786032c8007619154ece44647dc9cc5b1f9654ff"
1168
1169 /*
1170 ** CAPI3REF: Run-Time Library Version Numbers
1171 ** KEYWORDS: sqlite3_version sqlite3_sourceid
1172 **
@@ -6532,11 +6532,11 @@
6532 ** when first called if N is less than or equal to zero or if a memory
6533 ** allocate error occurs.
6534 **
6535 ** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is
6536 ** determined by the N parameter on first successful call. Changing the
6537 ** value of N in any subsequents call to sqlite3_aggregate_context() within
6538 ** the same aggregate function instance will not resize the memory
6539 ** allocation.)^ Within the xFinal callback, it is customary to set
6540 ** N=0 in calls to sqlite3_aggregate_context(C,N) so that no
6541 ** pointless memory allocations occur.
6542 **
@@ -17119,11 +17119,11 @@
17119 #define SQLITE_FUNC_EPHEM 0x0010 /* Ephemeral. Delete with VDBE */
17120 #define SQLITE_FUNC_NEEDCOLL 0x0020 /* sqlite3GetFuncCollSeq() might be called*/
17121 #define SQLITE_FUNC_LENGTH 0x0040 /* Built-in length() function */
17122 #define SQLITE_FUNC_TYPEOF 0x0080 /* Built-in typeof() function */
17123 #define SQLITE_FUNC_COUNT 0x0100 /* Built-in count(*) aggregate */
17124 #define SQLITE_FUNC_COALESCE 0x0200 /* Built-in coalesce() or ifnull() */
17125 #define SQLITE_FUNC_UNLIKELY 0x0400 /* Built-in unlikely() function */
17126 #define SQLITE_FUNC_CONSTANT 0x0800 /* Constant inputs give a constant output */
17127 #define SQLITE_FUNC_MINMAX 0x1000 /* True for min() and max() aggregates */
17128 #define SQLITE_FUNC_SLOCHNG 0x2000 /* "Slow Change". Value constant during a
17129 ** single query - might change over time */
@@ -17140,10 +17140,11 @@
17140 #define INLINEFUNC_coalesce 0
17141 #define INLINEFUNC_implies_nonnull_row 1
17142 #define INLINEFUNC_expr_implies_expr 2
17143 #define INLINEFUNC_expr_compare 3
17144 #define INLINEFUNC_affinity 4
 
17145 #define INLINEFUNC_unlikely 99 /* Default case */
17146
17147 /*
17148 ** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
17149 ** used to create the initializers for the FuncDef structures.
@@ -20064,12 +20065,14 @@
20064 # define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0)
20065 #endif
20066 SQLITE_PRIVATE int sqlite3ReadOnlyShadowTables(sqlite3 *db);
20067 #ifndef SQLITE_OMIT_VIRTUALTABLE
20068 SQLITE_PRIVATE int sqlite3ShadowTableName(sqlite3 *db, const char *zName);
 
20069 #else
20070 # define sqlite3ShadowTableName(A,B) 0
 
20071 #endif
20072 SQLITE_PRIVATE int sqlite3VtabEponymousTableInit(Parse*,Module*);
20073 SQLITE_PRIVATE void sqlite3VtabEponymousTableClear(sqlite3*,Module*);
20074 SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse*,Table*);
20075 SQLITE_PRIVATE void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*, int);
@@ -27924,11 +27927,11 @@
27924 }
27925 }else{
27926 assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
27927 assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
27928 sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
27929 pNew = sqlite3_realloc64(p, n);
27930 if( !pNew ){
27931 sqlite3OomFault(db);
27932 }
27933 sqlite3MemdebugSetType(pNew,
27934 (db->lookaside.bDisable==0 ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
@@ -29001,11 +29004,11 @@
29001 p->nAlloc = (int)szNew;
29002 }
29003 if( p->db ){
29004 zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc);
29005 }else{
29006 zNew = sqlite3_realloc64(zOld, p->nAlloc);
29007 }
29008 if( zNew ){
29009 assert( p->zText!=0 || p->nChar==0 );
29010 if( !isMalloced(p) && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
29011 p->zText = zNew;
@@ -29343,11 +29346,11 @@
29343 ** and segfaults if you give it a long long int.
29344 */
29345 SQLITE_PRIVATE void sqlite3DebugPrintf(const char *zFormat, ...){
29346 va_list ap;
29347 StrAccum acc;
29348 char zBuf[500];
29349 sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
29350 va_start(ap,zFormat);
29351 sqlite3_str_vappendf(&acc, zFormat, ap);
29352 va_end(ap);
29353 sqlite3StrAccumFinish(&acc);
@@ -45048,10 +45051,11 @@
45048 }
45049
45050 /* Forward references to VFS helper methods used for temporary files */
45051 static int winGetTempname(sqlite3_vfs *, char **);
45052 static int winIsDir(const void *);
 
45053 static BOOL winIsDriveLetterAndColon(const char *);
45054
45055 /*
45056 ** Control and query of the open file handle.
45057 */
@@ -46817,11 +46821,13 @@
46817 pFile->pVfs = pVfs;
46818 pFile->h = h;
46819 if( isReadonly ){
46820 pFile->ctrlFlags |= WINFILE_RDONLY;
46821 }
46822 if( sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) ){
 
 
46823 pFile->ctrlFlags |= WINFILE_PSOW;
46824 }
46825 pFile->lastErrno = NO_ERROR;
46826 pFile->zPath = zName;
46827 #if SQLITE_MAX_MMAP_SIZE>0
@@ -47026,10 +47032,21 @@
47026 *pResOut = rc;
47027 OSTRACE(("ACCESS name=%s, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n",
47028 zFilename, pResOut, *pResOut));
47029 return SQLITE_OK;
47030 }
 
 
 
 
 
 
 
 
 
 
 
47031
47032 /*
47033 ** Returns non-zero if the specified path name starts with a drive letter
47034 ** followed by a colon character.
47035 */
@@ -47091,14 +47108,15 @@
47091 DWORD nByte;
47092 void *zConverted;
47093 char *zOut;
47094 #endif
47095
47096 /* If this path name begins with "/X:", where "X" is any alphabetic
47097 ** character, discard the initial "/" from the pathname.
47098 */
47099 if( zRelative[0]=='/' && winIsDriveLetterAndColon(zRelative+1) ){
 
47100 zRelative++;
47101 }
47102
47103 #if defined(__CYGWIN__)
47104 SimulateIOError( return SQLITE_ERROR );
@@ -47850,11 +47868,11 @@
47850 if( newSz>p->szMax ){
47851 return SQLITE_FULL;
47852 }
47853 newSz *= 2;
47854 if( newSz>p->szMax ) newSz = p->szMax;
47855 pNew = sqlite3_realloc64(p->aData, newSz);
47856 if( pNew==0 ) return SQLITE_NOMEM;
47857 p->aData = pNew;
47858 p->szAlloc = newSz;
47859 return SQLITE_OK;
47860 }
@@ -59820,11 +59838,11 @@
59820
59821 /* Enlarge the pWal->apWiData[] array if required */
59822 if( pWal->nWiData<=iPage ){
59823 sqlite3_int64 nByte = sizeof(u32*)*(iPage+1);
59824 volatile u32 **apNew;
59825 apNew = (volatile u32 **)sqlite3_realloc64((void *)pWal->apWiData, nByte);
59826 if( !apNew ){
59827 *ppPage = 0;
59828 return SQLITE_NOMEM_BKPT;
59829 }
59830 memset((void*)&apNew[pWal->nWiData], 0,
@@ -59941,29 +59959,47 @@
59941
59942 aOut[0] = s1;
59943 aOut[1] = s2;
59944 }
59945
 
 
 
 
59946 static void walShmBarrier(Wal *pWal){
59947 if( pWal->exclusiveMode!=WAL_HEAPMEMORY_MODE ){
59948 sqlite3OsShmBarrier(pWal->pDbFd);
59949 }
59950 }
59951
 
 
 
 
 
 
 
 
 
 
 
 
 
59952 /*
59953 ** Write the header information in pWal->hdr into the wal-index.
59954 **
59955 ** The checksum on pWal->hdr is updated before it is written.
59956 */
59957 static void walIndexWriteHdr(Wal *pWal){
59958 volatile WalIndexHdr *aHdr = walIndexHdr(pWal);
59959 const int nCksum = offsetof(WalIndexHdr, aCksum);
59960
59961 assert( pWal->writeLock );
59962 pWal->hdr.isInit = 1;
59963 pWal->hdr.iVersion = WALINDEX_MAX_VERSION;
59964 walChecksumBytes(1, (u8*)&pWal->hdr, nCksum, 0, pWal->hdr.aCksum);
 
59965 memcpy((void*)&aHdr[1], (const void*)&pWal->hdr, sizeof(WalIndexHdr));
59966 walShmBarrier(pWal);
59967 memcpy((void*)&aHdr[0], (const void*)&pWal->hdr, sizeof(WalIndexHdr));
59968 }
59969
@@ -61074,11 +61110,11 @@
61074 pWal->nCkpt++;
61075 pWal->hdr.mxFrame = 0;
61076 sqlite3Put4byte((u8*)&aSalt[0], 1 + sqlite3Get4byte((u8*)&aSalt[0]));
61077 memcpy(&pWal->hdr.aSalt[1], &salt1, 4);
61078 walIndexWriteHdr(pWal);
61079 pInfo->nBackfill = 0;
61080 pInfo->nBackfillAttempted = 0;
61081 pInfo->aReadMark[1] = 0;
61082 for(i=2; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED;
61083 assert( pInfo->aReadMark[0]==0 );
61084 }
@@ -61149,36 +61185,17 @@
61149 ** cannot be backfilled from the WAL.
61150 */
61151 mxSafeFrame = pWal->hdr.mxFrame;
61152 mxPage = pWal->hdr.nPage;
61153 for(i=1; i<WAL_NREADER; i++){
61154 /* Thread-sanitizer reports that the following is an unsafe read,
61155 ** as some other thread may be in the process of updating the value
61156 ** of the aReadMark[] slot. The assumption here is that if that is
61157 ** happening, the other client may only be increasing the value,
61158 ** not decreasing it. So assuming either that either the "old" or
61159 ** "new" version of the value is read, and not some arbitrary value
61160 ** that would never be written by a real client, things are still
61161 ** safe.
61162 **
61163 ** Astute readers have pointed out that the assumption stated in the
61164 ** last sentence of the previous paragraph is not guaranteed to be
61165 ** true for all conforming systems. However, the assumption is true
61166 ** for all compilers and architectures in common use today (circa
61167 ** 2019-11-27) and the alternatives are both slow and complex, and
61168 ** so we will continue to go with the current design for now. If this
61169 ** bothers you, or if you really are running on a system where aligned
61170 ** 32-bit reads and writes are not atomic, then you can simply avoid
61171 ** the use of WAL mode, or only use WAL mode together with
61172 ** PRAGMA locking_mode=EXCLUSIVE and all will be well.
61173 */
61174 u32 y = pInfo->aReadMark[i];
61175 if( mxSafeFrame>y ){
61176 assert( y<=pWal->hdr.mxFrame );
61177 rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1);
61178 if( rc==SQLITE_OK ){
61179 pInfo->aReadMark[i] = (i==1 ? mxSafeFrame : READMARK_NOT_USED);
 
61180 walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
61181 }else if( rc==SQLITE_BUSY ){
61182 mxSafeFrame = y;
61183 xBusy = 0;
61184 }else{
@@ -61192,11 +61209,11 @@
61192 rc = walIteratorInit(pWal, pInfo->nBackfill, &pIter);
61193 assert( rc==SQLITE_OK || pIter==0 );
61194 }
61195
61196 if( pIter
61197 && (rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(0),1))==SQLITE_OK
61198 ){
61199 u32 nBackfill = pInfo->nBackfill;
61200
61201 pInfo->nBackfillAttempted = mxSafeFrame;
61202
@@ -61248,11 +61265,11 @@
61248 if( rc==SQLITE_OK ){
61249 rc = sqlite3OsSync(pWal->pDbFd, CKPT_SYNC_FLAGS(sync_flags));
61250 }
61251 }
61252 if( rc==SQLITE_OK ){
61253 pInfo->nBackfill = mxSafeFrame;
61254 }
61255 }
61256
61257 /* Release the reader lock held while backfilling */
61258 walUnlockExclusive(pWal, WAL_READ_LOCK(0), 1);
@@ -61407,11 +61424,11 @@
61407 ** and *pChanged is set to 1.
61408 **
61409 ** If the checksum cannot be verified return non-zero. If the header
61410 ** is read successfully and the checksum verified, return zero.
61411 */
61412 static int walIndexTryHdr(Wal *pWal, int *pChanged){
61413 u32 aCksum[2]; /* Checksum on the header content */
61414 WalIndexHdr h1, h2; /* Two copies of the header content */
61415 WalIndexHdr volatile *aHdr; /* Header in shared memory */
61416
61417 /* The first page of the wal-index must be mapped at this point. */
@@ -61420,17 +61437,23 @@
61420 /* Read the header. This might happen concurrently with a write to the
61421 ** same area of shared memory on a different CPU in a SMP,
61422 ** meaning it is possible that an inconsistent snapshot is read
61423 ** from the file. If this happens, return non-zero.
61424 **
 
61425 ** There are two copies of the header at the beginning of the wal-index.
61426 ** When reading, read [0] first then [1]. Writes are in the reverse order.
61427 ** Memory barriers are used to prevent the compiler or the hardware from
61428 ** reordering the reads and writes.
 
 
 
 
 
61429 */
61430 aHdr = walIndexHdr(pWal);
61431 memcpy(&h1, (void *)&aHdr[0], sizeof(h1));
61432 walShmBarrier(pWal);
61433 memcpy(&h2, (void *)&aHdr[1], sizeof(h2));
61434
61435 if( memcmp(&h1, &h2, sizeof(h1))!=0 ){
61436 return 1; /* Dirty read */
@@ -61871,11 +61894,11 @@
61871 }
61872
61873 assert( pWal->nWiData>0 );
61874 assert( pWal->apWiData[0]!=0 );
61875 pInfo = walCkptInfo(pWal);
61876 if( !useWal && pInfo->nBackfill==pWal->hdr.mxFrame
61877 #ifdef SQLITE_ENABLE_SNAPSHOT
61878 && (pWal->pSnapshot==0 || pWal->hdr.mxFrame==0)
61879 #endif
61880 ){
61881 /* The WAL has been completely backfilled (or it is empty).
@@ -62038,11 +62061,11 @@
62038 void *pBuf2 = sqlite3_malloc(szPage);
62039 if( pBuf1==0 || pBuf2==0 ){
62040 rc = SQLITE_NOMEM;
62041 }else{
62042 u32 i = pInfo->nBackfillAttempted;
62043 for(i=pInfo->nBackfillAttempted; i>pInfo->nBackfill; i--){
62044 WalHashLoc sLoc; /* Hash table location */
62045 u32 pgno; /* Page number in db file */
62046 i64 iDbOff; /* Offset of db file entry */
62047 i64 iWalOff; /* Offset of wal file entry */
62048
@@ -62267,26 +62290,28 @@
62267 for(iHash=walFramePage(iLast); iHash>=iMinHash; iHash--){
62268 WalHashLoc sLoc; /* Hash table location */
62269 int iKey; /* Hash slot index */
62270 int nCollide; /* Number of hash collisions remaining */
62271 int rc; /* Error code */
 
62272
62273 rc = walHashGet(pWal, iHash, &sLoc);
62274 if( rc!=SQLITE_OK ){
62275 return rc;
62276 }
62277 nCollide = HASHTABLE_NSLOT;
62278 for(iKey=walHash(pgno); sLoc.aHash[iKey]; iKey=walNextHash(iKey)){
62279 u32 iH = sLoc.aHash[iKey];
62280 u32 iFrame = iH + sLoc.iZero;
62281 if( iFrame<=iLast && iFrame>=pWal->minFrame && sLoc.aPgno[iH]==pgno ){
62282 assert( iFrame>iRead || CORRUPT_DB );
62283 iRead = iFrame;
62284 }
62285 if( (nCollide--)==0 ){
62286 return SQLITE_CORRUPT_BKPT;
62287 }
 
62288 }
62289 if( iRead ) break;
62290 }
62291
62292 #ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
@@ -79307,10 +79332,11 @@
79307 char *zP4;
79308 char *zCom;
79309 sqlite3 dummyDb;
79310 static const char *zFormat1 = "%4d %-13s %4d %4d %4d %-13s %.2X %s\n";
79311 if( pOut==0 ) pOut = stdout;
 
79312 dummyDb.mallocFailed = 1;
79313 zP4 = sqlite3VdbeDisplayP4(&dummyDb, pOp);
79314 #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
79315 zCom = sqlite3VdbeDisplayComment(0, pOp, zP4);
79316 #else
@@ -79325,10 +79351,11 @@
79325 zCom ? zCom : ""
79326 );
79327 fflush(pOut);
79328 sqlite3_free(zP4);
79329 sqlite3_free(zCom);
 
79330 }
79331 #endif
79332
79333 /*
79334 ** Initialize an array of N Mem element.
@@ -84066,11 +84093,11 @@
84066 p->db->errCode = SQLITE_OK;
84067
84068 /* If the bit corresponding to this variable in Vdbe.expmask is set, then
84069 ** binding a new value to this variable invalidates the current query plan.
84070 **
84071 ** IMPLEMENTATION-OF: R-48440-37595 If the specific value bound to host
84072 ** parameter in the WHERE clause might influence the choice of query plan
84073 ** for a statement, then the statement will be automatically recompiled,
84074 ** as if there had been a schema change, on the first sqlite3_step() call
84075 ** following any change to the bindings of that parameter.
84076 */
@@ -96365,12 +96392,12 @@
96365 *************************************************************************
96366 **
96367 ** This file implements virtual-tables for examining the bytecode content
96368 ** of a prepared statement.
96369 */
96370 #ifdef SQLITE_ENABLE_BYTECODE_VTAB
96371 /* #include "sqliteInt.h" */
 
96372 /* #include "vdbeInt.h" */
96373
96374 /* An instance of the bytecode() table-valued function.
96375 */
96376 typedef struct bytecodevtab bytecodevtab;
@@ -96771,10 +96798,12 @@
96771 if( rc==SQLITE_OK ){
96772 rc = sqlite3_create_module(db, "tables_used", &bytecodevtabModule, &db);
96773 }
96774 return rc;
96775 }
 
 
96776 #endif /* SQLITE_ENABLE_BYTECODE_VTAB */
96777
96778 /************** End of vdbevtab.c ********************************************/
96779 /************** Begin file memjournal.c **************************************/
96780 /*
@@ -103075,10 +103104,17 @@
103075 }
103076 setDoNotMergeFlagOnCopy(v);
103077 sqlite3VdbeResolveLabel(v, endCoalesce);
103078 break;
103079 }
 
 
 
 
 
 
 
103080
103081 default: {
103082 /* The UNLIKELY() function is a no-op. The result is the value
103083 ** of the first argument.
103084 */
@@ -105497,11 +105533,14 @@
105497 if( !zName ) goto exit_rename_table;
105498
105499 /* Check that a table or index named 'zName' does not already exist
105500 ** in database iDb. If so, this is an error.
105501 */
105502 if( sqlite3FindTable(db, zName, zDb) || sqlite3FindIndex(db, zName, zDb) ){
 
 
 
105503 sqlite3ErrorMsg(pParse,
105504 "there is already another table or index with this name: %s", zName);
105505 goto exit_rename_table;
105506 }
105507
@@ -110244,26 +110283,43 @@
110244 ** exists */
110245 if( db->auth.authLevel<UAUTH_Admin && sqlite3UserAuthTable(zName)!=0 ){
110246 return 0;
110247 }
110248 #endif
110249 while(1){
110250 for(i=OMIT_TEMPDB; i<db->nDb; i++){
110251 int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
110252 if( zDatabase==0 || sqlite3DbIsNamed(db, j, zDatabase) ){
110253 assert( sqlite3SchemaMutexHeld(db, j, 0) );
110254 p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName);
110255 if( p ) return p;
110256 }
110257 }
110258 /* Not found. If the name we were looking for was temp.sqlite_master
110259 ** then change the name to sqlite_temp_master and try again. */
110260 if( sqlite3StrICmp(zName, MASTER_NAME)!=0 ) break;
110261 if( sqlite3_stricmp(zDatabase, db->aDb[1].zDbSName)!=0 ) break;
110262 zName = TEMP_MASTER_NAME;
110263 }
110264 return 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110265 }
110266
110267 /*
110268 ** Locate the in-memory structure that describes a particular database
110269 ** table given the name of that table and (optionally) the name of the
@@ -112063,10 +112119,32 @@
112063 assert( pPk->nColumn==j );
112064 assert( pTab->nNVCol<=j );
112065 recomputeColumnsNotIndexed(pPk);
112066 }
112067
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112068 #ifndef SQLITE_OMIT_VIRTUALTABLE
112069 /*
112070 ** Return true if zName is a shadow table name in the current database
112071 ** connection.
112072 **
@@ -112074,26 +112152,21 @@
112074 ** restored to its original value prior to this routine returning.
112075 */
112076 SQLITE_PRIVATE int sqlite3ShadowTableName(sqlite3 *db, const char *zName){
112077 char *zTail; /* Pointer to the last "_" in zName */
112078 Table *pTab; /* Table that zName is a shadow of */
112079 Module *pMod; /* Module for the virtual table */
112080
112081 zTail = strrchr(zName, '_');
112082 if( zTail==0 ) return 0;
112083 *zTail = 0;
112084 pTab = sqlite3FindTable(db, zName, 0);
112085 *zTail = '_';
112086 if( pTab==0 ) return 0;
112087 if( !IsVirtual(pTab) ) return 0;
112088 pMod = (Module*)sqlite3HashFind(&db->aModule, pTab->azModuleArg[0]);
112089 if( pMod==0 ) return 0;
112090 if( pMod->pModule->iVersion<3 ) return 0;
112091 if( pMod->pModule->xShadowName==0 ) return 0;
112092 return pMod->pModule->xShadowName(zTail+1);
112093 }
112094 #endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
 
112095
112096 #ifdef SQLITE_DEBUG
112097 /*
112098 ** Mark all nodes of an expression as EP_Immutable, indicating that
112099 ** they should not be changed. Expressions attached to a table or
@@ -117780,11 +117853,11 @@
117780 if( (cntExpand&(cntExpand-1))==0 ){
117781 /* Grow the size of the output buffer only on substitutions
117782 ** whose index is a power of two: 1, 2, 4, 8, 16, 32, ... */
117783 u8 *zOld;
117784 zOld = zOut;
117785 zOut = sqlite3_realloc64(zOut, (int)nOut + (nOut - nStr - 1));
117786 if( zOut==0 ){
117787 sqlite3_result_error_nomem(context);
117788 sqlite3_free(zOld);
117789 return;
117790 }
@@ -118477,11 +118550,11 @@
118477 FUNCTION(round, 2, 0, 0, roundFunc ),
118478 #endif
118479 FUNCTION(upper, 1, 0, 0, upperFunc ),
118480 FUNCTION(lower, 1, 0, 0, lowerFunc ),
118481 FUNCTION(hex, 1, 0, 0, hexFunc ),
118482 INLINE_FUNC(ifnull, 2, INLINEFUNC_coalesce, SQLITE_FUNC_COALESCE),
118483 VFUNCTION(random, 0, 0, 0, randomFunc ),
118484 VFUNCTION(randomblob, 1, 0, 0, randomBlob ),
118485 FUNCTION(nullif, 2, 0, 1, nullifFunc ),
118486 DFUNCTION(sqlite_version, 0, 0, 0, versionFunc ),
118487 DFUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ),
@@ -118517,11 +118590,12 @@
118517 #ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
118518 FUNCTION(unknown, -1, 0, 0, unknownFunc ),
118519 #endif
118520 FUNCTION(coalesce, 1, 0, 0, 0 ),
118521 FUNCTION(coalesce, 0, 0, 0, 0 ),
118522 INLINE_FUNC(coalesce, -1, INLINEFUNC_coalesce, SQLITE_FUNC_COALESCE),
 
118523 };
118524 #ifndef SQLITE_OMIT_ALTERTABLE
118525 sqlite3AlterFunctions();
118526 #endif
118527 sqlite3WindowFunctions();
@@ -135570,11 +135644,11 @@
135570 need = nCol;
135571 }
135572 if( p->nData + need > p->nAlloc ){
135573 char **azNew;
135574 p->nAlloc = p->nAlloc*2 + need;
135575 azNew = sqlite3_realloc64( p->azResult, sizeof(char*)*p->nAlloc );
135576 if( azNew==0 ) goto malloc_failed;
135577 p->azResult = azNew;
135578 }
135579
135580 /* If this is the first row, then generate an extra row containing
@@ -135679,11 +135753,11 @@
135679 sqlite3_free_table(&res.azResult[1]);
135680 return rc;
135681 }
135682 if( res.nAlloc>res.nData ){
135683 char **azNew;
135684 azNew = sqlite3_realloc64( res.azResult, sizeof(char*)*res.nData );
135685 if( azNew==0 ){
135686 sqlite3_free_table(&res.azResult[1]);
135687 db->errCode = SQLITE_NOMEM;
135688 return SQLITE_NOMEM_BKPT;
135689 }
@@ -136969,14 +137043,14 @@
136969 ** Therefore, the P4 parameter is only required if the default value for
136970 ** the column is a literal number, string or null. The sqlite3ValueFromExpr()
136971 ** function is capable of transforming these types of expressions into
136972 ** sqlite3_value objects.
136973 **
136974 ** If parameter iReg is not negative, code an OP_RealAffinity instruction
136975 ** on register iReg. This is used when an equivalent integer value is
136976 ** stored in place of an 8-byte floating point value in order to save
136977 ** space.
136978 */
136979 SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){
136980 assert( pTab!=0 );
136981 if( !pTab->pSelect ){
136982 sqlite3_value *pValue = 0;
@@ -136989,11 +137063,11 @@
136989 if( pValue ){
136990 sqlite3VdbeAppendP4(v, pValue, P4_MEM);
136991 }
136992 }
136993 #ifndef SQLITE_OMIT_FLOATING_POINT
136994 if( pTab->aCol[i].affinity==SQLITE_AFF_REAL ){
136995 sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg);
136996 }
136997 #endif
136998 }
136999
@@ -139838,11 +139912,11 @@
139838 assert( IsVirtual(pTab) );
139839 for(i=0; i<pToplevel->nVtabLock; i++){
139840 if( pTab==pToplevel->apVtabLock[i] ) return;
139841 }
139842 n = (pToplevel->nVtabLock+1)*sizeof(pToplevel->apVtabLock[0]);
139843 apVtabLock = sqlite3_realloc64(pToplevel->apVtabLock, n);
139844 if( apVtabLock ){
139845 pToplevel->apVtabLock = apVtabLock;
139846 pToplevel->apVtabLock[pToplevel->nVtabLock++] = pTab;
139847 }else{
139848 sqlite3OomFault(pToplevel->db);
@@ -151130,17 +151204,23 @@
151130 ){
151131 if( pAppend ){
151132 int i;
151133 int nInit = pList ? pList->nExpr : 0;
151134 for(i=0; i<pAppend->nExpr; i++){
151135 int iDummy;
151136 Expr *pDup = sqlite3ExprDup(pParse->db, pAppend->a[i].pExpr, 0);
151137 assert( pDup==0 || !ExprHasProperty(pDup, EP_MemToken) );
151138 if( bIntToNull && pDup && sqlite3ExprIsInteger(pDup, &iDummy) ){
151139 pDup->op = TK_NULL;
151140 pDup->flags &= ~(EP_IntValue|EP_IsTrue|EP_IsFalse);
151141 pDup->u.zToken = 0;
 
 
 
 
 
 
 
151142 }
151143 pList = sqlite3ExprListAppend(pParse, pList, pDup);
151144 if( pList ) pList->a[nInit+i].sortFlags = pAppend->a[i].sortFlags;
151145 }
151146 }
@@ -160322,10 +160402,11 @@
160322 }
160323 #endif
160324 if( rc==SQLITE_OK ){
160325 sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage,
160326 sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage);
 
160327 sqlite3GlobalConfig.isInit = 1;
160328 #ifdef SQLITE_EXTRA_INIT
160329 bRunExtraInit = 1;
160330 #endif
160331 }
@@ -163270,11 +163351,11 @@
163270 assert( SQLITE_OPEN_CREATE == 0x04 );
163271 testcase( (1<<(flags&7))==0x02 ); /* READONLY */
163272 testcase( (1<<(flags&7))==0x04 ); /* READWRITE */
163273 testcase( (1<<(flags&7))==0x40 ); /* READWRITE | CREATE */
163274 if( ((1<<(flags&7)) & 0x46)==0 ){
163275 rc = SQLITE_MISUSE_BKPT; /* IMP: R-65497-44594 */
163276 }else{
163277 rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg);
163278 }
163279 if( rc!=SQLITE_OK ){
163280 if( rc==SQLITE_NOMEM ) sqlite3OomFault(db);
@@ -171194,10 +171275,11 @@
171194 while( *pRc==SQLITE_OK && pLeft->bEof==0 ){
171195 memset(pDl->pList, 0, pDl->nList);
171196 fts3EvalNextRow(pCsr, pLeft, pRc);
171197 }
171198 }
 
171199 }
171200 }
171201 break;
171202 }
171203
@@ -182739,11 +182821,11 @@
182739 iStart = pExpr->iPhrase * p->nCol;
182740 }else{
182741 iStart = pExpr->iPhrase * ((p->nCol + 31) / 32);
182742 }
182743
182744 while( 1 ){
182745 int nHit = fts3ColumnlistCount(&pIter);
182746 if( (pPhrase->iColumn>=pTab->nColumn || pPhrase->iColumn==iCol) ){
182747 if( p->flag==FTS3_MATCHINFO_LHITS ){
182748 p->aMatchinfo[iStart + iCol] = (u32)nHit;
182749 }else if( nHit ){
@@ -184653,10 +184735,11 @@
184653 }
184654
184655 /* Append N bytes from zIn onto the end of the JsonString string.
184656 */
184657 static void jsonAppendRaw(JsonString *p, const char *zIn, u32 N){
 
184658 if( (N+p->nUsed >= p->nAlloc) && jsonGrow(p,N)!=0 ) return;
184659 memcpy(p->zBuf+p->nUsed, zIn, N);
184660 p->nUsed += N;
184661 }
184662
@@ -224664,11 +224747,11 @@
224664 int nArg, /* Number of args */
224665 sqlite3_value **apUnused /* Function arguments */
224666 ){
224667 assert( nArg==0 );
224668 UNUSED_PARAM2(nArg, apUnused);
224669 sqlite3_result_text(pCtx, "fts5: 2020-05-08 19:02:21 3a16c0ce4d8851f79f670d94786032c8007619154ece44647dc9cc5b1f9654ff", -1, SQLITE_TRANSIENT);
224670 }
224671
224672 /*
224673 ** Return true if zName is the extension on one of the shadow tables used
224674 ** by this module.
@@ -229447,12 +229530,12 @@
229447 }
229448 #endif /* SQLITE_CORE */
229449 #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
229450
229451 /************** End of stmt.c ************************************************/
229452 #if __LINE__!=229452
229453 #undef SQLITE_SOURCE_ID
229454 #define SQLITE_SOURCE_ID "2020-05-08 19:02:21 3a16c0ce4d8851f79f670d94786032c8007619154ece44647dc9cc5b1f96alt2"
229455 #endif
229456 /* Return the source-id for this library */
229457 SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
229458 /************************** End of sqlite3.c ******************************/
229459
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -1162,11 +1162,11 @@
1162 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
1163 ** [sqlite_version()] and [sqlite_source_id()].
1164 */
1165 #define SQLITE_VERSION "3.32.0"
1166 #define SQLITE_VERSION_NUMBER 3032000
1167 #define SQLITE_SOURCE_ID "2020-05-19 15:51:10 3117c1b5a9e348fd8d16ba9d03fdafaad8514567fb3403f72b86d6162ad40bde"
1168
1169 /*
1170 ** CAPI3REF: Run-Time Library Version Numbers
1171 ** KEYWORDS: sqlite3_version sqlite3_sourceid
1172 **
@@ -6532,11 +6532,11 @@
6532 ** when first called if N is less than or equal to zero or if a memory
6533 ** allocate error occurs.
6534 **
6535 ** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is
6536 ** determined by the N parameter on first successful call. Changing the
6537 ** value of N in any subsequent call to sqlite3_aggregate_context() within
6538 ** the same aggregate function instance will not resize the memory
6539 ** allocation.)^ Within the xFinal callback, it is customary to set
6540 ** N=0 in calls to sqlite3_aggregate_context(C,N) so that no
6541 ** pointless memory allocations occur.
6542 **
@@ -17119,11 +17119,11 @@
17119 #define SQLITE_FUNC_EPHEM 0x0010 /* Ephemeral. Delete with VDBE */
17120 #define SQLITE_FUNC_NEEDCOLL 0x0020 /* sqlite3GetFuncCollSeq() might be called*/
17121 #define SQLITE_FUNC_LENGTH 0x0040 /* Built-in length() function */
17122 #define SQLITE_FUNC_TYPEOF 0x0080 /* Built-in typeof() function */
17123 #define SQLITE_FUNC_COUNT 0x0100 /* Built-in count(*) aggregate */
17124 /* 0x0200 -- available for reuse */
17125 #define SQLITE_FUNC_UNLIKELY 0x0400 /* Built-in unlikely() function */
17126 #define SQLITE_FUNC_CONSTANT 0x0800 /* Constant inputs give a constant output */
17127 #define SQLITE_FUNC_MINMAX 0x1000 /* True for min() and max() aggregates */
17128 #define SQLITE_FUNC_SLOCHNG 0x2000 /* "Slow Change". Value constant during a
17129 ** single query - might change over time */
@@ -17140,10 +17140,11 @@
17140 #define INLINEFUNC_coalesce 0
17141 #define INLINEFUNC_implies_nonnull_row 1
17142 #define INLINEFUNC_expr_implies_expr 2
17143 #define INLINEFUNC_expr_compare 3
17144 #define INLINEFUNC_affinity 4
17145 #define INLINEFUNC_iif 5
17146 #define INLINEFUNC_unlikely 99 /* Default case */
17147
17148 /*
17149 ** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
17150 ** used to create the initializers for the FuncDef structures.
@@ -20064,12 +20065,14 @@
20065 # define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0)
20066 #endif
20067 SQLITE_PRIVATE int sqlite3ReadOnlyShadowTables(sqlite3 *db);
20068 #ifndef SQLITE_OMIT_VIRTUALTABLE
20069 SQLITE_PRIVATE int sqlite3ShadowTableName(sqlite3 *db, const char *zName);
20070 SQLITE_PRIVATE int sqlite3IsShadowTableOf(sqlite3*,Table*,const char*);
20071 #else
20072 # define sqlite3ShadowTableName(A,B) 0
20073 # define sqlite3IsShadowTableOf(A,B,C) 0
20074 #endif
20075 SQLITE_PRIVATE int sqlite3VtabEponymousTableInit(Parse*,Module*);
20076 SQLITE_PRIVATE void sqlite3VtabEponymousTableClear(sqlite3*,Module*);
20077 SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse*,Table*);
20078 SQLITE_PRIVATE void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*, int);
@@ -27924,11 +27927,11 @@
27927 }
27928 }else{
27929 assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
27930 assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
27931 sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
27932 pNew = sqlite3Realloc(p, n);
27933 if( !pNew ){
27934 sqlite3OomFault(db);
27935 }
27936 sqlite3MemdebugSetType(pNew,
27937 (db->lookaside.bDisable==0 ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
@@ -29001,11 +29004,11 @@
29004 p->nAlloc = (int)szNew;
29005 }
29006 if( p->db ){
29007 zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc);
29008 }else{
29009 zNew = sqlite3Realloc(zOld, p->nAlloc);
29010 }
29011 if( zNew ){
29012 assert( p->zText!=0 || p->nChar==0 );
29013 if( !isMalloced(p) && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
29014 p->zText = zNew;
@@ -29343,11 +29346,11 @@
29346 ** and segfaults if you give it a long long int.
29347 */
29348 SQLITE_PRIVATE void sqlite3DebugPrintf(const char *zFormat, ...){
29349 va_list ap;
29350 StrAccum acc;
29351 char zBuf[SQLITE_PRINT_BUF_SIZE*10];
29352 sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
29353 va_start(ap,zFormat);
29354 sqlite3_str_vappendf(&acc, zFormat, ap);
29355 va_end(ap);
29356 sqlite3StrAccumFinish(&acc);
@@ -45048,10 +45051,11 @@
45051 }
45052
45053 /* Forward references to VFS helper methods used for temporary files */
45054 static int winGetTempname(sqlite3_vfs *, char **);
45055 static int winIsDir(const void *);
45056 static BOOL winIsLongPathPrefix(const char *);
45057 static BOOL winIsDriveLetterAndColon(const char *);
45058
45059 /*
45060 ** Control and query of the open file handle.
45061 */
@@ -46817,11 +46821,13 @@
46821 pFile->pVfs = pVfs;
46822 pFile->h = h;
46823 if( isReadonly ){
46824 pFile->ctrlFlags |= WINFILE_RDONLY;
46825 }
46826 if( (flags & SQLITE_OPEN_MAIN_DB)
46827 && sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE)
46828 ){
46829 pFile->ctrlFlags |= WINFILE_PSOW;
46830 }
46831 pFile->lastErrno = NO_ERROR;
46832 pFile->zPath = zName;
46833 #if SQLITE_MAX_MMAP_SIZE>0
@@ -47026,10 +47032,21 @@
47032 *pResOut = rc;
47033 OSTRACE(("ACCESS name=%s, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n",
47034 zFilename, pResOut, *pResOut));
47035 return SQLITE_OK;
47036 }
47037
47038 /*
47039 ** Returns non-zero if the specified path name starts with the "long path"
47040 ** prefix.
47041 */
47042 static BOOL winIsLongPathPrefix(
47043 const char *zPathname
47044 ){
47045 return ( zPathname[0]=='\\' && zPathname[1]=='\\'
47046 && zPathname[2]=='?' && zPathname[3]=='\\' );
47047 }
47048
47049 /*
47050 ** Returns non-zero if the specified path name starts with a drive letter
47051 ** followed by a colon character.
47052 */
@@ -47091,14 +47108,15 @@
47108 DWORD nByte;
47109 void *zConverted;
47110 char *zOut;
47111 #endif
47112
47113 /* If this path name begins with "/X:" or "\\?\", where "X" is any
47114 ** alphabetic character, discard the initial "/" from the pathname.
47115 */
47116 if( zRelative[0]=='/' && (winIsDriveLetterAndColon(zRelative+1)
47117 || winIsLongPathPrefix(zRelative+1)) ){
47118 zRelative++;
47119 }
47120
47121 #if defined(__CYGWIN__)
47122 SimulateIOError( return SQLITE_ERROR );
@@ -47850,11 +47868,11 @@
47868 if( newSz>p->szMax ){
47869 return SQLITE_FULL;
47870 }
47871 newSz *= 2;
47872 if( newSz>p->szMax ) newSz = p->szMax;
47873 pNew = sqlite3Realloc(p->aData, newSz);
47874 if( pNew==0 ) return SQLITE_NOMEM;
47875 p->aData = pNew;
47876 p->szAlloc = newSz;
47877 return SQLITE_OK;
47878 }
@@ -59820,11 +59838,11 @@
59838
59839 /* Enlarge the pWal->apWiData[] array if required */
59840 if( pWal->nWiData<=iPage ){
59841 sqlite3_int64 nByte = sizeof(u32*)*(iPage+1);
59842 volatile u32 **apNew;
59843 apNew = (volatile u32 **)sqlite3Realloc((void *)pWal->apWiData, nByte);
59844 if( !apNew ){
59845 *ppPage = 0;
59846 return SQLITE_NOMEM_BKPT;
59847 }
59848 memset((void*)&apNew[pWal->nWiData], 0,
@@ -59941,29 +59959,47 @@
59959
59960 aOut[0] = s1;
59961 aOut[1] = s2;
59962 }
59963
59964 /*
59965 ** If there is the possibility of concurrent access to the SHM file
59966 ** from multiple threads and/or processes, then do a memory barrier.
59967 */
59968 static void walShmBarrier(Wal *pWal){
59969 if( pWal->exclusiveMode!=WAL_HEAPMEMORY_MODE ){
59970 sqlite3OsShmBarrier(pWal->pDbFd);
59971 }
59972 }
59973
59974 /*
59975 ** Add the SQLITE_NO_TSAN as part of the return-type of a function
59976 ** definition as a hint that the function contains constructs that
59977 ** might give false-positive TSAN warnings.
59978 **
59979 ** See tag-20200519-1.
59980 */
59981 #if defined(__clang__) && !defined(SQLITE_NO_TSAN)
59982 # define SQLITE_NO_TSAN __attribute__((no_sanitize_thread))
59983 #else
59984 # define SQLITE_NO_TSAN
59985 #endif
59986
59987 /*
59988 ** Write the header information in pWal->hdr into the wal-index.
59989 **
59990 ** The checksum on pWal->hdr is updated before it is written.
59991 */
59992 static SQLITE_NO_TSAN void walIndexWriteHdr(Wal *pWal){
59993 volatile WalIndexHdr *aHdr = walIndexHdr(pWal);
59994 const int nCksum = offsetof(WalIndexHdr, aCksum);
59995
59996 assert( pWal->writeLock );
59997 pWal->hdr.isInit = 1;
59998 pWal->hdr.iVersion = WALINDEX_MAX_VERSION;
59999 walChecksumBytes(1, (u8*)&pWal->hdr, nCksum, 0, pWal->hdr.aCksum);
60000 /* Possible TSAN false-positive. See tag-20200519-1 */
60001 memcpy((void*)&aHdr[1], (const void*)&pWal->hdr, sizeof(WalIndexHdr));
60002 walShmBarrier(pWal);
60003 memcpy((void*)&aHdr[0], (const void*)&pWal->hdr, sizeof(WalIndexHdr));
60004 }
60005
@@ -61074,11 +61110,11 @@
61110 pWal->nCkpt++;
61111 pWal->hdr.mxFrame = 0;
61112 sqlite3Put4byte((u8*)&aSalt[0], 1 + sqlite3Get4byte((u8*)&aSalt[0]));
61113 memcpy(&pWal->hdr.aSalt[1], &salt1, 4);
61114 walIndexWriteHdr(pWal);
61115 AtomicStore(&pInfo->nBackfill, 0);
61116 pInfo->nBackfillAttempted = 0;
61117 pInfo->aReadMark[1] = 0;
61118 for(i=2; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED;
61119 assert( pInfo->aReadMark[0]==0 );
61120 }
@@ -61149,36 +61185,17 @@
61185 ** cannot be backfilled from the WAL.
61186 */
61187 mxSafeFrame = pWal->hdr.mxFrame;
61188 mxPage = pWal->hdr.nPage;
61189 for(i=1; i<WAL_NREADER; i++){
61190 u32 y = AtomicLoad(pInfo->aReadMark+i);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61191 if( mxSafeFrame>y ){
61192 assert( y<=pWal->hdr.mxFrame );
61193 rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1);
61194 if( rc==SQLITE_OK ){
61195 u32 iMark = (i==1 ? mxSafeFrame : READMARK_NOT_USED);
61196 AtomicStore(pInfo->aReadMark+i, iMark);
61197 walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
61198 }else if( rc==SQLITE_BUSY ){
61199 mxSafeFrame = y;
61200 xBusy = 0;
61201 }else{
@@ -61192,11 +61209,11 @@
61209 rc = walIteratorInit(pWal, pInfo->nBackfill, &pIter);
61210 assert( rc==SQLITE_OK || pIter==0 );
61211 }
61212
61213 if( pIter
61214 && (rc = walBusyLock(pWal,xBusy,pBusyArg,WAL_READ_LOCK(0),1))==SQLITE_OK
61215 ){
61216 u32 nBackfill = pInfo->nBackfill;
61217
61218 pInfo->nBackfillAttempted = mxSafeFrame;
61219
@@ -61248,11 +61265,11 @@
61265 if( rc==SQLITE_OK ){
61266 rc = sqlite3OsSync(pWal->pDbFd, CKPT_SYNC_FLAGS(sync_flags));
61267 }
61268 }
61269 if( rc==SQLITE_OK ){
61270 AtomicStore(&pInfo->nBackfill, mxSafeFrame);
61271 }
61272 }
61273
61274 /* Release the reader lock held while backfilling */
61275 walUnlockExclusive(pWal, WAL_READ_LOCK(0), 1);
@@ -61407,11 +61424,11 @@
61424 ** and *pChanged is set to 1.
61425 **
61426 ** If the checksum cannot be verified return non-zero. If the header
61427 ** is read successfully and the checksum verified, return zero.
61428 */
61429 static SQLITE_NO_TSAN int walIndexTryHdr(Wal *pWal, int *pChanged){
61430 u32 aCksum[2]; /* Checksum on the header content */
61431 WalIndexHdr h1, h2; /* Two copies of the header content */
61432 WalIndexHdr volatile *aHdr; /* Header in shared memory */
61433
61434 /* The first page of the wal-index must be mapped at this point. */
@@ -61420,17 +61437,23 @@
61437 /* Read the header. This might happen concurrently with a write to the
61438 ** same area of shared memory on a different CPU in a SMP,
61439 ** meaning it is possible that an inconsistent snapshot is read
61440 ** from the file. If this happens, return non-zero.
61441 **
61442 ** tag-20200519-1:
61443 ** There are two copies of the header at the beginning of the wal-index.
61444 ** When reading, read [0] first then [1]. Writes are in the reverse order.
61445 ** Memory barriers are used to prevent the compiler or the hardware from
61446 ** reordering the reads and writes. TSAN and similar tools can sometimes
61447 ** give false-positive warnings about these accesses because the tools do not
61448 ** account for the double-read and the memory barrier. The use of mutexes
61449 ** here would be problematic as the memory being accessed is potentially
61450 ** shared among multiple processes and not all mutex implementions work
61451 ** reliably in that environment.
61452 */
61453 aHdr = walIndexHdr(pWal);
61454 memcpy(&h1, (void *)&aHdr[0], sizeof(h1)); /* Possible TSAN false-positive */
61455 walShmBarrier(pWal);
61456 memcpy(&h2, (void *)&aHdr[1], sizeof(h2));
61457
61458 if( memcmp(&h1, &h2, sizeof(h1))!=0 ){
61459 return 1; /* Dirty read */
@@ -61871,11 +61894,11 @@
61894 }
61895
61896 assert( pWal->nWiData>0 );
61897 assert( pWal->apWiData[0]!=0 );
61898 pInfo = walCkptInfo(pWal);
61899 if( !useWal && AtomicLoad(&pInfo->nBackfill)==pWal->hdr.mxFrame
61900 #ifdef SQLITE_ENABLE_SNAPSHOT
61901 && (pWal->pSnapshot==0 || pWal->hdr.mxFrame==0)
61902 #endif
61903 ){
61904 /* The WAL has been completely backfilled (or it is empty).
@@ -62038,11 +62061,11 @@
62061 void *pBuf2 = sqlite3_malloc(szPage);
62062 if( pBuf1==0 || pBuf2==0 ){
62063 rc = SQLITE_NOMEM;
62064 }else{
62065 u32 i = pInfo->nBackfillAttempted;
62066 for(i=pInfo->nBackfillAttempted; i>AtomicLoad(&pInfo->nBackfill); i--){
62067 WalHashLoc sLoc; /* Hash table location */
62068 u32 pgno; /* Page number in db file */
62069 i64 iDbOff; /* Offset of db file entry */
62070 i64 iWalOff; /* Offset of wal file entry */
62071
@@ -62267,26 +62290,28 @@
62290 for(iHash=walFramePage(iLast); iHash>=iMinHash; iHash--){
62291 WalHashLoc sLoc; /* Hash table location */
62292 int iKey; /* Hash slot index */
62293 int nCollide; /* Number of hash collisions remaining */
62294 int rc; /* Error code */
62295 u32 iH;
62296
62297 rc = walHashGet(pWal, iHash, &sLoc);
62298 if( rc!=SQLITE_OK ){
62299 return rc;
62300 }
62301 nCollide = HASHTABLE_NSLOT;
62302 iKey = walHash(pgno);
62303 while( (iH = AtomicLoad(&sLoc.aHash[iKey]))!=0 ){
62304 u32 iFrame = iH + sLoc.iZero;
62305 if( iFrame<=iLast && iFrame>=pWal->minFrame && sLoc.aPgno[iH]==pgno ){
62306 assert( iFrame>iRead || CORRUPT_DB );
62307 iRead = iFrame;
62308 }
62309 if( (nCollide--)==0 ){
62310 return SQLITE_CORRUPT_BKPT;
62311 }
62312 iKey = walNextHash(iKey);
62313 }
62314 if( iRead ) break;
62315 }
62316
62317 #ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
@@ -79307,10 +79332,11 @@
79332 char *zP4;
79333 char *zCom;
79334 sqlite3 dummyDb;
79335 static const char *zFormat1 = "%4d %-13s %4d %4d %4d %-13s %.2X %s\n";
79336 if( pOut==0 ) pOut = stdout;
79337 sqlite3BeginBenignMalloc();
79338 dummyDb.mallocFailed = 1;
79339 zP4 = sqlite3VdbeDisplayP4(&dummyDb, pOp);
79340 #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
79341 zCom = sqlite3VdbeDisplayComment(0, pOp, zP4);
79342 #else
@@ -79325,10 +79351,11 @@
79351 zCom ? zCom : ""
79352 );
79353 fflush(pOut);
79354 sqlite3_free(zP4);
79355 sqlite3_free(zCom);
79356 sqlite3EndBenignMalloc();
79357 }
79358 #endif
79359
79360 /*
79361 ** Initialize an array of N Mem element.
@@ -84066,11 +84093,11 @@
84093 p->db->errCode = SQLITE_OK;
84094
84095 /* If the bit corresponding to this variable in Vdbe.expmask is set, then
84096 ** binding a new value to this variable invalidates the current query plan.
84097 **
84098 ** IMPLEMENTATION-OF: R-57496-20354 If the specific value bound to a host
84099 ** parameter in the WHERE clause might influence the choice of query plan
84100 ** for a statement, then the statement will be automatically recompiled,
84101 ** as if there had been a schema change, on the first sqlite3_step() call
84102 ** following any change to the bindings of that parameter.
84103 */
@@ -96365,12 +96392,12 @@
96392 *************************************************************************
96393 **
96394 ** This file implements virtual-tables for examining the bytecode content
96395 ** of a prepared statement.
96396 */
 
96397 /* #include "sqliteInt.h" */
96398 #if defined(SQLITE_ENABLE_BYTECODE_VTAB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
96399 /* #include "vdbeInt.h" */
96400
96401 /* An instance of the bytecode() table-valued function.
96402 */
96403 typedef struct bytecodevtab bytecodevtab;
@@ -96771,10 +96798,12 @@
96798 if( rc==SQLITE_OK ){
96799 rc = sqlite3_create_module(db, "tables_used", &bytecodevtabModule, &db);
96800 }
96801 return rc;
96802 }
96803 #elif defined(SQLITE_ENABLE_BYTECODE_VTAB)
96804 SQLITE_PRIVATE int sqlite3VdbeBytecodeVtabInit(sqlite3 *db){ return SQLITE_OK; }
96805 #endif /* SQLITE_ENABLE_BYTECODE_VTAB */
96806
96807 /************** End of vdbevtab.c ********************************************/
96808 /************** Begin file memjournal.c **************************************/
96809 /*
@@ -103075,10 +103104,17 @@
103104 }
103105 setDoNotMergeFlagOnCopy(v);
103106 sqlite3VdbeResolveLabel(v, endCoalesce);
103107 break;
103108 }
103109 case INLINEFUNC_iif: {
103110 Expr caseExpr;
103111 memset(&caseExpr, 0, sizeof(caseExpr));
103112 caseExpr.op = TK_CASE;
103113 caseExpr.x.pList = pFarg;
103114 return sqlite3ExprCodeTarget(pParse, &caseExpr, target);
103115 }
103116
103117 default: {
103118 /* The UNLIKELY() function is a no-op. The result is the value
103119 ** of the first argument.
103120 */
@@ -105497,11 +105533,14 @@
105533 if( !zName ) goto exit_rename_table;
105534
105535 /* Check that a table or index named 'zName' does not already exist
105536 ** in database iDb. If so, this is an error.
105537 */
105538 if( sqlite3FindTable(db, zName, zDb)
105539 || sqlite3FindIndex(db, zName, zDb)
105540 || sqlite3IsShadowTableOf(db, pTab, zName)
105541 ){
105542 sqlite3ErrorMsg(pParse,
105543 "there is already another table or index with this name: %s", zName);
105544 goto exit_rename_table;
105545 }
105546
@@ -110244,26 +110283,43 @@
110283 ** exists */
110284 if( db->auth.authLevel<UAUTH_Admin && sqlite3UserAuthTable(zName)!=0 ){
110285 return 0;
110286 }
110287 #endif
110288 if( zDatabase ){
110289 for(i=0; i<db->nDb; i++){
110290 if( sqlite3StrICmp(zDatabase, db->aDb[i].zDbSName)==0 ) break;
110291 }
110292 if( i>=db->nDb ){
110293 /* No match against the official names. But always match "main"
110294 ** to schema 0 as a legacy fallback. */
110295 if( sqlite3StrICmp(zDatabase,"main")==0 ){
110296 i = 0;
110297 }else{
110298 return 0;
110299 }
110300 }
110301 p = sqlite3HashFind(&db->aDb[i].pSchema->tblHash, zName);
110302 if( p==0 && i==1 && sqlite3StrICmp(zName, MASTER_NAME)==0 ){
110303 /* All temp.sqlite_master to be an alias for sqlite_temp_master */
110304 p = sqlite3HashFind(&db->aDb[1].pSchema->tblHash, TEMP_MASTER_NAME);
110305 }
110306 }else{
110307 /* Match against TEMP first */
110308 p = sqlite3HashFind(&db->aDb[1].pSchema->tblHash, zName);
110309 if( p ) return p;
110310 /* The main database is second */
110311 p = sqlite3HashFind(&db->aDb[0].pSchema->tblHash, zName);
110312 if( p ) return p;
110313 /* Attached databases are in order of attachment */
110314 for(i=2; i<db->nDb; i++){
110315 assert( sqlite3SchemaMutexHeld(db, i, 0) );
110316 p = sqlite3HashFind(&db->aDb[i].pSchema->tblHash, zName);
110317 if( p ) break;
110318 }
110319 }
110320 return p;
110321 }
110322
110323 /*
110324 ** Locate the in-memory structure that describes a particular database
110325 ** table given the name of that table and (optionally) the name of the
@@ -112063,10 +112119,32 @@
112119 assert( pPk->nColumn==j );
112120 assert( pTab->nNVCol<=j );
112121 recomputeColumnsNotIndexed(pPk);
112122 }
112123
112124
112125 #ifndef SQLITE_OMIT_VIRTUALTABLE
112126 /*
112127 ** Return true if pTab is a virtual table and zName is a shadow table name
112128 ** for that virtual table.
112129 */
112130 SQLITE_PRIVATE int sqlite3IsShadowTableOf(sqlite3 *db, Table *pTab, const char *zName){
112131 int nName; /* Length of zName */
112132 Module *pMod; /* Module for the virtual table */
112133
112134 if( !IsVirtual(pTab) ) return 0;
112135 nName = sqlite3Strlen30(pTab->zName);
112136 if( sqlite3_strnicmp(zName, pTab->zName, nName)!=0 ) return 0;
112137 if( zName[nName]!='_' ) return 0;
112138 pMod = (Module*)sqlite3HashFind(&db->aModule, pTab->azModuleArg[0]);
112139 if( pMod==0 ) return 0;
112140 if( pMod->pModule->iVersion<3 ) return 0;
112141 if( pMod->pModule->xShadowName==0 ) return 0;
112142 return pMod->pModule->xShadowName(zName+nName+1);
112143 }
112144 #endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
112145
112146 #ifndef SQLITE_OMIT_VIRTUALTABLE
112147 /*
112148 ** Return true if zName is a shadow table name in the current database
112149 ** connection.
112150 **
@@ -112074,26 +112152,21 @@
112152 ** restored to its original value prior to this routine returning.
112153 */
112154 SQLITE_PRIVATE int sqlite3ShadowTableName(sqlite3 *db, const char *zName){
112155 char *zTail; /* Pointer to the last "_" in zName */
112156 Table *pTab; /* Table that zName is a shadow of */
 
 
112157 zTail = strrchr(zName, '_');
112158 if( zTail==0 ) return 0;
112159 *zTail = 0;
112160 pTab = sqlite3FindTable(db, zName, 0);
112161 *zTail = '_';
112162 if( pTab==0 ) return 0;
112163 if( !IsVirtual(pTab) ) return 0;
112164 return sqlite3IsShadowTableOf(db, pTab, zName);
 
 
 
 
112165 }
112166 #endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
112167
112168
112169 #ifdef SQLITE_DEBUG
112170 /*
112171 ** Mark all nodes of an expression as EP_Immutable, indicating that
112172 ** they should not be changed. Expressions attached to a table or
@@ -117780,11 +117853,11 @@
117853 if( (cntExpand&(cntExpand-1))==0 ){
117854 /* Grow the size of the output buffer only on substitutions
117855 ** whose index is a power of two: 1, 2, 4, 8, 16, 32, ... */
117856 u8 *zOld;
117857 zOld = zOut;
117858 zOut = sqlite3Realloc(zOut, (int)nOut + (nOut - nStr - 1));
117859 if( zOut==0 ){
117860 sqlite3_result_error_nomem(context);
117861 sqlite3_free(zOld);
117862 return;
117863 }
@@ -118477,11 +118550,11 @@
118550 FUNCTION(round, 2, 0, 0, roundFunc ),
118551 #endif
118552 FUNCTION(upper, 1, 0, 0, upperFunc ),
118553 FUNCTION(lower, 1, 0, 0, lowerFunc ),
118554 FUNCTION(hex, 1, 0, 0, hexFunc ),
118555 INLINE_FUNC(ifnull, 2, INLINEFUNC_coalesce, 0 ),
118556 VFUNCTION(random, 0, 0, 0, randomFunc ),
118557 VFUNCTION(randomblob, 1, 0, 0, randomBlob ),
118558 FUNCTION(nullif, 2, 0, 1, nullifFunc ),
118559 DFUNCTION(sqlite_version, 0, 0, 0, versionFunc ),
118560 DFUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ),
@@ -118517,11 +118590,12 @@
118590 #ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
118591 FUNCTION(unknown, -1, 0, 0, unknownFunc ),
118592 #endif
118593 FUNCTION(coalesce, 1, 0, 0, 0 ),
118594 FUNCTION(coalesce, 0, 0, 0, 0 ),
118595 INLINE_FUNC(coalesce, -1, INLINEFUNC_coalesce, 0 ),
118596 INLINE_FUNC(iif, 3, INLINEFUNC_iif, 0 ),
118597 };
118598 #ifndef SQLITE_OMIT_ALTERTABLE
118599 sqlite3AlterFunctions();
118600 #endif
118601 sqlite3WindowFunctions();
@@ -135570,11 +135644,11 @@
135644 need = nCol;
135645 }
135646 if( p->nData + need > p->nAlloc ){
135647 char **azNew;
135648 p->nAlloc = p->nAlloc*2 + need;
135649 azNew = sqlite3Realloc( p->azResult, sizeof(char*)*p->nAlloc );
135650 if( azNew==0 ) goto malloc_failed;
135651 p->azResult = azNew;
135652 }
135653
135654 /* If this is the first row, then generate an extra row containing
@@ -135679,11 +135753,11 @@
135753 sqlite3_free_table(&res.azResult[1]);
135754 return rc;
135755 }
135756 if( res.nAlloc>res.nData ){
135757 char **azNew;
135758 azNew = sqlite3Realloc( res.azResult, sizeof(char*)*res.nData );
135759 if( azNew==0 ){
135760 sqlite3_free_table(&res.azResult[1]);
135761 db->errCode = SQLITE_NOMEM;
135762 return SQLITE_NOMEM_BKPT;
135763 }
@@ -136969,14 +137043,14 @@
137043 ** Therefore, the P4 parameter is only required if the default value for
137044 ** the column is a literal number, string or null. The sqlite3ValueFromExpr()
137045 ** function is capable of transforming these types of expressions into
137046 ** sqlite3_value objects.
137047 **
137048 ** If column as REAL affinity and the table is an ordinary b-tree table
137049 ** (not a virtual table) then the value might have been stored as an
137050 ** integer. In that case, add an OP_RealAffinity opcode to make sure
137051 ** it has been converted into REAL.
137052 */
137053 SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){
137054 assert( pTab!=0 );
137055 if( !pTab->pSelect ){
137056 sqlite3_value *pValue = 0;
@@ -136989,11 +137063,11 @@
137063 if( pValue ){
137064 sqlite3VdbeAppendP4(v, pValue, P4_MEM);
137065 }
137066 }
137067 #ifndef SQLITE_OMIT_FLOATING_POINT
137068 if( pTab->aCol[i].affinity==SQLITE_AFF_REAL && !IsVirtual(pTab) ){
137069 sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg);
137070 }
137071 #endif
137072 }
137073
@@ -139838,11 +139912,11 @@
139912 assert( IsVirtual(pTab) );
139913 for(i=0; i<pToplevel->nVtabLock; i++){
139914 if( pTab==pToplevel->apVtabLock[i] ) return;
139915 }
139916 n = (pToplevel->nVtabLock+1)*sizeof(pToplevel->apVtabLock[0]);
139917 apVtabLock = sqlite3Realloc(pToplevel->apVtabLock, n);
139918 if( apVtabLock ){
139919 pToplevel->apVtabLock = apVtabLock;
139920 pToplevel->apVtabLock[pToplevel->nVtabLock++] = pTab;
139921 }else{
139922 sqlite3OomFault(pToplevel->db);
@@ -151130,17 +151204,23 @@
151204 ){
151205 if( pAppend ){
151206 int i;
151207 int nInit = pList ? pList->nExpr : 0;
151208 for(i=0; i<pAppend->nExpr; i++){
 
151209 Expr *pDup = sqlite3ExprDup(pParse->db, pAppend->a[i].pExpr, 0);
151210 assert( pDup==0 || !ExprHasProperty(pDup, EP_MemToken) );
151211 if( bIntToNull && pDup ){
151212 int iDummy;
151213 Expr *pSub;
151214 for(pSub=pDup; ExprHasProperty(pSub, EP_Skip); pSub=pSub->pLeft){
151215 assert( pSub );
151216 }
151217 if( sqlite3ExprIsInteger(pSub, &iDummy) ){
151218 pSub->op = TK_NULL;
151219 pSub->flags &= ~(EP_IntValue|EP_IsTrue|EP_IsFalse);
151220 pSub->u.zToken = 0;
151221 }
151222 }
151223 pList = sqlite3ExprListAppend(pParse, pList, pDup);
151224 if( pList ) pList->a[nInit+i].sortFlags = pAppend->a[i].sortFlags;
151225 }
151226 }
@@ -160322,10 +160402,11 @@
160402 }
160403 #endif
160404 if( rc==SQLITE_OK ){
160405 sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage,
160406 sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage);
160407 sqlite3MemoryBarrier();
160408 sqlite3GlobalConfig.isInit = 1;
160409 #ifdef SQLITE_EXTRA_INIT
160410 bRunExtraInit = 1;
160411 #endif
160412 }
@@ -163270,11 +163351,11 @@
163351 assert( SQLITE_OPEN_CREATE == 0x04 );
163352 testcase( (1<<(flags&7))==0x02 ); /* READONLY */
163353 testcase( (1<<(flags&7))==0x04 ); /* READWRITE */
163354 testcase( (1<<(flags&7))==0x40 ); /* READWRITE | CREATE */
163355 if( ((1<<(flags&7)) & 0x46)==0 ){
163356 rc = SQLITE_MISUSE_BKPT; /* IMP: R-18321-05872 */
163357 }else{
163358 rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg);
163359 }
163360 if( rc!=SQLITE_OK ){
163361 if( rc==SQLITE_NOMEM ) sqlite3OomFault(db);
@@ -171194,10 +171275,11 @@
171275 while( *pRc==SQLITE_OK && pLeft->bEof==0 ){
171276 memset(pDl->pList, 0, pDl->nList);
171277 fts3EvalNextRow(pCsr, pLeft, pRc);
171278 }
171279 }
171280 pRight->bEof = pLeft->bEof = 1;
171281 }
171282 }
171283 break;
171284 }
171285
@@ -182739,11 +182821,11 @@
182821 iStart = pExpr->iPhrase * p->nCol;
182822 }else{
182823 iStart = pExpr->iPhrase * ((p->nCol + 31) / 32);
182824 }
182825
182826 if( pIter ) while( 1 ){
182827 int nHit = fts3ColumnlistCount(&pIter);
182828 if( (pPhrase->iColumn>=pTab->nColumn || pPhrase->iColumn==iCol) ){
182829 if( p->flag==FTS3_MATCHINFO_LHITS ){
182830 p->aMatchinfo[iStart + iCol] = (u32)nHit;
182831 }else if( nHit ){
@@ -184653,10 +184735,11 @@
184735 }
184736
184737 /* Append N bytes from zIn onto the end of the JsonString string.
184738 */
184739 static void jsonAppendRaw(JsonString *p, const char *zIn, u32 N){
184740 if( N==0 ) return;
184741 if( (N+p->nUsed >= p->nAlloc) && jsonGrow(p,N)!=0 ) return;
184742 memcpy(p->zBuf+p->nUsed, zIn, N);
184743 p->nUsed += N;
184744 }
184745
@@ -224664,11 +224747,11 @@
224747 int nArg, /* Number of args */
224748 sqlite3_value **apUnused /* Function arguments */
224749 ){
224750 assert( nArg==0 );
224751 UNUSED_PARAM2(nArg, apUnused);
224752 sqlite3_result_text(pCtx, "fts5: 2020-05-19 15:51:10 3117c1b5a9e348fd8d16ba9d03fdafaad8514567fb3403f72b86d6162ad40bde", -1, SQLITE_TRANSIENT);
224753 }
224754
224755 /*
224756 ** Return true if zName is the extension on one of the shadow tables used
224757 ** by this module.
@@ -229447,12 +229530,12 @@
229530 }
229531 #endif /* SQLITE_CORE */
229532 #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
229533
229534 /************** End of stmt.c ************************************************/
229535 #if __LINE__!=229535
229536 #undef SQLITE_SOURCE_ID
229537 #define SQLITE_SOURCE_ID "2020-05-19 15:51:10 3117c1b5a9e348fd8d16ba9d03fdafaad8514567fb3403f72b86d6162ad4alt2"
229538 #endif
229539 /* Return the source-id for this library */
229540 SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
229541 /************************** End of sqlite3.c ******************************/
229542
+2 -2
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -123,11 +123,11 @@
123123
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
124124
** [sqlite_version()] and [sqlite_source_id()].
125125
*/
126126
#define SQLITE_VERSION "3.32.0"
127127
#define SQLITE_VERSION_NUMBER 3032000
128
-#define SQLITE_SOURCE_ID "2020-05-08 19:02:21 3a16c0ce4d8851f79f670d94786032c8007619154ece44647dc9cc5b1f9654ff"
128
+#define SQLITE_SOURCE_ID "2020-05-19 15:51:10 3117c1b5a9e348fd8d16ba9d03fdafaad8514567fb3403f72b86d6162ad40bde"
129129
130130
/*
131131
** CAPI3REF: Run-Time Library Version Numbers
132132
** KEYWORDS: sqlite3_version sqlite3_sourceid
133133
**
@@ -5493,11 +5493,11 @@
54935493
** when first called if N is less than or equal to zero or if a memory
54945494
** allocate error occurs.
54955495
**
54965496
** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is
54975497
** determined by the N parameter on first successful call. Changing the
5498
-** value of N in any subsequents call to sqlite3_aggregate_context() within
5498
+** value of N in any subsequent call to sqlite3_aggregate_context() within
54995499
** the same aggregate function instance will not resize the memory
55005500
** allocation.)^ Within the xFinal callback, it is customary to set
55015501
** N=0 in calls to sqlite3_aggregate_context(C,N) so that no
55025502
** pointless memory allocations occur.
55035503
**
55045504
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -123,11 +123,11 @@
123 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
124 ** [sqlite_version()] and [sqlite_source_id()].
125 */
126 #define SQLITE_VERSION "3.32.0"
127 #define SQLITE_VERSION_NUMBER 3032000
128 #define SQLITE_SOURCE_ID "2020-05-08 19:02:21 3a16c0ce4d8851f79f670d94786032c8007619154ece44647dc9cc5b1f9654ff"
129
130 /*
131 ** CAPI3REF: Run-Time Library Version Numbers
132 ** KEYWORDS: sqlite3_version sqlite3_sourceid
133 **
@@ -5493,11 +5493,11 @@
5493 ** when first called if N is less than or equal to zero or if a memory
5494 ** allocate error occurs.
5495 **
5496 ** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is
5497 ** determined by the N parameter on first successful call. Changing the
5498 ** value of N in any subsequents call to sqlite3_aggregate_context() within
5499 ** the same aggregate function instance will not resize the memory
5500 ** allocation.)^ Within the xFinal callback, it is customary to set
5501 ** N=0 in calls to sqlite3_aggregate_context(C,N) so that no
5502 ** pointless memory allocations occur.
5503 **
5504
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -123,11 +123,11 @@
123 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
124 ** [sqlite_version()] and [sqlite_source_id()].
125 */
126 #define SQLITE_VERSION "3.32.0"
127 #define SQLITE_VERSION_NUMBER 3032000
128 #define SQLITE_SOURCE_ID "2020-05-19 15:51:10 3117c1b5a9e348fd8d16ba9d03fdafaad8514567fb3403f72b86d6162ad40bde"
129
130 /*
131 ** CAPI3REF: Run-Time Library Version Numbers
132 ** KEYWORDS: sqlite3_version sqlite3_sourceid
133 **
@@ -5493,11 +5493,11 @@
5493 ** when first called if N is less than or equal to zero or if a memory
5494 ** allocate error occurs.
5495 **
5496 ** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is
5497 ** determined by the N parameter on first successful call. Changing the
5498 ** value of N in any subsequent call to sqlite3_aggregate_context() within
5499 ** the same aggregate function instance will not resize the memory
5500 ** allocation.)^ Within the xFinal callback, it is customary to set
5501 ** N=0 in calls to sqlite3_aggregate_context(C,N) so that no
5502 ** pointless memory allocations occur.
5503 **
5504
+1 -1
--- src/th_main.c
+++ src/th_main.c
@@ -1500,11 +1500,11 @@
15001500
if( argc!=3 ){
15011501
return Th_WrongNumArgs(interp, "unversioned content FILENAME");
15021502
}
15031503
if( Th_IsRepositoryOpen() ){
15041504
Blob content;
1505
- if( unversioned_content(argv[2], &content)==0 ){
1505
+ if( unversioned_content(argv[2], &content)!=0 ){
15061506
Th_SetResult(interp, blob_str(&content), blob_size(&content));
15071507
blob_reset(&content);
15081508
return TH_OK;
15091509
}else{
15101510
return TH_ERROR;
15111511
--- src/th_main.c
+++ src/th_main.c
@@ -1500,11 +1500,11 @@
1500 if( argc!=3 ){
1501 return Th_WrongNumArgs(interp, "unversioned content FILENAME");
1502 }
1503 if( Th_IsRepositoryOpen() ){
1504 Blob content;
1505 if( unversioned_content(argv[2], &content)==0 ){
1506 Th_SetResult(interp, blob_str(&content), blob_size(&content));
1507 blob_reset(&content);
1508 return TH_OK;
1509 }else{
1510 return TH_ERROR;
1511
--- src/th_main.c
+++ src/th_main.c
@@ -1500,11 +1500,11 @@
1500 if( argc!=3 ){
1501 return Th_WrongNumArgs(interp, "unversioned content FILENAME");
1502 }
1503 if( Th_IsRepositoryOpen() ){
1504 Blob content;
1505 if( unversioned_content(argv[2], &content)!=0 ){
1506 Th_SetResult(interp, blob_str(&content), blob_size(&content));
1507 blob_reset(&content);
1508 return TH_OK;
1509 }else{
1510 return TH_ERROR;
1511
--- src/timeline.c
+++ src/timeline.c
@@ -1796,10 +1796,11 @@
17961796
}else if( fossil_stricmp(zMatchStyle, "regexp")==0 ){
17971797
matchStyle = MS_REGEXP;
17981798
}else{
17991799
/* For exact maching, inhibit links to the selected tag. */
18001800
zThisTag = zTagName;
1801
+ Th_Store("current_checkin", zTagName);
18011802
}
18021803
18031804
/* Display a checkbox to enable/disable display of related check-ins. */
18041805
if( advancedMenu ){
18051806
style_submenu_checkbox("rel", "Related", 0, 0);
@@ -2201,10 +2202,17 @@
22012202
"CREATE TEMP TABLE selected_nodes(rid INTEGER PRIMARY KEY);"
22022203
"INSERT OR IGNORE INTO selected_nodes"
22032204
" SELECT tagxref.rid FROM tagxref NATURAL JOIN tag"
22042205
" WHERE %s AND tagtype>0", zTagSql/*safe-for-%s*/
22052206
);
2207
+ if( zMark ){
2208
+ /* If the t=release option is used with m=UUID, then also
2209
+ ** include the UUID check-in in the display list */
2210
+ int ridMark = name_to_rid(zMark);
2211
+ db_multi_exec(
2212
+ "INSERT OR IGNORE INTO selected_nodes(rid) VALUES(%d)", ridMark);
2213
+ }
22062214
if( !related ){
22072215
blob_append_sql(&cond, " AND blob.rid IN selected_nodes");
22082216
}else{
22092217
db_multi_exec(
22102218
"CREATE TEMP TABLE related_nodes(rid INTEGER PRIMARY KEY);"
@@ -2427,10 +2435,13 @@
24272435
blob_appendf(&desc, " related to tags matching %h", zMatchDesc);
24282436
}else{
24292437
blob_appendf(&desc, " with tags matching %h", zMatchDesc);
24302438
}
24312439
}
2440
+ if( zMark ){
2441
+ blob_appendf(&desc," plus check-in \"%h\"", zMark);
2442
+ }
24322443
tmFlags |= TIMELINE_XMERGE | TIMELINE_FILLGAPS;
24332444
}
24342445
addFileGlobDescription(zChng, &desc);
24352446
if( rAfter>0.0 ){
24362447
if( rBefore>0.0 ){
24372448
--- src/timeline.c
+++ src/timeline.c
@@ -1796,10 +1796,11 @@
1796 }else if( fossil_stricmp(zMatchStyle, "regexp")==0 ){
1797 matchStyle = MS_REGEXP;
1798 }else{
1799 /* For exact maching, inhibit links to the selected tag. */
1800 zThisTag = zTagName;
 
1801 }
1802
1803 /* Display a checkbox to enable/disable display of related check-ins. */
1804 if( advancedMenu ){
1805 style_submenu_checkbox("rel", "Related", 0, 0);
@@ -2201,10 +2202,17 @@
2201 "CREATE TEMP TABLE selected_nodes(rid INTEGER PRIMARY KEY);"
2202 "INSERT OR IGNORE INTO selected_nodes"
2203 " SELECT tagxref.rid FROM tagxref NATURAL JOIN tag"
2204 " WHERE %s AND tagtype>0", zTagSql/*safe-for-%s*/
2205 );
 
 
 
 
 
 
 
2206 if( !related ){
2207 blob_append_sql(&cond, " AND blob.rid IN selected_nodes");
2208 }else{
2209 db_multi_exec(
2210 "CREATE TEMP TABLE related_nodes(rid INTEGER PRIMARY KEY);"
@@ -2427,10 +2435,13 @@
2427 blob_appendf(&desc, " related to tags matching %h", zMatchDesc);
2428 }else{
2429 blob_appendf(&desc, " with tags matching %h", zMatchDesc);
2430 }
2431 }
 
 
 
2432 tmFlags |= TIMELINE_XMERGE | TIMELINE_FILLGAPS;
2433 }
2434 addFileGlobDescription(zChng, &desc);
2435 if( rAfter>0.0 ){
2436 if( rBefore>0.0 ){
2437
--- src/timeline.c
+++ src/timeline.c
@@ -1796,10 +1796,11 @@
1796 }else if( fossil_stricmp(zMatchStyle, "regexp")==0 ){
1797 matchStyle = MS_REGEXP;
1798 }else{
1799 /* For exact maching, inhibit links to the selected tag. */
1800 zThisTag = zTagName;
1801 Th_Store("current_checkin", zTagName);
1802 }
1803
1804 /* Display a checkbox to enable/disable display of related check-ins. */
1805 if( advancedMenu ){
1806 style_submenu_checkbox("rel", "Related", 0, 0);
@@ -2201,10 +2202,17 @@
2202 "CREATE TEMP TABLE selected_nodes(rid INTEGER PRIMARY KEY);"
2203 "INSERT OR IGNORE INTO selected_nodes"
2204 " SELECT tagxref.rid FROM tagxref NATURAL JOIN tag"
2205 " WHERE %s AND tagtype>0", zTagSql/*safe-for-%s*/
2206 );
2207 if( zMark ){
2208 /* If the t=release option is used with m=UUID, then also
2209 ** include the UUID check-in in the display list */
2210 int ridMark = name_to_rid(zMark);
2211 db_multi_exec(
2212 "INSERT OR IGNORE INTO selected_nodes(rid) VALUES(%d)", ridMark);
2213 }
2214 if( !related ){
2215 blob_append_sql(&cond, " AND blob.rid IN selected_nodes");
2216 }else{
2217 db_multi_exec(
2218 "CREATE TEMP TABLE related_nodes(rid INTEGER PRIMARY KEY);"
@@ -2427,10 +2435,13 @@
2435 blob_appendf(&desc, " related to tags matching %h", zMatchDesc);
2436 }else{
2437 blob_appendf(&desc, " with tags matching %h", zMatchDesc);
2438 }
2439 }
2440 if( zMark ){
2441 blob_appendf(&desc," plus check-in \"%h\"", zMark);
2442 }
2443 tmFlags |= TIMELINE_XMERGE | TIMELINE_FILLGAPS;
2444 }
2445 addFileGlobDescription(zChng, &desc);
2446 if( rAfter>0.0 ){
2447 if( rBefore>0.0 ){
2448
--- src/unversioned.c
+++ src/unversioned.c
@@ -85,25 +85,40 @@
8585
}
8686
8787
/*
8888
** Initialize pContent to be the content of an unversioned file zName.
8989
**
90
-** Return 0 on success. Return 1 if zName is not found.
90
+** Return 0 on failures.
91
+** Return 1 if the file is found by name.
92
+** Return 2 if the file is found by hash.
9193
*/
9294
int unversioned_content(const char *zName, Blob *pContent){
9395
Stmt q;
94
- int rc = 1;
96
+ int rc = 0;
9597
blob_init(pContent, 0, 0);
96
- db_prepare(&q, "SELECT encoding, content FROM unversioned WHERE name=%Q", zName);
98
+ db_prepare(&q, "SELECT encoding, content FROM unversioned WHERE name=%Q",
99
+ zName);
97100
if( db_step(&q)==SQLITE_ROW ){
98101
db_column_blob(&q, 1, pContent);
99102
if( db_column_int(&q, 0)==1 ){
100103
blob_uncompress(pContent, pContent);
101104
}
102
- rc = 0;
105
+ rc = 1;
103106
}
104107
db_finalize(&q);
108
+ if( rc==0 && validate16(zName,-1) ){
109
+ db_prepare(&q, "SELECT encoding, content FROM unversioned WHERE hash=%Q",
110
+ zName);
111
+ if( db_step(&q)==SQLITE_ROW ){
112
+ db_column_blob(&q, 1, pContent);
113
+ if( db_column_int(&q, 0)==1 ){
114
+ blob_uncompress(pContent, pContent);
115
+ }
116
+ rc = 2;
117
+ }
118
+ db_finalize(&q);
119
+ }
105120
return rc;
106121
}
107122
108123
/*
109124
** Write unversioned content into the database.
@@ -328,11 +343,11 @@
328343
int i;
329344
verify_all_options();
330345
db_begin_transaction();
331346
for(i=3; i<g.argc; i++){
332347
Blob content;
333
- if( unversioned_content(g.argv[i], &content)==0 ){
348
+ if( unversioned_content(g.argv[i], &content)!=0 ){
334349
blob_write_to_file(&content, "-");
335350
}
336351
blob_reset(&content);
337352
}
338353
db_end_transaction(0);
@@ -352,11 +367,11 @@
352367
}
353368
zTFile = fossil_temp_filename();
354369
if( zTFile==0 ) fossil_fatal("cannot find a temporary filename");
355370
db_begin_transaction();
356371
content_rcvid_init("#!fossil unversioned edit");
357
- if( unversioned_content(zUVFile, &content) ){
372
+ if( unversioned_content(zUVFile, &content)==0 ){
358373
fossil_fatal("no such uv-file: %Q", zUVFile);
359374
}
360375
if( looks_like_binary(&content) ){
361376
fossil_fatal("cannot edit binary content");
362377
}
@@ -381,11 +396,11 @@
381396
blob_reset(&content);
382397
}else if( memcmp(zCmd, "export", nCmd)==0 ){
383398
Blob content;
384399
verify_all_options();
385400
if( g.argc!=5 ) usage("export UVFILE OUTPUT");
386
- if( unversioned_content(g.argv[3], &content) ){
401
+ if( unversioned_content(g.argv[3], &content)==0 ){
387402
fossil_fatal("no such uv-file: %Q", g.argv[3]);
388403
}
389404
blob_write_to_file(&content, g.argv[4]);
390405
blob_reset(&content);
391406
}else if( memcmp(zCmd, "hash", nCmd)==0 ){ /* undocumented */
392407
--- src/unversioned.c
+++ src/unversioned.c
@@ -85,25 +85,40 @@
85 }
86
87 /*
88 ** Initialize pContent to be the content of an unversioned file zName.
89 **
90 ** Return 0 on success. Return 1 if zName is not found.
 
 
91 */
92 int unversioned_content(const char *zName, Blob *pContent){
93 Stmt q;
94 int rc = 1;
95 blob_init(pContent, 0, 0);
96 db_prepare(&q, "SELECT encoding, content FROM unversioned WHERE name=%Q", zName);
 
97 if( db_step(&q)==SQLITE_ROW ){
98 db_column_blob(&q, 1, pContent);
99 if( db_column_int(&q, 0)==1 ){
100 blob_uncompress(pContent, pContent);
101 }
102 rc = 0;
103 }
104 db_finalize(&q);
 
 
 
 
 
 
 
 
 
 
 
 
105 return rc;
106 }
107
108 /*
109 ** Write unversioned content into the database.
@@ -328,11 +343,11 @@
328 int i;
329 verify_all_options();
330 db_begin_transaction();
331 for(i=3; i<g.argc; i++){
332 Blob content;
333 if( unversioned_content(g.argv[i], &content)==0 ){
334 blob_write_to_file(&content, "-");
335 }
336 blob_reset(&content);
337 }
338 db_end_transaction(0);
@@ -352,11 +367,11 @@
352 }
353 zTFile = fossil_temp_filename();
354 if( zTFile==0 ) fossil_fatal("cannot find a temporary filename");
355 db_begin_transaction();
356 content_rcvid_init("#!fossil unversioned edit");
357 if( unversioned_content(zUVFile, &content) ){
358 fossil_fatal("no such uv-file: %Q", zUVFile);
359 }
360 if( looks_like_binary(&content) ){
361 fossil_fatal("cannot edit binary content");
362 }
@@ -381,11 +396,11 @@
381 blob_reset(&content);
382 }else if( memcmp(zCmd, "export", nCmd)==0 ){
383 Blob content;
384 verify_all_options();
385 if( g.argc!=5 ) usage("export UVFILE OUTPUT");
386 if( unversioned_content(g.argv[3], &content) ){
387 fossil_fatal("no such uv-file: %Q", g.argv[3]);
388 }
389 blob_write_to_file(&content, g.argv[4]);
390 blob_reset(&content);
391 }else if( memcmp(zCmd, "hash", nCmd)==0 ){ /* undocumented */
392
--- src/unversioned.c
+++ src/unversioned.c
@@ -85,25 +85,40 @@
85 }
86
87 /*
88 ** Initialize pContent to be the content of an unversioned file zName.
89 **
90 ** Return 0 on failures.
91 ** Return 1 if the file is found by name.
92 ** Return 2 if the file is found by hash.
93 */
94 int unversioned_content(const char *zName, Blob *pContent){
95 Stmt q;
96 int rc = 0;
97 blob_init(pContent, 0, 0);
98 db_prepare(&q, "SELECT encoding, content FROM unversioned WHERE name=%Q",
99 zName);
100 if( db_step(&q)==SQLITE_ROW ){
101 db_column_blob(&q, 1, pContent);
102 if( db_column_int(&q, 0)==1 ){
103 blob_uncompress(pContent, pContent);
104 }
105 rc = 1;
106 }
107 db_finalize(&q);
108 if( rc==0 && validate16(zName,-1) ){
109 db_prepare(&q, "SELECT encoding, content FROM unversioned WHERE hash=%Q",
110 zName);
111 if( db_step(&q)==SQLITE_ROW ){
112 db_column_blob(&q, 1, pContent);
113 if( db_column_int(&q, 0)==1 ){
114 blob_uncompress(pContent, pContent);
115 }
116 rc = 2;
117 }
118 db_finalize(&q);
119 }
120 return rc;
121 }
122
123 /*
124 ** Write unversioned content into the database.
@@ -328,11 +343,11 @@
343 int i;
344 verify_all_options();
345 db_begin_transaction();
346 for(i=3; i<g.argc; i++){
347 Blob content;
348 if( unversioned_content(g.argv[i], &content)!=0 ){
349 blob_write_to_file(&content, "-");
350 }
351 blob_reset(&content);
352 }
353 db_end_transaction(0);
@@ -352,11 +367,11 @@
367 }
368 zTFile = fossil_temp_filename();
369 if( zTFile==0 ) fossil_fatal("cannot find a temporary filename");
370 db_begin_transaction();
371 content_rcvid_init("#!fossil unversioned edit");
372 if( unversioned_content(zUVFile, &content)==0 ){
373 fossil_fatal("no such uv-file: %Q", zUVFile);
374 }
375 if( looks_like_binary(&content) ){
376 fossil_fatal("cannot edit binary content");
377 }
@@ -381,11 +396,11 @@
396 blob_reset(&content);
397 }else if( memcmp(zCmd, "export", nCmd)==0 ){
398 Blob content;
399 verify_all_options();
400 if( g.argc!=5 ) usage("export UVFILE OUTPUT");
401 if( unversioned_content(g.argv[3], &content)==0 ){
402 fossil_fatal("no such uv-file: %Q", g.argv[3]);
403 }
404 blob_write_to_file(&content, g.argv[4]);
405 blob_reset(&content);
406 }else if( memcmp(zCmd, "hash", nCmd)==0 ){ /* undocumented */
407
+2 -2
--- www/cgi.wiki
+++ www/cgi.wiki
@@ -14,12 +14,12 @@
1414
script]. CGI is the technique that the three
1515
[./selfhost.wiki|self-hosting Fossil repositories] all use.
1616
1717
Setting up a Fossil server using CGI is mostly about writing a short
1818
script (usually just 2 lines line) in the cgi-bin folder of an ordinary
19
-web-browser. But there are a lot of extra options that can be added
20
-to this script, to customize the configuration. This article descripts
19
+web-server. But there are a lot of extra options that can be added
20
+to this script, to customize the configuration. This article describes
2121
those options.
2222
2323
<h1>CGI Script Options</h1>
2424
2525
The CGI script used to launch a Fossil server will usually look something
2626
--- www/cgi.wiki
+++ www/cgi.wiki
@@ -14,12 +14,12 @@
14 script]. CGI is the technique that the three
15 [./selfhost.wiki|self-hosting Fossil repositories] all use.
16
17 Setting up a Fossil server using CGI is mostly about writing a short
18 script (usually just 2 lines line) in the cgi-bin folder of an ordinary
19 web-browser. But there are a lot of extra options that can be added
20 to this script, to customize the configuration. This article descripts
21 those options.
22
23 <h1>CGI Script Options</h1>
24
25 The CGI script used to launch a Fossil server will usually look something
26
--- www/cgi.wiki
+++ www/cgi.wiki
@@ -14,12 +14,12 @@
14 script]. CGI is the technique that the three
15 [./selfhost.wiki|self-hosting Fossil repositories] all use.
16
17 Setting up a Fossil server using CGI is mostly about writing a short
18 script (usually just 2 lines line) in the cgi-bin folder of an ordinary
19 web-server. But there are a lot of extra options that can be added
20 to this script, to customize the configuration. This article describes
21 those options.
22
23 <h1>CGI Script Options</h1>
24
25 The CGI script used to launch a Fossil server will usually look something
26
+1 -1
--- www/index.wiki
+++ www/index.wiki
@@ -9,11 +9,11 @@
99
<li> [./build.wiki | Install]
1010
<li> [https://fossil-scm.org/forum | Support/Forum ]
1111
<li> [./hints.wiki | Tips &amp; Hints]
1212
<li> [./changes.wiki | Change Log]
1313
<li> [../COPYRIGHT-BSD2.txt | License]
14
-<li> [./userlinks.wiki | User inks]
14
+<li> [./userlinks.wiki | User Links]
1515
<li> [./hacker-howto.wiki | Hacker How-To]
1616
<li> [./fossil-v-git.wiki | Fossil vs. Git]
1717
<li> [./permutedindex.html | Documentation Index]
1818
</ul>
1919
<img src="fossil3.gif" align="center">
2020
--- www/index.wiki
+++ www/index.wiki
@@ -9,11 +9,11 @@
9 <li> [./build.wiki | Install]
10 <li> [https://fossil-scm.org/forum | Support/Forum ]
11 <li> [./hints.wiki | Tips &amp; Hints]
12 <li> [./changes.wiki | Change Log]
13 <li> [../COPYRIGHT-BSD2.txt | License]
14 <li> [./userlinks.wiki | User inks]
15 <li> [./hacker-howto.wiki | Hacker How-To]
16 <li> [./fossil-v-git.wiki | Fossil vs. Git]
17 <li> [./permutedindex.html | Documentation Index]
18 </ul>
19 <img src="fossil3.gif" align="center">
20
--- www/index.wiki
+++ www/index.wiki
@@ -9,11 +9,11 @@
9 <li> [./build.wiki | Install]
10 <li> [https://fossil-scm.org/forum | Support/Forum ]
11 <li> [./hints.wiki | Tips &amp; Hints]
12 <li> [./changes.wiki | Change Log]
13 <li> [../COPYRIGHT-BSD2.txt | License]
14 <li> [./userlinks.wiki | User Links]
15 <li> [./hacker-howto.wiki | Hacker How-To]
16 <li> [./fossil-v-git.wiki | Fossil vs. Git]
17 <li> [./permutedindex.html | Documentation Index]
18 </ul>
19 <img src="fossil3.gif" align="center">
20

Keyboard Shortcuts

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