Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Merge updates from trunk. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | cmake-ide |
Files: | files | file ages | folders |
SHA3-256: |
2269309f92d928ca9fcf3d57874c3992 |
User & Date: | ashepilko 2018-09-19 20:19:45.382 |
Context
2018-09-19
| ||
21:00 | Add docs on using IDE for Fossil development. ... (check-in: 7d2be6f8 user: ashepilko tags: cmake-ide) | |
20:19 | Merge updates from trunk. ... (check-in: 2269309f user: ashepilko tags: cmake-ide) | |
19:55 | Ignore errors in the clean target commands. ... (check-in: 27c7a491 user: ashepilko tags: trunk) | |
2018-09-14
| ||
21:15 | Describe the debugging options. ... (check-in: d364933a user: ashepilko tags: cmake-ide) | |
Changes
Changes to Dockerfile.
1 2 3 | ### # Dockerfile for Fossil ### | | | < < | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | ### # Dockerfile for Fossil ### FROM fedora:28 ### Now install some additional parts we will need for the build RUN dnf update -y && dnf install -y gcc make tcl tcl-devel zlib-devel openssl-devel tar && dnf clean all && groupadd -r fossil -g 433 && useradd -u 431 -r -g fossil -d /opt/fossil -s /sbin/nologin -c "Fossil user" fossil ### If you want to build "trunk", change the next line accordingly. ENV FOSSIL_INSTALL_VERSION release RUN curl "https://www.fossil-scm.org/index.html/tarball/fossil-src.tar.gz?name=fossil-src&uuid=${FOSSIL_INSTALL_VERSION}" | tar zx RUN cd fossil-src && ./configure --disable-fusefs --json --with-th1-docs --with-th1-hooks --with-tcl=1 --with-tcl-stubs --with-tcl-private-stubs RUN cd fossil-src/src && mv main.c main.c.orig && sed s/\"now\"/0/ <main.c.orig >main.c RUN cd fossil-src && make && strip fossil && cp fossil /usr/bin && cd .. && rm -rf fossil-src && chmod a+rx /usr/bin/fossil && mkdir -p /opt/fossil && chown fossil:fossil /opt/fossil ### Build is done, remove modules no longer needed RUN dnf remove -y gcc make zlib-devel tcl-devel openssl-devel tar && dnf clean all USER fossil ENV HOME /opt/fossil EXPOSE 8080 |
︙ | ︙ |
Changes to Makefile.in.
︙ | ︙ | |||
48 49 50 51 52 53 54 | USE_MMAN_H = @USE_MMAN_H@ USE_SEE = @USE_SEE@ FOSSIL_ENABLE_MINIZ = @FOSSIL_ENABLE_MINIZ@ include $(SRCDIR)/main.mk distclean: clean | | | 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | USE_MMAN_H = @USE_MMAN_H@ USE_SEE = @USE_SEE@ FOSSIL_ENABLE_MINIZ = @FOSSIL_ENABLE_MINIZ@ include $(SRCDIR)/main.mk distclean: clean -rm -f autoconfig.h config.log Makefile reconfig: @AUTOREMAKE@ # Automatically reconfigure whenever an autosetup file or one of the # make source files change. # |
︙ | ︙ |
Changes to VERSION.
|
| | | 1 | 2.7 |
Changes to auto.def.
︙ | ︙ | |||
124 125 126 127 128 129 130 | # search for the system SQLite once with -ldl, and once without. If # the library can only be found with $extralibs set to -ldl, then # the code below will append -ldl to LIBS. # foreach extralibs {{} {-ldl}} { # Locate the system SQLite by searching for sqlite3_open(). Then check | | | | | | 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | # search for the system SQLite once with -ldl, and once without. If # the library can only be found with $extralibs set to -ldl, then # the code below will append -ldl to LIBS. # foreach extralibs {{} {-ldl}} { # Locate the system SQLite by searching for sqlite3_open(). Then check # if sqlite3_create_window_function can be found as well. If we can find open() but # not create_window_function(), then the system SQLite is too old to link against # fossil. # if {[check-function-in-lib sqlite3_open sqlite3 $extralibs]} { if {![check-function-in-lib sqlite3_create_window_function sqlite3 $extralibs]} { user-error "system sqlite3 too old (require >= 3.25.0)" } # Success. Update symbols and return. # define USE_SYSTEM_SQLITE 1 define-append LIBS -lsqlite3 define-append LIBS $extralibs |
︙ | ︙ |
Changes to skins/default/css.txt.
︙ | ︙ | |||
141 142 143 144 145 146 147 | .udiff, .sbsdiff { font-size: .85em !important; overflow: auto; border: 1px solid #ccc; border-radius: 5px; } .content blockquote { | > > | > | 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | .udiff, .sbsdiff { font-size: .85em !important; overflow: auto; border: 1px solid #ccc; border-radius: 5px; } .content blockquote { background-color: rgba(65, 131, 196, 0.1); border-left: 3px solid #254769; padding: 0.1em; padding-left: 1em; } table.report { cursor: auto; border-radius: 5px; border: 1px solid #ccc; margin: 1em 0; |
︙ | ︙ |
Changes to src/branch.c.
︙ | ︙ | |||
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 | ** COMMAND: branch ** ** Usage: %fossil branch SUBCOMMAND ... ?OPTIONS? ** ** Run various subcommands to manage branches of the open repository or ** of the repository identified by the -R or --repository option. ** ** fossil branch new BRANCH-NAME BASIS ?OPTIONS? ** ** Create a new branch BRANCH-NAME off of check-in BASIS. ** Supported options for this subcommand include: ** --private branch is private (i.e., remains local) ** --bgcolor COLOR use COLOR instead of automatic background ** --nosign do not sign contents on this branch ** --date-override DATE DATE to use instead of 'now' ** --user-override USER USER to use instead of the current default ** ** DATE may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in ** year-month-day form, it may be truncated, the "T" may be ** replaced by a space, and it may also name a timezone offset ** from UTC as "-HH:MM" (westward) or "+HH:MM" (eastward). ** Either no timezone suffix or "Z" means UTC. ** | > > > > > > > > > > > > > > < | < < | > | | | < | < | > > > > > > > > > > > > > | > > > > > > > > > > | < < < | < < | < < < < < < < < | | 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 | ** COMMAND: branch ** ** Usage: %fossil branch SUBCOMMAND ... ?OPTIONS? ** ** Run various subcommands to manage branches of the open repository or ** of the repository identified by the -R or --repository option. ** ** fossil branch current ** ** Print the name of the branch for the current check-out ** ** fossil branch info BRANCH-NAME ** ** Print information about a branch ** ** fossil branch list|ls ?-a|--all|-c|--closed? ** ** List all branches. Use -a or --all to list all branches and ** -c or --closed to list all closed branches. The default is to ** show only open branches. ** ** fossil branch new BRANCH-NAME BASIS ?OPTIONS? ** ** Create a new branch BRANCH-NAME off of check-in BASIS. ** Supported options for this subcommand include: ** --private branch is private (i.e., remains local) ** --bgcolor COLOR use COLOR instead of automatic background ** --nosign do not sign contents on this branch ** --date-override DATE DATE to use instead of 'now' ** --user-override USER USER to use instead of the current default ** ** DATE may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in ** year-month-day form, it may be truncated, the "T" may be ** replaced by a space, and it may also name a timezone offset ** from UTC as "-HH:MM" (westward) or "+HH:MM" (eastward). ** Either no timezone suffix or "Z" means UTC. ** ** Options: ** -R|--repository FILE Run commands on repository FILE ** ** Summary: ** fossil branch current ** fossil branch info BRANCHNAME ** fossil branch [list|ls] ** fossil branch new */ void branch_cmd(void){ int n; const char *zCmd = "list"; db_find_and_open_repository(0, 0); if( g.argc>=3 ) zCmd = g.argv[2]; n = strlen(zCmd); if( strncmp(zCmd,"current",n)==0 ){ if( !g.localOpen ){ fossil_fatal("not within an open checkout"); }else{ int vid = db_lget_int("checkout", 0); char *zCurrent = db_text(0, "SELECT value FROM tagxref" " WHERE rid=%d AND tagid=%d", vid, TAG_BRANCH); fossil_print("%s\n", zCurrent); fossil_free(zCurrent); } }else if( strncmp(zCmd,"info",n)==0 ){ int i; for(i=3; i<g.argc; i++){ const char *zBrName = g.argv[i]; int rid = branch_is_open(zBrName); if( rid==0 ){ fossil_print("%s: not an open branch\n", zBrName); }else{ const char *zUuid = db_text(0,"SELECT uuid FROM blob WHERE rid=%d",rid); const char *zDate = db_text(0, "SELECT datetime(mtime,toLocal()) FROM event" " WHERE objid=%d", rid); fossil_print("%s: open as of %s on %.16s\n", zBrName, zDate, zUuid); } } }else if( (strncmp(zCmd,"list",n)==0)||(strncmp(zCmd, "ls", n)==0) ){ Stmt q; int vid; char *zCurrent = 0; int brFlags = BRL_OPEN_ONLY; if( find_option("all","a",0)!=0 ) brFlags = BRL_BOTH; if( find_option("closed","c",0)!=0 ) brFlags = BRL_CLOSED_ONLY; if( g.localOpen ){ vid = db_lget_int("checkout", 0); zCurrent = db_text(0, "SELECT value FROM tagxref" " WHERE rid=%d AND tagid=%d", vid, TAG_BRANCH); } branch_prepare_list_query(&q, brFlags); while( db_step(&q)==SQLITE_ROW ){ const char *zBr = db_column_text(&q, 0); int isCur = zCurrent!=0 && fossil_strcmp(zCurrent,zBr)==0; fossil_print("%s%s\n", (isCur ? "* " : " "), zBr); } db_finalize(&q); }else if( strncmp(zCmd,"new",n)==0 ){ branch_new(); }else{ fossil_fatal("branch subcommand should be one of: " "current info list ls new"); } } static const char brlistQuery[] = @ SELECT @ tagxref.value, @ max(event.mtime), |
︙ | ︙ |
Changes to src/json_branch.c.
︙ | ︙ | |||
66 67 68 69 70 71 72 | cson_value * payV; cson_object * pay; cson_value * listV; cson_array * list; char const * range = NULL; int branchListFlags = BRL_OPEN_ONLY; char * sawConversionError = NULL; | | | 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | cson_value * payV; cson_object * pay; cson_value * listV; cson_array * list; char const * range = NULL; int branchListFlags = BRL_OPEN_ONLY; char * sawConversionError = NULL; Stmt q = empty_Stmt; if( !g.perm.Read ){ json_set_err(FSL_JSON_E_DENIED, "Requires 'o' permissions."); return NULL; } payV = cson_value_new_object(); pay = cson_value_get_object(payV); |
︙ | ︙ | |||
141 142 143 144 145 146 147 148 149 150 151 152 153 154 | __FILE__,__LINE__); } } if( sawConversionError ){ json_warn(FSL_JSON_W_COL_TO_JSON_FAILED,"%s",sawConversionError); free(sawConversionError); } return payV; } /* ** Parameters for the create-branch operation. */ typedef struct BranchCreateOptions{ | > | 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | __FILE__,__LINE__); } } if( sawConversionError ){ json_warn(FSL_JSON_W_COL_TO_JSON_FAILED,"%s",sawConversionError); free(sawConversionError); } db_finalize(&q); return payV; } /* ** Parameters for the create-branch operation. */ typedef struct BranchCreateOptions{ |
︙ | ︙ |
Changes to src/main.mk.
︙ | ︙ | |||
684 685 686 687 688 689 690 | # This rule prevents make from using its default rules to try build # an executable named "manifest" out of the file named "manifest.c" # $(SRCDIR)/../manifest: # noop clean: | | | 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 | # This rule prevents make from using its default rules to try build # an executable named "manifest" out of the file named "manifest.c" # $(SRCDIR)/../manifest: # noop clean: -rm -rf $(OBJDIR)/* $(APPNAME) $(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex $(OBJDIR)/mkindex $(TRANS_SRC) >$@ $(OBJDIR)/builtin_data.h: $(OBJDIR)/mkbuiltin $(EXTRA_FILES) $(OBJDIR)/mkbuiltin --prefix $(SRCDIR)/ $(EXTRA_FILES) >$@ |
︙ | ︙ |
Changes to src/makemake.tcl.
︙ | ︙ | |||
446 447 448 449 450 451 452 | # This rule prevents make from using its default rules to try build # an executable named "manifest" out of the file named "manifest.c" # $(SRCDIR)/../manifest: # noop clean: | | | 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 | # This rule prevents make from using its default rules to try build # an executable named "manifest" out of the file named "manifest.c" # $(SRCDIR)/../manifest: # noop clean: -rm -rf $(OBJDIR)/* $(APPNAME) } set mhargs {} foreach s [lsort $src] { append mhargs "\$(OBJDIR)/${s}_.c:\$(OBJDIR)/$s.h <<<NEXT_LINE>>>" set extra_h($s) { } |
︙ | ︙ | |||
1983 1984 1985 1986 1987 1988 1989 | "$(OX)\page_index.h": "$(OBJDIR)\mkindex$E" $(SRC) $** > $@ "$(OX)\builtin_data.h": "$(OBJDIR)\mkbuiltin$E" "$(OX)\builtin_data.reslist" "$(OBJDIR)\mkbuiltin$E" --prefix "$(SRCDIR)/" --reslist "$(OX)\builtin_data.reslist" > $@ cleanx: | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 | "$(OX)\page_index.h": "$(OBJDIR)\mkindex$E" $(SRC) $** > $@ "$(OX)\builtin_data.h": "$(OBJDIR)\mkbuiltin$E" "$(OX)\builtin_data.reslist" "$(OBJDIR)\mkbuiltin$E" --prefix "$(SRCDIR)/" --reslist "$(OX)\builtin_data.reslist" > $@ cleanx: -del "$(OX)\*.obj" 2>NUL -del "$(OBJDIR)\*.obj" 2>NUL -del "$(OX)\*_.c" 2>NUL -del "$(OX)\*.h" 2>NUL -del "$(OX)\*.ilk" 2>NUL -del "$(OX)\*.map" 2>NUL -del "$(OX)\*.res" 2>NUL -del "$(OX)\*.reslist" 2>NUL -del "$(OX)\headers" 2>NUL -del "$(OX)\linkopts" 2>NUL -del "$(OX)\vc*.pdb" 2>NUL clean: cleanx -del "$(APPNAME)" 2>NUL -del "$(PDBNAME)" 2>NUL -del "$(APPMANIFEST)" 2>NUL -del "$(OBJDIR)\translate$E" 2>NUL -del "$(OBJDIR)\translate$P" 2>NUL -del "$(OBJDIR)\mkindex$E" 2>NUL -del "$(OBJDIR)\mkindex$P" 2>NUL -del "$(OBJDIR)\makeheaders$E" 2>NUL -del "$(OBJDIR)\makeheaders$P" 2>NUL -del "$(OBJDIR)\mkversion$E" 2>NUL -del "$(OBJDIR)\mkversion$P" 2>NUL -del "$(OBJDIR)\mkcss$E" 2>NUL -del "$(OBJDIR)\mkcss$P" 2>NUL -del "$(OBJDIR)\codecheck1$E" 2>NUL -del "$(OBJDIR)\codecheck1$P" 2>NUL -del "$(OBJDIR)\mkbuiltin$E" 2>NUL -del "$(OBJDIR)\mkbuiltin$P" 2>NUL realclean: clean "$(OBJDIR)\json$O" : "$(SRCDIR)\json_detail.h" "$(OBJDIR)\json_artifact$O" : "$(SRCDIR)\json_detail.h" "$(OBJDIR)\json_branch$O" : "$(SRCDIR)\json_detail.h" "$(OBJDIR)\json_config$O" : "$(SRCDIR)\json_detail.h" |
︙ | ︙ | |||
2273 2274 2275 2276 2277 2278 2279 | $(APPLICATION): $(TRANSLATEDOBJ) $(SQLITEOBJ) $(SQLITESHELLOBJ) $(THOBJ) $(ZLIBOBJ) headers $(RESOURCE) $(LINK) $(LINKFLAGS) -out:"$@" $(TRANSLATEDOBJ) $(SQLITEOBJ) $(SQLITESHELLOBJ) $(THOBJ) $(ZLIBOBJ) $(RESOURCE) # cleanup .PHONY: clean clean: | | | | | | | 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 | $(APPLICATION): $(TRANSLATEDOBJ) $(SQLITEOBJ) $(SQLITESHELLOBJ) $(THOBJ) $(ZLIBOBJ) headers $(RESOURCE) $(LINK) $(LINKFLAGS) -out:"$@" $(TRANSLATEDOBJ) $(SQLITEOBJ) $(SQLITESHELLOBJ) $(THOBJ) $(ZLIBOBJ) $(RESOURCE) # cleanup .PHONY: clean clean: -del /F $(TRANSLATEDOBJ) $(SQLITEOBJ) $(THOBJ) $(ZLIBOBJ) $(UTILS_OBJ) version.obj -del /F $(TRANSLATEDSRC) -del /F *.h headers -del /F $(RESOURCE) .PHONY: clobber clobber: clean -del /F *.exe }] |
Changes to src/sqlite3.c.
︙ | ︙ | |||
1154 1155 1156 1157 1158 1159 1160 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.25.0" #define SQLITE_VERSION_NUMBER 3025000 | | | 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.25.0" #define SQLITE_VERSION_NUMBER 3025000 #define SQLITE_SOURCE_ID "2018-09-15 04:01:47 b63af6c3bd33152742648d5d2e8dc5d5fcbcdd27df409272b6aea00a6f761760" /* ** CAPI3REF: Run-Time Library Version Numbers ** KEYWORDS: sqlite3_version sqlite3_sourceid ** ** These interfaces provide the same information as the [SQLITE_VERSION], ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros |
︙ | ︙ | |||
2111 2112 2113 2114 2115 2116 2117 | ** ** <li>[[SQLITE_FCNTL_DATA_VERSION]] ** The [SQLITE_FCNTL_DATA_VERSION] opcode is used to detect changes to ** a database file. The argument is a pointer to a 32-bit unsigned integer. ** The "data version" for the pager is written into the pointer. The ** "data version" changes whenever any change occurs to the corresponding ** database file, either through SQL statements on the same database | | | | | | > | 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 | ** ** <li>[[SQLITE_FCNTL_DATA_VERSION]] ** The [SQLITE_FCNTL_DATA_VERSION] opcode is used to detect changes to ** a database file. The argument is a pointer to a 32-bit unsigned integer. ** The "data version" for the pager is written into the pointer. The ** "data version" changes whenever any change occurs to the corresponding ** database file, either through SQL statements on the same database ** connection or through transactions committed by separate database ** connections possibly in other processes. The [sqlite3_total_changes()] ** interface can be used to find if any database on the connection has changed, ** but that interface responds to changes on TEMP as well as MAIN and does ** not provide a mechanism to detect changes to MAIN only. Also, the ** [sqlite3_total_changes()] interface responds to internal changes only and ** omits changes made by other database connections. The ** [PRAGMA data_version] command provide a mechanism to detect changes to ** a single attached database that occur due to other database connections, ** but omits changes implemented by the database connection on which it is ** called. This file control is the only mechanism to detect changes that ** happen either internally or externally and that are associated with ** a particular attached database. ** </ul> */ #define SQLITE_FCNTL_LOCKSTATE 1 #define SQLITE_FCNTL_GET_LOCKPROXYFILE 2 #define SQLITE_FCNTL_SET_LOCKPROXYFILE 3 #define SQLITE_FCNTL_LAST_ERRNO 4 #define SQLITE_FCNTL_SIZE_HINT 5 |
︙ | ︙ | |||
5760 5761 5762 5763 5764 5765 5766 | ** parameters. ^An aggregate SQL function requires an implementation of xStep ** and xFinal and NULL pointer must be passed for xFunc. ^To delete an existing ** SQL function or aggregate, pass NULL pointers for all three function ** callbacks. ** ** ^The sixth, seventh, eighth and ninth parameters (xStep, xFinal, xValue ** and xInverse) passed to sqlite3_create_window_function are pointers to | | | 5761 5762 5763 5764 5765 5766 5767 5768 5769 5770 5771 5772 5773 5774 5775 | ** parameters. ^An aggregate SQL function requires an implementation of xStep ** and xFinal and NULL pointer must be passed for xFunc. ^To delete an existing ** SQL function or aggregate, pass NULL pointers for all three function ** callbacks. ** ** ^The sixth, seventh, eighth and ninth parameters (xStep, xFinal, xValue ** and xInverse) passed to sqlite3_create_window_function are pointers to ** C-language callbacks that implement the new function. xStep and xFinal ** must both be non-NULL. xValue and xInverse may either both be NULL, in ** which case a regular aggregate function is created, or must both be ** non-NULL, in which case the new function may be used as either an aggregate ** or aggregate window function. More details regarding the implementation ** of aggregate window functions are ** [user-defined window functions|available here]. ** |
︙ | ︙ | |||
10286 10287 10288 10289 10290 10291 10292 | ** The following are allowed values for 6th argument (the F argument) to ** the [sqlite3_deserialize(D,S,P,N,M,F)] interface. ** ** The SQLITE_DESERIALIZE_FREEONCLOSE means that the database serialization ** in the P argument is held in memory obtained from [sqlite3_malloc64()] ** and that SQLite should take ownership of this memory and automatically ** free it when it has finished using it. Without this flag, the caller | | | 10287 10288 10289 10290 10291 10292 10293 10294 10295 10296 10297 10298 10299 10300 10301 | ** The following are allowed values for 6th argument (the F argument) to ** the [sqlite3_deserialize(D,S,P,N,M,F)] interface. ** ** The SQLITE_DESERIALIZE_FREEONCLOSE means that the database serialization ** in the P argument is held in memory obtained from [sqlite3_malloc64()] ** and that SQLite should take ownership of this memory and automatically ** free it when it has finished using it. Without this flag, the caller ** is responsible for freeing any dynamically allocated memory. ** ** The SQLITE_DESERIALIZE_RESIZEABLE flag means that SQLite is allowed to ** grow the size of the database using calls to [sqlite3_realloc64()]. This ** flag should only be used if SQLITE_DESERIALIZE_FREEONCLOSE is also used. ** Without this flag, the deserialized database cannot increase in size beyond ** the number of bytes specified by the M parameter. ** |
︙ | ︙ | |||
12464 12465 12466 12467 12468 12469 12470 | ** document such as "I won first place" is tokenized, entries are ** added to the FTS index for "i", "won", "first", "1st" and ** "place". ** ** This way, even if the tokenizer does not provide synonyms ** when tokenizing query text (it should not - to do would be ** inefficient), it doesn't matter if the user queries for | | | 12465 12466 12467 12468 12469 12470 12471 12472 12473 12474 12475 12476 12477 12478 12479 | ** document such as "I won first place" is tokenized, entries are ** added to the FTS index for "i", "won", "first", "1st" and ** "place". ** ** This way, even if the tokenizer does not provide synonyms ** when tokenizing query text (it should not - to do would be ** inefficient), it doesn't matter if the user queries for ** 'first + place' or '1st + place', as there are entries in the ** FTS index corresponding to both forms of the first token. ** </ol> ** ** Whether it is parsing document or query text, any call to xToken that ** specifies a <i>tflags</i> argument with the FTS5_TOKEN_COLOCATED bit ** is considered to supply a synonym for the previous token. For example, ** when parsing the document "I won first place", a tokenizer that supports |
︙ | ︙ | |||
12492 12493 12494 12495 12496 12497 12498 | ** There is no limit to the number of synonyms that may be provided for a ** single token. ** ** In many cases, method (1) above is the best approach. It does not add ** extra data to the FTS index or require FTS5 to query for multiple terms, ** so it is efficient in terms of disk space and query speed. However, it ** does not support prefix queries very well. If, as suggested above, the | | | 12493 12494 12495 12496 12497 12498 12499 12500 12501 12502 12503 12504 12505 12506 12507 | ** There is no limit to the number of synonyms that may be provided for a ** single token. ** ** In many cases, method (1) above is the best approach. It does not add ** extra data to the FTS index or require FTS5 to query for multiple terms, ** so it is efficient in terms of disk space and query speed. However, it ** does not support prefix queries very well. If, as suggested above, the ** token "first" is substituted for "1st" by the tokenizer, then the query: ** ** <codeblock> ** ... MATCH '1s*'</codeblock> ** ** will not match documents that contain the token "1st" (as the tokenizer ** will probably not map "1s" to any prefix of "first"). ** |
︙ | ︙ | |||
18970 18971 18972 18973 18974 18975 18976 18977 18978 18979 18980 18981 18982 18983 | SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*); SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int); SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *); SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *, SrcList *); SQLITE_PRIVATE void *sqlite3RenameTokenMap(Parse*, void*, Token*); SQLITE_PRIVATE void sqlite3RenameTokenRemap(Parse*, void *pTo, void *pFrom); SQLITE_PRIVATE void sqlite3RenameExprUnmap(Parse*, Expr*); SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*); SQLITE_PRIVATE char sqlite3AffinityType(const char*, Column*); SQLITE_PRIVATE void sqlite3Analyze(Parse*, Token*, Token*); SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*, sqlite3_file*); SQLITE_PRIVATE int sqlite3FindDb(sqlite3*, Token*); SQLITE_PRIVATE int sqlite3FindDbName(sqlite3 *, const char *); SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3*,int iDB); | > | 18971 18972 18973 18974 18975 18976 18977 18978 18979 18980 18981 18982 18983 18984 18985 | SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*); SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int); SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *); SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *, SrcList *); SQLITE_PRIVATE void *sqlite3RenameTokenMap(Parse*, void*, Token*); SQLITE_PRIVATE void sqlite3RenameTokenRemap(Parse*, void *pTo, void *pFrom); SQLITE_PRIVATE void sqlite3RenameExprUnmap(Parse*, Expr*); SQLITE_PRIVATE void sqlite3RenameExprlistUnmap(Parse*, ExprList*); SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*); SQLITE_PRIVATE char sqlite3AffinityType(const char*, Column*); SQLITE_PRIVATE void sqlite3Analyze(Parse*, Token*, Token*); SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*, sqlite3_file*); SQLITE_PRIVATE int sqlite3FindDb(sqlite3*, Token*); SQLITE_PRIVATE int sqlite3FindDbName(sqlite3 *, const char *); SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3*,int iDB); |
︙ | ︙ | |||
27604 27605 27606 27607 27608 27609 27610 | xtype = etSTRING; }else{ bufpt = va_arg(ap,char*); } if( bufpt==0 ){ bufpt = ""; }else if( xtype==etDYNSTRING ){ | | > > > > > | 27606 27607 27608 27609 27610 27611 27612 27613 27614 27615 27616 27617 27618 27619 27620 27621 27622 27623 27624 27625 | xtype = etSTRING; }else{ bufpt = va_arg(ap,char*); } if( bufpt==0 ){ bufpt = ""; }else if( xtype==etDYNSTRING ){ if( pAccum->nChar==0 && pAccum->mxAlloc && width==0 && precision<0 && pAccum->accError==0 ){ /* Special optimization for sqlite3_mprintf("%z..."): ** Extend an existing memory allocation rather than creating ** a new one. */ assert( (pAccum->printfFlags&SQLITE_PRINTF_MALLOCED)==0 ); pAccum->zText = bufpt; pAccum->nAlloc = sqlite3DbMallocSize(pAccum->db, bufpt); pAccum->nChar = 0x7fffffff & (int)strlen(bufpt); |
︙ | ︙ | |||
36966 36967 36968 36969 36970 36971 36972 | ** any load or store begun after the barrier. */ static void unixShmBarrier( sqlite3_file *fd /* Database file holding the shared memory */ ){ UNUSED_PARAMETER(fd); sqlite3MemoryBarrier(); /* compiler-defined memory barrier */ | > | > | 36973 36974 36975 36976 36977 36978 36979 36980 36981 36982 36983 36984 36985 36986 36987 36988 36989 | ** any load or store begun after the barrier. */ static void unixShmBarrier( sqlite3_file *fd /* Database file holding the shared memory */ ){ UNUSED_PARAMETER(fd); sqlite3MemoryBarrier(); /* compiler-defined memory barrier */ assert( fd->pMethods->xLock==nolockLock || unixFileMutexNotheld((unixFile*)fd) ); unixEnterMutex(); /* Also mutex, for redundancy */ unixLeaveMutex(); } /* ** Close a connection to shared-memory. Delete the underlying ** storage if deleteFlag is true. |
︙ | ︙ | |||
46283 46284 46285 46286 46287 46288 46289 | ** ** This file implements an in-memory VFS. A database is held as a contiguous ** block of memory. ** ** This file also implements interface sqlite3_serialize() and ** sqlite3_deserialize(). */ | < > | 46292 46293 46294 46295 46296 46297 46298 46299 46300 46301 46302 46303 46304 46305 46306 46307 | ** ** This file implements an in-memory VFS. A database is held as a contiguous ** block of memory. ** ** This file also implements interface sqlite3_serialize() and ** sqlite3_deserialize(). */ /* #include "sqliteInt.h" */ #ifdef SQLITE_ENABLE_DESERIALIZE /* ** Forward declaration of objects used by this utility */ typedef struct sqlite3_vfs MemVfs; typedef struct MemFile MemFile; |
︙ | ︙ | |||
60505 60506 60507 60508 60509 60510 60511 | ** it takes a snapshot of the state of the WAL and wal-index for the current ** instant in time. The current thread will continue to use this snapshot. ** Other threads might append new content to the WAL and wal-index but ** that extra content is ignored by the current thread. ** ** If the database contents have changes since the previous read ** transaction, then *pChanged is set to 1 before returning. The | | | 60514 60515 60516 60517 60518 60519 60520 60521 60522 60523 60524 60525 60526 60527 60528 | ** it takes a snapshot of the state of the WAL and wal-index for the current ** instant in time. The current thread will continue to use this snapshot. ** Other threads might append new content to the WAL and wal-index but ** that extra content is ignored by the current thread. ** ** If the database contents have changes since the previous read ** transaction, then *pChanged is set to 1 before returning. The ** Pager layer will use this to know that its cache is stale and ** needs to be flushed. */ SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ int rc; /* Return code */ int cnt = 0; /* Number of TryBeginRead attempts */ #ifdef SQLITE_ENABLE_SNAPSHOT |
︙ | ︙ | |||
78536 78537 78538 78539 78540 78541 78542 | /* If the VM did not run to completion or if it encountered an ** error, then it might not have been halted properly. So halt ** it now. */ sqlite3VdbeHalt(p); | | | 78545 78546 78547 78548 78549 78550 78551 78552 78553 78554 78555 78556 78557 78558 78559 | /* If the VM did not run to completion or if it encountered an ** error, then it might not have been halted properly. So halt ** it now. */ sqlite3VdbeHalt(p); /* If the VDBE has been run even partially, then transfer the error code ** and error message from the VDBE into the main database structure. But ** if the VDBE has just been set to run but has not actually executed any ** instructions yet, leave the main database error information unchanged. */ if( p->pc>=0 ){ vdbeInvokeSqllog(p); sqlite3VdbeTransferError(p); |
︙ | ︙ | |||
101159 101160 101161 101162 101163 101164 101165 | /* ** Generate code to verify that the schemas of database zDb and, if ** bTemp is not true, database "temp", can still be parsed. This is ** called at the end of the generation of an ALTER TABLE ... RENAME ... ** statement to ensure that the operation has not rendered any schema ** objects unusable. */ | | | 101168 101169 101170 101171 101172 101173 101174 101175 101176 101177 101178 101179 101180 101181 101182 | /* ** Generate code to verify that the schemas of database zDb and, if ** bTemp is not true, database "temp", can still be parsed. This is ** called at the end of the generation of an ALTER TABLE ... RENAME ... ** statement to ensure that the operation has not rendered any schema ** objects unusable. */ static void renameTestSchema(Parse *pParse, const char *zDb, int bTemp){ sqlite3NestedParse(pParse, "SELECT 1 " "FROM \"%w\".%s " "WHERE name NOT LIKE 'sqlite_%%'" " AND sql NOT LIKE 'create virtual%%'" " AND sqlite_rename_test(%Q, sql, type, name, %d)=NULL ", zDb, MASTER_NAME, |
︙ | ︙ | |||
101186 101187 101188 101189 101190 101191 101192 | } } /* ** Generate code to reload the schema for database iDb. And, if iDb!=1, for ** the temp database as well. */ | | | 101195 101196 101197 101198 101199 101200 101201 101202 101203 101204 101205 101206 101207 101208 101209 | } } /* ** Generate code to reload the schema for database iDb. And, if iDb!=1, for ** the temp database as well. */ static void renameReloadSchema(Parse *pParse, int iDb){ Vdbe *v = pParse->pVdbe; if( v ){ sqlite3ChangeCookie(pParse, iDb); sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, iDb, 0); if( iDb!=1 ) sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, 1, 0); } } |
︙ | ︙ | |||
101766 101767 101768 101769 101770 101771 101772 | ** ** sqlite3_free(x); ** if( x==y ) ... ** ** Technically, as x no longer points into a valid object or to the byte ** following a valid object, it may not be used in comparison operations. */ | | | 101775 101776 101777 101778 101779 101780 101781 101782 101783 101784 101785 101786 101787 101788 101789 | ** ** sqlite3_free(x); ** if( x==y ) ... ** ** Technically, as x no longer points into a valid object or to the byte ** following a valid object, it may not be used in comparison operations. */ static void renameTokenCheckAll(Parse *pParse, void *pPtr){ if( pParse->nErr==0 && pParse->db->mallocFailed==0 ){ RenameToken *p; u8 i = 0; for(p=pParse->pRename; p; p=p->pNext){ if( p->p ){ assert( p->p!=pPtr ); i += *(u8*)(p->p); |
︙ | ︙ | |||
101838 101839 101840 101841 101842 101843 101844 101845 101846 101847 101848 101849 101850 101851 | SQLITE_PRIVATE void sqlite3RenameExprUnmap(Parse *pParse, Expr *pExpr){ Walker sWalker; memset(&sWalker, 0, sizeof(Walker)); sWalker.pParse = pParse; sWalker.xExprCallback = renameUnmapExprCb; sqlite3WalkExpr(&sWalker, pExpr); } /* ** Free the list of RenameToken objects given in the second argument */ static void renameTokenFree(sqlite3 *db, RenameToken *pToken){ RenameToken *pNext; RenameToken *p; | > > > > > > > > > > > > > > > > > > | 101847 101848 101849 101850 101851 101852 101853 101854 101855 101856 101857 101858 101859 101860 101861 101862 101863 101864 101865 101866 101867 101868 101869 101870 101871 101872 101873 101874 101875 101876 101877 101878 | SQLITE_PRIVATE void sqlite3RenameExprUnmap(Parse *pParse, Expr *pExpr){ Walker sWalker; memset(&sWalker, 0, sizeof(Walker)); sWalker.pParse = pParse; sWalker.xExprCallback = renameUnmapExprCb; sqlite3WalkExpr(&sWalker, pExpr); } /* ** Remove all nodes that are part of expression-list pEList from the ** rename list. */ SQLITE_PRIVATE void sqlite3RenameExprlistUnmap(Parse *pParse, ExprList *pEList){ if( pEList ){ int i; Walker sWalker; memset(&sWalker, 0, sizeof(Walker)); sWalker.pParse = pParse; sWalker.xExprCallback = renameUnmapExprCb; sqlite3WalkExprList(&sWalker, pEList); for(i=0; i<pEList->nExpr; i++){ sqlite3RenameTokenRemap(pParse, 0, (void*)pEList->a[i].zName); } } } /* ** Free the list of RenameToken objects given in the second argument */ static void renameTokenFree(sqlite3 *db, RenameToken *pToken){ RenameToken *pNext; RenameToken *p; |
︙ | ︙ | |||
107744 107745 107746 107747 107748 107749 107750 107751 107752 107753 107754 107755 107756 107757 | sEnd.n = 1; /* Use sqlite3EndTable() to add the view to the SQLITE_MASTER table */ sqlite3EndTable(pParse, 0, &sEnd, 0, 0); create_view_fail: sqlite3SelectDelete(db, pSelect); sqlite3ExprListDelete(db, pCNames); return; } #endif /* SQLITE_OMIT_VIEW */ #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) /* | > > > | 107771 107772 107773 107774 107775 107776 107777 107778 107779 107780 107781 107782 107783 107784 107785 107786 107787 | sEnd.n = 1; /* Use sqlite3EndTable() to add the view to the SQLITE_MASTER table */ sqlite3EndTable(pParse, 0, &sEnd, 0, 0); create_view_fail: sqlite3SelectDelete(db, pSelect); if( IN_RENAME_OBJECT ){ sqlite3RenameExprlistUnmap(pParse, pCNames); } sqlite3ExprListDelete(db, pCNames); return; } #endif /* SQLITE_OMIT_VIEW */ #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) /* |
︙ | ︙ | |||
135327 135328 135329 135330 135331 135332 135333 | ** an access of the index rather than the original table. */ static int codeCursorHintFixExpr(Walker *pWalker, Expr *pExpr){ int rc = WRC_Continue; struct CCurHint *pHint = pWalker->u.pCCurHint; if( pExpr->op==TK_COLUMN ){ if( pExpr->iTable!=pHint->iTabCur ){ | < | < < | 135357 135358 135359 135360 135361 135362 135363 135364 135365 135366 135367 135368 135369 135370 135371 135372 | ** an access of the index rather than the original table. */ static int codeCursorHintFixExpr(Walker *pWalker, Expr *pExpr){ int rc = WRC_Continue; struct CCurHint *pHint = pWalker->u.pCCurHint; if( pExpr->op==TK_COLUMN ){ if( pExpr->iTable!=pHint->iTabCur ){ int reg = ++pWalker->pParse->nMem; /* Register for column value */ sqlite3ExprCode(pWalker->pParse, pExpr, reg); pExpr->op = TK_REGISTER; pExpr->iTable = reg; }else if( pHint->pIdx!=0 ){ pExpr->iTable = pHint->iIdxCur; pExpr->iColumn = sqlite3ColumnOfIndex(pHint->pIdx, pExpr->iColumn); assert( pExpr->iColumn>=0 ); } |
︙ | ︙ | |||
177351 177352 177353 177354 177355 177356 177357 | if( pStr ){ pStr->pCtx = ctx; jsonAppendChar(pStr, ']'); if( pStr->bErr ){ if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx); assert( pStr->bStatic ); }else if( isFinal ){ | | | | 177378 177379 177380 177381 177382 177383 177384 177385 177386 177387 177388 177389 177390 177391 177392 177393 177394 177395 177396 | if( pStr ){ pStr->pCtx = ctx; jsonAppendChar(pStr, ']'); if( pStr->bErr ){ if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx); assert( pStr->bStatic ); }else if( isFinal ){ sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free); pStr->bStatic = 1; }else{ sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT); pStr->nUsed--; } }else{ sqlite3_result_text(ctx, "[]", 2, SQLITE_STATIC); } sqlite3_result_subtype(ctx, JSON_SUBTYPE); } |
︙ | ︙ | |||
177404 177405 177406 177407 177408 177409 177410 | if( z[i]=='"' ){ inStr = !inStr; }else if( z[i]=='\\' ){ i++; } } pStr->nUsed -= i; | | | 177431 177432 177433 177434 177435 177436 177437 177438 177439 177440 177441 177442 177443 177444 177445 | if( z[i]=='"' ){ inStr = !inStr; }else if( z[i]=='\\' ){ i++; } } pStr->nUsed -= i; memmove(&z[1], &z[i+1], (size_t)pStr->nUsed-1); } #else # define jsonGroupInverse 0 #endif /* |
︙ | ︙ | |||
177450 177451 177452 177453 177454 177455 177456 | pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); if( pStr ){ jsonAppendChar(pStr, '}'); if( pStr->bErr ){ if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx); assert( pStr->bStatic ); }else if( isFinal ){ | | | | 177477 177478 177479 177480 177481 177482 177483 177484 177485 177486 177487 177488 177489 177490 177491 177492 177493 177494 177495 | pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); if( pStr ){ jsonAppendChar(pStr, '}'); if( pStr->bErr ){ if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx); assert( pStr->bStatic ); }else if( isFinal ){ sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free); pStr->bStatic = 1; }else{ sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT); pStr->nUsed--; } }else{ sqlite3_result_text(ctx, "{}", 2, SQLITE_STATIC); } sqlite3_result_subtype(ctx, JSON_SUBTYPE); } |
︙ | ︙ | |||
181308 181309 181310 181311 181312 181313 181314 | ** BEGIN; ** INSERT INTO rtree... ** DROP TABLE <tablename>; -- Would fail with SQLITE_LOCKED ** COMMIT; */ static int rtreeSavepoint(sqlite3_vtab *pVtab, int iSavepoint){ Rtree *pRtree = (Rtree *)pVtab; | | | 181335 181336 181337 181338 181339 181340 181341 181342 181343 181344 181345 181346 181347 181348 181349 | ** BEGIN; ** INSERT INTO rtree... ** DROP TABLE <tablename>; -- Would fail with SQLITE_LOCKED ** COMMIT; */ static int rtreeSavepoint(sqlite3_vtab *pVtab, int iSavepoint){ Rtree *pRtree = (Rtree *)pVtab; u8 iwt = pRtree->inWrTrans; UNUSED_PARAMETER(iSavepoint); pRtree->inWrTrans = 0; nodeBlobReset(pRtree); pRtree->inWrTrans = iwt; return SQLITE_OK; } |
︙ | ︙ | |||
182448 182449 182450 182451 182452 182453 182454 | } if( c<'0' || c>'9' ) return 0; continue; } break; } if( z[j-1]<'0' ) return 0; | | | 182475 182476 182477 182478 182479 182480 182481 182482 182483 182484 182485 182486 182487 182488 182489 | } if( c<'0' || c>'9' ) return 0; continue; } break; } if( z[j-1]<'0' ) return 0; if( pVal ) *pVal = (GeoCoord)atof((const char*)p->z); p->z += j; return 1; } /* ** If the input is a well-formed JSON array of coordinates with at least ** four coordinates and where each coordinate is itself a two-value array, |
︙ | ︙ | |||
182703 182704 182705 182706 182707 182708 182709 | double F = sqlite3_value_double(argv[6]); GeoCoord x1, y1, x0, y0; int ii; if( p ){ for(ii=0; ii<p->nVertex; ii++){ x0 = p->a[ii*2]; y0 = p->a[ii*2+1]; | | | | 182730 182731 182732 182733 182734 182735 182736 182737 182738 182739 182740 182741 182742 182743 182744 182745 | double F = sqlite3_value_double(argv[6]); GeoCoord x1, y1, x0, y0; int ii; if( p ){ for(ii=0; ii<p->nVertex; ii++){ x0 = p->a[ii*2]; y0 = p->a[ii*2+1]; x1 = (GeoCoord)(A*x0 + B*y0 + E); y1 = (GeoCoord)(C*x0 + D*y0 + F); p->a[ii*2] = x1; p->a[ii*2+1] = y1; } sqlite3_result_blob(context, p->hdr, 4+8*p->nVertex, SQLITE_TRANSIENT); sqlite3_free(p); } |
︙ | ︙ | |||
182779 182780 182781 182782 182783 182784 182785 | } if( p ){ int ii; mnX = mxX = p->a[0]; mnY = mxY = p->a[1]; for(ii=1; ii<p->nVertex; ii++){ double r = p->a[ii*2]; | | | | | | 182806 182807 182808 182809 182810 182811 182812 182813 182814 182815 182816 182817 182818 182819 182820 182821 182822 182823 182824 | } if( p ){ int ii; mnX = mxX = p->a[0]; mnY = mxY = p->a[1]; for(ii=1; ii<p->nVertex; ii++){ double r = p->a[ii*2]; if( r<mnX ) mnX = (float)r; else if( r>mxX ) mxX = (float)r; r = p->a[ii*2+1]; if( r<mnY ) mnY = (float)r; else if( r>mxY ) mxY = (float)r; } if( pRc ) *pRc = SQLITE_OK; if( aCoord==0 ){ geopolyBboxFill: pOut = sqlite3_realloc(p, sizeof(GeoPoly)+sizeof(GeoCoord)*6); if( pOut==0 ){ sqlite3_free(p); |
︙ | ︙ | |||
197383 197384 197385 197386 197387 197388 197389 | ** document such as "I won first place" is tokenized, entries are ** added to the FTS index for "i", "won", "first", "1st" and ** "place". ** ** This way, even if the tokenizer does not provide synonyms ** when tokenizing query text (it should not - to do would be ** inefficient), it doesn't matter if the user queries for | | | 197410 197411 197412 197413 197414 197415 197416 197417 197418 197419 197420 197421 197422 197423 197424 | ** document such as "I won first place" is tokenized, entries are ** added to the FTS index for "i", "won", "first", "1st" and ** "place". ** ** This way, even if the tokenizer does not provide synonyms ** when tokenizing query text (it should not - to do would be ** inefficient), it doesn't matter if the user queries for ** 'first + place' or '1st + place', as there are entries in the ** FTS index corresponding to both forms of the first token. ** </ol> ** ** Whether it is parsing document or query text, any call to xToken that ** specifies a <i>tflags</i> argument with the FTS5_TOKEN_COLOCATED bit ** is considered to supply a synonym for the previous token. For example, ** when parsing the document "I won first place", a tokenizer that supports |
︙ | ︙ | |||
197411 197412 197413 197414 197415 197416 197417 | ** There is no limit to the number of synonyms that may be provided for a ** single token. ** ** In many cases, method (1) above is the best approach. It does not add ** extra data to the FTS index or require FTS5 to query for multiple terms, ** so it is efficient in terms of disk space and query speed. However, it ** does not support prefix queries very well. If, as suggested above, the | | | 197438 197439 197440 197441 197442 197443 197444 197445 197446 197447 197448 197449 197450 197451 197452 | ** There is no limit to the number of synonyms that may be provided for a ** single token. ** ** In many cases, method (1) above is the best approach. It does not add ** extra data to the FTS index or require FTS5 to query for multiple terms, ** so it is efficient in terms of disk space and query speed. However, it ** does not support prefix queries very well. If, as suggested above, the ** token "first" is substituted for "1st" by the tokenizer, then the query: ** ** <codeblock> ** ... MATCH '1s*'</codeblock> ** ** will not match documents that contain the token "1st" (as the tokenizer ** will probably not map "1s" to any prefix of "first"). ** |
︙ | ︙ | |||
214385 214386 214387 214388 214389 214390 214391 | static void fts5SourceIdFunc( sqlite3_context *pCtx, /* Function call context */ int nArg, /* Number of args */ sqlite3_value **apUnused /* Function arguments */ ){ assert( nArg==0 ); UNUSED_PARAM2(nArg, apUnused); | | | 214412 214413 214414 214415 214416 214417 214418 214419 214420 214421 214422 214423 214424 214425 214426 | static void fts5SourceIdFunc( sqlite3_context *pCtx, /* Function call context */ int nArg, /* Number of args */ sqlite3_value **apUnused /* Function arguments */ ){ assert( nArg==0 ); UNUSED_PARAM2(nArg, apUnused); sqlite3_result_text(pCtx, "fts5: 2018-09-15 04:01:47 b63af6c3bd33152742648d5d2e8dc5d5fcbcdd27df409272b6aea00a6f761760", -1, SQLITE_TRANSIENT); } static int fts5Init(sqlite3 *db){ static const sqlite3_module fts5Mod = { /* iVersion */ 2, /* xCreate */ fts5CreateMethod, /* xConnect */ fts5ConnectMethod, |
︙ | ︙ | |||
219095 219096 219097 219098 219099 219100 219101 | #endif return rc; } #endif /* SQLITE_CORE */ #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */ /************** End of stmt.c ************************************************/ | | | | 219122 219123 219124 219125 219126 219127 219128 219129 219130 219131 219132 219133 219134 219135 | #endif return rc; } #endif /* SQLITE_CORE */ #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */ /************** End of stmt.c ************************************************/ #if __LINE__!=219129 #undef SQLITE_SOURCE_ID #define SQLITE_SOURCE_ID "2018-09-15 04:01:47 b63af6c3bd33152742648d5d2e8dc5d5fcbcdd27df409272b6aea00a6f76alt2" #endif /* Return the source-id for this library */ SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } /************************** End of sqlite3.c ******************************/ |
Changes to src/sqlite3.h.
︙ | ︙ | |||
121 122 123 124 125 126 127 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.25.0" #define SQLITE_VERSION_NUMBER 3025000 | | | 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.25.0" #define SQLITE_VERSION_NUMBER 3025000 #define SQLITE_SOURCE_ID "2018-09-15 04:01:47 b63af6c3bd33152742648d5d2e8dc5d5fcbcdd27df409272b6aea00a6f761760" /* ** CAPI3REF: Run-Time Library Version Numbers ** KEYWORDS: sqlite3_version sqlite3_sourceid ** ** These interfaces provide the same information as the [SQLITE_VERSION], ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros |
︙ | ︙ | |||
1078 1079 1080 1081 1082 1083 1084 | ** ** <li>[[SQLITE_FCNTL_DATA_VERSION]] ** The [SQLITE_FCNTL_DATA_VERSION] opcode is used to detect changes to ** a database file. The argument is a pointer to a 32-bit unsigned integer. ** The "data version" for the pager is written into the pointer. The ** "data version" changes whenever any change occurs to the corresponding ** database file, either through SQL statements on the same database | | | | | | > | 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 | ** ** <li>[[SQLITE_FCNTL_DATA_VERSION]] ** The [SQLITE_FCNTL_DATA_VERSION] opcode is used to detect changes to ** a database file. The argument is a pointer to a 32-bit unsigned integer. ** The "data version" for the pager is written into the pointer. The ** "data version" changes whenever any change occurs to the corresponding ** database file, either through SQL statements on the same database ** connection or through transactions committed by separate database ** connections possibly in other processes. The [sqlite3_total_changes()] ** interface can be used to find if any database on the connection has changed, ** but that interface responds to changes on TEMP as well as MAIN and does ** not provide a mechanism to detect changes to MAIN only. Also, the ** [sqlite3_total_changes()] interface responds to internal changes only and ** omits changes made by other database connections. The ** [PRAGMA data_version] command provide a mechanism to detect changes to ** a single attached database that occur due to other database connections, ** but omits changes implemented by the database connection on which it is ** called. This file control is the only mechanism to detect changes that ** happen either internally or externally and that are associated with ** a particular attached database. ** </ul> */ #define SQLITE_FCNTL_LOCKSTATE 1 #define SQLITE_FCNTL_GET_LOCKPROXYFILE 2 #define SQLITE_FCNTL_SET_LOCKPROXYFILE 3 #define SQLITE_FCNTL_LAST_ERRNO 4 #define SQLITE_FCNTL_SIZE_HINT 5 |
︙ | ︙ | |||
4727 4728 4729 4730 4731 4732 4733 | ** parameters. ^An aggregate SQL function requires an implementation of xStep ** and xFinal and NULL pointer must be passed for xFunc. ^To delete an existing ** SQL function or aggregate, pass NULL pointers for all three function ** callbacks. ** ** ^The sixth, seventh, eighth and ninth parameters (xStep, xFinal, xValue ** and xInverse) passed to sqlite3_create_window_function are pointers to | | | 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 | ** parameters. ^An aggregate SQL function requires an implementation of xStep ** and xFinal and NULL pointer must be passed for xFunc. ^To delete an existing ** SQL function or aggregate, pass NULL pointers for all three function ** callbacks. ** ** ^The sixth, seventh, eighth and ninth parameters (xStep, xFinal, xValue ** and xInverse) passed to sqlite3_create_window_function are pointers to ** C-language callbacks that implement the new function. xStep and xFinal ** must both be non-NULL. xValue and xInverse may either both be NULL, in ** which case a regular aggregate function is created, or must both be ** non-NULL, in which case the new function may be used as either an aggregate ** or aggregate window function. More details regarding the implementation ** of aggregate window functions are ** [user-defined window functions|available here]. ** |
︙ | ︙ | |||
9253 9254 9255 9256 9257 9258 9259 | ** The following are allowed values for 6th argument (the F argument) to ** the [sqlite3_deserialize(D,S,P,N,M,F)] interface. ** ** The SQLITE_DESERIALIZE_FREEONCLOSE means that the database serialization ** in the P argument is held in memory obtained from [sqlite3_malloc64()] ** and that SQLite should take ownership of this memory and automatically ** free it when it has finished using it. Without this flag, the caller | | | 9254 9255 9256 9257 9258 9259 9260 9261 9262 9263 9264 9265 9266 9267 9268 | ** The following are allowed values for 6th argument (the F argument) to ** the [sqlite3_deserialize(D,S,P,N,M,F)] interface. ** ** The SQLITE_DESERIALIZE_FREEONCLOSE means that the database serialization ** in the P argument is held in memory obtained from [sqlite3_malloc64()] ** and that SQLite should take ownership of this memory and automatically ** free it when it has finished using it. Without this flag, the caller ** is responsible for freeing any dynamically allocated memory. ** ** The SQLITE_DESERIALIZE_RESIZEABLE flag means that SQLite is allowed to ** grow the size of the database using calls to [sqlite3_realloc64()]. This ** flag should only be used if SQLITE_DESERIALIZE_FREEONCLOSE is also used. ** Without this flag, the deserialized database cannot increase in size beyond ** the number of bytes specified by the M parameter. ** |
︙ | ︙ | |||
11431 11432 11433 11434 11435 11436 11437 | ** document such as "I won first place" is tokenized, entries are ** added to the FTS index for "i", "won", "first", "1st" and ** "place". ** ** This way, even if the tokenizer does not provide synonyms ** when tokenizing query text (it should not - to do would be ** inefficient), it doesn't matter if the user queries for | | | 11432 11433 11434 11435 11436 11437 11438 11439 11440 11441 11442 11443 11444 11445 11446 | ** document such as "I won first place" is tokenized, entries are ** added to the FTS index for "i", "won", "first", "1st" and ** "place". ** ** This way, even if the tokenizer does not provide synonyms ** when tokenizing query text (it should not - to do would be ** inefficient), it doesn't matter if the user queries for ** 'first + place' or '1st + place', as there are entries in the ** FTS index corresponding to both forms of the first token. ** </ol> ** ** Whether it is parsing document or query text, any call to xToken that ** specifies a <i>tflags</i> argument with the FTS5_TOKEN_COLOCATED bit ** is considered to supply a synonym for the previous token. For example, ** when parsing the document "I won first place", a tokenizer that supports |
︙ | ︙ | |||
11459 11460 11461 11462 11463 11464 11465 | ** There is no limit to the number of synonyms that may be provided for a ** single token. ** ** In many cases, method (1) above is the best approach. It does not add ** extra data to the FTS index or require FTS5 to query for multiple terms, ** so it is efficient in terms of disk space and query speed. However, it ** does not support prefix queries very well. If, as suggested above, the | | | 11460 11461 11462 11463 11464 11465 11466 11467 11468 11469 11470 11471 11472 11473 11474 | ** There is no limit to the number of synonyms that may be provided for a ** single token. ** ** In many cases, method (1) above is the best approach. It does not add ** extra data to the FTS index or require FTS5 to query for multiple terms, ** so it is efficient in terms of disk space and query speed. However, it ** does not support prefix queries very well. If, as suggested above, the ** token "first" is substituted for "1st" by the tokenizer, then the query: ** ** <codeblock> ** ... MATCH '1s*'</codeblock> ** ** will not match documents that contain the token "1st" (as the tokenizer ** will probably not map "1s" to any prefix of "first"). ** |
︙ | ︙ |
Changes to win/Makefile.PellesCGMake.
︙ | ︙ | |||
182 183 184 185 186 187 188 | $(APPLICATION): $(TRANSLATEDOBJ) $(SQLITEOBJ) $(SQLITESHELLOBJ) $(THOBJ) $(ZLIBOBJ) headers $(RESOURCE) $(LINK) $(LINKFLAGS) -out:"$@" $(TRANSLATEDOBJ) $(SQLITEOBJ) $(SQLITESHELLOBJ) $(THOBJ) $(ZLIBOBJ) $(RESOURCE) # cleanup .PHONY: clean clean: | | | | | | | 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 | $(APPLICATION): $(TRANSLATEDOBJ) $(SQLITEOBJ) $(SQLITESHELLOBJ) $(THOBJ) $(ZLIBOBJ) headers $(RESOURCE) $(LINK) $(LINKFLAGS) -out:"$@" $(TRANSLATEDOBJ) $(SQLITEOBJ) $(SQLITESHELLOBJ) $(THOBJ) $(ZLIBOBJ) $(RESOURCE) # cleanup .PHONY: clean clean: -del /F $(TRANSLATEDOBJ) $(SQLITEOBJ) $(THOBJ) $(ZLIBOBJ) $(UTILS_OBJ) version.obj -del /F $(TRANSLATEDSRC) -del /F *.h headers -del /F $(RESOURCE) .PHONY: clobber clobber: clean -del /F *.exe |
Changes to win/Makefile.msc.
︙ | ︙ | |||
1020 1021 1022 1023 1024 1025 1026 | "$(OX)\page_index.h": "$(OBJDIR)\mkindex$E" $(SRC) $** > $@ "$(OX)\builtin_data.h": "$(OBJDIR)\mkbuiltin$E" "$(OX)\builtin_data.reslist" "$(OBJDIR)\mkbuiltin$E" --prefix "$(SRCDIR)/" --reslist "$(OX)\builtin_data.reslist" > $@ cleanx: | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 | "$(OX)\page_index.h": "$(OBJDIR)\mkindex$E" $(SRC) $** > $@ "$(OX)\builtin_data.h": "$(OBJDIR)\mkbuiltin$E" "$(OX)\builtin_data.reslist" "$(OBJDIR)\mkbuiltin$E" --prefix "$(SRCDIR)/" --reslist "$(OX)\builtin_data.reslist" > $@ cleanx: -del "$(OX)\*.obj" 2>NUL -del "$(OBJDIR)\*.obj" 2>NUL -del "$(OX)\*_.c" 2>NUL -del "$(OX)\*.h" 2>NUL -del "$(OX)\*.ilk" 2>NUL -del "$(OX)\*.map" 2>NUL -del "$(OX)\*.res" 2>NUL -del "$(OX)\*.reslist" 2>NUL -del "$(OX)\headers" 2>NUL -del "$(OX)\linkopts" 2>NUL -del "$(OX)\vc*.pdb" 2>NUL clean: cleanx -del "$(APPNAME)" 2>NUL -del "$(PDBNAME)" 2>NUL -del "$(APPMANIFEST)" 2>NUL -del "$(OBJDIR)\translate$E" 2>NUL -del "$(OBJDIR)\translate$P" 2>NUL -del "$(OBJDIR)\mkindex$E" 2>NUL -del "$(OBJDIR)\mkindex$P" 2>NUL -del "$(OBJDIR)\makeheaders$E" 2>NUL -del "$(OBJDIR)\makeheaders$P" 2>NUL -del "$(OBJDIR)\mkversion$E" 2>NUL -del "$(OBJDIR)\mkversion$P" 2>NUL -del "$(OBJDIR)\mkcss$E" 2>NUL -del "$(OBJDIR)\mkcss$P" 2>NUL -del "$(OBJDIR)\codecheck1$E" 2>NUL -del "$(OBJDIR)\codecheck1$P" 2>NUL -del "$(OBJDIR)\mkbuiltin$E" 2>NUL -del "$(OBJDIR)\mkbuiltin$P" 2>NUL realclean: clean "$(OBJDIR)\json$O" : "$(SRCDIR)\json_detail.h" "$(OBJDIR)\json_artifact$O" : "$(SRCDIR)\json_detail.h" "$(OBJDIR)\json_branch$O" : "$(SRCDIR)\json_detail.h" "$(OBJDIR)\json_config$O" : "$(SRCDIR)\json_detail.h" |
︙ | ︙ |
Changes to www/alerts.md.
|
| | < < < < | < < | | < < | | | | | | > | | > > > | | > | < > > > | < | < > > < < > > > > | < < > > > > > > < | > > | | > > > > > | | < > > > > > | | > | < > | | > | > > | > | | < < < < < > > > | | > | | < | | | | | | | > > > > > > | > > > | > > > | > > > | | | | > | | < | < | | | > | < | > > > > > > > > | < < < > | > > > | | | > | | | | | | | | > | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | > > > > > > | > > | > | > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > | > > > > > > > > | | > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | < | > | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 | # Email Alerts ## Overview Beginning with version 2.7, Fossil can send email messages to subscribers to alert them to changes in the repository: * New [checkins](/help?cmd=ci) * [Ticket](./tickets.wiki) changes * [Wiki](./wikitheory.wiki) page changes * New and edited [forum](./forum.wiki) posts * Announcements Subscribers can elect to receive emails as soon as these events happen, or they can receive a daily digest of the events instead. Email alerts are sent by a [Fossil server](./server.wiki), which must be [set up](#quick) by the Fossil administrator to send email. Email alerts do not currently work if you are only using Fossil from the command line. A bit of terminology: Fossil uses the terms "email alerts" and "notifications" interchangeably. We stick to the former term in this document except when referring to parts of the Fossil UI still using the latter term. ## Setup Prerequisites Much of this document describes how to set up Fossil's email alert system. To follow this guide, you will need a Fossil UI browser window open to the [Admin → Notification](/setup_notification) Fossil UI screen on the the Fossil server that will be sending these email alerts, logged in as a user with Admin capability. It is not possible to work on a clone of the server's repository and push the configuration changes up to that repo as an Admin user, [on purpose](#backup). **Important:** Do not confuse that screen with Admin → Email-Server, which sets up a different subsystem within Fossil. That feature is related to this document's topic, but it is currently incomplete, so we do not cover it at this time. <a id="cd"></a> You will also need a CLI window open with its working directory changed to a checkout directory of the Fossil repository you are setting up to send email. If you don't `cd` to such a checkout directory first, you'll need to add `-R /path/to/repo.fossil` to each `fossil` command below to tell Fossil which repository you mean it to apply the command to. There are other prerequisites for email service, but since they vary depending on the configuration you choose, we'll cover these inline below. <a id="quick"></a> ## Quick Email Service Setup If you've already got a working Postfix, Exim, or Sendmail server on the machine running your Fossil instance(s), and you aren't using Fossil's `chroot` feature to wall Fossil off from the rest of the machine, it's fairly simple to set up email alerts. (Otherwise, skip [ahead](#advanced) to the sections on advanced email service setup.) This is our "quick setup" option even though setting up an SMTP mail server is not trival, because there are many other reasons to have such a server set up already: internal project email service, `cron` notifications, server status monitoring notifications... With that out of the way, the Fossil-specific steps are easy: 1. Go to [Admin → Notification](/setup_notification) and fill out all of the **Required** fields: * **Canonical server URL** — Use the suggested URL * **"From" email address** — `forum-bounces@example.com` is traditional, but suit yourself * **Repository nickname** — See the suggested examples on the web page. 2. Set "Email Send Method" to "Pipe to a command" 3. Set the "Administrator email address" to a suitable valid email address on that machine. It could be the same value you used for the "From" address above, or it could be a different value like `admin@example.com`. Save your changes. At the command line, say $ fossil set email-send-command If that gives a blank value instead of `sendmail -ti`, say $ fossil set email-send-command "sendmail -ti" to force the setting. That works around a [known bug](https://fossil-scm.org/forum/forumpost/840b676410) which may be squished by the time you read this. If you're running Postfix or Exim, you might think that command is wrong, since you aren't running Sendmail. These mail servers provide a `sendmail` command for compatibility with software like Fossil that has no good reason to care exactly which SMTP server implementation is running at a given site. There may be other SMTP servers that also provide a compatible `sendmail` command, in which case they may work with Fossil using the same steps as above. <a id="status"></a> If you reload the Admin → Notification page, the Status section at the top should show: Outgoing Email: Piped to command "sendmail -ti" Pending Alerts: 0 normal, 0 digest Subscribers: 0 active, 0 total Before you move on to the next section, you might like to read up on [some subtleties](#pipe) with the "pipe to a command" method that we did not cover above. <a id="usage"></a> ## Usage and Testing Now that email service from Fossil is set up, you can test it and begin using it. <a id="sub" name="subscribe"></a> ### Subscribing to Alerts In the Status output above, we saw that there are no subscribers, so the next step is to add the first one. Go to the `/subscribe` page on your Fossil instance to sign up for email alerts. At the very least, you will need to sign up for "Forum Posts" and "Announcements" to complete the testing steps below. If you're logged in with a Fossil repository user account and put the same user name and email address into this forum as you used for your user information under Admin → Users, Fossil will simply tie your alert preferences to your login record, and the email address in your user's Contact Info field will be considered already-verified. Otherwise, Fossil will create an alert-only record, and you will have to verify the email address before Fossil will send alerts to it. This shows a key aspect of the way Fossil's email alerts system works, by the way: a user can be signed up for email alerts without having a full-fledged Fossil user account. Only when both user names are the same are the two records tied together under the hood. For more on this, see [Users vs Subscribers below](#uvs). If you are seeing the following complaint from Fossil: <blockquote> Use a different login with greater privilege than FOO to access /subscribe </blockquote> ...then the repository's administrator forgot to [give the Alerts capability](#cap7) to that user or to a user category that the user is a member of. After a subscriber signs up for alerts for the first time, a single verification email is sent to that subscriber's given email address. The new subscriber must click a link in that email in order to activate the subscription. Subscription verification emails are only sent once. This is a defense against malicious robots that try to harass innocent Internet users by having subscription pages send multiple verification emails. If the initial subscription verification does not go through correctly, an administrator must [intervene](#admin) to reset the subscription. Every subscriber-only email address has a [long random hexadecimal security code](#scode) that serves in place of a password. All email alerts contain a link in their footer back to the Fossil server, incorporating this security code, which allows the subscriber to adjust their subscription options. If a user doesn't have any of those emails, they can request a link via email by visiting the `/alerts` or `/unsubscribe` page on the repository. Those with Fossil repository logins can adjust their email alert settings by visiting the `/alerts` page on the repository. With the default skin, you can get there by clicking the "Logout" link in the upper right corner of any Fossil UI page then clicking the "Email Alerts" link. That link is also available via the Sitemap (`/sitemap`) and via the default skin's hamburger menu (☰). <a id="unsub" name="unsubscribe"></a> ### Unsubscribing To unsubscribe from alerts, visit the `/alerts` page on the repository, click the "Unsubscribe" button, then check the "Unsbuscribe" checkbox to verify your action and press the "Unsubscribe" button a second time. This interlock is intended to prevent accidental unsubscription. <a id="test"></a> ### Test Email Service The easiest way to test email sending from Fossil is via the "[Send Announcement](/announce)" link at the top of the "Email Notification Setup" page. Put your email address in the "To:" line and a test message below, then press "Send Message" to verify that outgoing email is working. Another method is from the command line: $ fossil alerts test-message you@example.com --body README.md --subject Test That should send you an email with "Test" in the subject line and the contents of your project's `README.md` file in the body. That command assumes that your project contains a "readme" file, but of course it does, because you have followed the [Programming Style Guide Checklist][cl], right? Right. [cl]: https://sendgrid.com/blog/programming-style-guide-checklist/ <a id="cap7"></a> ### User Capabilities Once email alerts are working, one must also adjust user permissions to allow users to subscribe to email alerts. In the capability list for each user on the Admin → Users page is a new capability called "Email Alerts". The corresponding capability letter is "7", which you must give to any user that needs to use the subscription setup pages, `/subscribe` and `/alerts`. To allow any passer-by on the Internet to subscribe, give the "Email Alerts" capability to the "nobody" user category. To require that a person solve a simple CAPTCHA first, give that capability to the "anonymous" user category instead. <a id="first" name="frist"></a> ### First Post I suggest taking the time to compose a suitable introductory message especially for your project's forum, one which a new user would find helpful. Wait a few seconds, and you should receive an email alert with the post's subject and body text in the email. <a id="trouble"></a> ### Troubleshooting If email alerts aren't working, there are several useful commands you can give to figure out why. (Be sure to [`cd` into a repo checkout directory](#cd) first!) $ fossil alerts status This should give much the same information as you saw [above](#status). One difference is that, since you've created a forum post, the `pending-alerts` value should only be zero if you did in fact get the requested email alert. If it's zero, check your mailer's spam folder. If it's nonzero, continue with these troubleshooting steps. $ fossil backoffice That forces Fossil to run its ["back office" process](./backoffice.md). Its only purpose at the time of this writing is to push out alert emails, but it might do other things later. Sometimes it can get stuck and needs to be kicked. For that reason, you might want to set up a crontab entry to make sure it runs occasionally. $ fossil alerts send This should also kick off the backoffice processing, if there are any pending alerts to send out. $ fossil alert pending Show any pending alerts. The number of lines output here should equal the [status output above](#status). $ fossil test-add-alerts f5900 $ fossil alert send Manually create an email alert and push it out immediately. The `f` in the first command's final parameter means you're scheduling a "forum" alert. The integer is the ID of a forum post, which you can find by visiting `/timeline?showid` on your Fossil instance. The second command above is necessary because the `test-add-alerts` command doesn't kick off a backoffice run. $ fossil ale send This only does the same thing as the final command above, rather than send you an ale, as you might be hoping. Sorry. <a id="advanced"></a> ## Advanced Email Setups Fossil offers several methods of sending email: 1. Pipe the email message text into a command. 2. Store email messages as entries in a SQLite database. 3. Store email messages as individual files in a directory. 4. Send emails to an SMTP relay. 5. Send emails directly to the recipients via SMTP. This wide range of options allows Fossil to talk to pretty much any SMTP setup. The first four options let Fossil delegate email handling to an existing [MTA][mta] so that Fossil does not need to implement the [roughly two dozen][mprotos] separate [RFCs][rfcs] required in order to properly support SMTP email in this complex world we've built. As well, this design choice means you do not need to do duplicate configuration, such as to point Fossil at your server's TLS certificate in order to support users behind mail servers that require STARTTLS encryption. [mprotos]: http://sqlite.1065341.n5.nabble.com/Many-ML-emails-going-to-GMail-s-SPAM-tp98685p98722.html [rfcs]: https://en.wikipedia.org/wiki/Request_for_Comments <a id="pipe"></a> ### Method 1: Pipe to a Command This is our ["quick setup" option](#quick) above, but there are some details we ignored which we'll cover now. Fossil pipes the email message in [RFC 822 format][rfc822] to the standard input of the command you gave as the "Email Send Method", defaulting to `sendmail -ti`. This constitutes a protocol between Fossil and the SMTP [message transfer agent (MTA)][mta]. Any other MTA which speaks the same protocol can be used in place of the most common options: Sendmail, Exim, and Postfix. The `-t` option tells the command to expect the list of email recipients in a `To` header in the RFC 822 message presented on its standard input. Without this option, the `sendmail` command expects to receive the recipient list on the command line, but that's not possible with the current design of this email sending method. Therefore, if you're attempting to use a less common MTA which cannot parse the recipient list from the `To` header in the email message, you might need to look for a different MTA. The `-i` option is only needed for MTAs that take a dot/period at the beginning of a line of standard input text as "end of message." Fossil doesn't attempt to escape such dots, so if the line wrapping happens to occur such that a dot or period in an alert message is at the beginning of a line, you'll get a truncated email message without this option. Statistically, this will happen about once every 70 or so messages, so it is important to give this option if your MTA treats leading dots on a line this way. <a id="msmtp"></a> We believe the [`msmtp`][msmtp] SMTP client is compatible with this protocol if you give it the `-t` option. To our knowledge, this remains untested, but if it works, this would be a useful option on a server hosting a Fossil repository which doesn't otherwise require a separate SMTP server for other purposes. It is probably also possible to configure [`procmail`][pmdoc] to work with this protocol. If you know how to do it, a patch to this document or a how-to on [the Fossil forum][ff] would be appreciated. [ff]: https://fossil-scm.org/forum/ [msmtp]: https://marlam.de/msmtp/ [mta]: https://en.wikipedia.org/wiki/Message_transfer_agent [pmdoc]: http://pm-doc.sourceforge.net/doc/ [rfc822]: https://www.w3.org/Protocols/rfc822/ <a id="db"></a> ### Method 2: Store in a Database The self-hosting Fossil repository at <https://www.fossil-scm.org/> currently uses this method rather than [the pipe method](#pipe) because it is running inside of a restrictive [chroot jail][cj] which is unable to hand off messages to the local MTA directly. When you configure a Fossil server this way, it adds outgoing email messages to a SQLite database file. A separate daemon process can then extract those messages for further disposition. Fossil includes a copy of [the daemon](/file/tools/email-sender.tcl) used on `fossil-scm.org`: it is just a short Tcl script that continuously monitors this database for new messages and hands any that it finds off to a local MTA using the same [pipe to MTA protocol](#pipe) as above. In this way, outbound email alerts escape the chroot jail without requiring that we insert a separate MTA configuration inside that jail. We only need to arrange that the same SQLite DB file be visible both inside and outside the chroot jail, which we do by naming the database file in the "Store Emails In This Database" setting under Admin → Notification. The Tcl script has this path hard-coded as `/home/www/fossil/emailqueue.db`, but you will probably need to adjust that for your local purposes. This method may work with other similar technologies besides `chroot`: Docker containers, LXC containers, BSD jails, Solaris zones, etc. With suitable file share mappings, this method may even work with virtual machine or distributed computing setups where the MTA and Fossil servers are not on the same machine, though beware the [risk of DB corruption][rdbc] if used with a file sharing technology that doesn't use proper file locking. You can start this Tcl script as a daemon automatically on most Unix and Unix-like systems by adding the following line to the `/etc/rc.local` file of the server that hosts the repository sending email alerts: /usr/bin/tclsh /home/www/fossil/email-sender.tcl & [cj]: https://en.wikipedia.org/wiki/Chroot [rdbc]: https://www.sqlite.org/howtocorrupt.html#_filesystems_with_broken_or_missing_lock_implementations <a id="dir"></a> ### Method 3: Store in a Directory This method is functionally very similar to [the DB method](#db), differing only in that messages are written to a directory in the filesystem. You should therefore read that section and make the minor adjustments required by the storage method. This method may work over a file sharing mechanism that doesn't do file locking properly, as long as the reading process is somehow restricted from reading a message file as it's being written. It might be useful in testing and debugging to temporarily switch to this method, since you can easily read the generated email messages without needing to involve [an MTA][mta]. <a id="relay"></a> ### Method 4: SMTP Relay In this configuration, the Fossil server contacts an open SMTP relay and sends the messages to it. This method is only appropriate when: 1. You have a local MTA that doesn't accept [the pipe protocol](#pipe). 2. The MTA is willing to accept anonymous submissions, since Fossil currently has no way to authenticate itself to the MTA. This is [an unsafe configuration][omr] in most cases, but some SMTP servers make an exception for connections coming from a `localhost` or LAN address, choosing to accept such submissions as inherently safe. If you have a local MTA meeting criterion #1 but not #2, we'd suggest using a more powerful SMTP client such as [msmtp](#msmtp) along with one of the other methods above. [omr]: https://en.wikipedia.org/wiki/Open_mail_relay <a id="direct"></a> ### Method 5: Direct SMTP Send As of Fossil 2.7, the code to support this method is incomplete, so you cannot currently select it as an option in Admin → Notification. <a id="uvs"></a> ## Users vs Subscribers Fossil makes a distinction between "users" and "subscribers". A user is someone with a username and password: that is, someone who can log into the Fossi repository. A subscriber is someone who receives email alerts. Users can also be subscribers and subscribers can be users, but that does not have to be the case. It is possible to be a user without being a subscriber and to be a subscriber without being a user. In the repository database file, users are tracked with the `user` table and subscribers are tracked via the `subscriber` table. <a id="admin"></a> ## Administrator Activities The "[List Subscribers](/subscribers)" button at the top of the Admin → Notification screen gives a list of subscribers, which gives a Fossil server administrator a lot of power over those subscriptions. Clicking an email address in this subscriber list opens the same `/alerts` page that the user can see for their own subscription, but with more information and functionality than normal users get: * Subscription creation and modification timestamps. * The IP address the user had when they last made a change via either `/subscribe` or `/alert`. * The user's login name, if they are not [a mere subscriber](#uvs). A Fossil Admin user is allowed to modify this, either to tie a subscription-only record to an existing Fossil user account or to break that tie. * The "Do not call" checkbox allows a Fossil Admin user to mark a given email address so that Fossil never sends email to that address. This is distinct from unsubscribing that email address because it prevents Fossil from accepting a new subscription for that address. * The Verified checkbox is initially unchecked for subscriber-only email addresses until the user clicks the link in the verification email. This checkbox lets the Fossil Admin user manually verify the user, such as in the case where the verification email message got lost. Unchecking this box does not cause another verification email to be sent. This screen also allows a Fossil Admin user to perform other activities on behalf of a subscriber which they could do themselves, such as to [unsubscribe](#unsub) them. <a id="backup"></a> ## Cloning, Syncing, and Backups The Admin → Notification settings are not replicated using clone or sync, and it is not possible to push such settings from one repository to another. In a network of peer repositories, you only want one repository sending email alerts. If you were to replicate the email alert settings to a separate repository, then subscribers would get multiple alerts for each event, which would be bad. However, the subscriber list can be synced for backup purposes. Use the [`fossil config pull subscriber`](/help?cmd=configuration) command to pull the latest subscriber list from a server into a backup repository. The `push`, `export`, and `import` commands all work similarly. <a id="pages" name="commands"></a> ## Controlling the Email Alert System This section collects the list of Fossil UI pages and CLI commands that control the email alert system, some of which have not been mentioned so far: Commands: * The [`alerts`](/help?cmd=alerts) command * The [`test-alert`](/help?cmd=test-alert) command * The [`test-add-alerts`](/help?cmd=test-add-alerts) command Web pages available to users and subscribers: * The [`/subscribe`](/help?cmd=/subscribe) page * The [`/alerts`](/help?cmd=/alerts) page * The [`/unsubscribe`](/help?cmd=/unsubscribe) page * The [`/contact_admin`](/help?cmd=/contact_admin) page Administrator-only web pages: * The [`/setup_notification`](/help?cmd=/setup_notification) page * The [`/subscribers`](/help?cmd=/subscribers) page <a id="design"></a> ## Design of Email Alerts This section describes the low-level design of the email alert system in Fossil. This expands on the high-level administion focused material above with minimal repetition. This section assumes expert-level systems knowledge. If the material above sufficed for your purposes, feel free to skip this section, which runs to the end of this document. <a id="datades"></a> ### Data Design There are three new tables in the repository database, starting with Fossil 2.7. These tables are not created in new repositories by default. The tables only come into existence as needed when email alerts are configured and used. * <b>SUBSCRIBER</b> → The subscriber table records the email address for people who want to receive email notifications. Each subscriber has a `subscriberCode` which is a random 32-byte blob that uniquely identifies the subscriber. There are also fields to indicate what kinds of notifications the subscriber wishes to receive, whether or not the email address of the subscriber has been verified, etc. * <b>PENDING\_ALERT</b> → The PENDING\_ALERT table contains records that define events about which alert emails might need to be sent. A pending\_alert always refers to an entry in the EVENT table. The EVENT table is part of the standard schema and records timeline entries. In other words, there is one row in the EVENT table for each possible timeline entry. The PENDING\_ALERT table refers to EVENT table entries for which we might need to send alert emails. * <b>EMAIL\_BOUNCE</b> → This table is intended to record email bounce history so that subscribers with excessive bounces can be turned off. That logic has not yet been implemented so the EMAIL\_BOUNCE table is currently unused. As pointed out above, ["subscribers" are distinct from "users"](#uvs). The SUBSCRIBER.SUNAME field is the optional linkage between users and subscribers. <a id="stdout"></a> ### The "stdout" Method The [list of mail sending methods](#advanced) above left out an internal-only method called "stdout" which simply writes the text of the email message on standard output. The "stdout" method is used for testing and debugging. If you need something similar and can't modify your local Fossil instance to use this method, you might temporarily switch to [the "dir" method](#dir) instead. <a id="msgfmt"></a> ### Message Format The email messages generated by Fossil have a [well-formed header][rfc822]. The downstream processing is expected to extract the "To:", "From:", "Subject:" and whatever other attributes it needs from the email header text. These emails use the `text/plain` MIME type with the UTF-8 character set. We currently use a transfer encoding of `quoted-printable`, but there is commented-out code in Fossil to switch to `base64` encoding, which Fossil used in the early days leading up to the 2.7 release. If you switch Fossil back to `base64` mode, you may want to build a utility program that ships in the Fossil source tree named ["tools/decode-email.c"](/file/tools/decode-email.c) which can decode these messages into a human-readable format. <a id="inbound" name="bounces"></a> ### Dealing with Inbound Email Inbound email messages — for example, bounces from failed alert emails — should be relayed to the `fossil email inbound` command. That command is currently a no-op place-holder. At some point, we will need to design and write a bounce-message processing system for Fossil. <a id="password" name="scode" name="verification"></a> ### Passwords vs Subscriber Codes When anonymous passers-by on the Internet sign up for email alerts, their email address must first be verified. An email message is sent to the address supplied inviting the user to click on a link. The link includes a pseudorandom 128-bit blob encoded as 32 hexadecimal digits, which serves in place of a password for that email address. (This is stored in the database as `subscriber.subscriberCode`.) If anyone visits the link, the email address is verified. Knowledge of the `subscriberCode` is sufficient to control a subscription. Because this code is included in plain text in email alert messages, it is not as secure as a separate password, but it has several virtues: * It is easier for the average subscriber to deal with in that they don't have to come up with yet another password and store it safely. * If the `subscriberCode` is stolen, the worst that can happen is that the thief can change that email address's subscription settings. Contrast a password which may be shared with other services, which then compromises those other services. * No PII other than the subscriber's email address is available to an attacker with the `subscriberCode`. Nor can knowledge of the `subscriberCode` lead to a email flood or other annoyance attack, as far as I can see. If the `subscriberCodes` for a Fossil repository are ever compromised, new ones can be generated as follows: UPDATE subscriber SET subscriberCode=randomblob(32); Since this then affects all new email alerts going out from Fossil, your end users may never even realize that they're getting new codes, as long as they don't click on the URLs in the footer of old alert messages. With that in mind, a Fossil server administrator could choose to randomize the `subscriberCodes` periodically, such as just before the daily digest emails are sent out each day. **Important:** All of the above is distinct from the passwords for users with a Fossil repository login. Such users also have subscriber codes, but those codes can only be used to modify the user's email alert settings. That code cannot allow a user to log into the user's Fossil repository account. <a id="processing"></a> ### Internal Processing Flow Almost all of the email alert code is found in the [`src/alerts.c`](/file/src/alerts.c) source file. When email alerts are enabled, a trigger is created in the schema (`email_trigger1`) that adds a new entry to the `PENDING_ALERT` table every time a row is added to the `EVENT` table. During a `fossil rebuild`, the `EVENT` table is rebuilt from scratch; since we do not want users to get alerts for every historical check-in, the trigger is disabled during `rebuild`. Email alerts are sent out by the `alert_send_alerts()` function, which is normally called automatically due to the `email-autoexec` setting, which defaults to enabled. If that setting is disabled or if the user simply wants to force email alerts to be sent immediately, they can give a `fossil alert send` command, such as via a `cron` script. Each time this function is called, the alert messages are moved further down the chain, so you cannot cause duplicate alerts by calling it too often. Digests are handled by recording the time of the last digest in the `email-last-digest` setting, and only sending a new digest if the current time is one day or later after the last digest. Individual emails are sent to each subscriber. I (drh) ran tests and found that I could send about 1200 emails/second, which is fast enough that I do not need to resort to trying to notify multiple subscribers with a single email. Because each subscriber gets a separate email, the system can include information in the email that is unique to the subscriber, such as a link to the page to edit their subscription. That link includes the `subscriberCode`. |
Changes to www/changes.wiki.
1 2 3 4 5 6 7 | <title>Change Log</title> <a name='v2_7'></a> <h2>Changes for Version 2.7 (2018-09-??)</h2> * Add the [./alerts.md|email alerts] feature for commits, ticket changes, wiki changes, forum posts, and announcements. This is | | > > | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | <title>Change Log</title> <a name='v2_7'></a> <h2>Changes for Version 2.7 (2018-09-??)</h2> * Add the [./alerts.md|email alerts] feature for commits, ticket changes, wiki changes, forum posts, and announcements. This is still a work in progress. It works, but it is not as easy to setup and use as it ought to be. * Add the [./forum.wiki|discussion forum] feature. * Add new user capabilities letters needed to support alerts and forum. Formerly, user capabilities were letters from [a-z], but with the enhancements, the supply of lower case letters was exhausted. User capabilities are now letters in [a-zA-Z0-9]. * The default skin is now responsive, providing better layout on small screens, including mobile devices. * The default skin now includes a hamburger menu that is generated by the [/sitemap] page. * The [/sitemap] and other list pages show as multiple columns if the viewing window is wide enough. * There is an optional "js" file for each skin that can be used to hold javascript. This file can be loaded by reference or can be included in the header or footer. * Add the [./backoffice.md|backoffice]. * Update internal Unicode character tables, used in regular expression handling, from version 10.0 to 11.0. * Improvements to the "Security Audit" administration page * Added the [/help?cmd=branch|fossil branch current] command. * Update the built-in SQLite to version 3.25.0. * Add support for TLS 1.3, when compiled with OpenSSL 1.1.1. * Some code and interfaces are in place to support sending and receiving email directly via SMTP, but this feature is not yet complete or ready for production use. <a name='v2_6'></a> <h2>Changes for Version 2.6 (2018-05-04)</h2> * Fix a bug that was causing crashes while trying to clone the TCL repository. This fix is the main reason for the current release. * Added the new "Classic" timeline viewing mode. "Classic" is the same as "Verbose" in the previous release. The "Verbose" mode is now like "Compact" except the extra check-in details are shown by default. * Add support for ETags:, Last-Modified:, and If-Modified-Since: cache control mechanisms. * Enhance the [/help?cmd=/tarball|/tarball], [/help?cmd=/zip|/zip], and [/help?cmd=/sqlar|/sqlar] pages so that the checkin name to be downloaded can be expressed as part of the URI, and without the need for query parameters. * On the [/help?cmd=/timeline|/timeline] webpage, add the days=N query parameter and enhance the ymd=DATE and yw=DATE query parameters to accept 'now' as an argument to show the latest day or week. * In the web page that comes up in response to the [/help?cmd=all|fossil all ui] command, show the last modification time for each repository, and allow click-to-sort on the modification time column. * In the tarball cache replacement algorithm, give extra weight to tarballs that have been accessed more than once. * Additional defenses against web-based attacks. There have not been any known vulnerabilities. We are just being paranoid. * Update the built-in SQLite to an alpha version of 3.24.0. <a name='v2_5'></a> <h2>Changes for Version 2.5 (2018-02-07)</h2> * Numerous enhancements to the look and feel of the web interface. Especially: Added separate "Modern", "Compact", "Verbose", and "Columnar" view options on timelines. * Common display settings (such as the "view" option and the number of rows in a timeline) are held in a cookie and thus persist across multiple pages. * Rework the skin editing process so that changes are implemented on one of nine /draft pages, evaluated, then merged back to the default. |
︙ | ︙ |
Deleted www/emaildesign.md.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to www/forum.wiki.
︙ | ︙ | |||
95 96 97 98 99 100 101 | restrict posts to plain text only or to allow wild-west HTML-formatted MIME email. Fossil's lightweight markup language formatting features give you a middle path, providing your users enough formatting power to communicate complex ideas well without providing so much power as to risk [https://wonko.com/post/html-escaping | security problems]. | | | < < < | | | | < < < < < < < < < < < | 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | restrict posts to plain text only or to allow wild-west HTML-formatted MIME email. Fossil's lightweight markup language formatting features give you a middle path, providing your users enough formatting power to communicate complex ideas well without providing so much power as to risk [https://wonko.com/post/html-escaping | security problems]. * <b>Easy Email Alerts:</b> You can configure Fossil to [./alerts.md | send email alerts]. Forum post emails include the complete message content for the benefit of those that prefer to visit the forum only when they need to post something. Alerts are optional, and each user gets the choice of immediate or daily digest delivery. <h2 id="setup">Setting up a Fossil Forum</h2> <h3 id="caps">Capabilities</h3> Fossil forums use the same role-based access control mechanism as |
︙ | ︙ | |||
148 149 150 151 152 153 154 | showing the list of pending moderation tasks. * <b>Supervise Forum</b> (<tt>6</tt>): User can grant or revoke <b>WriteTrusted</b> capability for other users. (Currently unimplemented.) * <b>Email Alerts</b> (<tt>7</tt>): User can sign themselves up for | | | 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | showing the list of pending moderation tasks. * <b>Supervise Forum</b> (<tt>6</tt>): User can grant or revoke <b>WriteTrusted</b> capability for other users. (Currently unimplemented.) * <b>Email Alerts</b> (<tt>7</tt>): User can sign themselves up for email alerts, a.k.a. notifications. By default, no Fossil user has permission to use the forums except for users with Setup and Admin capabilities, which get these as part of the large package of other capabilities they get. For public Fossil repositories that wish to accept new users without involving a human, go into Admin → Access and enable the "Allow |
︙ | ︙ | |||
171 172 173 174 175 176 177 | For either type of repository, you are likely to want to give at least the WriteTrusted capability (4) to users in the <tt>developer</tt> category. If you did not give the Read Forum capability (2) to <tt>anonymous</tt> above, you should give <tt>developer</tt> that capability here if you choose to give it capability 3 or 4. | | | | 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 | For either type of repository, you are likely to want to give at least the WriteTrusted capability (4) to users in the <tt>developer</tt> category. If you did not give the Read Forum capability (2) to <tt>anonymous</tt> above, you should give <tt>developer</tt> that capability here if you choose to give it capability 3 or 4. If you want to use the email alert feature, by default only those users in the Setup and Admin user categories can make use of it. Grant the Email Alerts capability (7) to give others access to this feature. Alternately, you can handle alert signups outside of Fossil, with a Setup or Admin users manually signing users up via Admin → Notification. You'll want to grant this capability to the <tt>nobody</tt> user category if you want anyone to sign up without any restrictions. Give it to <tt>anonymous</tt> instead if you want the user to solve a simple CAPTCHA before signing up. Or, give it to <tt>reader</tt> or <tt>developer</tt> if you want only users with Fossil logins to have this ability. (That's assuming you give one or both of |
︙ | ︙ | |||
217 218 219 220 221 222 223 | The remainder of this section summarizes the differences you're expected to see when taking option #2. The first thing is that you'll need to add something like the following to the Header part of the skin to create the navbar link: <verbatim> | | | | 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 | The remainder of this section summarizes the differences you're expected to see when taking option #2. The first thing is that you'll need to add something like the following to the Header part of the skin to create the navbar link: <verbatim> if {[anycap 23456] || [anoncap 2] || [anoncap 3]} { menulink /forum Forum } </verbatim> These rules say that any logged-in user with any forum-related capability (2-6 inclusive, as of this writing) or an anonymous user with read or write capability on the forum (2, 3) will see the "Forum" navbar link, which just takes you to <tt>/forum</tt>. The exact code you need here varies depending on which skin you're using. Follow the style you see for the other navbar links. The new forum feature also brings many new CSS styles to the table. If |
︙ | ︙ | |||
321 322 323 324 325 326 327 | project's Fossil-hosted forum. Fossil has a feature to solve this problem which is probably less well known than it should be, and which has been a feature of Fossil since April of 2011: Admin → Login-Group. This allows one Fossil repository to recognize users authorized on a different Fossil repository. | | < < | < < | < < < | | < < < < < | < < < | < < < < < < < | < < < < < < < | < < < < < < < < < < < | < < < < < | | | < < < < | < < | < < < < < | | < | < < | < < < < < | < < < < < | | < > < < < | < | < < < < | < < < | < < < < < < | | < | < < < < < | < < < < < < < < < < < < < < < < < < < < < < < | < < < < < | < < < | < < < < < | < < | < < < < | < | < < < < < < < < < < < < < < | 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 | project's Fossil-hosted forum. Fossil has a feature to solve this problem which is probably less well known than it should be, and which has been a feature of Fossil since April of 2011: Admin → Login-Group. This allows one Fossil repository to recognize users authorized on a different Fossil repository. <h3 id="alerts">Email Alerts (a.k.a. Notifications)</h3> Internet email service has become rather complicated since its initial simple and insecure implementation decades ago. Fossil's role in all of this is rather small at the moment, but the details of the integration are complex enough to justify [./alerts.md | a separate document]. (The other reason that document is separate is that Fossil's email alerts system also gets used by features of Fossil other than the forum.) <h2 id="access">Accessing the Forum</h2> There are many paths to a repository's Fossil forum: <ul> <li> <p>If you're using the default Fossil skin as shipped with Fossil 2.7 or one updated to include the changes since 2.6 or prior, there is a Forum button in the navbar which appears for users with any of the forum-related user capabilities: 2 through 6 inclusive for those with repository logins, or caps 2 and 3 for users without a user account but who have solved the Anonymous user CAPTCHA.</p> <p>This button will not appear in the default skin for such users if their browser window is not greater than 1200 pixels wide. The Fossil admin can adjust this limit in the skin's CSS section, down near the bottom in the definition of the `wideonly` style.</p> </li> <li>The other stock skins have this button in them as of 2.7 as well, without the screen width restriction, since the navbar in those skins wraps on narrow screens more gracefully than the default skin does.</li> <li>Users who set up their Fossil repository under prior versions and who now have local skin changes they don't want to overwrite by reverting to the stock 2.7 version of the skin they chose to start with can easily [#skin | edit their skin] to include these links.</li> <li>A "Forum" link appears in the drop-down panel when you click the default skin's hamburger menu (☰) while logged in as any user with one or more of the [#caps | user capabilities listed above].</li> <li>That same link also appears on the repository's <tt>/sitemap</tt> page, since it provides the content for the hamburger menu's panel.</li> </ul> <h2 id="moderation">How Moderation Works</h2> In this section, we're going to call all of the following a "forum update:" |
︙ | ︙ |
Changes to www/makefile.wiki.
︙ | ︙ | |||
68 69 70 71 72 73 74 | 11. [/file/src/mkversion.c | mkversion.c] The builtin_data.h header file contains the definitions of C-language byte-array constants that contain various resources such as scripts and images. The builtin_data.h header file is generate from the original resource files using a small program called: | | | 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | 11. [/file/src/mkversion.c | mkversion.c] The builtin_data.h header file contains the definitions of C-language byte-array constants that contain various resources such as scripts and images. The builtin_data.h header file is generate from the original resource files using a small program called: 12 [/file/src/mkbuiltin.c | mkbuiltin.c] Examples of built-in resources include the [/file/src/diff.tcl | diff.tcl] script used to implement the --tk option to [/help?cmd=diff| fossil diff], the [/file/src/markdown.md | markdown documentation], and the various CSS scripts, headers, and footers used to implement built-in skins. New resources files are added to the "extra_files" variable in [/file/src/makemake.tcl | makemake.tcl]. |
︙ | ︙ |
Changes to www/mkindex.tcl.
1 2 3 4 5 6 7 8 9 10 11 12 13 | #!/usr/bin/env tclsh # # Run this TCL script to generate a WIKI page that contains a # permuted index of the various documentation files. # # tclsh mkindex.tcl # set doclist { aboutcgi.wiki {How CGI Works In Fossil} aboutdownload.wiki {How The Download Page Works} adding_code.wiki {Adding New Features To Fossil} adding_code.wiki {Hacking Fossil} | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | #!/usr/bin/env tclsh # # Run this TCL script to generate a WIKI page that contains a # permuted index of the various documentation files. # # tclsh mkindex.tcl # set doclist { aboutcgi.wiki {How CGI Works In Fossil} aboutdownload.wiki {How The Download Page Works} adding_code.wiki {Adding New Features To Fossil} adding_code.wiki {Hacking Fossil} alerts.md {Email Alerts And Notifications} antibot.wiki {Defense against Spiders and Bots} backoffice.md {The "Backoffice" mechanism of Fossil} blame.wiki {The Annotate/Blame Algorithm Of Fossil} branching.wiki {Branching, Forking, Merging, and Tagging} bugtheory.wiki {Bug Tracking In Fossil} build.wiki {Compiling and Installing Fossil} changes.wiki {Fossil Changelog} |
︙ | ︙ | |||
33 34 35 36 37 38 39 40 41 42 43 44 45 46 | embeddeddoc.wiki {Embedded Project Documentation} encryptedrepos.wiki {How To Use Encrypted Repositories} env-opts.md {Environment Variables and Global Options} event.wiki {Events} faq.wiki {Frequently Asked Questions} fileformat.wiki {Fossil File Format} fiveminutes.wiki {Up and Running in 5 Minutes as a Single User} foss-cklist.wiki {Checklist For Successful Open-Source Projects} fossil-from-msvc.wiki {Integrating Fossil in the Microsoft Express 2010 IDE} fossil-v-git.wiki {Fossil Versus Git} globs.md {File Name Glob Patterns} hacker-howto.wiki {Hacker How-To} hashpolicy.wiki {Hash Policy: Choosing Between SHA1 and SHA3-256} /help {Lists of Commands and Webpages} | > | 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | embeddeddoc.wiki {Embedded Project Documentation} encryptedrepos.wiki {How To Use Encrypted Repositories} env-opts.md {Environment Variables and Global Options} event.wiki {Events} faq.wiki {Frequently Asked Questions} fileformat.wiki {Fossil File Format} fiveminutes.wiki {Up and Running in 5 Minutes as a Single User} forum.wiki {Fossil Forums} foss-cklist.wiki {Checklist For Successful Open-Source Projects} fossil-from-msvc.wiki {Integrating Fossil in the Microsoft Express 2010 IDE} fossil-v-git.wiki {Fossil Versus Git} globs.md {File Name Glob Patterns} hacker-howto.wiki {Hacker How-To} hashpolicy.wiki {Hash Policy: Choosing Between SHA1 and SHA3-256} /help {Lists of Commands and Webpages} |
︙ | ︙ |
Changes to www/permutedindex.html.
︙ | ︙ | |||
21 22 23 24 25 26 27 | <h2>Permuted Index:</h2> <ul> <li><a href="fiveminutes.wiki">5 Minutes as a Single User — Up and Running in</a></li> <li><a href="fossil-from-msvc.wiki">2010 IDE — Integrating Fossil in the Microsoft Express</a></li> <li><a href="tech_overview.wiki"><b>A Technical Overview Of The Design And Implementation Of Fossil</b></a></li> <li><a href="adding_code.wiki"><b>Adding New Features To Fossil</b></a></li> <li><a href="copyright-release.html">Agreement — Contributor License</a></li> | | | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | <h2>Permuted Index:</h2> <ul> <li><a href="fiveminutes.wiki">5 Minutes as a Single User — Up and Running in</a></li> <li><a href="fossil-from-msvc.wiki">2010 IDE — Integrating Fossil in the Microsoft Express</a></li> <li><a href="tech_overview.wiki"><b>A Technical Overview Of The Design And Implementation Of Fossil</b></a></li> <li><a href="adding_code.wiki"><b>Adding New Features To Fossil</b></a></li> <li><a href="copyright-release.html">Agreement — Contributor License</a></li> <li><a href="alerts.md">Alerts And Notifications — Email</a></li> <li><a href="delta_encoder_algorithm.wiki">Algorithm — Fossil Delta Encoding</a></li> <li><a href="blame.wiki">Algorithm Of Fossil — The Annotate/Blame</a></li> <li><a href="blame.wiki">Annotate/Blame Algorithm Of Fossil — The</a></li> <li><a href="customskin.md">Appearance of Web Pages — Theming: Customizing The</a></li> <li><a href="faq.wiki">Asked Questions — Frequently</a></li> <li><a href="password.wiki">Authentication — Password Management And</a></li> <li><a href="backoffice.md">Backoffice mechanism of Fossil — The</a></li> |
︙ | ︙ | |||
76 77 78 79 80 81 82 | <li><a href="tech_overview.wiki">Design And Implementation Of Fossil — A Technical Overview Of The</a></li> <li><a href="theory1.wiki">Design Of The Fossil DVCS — Thoughts On The</a></li> <li><a href="embeddeddoc.wiki">Documentation — Embedded Project</a></li> <li><a href="contribute.wiki">Documentation To The Fossil Project — Contributing Code or</a></li> <li><a href="aboutdownload.wiki">Download Page Works — How The</a></li> <li><a href="theory1.wiki">DVCS — Thoughts On The Design Of The Fossil</a></li> <li><a href="quotes.wiki">DVCSes in General — Quotes: What People Are Saying About Fossil, Git, and</a></li> | | > > | 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | <li><a href="tech_overview.wiki">Design And Implementation Of Fossil — A Technical Overview Of The</a></li> <li><a href="theory1.wiki">Design Of The Fossil DVCS — Thoughts On The</a></li> <li><a href="embeddeddoc.wiki">Documentation — Embedded Project</a></li> <li><a href="contribute.wiki">Documentation To The Fossil Project — Contributing Code or</a></li> <li><a href="aboutdownload.wiki">Download Page Works — How The</a></li> <li><a href="theory1.wiki">DVCS — Thoughts On The Design Of The Fossil</a></li> <li><a href="quotes.wiki">DVCSes in General — Quotes: What People Are Saying About Fossil, Git, and</a></li> <li><a href="alerts.md"><b>Email Alerts And Notifications</b></a></li> <li><a href="embeddeddoc.wiki"><b>Embedded Project Documentation</b></a></li> <li><a href="delta_encoder_algorithm.wiki">Encoding Algorithm — Fossil Delta</a></li> <li><a href="encryptedrepos.wiki">Encrypted Repositories — How To Use</a></li> <li><a href="env-opts.md"><b>Environment Variables and Global Options</b></a></li> <li><a href="event.wiki"><b>Events</b></a></li> <li><a href="webpage-ex.md">Examples — Webpage</a></li> <li><a href="inout.wiki">Export To And From Git — Import And</a></li> <li><a href="fossil-from-msvc.wiki">Express 2010 IDE — Integrating Fossil in the Microsoft</a></li> <li><a href="adding_code.wiki">Features To Fossil — Adding New</a></li> <li><a href="fileformat.wiki">File Format — Fossil</a></li> <li><a href="globs.md"><b>File Name Glob Patterns</b></a></li> <li><a href="unvers.wiki">Files — Unversioned</a></li> <li><a href="branching.wiki">Forking, Merging, and Tagging — Branching,</a></li> <li><a href="delta_format.wiki">Format — Fossil Delta</a></li> <li><a href="fileformat.wiki">Format — Fossil File</a></li> <li><a href="../../../md_rules">Formatting Rules — Markdown</a></li> <li><a href="../../../wiki_rules">Formatting Rules — Wiki</a></li> <li><a href="forum.wiki">Forums — Fossil</a></li> <li><a href="changes.wiki"><b>Fossil Changelog</b></a></li> <li><a href="concepts.wiki"><b>Fossil Core Concepts</b></a></li> <li><a href="delta_encoder_algorithm.wiki"><b>Fossil Delta Encoding Algorithm</b></a></li> <li><a href="delta_format.wiki"><b>Fossil Delta Format</b></a></li> <li><a href="fileformat.wiki"><b>Fossil File Format</b></a></li> <li><a href="forum.wiki"><b>Fossil Forums</b></a></li> <li><a href="quickstart.wiki"><b>Fossil Quick Start Guide</b></a></li> <li><a href="selfcheck.wiki"><b>Fossil Repository Integrity Self Checks</b></a></li> <li><a href="selfhost.wiki"><b>Fossil Self Hosting Repositories</b></a></li> <li><a href="settings.wiki"><b>Fossil Settings</b></a></li> <li><a href="hints.wiki"><b>Fossil Tips And Usage Hints</b></a></li> <li><a href="fossil-v-git.wiki"><b>Fossil Versus Git</b></a></li> <li><a href="quotes.wiki">Fossil, Git, and DVCSes in General — Quotes: What People Are Saying About</a></li> |
︙ | ︙ | |||
149 150 151 152 153 154 155 | <li><a href="branching.wiki">Merging, and Tagging — Branching, Forking,</a></li> <li><a href="fossil-from-msvc.wiki">Microsoft Express 2010 IDE — Integrating Fossil in the</a></li> <li><a href="fiveminutes.wiki">Minutes as a Single User — Up and Running in 5</a></li> <li><a href="globs.md">Name Glob Patterns — File</a></li> <li><a href="checkin_names.wiki">Names — Check-in And Version</a></li> <li><a href="adding_code.wiki">New Features To Fossil — Adding</a></li> <li><a href="newrepo.wiki">New Fossil Repository — How To Create A</a></li> | | | 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 | <li><a href="branching.wiki">Merging, and Tagging — Branching, Forking,</a></li> <li><a href="fossil-from-msvc.wiki">Microsoft Express 2010 IDE — Integrating Fossil in the</a></li> <li><a href="fiveminutes.wiki">Minutes as a Single User — Up and Running in 5</a></li> <li><a href="globs.md">Name Glob Patterns — File</a></li> <li><a href="checkin_names.wiki">Names — Check-in And Version</a></li> <li><a href="adding_code.wiki">New Features To Fossil — Adding</a></li> <li><a href="newrepo.wiki">New Fossil Repository — How To Create A</a></li> <li><a href="alerts.md">Notifications — Email Alerts And</a></li> <li><a href="foss-cklist.wiki">Open-Source Projects — Checklist For Successful</a></li> <li><a href="pop.wiki">Operation — Principles Of</a></li> <li><a href="env-opts.md">Options — Environment Variables and Global</a></li> <li><a href="tech_overview.wiki">Overview Of The Design And Implementation Of Fossil — A Technical</a></li> <li><a href="index.wiki">Page — Home</a></li> <li><a href="aboutdownload.wiki">Page Works — How The Download</a></li> <li><a href="customskin.md">Pages — Theming: Customizing The Appearance of Web</a></li> |
︙ | ︙ |