Index: BUILD.txt ================================================================== --- BUILD.txt +++ BUILD.txt @@ -22,11 +22,11 @@ cd win; nmake /f Makefile.msc If you have trouble, or you want to do something fancy, just look at Makefile.classic. There are 6 configuration options that are all well -commented. Instead of editing the Makefile.classic, consider copying +commented. Instead of editing the Makefile.classic, consider copying Makefile.classic to an alternative name such as "GNUMakefile", "BSDMakefile", or "makefile" and editing the copy. BUILDING OUTSIDE THE SOURCE TREE @@ -61,11 +61,11 @@ Do not edit src/main.mk directly. Update src/makemake.tcl and then rerun it. * The *.h header files are automatically generated using a program called "makeheaders". Source code to the makeheaders program is - found in src/makeheaders.c. Documentation is found in + found in src/makeheaders.c. Documentation is found in src/makeheaders.html. * Most *.c source files are preprocessed using a program called "translate". The sources to translate are found in src/translate.c. A header comment in src/translate.c explains in detail what it does. Index: COPYRIGHT-BSD2.txt ================================================================== --- COPYRIGHT-BSD2.txt +++ COPYRIGHT-BSD2.txt @@ -1,31 +1,31 @@ Copyright 2007 D. Richard Hipp. All rights reserved. -Redistribution and use in source and binary forms, with or -without modification, are permitted provided that the +Redistribution and use in source and binary forms, with or +without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above - copyright notice, this list of conditions and the + copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. -THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS -OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -The views and conclusions contained in the software and documentation -are those of the authors and contributors and should not be interpreted +The views and conclusions contained in the software and documentation +are those of the authors and contributors and should not be interpreted as representing official policies, either expressed or implied, of anybody else. Index: Makefile.Cygwin.in ================================================================== --- Makefile.Cygwin.in +++ Makefile.Cygwin.in @@ -36,13 +36,16 @@ # care about testing the end result, this can be blank. # TCLSH = tclsh LIB = @LDFLAGS@ @EXTRA_LDFLAGS@ @LIBS@ -TCC += @EXTRA_CFLAGS@ @CPPFLAGS@ @CFLAGS@ -DHAVE_AUTOCONFIG_H +TCC += @EXTRA_CFLAGS@ @CPPFLAGS@ @CFLAGS@ -DHAVE_AUTOCONFIG_H -DFOSSIL_OMIT_LOAD_AVERAGE INSTALLDIR =$(DESTDIR)@prefix@/bin USE_SYSTEM_SQLITE = @USE_SYSTEM_SQLITE@ +FOSSIL_ENABLE_TCL = @FOSSIL_ENABLE_TCL@ +FOSSIL_ENABLE_TCL_STUBS = @FOSSIL_ENABLE_TCL_STUBS@ +FOSSIL_ENABLE_TCL_PRIVATE_STUBS = @FOSSIL_ENABLE_TCL_PRIVATE_STUBS@ SQLITE_CFLAGS += -DSQLITE_WIN32_NO_ANSI SQLITE_CFLAGS += -DSQLITE_WIN32_MAX_PATH_BYTES=4096 SQLITE_CFLAGS += -DSQLITE_MAX_MMAP_SIZE=0x7fff0000 include $(SRCDIR)/main.mk Index: Makefile.in ================================================================== --- Makefile.in +++ Makefile.in @@ -40,10 +40,13 @@ LIB = @LDFLAGS@ @EXTRA_LDFLAGS@ @LIBS@ TCC += @EXTRA_CFLAGS@ @CPPFLAGS@ @CFLAGS@ -DHAVE_AUTOCONFIG_H INSTALLDIR = $(DESTDIR)@prefix@/bin USE_SYSTEM_SQLITE = @USE_SYSTEM_SQLITE@ +FOSSIL_ENABLE_TCL = @FOSSIL_ENABLE_TCL@ +FOSSIL_ENABLE_TCL_STUBS = @FOSSIL_ENABLE_TCL_STUBS@ +FOSSIL_ENABLE_TCL_PRIVATE_STUBS = @FOSSIL_ENABLE_TCL_PRIVATE_STUBS@ include $(SRCDIR)/main.mk distclean: clean rm -f autoconfig.h config.log Makefile Index: auto.def ================================================================== --- auto.def +++ auto.def @@ -88,10 +88,21 @@ if {[opt-bool static]} { # XXX: This will not work on all systems. define-append EXTRA_LDFLAGS -static } + +# Check for zlib, using the given location if specified +set zlibpath [opt-val with-zlib] +if {$zlibpath ne ""} { + cc-with [list -cflags "-I$zlibpath -L$zlibpath"] + define-append EXTRA_CFLAGS -I$zlibpath + define-append EXTRA_LDFLAGS -L$zlibpath +} +if {![cc-check-includes zlib.h] || ![cc-check-function-in-lib inflateEnd z]} { + user-error "zlib not found please install it or specify the location with --with-zlib" +} set tclpath [opt-val with-tcl] if {$tclpath ne ""} { set tclprivatestubs [opt-bool with-tcl-private-stubs] # Note parse-tclconfig-sh is in autosetup/local.tcl @@ -216,21 +227,10 @@ } else { user-error "OpenSSL not found. Consider --with-openssl=none to disable HTTPS support" } } -# Check for zlib, using the given location if specified -set zlibpath [opt-val with-zlib] -if {$zlibpath ne ""} { - cc-with [list -cflags "-I$zlibpath -L$zlibpath"] - define-append EXTRA_CFLAGS -I$zlibpath - define-append EXTRA_LDFLAGS -L$zlibpath -} -if {![cc-check-includes zlib.h] || ![cc-check-function-in-lib inflateEnd z]} { - user-error "zlib not found please install it or specify the location with --with-zlib" -} - if {[opt-bool lineedit]} { # Need readline-compatible line editing cc-with {-includes stdio.h} { if {[cc-check-includes readline/readline.h] && [cc-check-function-in-lib readline readline]} { msg-result "Using readline for line editing" @@ -249,15 +249,10 @@ define-append LIBS -lwsock32 } } cc-check-function-in-lib iconv iconv -# Check for getloadavg(), and if it doesn't exist, define FOSSIL_OMIT_LOAD_AVERAGE -if {![cc-check-functions getloadavg]} { - define FOSSIL_OMIT_LOAD_AVERAGE 1 -} - # Check for getpassphrase() for Solaris 10 where getpass() truncates to 10 chars if {![cc-check-functions getpassphrase]} { # Haiku needs this cc-check-function-in-lib getpass bsd } Index: src/add.c ================================================================== --- src/add.c +++ src/add.c @@ -25,11 +25,11 @@ #include "cygsup.h" /* ** This routine returns the names of files in a working checkout that ** are created by Fossil itself, and hence should not be added, deleted, -** or merge, and should be omitted from "clean" and "extras" lists. +** or merge, and should be omitted from "clean" and "extra" lists. ** ** Return the N-th name. The first name has N==0. When all names have ** been used, return 0. */ const char *fossil_reserved_name(int N, int omitRepo){ @@ -222,23 +222,18 @@ ** for files to be excluded. Example: '*.o,*.obj,*.exe' If the --ignore ** option does not appear on the command line then the "ignore-glob" setting ** is used. If the --clean option does not appear on the command line then ** the "clean-glob" setting is used. ** -** If files are attempted to be added explicitly on the command line which -** match "ignore-glob", a confirmation is asked first. This can be prevented -** using the -f|--force option. -** ** The --case-sensitive option determines whether or not filenames should ** be treated case sensitive or not. If the option is not given, the default ** depends on the global setting, or the operating system default, if not set. ** ** Options: ** ** --case-sensitive override case-sensitive setting ** --dotfiles include files beginning with a dot (".") -** -f|--force Add files without prompting ** --ignore ignore files matching patterns from the ** comma separated list of glob patterns. ** --clean also ignore files matching patterns from ** the comma separated list of glob patterns. ** @@ -250,15 +245,13 @@ int nRoot; /* Full path characters in g.zLocalRoot */ const char *zCleanFlag; /* The --clean option or clean-glob setting */ const char *zIgnoreFlag; /* The --ignore option or ignore-glob setting */ Glob *pIgnore, *pClean; /* Ignore everything matching the glob patterns */ unsigned scanFlags = 0; /* Flags passed to vfile_scan() */ - int forceFlag; zCleanFlag = find_option("clean",0,1); zIgnoreFlag = find_option("ignore",0,1); - forceFlag = find_option("force","f",0)!=0; if( find_option("dotfiles",0,0)!=0 ) scanFlags |= SCAN_ALL; capture_case_sensitive_option(); db_must_be_within_tree(); if( zCleanFlag==0 ){ zCleanFlag = db_get("clean-glob", 0); @@ -294,25 +287,10 @@ fossil_warning("not found: %s", zName); }else if( file_access(zName, R_OK) ){ fossil_fatal("cannot open %s", zName); }else{ char *zTreeName = &zName[nRoot]; - if( !forceFlag && glob_match(pIgnore, zTreeName) ){ - Blob ans; - char cReply; - char *prompt = mprintf("file \"%s\" matches \"ignore-glob\". " - "Add it (a=all/y/N)? ", zTreeName); - prompt_user(prompt, &ans); - cReply = blob_str(&ans)[0]; - blob_reset(&ans); - if( cReply=='a' || cReply=='A' ){ - forceFlag = 1; - }else if( cReply!='y' && cReply!='Y' ){ - blob_reset(&fullName); - continue; - } - } db_multi_exec( "INSERT OR IGNORE INTO sfile(x) VALUES(%Q)", zTreeName ); } @@ -461,11 +439,11 @@ ** ** Do all necessary "add" and "rm" commands to synchronize the repository ** with the content of the working checkout: ** ** * All files in the checkout but not in the repository (that is, -** all files displayed using the "extras" command) are added as +** all files displayed using the "extra" command) are added as ** if by the "add" command. ** ** * All files in the repository but missing from the checkout (that is, ** all files that show as MISSING with the "status" command) are ** removed as if by the "rm" command. @@ -692,13 +670,5 @@ mv_one_file(vid, zFrom, zTo); } db_finalize(&q); db_end_transaction(0); } - -/* -** Function for stash_apply to be able to restore a file and indicate -** newly ADDED state. -*/ -int stash_add_files_in_sfile(int vid){ - return add_files_in_sfile(vid); -} Index: src/allrepo.c ================================================================== --- src/allrepo.c +++ src/allrepo.c @@ -65,22 +65,16 @@ }else{ blob_appendf(pExtra, " --%s \"\"", zArg); } } } -static void collect_argv(Blob *pExtra, int iStart){ - int i; - for(i=iStart; i%S", + zTargetType = mprintf("Ticket %S", g.zTop, zTkt, zTkt); } if( zFrom==0 ) zFrom = mprintf("%s/home", g.zTop); if( P("cancel") ){ cgi_redirect(zFrom); @@ -309,11 +309,11 @@ if( n>0 ){ blob_appendf(&manifest, "C %#F\n", n, zComment); } zDate = date_in_standard_format("now"); blob_appendf(&manifest, "D %s\n", zDate); - blob_appendf(&manifest, "U %F\n", login_name()); + blob_appendf(&manifest, "U %F\n", g.zLogin ? g.zLogin : "nobody"); md5sum_blob(&manifest, &cksum); blob_appendf(&manifest, "Z %b\n", &cksum); attach_put(&manifest, rid, needModerator); assert( blob_is_reset(&manifest) ); db_end_transaction(0); @@ -427,11 +427,11 @@ zFile += n; if( zFile[0]==0 ) zFile = "unknown"; blob_appendf(&manifest, "A %F %F\n", zFile, zTarget); zDate = date_in_standard_format("now"); blob_appendf(&manifest, "D %s\n", zDate); - blob_appendf(&manifest, "U %F\n", login_name()); + blob_appendf(&manifest, "U %F\n", g.zLogin ? g.zLogin : "nobody"); md5sum_blob(&manifest, &cksum); blob_appendf(&manifest, "Z %b\n", &cksum); rid = content_put(&manifest); manifest_crosslink(rid, &manifest, MC_NONE); db_end_transaction(0); @@ -463,11 +463,11 @@ if( strcmp(zModAction,"approve")==0 ){ moderation_approve(rid); } } style_header("Attachment Details"); - style_submenu_element("Raw", "Raw", "%R/artifact/%s", zUuid); + style_submenu_element("Raw", "Raw", "%R/artifact/%S", zUuid); @
Overview
@

@ @ @ @ } @ @
Artifact ID:%z(href("%R/artifact/%s",zUuid))%s(zUuid) @@ -531,12 +531,12 @@ @
       @ %h(z)
       @ 
} }else if( strncmp(zMime, "image/", 6)==0 ){ - @ - style_submenu_element("Image", "Image", "%R/raw/%s?m=%s", zSrc, zMime); + @ + style_submenu_element("Image", "Image", "%R/raw/%S?m=%s", zSrc, zMime); }else{ int sz = db_int(0, "SELECT size FROM blob WHERE rid=%d", ridSrc); @ (file is %d(sz) bytes of binary data) } @ Index: src/bag.c ================================================================== --- src/bag.c +++ src/bag.c @@ -75,11 +75,11 @@ /* ** Change the size of the hash table on a bag so that ** it contains N slots ** ** Completely reconstruct the hash table from scratch. Deleted -** entries (indicated by a -1) are removed. When finished, it +** entries (indicated by a -1) are removed. When finished, it ** should be the case that p->cnt==p->used. */ static void bag_resize(Bag *p, int newSize){ int i; Bag old; Index: src/bisect.c ================================================================== --- src/bisect.c +++ src/bisect.c @@ -370,11 +370,11 @@ g.argv[2] = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", pMid->rid); g.argc = 3; g.fNoSync = 1; update_cmd(); } - + if( strncmp(zDisplay,"chart",m)==0 ){ bisect_chart(1); }else if( strncmp(zDisplay, "log", m)==0 ){ bisect_chart(0); }else if( strncmp(zDisplay, "status", m)==0 ){ Index: src/blob.c ================================================================== --- src/blob.c +++ src/blob.c @@ -224,19 +224,10 @@ */ void blob_set(Blob *pBlob, const char *zStr){ blob_init(pBlob, zStr, -1); } -/* -** Initialize a blob to a nul-terminated string obtained from fossil_malloc(). -** The blob will take responsibility for freeing the string. -*/ -void blob_set_dynamic(Blob *pBlob, char *zStr){ - blob_init(pBlob, zStr, -1); - pBlob->xRealloc = blobReallocMalloc; -} - /* ** Initialize a blob to an empty string. */ void blob_zero(Blob *pBlob){ static const char zEmpty[] = ""; @@ -786,17 +777,48 @@ return nWrote; } #endif fwrite(blob_buffer(pBlob), 1, nWrote, stdout); }else{ - file_mkfolder(zFilename, 1); - out = fossil_fopen(zFilename, "wb"); + int i, nName; + char *zName, zBuf[1000]; + + nName = strlen(zFilename); + if( nName>=sizeof(zBuf) ){ + zName = mprintf("%s", zFilename); + }else{ + zName = zBuf; + memcpy(zName, zFilename, nName+1); + } + nName = file_simplify_name(zName, nName, 0); + for(i=1; i } db_finalize(&q); + @ style_footer(); } /* ** This routine is called while for each check-in that is rendered by @@ -416,7 +423,13 @@ " ORDER BY event.mtime DESC", timeline_query_for_www(), TAG_BRANCH ); www_print_timeline(&q, 0, 0, 0, brtimeline_extra); db_finalize(&q); + @ style_footer(); } Index: src/browse.c ================================================================== --- src/browse.c +++ src/browse.c @@ -85,11 +85,11 @@ for(i=0; zPath[i]; i=j){ for(j=i; zPath[j] && zPath[j]!='/'; j++){} if( zPath[j] && g.perm.Hyperlink ){ if( zCI ){ - char *zLink = href("%R/%s?name=%#T%s&ci=%s", zURI, j, zPath, zREx, zCI); + char *zLink = href("%R/%s?ci=%S&name=%#T%s", zURI, zCI, j, zPath,zREx); blob_appendf(pOut, "%s%z%#h", zSep, zLink, j-i, &zPath[i]); }else{ char *zLink = href("%R/%s?name=%#T%s", zURI, j, zPath, zREx); blob_appendf(pOut, "%s%z%#h", @@ -179,15 +179,18 @@ if( linkTip ){ style_submenu_element("Tip", "Tip", "%s", url_render(&sURI, "ci", "tip", 0, 0)); } if( zCI ){ - @

Files of check-in [%z(href("vinfo?name=%s",zUuid))%.10s(zUuid)] + char zShort[20]; + memcpy(zShort, zUuid, 10); + zShort[10] = 0; + @

Files of check-in [%z(href("vinfo?name=%T",zUuid))%s(zShort)] @ %s(blob_str(&dirname))

- zSubdirLink = mprintf("%R/dir?ci=%s&name=%T", zUuid, zPrefix); + zSubdirLink = mprintf("%R/dir?ci=%S&name=%T", zUuid, zPrefix); if( nD==0 ){ - style_submenu_element("File Ages", "File Ages", "%R/fileage?name=%s", + style_submenu_element("File Ages", "File Ages", "%R/fileage?name=%S", zUuid); } }else{ @

The union of all files from all check-ins @ %s(blob_str(&dirname))

@@ -415,11 +418,10 @@ FileTreeNode *p; /* One line of the tree */ FileTree sTree; /* The complete tree of files */ HQuery sURI; /* Hyperlink */ int startExpanded; /* True to start out with the tree expanded */ int showDirOnly; /* Show directories only. Omit files */ - int nDir = 0; /* Number of directories. Used for ID attributes */ char *zProjectName = db_get("project-name", 0); if( strcmp(PD("type",""),"flat")==0 ){ page_dir(); return; } memset(&sTree, 0, sizeof(sTree)); login_check_credentials(); @@ -487,11 +489,11 @@ } if( zCI ){ style_submenu_element("All", "All", "%s", url_render(&sURI, "ci", 0, 0, 0)); if( nD==0 && !showDirOnly ){ - style_submenu_element("File Ages", "File Ages", "%R/fileage?name=%s", + style_submenu_element("File Ages", "File Ages", "%R/fileage?name=%S", zUuid); } } if( linkTrunk ){ style_submenu_element("Trunk", "Trunk", "%s", @@ -514,11 +516,13 @@ db_multi_exec( "CREATE TEMP TABLE filelist(" " x TEXT PRIMARY KEY COLLATE nocase," " uuid TEXT" - ") WITHOUT ROWID;" + ")%s;", + /* Can be removed as soon as SQLite 3.8.2 is sufficiently wide-spread */ + sqlite3_libversion_number()>=3008002 ? " WITHOUT ROWID" : "" ); db_prepare(&ins, "INSERT OR IGNORE INTO filelist VALUES(:f,:u)"); manifest_file_rewind(pM); while( (pFile = manifest_file_next(pM,0))!=0 ){ if( nD>0 @@ -571,11 +575,11 @@ if( zCI ){ @

%d(nFile) %s(zObjType) of check-in if( sqlite3_strnicmp(zCI, zUuid, (int)strlen(zCI))!=0 ){ @ "%h(zCI)" } - @ [%z(href("vinfo?name=%s",zUuid))%S(zUuid)] %s(blob_str(&dirname))

+ @ [%z(href("vinfo?name=%T",zUuid))%S(zUuid)] %s(blob_str(&dirname)) }else{ int n = db_int(0, "SELECT count(*) FROM plink"); @

%d(nFile) %s(zObjType) from all %d(n) check-ins @ %s(blob_str(&dirname))

} @@ -592,37 +596,37 @@ ** The
  • element for directories also contains a sublist
      ** for the contents of that directory. */ @
        if( nD ){ - @
      • + @
      • }else{ - @
      • + @
      • } @ %z(href("%s",url_render(&sURI,"name",0,0,0)))%h(zProjectName) @
          - for(p=sTree.pFirst, nDir=0; p; p=p->pNext){ - const char *zLastClass = p->isLast ? " last" : ""; + for(p=sTree.pFirst; p; p=p->pNext){ if( p->isDir ){ - const char *zSubdirClass = p->nFullName==nD-1 ? " subdir" : ""; - @
        • + if( p->nFullName==nD-1 ){ + @
        • + }else{ + @
        • + } @ %z(href("%s",url_render(&sURI,"name",p->zFullName,0,0)))%h(p->zName) if( startExpanded || p->nFullName<=nD ){ - @
            + @
              }else{ - @ @
      @ style_footer(); @@ -729,22 +699,20 @@ /* ** Look at all file containing in the version "vid". Construct a ** temporary table named "fileage" that contains the file-id for each ** files, the pathname, the check-in where the file was added, and the -** mtime on that checkin. If zGlob and *zGlob then only files matching -** the given glob are computed. +** mtime on that checkin. */ -int compute_fileage(int vid, char const * zGlob){ +int compute_fileage(int vid){ Manifest *pManifest; ManifestFile *pFile; int nFile = 0; double vmtime; Stmt ins; Stmt q1, q2, q3; Stmt upd; - if(zGlob && !*zGlob) zGlob = NULL; db_multi_exec( /*"DROP TABLE IF EXISTS temp.fileage;"*/ "CREATE TEMP TABLE fileage(" " fid INTEGER," " mid INTEGER," @@ -759,11 +727,10 @@ db_prepare(&ins, "INSERT INTO temp.fileage(fid, pathname)" " SELECT rid, :path FROM blob WHERE uuid=:uuid" ); while( (pFile = manifest_file_next(pManifest, 0))!=0 ){ - if(zGlob && !strglob(zGlob, pFile->zName)) continue; db_bind_text(&ins, ":uuid", pFile->zUuid); db_bind_text(&ins, ":path", pFile->zName); db_step(&ins); db_reset(&ins); nFile++; @@ -807,22 +774,20 @@ /* ** WEBPAGE: fileage ** ** Parameters: -** name=VERSION Selects the checkin version (default=tip). -** glob=STRING Only shows files matching this glob pattern -** (e.g. *.c or *.txt). +** name=VERSION */ void fileage_page(void){ int rid; const char *zName; char *zBaseTime; - char const * zGlob; Stmt q; double baseTime; int lastMid = -1; + login_check_credentials(); if( !g.perm.Read ){ login_needed(); return; } zName = P("name"); if( zName==0 ) zName = "tip"; rid = symbolic_name_to_rid(zName, "ci"); @@ -829,12 +794,11 @@ if( rid==0 ){ fossil_fatal("not a valid check-in: %s", zName); } style_submenu_element("Tree-View", "Tree-View", "%R/tree?ci=%T", zName); style_header("File Ages", zName); - zGlob = P("glob"); - compute_fileage(rid,zGlob); + compute_fileage(rid); baseTime = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid); zBaseTime = db_text("","SELECT datetime(%.20g%s)", baseTime, timeline_utc()); @

      File Ages For Check-in @ %z(href("%R/info?name=%T",zName))%h(zName)

      @ @@ -872,14 +836,14 @@ zAge[0] = 0; } @
  • %s(zAge) @ - @ %z(href("%R/artifact/%s?ln", zFUuid))%h(db_column_text(&q, 3)) + @ %z(href("%R/artifact/%S?ln", zFUuid))%h(db_column_text(&q, 3)) @

    db_finalize(&q); style_footer(); } Index: src/captcha.c ================================================================== --- src/captcha.c +++ src/captcha.c @@ -92,11 +92,11 @@ z[k++] = ' '; } z[k++] = '\n'; } z[k] = 0; - return z; + return z; } #endif /* CAPTCHA==1 */ #if CAPTCHA==2 @@ -148,11 +148,11 @@ "|__ |", " / / ", " /_/ ", /* 8 */ - " ___ ", + " ___ ", "( _ )", "/ _ \\", "\\___/", /* 9 */ @@ -218,11 +218,11 @@ } } z[k++] = '\n'; } z[k] = 0; - return z; + return z; } #endif /* CAPTCHA==2 */ #if CAPTCHA==3 static const char *const azFont3[] = { @@ -231,123 +231,123 @@ " / _ \\ ", "| | | |", "| | | |", "| |_| |", " \\___/ ", - + /* 1 */ " __ ", "/_ |", " | |", " | |", " | |", " |_|", - + /* 2 */ " ___ ", "|__ \\ ", " ) |", " / / ", " / /_ ", "|____|", - + /* 3 */ " ____ ", "|___ \\ ", " __) |", " |__ < ", " ___) |", "|____/ ", - + /* 4 */ " _ _ ", "| || | ", "| || |_ ", "|__ _|", " | | ", " |_| ", - + /* 5 */ " _____ ", "| ____|", "| |__ ", "|___ \\ ", " ___) |", "|____/ ", - + /* 6 */ " __ ", " / / ", " / /_ ", "| '_ \\ ", "| (_) |", " \\___/ ", - + /* 7 */ " ______ ", "|____ |", " / / ", " / / ", " / / ", " /_/ ", - + /* 8 */ " ___ ", " / _ \\ ", "| (_) |", " > _ < ", "| (_) |", " \\___/ ", - + /* 9 */ " ___ ", " / _ \\ ", "| (_) |", " \\__, |", " / / ", " /_/ ", - + /* A */ " ", " /\\ ", " / \\ ", " / /\\ \\ ", " / ____ \\ ", "/_/ \\_\\", - + /* B */ " ____ ", "| _ \\ ", "| |_) |", "| _ < ", "| |_) |", "|____/ ", - + /* C */ " _____ ", " / ____|", "| | ", "| | ", "| |____ ", " \\_____|", - + /* D */ " _____ ", "| __ \\ ", "| | | |", "| | | |", "| |__| |", "|_____/ ", - + /* E */ " ______ ", "| ____|", "| |__ ", "| __| ", "| |____ ", "|______|", - + /* F */ " ______ ", "| ____|", "| |__ ", "| __| ", @@ -408,11 +408,11 @@ } } z[k++] = '\n'; } z[k] = 0; - return z; + return z; } #endif /* CAPTCHA==3 */ /* ** COMMAND: test-captcha @@ -478,15 +478,16 @@ ** Return true if a CAPTCHA is required for editing wiki or tickets or for ** adding attachments. ** ** A CAPTCHA is required in those cases if the user is not logged in (if they ** are user "nobody") and if the "require-captcha" setting is true. The -** "require-captcha" setting is controlled on the Admin/Access page. It +** "require-captcha" setting is controlled on the Admin/Access page. It ** defaults to true. */ int captcha_needed(void){ - return login_is_nobody() && db_get_boolean("require-captcha", 1); + if( g.zLogin!=0 ) return 0; + return db_get_boolean("require-captcha", 1); } /* ** If a captcha is required but the correct captcha code is not supplied ** in the query parameters, then return false (0). Index: src/cgi.c ================================================================== --- src/cgi.c +++ src/cgi.c @@ -266,11 +266,11 @@ zTok = strtok_r(0, ",\"",&zPos)){} fossil_free(zBuf); if(zTok) return 1; } } - + return 0; } #endif /* @@ -497,11 +497,11 @@ ** must be made of zValue. */ void cgi_setenv(const char *zName, const char *zValue){ cgi_set_parameter_nocopy(zName, mprintf("%s",zValue), 0); } - + /* ** Add a list of query parameters or cookies to the parameter set. ** ** Each parameter is of the form NAME=VALUE. Both the NAME and the @@ -615,11 +615,11 @@ break; } } *pz = &z[i]; get_line_from_string(pz, pLen); - return z; + return z; } /* ** Tokenize a line of text into as many as nArg tokens. Make ** azArg[] point to the start of each token. @@ -722,11 +722,11 @@ cgi_set_parameter_nocopy(mprintf("%s:mimetype",zName), z, 1); } } } } - } + } } #ifdef FOSSIL_ENABLE_JSON /* @@ -903,11 +903,11 @@ z = (char*)P("HTTP_COOKIE"); if( z ){ z = mprintf("%s",z); add_param_list(z, ';'); } - + z = (char*)P("QUERY_STRING"); if( z ){ z = mprintf("%s",z); add_param_list(z, '&'); } @@ -919,11 +919,11 @@ len = atoi(PD("CONTENT_LENGTH", "0")); g.zContentType = zType = P("CONTENT_TYPE"); blob_zero(&g.cgiIn); if( len>0 && zType ){ - if( fossil_strcmp(zType,"application/x-www-form-urlencoded")==0 + if( fossil_strcmp(zType,"application/x-www-form-urlencoded")==0 || strncmp(zType,"multipart/form-data",19)==0 ){ z = fossil_malloc( len+1 ); len = fread(z, 1, len, g.httpIn); z[len] = 0; cgi_trace(z); @@ -949,11 +949,11 @@ /* FIXMEs: - See if fossil really needs g.cgiIn to be set for this purpose (i don't think it does). If it does then fill g.cgiIn and refactor to parse the JSON from there. - + - After parsing POST JSON, copy the "first layer" of keys/values to cgi_setenv(), honoring the upper-case distinction used in add_param_list(). However... - If we do that then we might get a disconnect in precedence of @@ -1225,11 +1225,11 @@ ** loaded into g.zIpAddr. */ static const char *cgi_accept_forwarded_for(const char *z){ int i; if( fossil_strcmp(g.zIpAddr, "127.0.0.1")!=0 ) return 0; - + i = strlen(z)-1; while( i>=0 && z[i]!=',' && !fossil_isspace(z[i]) ) i--; return &z[++i]; } @@ -1297,20 +1297,20 @@ for(i=0; zToken[i] && zToken[i]!='?'; i++){} if( zToken[i] ) zToken[i++] = 0; cgi_setenv("PATH_INFO", zToken); cgi_setenv("QUERY_STRING", &zToken[i]); if( zIpAddr==0 && - getpeername(fileno(g.httpIn), (struct sockaddr*)&remoteName, + getpeername(fileno(g.httpIn), (struct sockaddr*)&remoteName, &size)>=0 ){ zIpAddr = inet_ntoa(remoteName.sin_addr); } - if( zIpAddr ){ + if( zIpAddr ){ cgi_setenv("REMOTE_ADDR", zIpAddr); g.zIpAddr = mprintf("%s", zIpAddr); } - + /* Get all the optional fields that follow the first line. */ while( fgets(zLine,sizeof(zLine),g.httpIn) ){ char *zFieldName; char *zVal; @@ -1374,11 +1374,11 @@ const char *zType = 0; int i, content_length = 0; char zLine[2000]; /* A single line of input. */ if( zIpAddr ){ - if( nCycles==0 ){ + if( nCycles==0 ){ cgi_setenv("REMOTE_ADDR", zIpAddr); g.zIpAddr = mprintf("%s", zIpAddr); } }else{ fossil_panic("missing SSH IP address"); @@ -1440,11 +1440,11 @@ if( nCycles==0 ){ cgi_setenv("PATH_INFO", zToken); }else{ cgi_replace_parameter("PATH_INFO", mprintf("%s",zToken)); } - + /* Get all the optional fields that follow the first line. */ while( fgets(zLine,sizeof(zLine),g.httpIn) ){ char *zFieldName; char *zVal; @@ -1621,11 +1621,11 @@ cgi_init(); } #if INTERFACE -/* +/* ** Bitmap values for the flags parameter to cgi_http_server(). */ #define HTTP_SERVER_LOCALHOST 0x0001 /* Bind to 127.0.0.1 only */ #define HTTP_SERVER_SCGI 0x0002 /* SCGI instead of HTTP */ @@ -1706,13 +1706,15 @@ " port in the range %d..%d", mnPort, mxPort); } } if( iPort>mxPort ) return 1; listen(listener,10); - fossil_print("Listening for %s requests on TCP port %d\n", - (flags & HTTP_SERVER_SCGI)!=0?"SCGI":"HTTP", iPort); - fflush(stdout); + if( iPort>mnPort ){ + fossil_print("Listening for %s requests on TCP port %d\n", + (flags & HTTP_SERVER_SCGI)!=0?"SCGI":"HTTP", iPort); + fflush(stdout); + } if( zBrowser ){ zBrowser = mprintf(zBrowser, iPort); #if defined(__CYGWIN__) /* On Cygwin, we can do better than "echo" */ if( memcmp(zBrowser, "echo ", 5)==0 ){ @@ -1767,11 +1769,11 @@ /* Bury dead children */ while( waitpid(0, 0, WNOHANG)>0 ){ nchildren--; } } - /* NOT REACHED */ + /* NOT REACHED */ fossil_exit(1); #endif /* NOT REACHED */ return 0; } @@ -1855,11 +1857,11 @@ p->tm_mon %= 12; } isLeapYr = p->tm_year%4==0 && (p->tm_year%100!=0 || (p->tm_year+300)%400==0); p->tm_yday = priorDays[p->tm_mon] + p->tm_mday - 1; if( isLeapYr && p->tm_mon>1 ) p->tm_yday++; - nDay = (p->tm_year-70)*365 + (p->tm_year-69)/4 -p->tm_year/100 + + nDay = (p->tm_year-70)*365 + (p->tm_year-69)/4 -p->tm_year/100 + (p->tm_year+300)/400 + p->tm_yday; t = ((nDay*24 + p->tm_hour)*60 + p->tm_min)*60 + p->tm_sec; return t; } Index: src/checkin.c ================================================================== --- src/checkin.c +++ src/checkin.c @@ -179,11 +179,11 @@ ** --sha1sum Verify file status using SHA1 hashing rather ** than relying on file mtimes. ** --header Identify the repository if there are changes ** -v|--verbose Say "(none)" if there are no changes ** -** See also: extras, ls, status +** See also: extra, ls, status */ void changes_cmd(void){ Blob report; int vid; int useSha1sum = find_option("sha1sum", 0, 0)!=0; @@ -223,11 +223,11 @@ ** --rel-paths Display pathnames relative to the current working ** directory. ** --sha1sum Verify file status using SHA1 hashing rather ** than relying on file mtimes. ** -** See also: changes, extras, ls +** See also: changes, extra, ls */ void status_cmd(void){ int vid; db_must_be_within_tree(); /* 012345678901234 */ @@ -255,11 +255,11 @@ ** ** Options: ** --age Show when each file was committed ** -v|--verbose Provide extra information about each file. ** -** See also: changes, extras, status +** See also: changes, extra, status */ void ls_cmd(void){ int vid; Stmt q; int verboseFlag; @@ -433,22 +433,20 @@ ** ** Options: ** --abs-paths Display absolute pathnames. ** --case-sensitive override case-sensitive setting ** --dotfiles include files beginning with a dot (".") -** --header Identify the repository if there are extras ** --ignore ignore files matching patterns from the argument ** --rel-paths Display pathnames relative to the current working ** directory. ** ** See also: changes, clean, status */ -void extras_cmd(void){ +void extra_cmd(void){ Stmt q; const char *zIgnoreFlag = find_option("ignore",0,1); unsigned scanFlags = find_option("dotfiles",0,0)!=0 ? SCAN_ALL : 0; - int showHdr = find_option("header",0,0)!=0; int cwdRelative = 0; Glob *pIgnore; Blob rewrittenPathname; const char *zPathname, *zDisplayName; @@ -479,15 +477,10 @@ zDisplayName = blob_str(&rewrittenPathname); if( zDisplayName[0]=='.' && zDisplayName[1]=='/' ){ zDisplayName += 2; /* no unnecessary ./ prefix */ } } - if( showHdr ){ - showHdr = 0; - fossil_print("Extras for %s at %s:\n", db_get("project-name","???"), - g.zLocalRoot); - } fossil_print("%s\n", zDisplayName); } blob_reset(&rewrittenPathname); db_finalize(&q); } @@ -543,11 +536,11 @@ ** list of glob patterns. ** -n|--dry-run If given, display instead of run actions. ** --temp Remove only Fossil-generated temporary files. ** -v|--verbose Show all files as they are removed. ** -** See also: addremove, extras, status +** See also: addremove, extra, status */ void clean_cmd(void){ int allFileFlag, allDirFlag, dryRunFlag, verboseFlag; int emptyDirsFlag, dirsOnlyFlag; unsigned scanFlags = 0; @@ -607,10 +600,11 @@ if( !allFileFlag && !dryRunFlag && !glob_match(pClean, zName+nRoot) ){ Blob ans; char cReply; char *prompt = mprintf("Remove unmanaged file \"%s\" (a=all/y/N)? ", zName+nRoot); + blob_zero(&ans); prompt_user(prompt, &ans); cReply = blob_str(&ans)[0]; if( cReply=='a' || cReply=='A' ){ allFileFlag = 1; }else if( cReply!='y' && cReply!='Y' ){ @@ -648,10 +642,11 @@ if( !allDirFlag && !dryRunFlag && !glob_match(pClean, zName+nRoot) ){ Blob ans; char cReply; char *prompt = mprintf("Remove empty directory \"%s\" (a=all/y/N)? ", zName+nRoot); + blob_zero(&ans); prompt_user(prompt, &ans); cReply = blob_str(&ans)[0]; if( cReply=='a' || cReply=='A' ){ allDirFlag = 1; }else if( cReply!='y' && cReply!='Y' ){ @@ -808,11 +803,11 @@ blob_append(&prompt, "\n" "# Enter commit message for this check-in. Lines beginning with # are ignored.\n" "#\n", -1 ); - blob_appendf(&prompt, "# user: %s\n", p->zUserOvrd ? p->zUserOvrd : login_name()); + blob_appendf(&prompt, "# user: %s\n", p->zUserOvrd ? p->zUserOvrd : g.zLogin); if( p->zBranch && p->zBranch[0] ){ blob_appendf(&prompt, "# tags: %s\n#\n", p->zBranch); }else{ char *zTags = info_tags_of_checkin(parent_rid, 1); if( zTags ) blob_appendf(&prompt, "# tags: %z\n#\n", zTags); @@ -970,11 +965,11 @@ int verifyDate; /* Verify that child is younger */ int closeFlag; /* Close the branch being committed */ int integrateFlag; /* Close merged-in branches */ Blob *pCksum; /* Repository checksum. May be 0 */ const char *zDateOvrd; /* Date override. If 0 then use 'now' */ - const char *zUserOvrd; /* User override. If 0 then use login_name() */ + const char *zUserOvrd; /* User override. If 0 then use g.zLogin */ const char *zBranch; /* Branch name. May be 0 */ const char *zColor; /* One-time background color. May be 0 */ const char *zBrClr; /* Persistent branch color. May be 0 */ const char **azTag; /* Tags to apply to this check-in */ }; @@ -1196,11 +1191,11 @@ const char *zBrTag = db_column_text(&q, 0); blob_appendf(pOut, "T -%F *\n", zBrTag); } db_finalize(&q); } - blob_appendf(pOut, "U %F\n", p->zUserOvrd ? p->zUserOvrd : login_name()); + blob_appendf(pOut, "U %F\n", p->zUserOvrd ? p->zUserOvrd : g.zLogin); md5sum_blob(pOut, &mcksum); blob_appendf(pOut, "Z %b\n", &mcksum); if( pnFBcard ) *pnFBcard = nFBcard; } @@ -1290,13 +1285,17 @@ }else{ if( encodingOk ){ return 0; /* We don't want encoding warnings for this file. */ } zWarning = "Unicode"; +#if !defined(_WIN32) && !defined(__CYGWIN__) + zConvert = ""; /* On Unix, we cannot easily convert Unicode files. */ +#endif zDisable = "\"encoding-glob\" setting"; } file_relative_name(zFilename, &fname, 0); + blob_zero(&ans); zMsg = mprintf( "%s contains %s. Use --no-warnings or the %s to disable this warning.\n" "Commit anyhow (a=all/%sy/N)? ", blob_str(&fname), zWarning, zDisable, zConvert); prompt_user(zMsg, &ans); @@ -1308,25 +1307,21 @@ char *zOrig = file_newname(zFilename, "original", 1); FILE *f; blob_write_to_file(p, zOrig); fossil_free(zOrig); f = fossil_fopen(zFilename, "wb"); - if( f==0 ){ - fossil_warning("cannot open %s for writing", zFilename); - }else{ - if( fUnicode ) { - int bomSize; - const unsigned char *bom = get_utf8_bom(&bomSize); - fwrite(bom, 1, bomSize, f); - blob_to_utf8_no_bom(p, 0); - } - if( fHasAnyCr ){ - blob_to_lf_only(p); - } - fwrite(blob_buffer(p), 1, blob_size(p), f); - fclose(f); - } + if( fUnicode ) { + int bomSize; + const unsigned char *bom = get_utf8_bom(&bomSize); + fwrite(bom, 1, bomSize, f); + blob_to_utf8_no_bom(p, 0); + } + if( fHasAnyCr ){ + blob_to_lf_only(p); + } + fwrite(blob_buffer(p), 1, blob_size(p), f); + fclose(f); return 1; }else if( cReply!='y' && cReply!='Y' ){ fossil_fatal("Abandoning commit due to %s in %s", zWarning, blob_str(&fname)); } @@ -1419,11 +1414,11 @@ ** --private do not sync changes and their descendants ** --sha1sum verify file status using SHA1 hashing rather ** than relying on file mtimes ** --tag TAG-NAME assign given tag TAG-NAME to the checkin ** -** See also: branch, changes, checkout, extras, sync +** See also: branch, changes, checkout, extra, sync */ void commit_cmd(void){ int hasChanges; /* True if unsaved changes exist */ int vid; /* blob-id of parent version */ int nrid; /* blob-id of a modified file */ @@ -1528,21 +1523,20 @@ forceBaseline = 1; } /* Get the ID of the parent manifest artifact */ vid = db_lget_int("checkout", 0); - if( vid==0 ){ - useCksum = 1; - }else if( content_is_private(vid) ){ + if( content_is_private(vid) ){ g.markPrivate = 1; } /* ** Autosync if autosync is enabled and this is not a private check-in. */ if( !g.markPrivate ){ if( autosync(SYNC_PULL) ){ + blob_zero(&ans); prompt_user("continue in spite of sync failure (y/N)? ", &ans); cReply = blob_str(&ans)[0]; if( cReply!='y' && cReply!='Y' ){ fossil_exit(1); } @@ -1551,10 +1545,11 @@ /* Require confirmation to continue with the check-in if there is ** clock skew */ if( g.clockSkewSeen ){ + blob_zero(&ans); prompt_user("continue in spite of time skew (y/N)? ", &ans); cReply = blob_str(&ans)[0]; if( cReply!='y' && cReply!='Y' ){ fossil_exit(1); } @@ -1569,13 +1564,14 @@ ** array is allocated to contain the "id" field from the vfile table ** for each file to be committed. Or, if aCommitFile is NULL, all files ** should be committed. */ if( select_commit_files() ){ + blob_zero(&ans); prompt_user("continue (y/N)? ", &ans); cReply = blob_str(&ans)[0]; - if( cReply!='y' && cReply!='Y' ) fossil_exit(1); + if( cReply!='y' && cReply!='Y' ) fossil_exit(1);; } isAMerge = db_exists("SELECT 1 FROM vmerge WHERE id=0 OR id<-2"); if( g.aCommitFile && isAMerge ){ fossil_fatal("cannot do a partial commit of a merge"); } @@ -1669,18 +1665,20 @@ blob_zero(&comment); }else{ char *zInit = db_text(0, "SELECT value FROM vvar WHERE name='ci-comment'"); prepare_commit_comment(&comment, zInit, &sCiInfo, vid); if( zInit && zInit[0] && fossil_strcmp(zInit, blob_str(&comment))==0 ){ + blob_zero(&ans); prompt_user("unchanged check-in comment. continue (y/N)? ", &ans); cReply = blob_str(&ans)[0]; - if( cReply!='y' && cReply!='Y' ) fossil_exit(1); + if( cReply!='y' && cReply!='Y' ) fossil_exit(1);; } free(zInit); } if( blob_size(&comment)==0 ){ if( !dryRunFlag ){ + blob_zero(&ans); prompt_user("empty check-in comment. continue (y/N)? ", &ans); cReply = blob_str(&ans)[0]; if( cReply!='y' && cReply!='Y' ){ fossil_exit(1); } @@ -1809,10 +1807,11 @@ }else if( forceDelta ){ fossil_fatal("unable to find a baseline-manifest for the delta"); } } if( !noSign && !g.markPrivate && clearsign(&manifest, &manifest) ){ + blob_zero(&ans); prompt_user("unable to sign manifest. continue (y/N)? ", &ans); cReply = blob_str(&ans)[0]; if( cReply!='y' && cReply!='Y' ){ fossil_exit(1); } Index: src/checkout.c ================================================================== --- src/checkout.c +++ src/checkout.c @@ -157,11 +157,11 @@ zManFile = mprintf("%smanifest.uuid", g.zLocalRoot); file_delete(zManFile); free(zManFile); } } - + } /* ** COMMAND: checkout* ** COMMAND: co* @@ -175,11 +175,11 @@ ** leaves files on disk unchanged, except the manifest and manifest.uuid ** files. ** ** The --latest flag can be used in place of VERSION to checkout the ** latest version in the repository. -** +** ** Options: ** --force Ignore edited files in the current checkout ** --keep Only update the manifest and manifest.uuid files ** ** See also: update @@ -190,11 +190,11 @@ int latestFlag; /* Checkout the latest version */ char *zVers; /* Version to checkout */ int promptFlag; /* True to prompt before overwriting */ int vid, prior; Blob cksum1, cksum1b, cksum2; - + db_must_be_within_tree(); db_begin_transaction(); forceFlag = find_option("force","f",0)!=0; keepFlag = find_option("keep",0,0)!=0; latestFlag = find_option("latest",0,0)!=0; Index: src/clone.c ================================================================== --- src/clone.c +++ src/clone.c @@ -109,25 +109,22 @@ ** --admin-user|-A USERNAME Make USERNAME the administrator ** --once Don't save url. ** --private Also clone private branches ** --ssl-identity=filename Use the SSL identity if requested by the server ** --ssh-command|-c 'command' Use this SSH command -** --httpauth|-B 'user:pass' Add HTTP Basic Authorization to requests ** ** See also: init */ void clone_cmd(void){ char *zPassword; const char *zDefaultUser; /* Optional name of the default user */ - const char *zHttpAuth; /* HTTP Authorization user:pass information */ int nErr = 0; int bPrivate = 0; /* Also clone private branches */ int urlFlags = URL_PROMPT_PW | URL_REMEMBER; if( find_option("private",0,0)!=0 ) bPrivate = SYNC_PRIVATE; if( find_option("once",0,0)!=0) urlFlags &= ~URL_REMEMBER; - zHttpAuth = find_option("httpauth","B",1); zDefaultUser = find_option("admin-user","A",1); clone_ssh_find_options(); url_proxy_options(); if( g.argc < 4 ){ usage("?OPTIONS? FILE-OR-URL NEW-REPOSITORY"); @@ -136,13 +133,13 @@ if( file_size(g.argv[3])>0 ){ fossil_fatal("file already exists: %s", g.argv[3]); } url_parse(g.argv[2], urlFlags); - if( zDefaultUser==0 && g.url.user!=0 ) zDefaultUser = g.url.user; - if( g.url.isFile ){ - file_copy(g.url.name, g.argv[3]); + if( zDefaultUser==0 && g.urlUser!=0 ) zDefaultUser = g.urlUser; + if( g.urlIsFile ){ + file_copy(g.urlName, g.argv[3]); db_close(1); db_open_repository(g.argv[3]); db_record_repository_filename(g.argv[3]); url_remember(); if( !bPrivate ) delete_private_content(); @@ -162,11 +159,10 @@ db_initial_setup(0, 0, zDefaultUser, 0); user_select(); db_set("content-schema", CONTENT_SCHEMA, 0); db_set("aux-schema", AUX_SCHEMA, 0); db_set("rebuilt", get_version(), 0); - remember_or_get_http_auth(zHttpAuth, urlFlags & URL_REMEMBER, g.argv[2]); url_remember(); if( g.zSSLIdentity!=0 ){ /* If the --ssl-identity option was specified, store it as a setting */ Blob fn; blob_zero(&fn); @@ -200,57 +196,10 @@ zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin); fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword); db_end_transaction(0); } -/* -** If user chooses to use HTTP Authentication over unencrypted HTTP, -** remember decision. Otherwise, if the URL is being changed and no -** preference has been indicated, err on the safe side and revert the -** decision. Set the global preference if the URL is not being changed. -*/ -void remember_or_get_http_auth( - const char *zHttpAuth, /* Credentials in the form "user:password" */ - int fRemember, /* True to remember credentials for later reuse */ - const char *zUrl /* URL for which these credentials apply */ -){ - char *zKey = mprintf("http-auth:%s", g.url.canonical); - if( zHttpAuth && zHttpAuth[0] ){ - g.zHttpAuth = mprintf("%s", zHttpAuth); - } - if( fRemember ){ - if( g.zHttpAuth && g.zHttpAuth[0] ){ - set_httpauth(g.zHttpAuth); - }else if( zUrl && zUrl[0] ){ - db_unset(zKey, 0); - }else{ - g.zHttpAuth = get_httpauth(); - } - }else if( g.zHttpAuth==0 && zUrl==0 ){ - g.zHttpAuth = get_httpauth(); - } - free(zKey); -} - -/* -** Get the HTTP Authorization preference from db. -*/ -char *get_httpauth(void){ - char *zKey = mprintf("http-auth:%s", g.url.canonical); - return unobscure(db_get(zKey, 0)); - free(zKey); -} - -/* -** Set the HTTP Authorization preference in db. -*/ -void set_httpauth(const char *zHttpAuth){ - char *zKey = mprintf("http-auth:%s", g.url.canonical); - db_set(zKey, obscure(zHttpAuth), 0); - free(zKey); -} - /* ** Look for SSH clone command line options and setup in globals. */ void clone_ssh_find_options(void){ const char *zSshCmd; /* SSH command string */ Index: src/comformat.c ================================================================== --- src/comformat.c +++ src/comformat.c @@ -34,13 +34,12 @@ int tlen = lineLength - indent; int si, sk, i, k; int doIndent = 0; char *zBuf; char zBuffer[400]; - int lineCnt = 0; + int lineCnt = 0; - if( zText==0 ) zText = "(NULL)"; if( tlen<=0 ){ tlen = strlen(zText); } if( tlen >= (sizeof(zBuffer)) ){ zBuf = fossil_malloc(tlen+1); Index: src/config.h ================================================================== --- src/config.h +++ src/config.h @@ -62,93 +62,30 @@ # include # include # include #endif -/* -** Utility macro to wrap an argument with double quotes. -*/ -#if !defined(COMPILER_STRINGIFY) -# define COMPILER_STRINGIFY(x) COMPILER_STRINGIFY1(x) -# define COMPILER_STRINGIFY1(x) #x -#endif - /* ** Define the compiler variant, used to compile the project */ #if !defined(COMPILER_NAME) # if defined(__DMC__) -# if defined(COMPILER_VERSION) && !defined(NO_COMPILER_VERSION) -# define COMPILER_NAME "dmc-" COMPILER_VERSION -# else -# define COMPILER_NAME "dmc" -# endif +# define COMPILER_NAME "dmc" # elif defined(__POCC__) # if defined(_M_X64) -# if defined(COMPILER_VERSION) && !defined(NO_COMPILER_VERSION) -# define COMPILER_NAME "pellesc64-" COMPILER_VERSION -# else -# define COMPILER_NAME "pellesc64" -# endif +# define COMPILER_NAME "pellesc64" # else -# if defined(COMPILER_VERSION) && !defined(NO_COMPILER_VERSION) -# define COMPILER_NAME "pellesc32-" COMPILER_VERSION -# else -# define COMPILER_NAME "pellesc32" -# endif +# define COMPILER_NAME "pellesc32" # endif # elif defined(_MSC_VER) -# if !defined(COMPILER_VERSION) -# define COMPILER_VERSION COMPILER_STRINGIFY(_MSC_VER) -# endif -# if defined(COMPILER_VERSION) && !defined(NO_COMPILER_VERSION) -# define COMPILER_NAME "msc-" COMPILER_VERSION -# else -# define COMPILER_NAME "msc" -# endif +# define COMPILER_NAME "msc" # elif defined(__MINGW32__) -# if !defined(COMPILER_VERSION) -# if defined(__MINGW_VERSION) -# if defined(__GNUC__) -# if defined(__VERSION__) -# define COMPILER_VERSION COMPILER_STRINGIFY(__MINGW_VERSION) "-gcc-" __VERSION__ -# else -# define COMPILER_VERSION COMPILER_STRINGIFY(__MINGW_VERSION) "-gcc" -# endif -# else -# define COMPILER_VERSION COMPILER_STRINGIFY(__MINGW_VERSION) -# endif -# elif defined(__MINGW32_VERSION) -# if defined(__GNUC__) -# if defined(__VERSION__) -# define COMPILER_VERSION COMPILER_STRINGIFY(__MINGW32_VERSION) "-gcc-" __VERSION__ -# else -# define COMPILER_VERSION COMPILER_STRINGIFY(__MINGW32_VERSION) "-gcc" -# endif -# else -# define COMPILER_VERSION COMPILER_STRINGIFY(__MINGW32_VERSION) -# endif -# endif -# endif -# if defined(COMPILER_VERSION) && !defined(NO_COMPILER_VERSION) -# define COMPILER_NAME "mingw32-" COMPILER_VERSION -# else -# define COMPILER_NAME "mingw32" -# endif +# define COMPILER_NAME "mingw32" # elif defined(_WIN32) # define COMPILER_NAME "win32" # elif defined(__GNUC__) -# if !defined(COMPILER_VERSION) -# if defined(__VERSION__) -# define COMPILER_VERSION __VERSION__ -# endif -# endif -# if defined(COMPILER_VERSION) && !defined(NO_COMPILER_VERSION) -# define COMPILER_NAME "gcc-" COMPILER_VERSION -# else -# define COMPILER_NAME "gcc" -# endif +# define COMPILER_NAME "gcc-" __VERSION__ # else # define COMPILER_NAME "unknown" # endif #endif @@ -186,11 +123,11 @@ ** The following macros are used to cast pointers to integers and ** integers to pointers. The way you do this varies from one compiler ** to the next, so we have developed the following set of #if statements ** to generate appropriate macros for a wide range of compilers. ** -** The correct "ANSI" way to do this is to use the intptr_t type. +** The correct "ANSI" way to do this is to use the intptr_t type. ** Unfortunately, that typedef is not available on all compilers, or ** if it is available, it requires an #include of specific headers ** that vary from one machine to the next. */ #if defined(__PTRDIFF_TYPE__) /* This case should work for GCC */ Index: src/configure.c ================================================================== --- src/configure.c +++ src/configure.c @@ -924,11 +924,11 @@ mask = configure_name_to_mask(g.argv[3], 1); if( g.argc==5 ){ zServer = g.argv[4]; } url_parse(zServer, URL_PROMPT_PW); - if( g.url.protocol==0 ) fossil_fatal("no server URL specified"); + if( g.urlProtocol==0 ) fossil_fatal("no server URL specified"); user_select(); url_enable_proxy("via proxy: "); if( legacyFlag ) mask |= CONFIGSET_OLDFORMAT; if( overwriteFlag ) mask |= CONFIGSET_OVERWRITE; if( strncmp(zMethod, "push", n)==0 ){ Index: src/content.c ================================================================== --- src/content.c +++ src/content.c @@ -114,11 +114,11 @@ contentCache.n = 0; contentCache.szTotal = 0; } /* -** Return the srcid associated with rid. Or return 0 if rid is +** Return the srcid associated with rid. Or return 0 if rid is ** original content and not a delta. */ static int findSrcid(int rid){ static Stmt q; int srcid; @@ -154,11 +154,11 @@ ** a phantom. */ int content_is_available(int rid){ int srcid; int depth = 0; /* Limit to recursion depth */ - while( depth++ < 10000000 ){ + while( depth++ < 10000000 ){ if( bag_find(&contentCache.missing, rid) ){ return 0; } if( bag_find(&contentCache.available, rid) ){ return 1; @@ -416,11 +416,11 @@ /* Recursively dephantomize all artifacts that are derived by ** delta from artifact rid and which have not already been ** cross-linked. */ nChildUsed = 0; - db_prepare(&q, + db_prepare(&q, "SELECT rid FROM delta" " WHERE srcid=%d" " AND NOT EXISTS(SELECT 1 FROM mlink WHERE mid=delta.rid)", rid ); @@ -455,11 +455,11 @@ /* ** Write content into the database. Return the record ID. If the ** content is already in the database, just return the record ID. ** ** If srcId is specified, then pBlob is delta content from -** the srcId record. srcId might be a phantom. +** the srcId record. srcId might be a phantom. ** ** pBlob is normally uncompressed text. But if nBlob>0 then the ** pBlob value has already been compressed and nBlob is its uncompressed ** size. If nBlob>0 then zUuid must be valid. ** @@ -486,11 +486,11 @@ Stmt s1; Blob cmpr; Blob hash; int markAsUnclustered = 0; int isDephantomize = 0; - + assert( g.repositoryOpen ); assert( pBlob!=0 ); assert( srcId==0 || zUuid!=0 ); if( zUuid==0 ){ assert( nBlob==0 ); @@ -580,18 +580,18 @@ ** really a delta. Record this fact in the delta table. */ if( srcId ){ db_multi_exec("REPLACE INTO delta(rid,srcid) VALUES(%d,%d)", rid, srcId); } - if( !isDephantomize && bag_find(&contentCache.missing, rid) && + if( !isDephantomize && bag_find(&contentCache.missing, rid) && (srcId==0 || content_is_available(srcId)) ){ content_mark_available(rid); } if( isDephantomize ){ after_dephantomize(rid, 0); } - + /* Add the element to the unclustered table if has never been ** previously seen. */ if( markAsUnclustered ){ db_multi_exec("INSERT OR IGNORE INTO unclustered VALUES(%d)", rid); @@ -628,11 +628,11 @@ ** Create a new phantom with the given UUID and return its artifact ID. */ int content_new(const char *zUuid, int isPrivate){ int rid; static Stmt s1, s2, s3; - + assert( g.repositoryOpen ); db_begin_transaction(); if( uuid_is_shunned(zUuid) ){ db_end_transaction(0); return 0; @@ -727,15 +727,15 @@ "SELECT 1 FROM private WHERE rid=:rid" ); db_bind_int(&s1, ":rid", rid); rc = db_step(&s1); db_reset(&s1); - return rc==SQLITE_ROW; + return rc==SQLITE_ROW; } /* -** Make sure an artifact is public. +** Make sure an artifact is public. */ void content_make_public(int rid){ static Stmt s1; db_static_prepare(&s1, "DELETE FROM private WHERE rid=:rid" @@ -758,11 +758,11 @@ ** ** If srcid is a delta that depends on rid, then srcid is ** converted to undeltaed text. ** ** If either rid or srcid contain less than 50 bytes, or if the -** resulting delta does not achieve a compression of at least 25% +** resulting delta does not achieve a compression of at least 25% ** the rid is left untouched. ** ** Return 1 if a delta is made and 0 if no delta occurs. */ int content_deltify(int rid, int srcid, int force){ @@ -883,11 +883,11 @@ zId, rid, zSrc, srcid ); nErr++; } db_finalize(&q); - + db_prepare(&q, "SELECT rid, uuid, size FROM blob ORDER BY rid"); total = db_int(0, "SELECT max(rid) FROM blob"); while( db_step(&q)==SQLITE_ROW ){ int rid = db_column_int(&q, 0); const char *zUuid = db_column_text(&q, 1); @@ -945,12 +945,12 @@ } db_finalize(&q); fossil_print("%d non-phantom blobs (out of %d total) checked: %d errors\n", n2, n1, nErr); if( bParse ){ - static const char *const azType[] = { 0, "manifest", "cluster", - "control", "wiki", "ticket", "attachment", "event" }; + const char *azType[] = { 0, "manifest", "cluster", "control", "wiki", + "ticket", "attachment", "event" }; int i; fossil_print("%d total control artifacts\n", nCA); for(i=1; izBaseline, flags, p, "baseline of", 0); nErr += check_exists(p->zAttachSrc, flags, p, "file of", 0); for(i=0; inFile; i++){ - nErr += check_exists(p->aFile[i].zUuid, flags, p, "file of", + nErr += check_exists(p->aFile[i].zUuid, flags, p, "file of", p->aFile[i].zName); } for(i=0; inParent; i++){ nErr += check_exists(p->azParent[i], flags, p, "parent of", 0); } @@ -1115,14 +1115,14 @@ nErr += check_exists(p->azCChild[i], flags, p, "in", 0); } for(i=0; inTag; i++){ nErr += check_exists(p->aTag[i].zUuid, flags, p, "target of", 0); } - manifest_destroy(p); + manifest_destroy(p); } } db_finalize(&q); if( nErr>0 || quietFlag==0 ){ fossil_print("%d missing or shunned references in %d control artifacts\n", nErr, nArtifact); } } Index: src/db.c ================================================================== --- src/db.c +++ src/db.c @@ -44,11 +44,11 @@ ** An single SQL statement is represented as an instance of the following ** structure. */ struct Stmt { Blob sql; /* The SQL for this statement */ - sqlite3_stmt *pStmt; /* The results of sqlite3_prepare_v2() */ + sqlite3_stmt *pStmt; /* The results of sqlite3_prepare() */ Stmt *pNext, *pPrev; /* List of all unfinalized statements */ int nStep; /* Number of sqlite3_step() calls */ }; /* @@ -108,11 +108,11 @@ static struct DbLocalData { int nBegin; /* Nesting depth of BEGIN */ int doRollback; /* True to force a rollback */ int nCommitHook; /* Number of commit hooks */ Stmt *pAllStmt; /* List of all unfinalized statements */ - int nPrepare; /* Number of calls to sqlite3_prepare_v2() */ + int nPrepare; /* Number of calls to sqlite3_prepare() */ int nDeleteOnFail; /* Number of entries in azDeleteOnFail[] */ struct sCommitHook { int (*xHook)(void); /* Functions to call at db_end_transaction() */ int sequence; /* Call functions in sequence order */ } aHook[5]; @@ -316,14 +316,10 @@ } int db_bind_text(Stmt *pStmt, const char *zParamName, const char *zValue){ return sqlite3_bind_text(pStmt->pStmt, paramIdx(pStmt, zParamName), zValue, -1, SQLITE_STATIC); } -int db_bind_text16(Stmt *pStmt, const char *zParamName, const char *zValue){ - return sqlite3_bind_text16(pStmt->pStmt, paramIdx(pStmt, zParamName), zValue, - -1, SQLITE_STATIC); -} int db_bind_null(Stmt *pStmt, const char *zParamName){ return sqlite3_bind_null(pStmt->pStmt, paramIdx(pStmt, zParamName)); } int db_bind_blob(Stmt *pStmt, const char *zParamName, Blob *pBlob){ return sqlite3_bind_blob(pStmt->pStmt, paramIdx(pStmt, zParamName), @@ -715,11 +711,11 @@ */ LOCAL sqlite3 *db_open(const char *zDbName){ int rc; sqlite3 *db; -#if defined(__CYGWIN__) && USE_SYSTEM_SQLITE+0!=1 +#if defined(__CYGWIN__) zDbName = fossil_utf8_to_filename(zDbName); #endif if( g.fSqlTrace ) fossil_trace("-- sqlite3_open: [%s]\n", zDbName); rc = sqlite3_open_v2( zDbName, &db, @@ -831,21 +827,23 @@ } #if defined(_WIN32) || defined(__CYGWIN__) /* . filenames give some window systems problems and many apps problems */ zDbName = mprintf("%//_fossil", zHome); #else + if( file_access(zHome, W_OK) ){ + fossil_fatal("home directory %s must be writeable", zHome); + } zDbName = mprintf("%s/.fossil", zHome); #endif if( file_size(zDbName)<1024*3 ){ - if( file_access(zHome, W_OK) ){ - fossil_fatal("home directory %s must be writeable", zHome); - } db_init_database(zDbName, zConfigSchema, (char*)0); } +#if defined(_WIN32) || defined(__CYGWIN__) if( file_access(zDbName, W_OK) ){ fossil_fatal("configuration file %s must be writeable", zDbName); } +#endif if( useAttach ){ db_open_or_attach(zDbName, "configdb", &g.useAttach); g.dbConfig = 0; g.zConfigDbType = 0; }else{ @@ -1022,11 +1020,15 @@ g.json.resultCode = FSL_JSON_E_DB_NOT_VALID; #endif fossil_panic("not a valid repository: %s", zDbName); } } +#if defined(__CYGWIN__) + g.zRepositoryName = fossil_utf8_to_filename(zDbName); +#else g.zRepositoryName = mprintf("%s", zDbName); +#endif db_open_or_attach(g.zRepositoryName, "repository", 0); g.repositoryOpen = 1; /* Cache "allow-symlinks" option, because we'll need it on every stat call */ g.allowSymlinks = db_get_boolean("allow-symlinks", 0); } @@ -1985,28 +1987,23 @@ ** If VERSION is specified then that version is checked out. Otherwise ** the latest version is checked out. No files other than "manifest" ** and "manifest.uuid" are modified if the --keep option is present. ** ** Options: -** --empty Initialize checkout as being empty, but still connected -** with the local repository. If you commit this checkout, -** it will become a new "initial" commit in the repository. ** --keep Only modify the manifest and manifest.uuid files ** --nested Allow opening a repository inside an opened checkout ** ** See also: close */ void cmd_open(void){ - int emptyFlag; int keepFlag; int allowNested; char **oldArgv; int oldArgc; static char *azNewArgv[] = { 0, "checkout", "--prompt", 0, 0, 0 }; url_proxy_options(); - emptyFlag = find_option("empty",0,0)!=0; keepFlag = find_option("keep",0,0)!=0; allowNested = find_option("nested",0,0)!=0; if( g.argc!=3 && g.argc!=4 ){ usage("REPOSITORY-FILENAME ?VERSION?"); } @@ -2031,24 +2028,22 @@ db_lset_int("checkout", 0); oldArgv = g.argv; oldArgc = g.argc; azNewArgv[0] = g.argv[0]; g.argv = azNewArgv; - if( !emptyFlag){ - g.argc = 3; - if( oldArgc==4 ){ - azNewArgv[g.argc-1] = oldArgv[3]; - }else if( !db_exists("SELECT 1 FROM event WHERE type='ci'") ){ - azNewArgv[g.argc-1] = "--latest"; - }else{ - azNewArgv[g.argc-1] = db_get("main-branch", "trunk"); - } - if( keepFlag ){ - azNewArgv[g.argc++] = "--keep"; - } - checkout_cmd(); - } + g.argc = 3; + if( oldArgc==4 ){ + azNewArgv[g.argc-1] = oldArgv[3]; + }else if( !db_exists("SELECT 1 FROM event WHERE type='ci'") ){ + azNewArgv[g.argc-1] = "--latest"; + }else{ + azNewArgv[g.argc-1] = db_get("main-branch", "trunk"); + } + if( keepFlag ){ + azNewArgv[g.argc++] = "--keep"; + } + checkout_cmd(); g.argc = 2; info_cmd(); } /* @@ -2143,11 +2138,10 @@ { "ignore-glob", 0, 40, 1, 0, "" }, { "keep-glob", 0, 40, 1, 0, "" }, { "localauth", 0, 0, 0, 0, "off" }, { "main-branch", 0, 40, 0, 0, "trunk" }, { "manifest", 0, 0, 1, 0, "off" }, - { "max-loadavg", 0, 25, 0, 0, "0.0" }, { "max-upload", 0, 25, 0, 0, "250000" }, { "mtime-changes", 0, 0, 0, 0, "on" }, { "pgp-command", 0, 40, 0, 0, "gpg --clearsign -o " }, { "proxy", 0, 32, 0, 0, "off" }, { "relative-paths", 0, 0, 0, 0, "on" }, @@ -2294,17 +2288,10 @@ ** ** manifest If enabled, automatically create files "manifest" and ** (versionable) "manifest.uuid" in every checkout. The SQLite and ** Fossil repositories both require this. Default: off. ** -** max-loadavg Some CPU-intensive web pages (ex: /zip, /tarball, /blame) -** are disallowed if the system load average goes above this -** value. "0.0" means no limit. This only works on unix. -** Only local settings of this value make a difference since -** when running as a web-server, Fossil does not open the -** global configuration database. -** ** max-upload A limit on the size of uplink HTTP requests. The ** default is 250000 bytes. ** ** mtime-changes Use file modification times (mtimes) to detect when ** files have been modified. (Default "on".) Index: src/delta.c ================================================================== --- src/delta.c +++ src/delta.c @@ -467,11 +467,11 @@ zDelta += lenOut-base; } /* Output the final checksum record. */ putInt(checksum(zOut, lenOut), &zDelta); *(zDelta++) = ';'; - fossil_free(collide); + free(collide); return zDelta - zOrigDelta; } /* ** Return the size (in bytes) of the output from applying Index: src/descendants.c ================================================================== --- src/descendants.c +++ src/descendants.c @@ -157,10 +157,46 @@ /* ** Load the record ID rid and up to N-1 closest ancestors into ** the "ok" table. */ void compute_ancestors(int rid, int N, int directOnly){ +#if USE_SYSTEM_SQLITE+0==1 + if( sqlite3_libversion_number()<3008003 ){ + Bag seen; + PQueue queue; + Stmt ins; + Stmt q; + bag_init(&seen); + pqueuex_init(&queue); + bag_insert(&seen, rid); + pqueuex_insert(&queue, rid, 0.0, 0); + db_prepare(&ins, "INSERT OR IGNORE INTO ok VALUES(:rid)"); + db_prepare(&q, + "SELECT a.pid, b.mtime FROM plink a LEFT JOIN plink b ON b.cid=a.pid" + " WHERE a.cid=:rid %s", + directOnly ? " AND a.isprim" : "" + ); + while( (N--)>0 && (rid = pqueuex_extract(&queue, 0))!=0 ){ + db_bind_int(&ins, ":rid", rid); + db_step(&ins); + db_reset(&ins); + db_bind_int(&q, ":rid", rid); + while( db_step(&q)==SQLITE_ROW ){ + int pid = db_column_int(&q, 0); + double mtime = db_column_double(&q, 1); + if( bag_insert(&seen, pid) ){ + pqueuex_insert(&queue, pid, -mtime, 0); + } + } + db_reset(&q); + } + bag_clear(&seen); + pqueuex_clear(&queue); + db_finalize(&ins); + db_finalize(&q); + } else +#endif db_multi_exec( "WITH RECURSIVE " " ancestor(rid, mtime) AS (" " SELECT %d, mtime FROM event WHERE objid=%d " " UNION " Index: src/diff.c ================================================================== --- src/diff.c +++ src/diff.c @@ -29,21 +29,21 @@ ** of the diff output. */ #define DIFF_CONTEXT_MASK ((u64)0x0000ffff) /* Lines of context. Default if 0 */ #define DIFF_WIDTH_MASK ((u64)0x00ff0000) /* side-by-side column width */ #define DIFF_IGNORE_EOLWS ((u64)0x01000000) /* Ignore end-of-line whitespace */ -#define DIFF_IGNORE_ALLWS ((u64)0x03000000) /* Ignore all whitespace */ -#define DIFF_SIDEBYSIDE ((u64)0x04000000) /* Generate a side-by-side diff */ -#define DIFF_VERBOSE ((u64)0x08000000) /* Missing shown as empty files */ -#define DIFF_BRIEF ((u64)0x10000000) /* Show filenames only */ -#define DIFF_HTML ((u64)0x20000000) /* Render for HTML */ -#define DIFF_LINENO ((u64)0x40000000) /* Show line numbers */ +#define DIFF_SIDEBYSIDE ((u64)0x02000000) /* Generate a side-by-side diff */ +#define DIFF_VERBOSE ((u64)0x04000000) /* Missing shown as empty files */ +#define DIFF_BRIEF ((u64)0x08000000) /* Show filenames only */ +#define DIFF_INLINE ((u64)0x00000000) /* Inline (not side-by-side) diff */ +#define DIFF_HTML ((u64)0x10000000) /* Render for HTML */ +#define DIFF_LINENO ((u64)0x20000000) /* Show line numbers */ +#define DIFF_WS_WARNING ((u64)0x40000000) /* Warn about whitespace */ #define DIFF_NOOPT (((u64)0x01)<<32) /* Suppress optimizations (debug) */ #define DIFF_INVERT (((u64)0x02)<<32) /* Invert the diff (debug) */ #define DIFF_CONTEXT_EX (((u64)0x04)<<32) /* Use context even if zero */ #define DIFF_NOTTOOBIG (((u64)0x08)<<32) /* Only display if not too big */ -#define DIFF_STRIP_EOLCR (((u64)0x10)<<32) /* Strip trailing CR */ /* ** These error messages are shared in multiple locations. They are defined ** here for consistency. */ @@ -54,13 +54,10 @@ "cannot compute difference between symlink and regular file\n" #define DIFF_TOO_MANY_CHANGES \ "more than 10,000 changes\n" -#define DIFF_WHITESPACE_ONLY \ - "whitespace changes only\n" - /* ** Maximum length of a line in a text file, in bytes. (2**13 = 8192 bytes) */ #define LENGTH_MASK_SZ 13 #define LENGTH_MASK ((1<n) +#define LENGTH(X) ((X)->h & LENGTH_MASK) /* ** A context for running a raw diff. ** ** The aEdit[] array describes the raw diff. Each triple of integers in @@ -113,11 +108,10 @@ int nEditAlloc; /* Space allocated for aEdit[] */ DLine *aFrom; /* File on left side of the diff */ int nFrom; /* Number of lines in aFrom[] */ DLine *aTo; /* File on right side of the diff */ int nTo; /* Number of lines in aTo[] */ - int (*same_fn)(const DLine *, const DLine *); /* Function to be used for comparing */ }; /* ** Return an array of DLine objects containing a pointer to the ** start of each line and a hash of that line. The lower @@ -131,12 +125,12 @@ ** too long. ** ** Profiling show that in most cases this routine consumes the bulk of ** the CPU time on a diff. */ -static DLine *break_into_lines(const char *z, int n, int *pnLine, u64 diffFlags){ - int nLine, i, j, k, s, x; +static DLine *break_into_lines(const char *z, int n, int *pnLine, int ignoreWS){ + int nLine, i, j, k, x; unsigned int h, h2; DLine *a; /* Count the number of lines. Allocate space to hold ** the returned array. @@ -164,39 +158,18 @@ return a; } /* Fill in the array */ for(i=0; i0 && z[k-1]=='\r' ){ k--; } - } - a[i].n = k; - s = 0; - if( diffFlags & DIFF_IGNORE_EOLWS ){ - while( k>0 && fossil_isspace(z[k-1]) ){ k--; } - } - if( (diffFlags & DIFF_IGNORE_ALLWS)==DIFF_IGNORE_ALLWS ){ - int numws = 0; - while( s0 && fossil_isspace(z[k-1]) ){ k--; } + for(h=0, x=0; x<=k; x++){ + h = h ^ (h<<2) ^ z[x]; + } + a[i].h = h = (h<h==pB->h && memcmp(pA->z,pB->z, pA->h&LENGTH_MASK)==0; -} - -/* -** Return true if two DLine elements are identical, ignoring -** all whitespace. The indent field of pA/pB already points -** to the first non-space character in the string. -*/ - -static int same_dline_ignore_allws(const DLine *pA, const DLine *pB){ - int a = pA->indent, b = pB->indent; - if( pA->h==pB->h ){ - while( an && bn ){ - if( pA->z[a++] != pB->z[b++] ) return 0; - while( an && fossil_isspace(pA->z[a])) ++a; - while( bn && fossil_isspace(pB->z[b])) ++b; - } - return pA->n-a == pB->n-b; - } - return 0; +static int same_dline(DLine *pA, DLine *pB){ + return pA->h==pB->h && memcmp(pA->z,pB->z,pA->h & LENGTH_MASK)==0; } /* ** Return true if the regular expression *pRe matches any of the ** N dlines @@ -267,16 +221,16 @@ }else if( cPrefix=='+' ){ blob_append(pOut, "", -1); }else if( cPrefix=='-' ){ blob_append(pOut, "", -1); } - htmlize_to_blob(pOut, pLine->z, pLine->n); + htmlize_to_blob(pOut, pLine->z, (pLine->h & LENGTH_MASK)); if( cPrefix!=' ' ){ blob_append(pOut, "", -1); } }else{ - blob_append(pOut, pLine->z, pLine->n); + blob_append(pOut, pLine->z, pLine->h & LENGTH_MASK); } blob_append(pOut, "\n", 1); } /* @@ -448,11 +402,11 @@ b += m; if( inContext ) m = nContext; for(j=0; japCols[col]; - int n = pLine->n; + int n = pLine->h & LENGTH_MASK; int i; /* Number of input characters consumed */ int k; /* Cursor position */ int needEndSpan = 0; const char *zIn = pLine->z; int w = p->width; @@ -766,13 +720,13 @@ int aLCS[4]; /* Bounds of common middle segment */ static const char zClassRm[] = ""; static const char zClassAdd[] = ""; static const char zClassChng[] = ""; - nLeft = pLeft->n; + nLeft = pLeft->h & LENGTH_MASK; zLeft = pLeft->z; - nRight = pRight->n; + nRight = pRight->h & LENGTH_MASK; zRight = pRight->z; nShort = nLeftz; zB = pB->z; - nA = pA->n; - nB = pB->n; + nA = pA->h & LENGTH_MASK; + nB = pB->h & LENGTH_MASK; while( nA>0 && fossil_isspace(zA[0]) ){ nA--; zA++; } while( nA>0 && fossil_isspace(zA[nA-1]) ){ nA--; } while( nB>0 && fossil_isspace(zB[0]) ){ nB--; zB++; } while( nB>0 && fossil_isspace(zB[nB-1]) ){ nB--; } if( nA>250 ) nA = 250; @@ -1351,11 +1305,11 @@ sbsWriteMarker(&s, " ", ""); sbsWriteLineno(&s, b+j, SBS_LNB); sbsWriteText(&s, &B[b+j], SBS_TXTB); } } - + if( s.escHtml && blob_size(s.apCols[SBS_LNA])>0 ){ blob_append(pOut, "\n", -1); for(i=SBS_LNA; i<=SBS_TXTB; i++){ sbsWriteColumn(pOut, s.apCols[i], i); blob_reset(s.apCols[i]); @@ -1383,16 +1337,16 @@ int iSXb = iS1; /* Best match so far */ int iSYb = iS2; /* Best match so far */ for(i=iS1; isame_fn(&p->aFrom[i], &p->aTo[j]) ) continue; - if( mxLength && !p->same_fn(&p->aFrom[i+mxLength], &p->aTo[j+mxLength]) ){ + if( !same_dline(&p->aFrom[i], &p->aTo[j]) ) continue; + if( mxLength && !same_dline(&p->aFrom[i+mxLength], &p->aTo[j+mxLength]) ){ continue; } k = 1; - while( i+ksame_fn(&p->aFrom[i+k],&p->aTo[j+k]) ){ + while( i+kaFrom[i+k],&p->aTo[j+k]) ){ k++; } if( k>mxLength ){ iSXb = i; iSYb = j; @@ -1454,11 +1408,11 @@ mid = (iE1 + iS1)/2; for(i=iS1; iaTo[p->aFrom[i].h % p->nTo].iHash; while( j>0 - && (j-1=iE2 || !p->same_fn(&p->aFrom[i], &p->aTo[j-1])) + && (j-1=iE2 || !same_dline(&p->aFrom[i], &p->aTo[j-1])) ){ if( limit++ > 10 ){ j = 0; break; } @@ -1471,19 +1425,19 @@ iSX = i; iSY = j-1; pA = &p->aFrom[iSX-1]; pB = &p->aTo[iSY-1]; n = minInt(iSX-iS1, iSY-iS2); - for(k=0; ksame_fn(pA,pB); k++, pA--, pB--){} + for(k=0; kaFrom[iEX]; pB = &p->aTo[iEY]; n = minInt(iE1-iEX, iE2-iEY); - for(k=0; ksame_fn(pA,pB); k++, pA++, pB++){} + for(k=0; knFrom; iE2 = p->nTo; - while( iE1>0 && iE2>0 && p->same_fn(&p->aFrom[iE1-1], &p->aTo[iE2-1]) ){ + while( iE1>0 && iE2>0 && same_dline(&p->aFrom[iE1-1], &p->aTo[iE2-1]) ){ iE1--; iE2--; } mnE = iE1same_fn(&p->aFrom[iS],&p->aTo[iS]); iS++){} + for(iS=0; iSaFrom[iS],&p->aTo[iS]); iS++){} /* do the difference */ if( iS>0 ){ appendTriple(p, iS, 0, 0); } @@ -1694,11 +1648,11 @@ /* Shift insertions toward the beginning of the file */ while( cpy>0 && del==0 && ins>0 ){ DLine *pTop = &p->aFrom[lnFrom-1]; /* Line before start of insert */ DLine *pBtm = &p->aTo[lnTo+ins-1]; /* Last line inserted */ - if( p->same_fn(pTop, pBtm)==0 ) break; + if( same_dline(pTop, pBtm)==0 ) break; if( LENGTH(pTop+1)+LENGTH(pBtm)<=LENGTH(pTop)+LENGTH(pBtm-1) ) break; lnFrom--; lnTo--; p->aEdit[r]--; p->aEdit[r+3]++; @@ -1707,11 +1661,11 @@ /* Shift insertions toward the end of the file */ while( r+3nEdit && p->aEdit[r+3]>0 && del==0 && ins>0 ){ DLine *pTop = &p->aTo[lnTo]; /* First line inserted */ DLine *pBtm = &p->aTo[lnTo+ins]; /* First line past end of insert */ - if( p->same_fn(pTop, pBtm)==0 ) break; + if( same_dline(pTop, pBtm)==0 ) break; if( LENGTH(pTop)+LENGTH(pBtm-1)<=LENGTH(pTop+1)+LENGTH(pBtm) ) break; lnFrom++; lnTo++; p->aEdit[r]++; p->aEdit[r+3]--; @@ -1720,11 +1674,11 @@ /* Shift deletions toward the beginning of the file */ while( cpy>0 && del>0 && ins==0 ){ DLine *pTop = &p->aFrom[lnFrom-1]; /* Line before start of delete */ DLine *pBtm = &p->aFrom[lnFrom+del-1]; /* Last line deleted */ - if( p->same_fn(pTop, pBtm)==0 ) break; + if( same_dline(pTop, pBtm)==0 ) break; if( LENGTH(pTop+1)+LENGTH(pBtm)<=LENGTH(pTop)+LENGTH(pBtm-1) ) break; lnFrom--; lnTo--; p->aEdit[r]--; p->aEdit[r+3]++; @@ -1733,11 +1687,11 @@ /* Shift deletions toward the end of the file */ while( r+3nEdit && p->aEdit[r+3]>0 && del>0 && ins==0 ){ DLine *pTop = &p->aFrom[lnFrom]; /* First line deleted */ DLine *pBtm = &p->aFrom[lnFrom+del]; /* First line past end of delete */ - if( p->same_fn(pTop, pBtm)==0 ) break; + if( same_dline(pTop, pBtm)==0 ) break; if( LENGTH(pTop)+LENGTH(pBtm-1)<=LENGTH(pTop)+LENGTH(pBtm) ) break; lnFrom++; lnTo++; p->aEdit[r]++; p->aEdit[r+3]--; @@ -1799,33 +1753,26 @@ Blob *pB_Blob, /* TO file */ Blob *pOut, /* Write diff here if not NULL */ ReCompiled *pRe, /* Only output changes where this Regexp matches */ u64 diffFlags /* DIFF_* flags defined above */ ){ - int ignoreWs; /* Ignore whitespace */ + int ignoreEolWs; /* Ignore whitespace at the end of lines */ DContext c; if( diffFlags & DIFF_INVERT ){ Blob *pTemp = pA_Blob; pA_Blob = pB_Blob; pB_Blob = pTemp; } - ignoreWs = (diffFlags & DIFF_IGNORE_ALLWS)!=0; - blob_to_utf8_no_bom(pA_Blob, 0); - blob_to_utf8_no_bom(pB_Blob, 0); + ignoreEolWs = (diffFlags & DIFF_IGNORE_EOLWS)!=0; /* Prepare the input files */ memset(&c, 0, sizeof(c)); - if( (diffFlags & DIFF_IGNORE_ALLWS)==DIFF_IGNORE_ALLWS ){ - c.same_fn = same_dline_ignore_allws; - }else{ - c.same_fn = same_dline; - } c.aFrom = break_into_lines(blob_str(pA_Blob), blob_size(pA_Blob), - &c.nFrom, diffFlags); + &c.nFrom, ignoreEolWs); c.aTo = break_into_lines(blob_str(pB_Blob), blob_size(pB_Blob), - &c.nTo, diffFlags); + &c.nTo, ignoreEolWs); if( c.aFrom==0 || c.aTo==0 ){ fossil_free(c.aFrom); fossil_free(c.aTo); if( pOut ){ diff_errmsg(pOut, DIFF_CANNOT_COMPUTE_BINARY, diffFlags); @@ -1833,27 +1780,20 @@ return 0; } /* Compute the difference */ diff_all(&c); - if( ignoreWs && c.nEdit==6 && c.aEdit[1]==0 && c.aEdit[2]==0 ){ - fossil_free(c.aFrom); - fossil_free(c.aTo); - fossil_free(c.aEdit); - if( pOut ) diff_errmsg(pOut, DIFF_WHITESPACE_ONLY, diffFlags); - return 0; - } if( (diffFlags & DIFF_NOTTOOBIG)!=0 ){ int i, m, n; int *a = c.aEdit; int mx = c.nEdit; for(i=m=n=0; i10000 ){ fossil_free(c.aFrom); fossil_free(c.aTo); fossil_free(c.aEdit); - if( pOut ) diff_errmsg(pOut, DIFF_TOO_MANY_CHANGES, diffFlags); + diff_errmsg(pOut, DIFF_TOO_MANY_CHANGES, diffFlags); return 0; } } if( (diffFlags & DIFF_NOOPT)==0 ){ diff_optimize(&c); @@ -1882,36 +1822,24 @@ /* ** Process diff-related command-line options and return an appropriate ** "diffFlags" integer. ** -** --brief Show filenames only DIFF_BRIEF -** -c|--context N N lines of context. DIFF_CONTEXT_MASK -** --html Format for HTML DIFF_HTML -** --invert Invert the diff DIFF_INVERT -** -n|--linenum Show line numbers DIFF_LINENO -** --noopt Disable optimization DIFF_NOOPT -** --strip-trailing-cr Strip trailing CR DIFF_STRIP_EOLCR -** --unified Unified diff. ~DIFF_SIDEBYSIDE -** -w|--ignore-all-space Ignore all whitespaces DIFF_IGNORE_ALLWS -** -W|--width N N character lines. DIFF_WIDTH_MASK -** -y|--side-by-side Side-by-side diff. DIFF_SIDEBYSIDE -** -Z|--ignore-trailing-space Ignore eol-whitespaces DIFF_IGNORE_EOLWS +** --brief Show filenames only DIFF_BRIEF +** --context|-c N N lines of context. DIFF_CONTEXT_MASK +** --html Format for HTML DIFF_HTML +** --invert Invert the diff DIFF_INVERT +** --linenum|-n Show line numbers DIFF_LINENO +** --noopt Disable optimization DIFF_NOOPT +** --side-by-side|-y Side-by-side diff. DIFF_SIDEBYSIDE +** --unified Unified diff. ~DIFF_SIDEBYSIDE +** --width|-W N N character lines. DIFF_WIDTH_MASK */ u64 diff_options(void){ u64 diffFlags = 0; const char *z; int f; - if( find_option("ignore-trailing-space","Z",0)!=0 ){ - diffFlags = DIFF_IGNORE_EOLWS; - } - if( find_option("ignore-all-space","w",0)!=0 ){ - diffFlags = DIFF_IGNORE_ALLWS; /* stronger than DIFF_IGNORE_EOLWS */ - } - if( find_option("strip-trailing-cr",0,0)!=0 ){ - diffFlags |= DIFF_STRIP_EOLCR; - } if( find_option("side-by-side","y",0)!=0 ) diffFlags |= DIFF_SIDEBYSIDE; if( find_option("unified",0,0)!=0 ) diffFlags &= ~DIFF_SIDEBYSIDE; if( (z = find_option("context","c",1))!=0 && (f = atoi(z))>=0 ){ if( f > DIFF_CONTEXT_MASK ) f = DIFF_CONTEXT_MASK; diffFlags |= f + DIFF_CONTEXT_EX; @@ -2000,11 +1928,11 @@ typedef struct Annotator Annotator; struct Annotator { DContext c; /* The diff-engine context */ struct AnnLine { /* Lines of the original files... */ const char *z; /* The text of the line */ - short int n; /* Number of bytes (omitting trailing \n) */ + short int n; /* Number of bytes (omitting trailing space and \n) */ short int iVers; /* Level at which tag was set */ } *aOrig; int nOrig; /* Number of elements in aOrig[] */ int nVers; /* Number of versions analyzed */ int bLimit; /* True if the iLimit was reached */ @@ -2022,28 +1950,22 @@ /* ** Initialize the annotation process by specifying the file that is ** to be annotated. The annotator takes control of the input Blob and ** will release it when it is finished with it. */ -static int annotation_start(Annotator *p, Blob *pInput, u64 diffFlags){ +static int annotation_start(Annotator *p, Blob *pInput){ int i; memset(p, 0, sizeof(*p)); - if( (diffFlags & DIFF_IGNORE_ALLWS)==DIFF_IGNORE_ALLWS ){ - p->c.same_fn = same_dline_ignore_allws; - }else{ - p->c.same_fn = same_dline; - } - p->c.aTo = break_into_lines(blob_str(pInput), blob_size(pInput),&p->c.nTo, - diffFlags); + p->c.aTo = break_into_lines(blob_str(pInput), blob_size(pInput),&p->c.nTo,1); if( p->c.aTo==0 ){ return 1; } p->aOrig = fossil_malloc( sizeof(p->aOrig[0])*p->c.nTo ); for(i=0; ic.nTo; i++){ p->aOrig[i].z = p->c.aTo[i].z; - p->aOrig[i].n = p->c.aTo[i].n; + p->aOrig[i].n = p->c.aTo[i].h & LENGTH_MASK; p->aOrig[i].iVers = -1; } p->nOrig = p->c.nTo; return 0; } @@ -2053,17 +1975,17 @@ ** being annotated. Do another step of the annotation. Return true ** if additional annotation is required. zPName is the tag to insert ** on each line of the file being annotated that was contributed by ** pParent. Memory to hold zPName is leaked. */ -static int annotation_step(Annotator *p, Blob *pParent, int iVers, u64 diffFlags){ +static int annotation_step(Annotator *p, Blob *pParent, int iVers){ int i, j; int lnTo; /* Prepare the parent file to be diffed */ p->c.aFrom = break_into_lines(blob_str(pParent), blob_size(pParent), - &p->c.nFrom, diffFlags); + &p->c.nFrom, 1); if( p->c.aFrom==0 ){ return 1; } /* Compute the differences going from pParent to the file being @@ -2096,13 +2018,13 @@ /* Return no errors */ return 0; } -/* Annotation flags (any DIFF flag can be used as Annotation flag as well) */ -#define ANN_FILE_VERS (((u64)0x20)<<32) /* Show file vers rather than commit vers */ -#define ANN_FILE_ANCEST (((u64)0x40)<<32) /* Prefer check-ins in the ANCESTOR table */ +/* Annotation flags */ +#define ANN_FILE_VERS 0x01 /* Show file vers rather than commit vers */ +#define ANN_FILE_ANCEST 0x02 /* Prefer check-ins in the ANCESTOR table */ /* ** Compute a complete annotation on a file. The file is identified ** by its filename number (filename.fnid) and the baseline in which ** it was checked in (mlink.mid). @@ -2110,11 +2032,11 @@ static void annotate_file( Annotator *p, /* The annotator */ int fnid, /* The name of the file to be annotated */ int mid, /* Use the version of the file in this check-in */ int iLimit, /* Limit the number of levels if greater than zero */ - u64 annFlags /* Flags to alter the annotation */ + int annFlags /* Flags to alter the annotation */ ){ Blob toAnnotate; /* Text of the final (mid) version of the file */ Blob step; /* Text of previous revision */ int rid; /* Artifact ID of the file being annotated */ Stmt q; /* Query returning all ancestor versions */ @@ -2128,12 +2050,11 @@ } if( !content_get(rid, &toAnnotate) ){ fossil_fatal("unable to retrieve content of artifact #%d", rid); } if( iLimit<=0 ) iLimit = 1000000000; - blob_to_utf8_no_bom(&toAnnotate, 0); - annotation_start(p, &toAnnotate, annFlags); + annotation_start(p, &toAnnotate); db_begin_transaction(); db_multi_exec( "CREATE TEMP TABLE IF NOT EXISTS vseen(rid INTEGER PRIMARY KEY);" "DELETE FROM vseen;" ); @@ -2163,12 +2084,11 @@ p->aVers[p->nVers].zMUuid = fossil_strdup(db_column_text(&q, 1)); p->aVers[p->nVers].zDate = fossil_strdup(db_column_text(&q, 2)); p->aVers[p->nVers].zUser = fossil_strdup(db_column_text(&q, 3)); if( p->nVers ){ content_get(rid, &step); - blob_to_utf8_no_bom(&step, 0); - annotation_step(p, &step, p->nVers-1, annFlags); + annotation_step(p, &step, p->nVers-1); blob_reset(&step); } p->nVers++; db_bind_int(&ins, ":rid", rid); db_step(&ins); @@ -2189,11 +2109,10 @@ */ unsigned gradient_color(unsigned c1, unsigned c2, int n, int i){ unsigned c; /* Result color */ unsigned x1, x2; if( i==0 || n==0 ) return c1; - else if(i>=n) return c2; x1 = (c1>>16)&0xff; x2 = (c2>>16)&0xff; c = (x1*(n-i) + x2*i)/n<<16 & 0xff0000; x1 = (c1>>8)&0xff; x2 = (c2>>8)&0xff; @@ -2205,11 +2124,10 @@ } /* ** WEBPAGE: annotate ** WEBPAGE: blame -** WEBPAGE: praise ** ** Query parameters: ** ** checkin=ID The manifest ID at which to start the annotation ** filename=FILENAME The filename. @@ -2220,35 +2138,31 @@ void annotation_page(void){ int mid; int fnid; int i; int iLimit; /* Depth limit */ - u64 annFlags = (ANN_FILE_ANCEST|DIFF_STRIP_EOLCR); + int annFlags = ANN_FILE_ANCEST; int showLog = 0; /* True to display the log */ - int ignoreWs = 0; /* Ignore whitespace */ const char *zFilename; /* Name of file to annotate */ const char *zCI; /* The check-in containing zFilename */ Annotator ann; HQuery url; struct AnnVers *p; unsigned clr1, clr2, clr; - int bBlame = g.zPath[0]!='a';/* True for BLAME output. False for ANNOTATE. */ + int bBlame = g.zPath[0]=='b';/* True for BLAME output. False for ANNOTATE. */ /* Gather query parameters */ showLog = atoi(PD("log","1")); login_check_credentials(); if( !g.perm.Read ){ login_needed(); return; } if( exclude_spiders("annotate") ) return; - load_control(); mid = name_to_typed_rid(PD("checkin","0"),"ci"); zFilename = P("filename"); fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename); if( mid==0 || fnid==0 ){ fossil_redirect_home(); } iLimit = atoi(PD("limit","20")); if( P("filevers") ) annFlags |= ANN_FILE_VERS; - ignoreWs = P("w")!=0; - if( ignoreWs ) annFlags |= DIFF_IGNORE_ALLWS; if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){ fossil_redirect_home(); } /* compute the annotation */ @@ -2256,29 +2170,17 @@ annotate_file(&ann, fnid, mid, iLimit, annFlags); zCI = ann.aVers[0].zMUuid; /* generate the web page */ style_header("Annotation For %h", zFilename); - if( bBlame ){ - url_initialize(&url, "blame"); - }else{ - url_initialize(&url, "annotate"); - } + url_initialize(&url, "annotate"); url_add_parameter(&url, "checkin", P("checkin")); url_add_parameter(&url, "filename", zFilename); if( iLimit!=20 ){ url_add_parameter(&url, "limit", sqlite3_mprintf("%d", iLimit)); } url_add_parameter(&url, "log", showLog ? "1" : "0"); - if( ignoreWs ){ - url_add_parameter(&url, "w", ""); - style_submenu_element("Show Whitespace Changes", "Show Whitespace Changes", - "%s", url_render(&url, "w", 0, 0, 0)); - }else{ - style_submenu_element("Ignore Whitespace", "Ignore Whitespace", - "%s", url_render(&url, "w", "", 0, 0)); - } if( showLog ){ style_submenu_element("Hide Log", "Hide Log", "%s", url_render(&url, "log", "0", 0, 0)); }else{ style_submenu_element("Show Log", "Show Log", @@ -2304,20 +2206,20 @@ clr2 = 0xb5e0ff; /* Older changes: blue (cold) */ } for(p=ann.aVers, i=0; iAncestors of %z(zLink)%h(zFilename) analyzed: @
      for(p=ann.aVers, i=0; i%s(p->zDate) - @ check-in %z(href("%R/info/%s",p->zMUuid))%.10s(p->zMUuid) - @ artifact %z(href("%R/artifact/%s",p->zFUuid))%.10s(p->zFUuid) + @ check-in %z(href("%R/info/%S",p->zMUuid))%.10s(p->zMUuid) + @ artifact %z(href("%R/artifact/%S",p->zFUuid))%.10s(p->zFUuid) @ #if 0 if( i>0 ){ char *zLink = xhref("target='infowindow'", "%R/fdiff?v1=%S&v2=%S&sbs=1", @@ -2334,18 +2236,18 @@ } @
    @
    } if( !ann.bLimit ){ - @

    Origin for each line in - @ %z(href("%R/finfo?name=%h&ci=%s", zFilename, zCI))%h(zFilename) - @ from check-in %z(href("%R/info/%s",zCI))%S(zCI):

    + @

    Origin for each line in + @ %z(href("%R/finfo?name=%h&ci=%S", zFilename, zCI))%h(zFilename) + @ from check-in %z(href("%R/info/%S",zCI))%S(zCI):

    iLimit = ann.nVers+10; }else{ @

    Lines added by the %d(iLimit) most recent ancestors of - @ %z(href("%R/finfo?name=%h&ci=%s", zFilename, zCI))%h(zFilename) - @ from check-in %z(href("%R/info/%s",zCI))%S(zCI):

    + @ %z(href("%R/finfo?name=%h&ci=%S", zFilename, zCI))%h(zFilename) + @ from check-in %z(href("%R/info/%S",zCI))%S(zCI): } @
       for(i=0; iann.nVers && iVers<0 ) iVers = ann.nVers-1;
     
         if( bBlame ){
           if( iVers>=0 ){
             struct AnnVers *p = ann.aVers+iVers;
    -        char *zLink = xhref("target='infowindow'", "%R/info/%s", p->zMUuid);
    +        char *zLink = xhref("target='infowindow'", "%R/info/%S", p->zMUuid);
             sqlite3_snprintf(sizeof(zPrefix), zPrefix,
                  ""
                  "%s%.10s %s %13.13s:",
                  p->zBgColor, zLink, p->zMUuid, p->zDate, p->zUser);
             fossil_free(zLink);
    @@ -2367,11 +2269,11 @@
             sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%36s", "");
           }
         }else{
           if( iVers>=0 ){
             struct AnnVers *p = ann.aVers+iVers;
    -        char *zLink = xhref("target='infowindow'", "%R/info/%s", p->zMUuid);
    +        char *zLink = xhref("target='infowindow'", "%R/info/%S", p->zMUuid);
             sqlite3_snprintf(sizeof(zPrefix), zPrefix,
                  ""
                  "%s%.10s %s %4d:",
                  p->zBgColor, zLink, p->zMUuid, p->zDate, i+1);
             fossil_free(zLink);
    @@ -2387,25 +2289,22 @@
     }
     
     /*
     ** COMMAND: annotate
     ** COMMAND: blame
    -** COMMAND: praise
     **
    -** %fossil (annotate|blame|praise) ?OPTIONS? FILENAME
    +** %fossil (annotate|blame) ?OPTIONS? FILENAME
     **
     ** Output the text of a file with markings to show when each line of
     ** the file was last modified.  The "annotate" command shows line numbers
    -** and omits the username.  The "blame" and "praise" commands show the user
    -** who made each checkin and omits the line number.
    +** and omits the username.  The "blame" command shows the user who made each
    +** checkin and omits the line number.
     **
     ** Options:
    -**   --filevers                 Show file version numbers rather than check-in versions
    -**   -l|--log                   List all versions analyzed
    -**   -n|--limit N               Only look backwards in time by N versions
    -**   -w|--ignore-all-space      Ignore white space when comparing lines
    -**   -Z|--ignore-trailing-space Ignore whitespace at line end
    +**   --filevers      Show file version numbers rather than check-in versions
    +**   -l|--log        List all versions analyzed
    +**   -n|--limit N    Only look backwards in time by N versions
     **
     ** See also: info, finfo, timeline
     */
     void annotate_cmd(void){
       int fnid;         /* Filename ID */
    @@ -2418,24 +2317,18 @@
       int i;            /* Loop counter */
       const char *zLimit; /* The value to the -n|--limit option */
       int iLimit;       /* How far back in time to look */
       int showLog;      /* True to show the log */
       int fileVers;     /* Show file version instead of check-in versions */
    -  u64 annFlags = 0; /* Flags to control annotation properties */
    +  int annFlags = 0; /* Flags to control annotation properties */
       int bBlame = 0;   /* True for BLAME output.  False for ANNOTATE. */
     
    -  bBlame = g.argv[1][0]!='a';
    +  bBlame = g.argv[1][0]=='b';
       zLimit = find_option("limit","n",1);
       if( zLimit==0 || zLimit[0]==0 ) zLimit = "-1";
       iLimit = atoi(zLimit);
       showLog = find_option("log","l",0)!=0;
    -  if( find_option("ignore-trailing-space","Z",0)!=0 ){
    -    annFlags = DIFF_IGNORE_EOLWS;
    -  }
    -  if( find_option("ignore-all-space","w",0)!=0 ){
    -    annFlags = DIFF_IGNORE_ALLWS; /* stronger than DIFF_IGNORE_EOLWS */
    -  }
       fileVers = find_option("filevers",0,0)!=0;
       db_must_be_within_tree();
       if( g.argc<3 ) {
         usage("FILENAME");
       }
    @@ -2460,11 +2353,11 @@
               " ORDER BY ancestor.generation ASC LIMIT 1",
               fid, fnid);
       if( mid==0 ){
         fossil_fatal("unable to find manifest");
       }
    -  annFlags |= (ANN_FILE_ANCEST|DIFF_STRIP_EOLCR);
    +  annFlags |= ANN_FILE_ANCEST;
       annotate_file(&ann, fnid, mid, iLimit, annFlags);
       if( showLog ){
         struct AnnVers *p;
         for(p=ann.aVers, i=0; iw*2 ) n1 = w*2;
    -      x = w*2+17 - (n1+2);
    -      z = mprintf("%.*c %.*s %.*c\n",
    -                 x/2, '=', n1, zLeft, (x+1)/2, '=');
    -    }else{
    -      if( w<20 ) w = 20;
    -      if( n1>w-10 ) n1 = w - 10;
    -      if( n2>w-10 ) n2 = w - 10;
    -      z = mprintf("%.*c %.*s %.*c versus %.*c %.*s %.*c\n",
    -                  (w-n1+10)/2, '=', n1, zLeft, (w-n1+1)/2, '=',
    -                  (w-n2)/2, '=', n2, zRight, (w-n2+1)/2, '=');
    -    }
    +    if( n1>w*2 ) n1 = w*2;
    +    x = w*2+17 - (n1+2);
    +    z = mprintf("%.*c %.*s %.*c\n",
    +                x/2, '=', n1, zLeft, (x+1)/2, '=');
       }else{
         z = mprintf("--- %s\n+++ %s\n", zLeft, zRight);
       }
       fossil_print("%s", z);
       fossil_free(z);
    @@ -608,13 +598,12 @@
     }
     
     /* A Tcl/Tk script used to render diff output.
     */
     static const char zDiffScript[] =
    -@ set prog {
     @ package require Tk
    -@
    +@ 
     @ array set CFG {
     @   TITLE      {Fossil Diff}
     @   LN_COL_BG  #dddddd
     @   LN_COL_FG  #444444
     @   TXT_COL_BG #ffffff
    @@ -628,97 +617,74 @@
     @   HR_PAD_TOP 4
     @   HR_PAD_BTM 8
     @   FN_BG      #444444
     @   FN_FG      #ffffff
     @   FN_PAD     5
    -@   ERR_FG     #ee0000
     @   PADX       5
     @   WIDTH      80
     @   HEIGHT     45
     @   LB_HEIGHT  25
     @ }
    -@
    +@ 
     @ if {![namespace exists ttk]} {
     @   interp alias {} ::ttk::scrollbar {} ::scrollbar
     @   interp alias {} ::ttk::menubutton {} ::menubutton
     @ }
    -@
    +@ 
     @ proc dehtml {x} {
     @   set x [regsub -all {<[^>]*>} $x {}]
     @   return [string map {& & < < > > ' ' " \"} $x]
     @ }
    -@
    +@ 
     @ proc cols {} {
     @   return [list .lnA .txtA .mkr .lnB .txtB]
     @ }
    -@
    +@ 
     @ proc colType {c} {
     @   regexp {[a-z]+} $c type
     @   return $type
     @ }
    -@
    -@ proc getLine {difftxt N iivar} {
    -@   upvar $iivar ii
    -@   if {$ii>=$N} {return -1}
    -@   set x [lindex $difftxt $ii]
    -@   incr ii
    -@   return $x
    -@ }
    -@
    +@ 
     @ proc readDiffs {fossilcmd} {
    -@   global difftxt
    -@   if {![info exists difftxt]} {
    -@     set in [open $fossilcmd r]
    -@     fconfigure $in -encoding utf-8
    -@     set difftxt [split [read $in] \n]
    -@     close $in
    -@   }
    -@   set N [llength $difftxt]
    -@   set ii 0
    +@   set in [open $fossilcmd r]
    +@   fconfigure $in -encoding utf-8
     @   set nDiffs 0
     @   array set widths {txt 0 ln 0 mkr 0}
    -@   while {[set line [getLine $difftxt $N ii]] != -1} {
    -@     set fn2 {}
    -@     if {![regexp {^=+ (.*?) =+ versus =+ (.*?) =+$} $line all fn fn2]
    -@      && ![regexp {^=+ (.*?) =+$} $line all fn]
    -@     } {
    +@   while {[gets $in line] != -1} {
    +@     if {![regexp {^=+\s+(.*?)\s+=+$} $line all fn]} {
     @       continue
     @     }
    -@     set errMsg ""
    -@     set line [getLine $difftxt $N ii]
    -@     if {[string compare -length 6 $line "]*>(.+)} $line - errMsg]} {
    +@     if {[string compare -length 6 [gets $in] " 1 ? [.txtA index end] : "1.0"}]
     @     .wfiles.lb insert end $fn
    -@
    +@     
     @     foreach c [cols] {
    +@       while {[gets $in] ne "
    "} continue
    +@       
     @       if {$nDiffs > 1} {
     @         $c insert end \n -
     @       }
     @       if {[colType $c] eq "txt"} {
     @         $c insert end $fn\n fn
    -@         if {$fn2!=""} {set fn $fn2}
     @       } else {
     @         $c insert end \n fn
     @       }
     @       $c insert end \n -
    -@
    -@       if {$errMsg ne ""} continue
    -@       while {[getLine $difftxt $N ii] ne "
    "} continue
    +@        
     @       set type [colType $c]
     @       set str {}
    -@       while {[set line [getLine $difftxt $N ii]] ne "
    "} { +@ while {[set line [gets $in]] ne "
    "} { @ set len [string length [dehtml $line]] @ if {$len > $widths($type)} { @ set widths($type) $len @ } @ append str $line\n @ } -@ +@ @ set re {([^<]*)} @ # Use \r as separator since it can't appear in the diff output (it gets @ # converted to a space). @ set str [regsub -all $re $str "\r\\1\r\\2\r"] @ foreach {pre class mid} [split $str \r] { @@ -727,17 +693,13 @@ @ } else { @ $c insert end [dehtml $pre] - @ } @ } @ } -@ -@ if {$errMsg ne ""} { -@ foreach c {.txtA .txtB} {$c insert end [string trim $errMsg] err} -@ foreach c [cols] {$c insert end \n -} -@ } @ } -@ +@ close $in +@ @ foreach c [cols] { @ set type [colType $c] @ if {$type ne "txt"} { @ $c config -width $widths($type) @ } @@ -745,19 +707,19 @@ @ } @ if {$nDiffs <= [.wfiles.lb cget -height]} { @ .wfiles.lb config -height $nDiffs @ grid remove .wfiles.sb @ } -@ +@ @ return $nDiffs @ } -@ +@ @ proc viewDiff {idx} { @ .txtA yview $idx @ .txtA xview moveto 0 @ } -@ +@ @ proc cycleDiffs {{reverse 0}} { @ if {$reverse} { @ set range [.txtA tag prevrange fn @0,0 1.0] @ if {$range eq ""} { @ viewDiff {fn.last -1c} @@ -771,36 +733,36 @@ @ } else { @ viewDiff [lindex $range 0] @ } @ } @ } -@ +@ @ proc xvis {col} { @ set view [$col xview] @ return [expr {[lindex $view 1]-[lindex $view 0]}] @ } -@ +@ @ proc scroll-x {args} { @ set c .txt[expr {[xvis .txtA] < [xvis .txtB] ? "A" : "B"}] @ eval $c xview $args @ } -@ +@ @ interp alias {} scroll-y {} .txtA yview -@ +@ @ proc noop {args} {} -@ +@ @ proc enableSync {axis} { @ update idletasks @ interp alias {} sync-$axis {} @ rename _sync-$axis sync-$axis @ } -@ +@ @ proc disableSync {axis} { @ rename sync-$axis _sync-$axis @ interp alias {} sync-$axis {} noop @ } -@ +@ @ proc sync-x {col first last} { @ disableSync x @ $col xview moveto [expr {$first*[xvis $col]/($last-$first)}] @ foreach side {A B} { @ set sb .sbx$side @@ -826,21 +788,21 @@ @ } else { @ grid remove .sby @ } @ enableSync y @ } -@ +@ @ wm withdraw . @ wm title . $CFG(TITLE) @ wm iconname . $CFG(TITLE) @ bind . exit @ bind . {after 0 exit} @ bind . {cycleDiffs; break} @ bind . <> {cycleDiffs 1; break} @ bind . { -@ event generate .bb.files <1> -@ event generate .bb.files +@ event generate .files <1> +@ event generate .files @ break @ } @ foreach {key axis args} { @ Up y {scroll -5 units} @ Down y {scroll 5 units} @@ -852,23 +814,22 @@ @ End y {moveto 1} @ } { @ bind . <$key> "scroll-$axis $args; break" @ bind . continue @ } -@ -@ frame .bb -@ ::ttk::menubutton .bb.files -text "Files" +@ +@ ::ttk::menubutton .files -text "Files" @ toplevel .wfiles @ wm withdraw .wfiles @ update idletasks @ wm transient .wfiles . @ wm overrideredirect .wfiles 1 @ listbox .wfiles.lb -width 0 -height $CFG(LB_HEIGHT) -activestyle none \ @ -yscroll {.wfiles.sb set} @ ::ttk::scrollbar .wfiles.sb -command {.wfiles.lb yview} @ grid .wfiles.lb .wfiles.sb -sticky ns -@ bind .bb.files <1> { +@ bind .files <1> { @ set x [winfo rootx %W] @ set y [expr {[winfo rooty %W]+[winfo height %W]}] @ wm geometry .wfiles +$x+$y @ wm deiconify .wfiles @ focus .wfiles.lb @@ -887,16 +848,16 @@ @ } @ bind .wfiles.lb { @ %W selection clear 0 end @ %W selection set @%x,%y @ } -@ +@ @ foreach {side syncCol} {A .txtB B .txtA} { @ set ln .ln$side @ text $ln @ $ln tag config - -justify right -@ +@ @ set txt .txt$side @ text $txt -width $CFG(WIDTH) -height $CFG(HEIGHT) -wrap none \ @ -xscroll "sync-x $syncCol" @ catch {$txt config -tabstyle wordprocessor} ;# Required for Tk>=8.5 @ foreach tag {add rm chng} { @@ -903,14 +864,13 @@ @ $txt tag config $tag -background $CFG([string toupper $tag]_BG) @ $txt tag lower $tag @ } @ $txt tag config fn -background $CFG(FN_BG) -foreground $CFG(FN_FG) \ @ -justify center -@ $txt tag config err -foreground $CFG(ERR_FG) @ } @ text .mkr -@ +@ @ foreach c [cols] { @ set keyPrefix [string toupper [colType $c]]_COL_ @ if {[tk windowingsystem] eq "win32"} {$c config -font {courier 9}} @ $c config -bg $CFG(${keyPrefix}BG) -fg $CFG(${keyPrefix}FG) -borderwidth 0 \ @ -padx $CFG(PADX) -yscroll sync-y @@ -918,86 +878,40 @@ @ -foreground $CFG(HR_FG) @ $c tag config fn -spacing1 $CFG(FN_PAD) -spacing3 $CFG(FN_PAD) @ bindtags $c ". $c Text all" @ bind $c <1> {focus %W} @ } -@ +@ @ ::ttk::scrollbar .sby -command {.txtA yview} -orient vertical @ ::ttk::scrollbar .sbxA -command {.txtA xview} -orient horizontal @ ::ttk::scrollbar .sbxB -command {.txtB xview} -orient horizontal @ frame .spacer -@ +@ @ if {[readDiffs $fossilcmd] == 0} { @ tk_messageBox -type ok -title $CFG(TITLE) -message "No changes" @ exit @ } @ update idletasks -@ -@ proc saveDiff {} { -@ set fn [tk_getSaveFile] -@ set out [open $fn wb] -@ puts $out "#!/usr/bin/tclsh\n#\n# Run this script using 'tclsh' or 'wish'" -@ puts $out "# to see the graphical diff.\n#" -@ puts $out "set fossilcmd {}" -@ puts $out "set prog [list $::prog]" -@ puts $out "set difftxt \173" -@ foreach e $::difftxt {puts $out [list $e]} -@ puts $out "\175" -@ puts $out "eval \$prog" -@ close $out -@ } -@ proc invertDiff {} { -@ global CFG -@ array set x [grid info .txtA] -@ if {$x(-column)==1} { -@ grid config .lnB -column 0 -@ grid config .txtB -column 1 -@ .txtB tag config add -background $CFG(RM_BG) -@ grid config .lnA -column 3 -@ grid config .txtA -column 4 -@ .txtA tag config rm -background $CFG(ADD_BG) -@ } else { -@ grid config .lnA -column 0 -@ grid config .txtA -column 1 -@ .txtA tag config rm -background $CFG(RM_BG) -@ grid config .lnB -column 3 -@ grid config .txtB -column 4 -@ .txtB tag config add -background $CFG(ADD_BG) -@ } -@ .mkr config -state normal -@ set clt [.mkr search -all < 1.0 end] -@ set cgt [.mkr search -all > 1.0 end] -@ foreach c $clt {.mkr replace $c "$c +1 chars" >} -@ foreach c $cgt {.mkr replace $c "$c +1 chars" <} -@ .mkr config -state disabled -@ } -@ ::ttk::button .bb.quit -text {Quit} -command exit -@ ::ttk::button .bb.invert -text {Invert} -command invertDiff -@ ::ttk::button .bb.save -text {Save As...} -command saveDiff -@ pack .bb.quit .bb.invert -side left -@ if {$fossilcmd!=""} {pack .bb.save -side left} -@ pack .bb.files -side left +@ @ grid rowconfigure . 1 -weight 1 @ grid columnconfigure . 1 -weight 1 @ grid columnconfigure . 4 -weight 1 -@ grid .bb -row 0 -columnspan 6 +@ grid .files -row 0 -columnspan 6 @ eval grid [cols] -row 1 -sticky nsew @ grid .sby -row 1 -column 5 -sticky ns @ grid .sbxA -row 2 -columnspan 2 -sticky ew @ grid .spacer -row 2 -column 2 @ grid .sbxB -row 2 -column 3 -columnspan 2 -sticky ew @ @ .spacer config -height [winfo height .sbxA] @ wm deiconify . -@ } -@ eval $prog ; /* ** Show diff output in a Tcl/Tk window, in response to the --tk option ** to the diff command. -** +** ** If fossil has direct access to a Tcl interpreter (either loaded ** dynamically through stubs or linked in statically), we can use it ** directly. Otherwise: ** (1) Write the Tcl/Tk script used for rendering into a temp file. ** (2) Invoke "tclsh" on the temp file using fossil_system(). @@ -1024,17 +938,12 @@ i++; zTempFile = g.argv[i]; continue; } } - if( sqlite3_strglob("*}*",z) ){ - blob_appendf(&script, " {%/}", z); - }else{ - int j; - blob_append(&script, " ", 1); - for(j=0; z[j]; j++) blob_appendf(&script, "\\%03o", (unsigned char)z[j]); - } + blob_append(&script, " ", 1); + shell_escape(&script, z); } blob_appendf(&script, "}\n%s", zDiffScript); if( zTempFile ){ blob_write_to_file(&script, zTempFile); fossil_print("To see diff, run: tclsh \"%s\"\n", zTempFile); @@ -1096,11 +1005,11 @@ ** specified (as they exist on disk) and that same file as it was checked ** out. Or if the FILE arguments are omitted, show the unsaved changed ** currently in the working check-out. ** ** If the "--from VERSION" or "-r VERSION" option is used it specifies -** the source check-in for the diff operation. If not specified, the +** the source check-in for the diff operation. If not specified, the ** source check-in is the base check-in for the current check-out. ** ** If the "--to VERSION" option appears, it specifies the check-in from ** which the second version of the file or files is taken. If there is ** no "--to" option then the (possibly edited) files in the current check-out @@ -1120,26 +1029,23 @@ ** The "--binary" option causes files matching the glob PATTERN to be treated ** as binary when considering if they should be used with external diff program. ** This option overrides the "binary-glob" setting. ** ** Options: -** --binary PATTERN Treat files that match the glob PATTERN as binary -** --branch BRANCH Show diff of all changes on BRANCH -** --brief Show filenames only -** --context|-c N Use N lines of context -** --diff-binary BOOL Include binary files when using external commands -** --from|-r VERSION select VERSION as source for the diff -** --internal|-i use internal diff logic -** --side-by-side|-y side-by-side diff -** --strip-trailing-cr Strip trailing CR -** --tk Launch a Tcl/Tk GUI for display -** --to VERSION select VERSION as target for the diff -** --unified unified diff -** -v|--verbose output complete text of added or deleted files -** -w|--ignore-all-space Ignore white space when comparing lines -** -W|--width Width of lines in side-by-side diff -** -Z|--ignore-trailing-space Ignore changes to end-of-line whitespace +** --binary PATTERN Treat files that match the glob PATTERN as binary +** --branch BRANCH Show diff of all changes on BRANCH +** --brief Show filenames only +** --context|-c N Use N lines of context +** --diff-binary BOOL Include binary files when using external commands +** --from|-r VERSION select VERSION as source for the diff +** --internal|-i use internal diff logic +** --side-by-side|-y side-by-side diff +** --tk Launch a Tcl/Tk GUI for display +** --to VERSION select VERSION as target for the diff +** --unified unified diff +** -v|--verbose output complete text of added or deleted files +** -W|--width Width of lines in side-by-side diff */ void diff_cmd(void){ int isGDiff; /* True for gdiff. False for normal diff */ int isInternDiff; /* True for internal diff */ int verboseFlag; /* True if -v or --verbose flag is used */ @@ -1165,10 +1071,11 @@ verboseFlag = find_option("verbose","v",0)!=0; if( !verboseFlag ){ verboseFlag = find_option("new-file","N",0)!=0; /* deprecated */ } if( verboseFlag ) diffFlags |= DIFF_VERBOSE; + if( zBranch ){ if( zTo || zFrom ){ fossil_fatal("cannot use --from or --to with --branch"); } zTo = zBranch; Index: src/doc.c ================================================================== --- src/doc.c +++ src/doc.c @@ -483,11 +483,10 @@ if( content_get(rid, &filebody)==0 ){ goto doc_not_found; } db_end_transaction(0); } - blob_to_utf8_no_bom(&filebody, 0); /* The file is now contained in the filebody blob. Deliver the ** file to the user */ zMime = P("mimetype"); Index: src/event.c ================================================================== --- src/event.c +++ src/event.c @@ -185,11 +185,11 @@ blob_init(&comment, pEvent->zComment, -1); wiki_convert(&comment, 0, WIKI_INLINE); blob_reset(&comment); @ @
    - } + } wiki_convert(&tail, 0, 0); style_footer(); manifest_destroy(pEvent); } @@ -227,11 +227,11 @@ fossil_redirect_home(); return; } } zTag = mprintf("event-%s", zEventId); - rid = db_int(0, + rid = db_int(0, "SELECT rid FROM tagxref" " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)" " ORDER BY mtime DESC", zTag ); free(zTag); @@ -312,11 +312,11 @@ Stmt q; char *zBlob; /* Load the tags string into a blob */ blob_zero(&tags); - blob_append(&tags, zTags, -1); + blob_append(&tags, zTags, -1); /* Collapse all sequences of whitespace and "," characters into ** a single space character */ zBlob = blob_str(&tags); for(i=j=0; zBlob[i]; i++, j++){ @@ -341,13 +341,13 @@ db_prepare(&q, "SELECT x FROM newtags ORDER BY x"); while( db_step(&q)==SQLITE_ROW ){ blob_appendf(&event, "T +sym-%F *\n", db_column_text(&q, 0)); } db_finalize(&q); - } - if( !login_is_nobody() ){ - blob_appendf(&event, "U %F\n", login_name()); + } + if( g.zLogin ){ + blob_appendf(&event, "U %F\n", g.zLogin); } blob_appendf(&event, "W %d\n%s\n", strlen(zBody), zBody); md5sum_blob(&event, &cksum); blob_appendf(&event, "Z %b\n", &cksum); blob_reset(&cksum); @@ -411,27 +411,27 @@ @ @
    @ @ @ @ - + @ @ - + @ @ @ @ @ @ blob_reset(&projName); } @@ -665,74 +647,79 @@ style_header("Check-in Information"); login_anonymous_available(); } db_finalize(&q1); showTags(rid, ""); - @
    Changes
    - @
    - verboseFlag = g.zPath[0]!='c'; - if( db_get_boolean("show-version-diffs", 0)==0 ){ - verboseFlag = !verboseFlag; - zPage = "ci"; - zPageHide = "vinfo"; - } - diffFlags = construct_diff_flags(verboseFlag, sideBySide); - zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":""; - if( verboseFlag ){ - @ %z(xhref("class='button'","%R/%s/%T",zPageHide,zName)) - @ Hide Diffs - if( sideBySide ){ - @ %z(xhref("class='button'","%R/%s/%T?sbs=0%s",zPage,zName,zW)) - @ Unified Diffs - }else{ - @ %z(xhref("class='button'","%R/%s/%T?sbs=1%s",zPage,zName,zW)) - @ Side-by-Side Diffs - } - if( *zW ){ - @ %z(xhref("class='button'","%R/%s/%T?sbs=%d",zPage,zName,sideBySide)) - @ Show Whitespace Changes - }else{ - @ %z(xhref("class='button'","%R/%s/%T?sbs=%d&w",zPage,zName,sideBySide)) - @ Ignore Whitespace - } - }else{ - @ %z(xhref("class='button'","%R/%s/%T?sbs=0",zPage,zName)) - @ Show Unified Diffs - @ %z(xhref("class='button'","%R/%s/%T?sbs=1",zPage,zName)) - @ Show Side-by-Side Diffs - } if( zParent ){ - @ %z(xhref("class='button'","%R/vpatch?from=%s&to=%s",zParent,zUuid)) - @ Patch - } - @
    - if( pRe ){ - @

    Only differences that match regular expression "%h(zRe)" - @ are shown.

    - } - db_prepare(&q3, - "SELECT name," - " mperm," - " (SELECT uuid FROM blob WHERE rid=mlink.pid)," - " (SELECT uuid FROM blob WHERE rid=mlink.fid)," - " (SELECT name FROM filename WHERE filename.fnid=mlink.pfnid)" - " FROM mlink JOIN filename ON filename.fnid=mlink.fnid" - " WHERE mlink.mid=%d" - " AND (mlink.fid>0" - " OR mlink.fnid NOT IN (SELECT pfnid FROM mlink WHERE mid=%d))" - " ORDER BY name /*sort*/", - rid, rid - ); - while( db_step(&q3)==SQLITE_ROW ){ - const char *zName = db_column_text(&q3,0); - int mperm = db_column_int(&q3, 1); - const char *zOld = db_column_text(&q3,2); - const char *zNew = db_column_text(&q3,3); - const char *zOldName = db_column_text(&q3, 4); - append_file_change_line(zName, zOld, zNew, zOldName, diffFlags,pRe,mperm); - } - db_finalize(&q3); + @
    Changes
    + @
    + verboseFlag = g.zPath[0]!='c'; + if( db_get_boolean("show-version-diffs", 0)==0 ){ + verboseFlag = !verboseFlag; + if( verboseFlag ){ + @ %z(xhref("class='button'","%R/vinfo/%T",zName)) + @ hide diffs + if( sideBySide ){ + @ %z(xhref("class='button'","%R/ci/%T?sbs=0",zName)) + @ unified diffs + }else{ + @ %z(xhref("class='button'","%R/ci/%T?sbs=1",zName)) + @ side-by-side diffs + } + }else{ + @ %z(xhref("class='button'","%R/ci/%T?sbs=0",zName)) + @ show unified diffs + @ %z(xhref("class='button'","%R/ci/%T?sbs=1",zName)) + @ show side-by-side diffs + } + }else{ + if( verboseFlag ){ + @ %z(xhref("class='button'","%R/ci/%T",zName))hide diffs + if( sideBySide ){ + @ %z(xhref("class='button'","%R/info/%T?sbs=0",zName)) + @ unified diffs + }else{ + @ %z(xhref("class='button'","%R/info/%T?sbs=1",zName)) + @ side-by-side diffs + } + }else{ + @ %z(xhref("class='button'","%R/vinfo/%T?sbs=0",zName)) + @ show unified diffs + @ %z(xhref("class='button'","%R/vinfo/%T?sbs=1",zName)) + @ show side-by-side diffs + } + } + @ %z(xhref("class='button'","%R/vpatch?from=%S&to=%S",zParent,zUuid)) + @ patch
    + if( pRe ){ + @

    Only differences that match regular expression "%h(zRe)" + @ are shown.

    + } + db_prepare(&q3, + "SELECT name," + " mperm," + " (SELECT uuid FROM blob WHERE rid=mlink.pid)," + " (SELECT uuid FROM blob WHERE rid=mlink.fid)," + " (SELECT name FROM filename WHERE filename.fnid=mlink.pfnid)" + " FROM mlink JOIN filename ON filename.fnid=mlink.fnid" + " WHERE mlink.mid=%d" + " AND (mlink.fid>0" + " OR mlink.fnid NOT IN (SELECT pfnid FROM mlink WHERE mid=%d))" + " ORDER BY name /*sort*/", + rid, rid + ); + diffFlags = construct_diff_flags(verboseFlag, sideBySide); + while( db_step(&q3)==SQLITE_ROW ){ + const char *zName = db_column_text(&q3,0); + int mperm = db_column_int(&q3, 1); + const char *zOld = db_column_text(&q3,2); + const char *zNew = db_column_text(&q3,3); + const char *zOldName = db_column_text(&q3, 4); + append_file_change_line(zName, zOld, zNew, zOldName, diffFlags,pRe,mperm); + } + db_finalize(&q3); + } append_diff_javascript(sideBySide); style_footer(); } /* @@ -770,11 +757,11 @@ } } style_header("Update of \"%h\"", pWiki->zWikiTitle); zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); zDate = db_text(0, "SELECT datetime(%.17g)", pWiki->rDate); - style_submenu_element("Raw", "Raw", "artifact/%s", zUuid); + style_submenu_element("Raw", "Raw", "artifact/%S", zUuid); style_submenu_element("History", "History", "whistory?name=%t", pWiki->zWikiTitle); style_submenu_element("Page", "Page", "wiki?name=%t", pWiki->zWikiTitle); login_anonymous_available(); @@ -798,11 +785,11 @@ if( pWiki->nParent>0 ){ int i; @ } @
    Timeline Comment: - @ @
    Background Color: render_color_chooser(0, zClr, 0, "clr", "cclr"); @
    Tags: @ @
    Page Content: - @ @
    @ Index: src/file.c ================================================================== --- src/file.c +++ src/file.c @@ -393,36 +393,19 @@ FILE *in, *out; int got; char zBuf[8192]; in = fossil_fopen(zFrom, "rb"); if( in==0 ) fossil_fatal("cannot open \"%s\" for reading", zFrom); - file_mkfolder(zTo, 0); out = fossil_fopen(zTo, "wb"); if( out==0 ) fossil_fatal("cannot open \"%s\" for writing", zTo); while( (got=fread(zBuf, 1, sizeof(zBuf), in))>0 ){ fwrite(zBuf, 1, got, out); } fclose(in); fclose(out); } -/* -** COMMAND: test-file-copy -** -** Usage: %fossil test-file-copy SOURCE DESTINATION -** -** Make a copy of the file at SOURCE into a new name DESTINATION. Any -** directories in the path leading up to DESTINATION that do not already -** exist are created automatically. -*/ -void test_file_copy(void){ - if( g.argc!=4 ){ - fossil_fatal("Usage: %s test-file-copy SOURCE DESTINATION", g.argv[0]); - } - file_copy(g.argv[2], g.argv[3]); -} - /* ** Set or clear the execute bit on a file. Return true if a change ** occurred and false if this routine is a no-op. */ int file_wd_setexe(const char *zFilename, int onoff){ @@ -534,45 +517,10 @@ return rc; } return 0; } -/* -** Create the tree of directories in which zFilename belongs, if that sequence -** of directories does not already exist. -*/ -void file_mkfolder(const char *zFilename, int forceFlag){ - int i, nName; - char *zName; - - nName = strlen(zFilename); - zName = mprintf("%s", zFilename); - nName = file_simplify_name(zName, nName, 0); - for(i=1; i3 && !memcmp(z, "//?/", 4) ){ - if( fossil_strnicmp(z+4,"UNC", 3) ){ - i += 4; - z[0] = z[4]; - }else{ - i += 6; - z[0] = '/'; - } + for(i=0; i1 && z[n-1]=='/' ){ n--; } } /* Remove duplicate '/' characters. Except, two // at the beginning ** of a pathname is allowed since this is important on windows. */ - for(j=1; i0 && zLocalRoot[nLocalRoot-1]=='/' ); file_canonical_name(zOrigName, &full, 0); @@ -1064,11 +998,11 @@ }else{ xCmp = fossil_strnicmp; } /* Special case. zOrigName refers to g.zLocalRoot directory. */ - if( (nFull==nLocalRoot-1 && xCmp(zLocalRoot, zFull, nFull)==0) + if( (nFull==nLocalRoot-1 && xCmp(zLocalRoot, zFull, nFull)==0) || (nFull==1 && zFull[0]=='/' && nLocalRoot==1 && zLocalRoot[0]=='/') ){ blob_append(pOut, ".", 1); blob_reset(&localRoot); blob_reset(&full); return 1; @@ -1098,11 +1032,10 @@ ** a boolean: "yes", "no", "true", "false", etc. */ void cmd_test_tree_name(void){ int i; Blob x; - db_find_and_open_repository(0,0); blob_zero(&x); capture_case_sensitive_option(); for(i=2; i0 AND tagid=%d" " AND tagxref.rid=mlink.mid)" " WHEN 'trunk' THEN event.mtime-10000 ELSE event.mtime END)", TAG_BRANCH); @@ -374,11 +374,11 @@ } blob_reset(&sql); blob_zero(&title); if( baseCheckin ){ char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", baseCheckin); - char *zLink = href("%R/info/%s", zUuid); + char *zLink = href("%R/info/%S", zUuid); blob_appendf(&title, "Ancestors of file "); hyperlinked_path(zFilename, &title, zUuid, "tree", ""); blob_appendf(&title, " from check-in %z%.10s", zLink, zUuid); fossil_free(zUuid); }else{ @@ -404,10 +404,12 @@ const char *zBr = db_column_text(&q, 9); int fmid = db_column_int(&q, 10); int pfnid = db_column_int(&q, 11); int gidx; char zTime[10]; + char zShort[20]; + char zShortCkin[20]; if( zBr==0 ) zBr = "trunk"; if( uBg ){ zBgClr = hash_color(zUser); }else if( brBg || zBgClr==0 || zBgClr[0]==0 ){ zBgClr = strcmp(zBr,"trunk")==0 ? "" : hash_color(zBr); @@ -428,10 +430,12 @@ if( zBgClr && zBgClr[0] ){ @ }else{ @ } + sqlite3_snprintf(sizeof(zShort), zShort, "%.10s", zUuid); + sqlite3_snprintf(sizeof(zShortCkin), zShortCkin, "%.10s", zCkin); if( zUuid ){ if( fpid==0 ){ @ Added }else if( pfnid ){ char *zPrevName = db_text(0, "SELECT name FROM filename WHERE fnid=%d", @@ -454,23 +458,23 @@ fossil_free(zNewName); }else{ @ Deleted by check-in } } - hyperlink_to_uuid(zCkin); + hyperlink_to_uuid(zShortCkin); @ %w(zCom) (user: hyperlink_to_user(zUser, zDate, ""); @ branch: %h(zBr)) if( g.perm.Hyperlink && zUuid ){ const char *z = zFilename; - @ %z(href("%R/annotate?filename=%h&checkin=%s",z,zCkin)) + @ %z(href("%R/annotate?checkin=%S&filename=%h",zCkin,z)) @ [annotate] - @ %z(href("%R/blame?filename=%h&checkin=%s",z,zCkin)) + @ %z(href("%R/blame?checkin=%S&filename=%h",zCkin,z)) @ [blame] - @ %z(href("%R/timeline?n=200&uf=%s",zUuid))[checkins using] + @ %z(href("%R/timeline?n=200&uf=%S",zUuid))[checkins using] if( fpid ){ - @ %z(href("%R/fdiff?sbs=1&v1=%s&v2=%s",zPUuid,zUuid))[diff] + @ %z(href("%R/fdiff?v1=%S&v2=%S&sbs=1",zPUuid,zUuid))[diff] } } if( fDebug & FINFO_DEBUG_MLINK ){ int srcid = db_int(0, "SELECT srcid FROM delta WHERE rid=%d", frid); int sz = db_int(0, "SELECT length(content) FROM blob WHERE rid=%d", frid); Index: src/glob.c ================================================================== --- src/glob.c +++ src/glob.c @@ -154,11 +154,71 @@ ** characters. ** ** [^...] Matches one character not in the enclosed list. */ int strglob(const char *zGlob, const char *z){ - return sqlite3_strglob(zGlob, z)==0; + int c, c2; + int invert; + int seen; + + while( (c = (*(zGlob++)))!=0 ){ + if( c=='*' ){ + while( (c=(*(zGlob++))) == '*' || c=='?' ){ + if( c=='?' && (*(z++))==0 ) return 0; + } + if( c==0 ){ + return 1; + }else if( c=='[' ){ + while( *z && strglob(zGlob-1,z)==0 ){ + z++; + } + return (*z)!=0; + } + while( (c2 = (*(z++)))!=0 ){ + while( c2!=c ){ + c2 = *(z++); + if( c2==0 ) return 0; + } + if( strglob(zGlob,z) ) return 1; + } + return 0; + }else if( c=='?' ){ + if( (*(z++))==0 ) return 0; + }else if( c=='[' ){ + int prior_c = 0; + seen = 0; + invert = 0; + c = *(z++); + if( c==0 ) return 0; + c2 = *(zGlob++); + if( c2=='^' ){ + invert = 1; + c2 = *(zGlob++); + } + if( c2==']' ){ + if( c==']' ) seen = 1; + c2 = *(zGlob++); + } + while( c2 && c2!=']' ){ + if( c2=='-' && zGlob[0]!=']' && zGlob[0]!=0 && prior_c>0 ){ + c2 = *(zGlob++); + if( c>=prior_c && c<=c2 ) seen = 1; + prior_c = 0; + }else{ + if( c==c2 ){ + seen = 1; + } + prior_c = c2; + } + c2 = *(zGlob++); + } + if( c2==0 || (seen ^ invert)==0 ) return 0; + }else{ + if( c!=(*(z++)) ) return 0; + } + } + return *z==0; } /* ** Return true (non-zero) if zString matches any of the patterns in ** the Glob. The value returned is actually a 1-based index of the pattern @@ -168,11 +228,11 @@ */ int glob_match(Glob *pGlob, const char *zString){ int i; if( pGlob==0 ) return 0; for(i=0; inPattern; i++){ - if( sqlite3_strglob(pGlob->azPattern[i], zString)==0 ) return i+1; + if( strglob(pGlob->azPattern[i], zString) ) return i+1; } return 0; } /* Index: src/gzip.c ================================================================== --- src/gzip.c +++ src/gzip.c @@ -73,11 +73,11 @@ */ #define GZIP_BUFSZ 100000 void gzip_step(const char *pIn, int nIn){ char *zOutBuf; int nOut; - + nOut = nIn + nIn/10 + 100; if( nOut<100000 ) nOut = 100000; zOutBuf = fossil_malloc(nOut); gzip.stream.avail_in = nIn; gzip.stream.next_in = (unsigned char*)pIn; Index: src/http.c ================================================================== --- src/http.c +++ src/http.c @@ -19,26 +19,10 @@ */ #include "config.h" #include "http.h" #include -#ifdef _WIN32 -#include -#ifndef isatty -#define isatty(d) _isatty(d) -#endif -#ifndef fileno -#define fileno(s) _fileno(s) -#endif -#endif - -/* Maximum number of HTTP Authorization attempts */ -#define MAX_HTTP_AUTH 2 - -/* Keep track of HTTP Basic Authorization failures */ -static int fSeenHttpAuth = 0; - /* ** Construct the "login" card with the client credentials. ** ** login LOGIN NONCE SIGNATURE ** @@ -55,32 +39,38 @@ const char *zPw; /* The user password */ Blob pw; /* The nonce with user password appended */ Blob sig; /* The signature field */ blob_zero(pLogin); - if( g.url.user==0 || fossil_strcmp(g.url.user, "anonymous")==0 ){ + if( g.urlUser==0 || fossil_strcmp(g.urlUser, "anonymous")==0 ){ return; /* If no login card for users "nobody" and "anonymous" */ } - if( g.url.isSsh ){ + if( g.urlIsSsh ){ return; /* If no login card for SSH: */ } blob_zero(&nonce); blob_zero(&pw); sha1sum_blob(pPayload, &nonce); blob_copy(&pw, &nonce); - zLogin = g.url.user; - if( g.url.passwd ){ - zPw = g.url.passwd; + zLogin = g.urlUser; + if( g.urlPasswd ){ + zPw = g.urlPasswd; }else if( g.cgiOutput ){ /* Password failure while doing a sync from the web interface */ cgi_printf("*** incorrect or missing password for user %h\n", zLogin); zPw = 0; }else{ /* Password failure while doing a sync from the command-line interface */ url_prompt_for_password(); - zPw = g.url.passwd; + zPw = g.urlPasswd; } + + /* If the first character of the password is "#", then that character is + ** not really part of the password - it is an indicator that we should + ** use Basic Authentication. So skip that character. + */ + if( zPw && zPw[0]=='#' ) zPw++; /* The login card wants the SHA1 hash of the password, so convert the ** password to its SHA1 hash it it isn't already a SHA1 hash. */ /* fossil_print("\nzPw=[%s]\n", zPw); // TESTING ONLY */ @@ -102,98 +92,38 @@ static void http_build_header(Blob *pPayload, Blob *pHdr){ int i; const char *zSep; blob_zero(pHdr); - i = strlen(g.url.path); - if( i>0 && g.url.path[i-1]=='/' ){ + i = strlen(g.urlPath); + if( i>0 && g.urlPath[i-1]=='/' ){ zSep = ""; }else{ zSep = "/"; } - blob_appendf(pHdr, "POST %s%sxfer/xfer HTTP/1.0\r\n", g.url.path, zSep); - if( g.url.proxyAuth ){ - blob_appendf(pHdr, "Proxy-Authorization: %s\r\n", g.url.proxyAuth); + blob_appendf(pHdr, "POST %s%sxfer/xfer HTTP/1.0\r\n", g.urlPath, zSep); + if( g.urlProxyAuth ){ + blob_appendf(pHdr, "Proxy-Authorization: %s\r\n", g.urlProxyAuth); } - if( g.zHttpAuth && g.zHttpAuth[0] ){ - const char *zCredentials = g.zHttpAuth; + if( g.urlPasswd && g.urlUser && g.urlPasswd[0]=='#' ){ + char *zCredentials = mprintf("%s:%s", g.urlUser, &g.urlPasswd[1]); char *zEncoded = encode64(zCredentials, -1); blob_appendf(pHdr, "Authorization: Basic %s\r\n", zEncoded); fossil_free(zEncoded); + fossil_free(zCredentials); } - blob_appendf(pHdr, "Host: %s\r\n", g.url.hostname); + blob_appendf(pHdr, "Host: %s\r\n", g.urlHostname); blob_appendf(pHdr, "User-Agent: %s\r\n", get_user_agent()); - if( g.url.isSsh ) blob_appendf(pHdr, "X-Fossil-Transport: SSH\r\n"); + if( g.urlIsSsh ) blob_appendf(pHdr, "X-Fossil-Transport: SSH\r\n"); if( g.fHttpTrace ){ blob_appendf(pHdr, "Content-Type: application/x-fossil-debug\r\n"); }else{ blob_appendf(pHdr, "Content-Type: application/x-fossil\r\n"); } blob_appendf(pHdr, "Content-Length: %d\r\n\r\n", blob_size(pPayload)); } -/* -** Use Fossil credentials for HTTP Basic Authorization prompt -*/ -static int use_fossil_creds_for_httpauth_prompt(void){ - Blob x; - char c; - prompt_user("Use Fossil username and password (y/N)? ", &x); - c = blob_str(&x)[0]; - blob_reset(&x); - return ( c=='y' || c=='Y' ); -} - -/* -** Prompt to save HTTP Basic Authorization information -*/ -static int save_httpauth_prompt(void){ - Blob x; - char c; - if( (g.url.flags & URL_REMEMBER)==0 ) return 0; - prompt_user("Remember Basic Authorization credentials (Y/n)? ", &x); - c = blob_str(&x)[0]; - blob_reset(&x); - return ( c!='n' && c!='N' ); -} - -/* -** Get the HTTP Basic Authorization credentials from the user -** when 401 is received. -*/ -char *prompt_for_httpauth_creds(void){ - Blob x; - char *zUser; - char *zPw; - char *zPrompt; - char *zHttpAuth = 0; - if( !isatty(fileno(stdin)) ) return 0; - zPrompt = mprintf("\n%s authorization required by\n%s\n", - g.url.isHttps==1 ? "Encrypted HTTPS" : "Unencrypted HTTP", g.url.canonical); - fossil_print(zPrompt); - free(zPrompt); - if ( g.url.user && g.url.passwd && use_fossil_creds_for_httpauth_prompt() ){ - zHttpAuth = mprintf("%s:%s", g.url.user, g.url.passwd); - }else{ - prompt_user("Basic Authorization user: ", &x); - zUser = mprintf("%b", &x); - zPrompt = mprintf("HTTP password for %b: ", &x); - blob_reset(&x); - prompt_for_password(zPrompt, &x, 1); - zPw = mprintf("%b", &x); - zHttpAuth = mprintf("%s:%s", zUser, zPw); - free(zUser); - free(zPw); - free(zPrompt); - blob_reset(&x); - } - if( save_httpauth_prompt() ){ - set_httpauth(zHttpAuth); - } - return zHttpAuth; -} - /* ** Sign the content in pSend, compress it, and send it to the server ** via HTTP or HTTPS. Get a reply, uncompress the reply, and store the reply ** in pRecv. pRecv is assumed to be uninitialized when ** this routine is called - this routine will initialize it. @@ -213,12 +143,12 @@ char *zLine; /* A single line of the reply header */ int i; /* Loop counter */ int isError = 0; /* True if the reply is an error message */ int isCompressed = 1; /* True if the reply is compressed */ - if( transport_open(&g.url) ){ - fossil_warning(transport_errmsg(&g.url)); + if( transport_open(GLOBAL_URL()) ){ + fossil_warning(transport_errmsg(GLOBAL_URL())); return 1; } /* Construct the login card and prepare the complete payload */ blob_zero(&login); @@ -260,35 +190,25 @@ } /* ** Send the request to the server. */ - transport_send(&g.url, &hdr); - transport_send(&g.url, &payload); + transport_send(GLOBAL_URL(), &hdr); + transport_send(GLOBAL_URL(), &payload); blob_reset(&hdr); blob_reset(&payload); - transport_flip(&g.url); + transport_flip(GLOBAL_URL()); /* ** Read and interpret the server reply */ closeConnection = 1; iLength = -1; - while( (zLine = transport_receive_line(&g.url))!=0 && zLine[0]!=0 ){ + while( (zLine = transport_receive_line(GLOBAL_URL()))!=0 && zLine[0]!=0 ){ /* printf("[%s]\n", zLine); fflush(stdout); */ if( fossil_strnicmp(zLine, "http/1.", 7)==0 ){ if( sscanf(zLine, "HTTP/1.%d %d", &iHttpVersion, &rc)!=2 ) goto write_err; - if( rc==401 ){ - if( fSeenHttpAuth++ < MAX_HTTP_AUTH ){ - if( g.zHttpAuth ){ - if( g.zHttpAuth ) free(g.zHttpAuth); - } - g.zHttpAuth = prompt_for_httpauth_creds(); - transport_close(&g.url); - return http_exchange(pSend, pReply, useLogin, maxRedirect); - } - } if( rc!=200 && rc!=302 ){ int ii; for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){} while( zLine[ii]==' ' ) ii++; fossil_warning("server says: %s", &zLine[ii]); @@ -297,11 +217,11 @@ if( iHttpVersion==0 ){ closeConnection = 1; }else{ closeConnection = 0; } - }else if( g.url.isSsh && fossil_strnicmp(zLine, "status:", 7)==0 ){ + }else if( g.urlIsSsh && fossil_strnicmp(zLine, "status:", 7)==0 ){ if( sscanf(zLine, "Status: %d", &rc)!=1 ) goto write_err; if( rc!=200 && rc!=302 ){ int ii; for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){} while( zLine[ii]==' ' ) ii++; @@ -334,14 +254,11 @@ j -= 4; zLine[j] = 0; } fossil_print("redirect to %s\n", &zLine[i]); url_parse(&zLine[i], 0); - fSeenHttpAuth = 0; - if( g.zHttpAuth ) free(g.zHttpAuth); - g.zHttpAuth = get_httpauth(); - transport_close(&g.url); + transport_close(GLOBAL_URL()); return http_exchange(pSend, pReply, useLogin, maxRedirect); }else if( fossil_strnicmp(zLine, "content-type: ", 14)==0 ){ if( fossil_strnicmp(&zLine[14], "application/x-fossil-debug", -1)==0 ){ isCompressed = 0; }else if( fossil_strnicmp(&zLine[14], @@ -364,11 +281,11 @@ /* ** Extract the reply payload that follows the header */ blob_zero(pReply); blob_resize(pReply, iLength); - iLength = transport_receive(&g.url, blob_buffer(pReply), iLength); + iLength = transport_receive(GLOBAL_URL(), blob_buffer(pReply), iLength); blob_resize(pReply, iLength); if( isError ){ char *z; int i, j; z = blob_str(pReply); @@ -391,20 +308,20 @@ ** connection from remaining open. The easiest fix for now is to ** simply close and restart the connection for each round-trip. ** ** For SSH we will leave the connection open. */ - if( ! g.url.isSsh ) closeConnection = 1; /* FIX ME */ + if( ! g.urlIsSsh ) closeConnection = 1; /* FIX ME */ if( closeConnection ){ - transport_close(&g.url); + transport_close(GLOBAL_URL()); }else{ - transport_rewind(&g.url); + transport_rewind(GLOBAL_URL()); } return 0; /* ** Jump to here if an error is seen. */ write_err: - transport_close(&g.url); + transport_close(GLOBAL_URL()); return 1; } Index: src/http_socket.c ================================================================== --- src/http_socket.c +++ src/http_socket.c @@ -124,14 +124,14 @@ } } /* ** Open a socket connection. The identify of the server is determined -** by pUrlData +** by global variables that are set using url_parse(): ** -** pUrlDAta->name Name of the server. Ex: www.fossil-scm.org -** pUrlDAta->port TCP/IP port to use. Ex: 80 +** g.urlName Name of the server. Ex: www.fossil-scm.org +** g.urlPort TCP/IP port to use. Ex: 80 ** ** Return the number of errors. */ int socket_open(UrlData *pUrlData){ static struct sockaddr_in addr; /* The server address */ @@ -212,14 +212,13 @@ } return total; } /* -** Attempt to resolve pUrlData->name to an IP address and setup g.zIpAddr -** so rcvfrom gets populated. For hostnames with more than one IP (or -** if overridden in ~/.ssh/config) the rcvfrom may not match the host -** to which we connect. +** Attempt to resolve g.urlName to IP and setup g.zIpAddr so rcvfrom gets +** populated. For hostnames with more than one IP (or if overridden in +** ~/.ssh/config) the rcvfrom may not match the host to which we connect. */ void socket_ssh_resolve_addr(UrlData *pUrlData){ struct hostent *pHost; /* Used to make best effort for rcvfrom */ struct sockaddr_in addr; Index: src/http_ssl.c ================================================================== --- src/http_ssl.c +++ src/http_ssl.c @@ -174,64 +174,16 @@ (void)BIO_reset(iBio); BIO_free_all(iBio); } } -/* See RFC2817 for details */ -static int establish_proxy_tunnel(UrlData *pUrlData, BIO *bio){ - int rc, httpVerMin; - char *bbuf; - Blob snd, reply; - int done=0,end=0; - blob_zero(&snd); - blob_appendf(&snd, "CONNECT %s:%d HTTP/1.1\r\n", pUrlData->hostname, - pUrlData->proxyOrigPort); - blob_appendf(&snd, "Host: %s:%d\r\n", pUrlData->hostname, pUrlData->proxyOrigPort); - if( pUrlData->proxyAuth ){ - blob_appendf(&snd, "Proxy-Authorization: %s\r\n", pUrlData->proxyAuth); - } - blob_append(&snd, "Proxy-Connection: keep-alive\r\n", -1); - blob_appendf(&snd, "User-Agent: %s\r\n", get_user_agent()); - blob_append(&snd, "\r\n", 2); - BIO_write(bio, blob_buffer(&snd), blob_size(&snd)); - blob_reset(&snd); - - /* Wait for end of reply */ - blob_zero(&reply); - do{ - int len; - char buf[256]; - len = BIO_read(bio, buf, sizeof(buf)); - blob_append(&reply, buf, len); - - bbuf = blob_buffer(&reply); - len = blob_size(&reply); - while(end < len) { - if(bbuf[end] == '\r') { - if(len - end < 4) { - /* need more data */ - break; - } - if(memcmp(&bbuf[end], "\r\n\r\n", 4) == 0) { - done = 1; - break; - } - } - end++; - } - }while(!done); - sscanf(bbuf, "HTTP/1.%d %d", &httpVerMin, &rc); - blob_reset(&reply); - return rc; -} - /* ** Open an SSL connection. The identify of the server is determined -** as follows: +** by global variables that are set using url_parse(): ** -** g.url.name Name of the server. Ex: www.fossil-scm.org -** pUrlData->port TCP/IP port to use. Ex: 80 +** g.urlName Name of the server. Ex: www.fossil-scm.org +** g.urlPort TCP/IP port to use. Ex: 80 ** ** Return the number of errors. */ int ssl_open(UrlData *pUrlData){ X509 *cert; @@ -249,67 +201,41 @@ X509_STORE_add_cert(SSL_CTX_get_cert_store(sslCtx), cert); X509_free(cert); hasSavedCertificate = 1; } - if( pUrlData->useProxy ){ - int rc; - BIO *sBio; - char *connStr; - connStr = mprintf("%s:%d", g.url.name, pUrlData->port); - sBio = BIO_new_connect(connStr); - free(connStr); - if( BIO_do_connect(sBio)<=0 ){ - ssl_set_errmsg("SSL: cannot connect to proxy %s:%d (%s)", - pUrlData->name, pUrlData->port, ERR_reason_error_string(ERR_get_error())); - ssl_close(); - return 1; - } - rc = establish_proxy_tunnel(pUrlData, sBio); - if( rc<200||rc>299 ){ - ssl_set_errmsg("SSL: proxy connect failed with HTTP status code %d", rc); - return 1; - } - - pUrlData->path = pUrlData->proxyUrlPath; - - iBio = BIO_new_ssl(sslCtx, 1); - BIO_push(iBio, sBio); - }else{ - iBio = BIO_new_ssl_connect(sslCtx); - } - if( iBio==NULL ) { - ssl_set_errmsg("SSL: cannot open SSL (%s)", - ERR_reason_error_string(ERR_get_error())); - return 1; - } + iBio = BIO_new_ssl_connect(sslCtx); BIO_get_ssl(iBio, &ssl); #if (SSLEAY_VERSION_NUMBER >= 0x00908070) && !defined(OPENSSL_NO_TLSEXT) - if( !SSL_set_tlsext_host_name(ssl, (pUrlData->useProxy?pUrlData->hostname:pUrlData->name)) ){ + if( !SSL_set_tlsext_host_name(ssl, pUrlData->name) ){ fossil_warning("WARNING: failed to set server name indication (SNI), " "continuing without it.\n"); } #endif SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); - - if( !pUrlData->useProxy ){ - BIO_set_conn_hostname(iBio, pUrlData->name); - BIO_set_conn_int_port(iBio, &pUrlData->port); - if( BIO_do_connect(iBio)<=0 ){ - ssl_set_errmsg("SSL: cannot connect to host %s:%d (%s)", - pUrlData->name, pUrlData->port, ERR_reason_error_string(ERR_get_error())); - ssl_close(); - return 1; - } + if( iBio==NULL ) { + ssl_set_errmsg("SSL: cannot open SSL (%s)", + ERR_reason_error_string(ERR_get_error())); + return 1; + } + + BIO_set_conn_hostname(iBio, pUrlData->name); + BIO_set_conn_int_port(iBio, &pUrlData->port); + + if( BIO_do_connect(iBio)<=0 ){ + ssl_set_errmsg("SSL: cannot connect to host %s:%d (%s)", + pUrlData->name, pUrlData->port, + ERR_reason_error_string(ERR_get_error())); + ssl_close(); + return 1; } if( BIO_do_handshake(iBio)<=0 ) { ssl_set_errmsg("Error establishing SSL connection %s:%d (%s)", - pUrlData->useProxy?pUrlData->hostname:pUrlData->name, - pUrlData->useProxy?pUrlData->proxyOrigPort:pUrlData->port, + pUrlData->name, pUrlData->port, ERR_reason_error_string(ERR_get_error())); ssl_close(); return 1; } /* Check if certificate is valid */ @@ -357,11 +283,11 @@ " certificates list\n\n" "If you are not expecting this message, answer no and " "contact your server\nadministrator.\n\n" "Accept certificate for host %s (a=always/y/N)? ", X509_verify_cert_error_string(e), desc, warning, - pUrlData->useProxy?pUrlData->hostname:pUrlData->name); + pUrlData->name); BIO_free(mem); prompt_user(prompt, &ans); free(prompt); cReply = blob_str(&ans)[0]; @@ -407,38 +333,36 @@ mem = BIO_new(BIO_s_mem()); PEM_write_bio_X509(mem, cert); BIO_write(mem, "", 1); /* nul-terminate mem buffer */ BIO_get_mem_data(mem, &zCert); - zHost = mprintf("cert:%s", pUrlData->useProxy?pUrlData->hostname:pUrlData->name); + zHost = mprintf("cert:%s", pUrlData->name); db_set(zHost, zCert, 1); free(zHost); - zHost = mprintf("trusted:%s", pUrlData->useProxy?pUrlData->hostname:pUrlData->name); + zHost = mprintf("trusted:%s", pUrlData->name); db_set_int(zHost, trusted, 1); free(zHost); BIO_free(mem); } /* -** Get certificate for pUrlData->urlName from global config. +** Get certificate for g.urlName from global config. ** Return NULL if no certificate found. */ X509 *ssl_get_certificate(UrlData *pUrlData, int *pTrusted){ char *zHost, *zCert; BIO *mem; X509 *cert; - zHost = mprintf("cert:%s", - pUrlData->useProxy ? pUrlData->hostname : pUrlData->name); + zHost = mprintf("cert:%s", pUrlData->name); zCert = db_get(zHost, NULL); free(zHost); if ( zCert==NULL ) return NULL; if ( pTrusted!=0 ){ - zHost = mprintf("trusted:%s", - pUrlData->useProxy ? pUrlData->hostname : pUrlData->name); + zHost = mprintf("trusted:%s", pUrlData->name); *pTrusted = db_get_int(zHost, 0); free(zHost); } mem = BIO_new(BIO_s_mem()); Index: src/http_transport.c ================================================================== --- src/http_transport.c +++ src/http_transport.c @@ -138,15 +138,15 @@ return sshPid==0; } /* ** Open a connection to the server. The server is defined by the following -** variables: +** global variables: ** -** pUrlData->name Name of the server. Ex: www.fossil-scm.org -** pUrlData->port TCP/IP port. Ex: 80 -** pUrlData->isHttps Use TLS for the connection +** g.urlName Name of the server. Ex: www.fossil-scm.org +** g.urlPort TCP/IP port. Ex: 80 +** g.urlIsHttps Use TLS for the connection ** ** Return the number of errors. */ int transport_open(UrlData *pUrlData){ int rc = 0; Index: src/import.c ================================================================== --- src/import.c +++ src/import.c @@ -575,37 +575,22 @@ fossil_free(gg.zMark); gg.zMark = fossil_strdup(&zLine[5]); }else if( memcmp(zLine, "tagger ", 7)==0 || memcmp(zLine, "committer ",10)==0 ){ sqlite3_int64 secSince1970; - int hastz; - char tzdir; - int tz; for(i=0; zLine[i] && zLine[i]!='<'; i++){} if( zLine[i]==0 ) goto malformed_line; z = &zLine[i+1]; for(i=i+1; zLine[i] && zLine[i]!='>'; i++){} if( zLine[i]==0 ) goto malformed_line; zLine[i] = 0; fossil_free(gg.zUser); gg.zUser = fossil_strdup(z); secSince1970 = 0; - - /* We don't use sscanf here because of int64 portability issues. */ for(i=i+2; fossil_isdigit(zLine[i]); i++){ secSince1970 = secSince1970*10 + zLine[i] - '0'; } - - /* Read in optional timezone modifier (we don't know if it's strictly - * optional, but better to be sure). */ - tzdir = '+'; - tz = 0; - hastz = sscanf(&zLine[i], " %c%d", &tzdir, &tz); - if ((hastz == 1) || (hastz > 2)) goto malformed_line; - secSince1970 += ((tzdir == '-') ? -1 : 1) * - ((tz/100)*3600 + (tz%100)*60); - fossil_free(gg.zDate); gg.zDate = db_text(0, "SELECT datetime(%lld, 'unixepoch')", secSince1970); gg.zDate[10] = 'T'; }else if( memcmp(zLine, "from ", 5)==0 ){ Index: src/info.c ================================================================== --- src/info.c +++ src/info.c @@ -109,26 +109,10 @@ fossil_print("%-13s %s %s\n", zType, zUuid, zDate); free(zDate); } db_finalize(&q); } - if( zUuid ){ - fossil_print("%-13s ", "leaf:"); - if(is_a_leaf(rid)){ - if(db_int(0, "SELECT 1 FROM tagxref AS tx" - " WHERE tx.rid=%d" - " AND tx.tagid=%d" - " AND tx.tagtype>0", - rid, TAG_CLOSED)){ - fossil_print("%s\n", "closed"); - }else{ - fossil_print("%s\n", "open"); - } - }else{ - fossil_print("no\n"); - } - } zTags = info_tags_of_checkin(rid, 0); if( zTags && zTags[0] ){ fossil_print("tags: %s\n", zTags); } free(zTags); @@ -399,11 +383,11 @@ } if( diffFlags ){ append_diff(zOld, zNew, diffFlags, pRe); }else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){ @    - @ %z(href("%R/fdiff?v1=%s&v2=%s&sbs=1",zOld,zNew))[diff] + @ %z(href("%R/fdiff?v1=%S&v2=%S&sbs=1",zOld,zNew))[diff] } } } /* @@ -443,36 +427,37 @@ /* ** Construct an appropriate diffFlag for text_diff() based on query ** parameters and the to boolean arguments. */ u64 construct_diff_flags(int verboseFlag, int sideBySide){ - u64 diffFlags = 0; /* Zero means do not show any diff */ - if( verboseFlag!=0 ){ + u64 diffFlags; + if( verboseFlag==0 ){ + diffFlags = 0; /* Zero means do not show any diff */ + }else{ int x; if( sideBySide ){ - diffFlags = DIFF_SIDEBYSIDE; + diffFlags = DIFF_SIDEBYSIDE | DIFF_IGNORE_EOLWS; /* "dw" query parameter determines width of each column */ x = atoi(PD("dw","80"))*(DIFF_CONTEXT_MASK+1); if( x<0 || x>DIFF_WIDTH_MASK ) x = DIFF_WIDTH_MASK; diffFlags += x; + }else{ + diffFlags = DIFF_INLINE | DIFF_IGNORE_EOLWS; } - if( P("w") ){ - diffFlags |= DIFF_IGNORE_ALLWS; - } /* "dc" query parameter determines lines of context */ x = atoi(PD("dc","7")); if( x<0 || x>DIFF_CONTEXT_MASK ) x = DIFF_CONTEXT_MASK; diffFlags += x; /* The "noopt" parameter disables diff optimization */ if( PD("noopt",0)!=0 ) diffFlags |= DIFF_NOOPT; - diffFlags |= DIFF_STRIP_EOLCR; } return diffFlags; } + /* ** WEBPAGE: vinfo ** WEBPAGE: ci ** URL: /ci?name=RID|ARTIFACTID @@ -497,13 +482,10 @@ const char *zName; /* Name of the checkin to be displayed */ const char *zUuid; /* UUID of zName */ const char *zParent; /* UUID of the parent checkin (if any) */ const char *zRe; /* regex parameter */ ReCompiled *pRe = 0; /* regex */ - const char *zW; /* URL param for ignoring whitespace */ - const char *zPage = "vinfo"; /* Page that shows diffs */ - const char *zPageHide = "ci"; /* Page that hides diffs */ login_check_credentials(); if( !g.perm.Read ){ login_needed(); return; } zName = P("name"); rid = name_to_rid_www("name"); @@ -612,19 +594,19 @@ if( (zPJ[jj]>0 && zPJ[jj]<' ') || strchr("\"*/:<>?\\|", zPJ[jj]) ){ zPJ[jj] = '_'; } } @
    Timelines: - @ %z(href("%R/timeline?f=%s&unhide",zUuid))family + @ %z(href("%R/timeline?f=%S&unhide",zUuid))family if( zParent ){ - @ | %z(href("%R/timeline?p=%s&unhide",zUuid))ancestors + @ | %z(href("%R/timeline?p=%S&unhide",zUuid))ancestors } if( !isLeaf ){ - @ | %z(href("%R/timeline?d=%s&unhide",zUuid))descendants + @ | %z(href("%R/timeline?d=%S&unhide",zUuid))descendants } if( zParent && !isLeaf ){ - @ | %z(href("%R/timeline?dp=%s&unhide",zUuid))both + @ | %z(href("%R/timeline?dp=%S&unhide",zUuid))both } db_prepare(&q2,"SELECT substr(tag.tagname,5) FROM tagxref, tag " " WHERE rid=%d AND tagtype>0 " " AND tag.tagid=tagxref.tagid " " AND +tag.tagname GLOB 'sym-*'", rid); @@ -647,16 +629,16 @@ fossil_free(zUrl); } @
    Other Links: - @ %z(href("%R/tree?ci=%s",zUuid))files - @ | %z(href("%R/fileage?name=%s",zUuid))file ages - @ | %z(href("%R/tree?ci=%s&nofiles",zUuid))folders - @ | %z(href("%R/artifact/%s",zUuid))manifest + @ %z(href("%R/tree?ci=%S",zUuid))files + @ | %z(href("%R/fileage?name=%S",zUuid))file ages + @ | %z(href("%R/tree?ci=%S&nofiles",zUuid))folders + @ | %z(href("%R/artifact/%S",zUuid))manifest if( g.perm.Write ){ - @ | %z(href("%R/ci_edit?r=%s",zUuid))edit + @ | %z(href("%R/ci_edit?r=%S",zUuid))edit } @
    Parent%s(pWiki->nParent==1?"":"s"): for(i=0; inParent; i++){ char *zParent = pWiki->azParent[i]; - @ %z(href("info/%s",zParent))%s(zParent) + @ %z(href("info/%S",zParent))%s(zParent) } @
    @@ -930,16 +917,15 @@ ** WEBPAGE: vdiff ** URL: /vdiff ** ** Query parameters: ** -** from=TAG Left side of the comparison -** to=TAG Right side of the comparison -** branch=TAG Show all changes on a particular branch -** v=BOOLEAN Default true. If false, only list files that have changed -** sbs=BOOLEAN Side-by-side diff if true. Unified diff if false -** glob=STRING only diff files matching this glob +** from=TAG +** to=TAG +** branch=TAG +** v=BOOLEAN +** sbs=BOOLEAN ** ** ** Show all differences between two checkins. */ void vdiff_page(void){ @@ -951,17 +937,17 @@ ManifestFile *pFileFrom, *pFileTo; const char *zBranch; const char *zFrom; const char *zTo; const char *zRe; - const char *zW; const char *zVerbose; - const char *zGlob; ReCompiled *pRe = 0; + login_check_credentials(); if( !g.perm.Read ){ login_needed(); return; } login_anonymous_available(); + zRe = P("regex"); if( zRe ) re_compile(&pRe, zRe, 0); zBranch = P("branch"); if( zBranch && zBranch[0] ){ cgi_replace_parameter("from", mprintf("root:%s", zBranch)); @@ -979,61 +965,30 @@ if( !zVerbose ){ zVerbose = P("detail"); /* deprecated */ } verboseFlag = (zVerbose!=0) && !is_false(zVerbose); if( !verboseFlag && sideBySide ) verboseFlag = 1; - zGlob = P("glob"); zFrom = P("from"); zTo = P("to"); - if(zGlob && !*zGlob){ - zGlob = NULL; - } - diffFlags = construct_diff_flags(verboseFlag, sideBySide); - zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":""; if( sideBySide || verboseFlag ){ style_submenu_element("Hide Diff", "hidediff", - "%R/vdiff?from=%T&to=%T&sbs=0%s%T%s", - zFrom, zTo, - zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW); + "%R/vdiff?from=%T&to=%T&sbs=0", + zFrom, zTo); } if( !sideBySide ){ - style_submenu_element("Side-by-Side Diff", "sbsdiff", - "%R/vdiff?from=%T&to=%T&sbs=1%s%T%s", - zFrom, zTo, - zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW); + style_submenu_element("Side-by-side Diff", "sbsdiff", + "%R/vdiff?from=%T&to=%T&sbs=1", + zFrom, zTo); } if( sideBySide || !verboseFlag ) { style_submenu_element("Unified Diff", "udiff", - "%R/vdiff?from=%T&to=%T&sbs=0&v%s%T%s", - zFrom, zTo, - zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW); + "%R/vdiff?from=%T&to=%T&sbs=0&v", + zFrom, zTo); } style_submenu_element("Invert", "invert", - "%R/vdiff?from=%T&to=%T&sbs=%d%s%s%T%s", zTo, zFrom, - sideBySide, (verboseFlag && !sideBySide)?"&v":"", - zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW); - if( zGlob ){ - style_submenu_element("Clear glob", "clearglob", - "%R/vdiff?from=%T&to=%T&sbs=%d%s%s", zFrom, zTo, - sideBySide, (verboseFlag && !sideBySide)?"&v":"", zW); - }else{ - style_submenu_element("Patch", "patch", - "%R/vpatch?from=%T&to=%T%s", zFrom, zTo, zW); - } - if( sideBySide || verboseFlag ){ - if( *zW ){ - style_submenu_element("Show Whitespace Differences", "whitespace", - "%R/vdiff?from=%T&to=%T&sbs=%d%s%s%T", zFrom, zTo, - sideBySide, (verboseFlag && !sideBySide)?"&v":"", - zGlob ? "&glob=" : "", zGlob ? zGlob : ""); - }else{ - style_submenu_element("Ignore Whitespace", "ignorews", - "%R/vdiff?from=%T&to=%T&sbs=%d%s%s%T&w", zFrom, zTo, - sideBySide, (verboseFlag && !sideBySide)?"&v":"", - zGlob ? "&glob=" : "", zGlob ? zGlob : ""); - } - } + "%R/vdiff?from=%T&to=%T&sbs=%d%s", zTo, zFrom, + sideBySide, (verboseFlag && !sideBySide)?"&v":""); style_header("Check-in Differences"); @

    Difference From:

    checkin_description(ridFrom); @

    To:

    checkin_description(ridTo); @@ -1040,19 +995,17 @@ @
    if( pRe ){ @

    Only differences that match regular expression "%h(zRe)" @ are shown.

    } - if( zGlob ){ - @

    Only files matching the glob "%h(zGlob)" are shown.

    - } @

    manifest_file_rewind(pFrom); pFileFrom = manifest_file_next(pFrom, 0); manifest_file_rewind(pTo); pFileTo = manifest_file_next(pTo, 0); + diffFlags = construct_diff_flags(verboseFlag, sideBySide); while( pFileFrom || pFileTo ){ int cmp; if( pFileFrom==0 ){ cmp = +1; }else if( pFileTo==0 ){ @@ -1059,33 +1012,27 @@ cmp = -1; }else{ cmp = fossil_strcmp(pFileFrom->zName, pFileTo->zName); } if( cmp<0 ){ - if(!zGlob || strglob(zGlob, pFileFrom->zName)){ - append_file_change_line(pFileFrom->zName, - pFileFrom->zUuid, 0, 0, diffFlags, pRe, 0); - } + append_file_change_line(pFileFrom->zName, + pFileFrom->zUuid, 0, 0, diffFlags, pRe, 0); pFileFrom = manifest_file_next(pFrom, 0); }else if( cmp>0 ){ - if(!zGlob || strglob(zGlob, pFileTo->zName)){ - append_file_change_line(pFileTo->zName, - 0, pFileTo->zUuid, 0, diffFlags, pRe, - manifest_file_mperm(pFileTo)); - } + append_file_change_line(pFileTo->zName, + 0, pFileTo->zUuid, 0, diffFlags, pRe, + manifest_file_mperm(pFileTo)); pFileTo = manifest_file_next(pTo, 0); }else if( fossil_strcmp(pFileFrom->zUuid, pFileTo->zUuid)==0 ){ + /* No changes */ pFileFrom = manifest_file_next(pFrom, 0); pFileTo = manifest_file_next(pTo, 0); }else{ - if(!zGlob || (strglob(zGlob, pFileFrom->zName) - || strglob(zGlob, pFileTo->zName))){ - append_file_change_line(pFileFrom->zName, - pFileFrom->zUuid, - pFileTo->zUuid, 0, diffFlags, pRe, - manifest_file_mperm(pFileTo)); - } + append_file_change_line(pFileFrom->zName, + pFileFrom->zUuid, + pFileTo->zUuid, 0, diffFlags, pRe, + manifest_file_mperm(pFileTo)); pFileFrom = manifest_file_next(pFrom, 0); pFileTo = manifest_file_next(pTo, 0); } } manifest_destroy(pFrom); @@ -1188,14 +1135,14 @@ @ on branch %z(href("%R/timeline?r=%T",zBr))%h(zBr) } @ - %!w(zCom) (user: hyperlink_to_user(zUser,zDate,")"); if( g.perm.Hyperlink ){ - @ %z(href("%R/finfo?name=%T&ci=%s",zName,zVers))[ancestry] - @ %z(href("%R/annotate?filename=%T&checkin=%s",zName,zVers)) + @ %z(href("%R/finfo?name=%T&ci=%S",zName,zVers))[ancestry] + @ %z(href("%R/annotate?checkin=%S&filename=%T",zVers,zName)) @ [annotate] - @ %z(href("%R/blame?filename=%T&checkin=%s",zName,zVers)) + @ %z(href("%R/blame?checkin=%S&filename=%T",zVers,zName)) @ [blame] } cnt++; if( pDownloadName && blob_size(pDownloadName)==0 ){ blob_append(pDownloadName, zName, -1); @@ -1302,11 +1249,11 @@ @ Attachment "%h(zFilename)" to } objType |= OBJTYPE_ATTACHMENT; if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){ if( g.perm.Hyperlink && g.perm.RdTkt ){ - @ ticket [%z(href("%R/tktview?name=%s",zTarget))%S(zTarget)] + @ ticket [%z(href("%R/tktview?name=%S",zTarget))%S(zTarget)] }else{ @ ticket [%S(zTarget)] } }else{ if( g.perm.Hyperlink && g.perm.RdWiki ){ @@ -1328,11 +1275,11 @@ @ Control artifact. if( pDownloadName && blob_size(pDownloadName)==0 ){ blob_appendf(pDownloadName, "%.10s.txt", zUuid); } }else if( linkToView && g.perm.Hyperlink ){ - @ %z(href("%R/artifact/%s",zUuid))[view] + @ %z(href("%R/artifact/%S",zUuid))[view] } return objType; } @@ -1349,11 +1296,10 @@ int isPatch; int sideBySide; char *zV1; char *zV2; const char *zRe; - const char *zW; /* URL param for ignoring whitespace */ ReCompiled *pRe = 0; u64 diffFlags; login_check_credentials(); if( !g.perm.Read ){ login_needed(); return; } @@ -1380,41 +1326,31 @@ zV1 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v1); zV2 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v2); diffFlags = construct_diff_flags(1, sideBySide) | DIFF_HTML; style_header("Diff"); - zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":""; - if( *zW ){ - style_submenu_element("Show Whitespace Changes", "Show Whitespace Changes", - "%s/fdiff?v1=%T&v2=%T&sbs=%d", - g.zTop, P("v1"), P("v2"), sideBySide); - }else{ - style_submenu_element("Ignore Whitespace", "Ignore Whitespace", - "%s/fdiff?v1=%T&v2=%T&sbs=%d&w", - g.zTop, P("v1"), P("v2"), sideBySide); - } style_submenu_element("Patch", "Patch", "%s/fdiff?v1=%T&v2=%T&patch", g.zTop, P("v1"), P("v2")); if( !sideBySide ){ - style_submenu_element("Side-by-Side Diff", "sbsdiff", - "%s/fdiff?v1=%T&v2=%T&sbs=1%s", - g.zTop, P("v1"), P("v2"), zW); + style_submenu_element("Side-by-side Diff", "sbsdiff", + "%s/fdiff?v1=%T&v2=%T&sbs=1", + g.zTop, P("v1"), P("v2")); }else{ style_submenu_element("Unified Diff", "udiff", - "%s/fdiff?v1=%T&v2=%T&sbs=0%s", - g.zTop, P("v1"), P("v2"), zW); + "%s/fdiff?v1=%T&v2=%T&sbs=0", + g.zTop, P("v1"), P("v2")); } if( P("smhdr")!=0 ){ @

    Differences From Artifact - @ %z(href("%R/artifact/%s",zV1))[%S(zV1)] To - @ %z(href("%R/artifact/%s",zV2))[%S(zV2)].

    + @ %z(href("%R/artifact/%S",zV1))[%S(zV1)] To + @ %z(href("%R/artifact/%S",zV2))[%S(zV2)]. }else{ @

    Differences From - @ Artifact %z(href("%R/artifact/%s",zV1))[%S(zV1)]:

    + @ Artifact %z(href("%R/artifact/%S",zV1))[%S(zV1)]: object_description(v1, 0, 0); - @

    To Artifact %z(href("%R/artifact/%s",zV2))[%S(zV2)]:

    + @

    To Artifact %z(href("%R/artifact/%S",zV2))[%S(zV2)]:

    object_description(v2, 0, 0); } if( pRe ){ @ Only differences that match regular expression "%h(zRe)" @ are shown. @@ -1441,11 +1377,11 @@ rid = name_to_rid_www("name"); login_check_credentials(); if( !g.perm.Read ){ login_needed(); return; } if( rid==0 ) fossil_redirect_home(); zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); - if( fossil_strcmp(P("name"), zUuid)==0 && login_is_nobody() ){ + if( fossil_strcmp(P("name"), zUuid)==0 ){ g.isConst = 1; } free(zUuid); zMime = P("m"); if( zMime==0 ){ @@ -1719,12 +1655,11 @@ }else{ renderAsHtml = 1; style_submenu_element("Text", "Text", "%s/artifact/%s?txt=1", g.zTop, zUuid); } - }else if( fossil_strcmp(zMime, "text/x-fossil-wiki")==0 - || fossil_strcmp(zMime, "text/x-markdown")==0 ){ + }else if( fossil_strcmp(zMime, "text/x-fossil-wiki")==0 ){ if( asText ){ style_submenu_element("Wiki", "Wiki", "%s/artifact/%s", g.zTop, zUuid); }else{ renderAsWiki = 1; @@ -1737,37 +1672,37 @@ style_submenu_element("Parsed", "Parsed", "%R/info/%s", zUuid); } @
    content_get(rid, &content); if( renderAsWiki ){ - wiki_render_by_mimetype(&content, zMime); + wiki_convert(&content, 0, 0); }else if( renderAsHtml ){ @ }else{ style_submenu_element("Hex","Hex", "%s/hexdump?name=%s", g.zTop, zUuid); - blob_to_utf8_no_bom(&content, 0); zMime = mimetype_from_content(&content); @
    if( zMime==0 ){ const char *zLn = P("ln"); const char *z; + blob_to_utf8_no_bom(&content, 0); z = blob_str(&content); if( zLn ){ output_text_with_line_numbers(z, zLn); }else{ @
             @ %h(z)
             @ 
    } }else if( strncmp(zMime, "image/", 6)==0 ){ - @ + @ style_submenu_element("Image", "Image", - "%R/raw/%s?m=%s", zUuid, zMime); + "%R/raw/%S?m=%s", zUuid, zMime); }else{ @ (file is %d(blob_size(&content)) bytes of binary data) } @
    } @@ -1819,19 +1754,19 @@ } zTktTitle = db_table_has_column( "ticket", "title" ) ? db_text("(No title)", "SELECT title FROM ticket WHERE tkt_uuid=%Q", zTktName) : 0; style_header("Ticket Change Details"); - style_submenu_element("Raw", "Raw", "%R/artifact/%s", zUuid); + style_submenu_element("Raw", "Raw", "%R/artifact/%S", zUuid); style_submenu_element("History", "History", "%R/tkthistory/%s", zTktName); style_submenu_element("Page", "Page", "%R/tktview/%t", zTktName); style_submenu_element("Timeline", "Timeline", "%R/tkttimeline/%t", zTktName); if( P("plaintext") ){ - style_submenu_element("Formatted", "Formatted", "%R/info/%s", zUuid); + style_submenu_element("Formatted", "Formatted", "%R/info/%S", zUuid); }else{ style_submenu_element("Plaintext", "Plaintext", - "%R/info/%s?plaintext", zUuid); + "%R/info/%S?plaintext", zUuid); } @
    Overview
    @

    @ @@ -2261,11 +2196,11 @@ } db_finalize(&q); if( nChng>0 ){ int nrid; Blob cksum; - blob_appendf(&ctrl, "U %F\n", login_name()); + blob_appendf(&ctrl, "U %F\n", g.zLogin); md5sum_blob(&ctrl, &cksum); blob_appendf(&ctrl, "Z %b\n", &cksum); db_begin_transaction(); g.markPrivate = content_is_private(rid); nrid = content_put(&ctrl); @@ -2341,11 +2276,11 @@ } @

    Make changes to attributes of check-in @ [%z(href("%R/ci/%s",zUuid))%s(zUuid)]:

    form_begin(0, "%R/ci_edit"); login_insert_csrf_secret(); - @
    + @
    @
    Artifact ID:
    @ @ if( !fHasHidden ){ @ @ } if( !fHasClosed ){ Index: src/json.c ================================================================== --- src/json.c +++ src/json.c @@ -30,12 +30,12 @@ ** dispatch to a JSON-mode-specific command/page handler with the type fossil_json_f(). ** See the API docs for that typedef (below) for the semantics of the callbacks. ** ** */ -#include "VERSION.h" #include "config.h" +#include "VERSION.h" #include "json.h" #include #include #if INTERFACE @@ -1275,15 +1275,15 @@ INT(g, xlinkClusterOnly); INT(g, fTimeFormat); INT(g, markPrivate); INT(g, clockSkewSeen); INT(g, isHTTP); - INT(g.url, isFile); - INT(g.url, isHttps); - INT(g.url, isSsh); - INT(g.url, port); - INT(g.url, dfltPort); + INT(g, urlIsFile); + INT(g, urlIsHttps); + INT(g, urlIsSsh); + INT(g, urlPort); + INT(g, urlDfltPort); INT(g, useLocalauth); INT(g, noPswd); INT(g, userUid); INT(g, rcvid); INT(g, okCsrf); @@ -1299,19 +1299,19 @@ CSTR(g, zExtra); CSTR(g, zBaseURL); CSTR(g, zTop); CSTR(g, zContentType); CSTR(g, zErrMsg); - CSTR(g.url, name); - CSTR(g.url, hostname); - CSTR(g.url, protocol); - CSTR(g.url, path); - CSTR(g.url, user); - CSTR(g.url, passwd); - CSTR(g.url, canonical); - CSTR(g.url, proxyAuth); - CSTR(g.url, fossil); + CSTR(g, urlName); + CSTR(g, urlHostname); + CSTR(g, urlProtocol); + CSTR(g, urlPath); + CSTR(g, urlUser); + CSTR(g, urlPasswd); + CSTR(g, urlCanonical); + CSTR(g, urlProxyAuth); + CSTR(g, urlFossil); CSTR(g, zLogin); CSTR(g, zSSLIdentity); CSTR(g, zIpAddr); CSTR(g, zNonce); CSTR(g, zCsrfToken); Index: src/json_timeline.c ================================================================== --- src/json_timeline.c +++ src/json_timeline.c @@ -66,11 +66,11 @@ /* ** Create a temporary table suitable for storing timeline data. */ static void json_timeline_temp_table(void){ /* Field order MUST match that from json_timeline_query()!!! */ - static const char zSql[] = + static const char zSql[] = @ CREATE TEMP TABLE IF NOT EXISTS json_timeline( @ sortId INTEGER PRIMARY KEY, @ rid INTEGER, @ uuid TEXT, @ mtime INTEGER, @@ -109,11 +109,11 @@ @ (SELECT group_concat(substr(tagname,5), ',') FROM tag, tagxref @ WHERE tagname GLOB 'sym-*' AND tag.tagid=tagxref.tagid @ AND tagxref.rid=blob.rid AND tagxref.tagtype>0) as tags, @ tagid as tagId, @ brief as brief - @ FROM event JOIN blob + @ FROM event JOIN blob @ WHERE blob.rid=event.objid ; return zBaseSql; } @@ -316,11 +316,11 @@ */ cson_value * json_get_changed_files(int rid, int flags){ cson_value * rowsV = NULL; cson_array * rows = NULL; Stmt q = empty_Stmt; - db_prepare(&q, + db_prepare(&q, "SELECT (pid==0) AS isnew," " (fid==0) AS isdel," " (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name," " blob.uuid as uuid," " (SELECT uuid FROM blob WHERE rid=pid) as parent," Index: src/json_wiki.c ================================================================== --- src/json_wiki.c +++ src/json_wiki.c @@ -542,11 +542,11 @@ blob_init(&w1, pW1->zWiki, -1); blob_zero(&w2); blob_init(&w2, pW2->zWiki, -1); blob_zero(&d); - diffFlags = DIFF_IGNORE_EOLWS | DIFF_STRIP_EOLCR; + diffFlags = DIFF_IGNORE_EOLWS | DIFF_INLINE; text_diff(&w2, &w1, &d, 0, diffFlags); blob_reset(&w1); blob_reset(&w2); pay = cson_new_object(); DELETED src/loadctrl.c Index: src/loadctrl.c ================================================================== --- src/loadctrl.c +++ /dev/null @@ -1,65 +0,0 @@ -/* -** Copyright (c) 2014 D. Richard Hipp -** -** This program is free software; you can redistribute it and/or -** modify it under the terms of the Simplified BSD License (also -** known as the "2-Clause License" or "FreeBSD License".) - -** This program is distributed in the hope that it will be useful, -** but without any warranty; without even the implied warranty of -** merchantability or fitness for a particular purpose. -** -** Author contact information: -** drh@hwaci.com -** http://www.hwaci.com/drh/ -** -******************************************************************************* -** -** This file contains code to check the host load-average and abort -** CPU-intensive operations if the load-average is too high. -*/ -#include "config.h" -#include "loadctrl.h" -#include - -/* -** Return the load average for the host processor -*/ -double load_average(void){ -#if !defined(_WIN32) && !defined(FOSSIL_OMIT_LOAD_AVERAGE) - double a[3]; - if( getloadavg(a, 3)>0 ){ - return a[0]; - } -#endif - return 0.0; -} - -/* -** COMMAND: test-loadavg -** %fossil test-loadavg -** -** Print the load average on the host machine. -*/ -void loadavg_test_cmd(void){ - fossil_print("load-average: %f\n", load_average()); -} - -/* -** Abort the current operation of the load average of the host computer -** is too high. -*/ -void load_control(void){ - double mxLoad = atof(db_get("max-loadavg", "0")); - if( mxLoad<=0.0 || mxLoad>=load_average() ) return; - - style_header("Server Overload"); - @

    The server load is currently too high. - @ Please try again later.

    - @

    Current load average: %f(load_average()).
    - @ Load average limit: %f(mxLoad)

    - style_footer(); - cgi_set_status(503,"Server Overload"); - cgi_reply(); - exit(0); -} Index: src/login.c ================================================================== --- src/login.c +++ src/login.c @@ -41,11 +41,11 @@ ** logs and downloading diffs of very version of the archive that ** has ever existed, and things like that. */ #include "config.h" #include "login.h" -#if defined(_WIN32) +#if defined(_WIN32) # include /* for Sleep */ # if defined(__MINGW32__) || defined(_MSC_VER) # define sleep Sleep /* windows does not have sleep, but Sleep */ # endif #endif @@ -112,13 +112,13 @@ } } /* ** The IP address of the client is stored as part of login cookies. -** But some clients are behind firewalls that shift the IP address -** with each HTTP request. To allow such (broken) clients to log in, -** extract just a prefix of the IP address. +** But some clients are behind firewalls that shift the IP address +** with each HTTP request. To allow such (broken) clients to log in, +** extract just a prefix of the IP address. */ static char *ipPrefix(const char *zIP){ int i, j; static int ip_prefix_terms = -1; if( ip_prefix_terms<0 ){ @@ -344,11 +344,11 @@ */ void login_clear_login_data(){ if(!g.userUid){ return; }else{ - char const * cookie = login_cookie_name(); + char const * cookie = login_cookie_name(); /* To logout, change the cookie value to an empty string */ cgi_set_cookie(cookie, "", login_cookie_path(), -86400); db_multi_exec("UPDATE user SET cookie=NULL, ipaddr=NULL, " " cexpire=0 WHERE uid=%d" @@ -492,21 +492,21 @@ /* The user requests a password change */ zSha1Pw = sha1_shared_secret(zPasswd, g.zLogin, 0); if( db_int(1, "SELECT 0 FROM user" " WHERE uid=%d" " AND (constant_time_cmp(pw,%Q)=0" - " OR constant_time_cmp(pw,%Q)=0)", + " OR constant_time_cmp(pw,%Q)=0)", g.userUid, zSha1Pw, zPasswd) ){ sleep(1); - zErrMsg = + zErrMsg = @

    @ You entered an incorrect old password while attempting to change @ your password. Your password is unchanged. @

    ; }else if( fossil_strcmp(zNew1,zNew2)!=0 ){ - zErrMsg = + zErrMsg = @

    @ The two copies of your new passwords do not match. @ Your password is unchanged. @

    ; @@ -546,11 +546,11 @@ /* Attempting to log in as a user other than anonymous. */ uid = login_search_uid(zUsername, zPasswd); if( uid<=0 ){ sleep(1); - zErrMsg = + zErrMsg = @

    @ You entered an unknown user or an incorrect password. @

    ; record_login_attempt(zUsername, zIpAddr, 0); @@ -599,11 +599,11 @@ @
    @ @ @
    User: @ @@ -2437,11 +2372,11 @@ @ onkeyup="chgbn(this.value.trim(),'%h(zBranchName)')" />
    Branch Hiding: @ @
    - @ } /* ** Add a new element to the submenu @@ -308,11 +309,11 @@ Th_Store("manifest_date", MANIFEST_DATE); Th_Store("compiler_name", COMPILER_NAME); url_var("stylesheet", "css", "style.css"); image_url_var("logo"); image_url_var("background"); - if( !login_is_nobody() ){ + if( g.zLogin ){ Th_Store("login", g.zLogin); } if( g.thTrace ) Th_Trace("BEGIN_HEADER_SCRIPT
    \n", -1); Th_Render(zHeader); if( g.thTrace ) Th_Trace("END_HEADER
    \n", -1); @@ -346,14 +347,12 @@ static void style_ad_unit(void){ const char *zAd; if( g.perm.Admin && db_get_boolean("adunit-omit-if-admin",0) ){ return; } - if( !login_is_nobody() - && fossil_strcmp(g.zLogin,"anonymous")!=0 - && db_get_boolean("adunit-omit-if-user",0) - ){ + if( g.zLogin && strcmp(g.zLogin,"anonymous")!=0 + && db_get_boolean("adunit-omit-if-user",0) ){ return; } zAd = db_get("adunit", 0); if( zAd ) cgi_append_content(zAd, -1); } @@ -783,24 +782,18 @@ "tree-view lists", @ margin: 0; @ padding: 0; @ list-style: none; }, - { ".filetree ul.collapsed", - "tree-view collapsed list", - @ display: none; - }, { ".filetree ul ul", "tree-view lists below the root", @ position: relative; @ margin: 0 0 0 21px; }, { ".filetree li", "tree-view lists items", @ position: relative; - @ margin: 0; - @ padding: 0; }, { ".filetree li li:before", "tree-view node lines", @ content: ''; @ position: absolute; @@ -809,20 +802,20 @@ @ width: 14px; @ height: 1.5em; @ border-left: 2px solid #aaa; @ border-bottom: 2px solid #aaa; }, - { ".filetree li > ul:before", + { ".filetree ul ul:before", "tree-view directory lines", @ content: ''; @ position: absolute; @ top: -1.5em; @ bottom: 0; @ left: -35px; @ border-left: 2px solid #aaa; }, - { ".filetree li.last > ul:before", + { ".filetree li:last-child > ul:before", "hide lines for last-child directories", @ display: none; }, { ".filetree a", "tree-view links", @@ -1159,11 +1152,11 @@ @ vertical-align: top; @ text-align: right; @ padding: 0.2ex 2ex; }, { ".statistics-report-graph-line", - "for the /reports views", + "for the /stats_report views", @ background-color: #446979; }, { ".statistics-report-table-events th", "", @ padding: 0 1em 0 1em; @@ -1173,10 +1166,14 @@ @ padding: 0.1em 1em 0.1em 1em; }, { ".statistics-report-row-year", "", @ text-align: left; + }, + { ".statistics-report-graph-line", + "for the /stats_report views", + @ background-color: #446979; }, { ".statistics-report-week-number-label", "for the /stats_report views", @ text-align: right; @ font-size: 0.8em; @@ -1263,11 +1260,11 @@ void page_test_env(void){ char c; int i; int showAll; char zCap[30]; - static const char *const azCgiVars[] = { + static const char *azCgiVars[] = { "COMSPEC", "DOCUMENT_ROOT", "GATEWAY_INTERFACE", "HTTP_ACCEPT", "HTTP_ACCEPT_CHARSET", "HTTP_ACCEPT_ENCODING", "HTTP_ACCEPT_LANGUAGE", "HTTP_CONNECTION", "HTTP_HOST", "HTTP_USER_AGENT", "HTTP_REFERER", "PATH_INFO", "PATH_TRANSLATED", "QUERY_STRING", "REMOTE_ADDR", "REMOTE_PORT", "REQUEST_METHOD", @@ -1300,12 +1297,10 @@ zCap[i] = 0; @ g.userUid = %d(g.userUid)
    @ g.zLogin = %h(g.zLogin)
    @ g.isHuman = %d(g.isHuman)
    @ capabilities = %s(zCap)
    - @ g.zRepositoryName = %h(g.zRepositoryName)
    - @ load_average() = %f(load_average())
    @


    P("HTTP_USER_AGENT"); cgi_print_all(showAll); if( showAll && blob_size(&g.httpHeader)>0 ){ @
    Index: src/sync.c ================================================================== --- src/sync.c +++ src/sync.c @@ -48,17 +48,16 @@ } }else{ /* Autosync defaults on. To make it default off, "return" here. */ } url_parse(0, URL_REMEMBER); - if( g.url.protocol==0 ) return 0; - if( g.url.user!=0 && g.url.passwd==0 ){ - g.url.passwd = unobscure(db_get("last-sync-pw", 0)); - g.url.flags |= URL_PROMPT_PW; + if( g.urlProtocol==0 ) return 0; + if( g.urlUser!=0 && g.urlPasswd==0 ){ + g.urlPasswd = unobscure(db_get("last-sync-pw", 0)); + g.urlFlags |= URL_PROMPT_PW; url_prompt_for_password(); } - g.zHttpAuth = get_httpauth(); url_remember(); #if 0 /* Disabled for now */ if( (flags & AUTOSYNC_PULL)!=0 && db_get_boolean("auto-shun",1) ){ /* When doing an automatic pull, also automatically pull shuns from ** the server if pull_shuns is enabled. @@ -69,11 +68,11 @@ */ configSync = CONFIGSET_SHUN; } #endif if( find_option("verbose","v",0)!=0 ) flags |= SYNC_VERBOSE; - fossil_print("Autosync: %s\n", g.url.canonical); + fossil_print("Autosync: %s\n", g.urlCanonical); url_enable_proxy("via proxy: "); rc = client_sync(flags, configSync, 0); if( rc ) fossil_warning("Autosync failed"); return rc; } @@ -84,19 +83,17 @@ ** of a server to sync against. If no argument is given, use the ** most recently synced URL. Remember the current URL for next time. */ static void process_sync_args(unsigned *pConfigFlags, unsigned *pSyncFlags){ const char *zUrl = 0; - const char *zHttpAuth = 0; unsigned configSync = 0; unsigned urlFlags = URL_REMEMBER | URL_PROMPT_PW; int urlOptional = 0; if( find_option("autourl",0,0)!=0 ){ urlOptional = 1; urlFlags = 0; } - zHttpAuth = find_option("httpauth","B",1); if( find_option("once",0,0)!=0 ) urlFlags &= ~URL_REMEMBER; if( find_option("private",0,0)!=0 ){ *pSyncFlags |= SYNC_PRIVATE; } if( find_option("verbose","v",0)!=0 ){ @@ -119,24 +116,23 @@ } if( urlFlags & URL_REMEMBER ){ clone_ssh_db_set_options(); } url_parse(zUrl, urlFlags); - remember_or_get_http_auth(zHttpAuth, urlFlags & URL_REMEMBER, zUrl); url_remember(); - if( g.url.protocol==0 ){ + if( g.urlProtocol==0 ){ if( urlOptional ) fossil_exit(0); usage("URL"); } user_select(); if( g.argc==2 ){ if( ((*pSyncFlags) & (SYNC_PUSH|SYNC_PULL))==(SYNC_PUSH|SYNC_PULL) ){ - fossil_print("Sync with %s\n", g.url.canonical); + fossil_print("Sync with %s\n", g.urlCanonical); }else if( (*pSyncFlags) & SYNC_PUSH ){ - fossil_print("Push to %s\n", g.url.canonical); + fossil_print("Push to %s\n", g.urlCanonical); }else if( (*pSyncFlags) & SYNC_PULL ){ - fossil_print("Pull from %s\n", g.url.canonical); + fossil_print("Pull from %s\n", g.urlCanonical); } } url_enable_proxy("via proxy: "); *pConfigFlags |= configSync; } @@ -267,11 +263,10 @@ usage("remote-url ?URL|off?"); } if( g.argc==3 ){ db_unset("last-sync-url", 0); db_unset("last-sync-pw", 0); - db_unset("http-auth", 0); if( is_false(g.argv[2]) ) return; url_parse(g.argv[2], URL_REMEMBER|URL_PROMPT_PW|URL_ASK_REMEMBER_PW); } url_remember(); zUrl = db_get("last-sync-url", 0); @@ -278,8 +273,8 @@ if( zUrl==0 ){ fossil_print("off\n"); return; }else{ url_parse(zUrl, 0); - fossil_print("%s\n", g.url.canonical); + fossil_print("%s\n", g.urlCanonical); } } Index: src/tag.c ================================================================== --- src/tag.c +++ src/tag.c @@ -322,11 +322,11 @@ if( tagtype>0 && zValue && zValue[0] ){ blob_appendf(&ctrl, " %F\n", zValue); }else{ blob_appendf(&ctrl, "\n"); } - blob_appendf(&ctrl, "U %F\n", zUserOvrd ? zUserOvrd : login_name()); + blob_appendf(&ctrl, "U %F\n", zUserOvrd ? zUserOvrd : g.zLogin); md5sum_blob(&ctrl, &cksum); blob_appendf(&ctrl, "Z %b\n", &cksum); nrid = content_put(&ctrl); manifest_crosslink(nrid, &ctrl, MC_PERMIT_HOOKS); assert( blob_is_reset(&ctrl) ); @@ -595,7 +595,13 @@ timeline_query_for_www() ); www_print_timeline(&q, 0, 0, 0, 0); db_finalize(&q); @
    + @ style_footer(); } Index: src/tar.c ================================================================== --- src/tar.c +++ src/tar.c @@ -336,13 +336,12 @@ unsigned int mTime /* Modification time */ ){ int i; for(i=nName-1; i>0 && zName[i]!='/'; i--){} if( i<=0 ) return; - if( i= tball.nPrevDirAlloc ){ @@ -571,29 +570,19 @@ ** WEBPAGE: tarball ** URL: /tarball/RID.tar.gz ** ** Generate a compressed tarball for a checkin. ** Return that tarball as the HTTP reply content. -** -** Optional URL Parameters: -** -** - name=base name of the output file. Defaults to -** something project/version-specific. -** -** - uuid=the version to tar (may be a tag/branch name). -** Defaults to trunk. -** */ void tarball_page(void){ int rid; char *zName, *zRid; int nName, nRid; Blob tarball; login_check_credentials(); if( !g.perm.Zip ){ login_needed(); return; } - load_control(); zName = mprintf("%s", PD("name","")); nName = strlen(zName); zRid = mprintf("%s", PD("uuid","trunk")); nRid = strlen(zRid); if( nName>7 && fossil_strcmp(&zName[nName-7], ".tar.gz")==0 ){ Index: src/th.c ================================================================== --- src/th.c +++ src/th.c @@ -128,11 +128,10 @@ */ static int thNextCommand(Th_Interp*, const char *z, int n, int *pN); static int thNextEscape (Th_Interp*, const char *z, int n, int *pN); static int thNextVarname(Th_Interp*, const char *z, int n, int *pN); static int thNextNumber (Th_Interp*, const char *z, int n, int *pN); -static int thNextInteger (Th_Interp*, const char *z, int n, int *pN); static int thNextSpace (Th_Interp*, const char *z, int n, int *pN); /* ** Given that the input string (z, n) contains a language construct of ** the relevant type (a command enclosed in [], an escape sequence @@ -1868,43 +1867,10 @@ {"|", OP_BITWISE_OR, 10, ARG_INTEGER}, {0,0,0,0} }; -/* -** The first part of the string (zInput,nInput) contains an integer. -** Set *pnVarname to the number of bytes in the numeric string. -*/ -static int thNextInteger( - Th_Interp *interp, - const char *zInput, - int nInput, - int *pnLiteral -){ - int i; - int (*isdigit)(char) = th_isdigit; - char c; - - if( nInput<2) return TH_ERROR; - assert(zInput[0]=='0'); - c = zInput[1]; - if( c>='A' && c<='Z' ) c += 'a' - 'A'; - if( c=='x' ){ - isdigit = th_ishexdig; - }else if( c!='o' && c!='b' ){ - return TH_ERROR; - } - for(i=2; ipOp->eOp ) { - case OP_MULTIPLY: Th_SetResultDouble(interp, fLeft*fRight); break; + case OP_MULTIPLY: Th_SetResultDouble(interp, fLeft*fRight); break; case OP_DIVIDE: if( fRight==0.0 ){ Th_ErrorMessage(interp, "Divide by 0:", zLeft, nLeft); rc = TH_ERROR; goto finish; } Th_SetResultDouble(interp, fLeft/fRight); break; - case OP_ADD: Th_SetResultDouble(interp, fLeft+fRight); break; - case OP_SUBTRACT: Th_SetResultDouble(interp, fLeft-fRight); break; - case OP_LT: Th_SetResultInt(interp, fLeftfRight); break; - case OP_LE: Th_SetResultInt(interp, fLeft<=fRight); break; - case OP_GE: Th_SetResultInt(interp, fLeft>=fRight); break; - case OP_EQ: Th_SetResultInt(interp, fLeft==fRight); break; - case OP_NE: Th_SetResultInt(interp, fLeft!=fRight); break; - case OP_UNARY_MINUS: Th_SetResultDouble(interp, -fLeft); break; - case OP_UNARY_PLUS: Th_SetResultDouble(interp, +fLeft); break; + case OP_ADD: Th_SetResultDouble(interp, fLeft+fRight); break; + case OP_SUBTRACT: Th_SetResultDouble(interp, fLeft-fRight); break; + case OP_LT: Th_SetResultInt(interp, fLeftfRight); break; + case OP_LE: Th_SetResultInt(interp, fLeft<=fRight); break; + case OP_GE: Th_SetResultInt(interp, fLeft>=fRight); break; + case OP_EQ: Th_SetResultInt(interp, fLeft==fRight); break; + case OP_NE: Th_SetResultInt(interp, fLeft!=fRight); break; default: assert(!"Internal error"); } }else if( rc==TH_OK ){ int iEqual = 0; assert( eArgType==ARG_STRING ); @@ -2189,17 +2153,12 @@ }else{ Expr *pNew = (Expr *)Th_Malloc(interp, sizeof(Expr)); const char *z = &zExpr[i]; switch (c) { - case '0': - if( thNextInteger(interp, z, nExpr-i, &pNew->nValue)==TH_OK ){ - break; - } - /* fall through */ - case '1': case '2': case '3': case '4': case '5': - case '6': case '7': case '8': case '9': + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': thNextNumber(interp, z, nExpr-i, &pNew->nValue); break; case '$': thNextVarname(interp, z, nExpr-i, &pNew->nValue); @@ -2450,12 +2409,11 @@ ** '\f' 0x0C ** '\r' 0x0D ** ** Whitespace characters have the 0x01 flag set. Decimal digits have the ** 0x2 flag set. Single byte printable characters have the 0x4 flag set. -** Alphabet characters have the 0x8 bit set. Hexadecimal digits have the -** 0x20 flag set. +** Alphabet characters have the 0x8 bit set. ** ** The special list characters have the 0x10 flag set ** ** { } [ ] \ ; ' " ** @@ -2464,14 +2422,14 @@ */ static unsigned char aCharProp[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, /* 0x0. */ 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x1. */ 5, 4, 20, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* 0x2. */ - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 4, 20, 4, 4, 4, 4, /* 0x3. */ - 4, 44, 44, 44, 44, 44, 44, 12, 12, 12, 12, 12, 12, 12, 12, 12, /* 0x4. */ + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 4, 20, 4, 4, 4, 4, /* 0x3. */ + 4, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, /* 0x4. */ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 20, 20, 20, 4, 4, /* 0x5. */ - 4, 44, 44, 44, 44, 44, 44, 12, 12, 12, 12, 12, 12, 12, 12, 12, /* 0x6. */ + 4, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, /* 0x6. */ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 20, 4, 20, 4, 4, /* 0x7. */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x8. */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x9. */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA. */ @@ -2495,22 +2453,10 @@ return (aCharProp[(unsigned char)c] & 0x11); } int th_isalnum(char c){ return (aCharProp[(unsigned char)c] & 0x0A); } -int th_isalpha(char c){ - return (aCharProp[(unsigned char)c] & 0x08); -} -int th_ishexdig(char c){ - return (aCharProp[(unsigned char)c] & 0x20); -} -int th_isoctdig(char c){ - return ((c|7) == '7'); -} -int th_isbindig(char c){ - return ((c|1) == '1'); -} #ifndef LONGDOUBLE_TYPE # define LONGDOUBLE_TYPE long double #endif @@ -2623,51 +2569,24 @@ ** interpreter result too. */ int Th_ToInt(Th_Interp *interp, const char *z, int n, int *piOut){ int i = 0; int iOut = 0; - int base = 10; - int (*isdigit)(char) = th_isdigit; if( n<0 ){ n = th_strlen(z); } if( n>0 && (z[0]=='-' || z[0]=='+') ){ i = 1; } - if( n>2 ){ - if( z[i]=='0' ){ - if( z[i+1]=='x' || z[i+1]=='X' ){ - i += 2; - base = 16; - isdigit = th_ishexdig; - }else if( z[i+1]=='o' || z[i+1]=='O' ){ - i += 2; - base = 8; - isdigit = th_isoctdig; - }else if( z[i+1]=='b' || z[i+1]=='B' ){ - i += 2; - base = 2; - isdigit = th_isbindig; - } - } - } for(; i='a' ){ - c -= 'a'-10; - }else if( c>='A' ){ - c -= 'A'-10; - }else{ - c -= '0'; - } - iOut = iOut * base + c; + iOut = iOut * 10 + (z[i] - 48); } if( n>0 && z[0]=='-' ){ iOut *= -1; } @@ -2711,13 +2630,13 @@ if( iVal<0 ){ isNegative = 1; iVal = iVal * -1; } *(--z) = '\0'; - *(--z) = (char)(48+((unsigned)iVal%10)); - while( (iVal = ((unsigned)iVal/10))>0 ){ - *(--z) = (char)(48+((unsigned)iVal%10)); + *(--z) = (char)(48+(iVal%10)); + while( (iVal = (iVal/10))>0 ){ + *(--z) = (char)(48+(iVal%10)); assert(z>zBuf); } if( isNegative ){ *(--z) = '-'; } Index: src/th.h ================================================================== --- src/th.h +++ src/th.h @@ -7,15 +7,15 @@ /* ** Before creating an interpreter, the application must allocate and ** populate an instance of the following structure. It must remain valid ** for the lifetime of the interpreter. */ -typedef struct Th_Vtab Th_Vtab; struct Th_Vtab { void *(*xMalloc)(unsigned int); void (*xFree)(void *); }; +typedef struct Th_Vtab Th_Vtab; /* ** Opaque handle for interpeter. */ typedef struct Th_Interp Th_Interp; @@ -145,15 +145,11 @@ */ int th_strlen(const char *); int th_isdigit(char); int th_isspace(char); int th_isalnum(char); -int th_isalpha(char); int th_isspecial(char); -int th_ishexdig(char); -int th_isoctdig(char); -int th_isbindig(char); char *th_strdup(Th_Interp *interp, const char *z, int n); /* ** Interfaces to register the language extensions. */ @@ -190,7 +186,7 @@ /* ** Useful functions from th_lang.c. */ int Th_WrongNumArgs(Th_Interp *interp, const char *zMsg); -typedef struct Th_SubCommand {const char *zName; Th_CommandProc xProc;} Th_SubCommand; -int Th_CallSubCommand(Th_Interp*,void*,int,const char**,int*,const Th_SubCommand*); +typedef struct Th_SubCommand {char *zName; Th_CommandProc xProc;} Th_SubCommand; +int Th_CallSubCommand(Th_Interp*,void*,int,const char**,int*,Th_SubCommand*); Index: src/th_lang.c ================================================================== --- src/th_lang.c +++ src/th_lang.c @@ -425,11 +425,11 @@ int argc, const char **argv, int *argl ){ int rc; - const char *zName; + char *zName; ProcDefn *p; int nByte; int i; char *zSpace; @@ -521,11 +521,11 @@ } p->zUsage = zUsage; p->nUsage = nUsage; /* Register the new command with the th1 interpreter. */ - zName = argv[1]; + zName = (char *)argv[1]; rc = Th_CreateCommand(interp, zName, proc_call1, (void *)p, proc_del); if( rc==TH_OK ){ Th_SetResult(interp, 0, 0); } @@ -887,16 +887,16 @@ Th_Interp *interp, void *ctx, int argc, const char **argv, int *argl, - const Th_SubCommand *aSub + Th_SubCommand *aSub ){ if( argc>1 ){ int i; for(i=0; aSub[i].zName; i++){ - const char *zName = aSub[i].zName; + char *zName = (char *)aSub[i].zName; if( th_strlen(zName)==argl[1] && 0==memcmp(zName, argv[1], argl[1]) ){ return aSub[i].xProc(interp, ctx, argc, argv, argl); } } } @@ -924,11 +924,11 @@ void *ctx, int argc, const char **argv, int *argl ){ - static const Th_SubCommand aSub[] = { + Th_SubCommand aSub[] = { { "compare", string_compare_command }, { "first", string_first_command }, { "is", string_is_command }, { "last", string_last_command }, { "length", string_length_command }, @@ -952,11 +952,11 @@ void *ctx, int argc, const char **argv, int *argl ){ - static const Th_SubCommand aSub[] = { + Th_SubCommand aSub[] = { { "exists", info_exists_command }, { 0, 0 } }; return Th_CallSubCommand(interp, ctx, argc, argv, argl, aSub); } @@ -1097,11 +1097,11 @@ {"continue", simple_command, (void *)TH_CONTINUE}, {"error", simple_command, (void *)TH_ERROR}, {0, 0, 0} }; - size_t i; + int i; /* Add the language commands. */ for(i=0; i<(sizeof(aCommand)/sizeof(aCommand[0])); i++){ void *ctx; if ( !aCommand[i].zName || !aCommand[i].xProc ) continue; Index: src/timeline.c ================================================================== --- src/timeline.c +++ src/timeline.c @@ -48,15 +48,28 @@ */ void hyperlink_to_uuid(const char *zUuid){ char z[UUID_SIZE+1]; shorten_uuid(z, zUuid); if( g.perm.Hyperlink ){ - @ %z(xhref("class='timelineHistLink'","%R/info/%s",zUuid))[%s(z)] + @ %z(xhref("class='timelineHistLink'","%R/info/%s",z))[%s(z)] }else{ @ [%s(z)] } } + +/* +** Generate a hyperlink to a diff between two versions. +*/ +void hyperlink_to_diff(const char *zV1, const char *zV2){ + if( g.perm.Hyperlink ){ + if( zV2==0 ){ + @ %z(href("%R/diff?v2=%s",zV1))[diff] + }else{ + @ %z(href("%R/diff?v1=%s&v2=%s",zV1,zV2))[diff] + } + } +} /* ** Generate a hyperlink to a date & time. */ void hyperlink_to_date(const char *zDate, const char *zSuffix){ @@ -234,14 +247,14 @@ int fchngQueryInit = 0; /* True if fchngQuery is initialized */ Stmt fchngQuery; /* Query for file changes on check-ins */ static Stmt qbranch; int pendingEndTr = 0; /* True if a is needed */ int vid = 0; /* Current checkout version */ - int dateFormat = 0; /* 0: HH:MM 1: HH:MM:SS + int dateFormat = 0; /* 0: HH:MM 1: HH:MM:SS 2: YYYY-MM-DD HH:MM 3: YYMMDD HH:MM */ - + if( fossil_strcmp(g.zIpAddr, "127.0.0.1")==0 && db_open_local(0) ){ vid = db_lget_int("checkout", 0); } zPrevDate[0] = 0; mxWikiLen = db_get_int("timeline-max-comment", 0); @@ -435,11 +448,11 @@ @ (user: %h(zDispUser)%s(zTagList?",":"\051") } /* Generate a "detail" link for tags. */ if( (zType[0]=='g' || zType[0]=='w' || zType[0]=='t') && g.perm.Hyperlink ){ - @ [%z(href("%R/info/%s",zUuid))details] + @ [%z(href("%R/info/%S",zUuid))details] } /* Generate the "tags: TAGLIST" at the end of the comment, together ** with hyperlinks to the tag list. */ @@ -514,23 +527,23 @@ } continue; } if( isNew ){ @
  • %h(zFilename) (new file)   - @ %z(href("%R/artifact/%s",zNew))[view]
  • + @ %z(href("%R/artifact/%S",zNew))[view] }else if( isDel ){ @
  • %h(zFilename) (deleted)
  • }else if( fossil_strcmp(zOld,zNew)==0 && zOldName!=0 ){ @
  • %h(zOldName) → %h(zFilename) - @ %z(href("%R/artifact/%s",zNew))[view]
  • + @ %z(href("%R/artifact/%S",zNew))[view] }else{ if( zOldName!=0 ){ @
  • %h(zOldName) → %h(zFilename) }else{ @
  • %h(zFilename)   } - @ %z(href("%R/fdiff?sbs=1&v1=%s&v2=%s",zOld,zNew))[diff]
  • + @ %z(href("%R/fdiff?v1=%S&v2=%S&sbs=1",zOld,zNew))[diff] } } db_reset(&fchngQuery); if( inUl ){ @ @@ -578,12 +591,13 @@ ){ if( pGraph && pGraph->nErr==0 && pGraph->nRow>0 ){ GraphRow *pRow; int i; char cSep; - - @ } } /* @@ -1429,11 +1444,11 @@ blob_appendf(&desc, "%d %ss", n, zEType); } if( zUses ){ char *zFilenames = names_of_file(zUses); blob_appendf(&desc, " using file %s version %z%S", zFilenames, - href("%R/artifact/%s",zUses), zUses); + href("%R/artifact/%S",zUses), zUses); tmFlags |= TIMELINE_DISJOINT; } if( renameOnly ){ blob_appendf(&desc, " that contain filename changes"); tmFlags |= TIMELINE_DISJOINT|TIMELINE_FRENAMES; @@ -1950,11 +1965,11 @@ " AND blob.rid=c.cid" ); while( db_step(&q)==SQLITE_ROW ){ const char *zUuid = db_column_text(&q, 0); @
  • - @ %S(zUuid) + @ %S(zUuid) } db_finalize(&q); style_footer(); } @@ -2062,24 +2077,16 @@ } /* ** A helper for the /reports family of pages which prints out a menu ** of links for the various type=XXX flags. zCurrentViewName must be -** the name/value of the 'view' parameter which is in effect at the -** time this is called. e.g. if called from the 'byuser' view then -** zCurrentViewName must be "byuser". Any URL parameters which need to -** be added to the generated URLs should be passed in zParam. The -** caller is expected to have already encoded any zParam in the %T or -** %t encoding. */ -static void stats_report_event_types_menu(char const * zCurrentViewName, - char const * zParam){ - char * zTop; - if(zParam && !*zParam){ - zParam = NULL; - } - zTop = mprintf("%s/reports?view=%s%s%s", g.zTop, zCurrentViewName, - zParam ? "&" : "", zParam); +** the name/value of the 'view' parameter which is in effect at +** the time this is called. e.g. if called from the 'byuser' view +** then zCurrentViewName must be "byuser". +*/ +static void stats_report_event_types_menu(char const * zCurrentViewName){ + char * zTop = mprintf("%s/reports?view=%s", g.zTop, zCurrentViewName); cgi_printf("
    "); cgi_printf("Event types: "); if('*' == statsReportType){ cgi_printf(" all", zTop); }else{ @@ -2166,11 +2173,11 @@ int nMaxEvents = 1; /* for calculating length of graph bars. */ int iterations = 0; /* number of weeks/months we iterate over */ stats_report_init_view(); - stats_report_event_types_menu( includeMonth ? "bymonth" : "byyear", NULL ); + stats_report_event_types_menu( includeMonth ? "bymonth" : "byyear" ); blob_appendf(&header, "Timeline Events (%s) by year%s", stats_report_label_for_type(), (includeMonth ? "/month" : "")); blob_appendf(&sql, "SELECT substr(date(mtime),1,%d) AS timeframe, " @@ -2225,11 +2232,11 @@ if(showYearTotal){ rowClass = ++nRowNumber % 2; @ @ @ Yearly total: %d(nEventsPerYear) - @ + @ } nEventsPerYear = 0; memcpy(zPrevYear,zTimeframe,4); rowClass = ++nRowNumber % 2; @ @@ -2263,12 +2270,12 @@ cgi_printf("'>%s", zTimeframe); } @ %d(nCount) @ @
     
    - @ + @ style='height:16px;width:%d(nSize)%%;'> + @
    @ if(includeWeeks){ /* This part works fine for months but it terribly slow (4.5s on my PC), so it's only shown for by-year for now. Suggestions/patches for a better/faster layout are welcomed. */ @@ -2289,11 +2296,11 @@ /* Add final year total separator. */ rowClass = ++nRowNumber % 2; @ @ @ Yearly total: %d(nEventsPerYear) - @ + @ } @ if(nEventTotal){ char const * zAvgLabel = includeMonth ? "month" : "year"; int nAvg = iterations ? (nEventTotal/iterations) : 0; @@ -2317,11 +2324,11 @@ row colors */ Blob sql = empty_blob; /* SQL */ int nMaxEvents = 1; /* max number of events for all rows. */ stats_report_init_view(); - stats_report_event_types_menu("byuser", NULL); + stats_report_event_types_menu("byuser"); blob_append(&sql, "SELECT user, " "COUNT(*) AS eventCount " "FROM v_reports " "GROUP BY user ORDER BY eventCount DESC", @@ -2358,12 +2365,12 @@ @ @ %h(zUser) @ %d(nCount) @ @
     
    - @ + @ style='height:16px;width:%d(nSize)%%;'> + @ @ /* Potential improvement: calculate the min/max event counts and use percent-based graph bars. */ @@ -2388,28 +2395,21 @@ Blob sql = empty_blob; int nMaxEvents = 1; /* max number of events for all rows. */ int iterations = 0; /* # of active time periods. */ stats_report_init_view(); - if(4==nYear){ - Blob urlParams = empty_blob; - blob_appendf(&urlParams, "y=%T", zYear); - stats_report_event_types_menu("byweek", blob_str(&urlParams)); - blob_reset(&urlParams); - }else{ - stats_report_event_types_menu("byweek", NULL); - } + stats_report_event_types_menu("byweek"); + cgi_printf("Select year: "); blob_append(&sql, "SELECT DISTINCT substr(date(mtime),1,4) AS y " "FROM v_reports WHERE 1 ", -1); if(zUserName&&*zUserName){ blob_appendf(&sql,"AND user=%Q ", zUserName); } blob_append(&sql,"GROUP BY y ORDER BY y", -1); db_prepare(&qYears, blob_str(&sql)); blob_reset(&sql); - cgi_printf("Select year: "); while( SQLITE_ROW == db_step(&qYears) ){ const char * zT = db_column_text(&qYears, 0); if( i++ ){ cgi_printf(" "); } @@ -2487,11 +2487,11 @@ cgi_printf("%d",nCount); cgi_printf(""); if(nCount){ cgi_printf("
     
    ", + "style='height:16px;width:%d%%;'>", nSize); } cgi_printf(""); } db_finalize(&stWeek); @@ -2529,15 +2529,13 @@ */ void stats_report_page(){ HQuery url; /* URL for various branch links */ const char * zView = P("view"); /* Which view/report to show. */ const char *zUserName = P("user"); - - login_check_credentials(); - if( !g.perm.Read ){ login_needed(); return; } if(!zUserName) zUserName = P("u"); url_initialize(&url, "reports"); + if(zUserName && *zUserName){ url_add_parameter(&url,"user", zUserName); timeline_submenu(&url, "(Remove User Flag)", "view", zView, "user"); } timeline_submenu(&url, "By Year", "view", "byyear", 0); Index: src/tkt.c ================================================================== --- src/tkt.c +++ src/tkt.c @@ -61,11 +61,11 @@ } return -1; } /* -** Obtain a list of all fields of the TICKET and TICKETCHNG tables. Put them +** Obtain a list of all fields of the TICKET and TICKETCHNG tables. Put them ** in sorted order in aField[]. ** ** The haveTicket and haveTicketChng variables are set to 1 if the TICKET and ** TICKETCHANGE tables exist, respectively. */ @@ -429,15 +429,15 @@ if( g.perm.WrTkt || g.perm.ApndTkt ){ style_submenu_element("Edit", "Edit The Ticket", "%s/tktedit?name=%T", g.zTop, PD("name","")); } if( g.perm.Hyperlink ){ - style_submenu_element("History", "History Of This Ticket", + style_submenu_element("History", "History Of This Ticket", "%s/tkthistory/%T", g.zTop, zUuid); - style_submenu_element("Timeline", "Timeline Of This Ticket", + style_submenu_element("Timeline", "Timeline Of This Ticket", "%s/tkttimeline/%T", g.zTop, zUuid); - style_submenu_element("Check-ins", "Check-ins Of This Ticket", + style_submenu_element("Check-ins", "Check-ins Of This Ticket", "%s/tkttimeline/%T?y=ci", g.zTop, zUuid); } if( g.perm.NewTkt ){ style_submenu_element("New Ticket", "Create a new ticket", "%s/tktnew", g.zTop); @@ -446,14 +446,14 @@ style_submenu_element("Attach", "Add An Attachment", "%s/attachadd?tkt=%T&from=%s/tktview/%t", g.zTop, zUuid, g.zTop, zUuid); } if( P("plaintext") ){ - style_submenu_element("Formatted", "Formatted", "%R/tktview/%s", zUuid); + style_submenu_element("Formatted", "Formatted", "%R/tktview/%S", zUuid); }else{ style_submenu_element("Plaintext", "Plaintext", - "%R/tktview/%s?plaintext", zUuid); + "%R/tktview/%S?plaintext", zUuid); } style_header("View Ticket"); if( g.thTrace ) Th_Trace("BEGIN_TKTVIEW
    \n", -1); ticket_init(); initializeVariablesFromCGI(); @@ -463,17 +463,17 @@ if( P("showfields")!=0 ) showAllFields(); if( g.thTrace ) Th_Trace("BEGIN_TKTVIEW_SCRIPT
    \n", -1); Th_Render(zScript); if( g.thTrace ) Th_Trace("END_TKTVIEW
    \n", -1); - zFullName = db_text(0, + zFullName = db_text(0, "SELECT tkt_uuid FROM ticket" " WHERE tkt_uuid GLOB '%q*'", zUuid); if( zFullName ){ attachment_list(zFullName, "

    Attachments:

      "); } - + style_footer(); } /* ** TH command: append_field FIELD STRING @@ -482,14 +482,14 @@ ** to append text. STRING is the text to be appended to that ** column. The append does not actually occur until the ** submit_ticket command is run. */ static int appendRemarkCmd( - Th_Interp *interp, - void *p, - int argc, - const char **argv, + Th_Interp *interp, + void *p, + int argc, + const char **argv, int *argl ){ int idx; if( argc!=3 ){ @@ -555,14 +555,14 @@ ** taken from TH variables. If the content is unchanged, the field is ** omitted from the artifact. Fields whose names begin with "private_" ** are concealed using the db_conceal() function. */ static int submitTicketCmd( - Th_Interp *interp, - void *pUuid, - int argc, - const char **argv, + Th_Interp *interp, + void *pUuid, + int argc, + const char **argv, int *argl ){ char *zDate; const char *zUuid; int i; @@ -606,19 +606,19 @@ nJ++; } } } if( *(char**)pUuid ){ - zUuid = db_text(0, + zUuid = db_text(0, "SELECT tkt_uuid FROM ticket WHERE tkt_uuid GLOB '%q*'", P("name") ); }else{ zUuid = db_text(0, "SELECT lower(hex(randomblob(20)))"); } *(const char**)pUuid = zUuid; blob_appendf(&tktchng, "K %s\n", zUuid); - blob_appendf(&tktchng, "U %F\n", login_name()); + blob_appendf(&tktchng, "U %F\n", g.zLogin ? g.zLogin : ""); md5sum_blob(&tktchng, &cksum); blob_appendf(&tktchng, "Z %b\n", &cksum); if( nJ==0 ){ blob_reset(&tktchng); return TH_OK; @@ -675,11 +675,11 @@ login_insert_csrf_secret(); if( P("date_override") && g.perm.Setup ){ @ } zScript = ticket_newpage_code(); - Th_Store("login", login_name()); + Th_Store("login", g.zLogin ? g.zLogin : "nobody"); Th_Store("date", db_text(0, "SELECT datetime('now')")); Th_CreateCommand(g.interp, "submit_ticket", submitTicketCmd, (void*)&zNewUuid, 0); if( g.thTrace ) Th_Trace("BEGIN_TKTNEW_SCRIPT
      \n", -1); if( Th_Render(zScript)==TH_RETURN && !g.thTrace && zNewUuid ){ @@ -743,11 +743,11 @@ if( g.zPath[0]=='d' ) showAllFields(); form_begin(0, "%R/%s", g.zPath); @ login_insert_csrf_secret(); zScript = ticket_editpage_code(); - Th_Store("login", login_name()); + Th_Store("login", g.zLogin ? g.zLogin : "nobody"); Th_Store("date", db_text(0, "SELECT datetime('now')")); Th_CreateCommand(g.interp, "append_field", appendRemarkCmd, 0, 0); Th_CreateCommand(g.interp, "submit_ticket", submitTicketCmd, (void*)&zName,0); if( g.thTrace ) Th_Trace("BEGIN_TKTEDIT_SCRIPT
      \n", -1); if( Th_Render(zScript)==TH_RETURN && !g.thTrace && zName ){ @@ -895,14 +895,14 @@ "%s/tkttimeline?name=%s&y=ci", g.zTop, zUuid); style_submenu_element("Timeline", "Timeline", "%s/tkttimeline?name=%s", g.zTop, zUuid); if( P("plaintext")!=0 ){ style_submenu_element("Formatted", "Formatted", - "%R/tkthistory/%s", zUuid); + "%R/tkthistory/%S", zUuid); }else{ style_submenu_element("Plaintext", "Plaintext", - "%R/tkthistory/%s?plaintext", zUuid); + "%R/tkthistory/%S?plaintext", zUuid); } style_header(zTitle); free(zTitle); tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'",zUuid); @@ -924,39 +924,42 @@ " ORDER BY 1", timeline_utc(), tagid, timeline_utc(), tagid ); while( db_step(&q)==SQLITE_ROW ){ Manifest *pTicket; + char zShort[12]; const char *zDate = db_column_text(&q, 0); int rid = db_column_int(&q, 1); const char *zChngUuid = db_column_text(&q, 2); const char *zFile = db_column_text(&q, 4); + memcpy(zShort, zChngUuid, 10); + zShort[10] = 0; if( nChng==0 ){ @
        } nChng++; if( zFile!=0 ){ const char *zSrc = db_column_text(&q, 3); const char *zUser = db_column_text(&q, 5); if( zSrc==0 || zSrc[0]==0 ){ - @ + @ @
      1. Delete attachment "%h(zFile)" }else{ - @ + @ @

      2. Add attachment - @ "%z(href("%R/artifact/%s",zSrc))%s(zFile)" + @ "%z(href("%R/artifact/%S",zSrc))%s(zFile)" } - @ [%z(href("%R/artifact/%s",zChngUuid))%.10s(zChngUuid)] + @ [%z(href("%R/artifact/%T",zChngUuid))%s(zShort)] @ (rid %d(rid)) by hyperlink_to_user(zUser,zDate," on"); hyperlink_to_date(zDate, ".

        "); }else{ pTicket = manifest_get(rid, CFTYPE_TICKET, 0); if( pTicket ){ @ @
      3. Ticket change - @ [%z(href("%R/artifact/%s",zChngUuid))%.10s(zChngUuid)] + @ [%z(href("%R/artifact/%T",zChngUuid))%s(zShort)] @ (rid %d(rid)) by hyperlink_to_user(pTicket->zUser,zDate," on"); hyperlink_to_date(zDate, ":"); @

        ticket_output_change_artifact(pTicket, "a"); @@ -1099,11 +1102,11 @@ /* do some ints, we want to be inside a checkout */ db_find_and_open_repository(0, 0); user_select(); zUser = find_option("user-override",0,1); - if( zUser==0 ) zUser = login_name(); + if( zUser==0 ) zUser = g.zLogin; zDate = find_option("date-override",0,1); if( zDate==0 ) zDate = "now"; zDate = date_in_standard_format(zDate); zTktUuid = find_option("uuid-override",0,1); if( zTktUuid && (strlen(zTktUuid)!=40 || !validate16(zTktUuid,40)) ){ @@ -1148,11 +1151,11 @@ }else{ /* add a new ticket or set fields on existing tickets */ tTktShowEncoding tktEncoding; tktEncoding = find_option("quote","q",0) ? tktFossilize : tktNoTab; - + if( strncmp(g.argv[2],"show",n)==0 ){ if( g.argc==3 ){ usage("show REPORTNR"); }else{ const char *zRep = 0; @@ -1183,11 +1186,11 @@ eCmd = set; } if( g.argc==3 ){ usage("set|change|history TICKETUUID"); } - zTktUuid = db_text(0, + zTktUuid = db_text(0, "SELECT tkt_uuid FROM ticket WHERE tkt_uuid GLOB '%s*'", g.argv[3] ); if( !zTktUuid ){ fossil_fatal("unknown ticket: '%s'!",g.argv[3]); } @@ -1214,33 +1217,37 @@ } tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'", zTktUuid); if( tagid==0 ){ fossil_fatal("no such ticket %h", zTktUuid); - } + } db_prepare(&q, - "SELECT datetime(mtime%s), objid, NULL, NULL, NULL" + "SELECT datetime(mtime%s), objid, uuid, NULL, NULL, NULL" " FROM event, blob" " WHERE objid IN (SELECT rid FROM tagxref WHERE tagid=%d)" " AND blob.rid=event.objid" " UNION " - "SELECT datetime(mtime%s), attachid, filename, " - " src, user" + "SELECT datetime(mtime%s), attachid, uuid, src, " + " filename, user" " FROM attachment, blob" " WHERE target=(SELECT substr(tagname,5) FROM tag WHERE tagid=%d)" " AND blob.rid=attachid" " ORDER BY 1 DESC", timeline_utc(), tagid, timeline_utc(), tagid ); while( db_step(&q)==SQLITE_ROW ){ Manifest *pTicket; + char zShort[12]; const char *zDate = db_column_text(&q, 0); int rid = db_column_int(&q, 1); - const char *zFile = db_column_text(&q, 2); + const char *zChngUuid = db_column_text(&q, 2); + const char *zFile = db_column_text(&q, 4); + memcpy(zShort, zChngUuid, 10); + zShort[10] = 0; if( zFile!=0 ){ const char *zSrc = db_column_text(&q, 3); - const char *zUser = db_column_text(&q, 4); + const char *zUser = db_column_text(&q, 5); if( zSrc==0 || zSrc[0]==0 ){ fossil_print("Delete attachment %s\n", zFile); }else{ fossil_print("Add attachment %s\n", zFile); } Index: src/tktsetup.c ================================================================== --- src/tktsetup.c +++ src/tktsetup.c @@ -115,11 +115,11 @@ void (*xRebuild)(void), /* Run after successful update */ int height /* Height of the edit box */ ){ const char *z; int isSubmit; - + login_check_credentials(); if( !g.perm.Setup ){ login_needed(); } if( P("setup") ){ @@ -314,43 +314,43 @@ @ @ Enter a one-line summary of the ticket:
        @ @ @ -@ +@ @ @ Type: @ combobox type $type_choices 1 @ What type of ticket is this? @ -@ +@ @ @ Version: @ @ @ @ In what version or build number do you observe @ the problem? @ -@ +@ @ @ Severity: @ combobox severity $severity_choices 1 @ How debilitating is the problem? How badly does the problem @ affect the operation of the product? @ -@ +@ @ @ EMail: @ @ @ @ Not publicly visible @ Used by developers to contact you with questions. @ -@ +@ @ @ @ Enter a detailed description of the problem. @ For code defects, be sure to provide details on exactly how @ the problem can be reproduced. Provide as much detail as @@ -359,11 +359,11 @@ @
        @ set nline [linecount $comment 50 10] @
        @ -@ +@ @ enable_output [info exists preview] @ @ Description Preview:

        @ @ if {$mutype eq "Wiki"} { @@ -378,28 +378,28 @@ @ wiki "$icomment\n" @ } @ @
        @ enable_output 1 -@ +@ @ @ @ @ @ See how the description will appear after formatting. @ -@ +@ @ enable_output [info exists preview] @ @ @ @ -@ After filling in the information above, press this +@ After filling in the information above, press this @ button to create the new ticket @ @ enable_output 1 -@ +@ @ @ @ @ @ Abandon and forget this ticket @@ -477,11 +477,11 @@ @ @ Version Found In: @ @ $ @ -@ +@ @ @ if {[info exists comment] && [string length $comment]>10} { @ html { @ Description: @ @@ -577,55 +577,55 @@ @ @ @ -@ +@ @ -@ +@ @ -@ +@ @ -@ +@ @ -@ +@ @ -@ +@ @ -@ +@ @ enable_output [hascap e] @ @ enable_output 1 -@ +@ @ -@ +@ @ -@ +@ @ enable_output [info exists preview] @ @ enable_output 1 -@ +@ @ @ @ @ -@ +@ @ enable_output [info exists preview] @ @ @ @ @ enable_output 1 -@ +@ @ @ @ @ -@ +@ @
        Title: @ @
        Status: @ combobox status $status_choices 1 @
        Type: @ combobox type $type_choices 1 @
        Severity: @ combobox severity $severity_choices 1 @
        Priority: @ combobox priority $priority_choices 1 @
        Resolution: @ combobox resolution $resolution_choices 1 @
        Subsystem: @ combobox subsystem $subsystem_choices 1 @
        Contact: @ @
        Version Found In: @ @
        @ Append Remark with format @ combobox mutype {Wiki HTML {Plain Text} {[links only]}} 1 @ from @ :
        @ @
        @ Description Preview:

        @ @ if {$mutype eq "Wiki"} { @@ -641,34 +641,34 @@ @ } @ @
        @
        @ @ See how the description will appear after formatting.
        @ @ Apply the changes shown above
        @ @ Abandon this edit
        ; /* ** Return the code used to generate the edit ticket page @@ -703,16 +703,16 @@ @ if {[hascap n]} { @ html "

        Enter a new ticket:

        " @ html "" @ } @ -@ +@ @

        Choose a report format from the following list:

        @
          @ html $report_items @
        -@ +@ @ @ if {[hascap t q]} { @ html "

        Other options:

        \n
          \n" @ if {[hascap t]} { @ html "
        • New report format
        • \n" @@ -750,11 +750,11 @@ } /* ** The default template ticket report format: */ -static char zDefaultReport[] = +static char zDefaultReport[] = @ SELECT @ CASE WHEN status IN ('Open','Verified') THEN '#f2dcdc' @ WHEN status='Review' THEN '#e8e8e8' @ WHEN status='Fixed' THEN '#cfe8bd' @ WHEN status='Tested' THEN '#bde5d6' @@ -799,11 +799,11 @@ } /* ** The default template ticket key: */ -static const char zDefaultKey[] = +static const char zDefaultKey[] = @ #ffffff Key: @ #f2dcdc Active @ #e8e8e8 Review @ #cfe8bd Fixed @ #bde5d6 Tested @@ -880,7 +880,7 @@ @ @

          @ db_end_transaction(0); style_footer(); - + } Index: src/update.c ================================================================== --- src/update.c +++ src/update.c @@ -625,12 +625,10 @@ ManifestFile *pFile; int rid=0; if( revision ){ rid = name_to_typed_rid(revision,"ci"); - }else if( !g.localOpen ){ - rid = name_to_typed_rid(db_get("main-branch","trunk"),"ci"); }else{ rid = db_lget_int("checkout", 0); } if( !is_a_version(rid) ){ if( errCode>0 ) return errCode; @@ -719,12 +717,16 @@ db_multi_exec( "REPLACE INTO torevert VALUES(%B);" "INSERT OR IGNORE INTO torevert" " SELECT pathname" " FROM vfile" - " WHERE origname=%B;", - &fname, &fname + " WHERE origname IN(%B)" + " UNION ALL" + " SELECT origname" + " FROM vfile" + " WHERE pathname IN(%B) AND origname IS NOT NULL;", + &fname, &fname, &fname ); blob_reset(&fname); } }else{ int vid; @@ -733,19 +735,17 @@ db_multi_exec( "DELETE FROM vmerge;" "INSERT OR IGNORE INTO torevert " " SELECT pathname" " FROM vfile " - " WHERE chnged OR deleted OR rid=0 OR pathname!=origname;" + " WHERE chnged OR deleted OR rid=0 OR pathname!=origname " + " UNION ALL " + " SELECT origname" + " FROM vfile" + " WHERE origname!=pathname;" ); } - db_multi_exec( - "INSERT OR IGNORE INTO torevert" - " SELECT origname" - " FROM vfile" - " WHERE origname!=pathname AND pathname IN (SELECT name FROM torevert);" - ); blob_zero(&record); db_prepare(&q, "SELECT name FROM torevert"); if( zRevision==0 ){ int vid = db_lget_int("checkout", 0); zRevision = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid); @@ -766,13 +766,13 @@ undo_save(zFile); file_delete(zFull); fossil_print("DELETE: %s\n", zFile); } db_multi_exec( - "UPDATE OR REPLACE vfile" + "UPDATE vfile" " SET pathname=origname, origname=NULL" - " WHERE pathname=%Q AND origname!=pathname;" + " WHERE pathname=%Q AND origname!=pathname AND origname IS NOT NULL;" "DELETE FROM vfile WHERE pathname=%Q", zFile, zFile ); }else{ sqlite3_int64 mtime; Index: src/url.c ================================================================== --- src/url.c +++ src/url.c @@ -62,13 +62,10 @@ char *passwd; /* Password for http: */ char *canonical; /* Canonical representation of the URL */ char *proxyAuth; /* Proxy-Authorizer: string */ char *fossil; /* The fossil query parameter on ssh: */ unsigned flags; /* Boolean flags controlling URL processing */ - int useProxy; /* Used to remember that a proxy is in use */ - char *proxyUrlPath; - int proxyOrigPort; /* Tunneled port number for https through proxy */ }; #endif /* INTERFACE */ /* @@ -123,11 +120,10 @@ char *zLogin; char *zExe; char cQuerySep = '?'; pUrlData->isFile = 0; - pUrlData->useProxy = 0; if( zUrl[4]=='s' ){ pUrlData->isHttps = 1; pUrlData->protocol = "https"; pUrlData->dfltPort = 443; iStart = 8; @@ -275,22 +271,22 @@ /* ** Parse the given URL, which describes a sync server. Populate variables ** in the global "g" structure as follows: ** -** g.url.isFile True if FILE: -** g.url.isHttps True if HTTPS: -** g.url.isSsh True if SSH: -** g.url.protocol "http" or "https" or "file" -** g.url.name Hostname for HTTP:, HTTPS:, SSH:. Filename for FILE: -** g.url.port TCP port number for HTTP or HTTPS. -** g.url.dfltPort Default TCP port number (80 or 443). -** g.url.path Path name for HTTP or HTTPS. -** g.url.user Userid. -** g.url.passwd Password. -** g.url.hostname HOST:PORT or just HOST if port is the default. -** g.url.canonical The URL in canonical form, omitting the password +** g.urlIsFile True if FILE: +** g.urlIsHttps True if HTTPS: +** g.urlIsSsh True if SSH: +** g.urlProtocol "http" or "https" or "file" +** g.urlName Hostname for HTTP:, HTTPS:, SSH:. Filename for FILE: +** g.urlPort TCP port number for HTTP or HTTPS. +** g.urlDfltPort Default TCP port number (80 or 443). +** g.urlPath Path name for HTTP or HTTPS. +** g.urlUser Userid. +** g.urlPasswd Password. +** g.urlHostname HOST:PORT or just HOST if port is the default. +** g.urlCanonical The URL in canonical form, omitting the password ** ** HTTP url format as follows (HTTPS is the same with a different scheme): ** ** http://userid:password@host:port/path ** @@ -298,11 +294,11 @@ ** ** ssh://userid@host:port/path?fossil=path/to/fossil.exe ** */ void url_parse(const char *zUrl, unsigned int urlFlags){ - url_parse_local(zUrl, urlFlags, &g.url); + url_parse_local(zUrl, urlFlags, GLOBAL_URL()); } /* ** COMMAND: test-urlparser ** @@ -323,25 +319,25 @@ if( g.argc!=3 && g.argc!=4 ){ usage("URL"); } url_parse(g.argv[2], fg); for(i=0; i<2; i++){ - fossil_print("g.url.isFile = %d\n", g.url.isFile); - fossil_print("g.url.isHttps = %d\n", g.url.isHttps); - fossil_print("g.url.isSsh = %d\n", g.url.isSsh); - fossil_print("g.url.protocol = %s\n", g.url.protocol); - fossil_print("g.url.name = %s\n", g.url.name); - fossil_print("g.url.port = %d\n", g.url.port); - fossil_print("g.url.dfltPort = %d\n", g.url.dfltPort); - fossil_print("g.url.hostname = %s\n", g.url.hostname); - fossil_print("g.url.path = %s\n", g.url.path); - fossil_print("g.url.user = %s\n", g.url.user); - fossil_print("g.url.passwd = %s\n", g.url.passwd); - fossil_print("g.url.canonical = %s\n", g.url.canonical); - fossil_print("g.url.fossil = %s\n", g.url.fossil); - fossil_print("g.url.flags = 0x%02x\n", g.url.flags); - if( g.url.isFile || g.url.isSsh ) break; + fossil_print("g.urlIsFile = %d\n", g.urlIsFile); + fossil_print("g.urlIsHttps = %d\n", g.urlIsHttps); + fossil_print("g.urlIsSsh = %d\n", g.urlIsSsh); + fossil_print("g.urlProtocol = %s\n", g.urlProtocol); + fossil_print("g.urlName = %s\n", g.urlName); + fossil_print("g.urlPort = %d\n", g.urlPort); + fossil_print("g.urlDfltPort = %d\n", g.urlDfltPort); + fossil_print("g.urlHostname = %s\n", g.urlHostname); + fossil_print("g.urlPath = %s\n", g.urlPath); + fossil_print("g.urlUser = %s\n", g.urlUser); + fossil_print("g.urlPasswd = %s\n", g.urlPasswd); + fossil_print("g.urlCanonical = %s\n", g.urlCanonical); + fossil_print("g.urlFossil = %s\n", g.urlFossil); + fossil_print("g.urlFlags = 0x%02x\n", g.urlFlags); + if( g.urlIsFile || g.urlIsSsh ) break; if( i==0 ){ fossil_print("********\n"); url_enable_proxy("Using proxy: "); } } @@ -385,38 +381,31 @@ if( zProxy==0 || zProxy[0]==0 || is_truth(zProxy) ){ zProxy = fossil_getenv("http_proxy"); } } if( zProxy && zProxy[0] && !is_false(zProxy) - && !g.url.isSsh && !g.url.isFile ){ - char *zOriginalUrl = g.url.canonical; - char *zOriginalHost = g.url.hostname; - int fOriginalIsHttps = g.url.isHttps; - char *zOriginalUser = g.url.user; - char *zOriginalPasswd = g.url.passwd; - char *zOriginalUrlPath = g.url.path; - int iOriginalPort = g.url.port; - unsigned uOriginalFlags = g.url.flags; - g.url.user = 0; - g.url.passwd = ""; + && !g.urlIsSsh && !g.urlIsFile ){ + char *zOriginalUrl = g.urlCanonical; + char *zOriginalHost = g.urlHostname; + char *zOriginalUser = g.urlUser; + char *zOriginalPasswd = g.urlPasswd; + unsigned uOriginalFlags = g.urlFlags; + g.urlUser = 0; + g.urlPasswd = ""; url_parse(zProxy, 0); - if( zMsg ) fossil_print("%s%s\n", zMsg, g.url.canonical); - g.url.path = zOriginalUrl; - g.url.hostname = zOriginalHost; - if( g.url.user ){ - char *zCredentials1 = mprintf("%s:%s", g.url.user, g.url.passwd); + if( zMsg ) fossil_print("%s%s\n", zMsg, g.urlCanonical); + g.urlPath = zOriginalUrl; + g.urlHostname = zOriginalHost; + if( g.urlUser ){ + char *zCredentials1 = mprintf("%s:%s", g.urlUser, g.urlPasswd); char *zCredentials2 = encode64(zCredentials1, -1); - g.url.proxyAuth = mprintf("Basic %z", zCredentials2); + g.urlProxyAuth = mprintf("Basic %z", zCredentials2); free(zCredentials1); } - g.url.user = zOriginalUser; - g.url.passwd = zOriginalPasswd; - g.url.isHttps = fOriginalIsHttps; - g.url.useProxy = 1; - g.url.proxyUrlPath = zOriginalUrlPath; - g.url.proxyOrigPort = iOriginalPort; - g.url.flags = uOriginalFlags; + g.urlUser = zOriginalUser; + g.urlPasswd = zOriginalPasswd; + g.urlFlags = uOriginalFlags; } } #if INTERFACE /* @@ -529,35 +518,35 @@ pUrlData->user); } } /* -** Prompt the user for the password for g.url.user. Store the result -** in g.url.passwd. +** Prompt the user for the password for g.urlUser. Store the result +** in g.urlPasswd. */ void url_prompt_for_password(void){ - url_prompt_for_password_local(&g.url); + url_prompt_for_password_local(GLOBAL_URL()); } /* ** Remember the URL and password if requested. */ void url_remember(void){ - if( g.url.flags & URL_REMEMBER ){ - db_set("last-sync-url", g.url.canonical, 0); - if( g.url.user!=0 && g.url.passwd!=0 && ( g.url.flags & URL_REMEMBER_PW ) ){ - db_set("last-sync-pw", obscure(g.url.passwd), 0); + if( g.urlFlags & URL_REMEMBER ){ + db_set("last-sync-url", g.urlCanonical, 0); + if( g.urlUser!=0 && g.urlPasswd!=0 && ( g.urlFlags & URL_REMEMBER_PW ) ){ + db_set("last-sync-pw", obscure(g.urlPasswd), 0); } } } /* Preemptively prompt for a password if a username is given in the ** URL but no password. */ void url_get_password_if_needed(void){ - if( (g.url.user && g.url.user[0]) - && (g.url.passwd==0 || g.url.passwd[0]==0) + if( (g.urlUser && g.urlUser[0]) + && (g.urlPasswd==0 || g.urlPasswd[0]==0) && isatty(fileno(stdin)) ){ url_prompt_for_password(); } } Index: src/user.c ================================================================== --- src/user.c +++ src/user.c @@ -375,11 +375,11 @@ if( attempt_user(fossil_getenv("LOGNAME")) ) return; if( attempt_user(fossil_getenv("USERNAME")) ) return; url_parse(0, 0); - if( g.url.user && attempt_user(g.url.user) ) return; + if( g.urlUser && attempt_user(g.urlUser) ) return; fossil_print( "Cannot figure out who you are! Consider using the --user\n" "command line option, setting your USER environment variable,\n" "or setting a default user with \"fossil user default USER\".\n" Index: src/utf8.c ================================================================== --- src/utf8.c +++ src/utf8.c @@ -54,22 +54,18 @@ ** returned pointer when done. */ char *fossil_unicode_to_utf8(const void *zUnicode){ #if defined(_WIN32) || defined(__CYGWIN__) int nByte = WideCharToMultiByte(CP_UTF8, 0, zUnicode, -1, 0, 0, 0, 0); - char *zUtf = fossil_malloc( nByte ); + char *zUtf = sqlite3_malloc( nByte ); + if( zUtf==0 ){ + return 0; + } WideCharToMultiByte(CP_UTF8, 0, zUnicode, -1, zUtf, nByte, 0, 0); return zUtf; #else - static Stmt q; - char *zUtf8; - db_static_prepare(&q, "SELECT :utf8"); - db_bind_text16(&q, ":utf8", zUnicode); - db_step(&q); - zUtf8 = fossil_strdup(db_column_text(&q, 0)); - db_reset(&q); - return zUtf8; + return fossil_strdup(zUnicode); /* TODO: implement for unix */ #endif } /* ** Translate UTF-8 to unicode for use in system calls. Return a pointer to the @@ -77,25 +73,31 @@ ** used to store the returned pointer when done. */ void *fossil_utf8_to_unicode(const char *zUtf8){ #if defined(_WIN32) || defined(__CYGWIN__) int nByte = MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, 0, 0); - wchar_t *zUnicode = fossil_malloc( nByte * 2 ); + wchar_t *zUnicode = sqlite3_malloc( nByte * 2 ); + if( zUnicode==0 ){ + return 0; + } MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nByte); return zUnicode; #else - assert( 0 ); /* Never used in unix */ return fossil_strdup(zUtf8); /* TODO: implement for unix */ #endif } /* ** Deallocate any memory that was previously allocated by ** fossil_unicode_to_utf8(). */ void fossil_unicode_free(void *pOld){ +#if defined(_WIN32) || defined(__CYGWIN__) + sqlite3_free(pOld); +#else fossil_free(pOld); +#endif } #if defined(__APPLE__) && !defined(WITHOUT_ICONV) # include #endif @@ -177,12 +179,11 @@ ** Call fossil_filename_free() to deallocate any memory used to store the ** returned pointer when done. ** ** On Windows, characters in the range U+0001 to U+0031 and the ** characters '"', '*', ':', '<', '>', '?' and '|' are invalid -** to be used, except in the 'extended path' prefix ('?') and -** as drive specifier (':'). Therefore, translate those to characters +** to be used. Therefore, translate those to characters in the ** in the range U+F001 - U+F07F (private use area), so those ** characters never arrive in any Windows API. The filenames might ** look strange in Windows explorer, but in the cygwin shell ** everything looks as expected. ** @@ -190,60 +191,22 @@ ** */ void *fossil_utf8_to_filename(const char *zUtf8){ #ifdef _WIN32 int nChar = MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, 0, 0); - /* Overallocate 6 chars, making some room for extended paths */ - wchar_t *zUnicode = sqlite3_malloc( (nChar+6) * sizeof(wchar_t) ); + wchar_t *zUnicode = sqlite3_malloc( nChar * 2 ); wchar_t *wUnicode = zUnicode; if( zUnicode==0 ){ return 0; } MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nChar); - /* - ** If path starts with "//?/" or "\\?\" (extended path), translate - ** any slashes to backslashes but leave the '?' intact - */ - if( (zUtf8[0]=='\\' || zUtf8[0]=='/') && (zUtf8[1]=='\\' || zUtf8[1]=='/') - && zUtf8[2]=='?' && (zUtf8[3]=='\\' || zUtf8[3]=='/')) { - wUnicode[0] = wUnicode[1] = wUnicode[3] = '\\'; - zUtf8 += 4; - wUnicode += 4; - } - /* - ** If there is no "\\?\" prefix but there is a drive or UNC - ** path prefix and the path is larger than MAX_PATH chars, - ** no Win32 API function can handle that unless it is - ** prefixed with the extended path prefix. See: - ** - **/ + /* If path starts with ":/" or ":\", don't translate the ':' */ if( fossil_isalpha(zUtf8[0]) && zUtf8[1]==':' - && (zUtf8[2]=='\\' || zUtf8[2]=='/') ){ - if( wUnicode==zUnicode && nChar>MAX_PATH){ - memmove(wUnicode+4, wUnicode, nChar*sizeof(wchar_t)); - memcpy(wUnicode, L"\\\\?\\", 4*sizeof(wchar_t)); - wUnicode += 4; - } - /* - ** If (remainder of) path starts with ":/" or ":\", - ** leave the ':' intact but translate the backslash to a slash. - */ - wUnicode[2] = '\\'; + && (zUtf8[2]=='\\' || zUtf8[2]=='/')) { + zUnicode[2] = '\\'; wUnicode += 3; - }else if( wUnicode==zUnicode && nChar>MAX_PATH - && (zUtf8[0]=='\\' || zUtf8[0]=='/') - && (zUtf8[1]=='\\' || zUtf8[1]=='/') && zUtf8[2]!='?'){ - memmove(wUnicode+6, wUnicode, nChar*sizeof(wchar_t)); - memcpy(wUnicode, L"\\\\?\\UNC", 7*sizeof(wchar_t)); - wUnicode += 7; - } - /* - ** In the remainder of the path, translate invalid characters to - ** characters in the Unicode private use area. This is what makes - ** Win32 fossil.exe work well in a Cygwin environment even when a - ** filename contains characters which are invalid for Win32. - */ + } while( *wUnicode != '\0' ){ if ( (*wUnicode < ' ') || wcschr(L"\"*:<>?|", *wUnicode) ){ *wUnicode |= 0xF000; }else if( *wUnicode == '/' ){ *wUnicode = '\\'; Index: src/vfile.c ================================================================== --- src/vfile.c +++ src/vfile.c @@ -45,18 +45,18 @@ ** does not exist, then return 0. ** ** For this routine, the UUID must be exact. For a match against ** user input with mixed case, use resolve_uuid(). ** -** If the UUID is not found and phantomize is 1 or 2, then attempt to +** If the UUID is not found and phantomize is 1 or 2, then attempt to ** create a phantom record. A private phantom is created for 2 and ** a public phantom is created for 1. */ int uuid_to_rid(const char *zUuid, int phantomize){ int rid, sz; char z[UUID_SIZE+1]; - + sz = strlen(zUuid); if( sz!=UUID_SIZE || !validate16(zUuid, sz) ){ return 0; } memcpy(z, zUuid, UUID_SIZE+1); @@ -140,11 +140,11 @@ ** the file has changed due to a merge. 3 means the file was added ** by a merge. ** ** If VFILE.DELETED is true or if VFILE.RID is zero, then the file was either ** removed from configuration management via "fossil rm" or added via -** "fossil add", respectively, and in both cases we always know that +** "fossil add", respectively, and in both cases we always know that ** the file has changed without having the check the size, mtime, ** or on-disk content. ** ** If the size of the file has changed, then we always know that the file ** changed without having to look at the mtime or on-disk content. @@ -315,11 +315,11 @@ } if( verbose ) fossil_print("%s\n", &zName[nRepos]); if( file_wd_isdir(zName) == 1 ){ /*TODO(dchest): remove directories? */ fossil_fatal("%s is directory, cannot overwrite\n", zName); - } + } if( file_wd_size(zName)>=0 && (isLink || file_wd_islink(zName)) ){ file_delete(zName); } if( isLink ){ symlink_create(blob_str(&content), zName); @@ -392,11 +392,11 @@ "merge", "original", "output", }; int i, j, n; - + if( strglob("ci-comment-????????????.txt", zName) ) return 1; for(; zName[0]!=0; zName++){ if( zName[0]=='/' && strglob("/ci-comment-????????????.txt", zName) ){ return 1; } @@ -407,11 +407,11 @@ if( zName[n+1]==0 ) return 1; if( zName[n+1]=='-' ){ for(j=n+2; zName[j] && fossil_isdigit(zName[j]); j++){} if( zName[j]==0 ) return 1; } - } + } } return 0; } #if INTERFACE @@ -674,11 +674,11 @@ FILE *in; Stmt q; char zBuf[4096]; db_must_be_within_tree(); - db_prepare(&q, + db_prepare(&q, "SELECT %Q || pathname, pathname, origname, is_selected(id), rid" " FROM vfile" " WHERE (NOT deleted OR NOT is_selected(id)) AND vid=%d" " ORDER BY if_selected(id, pathname, origname) /*scan*/", g.zLocalRoot, vid @@ -693,11 +693,11 @@ md5sum_step_text(zName, -1); if( file_wd_islink(zFullpath) ){ /* Instead of file content, use link destination path */ Blob pathBuf; - sqlite3_snprintf(sizeof(zBuf), zBuf, " %ld\n", + sqlite3_snprintf(sizeof(zBuf), zBuf, " %ld\n", blob_read_link(&pathBuf, zFullpath)); md5sum_step_text(zBuf, -1); md5sum_step_text(blob_str(&pathBuf), -1); blob_reset(&pathBuf); }else{ @@ -724,11 +724,11 @@ const char *zOrigName = db_column_text(&q, 2); char zBuf[100]; Blob file; if( zOrigName ) zName = zOrigName; - if( rid>0 || vid==0 ){ + if( rid>0 ){ md5sum_step_text(zName, -1); blob_zero(&file); content_get(rid, &file); sqlite3_snprintf(sizeof(zBuf), zBuf, " %d\n", blob_size(&file)); md5sum_step_text(zBuf, -1); @@ -763,13 +763,13 @@ void vfile_compare_repository_to_disk(int vid){ int rc; Stmt q; Blob disk, repo; char *zOut; - + db_must_be_within_tree(); - db_prepare(&q, + db_prepare(&q, "SELECT %Q || pathname, pathname, rid FROM vfile" " WHERE NOT deleted AND vid=%d AND is_selected(id)" " ORDER BY if_selected(id, pathname, origname) /*scan*/", g.zLocalRoot, vid ); @@ -829,17 +829,17 @@ Blob file; Stmt q; char zBuf[100]; db_must_be_within_tree(); - + db_prepare(&q, "SELECT pathname, origname, rid, is_selected(id)" " FROM vfile" " WHERE (NOT deleted OR NOT is_selected(id))" - " %s AND vid=%d" + " AND rid>0 AND vid=%d" " ORDER BY if_selected(id,pathname,origname) /*scan*/", - (vid ? "AND rid>0" : ""), vid); + vid); blob_zero(&file); md5sum_init(); while( db_step(&q)==SQLITE_ROW ){ const char *zName = db_column_text(&q, 0); const char *zOrigName = db_column_text(&q, 1); @@ -867,11 +867,11 @@ ** ** If pManOut is not NULL then fill it with the checksum found in the ** "R" card near the end of the manifest. ** ** In a well-formed manifest, the two checksums computed here, pOut and -** pManOut, should be identical. +** pManOut, should be identical. */ void vfile_aggregate_checksum_manifest(int vid, Blob *pOut, Blob *pManOut){ int fid; Blob file; Blob err; Index: src/wiki.c ================================================================== --- src/wiki.c +++ src/wiki.c @@ -222,11 +222,11 @@ zBody = db_get("sandbox",zBody); zMimetype = db_get("sandbox-mimetype","text/x-fossil-wiki"); rid = 0; }else{ zTag = mprintf("wiki-%s", zPageName); - rid = db_int(0, + rid = db_int(0, "SELECT rid FROM tagxref" " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)" " ORDER BY mtime DESC", zTag ); free(zTag); @@ -241,11 +241,11 @@ if( rid ){ style_submenu_element("Diff", "Last change", "%R/wdiff?name=%T&a=%d", zPageName, rid); zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); style_submenu_element("Details", "Details", - "%R/info/%s", zUuid); + "%R/info/%S", zUuid); } if( (rid && g.perm.WrWiki) || (!rid && g.perm.NewWiki) ){ if( db_get_boolean("wysiwyg-wiki", 0) ){ style_submenu_element("Edit", "Edit Wiki Page", "%s/wikiedit?name=%T&wysiwyg=1", @@ -260,11 +260,11 @@ style_submenu_element("Attach", "Add An Attachment", "%s/attachadd?page=%T&from=%s/wiki%%3fname=%T", g.zTop, zPageName, g.zTop, zPageName); } if( rid && g.perm.ApndWiki ){ - style_submenu_element("Append", "Add A Comment", + style_submenu_element("Append", "Add A Comment", "%s/wikiappend?name=%T&mimetype=%s", g.zTop, zPageName, zMimetype); } if( g.perm.Hyperlink ){ style_submenu_element("History", "History", "%s/whistory?name=%T", @@ -300,11 +300,11 @@ } /* ** Formal names and common names for the various wiki styles. */ -static const char *const azStyles[] = { +static const char *azStyles[] = { "text/x-fossil-wiki", "Fossil Wiki", "text/x-markdown", "Markdown", "text/plain", "Plain Text" }; @@ -381,11 +381,11 @@ zBody = db_get("sandbox",""); zMimetype = db_get("sandbox-mimetype","text/x-fossil-wiki"); } }else{ zTag = mprintf("wiki-%s", zPageName); - rid = db_int(0, + rid = db_int(0, "SELECT rid FROM tagxref" " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)" " ORDER BY mtime DESC", zTag ); free(zTag); @@ -420,12 +420,12 @@ if( rid ){ char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); blob_appendf(&wiki, "P %s\n", zUuid); free(zUuid); } - if( !login_is_nobody() ){ - blob_appendf(&wiki, "U %F\n", login_name()); + if( g.zLogin ){ + blob_appendf(&wiki, "U %F\n", g.zLogin); } blob_appendf(&wiki, "W %d\n%s\n", strlen(zBody), zBody); md5sum_blob(&wiki, &cksum); blob_appendf(&wiki, "Z %b\n", &cksum); blob_reset(&cksum); @@ -462,11 +462,11 @@ if( !isWysiwyg ){ /* Traditional markup-only editing */ form_begin(0, "%R/wikiedit"); @
          mimetype_option_menu(zMimetype); - @
          @
          if( db_get_boolean("wysiwyg-wiki", 0) ){ @ @@ -514,11 +514,11 @@ const char *zMimetype; login_check_credentials(); if( !g.perm.NewWiki ){ login_needed(); return; - } + } zName = PD("name",""); zMimetype = wiki_filter_mimetypes(P("mimetype")); if( zName[0] && wiki_name_is_wellformed((const unsigned char *)zName) ){ if( fossil_strcmp(zMimetype,"text/x-fossil-wiki")==0 && db_get_boolean("wysiwyg-wiki", 0) @@ -557,26 +557,26 @@ zDate = db_text(0, "SELECT datetime('now')"); zRemark = PD("r",""); zUser = PD("u",g.zLogin); if( fossil_strcmp(zMimetype, "text/x-fossil-wiki")==0 ){ zId = db_text(0, "SELECT lower(hex(randomblob(8)))"); - blob_appendf(p, "\n\n
          On %s UTC %h", - zId, zDate, login_name()); - if( zUser[0] && fossil_strcmp(zUser,login_name()) ){ + blob_appendf(p, "\n\n
          On %s UTC %h", + zId, zDate, g.zLogin); + if( zUser[0] && fossil_strcmp(zUser,g.zLogin) ){ blob_appendf(p, " (claiming to be %h)", zUser); } blob_appendf(p, " added:
          \n%s
          ", zRemark, zId); }else if( fossil_strcmp(zMimetype, "text/x-markdown")==0 ){ - blob_appendf(p, "\n\n------\n*On %s UTC %h", zDate, login_name()); - if( zUser[0] && fossil_strcmp(zUser,login_name()) ){ + blob_appendf(p, "\n\n------\n*On %s UTC %h", zDate, g.zLogin); + if( zUser[0] && fossil_strcmp(zUser,g.zLogin) ){ blob_appendf(p, " (claiming to be %h)", zUser); } blob_appendf(p, " added:*\n\n%s\n", zRemark); }else{ blob_appendf(p, "\n\n------------------------------------------------\n" - "On %s UTC %s", zDate, login_name()); - if( zUser[0] && fossil_strcmp(zUser,login_name()) ){ + "On %s UTC %s", zDate, g.zLogin); + if( zUser[0] && fossil_strcmp(zUser,g.zLogin) ){ blob_appendf(p, " (claiming to be %s)", zUser); } blob_appendf(p, " added:\n\n%s\n", zRemark); } fossil_free(zDate); @@ -601,11 +601,11 @@ zMimetype = wiki_filter_mimetypes(P("mimetype")); if( check_name(zPageName) ) return; isSandbox = is_sandbox(zPageName); if( !isSandbox ){ zTag = mprintf("wiki-%s", zPageName); - rid = db_int(0, + rid = db_int(0, "SELECT rid FROM tagxref" " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)" " ORDER BY mtime DESC", zTag ); free(zTag); @@ -650,12 +650,12 @@ if( rid ){ char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); blob_appendf(&wiki, "P %s\n", zUuid); free(zUuid); } - if( !login_is_nobody() ){ - blob_appendf(&wiki, "U %F\n", login_name()); + if( g.zLogin ){ + blob_appendf(&wiki, "U %F\n", g.zLogin); } appendRemark(&body, zMimetype); blob_appendf(&wiki, "W %d\n%s\n", blob_size(&body), blob_str(&body)); md5sum_blob(&wiki, &cksum); blob_appendf(&wiki, "Z %b\n", &cksum); @@ -690,11 +690,11 @@ @ @ Your Name: @
          zFormat = mimetype_common_name(zMimetype); @ Comment to append (formatted as %s(zFormat)):
          - @ @
          @ @ @ @@ -809,11 +809,11 @@ ** - tagxref (whatever that really is!) ** ** Used by wcontent_page() and the JSON wiki code. */ void wiki_prepare_page_list( Stmt * pStmt ){ - db_prepare(pStmt, + db_prepare(pStmt, "SELECT" " substr(tagname, 6) as name," " (SELECT value FROM tagxref WHERE tagid=tag.tagid ORDER BY mtime DESC) as tagXref" " FROM tag WHERE tagname GLOB 'wiki-*'" " ORDER BY lower(tagname) /*sort*/" @@ -866,11 +866,11 @@ login_check_credentials(); if( !g.perm.RdWiki ){ login_needed(); return; } zTitle = PD("title","*"); style_header("Wiki Pages Found"); @
            - db_prepare(&q, + db_prepare(&q, "SELECT substr(tagname, 6, 1000) FROM tag WHERE tagname like 'wiki-%%%q%%'" " ORDER BY lower(tagname) /*sort*/" , zTitle); while( db_step(&q)==SQLITE_ROW ){ const char *zName = db_column_text(&q, 0); @@ -917,11 +917,11 @@ @ surrounded on both sides by two or more spaces or by a tab. Only a single @ level of enumeration list is supported by wiki. For nested lists or for @ enumerations that count using letters or roman numerials, use HTML.

            @
          • Indented Paragraphs. @ Any paragraph that begins with two or more spaces or a tab and - @ which is not a bullet or enumeration list item is rendered + @ which is not a bullet or enumeration list item is rendered @ indented. Only a single level of indentation is supported by wiki; use @ HTML for deeper indentation.

          • @
          • Hyperlinks. @ Text within square brackets ("[...]") becomes a hyperlink. The @ target can be a wiki page name, the artifact ID of a check-in or ticket, @@ -993,12 +993,12 @@ zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); blob_appendf(&wiki, "P %s\n", zUuid); free(zUuid); } user_select(); - if( !login_is_nobody() ){ - blob_appendf(&wiki, "U %F\n", login_name()); + if( g.zLogin ){ + blob_appendf(&wiki, "U %F\n", g.zLogin); } blob_appendf( &wiki, "W %d\n%s\n", blob_size(pContent), blob_str(pContent) ); md5sum_blob(&wiki, &cksum); blob_appendf(&wiki, "Z %b\n", &cksum); @@ -1062,11 +1062,11 @@ } zPageName = g.argv[3]; rid = db_int(0, "SELECT x.rid FROM tag t, tagxref x" " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'" " ORDER BY x.mtime DESC LIMIT 1", - zPageName + zPageName ); if( (pWiki = manifest_get(rid, CFTYPE_WIKI, 0))!=0 ){ zBody = pWiki->zWiki; } if( zBody==0 ){ @@ -1110,11 +1110,11 @@ } fossil_fatal("delete not yet implemented."); }else if( strncmp(g.argv[2],"list",n)==0 ){ Stmt q; - db_prepare(&q, + db_prepare(&q, "SELECT substr(tagname, 6) FROM tag WHERE tagname GLOB 'wiki-*'" " ORDER BY lower(tagname) /*sort*/" ); while( db_step(&q)==SQLITE_ROW ){ const char *zName = db_column_text(&q, 0); Index: src/wikiformat.c ================================================================== --- src/wikiformat.c +++ src/wikiformat.c @@ -35,112 +35,103 @@ /* ** These are the only markup attributes allowed. */ -enum allowed_attr_t { - ATTR_ALIGN = 1, - ATTR_ALT, - ATTR_BGCOLOR, - ATTR_BORDER, - ATTR_CELLPADDING, - ATTR_CELLSPACING, - ATTR_CLASS, - ATTR_CLEAR, - ATTR_COLOR, - ATTR_COLSPAN, - ATTR_COMPACT, - ATTR_FACE, - ATTR_HEIGHT, - ATTR_HREF, - ATTR_HSPACE, - ATTR_ID, - ATTR_LINKS, - ATTR_NAME, - ATTR_ROWSPAN, - ATTR_SIZE, - ATTR_SRC, - ATTR_START, - ATTR_STYLE, - ATTR_TARGET, - ATTR_TYPE, - ATTR_VALIGN, - ATTR_VALUE, - ATTR_VSPACE, - ATTR_WIDTH -}; - -enum amsk_t { - AMSK_ALIGN = 0x00000001, - AMSK_ALT = 0x00000002, - AMSK_BGCOLOR = 0x00000004, - AMSK_BORDER = 0x00000008, - AMSK_CELLPADDING = 0x00000010, - AMSK_CELLSPACING = 0x00000020, - AMSK_CLASS = 0x00000040, - AMSK_CLEAR = 0x00000080, - AMSK_COLOR = 0x00000100, - AMSK_COLSPAN = 0x00000200, - AMSK_COMPACT = 0x00000400, - /* re-use = 0x00000800, */ - AMSK_FACE = 0x00001000, - AMSK_HEIGHT = 0x00002000, - AMSK_HREF = 0x00004000, - AMSK_HSPACE = 0x00008000, - AMSK_ID = 0x00010000, - AMSK_LINKS = 0x00020000, - AMSK_NAME = 0x00040000, - AMSK_ROWSPAN = 0x00080000, - AMSK_SIZE = 0x00100000, - AMSK_SRC = 0x00200000, - AMSK_START = 0x00400000, - AMSK_STYLE = 0x00800000, - AMSK_TARGET = 0x01000000, - AMSK_TYPE = 0x02000000, - AMSK_VALIGN = 0x04000000, - AMSK_VALUE = 0x08000000, - AMSK_VSPACE = 0x10000000, - AMSK_WIDTH = 0x20000000 -}; +#define ATTR_ALIGN 1 +#define ATTR_ALT 2 +#define ATTR_BGCOLOR 3 +#define ATTR_BORDER 4 +#define ATTR_CELLPADDING 5 +#define ATTR_CELLSPACING 6 +#define ATTR_CLASS 7 +#define ATTR_CLEAR 8 +#define ATTR_COLOR 9 +#define ATTR_COLSPAN 10 +#define ATTR_COMPACT 11 +#define ATTR_FACE 12 +#define ATTR_HEIGHT 13 +#define ATTR_HREF 14 +#define ATTR_HSPACE 15 +#define ATTR_ID 16 +#define ATTR_LINKS 17 +#define ATTR_NAME 18 +#define ATTR_ROWSPAN 19 +#define ATTR_SIZE 20 +#define ATTR_SRC 21 +#define ATTR_START 22 +#define ATTR_STYLE 23 +#define ATTR_TARGET 24 +#define ATTR_TYPE 25 +#define ATTR_VALIGN 26 +#define ATTR_VALUE 27 +#define ATTR_VSPACE 28 +#define ATTR_WIDTH 29 +#define AMSK_ALIGN 0x00000001 +#define AMSK_ALT 0x00000002 +#define AMSK_BGCOLOR 0x00000004 +#define AMSK_BORDER 0x00000008 +#define AMSK_CELLPADDING 0x00000010 +#define AMSK_CELLSPACING 0x00000020 +#define AMSK_CLASS 0x00000040 +#define AMSK_CLEAR 0x00000080 +#define AMSK_COLOR 0x00000100 +#define AMSK_COLSPAN 0x00000200 +#define AMSK_COMPACT 0x00000400 +#define AMSK_FACE 0x00000800 +#define AMSK_HEIGHT 0x00001000 +#define AMSK_HREF 0x00002000 +#define AMSK_HSPACE 0x00004000 +#define AMSK_ID 0x00008000 +#define AMSK_LINKS 0x00010000 +#define AMSK_NAME 0x00020000 +#define AMSK_ROWSPAN 0x00040000 +#define AMSK_SIZE 0x00080000 +#define AMSK_SRC 0x00100000 +#define AMSK_START 0x00200000 +#define AMSK_STYLE 0x00400000 +#define AMSK_TARGET 0x00800000 +#define AMSK_TYPE 0x01000000 +#define AMSK_VALIGN 0x02000000 +#define AMSK_VALUE 0x04000000 +#define AMSK_VSPACE 0x08000000 +#define AMSK_WIDTH 0x10000000 static const struct AllowedAttribute { const char *zName; unsigned int iMask; } aAttribute[] = { - /* These indexes MUST line up with their - corresponding allowed_attr_t enum values. - */ { 0, 0 }, - { "align", AMSK_ALIGN }, - { "alt", AMSK_ALT }, - { "bgcolor", AMSK_BGCOLOR }, - { "border", AMSK_BORDER }, - { "cellpadding", AMSK_CELLPADDING }, - { "cellspacing", AMSK_CELLSPACING }, - { "class", AMSK_CLASS }, - { "clear", AMSK_CLEAR }, - { "color", AMSK_COLOR }, - { "colspan", AMSK_COLSPAN }, - { "compact", AMSK_COMPACT }, - { "face", AMSK_FACE }, - { "height", AMSK_HEIGHT }, - { "href", AMSK_HREF }, - { "hspace", AMSK_HSPACE }, - { "id", AMSK_ID }, - { "links", AMSK_LINKS }, - { "name", AMSK_NAME }, - { "rowspan", AMSK_ROWSPAN }, - { "size", AMSK_SIZE }, - { "src", AMSK_SRC }, - { "start", AMSK_START }, - { "style", AMSK_STYLE }, - { "target", AMSK_TARGET }, - { "type", AMSK_TYPE }, - { "valign", AMSK_VALIGN }, - { "value", AMSK_VALUE }, - { "vspace", AMSK_VSPACE }, - { "width", AMSK_WIDTH }, + { "align", AMSK_ALIGN, }, + { "alt", AMSK_ALT, }, + { "bgcolor", AMSK_BGCOLOR, }, + { "border", AMSK_BORDER, }, + { "cellpadding", AMSK_CELLPADDING, }, + { "cellspacing", AMSK_CELLSPACING, }, + { "class", AMSK_CLASS, }, + { "clear", AMSK_CLEAR, }, + { "color", AMSK_COLOR, }, + { "colspan", AMSK_COLSPAN, }, + { "compact", AMSK_COMPACT, }, + { "face", AMSK_FACE, }, + { "height", AMSK_HEIGHT, }, + { "href", AMSK_HREF, }, + { "hspace", AMSK_HSPACE, }, + { "id", AMSK_ID, }, + { "links", AMSK_LINKS, }, + { "name", AMSK_NAME, }, + { "rowspan", AMSK_ROWSPAN, }, + { "size", AMSK_SIZE, }, + { "src", AMSK_SRC, }, + { "start", AMSK_START, }, + { "style", AMSK_STYLE, }, + { "target", AMSK_TARGET, }, + { "type", AMSK_TYPE, }, + { "valign", AMSK_VALIGN, }, + { "value", AMSK_VALUE, }, + { "vspace", AMSK_VSPACE, }, + { "width", AMSK_WIDTH, }, }; /* ** Use binary search to locate a tag in the aAttribute[] table. */ @@ -173,69 +164,62 @@ ** in aAllowedMarkup[]. */ #define MARKUP_INVALID 0 #define MARKUP_A 1 #define MARKUP_ADDRESS 2 -#define MARKUP_HTML5_ARTICLE 3 -#define MARKUP_HTML5_ASIDE 4 -#define MARKUP_B 5 -#define MARKUP_BIG 6 -#define MARKUP_BLOCKQUOTE 7 -#define MARKUP_BR 8 -#define MARKUP_CENTER 9 -#define MARKUP_CITE 10 -#define MARKUP_CODE 11 -#define MARKUP_COL 12 -#define MARKUP_COLGROUP 13 -#define MARKUP_DD 14 -#define MARKUP_DFN 15 -#define MARKUP_DIV 16 -#define MARKUP_DL 17 -#define MARKUP_DT 18 -#define MARKUP_EM 19 -#define MARKUP_FONT 20 -#define MARKUP_HTML5_FOOTER 21 -#define MARKUP_H1 22 -#define MARKUP_H2 23 -#define MARKUP_H3 24 -#define MARKUP_H4 25 -#define MARKUP_H5 26 -#define MARKUP_H6 27 -#define MARKUP_HTML5_HEADER 28 -#define MARKUP_HR 29 -#define MARKUP_I 30 -#define MARKUP_IMG 31 -#define MARKUP_KBD 32 -#define MARKUP_LI 33 -#define MARKUP_HTML5_NAV 34 -#define MARKUP_NOBR 35 -#define MARKUP_NOWIKI 36 -#define MARKUP_OL 37 -#define MARKUP_P 38 -#define MARKUP_PRE 39 -#define MARKUP_S 40 -#define MARKUP_SAMP 41 -#define MARKUP_HTML5_SECTION 42 -#define MARKUP_SMALL 43 -#define MARKUP_SPAN 44 -#define MARKUP_STRIKE 45 -#define MARKUP_STRONG 46 -#define MARKUP_SUB 47 -#define MARKUP_SUP 48 -#define MARKUP_TABLE 49 -#define MARKUP_TBODY 50 -#define MARKUP_TD 51 -#define MARKUP_TFOOT 52 -#define MARKUP_TH 53 -#define MARKUP_THEAD 54 -#define MARKUP_TITLE 55 -#define MARKUP_TR 56 -#define MARKUP_TT 57 -#define MARKUP_U 58 -#define MARKUP_UL 59 -#define MARKUP_VAR 60 -#define MARKUP_VERBATIM 61 +#define MARKUP_B 3 +#define MARKUP_BIG 4 +#define MARKUP_BLOCKQUOTE 5 +#define MARKUP_BR 6 +#define MARKUP_CENTER 7 +#define MARKUP_CITE 8 +#define MARKUP_CODE 9 +#define MARKUP_COL 10 +#define MARKUP_COLGROUP 11 +#define MARKUP_DD 12 +#define MARKUP_DFN 13 +#define MARKUP_DIV 14 +#define MARKUP_DL 15 +#define MARKUP_DT 16 +#define MARKUP_EM 17 +#define MARKUP_FONT 18 +#define MARKUP_H1 19 +#define MARKUP_H2 20 +#define MARKUP_H3 21 +#define MARKUP_H4 22 +#define MARKUP_H5 23 +#define MARKUP_H6 24 +#define MARKUP_HR 25 +#define MARKUP_I 26 +#define MARKUP_IMG 27 +#define MARKUP_KBD 28 +#define MARKUP_LI 29 +#define MARKUP_NOBR 30 +#define MARKUP_NOWIKI 31 +#define MARKUP_OL 32 +#define MARKUP_P 33 +#define MARKUP_PRE 34 +#define MARKUP_S 35 +#define MARKUP_SAMP 36 +#define MARKUP_SMALL 37 +#define MARKUP_SPAN 38 +#define MARKUP_STRIKE 39 +#define MARKUP_STRONG 40 +#define MARKUP_SUB 41 +#define MARKUP_SUP 42 +#define MARKUP_TABLE 43 +#define MARKUP_TBODY 44 +#define MARKUP_TD 45 +#define MARKUP_TFOOT 46 +#define MARKUP_TH 47 +#define MARKUP_THEAD 48 +#define MARKUP_TR 49 +#define MARKUP_TT 50 +#define MARKUP_U 51 +#define MARKUP_UL 52 +#define MARKUP_VAR 53 +#define MARKUP_VERBATIM 54 /* ** The various markup is divided into the following types: */ #define MUTYPE_SINGLE 0x0001 /* ,
            , or


            */ @@ -267,15 +251,10 @@ } aMarkup[] = { { 0, MARKUP_INVALID, 0, 0 }, { "a", MARKUP_A, MUTYPE_HYPERLINK, AMSK_HREF|AMSK_NAME|AMSK_CLASS|AMSK_TARGET|AMSK_STYLE }, { "address", MARKUP_ADDRESS, MUTYPE_BLOCK, AMSK_STYLE }, - { "article", MARKUP_HTML5_ARTICLE, MUTYPE_BLOCK, - AMSK_ID|AMSK_CLASS|AMSK_STYLE }, - { "aside", MARKUP_HTML5_ASIDE, MUTYPE_BLOCK, - AMSK_ID|AMSK_CLASS|AMSK_STYLE }, - { "b", MARKUP_B, MUTYPE_FONT, AMSK_STYLE }, { "big", MARKUP_BIG, MUTYPE_FONT, AMSK_STYLE }, { "blockquote", MARKUP_BLOCKQUOTE, MUTYPE_BLOCK, AMSK_STYLE }, { "br", MARKUP_BR, MUTYPE_SINGLE, AMSK_CLEAR }, { "center", MARKUP_CENTER, MUTYPE_BLOCK, AMSK_STYLE }, @@ -293,13 +272,10 @@ AMSK_COMPACT|AMSK_STYLE }, { "dt", MARKUP_DT, MUTYPE_LI, AMSK_STYLE }, { "em", MARKUP_EM, MUTYPE_FONT, AMSK_STYLE }, { "font", MARKUP_FONT, MUTYPE_FONT, AMSK_COLOR|AMSK_FACE|AMSK_SIZE|AMSK_STYLE }, - { "footer", MARKUP_HTML5_FOOTER, MUTYPE_BLOCK, - AMSK_ID|AMSK_CLASS|AMSK_STYLE }, - { "h1", MARKUP_H1, MUTYPE_BLOCK, AMSK_ALIGN|AMSK_CLASS|AMSK_STYLE }, { "h2", MARKUP_H2, MUTYPE_BLOCK, AMSK_ALIGN|AMSK_CLASS|AMSK_STYLE }, { "h3", MARKUP_H3, MUTYPE_BLOCK, @@ -308,14 +284,10 @@ AMSK_ALIGN|AMSK_CLASS|AMSK_STYLE }, { "h5", MARKUP_H5, MUTYPE_BLOCK, AMSK_ALIGN|AMSK_CLASS|AMSK_STYLE }, { "h6", MARKUP_H6, MUTYPE_BLOCK, AMSK_ALIGN|AMSK_CLASS|AMSK_STYLE }, - - { "header", MARKUP_HTML5_HEADER, MUTYPE_BLOCK, - AMSK_ID|AMSK_CLASS|AMSK_STYLE }, - { "hr", MARKUP_HR, MUTYPE_SINGLE, AMSK_ALIGN|AMSK_COLOR|AMSK_SIZE|AMSK_WIDTH| AMSK_STYLE|AMSK_CLASS }, { "i", MARKUP_I, MUTYPE_FONT, AMSK_STYLE }, { "img", MARKUP_IMG, MUTYPE_SINGLE, @@ -322,23 +294,19 @@ AMSK_ALIGN|AMSK_ALT|AMSK_BORDER|AMSK_HEIGHT| AMSK_HSPACE|AMSK_SRC|AMSK_VSPACE|AMSK_WIDTH|AMSK_STYLE }, { "kbd", MARKUP_KBD, MUTYPE_FONT, AMSK_STYLE }, { "li", MARKUP_LI, MUTYPE_LI, AMSK_TYPE|AMSK_VALUE|AMSK_STYLE }, - { "nav", MARKUP_HTML5_NAV, MUTYPE_BLOCK, - AMSK_ID|AMSK_CLASS|AMSK_STYLE }, { "nobr", MARKUP_NOBR, MUTYPE_FONT, 0 }, { "nowiki", MARKUP_NOWIKI, MUTYPE_SPECIAL, 0 }, { "ol", MARKUP_OL, MUTYPE_LIST, AMSK_START|AMSK_TYPE|AMSK_COMPACT|AMSK_STYLE }, { "p", MARKUP_P, MUTYPE_BLOCK, AMSK_ALIGN|AMSK_CLASS|AMSK_STYLE }, { "pre", MARKUP_PRE, MUTYPE_BLOCK, AMSK_STYLE }, { "s", MARKUP_S, MUTYPE_FONT, AMSK_STYLE }, { "samp", MARKUP_SAMP, MUTYPE_FONT, AMSK_STYLE }, - { "section", MARKUP_HTML5_SECTION, MUTYPE_BLOCK, - AMSK_ID|AMSK_CLASS|AMSK_STYLE }, { "small", MARKUP_SMALL, MUTYPE_FONT, AMSK_STYLE }, { "span", MARKUP_SPAN, MUTYPE_BLOCK, AMSK_ALIGN|AMSK_CLASS|AMSK_STYLE }, { "strike", MARKUP_STRIKE, MUTYPE_FONT, AMSK_STYLE }, { "strong", MARKUP_STRONG, MUTYPE_FONT, AMSK_STYLE }, @@ -358,11 +326,10 @@ { "th", MARKUP_TH, MUTYPE_TD, AMSK_ALIGN|AMSK_BGCOLOR|AMSK_COLSPAN| AMSK_ROWSPAN|AMSK_VALIGN|AMSK_CLASS|AMSK_STYLE }, { "thead", MARKUP_THEAD, MUTYPE_BLOCK, AMSK_ALIGN|AMSK_CLASS|AMSK_STYLE }, - { "title", MARKUP_TITLE, MUTYPE_BLOCK, 0 }, { "tr", MARKUP_TR, MUTYPE_TR, AMSK_ALIGN|AMSK_BGCOLOR|AMSK_VALIGN|AMSK_CLASS|AMSK_STYLE }, { "tt", MARKUP_TT, MUTYPE_FONT, AMSK_STYLE }, { "u", MARKUP_U, MUTYPE_FONT, AMSK_STYLE }, { "ul", MARKUP_UL, MUTYPE_LIST, @@ -372,10 +339,11 @@ AMSK_ID|AMSK_TYPE }, }; void show_allowed_wiki_markup( void ){ int i; /* loop over allowedAttr */ + for( i=1 ; i<=sizeof(aMarkup)/sizeof(aMarkup[0]) - 1 ; i++ ){ @ <%s(aMarkup[i].zName)> } } @@ -798,11 +766,11 @@ p->nAttr = 1; if( c=='>' ) return; } while( fossil_isspace(z[i]) ){ i++; } while( c!='>' && p->nAttr<8 && fossil_isalpha(z[i]) ){ - int attrOk; /* True to preserve attribute. False to ignore it */ + int attrOk; /* True to preserver attribute. False to ignore it */ j = 0; while( fossil_isalnum(z[i]) ){ if( jnAttr; i++){ char *z = p->aAttr[i].zValue; if( z==0 ) continue; - if( p->aAttr[i].cTerm ){ - n = strlen(z); - z[n] = p->aAttr[i].cTerm; - } + n = strlen(z); + z[n] = p->aAttr[i].cTerm; } } /* ** Return the value of attribute attrId. Return NULL if there is no @@ -1482,19 +1448,10 @@ case TOKEN_MARKUP: { const char *zId; int iDiv; parseMarkup(&markup, z); - /* Convert to <h1 align='center'> */ - if( markup.iCode==MARKUP_TITLE && !p->inVerbatim ){ - markup.iCode = MARKUP_H1; - markup.nAttr = 1; - markup.aAttr[0].iACode = AMSK_ALIGN; - markup.aAttr[0].zValue = "center"; - markup.aAttr[0].cTerm = 0; - } - /* Markup of the form </div id=ID> where there is a matching ** ID somewhere on the stack. Exit any contained verbatim. ** Pop the stack up to the matching <div>. Discard the </div> */ if( markup.iCode==MARKUP_DIV && markup.endTag && @@ -1761,22 +1718,14 @@ z = blob_str(pIn); for(i=0; fossil_isspace(z[i]); i++){} if( z[i]!='<' ) return 0; i++; if( strncmp(&z[i],"title>", 6)!=0 ) return 0; - for(iStart=i+6; fossil_isspace(z[iStart]); iStart++){} + iStart = i+6; for(i=iStart; z[i] && (z[i]!='<' || strncmp(&z[i],"",8)!=0); i++){} - if( strncmp(&z[i],"",8)!=0 ){ - blob_init(pTitle, 0, 0); - blob_init(pTail, &z[iStart], -1); - return 1; - } - if( i-iStart>0 ){ - blob_init(pTitle, &z[iStart], i-iStart); - }else{ - blob_init(pTitle, 0, 0); - } + if( z[i]!='<' ) return 0; + blob_init(pTitle, &z[iStart], i-iStart); blob_init(pTail, &z[i+8], -1); return 1; } /* Index: src/winhttp.c ================================================================== --- src/winhttp.c +++ src/winhttp.c @@ -67,18 +67,15 @@ HttpRequest *p = (HttpRequest*)pAppData; FILE *in = 0, *out = 0; int amt, got; int wanted = 0; char *z; - char zCmdFName[MAX_PATH]; char zRequestFName[MAX_PATH]; char zReplyFName[MAX_PATH]; char zCmd[2000]; /* Command-line to process the request */ char zHdr[2000]; /* The HTTP request header */ - sqlite3_snprintf(MAX_PATH, zCmdFName, - "%s_cmd%d.txt", zTempPrefix, p->id); sqlite3_snprintf(MAX_PATH, zRequestFName, "%s_in%d.txt", zTempPrefix, p->id); sqlite3_snprintf(MAX_PATH, zReplyFName, "%s_out%d.txt", zTempPrefix, p->id); amt = 0; @@ -111,21 +108,13 @@ } wanted -= got; } fclose(out); out = 0; - sqlite3_snprintf(sizeof(zCmd), zCmd, "%s%s\n%s\n%s\n%s", - get_utf8_bom(0), g.zRepositoryName, zRequestFName, zReplyFName, - inet_ntoa(p->addr.sin_addr) - ); - out = fossil_fopen(zCmdFName, "wb"); - if( out==0 ) goto end_request; - fwrite(zCmd, 1, strlen(zCmd), out); - fclose(out); - - sqlite3_snprintf(sizeof(zCmd), zCmd, "\"%s\" http -args \"%s\" --nossl%s", - g.nameOfExe, zCmdFName, p->zOptions + sqlite3_snprintf(sizeof(zCmd), zCmd, "\"%s\" http \"%s\" %s %s %s --nossl%s", + g.nameOfExe, g.zRepositoryName, zRequestFName, zReplyFName, + inet_ntoa(p->addr.sin_addr), p->zOptions ); fossil_system(zCmd); in = fossil_fopen(zReplyFName, "rb"); if( in ){ while( (got = fread(zHdr, 1, sizeof(zHdr), in))>0 ){ @@ -137,11 +126,10 @@ if( out ) fclose(out); if( in ) fclose(in); closesocket(p->s); file_delete(zRequestFName); file_delete(zReplyFName); - file_delete(zCmdFName); free(p); } /* ** Process a single incoming SCGI request. Index: src/wysiwyg.c ================================================================== --- src/wysiwyg.c +++ src/wysiwyg.c @@ -228,18 +228,18 @@ @
            %s(zContent)
            @