Fossil SCM
Merge latest trunk
Commit
befd44c747405c1abb9264a14fe796cc648ffb40
Parent
0746fbe416408de…
71 files changed
+26
+4
-4
+29
+82
+1
+43
+68
+3
+3
+1
+23
+75
+68
+23
+75
+1
+3
+3
+27
+1
+1
+18
+6
+1
+13
+105
+1
+38
+2
-2
+3
-2
+7
+10
-2
+3
+4
-4
+192
+41
-24
+9
+77
-93
+19
+41
-38
+1
-3
+1
+77
-14
+24
+59
-59
+15
-4
+27
-7
+3
-3
+1
-1
+17
-14
+1
-1
+55
-16
+1
+196
-1310
+2
+59
-9
+2
-2
+3
+64
-240
+2
-1
+1
-1
+1
-1
+1
+5
-4
+10
+2
-2
+27
-2
+24
-2
+26
-2
+2
-2
+1
-1
~
.dockerignore
~
Dockerfile
~
skins/README.md
~
skins/black_and_white/css.txt
~
skins/black_and_white/footer.txt
~
skins/black_and_white/header.txt
~
skins/default/css.txt
~
skins/default/footer.txt
~
skins/default/header.txt
~
skins/eagle/css.txt
~
skins/eagle/footer.txt
~
skins/eagle/header.txt
~
skins/enhanced1/css.txt
~
skins/enhanced1/footer.txt
~
skins/enhanced1/header.txt
~
skins/etienne1/README.md
~
skins/etienne1/css.txt
~
skins/etienne1/footer.txt
~
skins/etienne1/header.txt
~
skins/khaki/css.txt
~
skins/khaki/footer.txt
~
skins/khaki/header.txt
~
skins/plain_gray/css.txt
~
skins/plain_gray/footer.txt
~
skins/plain_gray/header.txt
~
skins/rounded1/css.txt
~
skins/rounded1/footer.txt
~
skins/rounded1/header.txt
~
src/attach.c
~
src/branch.c
~
src/browse.c
~
src/builtin.c
~
src/cgi.c
~
src/codecheck1.c
~
src/configure.c
~
src/db.c
~
src/diff.tcl
~
src/doc.c
~
src/file.c
~
src/http_socket.c
~
src/info.c
~
src/login.c
~
src/main.c
~
src/main.mk
~
src/makeheaders.c
~
src/makemake.tcl
~
src/mkbuiltin.c
~
src/mkindex.c
~
src/mkversion.c
~
src/report.c
~
src/search.c
~
src/setup.c
~
src/sitemap.c
~
src/skins.c
~
src/sqlcmd.c
~
src/sqlite3.c
~
src/sqlite3.h
~
src/stat.c
~
src/style.c
~
src/tag.c
~
src/th.h
~
src/translate.c
~
src/url.c
~
src/user.c
~
src/util.c
~
src/xfer.c
~
win/Makefile.mingw
~
win/Makefile.mingw.mistachkin
~
win/Makefile.msc
~
win/include/unistd.h
~
www/build.wiki
+26
| --- a/.dockerignore | ||
| +++ b/.dockerignore | ||
| @@ -0,0 +1,26 @@ | ||
| 1 | +_FOSSIL_ | |
| 2 | +.fslckout | |
| 3 | +ajax | |
| 4 | +art | |
| 5 | +autosetup | |
| 6 | +bld | |
| 7 | +compat | |
| 8 | +debian | |
| 9 | +fossil | |
| 10 | +fossil.exe | |
| 11 | +setup | |
| 12 | +src | |
| 13 | +test | |
| 14 | +tools | |
| 15 | +win | |
| 16 | +wbld | |
| 17 | +win | |
| 18 | +www | |
| 19 | +*.a | |
| 20 | +*.lib | |
| 21 | +*.log | |
| 22 | +*.manifest | |
| 23 | +*.o | |
| 24 | +*.obj | |
| 25 | +*.pdb | |
| 26 | +*.res |
| --- a/.dockerignore | |
| +++ b/.dockerignore | |
| @@ -0,0 +1,26 @@ | |
| --- a/.dockerignore | |
| +++ b/.dockerignore | |
| @@ -0,0 +1,26 @@ | |
| 1 | _FOSSIL_ |
| 2 | .fslckout |
| 3 | ajax |
| 4 | art |
| 5 | autosetup |
| 6 | bld |
| 7 | compat |
| 8 | debian |
| 9 | fossil |
| 10 | fossil.exe |
| 11 | setup |
| 12 | src |
| 13 | test |
| 14 | tools |
| 15 | win |
| 16 | wbld |
| 17 | win |
| 18 | www |
| 19 | *.a |
| 20 | *.lib |
| 21 | *.log |
| 22 | *.manifest |
| 23 | *.o |
| 24 | *.obj |
| 25 | *.pdb |
| 26 | *.res |
+4
-4
| --- Dockerfile | ||
| +++ Dockerfile | ||
| @@ -2,21 +2,21 @@ | ||
| 2 | 2 | # Dockerfile for Fossil |
| 3 | 3 | ### |
| 4 | 4 | FROM fedora:21 |
| 5 | 5 | |
| 6 | 6 | ### Now install some additional parts we will need for the build |
| 7 | -RUN yum update -y && yum install -y gcc make zlib-devel openssl-devel tcl-devel tar && yum clean all && groupadd -r fossil -g 433 && useradd -u 431 -r -g fossil -d /opt/fossil -s /sbin/nologin -c "Fossil user" fossil | |
| 7 | +RUN yum update -y && yum install -y gcc make zlib-devel openssl-devel tcl tar && yum clean all && groupadd -r fossil -g 433 && useradd -u 431 -r -g fossil -d /opt/fossil -s /sbin/nologin -c "Fossil user" fossil | |
| 8 | 8 | |
| 9 | -### If you want to build "trunk", change the next line accordingly. | |
| 10 | -ENV FOSSIL_INSTALL_VERSION release | |
| 9 | +### If you want to build "release", change the next line accordingly. | |
| 10 | +ENV FOSSIL_INSTALL_VERSION trunk | |
| 11 | 11 | |
| 12 | 12 | RUN curl "http://www.fossil-scm.org/index.html/tarball/fossil-src.tar.gz?name=fossil-src&uuid=${FOSSIL_INSTALL_VERSION}" | tar zx |
| 13 | 13 | RUN cd fossil-src && ./configure --disable-lineedit --disable-fusefs --json --with-th1-docs --with-th1-hooks --with-tcl --with-tcl-stubs --with-tcl-private-stubs && make; |
| 14 | 14 | RUN cp fossil-src/fossil /usr/bin && rm -rf fossil-src && chmod a+rx /usr/bin/fossil && mkdir -p /opt/fossil && chown fossil:fossil /opt/fossil |
| 15 | 15 | |
| 16 | 16 | ### Build is done, remove modules no longer needed |
| 17 | -RUN yum remove -y gcc make zlib-devel openssl-devel tcl-devel tar && yum clean all | |
| 17 | +RUN yum remove -y gcc make zlib-devel openssl-devel tar && yum clean all | |
| 18 | 18 | |
| 19 | 19 | USER fossil |
| 20 | 20 | |
| 21 | 21 | ENV HOME /opt/fossil |
| 22 | 22 | |
| 23 | 23 | |
| 24 | 24 | ADDED skins/README.md |
| 25 | 25 | ADDED skins/black_and_white/css.txt |
| 26 | 26 | ADDED skins/black_and_white/footer.txt |
| 27 | 27 | ADDED skins/black_and_white/header.txt |
| 28 | 28 | ADDED skins/default/css.txt |
| 29 | 29 | ADDED skins/default/footer.txt |
| 30 | 30 | ADDED skins/default/header.txt |
| 31 | 31 | ADDED skins/eagle/css.txt |
| 32 | 32 | ADDED skins/eagle/footer.txt |
| 33 | 33 | ADDED skins/eagle/header.txt |
| 34 | 34 | ADDED skins/enhanced1/css.txt |
| 35 | 35 | ADDED skins/enhanced1/footer.txt |
| 36 | 36 | ADDED skins/enhanced1/header.txt |
| 37 | 37 | ADDED skins/etienne1/README.md |
| 38 | 38 | ADDED skins/etienne1/css.txt |
| 39 | 39 | ADDED skins/etienne1/footer.txt |
| 40 | 40 | ADDED skins/etienne1/header.txt |
| 41 | 41 | ADDED skins/khaki/css.txt |
| 42 | 42 | ADDED skins/khaki/footer.txt |
| 43 | 43 | ADDED skins/khaki/header.txt |
| 44 | 44 | ADDED skins/plain_gray/css.txt |
| 45 | 45 | ADDED skins/plain_gray/footer.txt |
| 46 | 46 | ADDED skins/plain_gray/header.txt |
| 47 | 47 | ADDED skins/rounded1/css.txt |
| 48 | 48 | ADDED skins/rounded1/footer.txt |
| 49 | 49 | ADDED skins/rounded1/header.txt |
| --- Dockerfile | |
| +++ Dockerfile | |
| @@ -2,21 +2,21 @@ | |
| 2 | # Dockerfile for Fossil |
| 3 | ### |
| 4 | FROM fedora:21 |
| 5 | |
| 6 | ### Now install some additional parts we will need for the build |
| 7 | RUN yum update -y && yum install -y gcc make zlib-devel openssl-devel tcl-devel tar && yum clean all && groupadd -r fossil -g 433 && useradd -u 431 -r -g fossil -d /opt/fossil -s /sbin/nologin -c "Fossil user" fossil |
| 8 | |
| 9 | ### If you want to build "trunk", change the next line accordingly. |
| 10 | ENV FOSSIL_INSTALL_VERSION release |
| 11 | |
| 12 | RUN curl "http://www.fossil-scm.org/index.html/tarball/fossil-src.tar.gz?name=fossil-src&uuid=${FOSSIL_INSTALL_VERSION}" | tar zx |
| 13 | RUN cd fossil-src && ./configure --disable-lineedit --disable-fusefs --json --with-th1-docs --with-th1-hooks --with-tcl --with-tcl-stubs --with-tcl-private-stubs && make; |
| 14 | RUN cp fossil-src/fossil /usr/bin && rm -rf fossil-src && chmod a+rx /usr/bin/fossil && mkdir -p /opt/fossil && chown fossil:fossil /opt/fossil |
| 15 | |
| 16 | ### Build is done, remove modules no longer needed |
| 17 | RUN yum remove -y gcc make zlib-devel openssl-devel tcl-devel tar && yum clean all |
| 18 | |
| 19 | USER fossil |
| 20 | |
| 21 | ENV HOME /opt/fossil |
| 22 | |
| 23 | |
| 24 | DDED skins/README.md |
| 25 | DDED skins/black_and_white/css.txt |
| 26 | DDED skins/black_and_white/footer.txt |
| 27 | DDED skins/black_and_white/header.txt |
| 28 | DDED skins/default/css.txt |
| 29 | DDED skins/default/footer.txt |
| 30 | DDED skins/default/header.txt |
| 31 | DDED skins/eagle/css.txt |
| 32 | DDED skins/eagle/footer.txt |
| 33 | DDED skins/eagle/header.txt |
| 34 | DDED skins/enhanced1/css.txt |
| 35 | DDED skins/enhanced1/footer.txt |
| 36 | DDED skins/enhanced1/header.txt |
| 37 | DDED skins/etienne1/README.md |
| 38 | DDED skins/etienne1/css.txt |
| 39 | DDED skins/etienne1/footer.txt |
| 40 | DDED skins/etienne1/header.txt |
| 41 | DDED skins/khaki/css.txt |
| 42 | DDED skins/khaki/footer.txt |
| 43 | DDED skins/khaki/header.txt |
| 44 | DDED skins/plain_gray/css.txt |
| 45 | DDED skins/plain_gray/footer.txt |
| 46 | DDED skins/plain_gray/header.txt |
| 47 | DDED skins/rounded1/css.txt |
| 48 | DDED skins/rounded1/footer.txt |
| 49 | DDED skins/rounded1/header.txt |
| --- Dockerfile | |
| +++ Dockerfile | |
| @@ -2,21 +2,21 @@ | |
| 2 | # Dockerfile for Fossil |
| 3 | ### |
| 4 | FROM fedora:21 |
| 5 | |
| 6 | ### Now install some additional parts we will need for the build |
| 7 | RUN yum update -y && yum install -y gcc make zlib-devel openssl-devel tcl tar && yum clean all && groupadd -r fossil -g 433 && useradd -u 431 -r -g fossil -d /opt/fossil -s /sbin/nologin -c "Fossil user" fossil |
| 8 | |
| 9 | ### If you want to build "release", change the next line accordingly. |
| 10 | ENV FOSSIL_INSTALL_VERSION trunk |
| 11 | |
| 12 | RUN curl "http://www.fossil-scm.org/index.html/tarball/fossil-src.tar.gz?name=fossil-src&uuid=${FOSSIL_INSTALL_VERSION}" | tar zx |
| 13 | RUN cd fossil-src && ./configure --disable-lineedit --disable-fusefs --json --with-th1-docs --with-th1-hooks --with-tcl --with-tcl-stubs --with-tcl-private-stubs && make; |
| 14 | RUN cp fossil-src/fossil /usr/bin && rm -rf fossil-src && chmod a+rx /usr/bin/fossil && mkdir -p /opt/fossil && chown fossil:fossil /opt/fossil |
| 15 | |
| 16 | ### Build is done, remove modules no longer needed |
| 17 | RUN yum remove -y gcc make zlib-devel openssl-devel tar && yum clean all |
| 18 | |
| 19 | USER fossil |
| 20 | |
| 21 | ENV HOME /opt/fossil |
| 22 | |
| 23 | |
| 24 | DDED skins/README.md |
| 25 | DDED skins/black_and_white/css.txt |
| 26 | DDED skins/black_and_white/footer.txt |
| 27 | DDED skins/black_and_white/header.txt |
| 28 | DDED skins/default/css.txt |
| 29 | DDED skins/default/footer.txt |
| 30 | DDED skins/default/header.txt |
| 31 | DDED skins/eagle/css.txt |
| 32 | DDED skins/eagle/footer.txt |
| 33 | DDED skins/eagle/header.txt |
| 34 | DDED skins/enhanced1/css.txt |
| 35 | DDED skins/enhanced1/footer.txt |
| 36 | DDED skins/enhanced1/header.txt |
| 37 | DDED skins/etienne1/README.md |
| 38 | DDED skins/etienne1/css.txt |
| 39 | DDED skins/etienne1/footer.txt |
| 40 | DDED skins/etienne1/header.txt |
| 41 | DDED skins/khaki/css.txt |
| 42 | DDED skins/khaki/footer.txt |
| 43 | DDED skins/khaki/header.txt |
| 44 | DDED skins/plain_gray/css.txt |
| 45 | DDED skins/plain_gray/footer.txt |
| 46 | DDED skins/plain_gray/header.txt |
| 47 | DDED skins/rounded1/css.txt |
| 48 | DDED skins/rounded1/footer.txt |
| 49 | DDED skins/rounded1/header.txt |
+29
| --- a/skins/README.md | ||
| +++ b/skins/README.md | ||
| @@ -0,0 +1,29 @@ | ||
| 1 | +Built-in Skins | |
| 2 | +============== | |
| 3 | + | |
| 4 | +Each subdirectory under this folder describes a three files in each subheader, | |
| 5 | +and the foothe Content Footer | |
| 6 | + | |
| 7 | +To improve an exieing built-in skin, simply edit the appropriate | |
| 8 | +files and recompile. | |
| 9 | + | |
| 10 | +To add a new skin: | |
| 11 | + | |
| 12 | + 1. Create a new subdirectory under skins/. (The new directory is | |
| 13 | + called "skins/newskin" below but you should use a new original | |
| 14 | + name, of course.) | |
| 15 | + | |
| 16 | + 2. Add files skins/newskin/css.txt, skins and skinheader.txt, | |
| 17 | + . Go to the src/ footer.txt.the src/ directory and rerun "tclsh makemake.tcl". This | |
| 18 | + step rebuilds the various makefiles so that they have dependencies | |
| 19 | + on the skin files you just installed. | |
| 20 | + | |
| 21 | + 4. Edit the BuiltinSkin[] array near the top of the src/skins.c source | |
| 22 | + file so that it describes and references the "newskin" skin. | |
| 23 | + | |
| 24 | + 5. Type "make" to rebuild. | |
| 25 | + | |
| 26 | +Development Hints | |
| 27 | +----------------- | |
| 28 | + | |
| 29 | +One way to develop a new skin is to copy th |
| --- a/skins/README.md | |
| +++ b/skins/README.md | |
| @@ -0,0 +1,29 @@ | |
| --- a/skins/README.md | |
| +++ b/skins/README.md | |
| @@ -0,0 +1,29 @@ | |
| 1 | Built-in Skins |
| 2 | ============== |
| 3 | |
| 4 | Each subdirectory under this folder describes a three files in each subheader, |
| 5 | and the foothe Content Footer |
| 6 | |
| 7 | To improve an exieing built-in skin, simply edit the appropriate |
| 8 | files and recompile. |
| 9 | |
| 10 | To add a new skin: |
| 11 | |
| 12 | 1. Create a new subdirectory under skins/. (The new directory is |
| 13 | called "skins/newskin" below but you should use a new original |
| 14 | name, of course.) |
| 15 | |
| 16 | 2. Add files skins/newskin/css.txt, skins and skinheader.txt, |
| 17 | . Go to the src/ footer.txt.the src/ directory and rerun "tclsh makemake.tcl". This |
| 18 | step rebuilds the various makefiles so that they have dependencies |
| 19 | on the skin files you just installed. |
| 20 | |
| 21 | 4. Edit the BuiltinSkin[] array near the top of the src/skins.c source |
| 22 | file so that it describes and references the "newskin" skin. |
| 23 | |
| 24 | 5. Type "make" to rebuild. |
| 25 | |
| 26 | Development Hints |
| 27 | ----------------- |
| 28 | |
| 29 | One way to develop a new skin is to copy th |
| --- a/skins/black_and_white/css.txt | ||
| +++ b/skins/black_and_white/css.txt | ||
| @@ -0,0 +1,82 @@ | ||
| 1 | +/* General settings for the entire page */ | |
| 2 | +body { | |
| 3 | + margin:0px 0px 0px 0px; | |
| 4 | + padding:0px; | |
| 5 | + font-family:verdana, arial, helvetica, "sans serif"; | |
| 6 | + color:#333; | |
| 7 | + background-color:white; | |
| 8 | +mx-text-size-adjust: none; | |
| 9 | +} | |
| 10 | + | |
| 11 | +/* consistent colours */ | |
| 12 | +h2 { | |
| 13 | + color: #333; | |
| 14 | +} | |
| 15 | +h3 { | |
| 16 | + color: #333; | |
| 17 | +} | |
| 18 | + | |
| 19 | +/* The project logo in the upper left-hand corner of each page */ | |
| 20 | +div.logo { | |
| 21 | + display: table-cell; | |
| 22 | + text-align: left; | |
| 23 | + vertical-align: bottom; | |
| 24 | + font-weight: bold; | |
| 25 | + color: #333; | |
| 26 | + white-space: nowrap; | |
| 27 | +} | |
| 28 | + | |
| 29 | +/* The page title centered at the top of each page */ | |
| 30 | +div.title { | |
| 31 | + -size: 2em; | |
| 32 | + font-weight: bold; | |
| 33 | + text-align: center; | |
| 34 | + color: #333; | |
| 35 | + vertical-align: bot The login status message in the top right-hand corner */ | |
| 36 | +div.status { | |
| 37 | + display: table-cell; | |
| 38 | + padding-right: 10px; | |
| 39 | + text-align: right; | |
| 40 | + vertical-align: bottom; | |
| 41 | + padding-bottom: 5px; | |
| 42 | + color: #333; | |
| 43 | + font-size: 0.8em; | |
| 44 | + font-weight: bold; | |
| 45 | + white-space: nowrap; | |
| 46 | +} | |
| 47 | + | |
| 48 | +/* The header across the top of the page */ | |
| 49 | +div.header { | |
| 50 | + margin:10px 0px 10px 0px; | |
| 51 | + padding:1px 0px 0px 20px; | |
| 52 | + border-style:solid; | |
| 53 | + border-color:black; | |
| 54 | + border-width:1px 0px; | |
| 55 | + background-color:#eee; | |
| 56 | +} | |
| 57 | + | |
| 58 | +/* The main menu bar that appears at the top left of the page beneath | |
| 59 | +** the header. Width must be co-ordinated wdiv.mainmenu { | |
| 60 | + float: left; | |
| 61 | + margin-left: 10px; | |
| 62 | + margin-right: vertical-align: bottpadding:5px; | |
| 63 | + background-color:#eee; | |
| 64 | + border:1px solid #999; | |
| 65 | + width:8em; | |
| 66 | +} | |
| 67 | + | |
| 68 | +/* Main menu is now a list */ | |
| 69 | +diin menu is now a list */div.mainmenu a, di:none; | |
| 70 | +} | |
| 71 | +nav.mainmenu a, nav.mainmenu a:visited{ | |
| 72 | + padding: 1px 10px 1px 10px; | |
| 73 | + color: #333; | |
| 74 | +div.mainmenu a:hover { | |
| 75 | + color: #eee; | |
| 76 | + background-color: #333; | |
| 77 | +} | |
| 78 | + | |
| 79 | +/* Container for the sub-menu and content so they don't spread | |
| 80 | +** out underneath the main menu */ | |
| 81 | +#container { | |
| 82 | + padding-leftdidiv.submenu a, didi/* General settings for the en |
| --- a/skins/black_and_white/css.txt | |
| +++ b/skins/black_and_white/css.txt | |
| @@ -0,0 +1,82 @@ | |
| --- a/skins/black_and_white/css.txt | |
| +++ b/skins/black_and_white/css.txt | |
| @@ -0,0 +1,82 @@ | |
| 1 | /* General settings for the entire page */ |
| 2 | body { |
| 3 | margin:0px 0px 0px 0px; |
| 4 | padding:0px; |
| 5 | font-family:verdana, arial, helvetica, "sans serif"; |
| 6 | color:#333; |
| 7 | background-color:white; |
| 8 | mx-text-size-adjust: none; |
| 9 | } |
| 10 | |
| 11 | /* consistent colours */ |
| 12 | h2 { |
| 13 | color: #333; |
| 14 | } |
| 15 | h3 { |
| 16 | color: #333; |
| 17 | } |
| 18 | |
| 19 | /* The project logo in the upper left-hand corner of each page */ |
| 20 | div.logo { |
| 21 | display: table-cell; |
| 22 | text-align: left; |
| 23 | vertical-align: bottom; |
| 24 | font-weight: bold; |
| 25 | color: #333; |
| 26 | white-space: nowrap; |
| 27 | } |
| 28 | |
| 29 | /* The page title centered at the top of each page */ |
| 30 | div.title { |
| 31 | -size: 2em; |
| 32 | font-weight: bold; |
| 33 | text-align: center; |
| 34 | color: #333; |
| 35 | vertical-align: bot The login status message in the top right-hand corner */ |
| 36 | div.status { |
| 37 | display: table-cell; |
| 38 | padding-right: 10px; |
| 39 | text-align: right; |
| 40 | vertical-align: bottom; |
| 41 | padding-bottom: 5px; |
| 42 | color: #333; |
| 43 | font-size: 0.8em; |
| 44 | font-weight: bold; |
| 45 | white-space: nowrap; |
| 46 | } |
| 47 | |
| 48 | /* The header across the top of the page */ |
| 49 | div.header { |
| 50 | margin:10px 0px 10px 0px; |
| 51 | padding:1px 0px 0px 20px; |
| 52 | border-style:solid; |
| 53 | border-color:black; |
| 54 | border-width:1px 0px; |
| 55 | background-color:#eee; |
| 56 | } |
| 57 | |
| 58 | /* The main menu bar that appears at the top left of the page beneath |
| 59 | ** the header. Width must be co-ordinated wdiv.mainmenu { |
| 60 | float: left; |
| 61 | margin-left: 10px; |
| 62 | margin-right: vertical-align: bottpadding:5px; |
| 63 | background-color:#eee; |
| 64 | border:1px solid #999; |
| 65 | width:8em; |
| 66 | } |
| 67 | |
| 68 | /* Main menu is now a list */ |
| 69 | diin menu is now a list */div.mainmenu a, di:none; |
| 70 | } |
| 71 | nav.mainmenu a, nav.mainmenu a:visited{ |
| 72 | padding: 1px 10px 1px 10px; |
| 73 | color: #333; |
| 74 | div.mainmenu a:hover { |
| 75 | color: #eee; |
| 76 | background-color: #333; |
| 77 | } |
| 78 | |
| 79 | /* Container for the sub-menu and content so they don't spread |
| 80 | ** out underneath the main menu */ |
| 81 | #container { |
| 82 | padding-leftdidiv.submenu a, didi/* General settings for the en |
| --- a/skins/black_and_white/footer.txt | ||
| +++ b/skins/black_and_white/footer.txt | ||
| @@ -0,0 +1 @@ | ||
| 1 | +< |
| --- a/skins/black_and_white/footer.txt | |
| +++ b/skins/black_and_white/footer.txt | |
| @@ -0,0 +1 @@ | |
| --- a/skins/black_and_white/footer.txt | |
| +++ b/skins/black_and_white/footer.txt | |
| @@ -0,0 +1 @@ | |
| 1 | < |
| --- a/skins/black_and_white/header.txt | ||
| +++ b/skins/black_and_white/header.txt | ||
| @@ -0,0 +1,43 @@ | ||
| 1 | +<html> | |
| 2 | +<head> | |
| 3 | +<base href="$baseu>$<project_name> | |
| 4 | + </div> | |
| 5 | + <div class="title">$<title></div> | |
| 6 | + <diiv class="status"><th1> | |
| 7 | + if {[i puts "Logged in as $login" | |
| 8 | + } else { | |
| 9 | + in as $login" | |
| 10 | + } else { | |
| 11 | + } | |
| 12 | + </th1></div> | |
| 13 | +</div> | |
| 14 | +<diiter class} $mainmenu { | |
| 15 | + html "<a href='$home$index_page'>Htimeline'>Timelintree?ci=tip'>Filbrlist'>Branches</a>\n"taglist'>Tags</a>\n" | |
| 16 | +} | |
| 17 | +if {[anycap 23456] || [anoncap 2] || [anoncap 3]forum'>Forum</a>\n"[anoncap r]ticket'>Tickewiki'>Wiki</a>\n" | |
| 18 | +} | |
| 19 | +if {[hascap s]etup'>Admin<etup_ulist'>Users</a>\n" | |
| 20 | +} | |
| 21 | +if {[i puts "Logged in as $lohtml "<a href='$home/login'>Login<: $<title></title> | |
| 22 | +<link rel="alternate" type="application/rss+xml" title="RSS Feed" | |
| 23 | + href="$home/timeline.rss"> | |
| 24 | +<link rel="styleshasd> | |
| 25 | +<base href="$baseu>$<project_name> | |
| 26 | + </div> | |
| 27 | + <div class="title"<html> | |
| 28 | +<ss} $mainmenu { | |
| 29 | + html "<a href='$home$index_page'>Htimeline'>Timelintree?ci=tip'>Filbrlist'>Branches</a>\n"taglist'>Tags</a>\n" | |
| 30 | +} | |
| 31 | +if {[anycap 23456] || [anoncap 2] |reportlisoncap 3]forum'>Forum</a>\n"[anoncap r]ticket'>Tickewikiv class="logo"> | |
| 32 | + <img src="$logo_image_url" alt="logo"> | |
| 33 | + <br />$<projhascap ="RSS Feed" | |
| 34 | + href="$home/tss="status"><th1> | |
| 35 | + if {[ihastatus"><th1> | |
| 36 | + if {[i puts "Logged in as $login" | |
| 37 | + } else { | |
| 38 | + in as $login" | |
| 39 | + } else { | |
| 40 | + } | |
| 41 | + </th1></div> | |
| 42 | +</div> | |
| 43 | +<diiter clas |
| --- a/skins/black_and_white/header.txt | |
| +++ b/skins/black_and_white/header.txt | |
| @@ -0,0 +1,43 @@ | |
| --- a/skins/black_and_white/header.txt | |
| +++ b/skins/black_and_white/header.txt | |
| @@ -0,0 +1,43 @@ | |
| 1 | <html> |
| 2 | <head> |
| 3 | <base href="$baseu>$<project_name> |
| 4 | </div> |
| 5 | <div class="title">$<title></div> |
| 6 | <diiv class="status"><th1> |
| 7 | if {[i puts "Logged in as $login" |
| 8 | } else { |
| 9 | in as $login" |
| 10 | } else { |
| 11 | } |
| 12 | </th1></div> |
| 13 | </div> |
| 14 | <diiter class} $mainmenu { |
| 15 | html "<a href='$home$index_page'>Htimeline'>Timelintree?ci=tip'>Filbrlist'>Branches</a>\n"taglist'>Tags</a>\n" |
| 16 | } |
| 17 | if {[anycap 23456] || [anoncap 2] || [anoncap 3]forum'>Forum</a>\n"[anoncap r]ticket'>Tickewiki'>Wiki</a>\n" |
| 18 | } |
| 19 | if {[hascap s]etup'>Admin<etup_ulist'>Users</a>\n" |
| 20 | } |
| 21 | if {[i puts "Logged in as $lohtml "<a href='$home/login'>Login<: $<title></title> |
| 22 | <link rel="alternate" type="application/rss+xml" title="RSS Feed" |
| 23 | href="$home/timeline.rss"> |
| 24 | <link rel="styleshasd> |
| 25 | <base href="$baseu>$<project_name> |
| 26 | </div> |
| 27 | <div class="title"<html> |
| 28 | <ss} $mainmenu { |
| 29 | html "<a href='$home$index_page'>Htimeline'>Timelintree?ci=tip'>Filbrlist'>Branches</a>\n"taglist'>Tags</a>\n" |
| 30 | } |
| 31 | if {[anycap 23456] || [anoncap 2] |reportlisoncap 3]forum'>Forum</a>\n"[anoncap r]ticket'>Tickewikiv class="logo"> |
| 32 | <img src="$logo_image_url" alt="logo"> |
| 33 | <br />$<projhascap ="RSS Feed" |
| 34 | href="$home/tss="status"><th1> |
| 35 | if {[ihastatus"><th1> |
| 36 | if {[i puts "Logged in as $login" |
| 37 | } else { |
| 38 | in as $login" |
| 39 | } else { |
| 40 | } |
| 41 | </th1></div> |
| 42 | </div> |
| 43 | <diiter clas |
+68
| --- a/skins/default/css.txt | ||
| +++ b/skins/default/css.txt | ||
| @@ -0,0 +1,68 @@ | ||
| 1 | +/* General settings for the entire page */ | |
| 2 | +body { | |
| 3 | + margin: 0ex 1ex; | |
| 4 | + padding: 0px; | |
| 5 | + background-color: white; | |
| 6 | + font-family: sans-serif; | |
| 7 | +mx-text-size-adjust: none; | |
| 8 | +} | |
| 9 | + | |
| 10 | +/* The project logo in the upper left-hand corner of each page */ | |
| 11 | +div.logo { | |
| 12 | + display: table-cell; | |
| 13 | + text-align: center; | |
| 14 | + vertical-align: bottom; | |
| 15 | + font-weight: bold; | |
| 16 | + co20or: #558195; | |
| 17 | + min-width: 50px; | |
| 18 | + white-space: nowrap; | |
| 19 | +} | |
| 20 | + | |
| 21 | +/* The page title centered at the top of each page */ | |
| 22 | +div.title { | |
| 23 | + display: table-cell; | |
| 24 | + font-size: 2em; | |
| 25 | + font-weight: bold; | |
| 26 | + text-align: center; | |
| 27 | + padding: 0 0 0 1em; | |
| 28 | + color: #558195; | |
| 29 | + vertical-align: bottom; | |
| 30 | + width: 100%; | |
| 31 | +} | |
| 32 | + | |
| 33 | +/* The login status message in the top right-hand corner */ | |
| 34 | +div.status { | |
| 35 | + display: table-cell; | |
| 36 | + text-align: right; | |
| 37 | + vertical-align: bottom; | |
| 38 | + color: #558195; | |
| 39 | + font-size: 0.8min-width: 20or: #558195e-space: nowrap; | |
| 40 | +} | |
| 41 | + | |
| 42 | +/* The header across the top of the page */ | |
| 43 | +div.header { | |
| 44 | + display: table; | |
| 45 | + width: 100%; | |
| 46 | +} | |
| 47 | + | |
| 48 | +/* The main menu bar that appears at the top of the page beneath | |
| 49 | +** the header */ | |
| 50 | +diisplay: table; | |
| 51 | + winmenu { | |
| 52 | + padding: 5px; | |
| 53 | + font-size: 0.9em; | |
| 54 | + font-weight: bold; | |
| 55 | + text-align: center; | |
| 56 | + letter-spacing: 1px; | |
| 57 | + background-color: #558195; | |
| 58 | + border-top-left-radius: 8px; | |
| 59 | + border-top-right-radius: 8px; | |
| 60 | + color: white; | |
| 61 | +} | |
| 62 | + | |
| 63 | +/* The submenu bar that *sometimes* appedis below the main menu */ | |
| 64 | +div.submenu, div.sectionmenu { | |
| 65 | + padding: 3px 10px 3px 0px; | |
| 66 | + font-size: 0.9em; | |
| 67 | + text-align: center; | |
| 68 | + background-color: div.mainmenu a, div |
| --- a/skins/default/css.txt | |
| +++ b/skins/default/css.txt | |
| @@ -0,0 +1,68 @@ | |
| --- a/skins/default/css.txt | |
| +++ b/skins/default/css.txt | |
| @@ -0,0 +1,68 @@ | |
| 1 | /* General settings for the entire page */ |
| 2 | body { |
| 3 | margin: 0ex 1ex; |
| 4 | padding: 0px; |
| 5 | background-color: white; |
| 6 | font-family: sans-serif; |
| 7 | mx-text-size-adjust: none; |
| 8 | } |
| 9 | |
| 10 | /* The project logo in the upper left-hand corner of each page */ |
| 11 | div.logo { |
| 12 | display: table-cell; |
| 13 | text-align: center; |
| 14 | vertical-align: bottom; |
| 15 | font-weight: bold; |
| 16 | co20or: #558195; |
| 17 | min-width: 50px; |
| 18 | white-space: nowrap; |
| 19 | } |
| 20 | |
| 21 | /* The page title centered at the top of each page */ |
| 22 | div.title { |
| 23 | display: table-cell; |
| 24 | font-size: 2em; |
| 25 | font-weight: bold; |
| 26 | text-align: center; |
| 27 | padding: 0 0 0 1em; |
| 28 | color: #558195; |
| 29 | vertical-align: bottom; |
| 30 | width: 100%; |
| 31 | } |
| 32 | |
| 33 | /* The login status message in the top right-hand corner */ |
| 34 | div.status { |
| 35 | display: table-cell; |
| 36 | text-align: right; |
| 37 | vertical-align: bottom; |
| 38 | color: #558195; |
| 39 | font-size: 0.8min-width: 20or: #558195e-space: nowrap; |
| 40 | } |
| 41 | |
| 42 | /* The header across the top of the page */ |
| 43 | div.header { |
| 44 | display: table; |
| 45 | width: 100%; |
| 46 | } |
| 47 | |
| 48 | /* The main menu bar that appears at the top of the page beneath |
| 49 | ** the header */ |
| 50 | diisplay: table; |
| 51 | winmenu { |
| 52 | padding: 5px; |
| 53 | font-size: 0.9em; |
| 54 | font-weight: bold; |
| 55 | text-align: center; |
| 56 | letter-spacing: 1px; |
| 57 | background-color: #558195; |
| 58 | border-top-left-radius: 8px; |
| 59 | border-top-right-radius: 8px; |
| 60 | color: white; |
| 61 | } |
| 62 | |
| 63 | /* The submenu bar that *sometimes* appedis below the main menu */ |
| 64 | div.submenu, div.sectionmenu { |
| 65 | padding: 3px 10px 3px 0px; |
| 66 | font-size: 0.9em; |
| 67 | text-align: center; |
| 68 | background-color: div.mainmenu a, div |
| --- a/skins/default/footer.txt | ||
| +++ b/skins/default/footer.txt | ||
| @@ -0,0 +1,3 @@ | ||
| 1 | +<div class="footer"> | |
| 2 | +This page was generated in about | |
| 3 | +<th1>puts [expr {([utime]+[stime]+1000)/100 |
| --- a/skins/default/footer.txt | |
| +++ b/skins/default/footer.txt | |
| @@ -0,0 +1,3 @@ | |
| --- a/skins/default/footer.txt | |
| +++ b/skins/default/footer.txt | |
| @@ -0,0 +1,3 @@ | |
| 1 | <div class="footer"> |
| 2 | This page was generated in about |
| 3 | <th1>puts [expr {([utime]+[stime]+1000)/100 |
| --- a/skins/default/header.txt | ||
| +++ b/skins/default/header.txt | ||
| @@ -0,0 +1,3 @@ | ||
| 1 | +reportlis� }her} Wiki wideonlhas { | |
| 2 | +="her} Wiki wideonly | |
| 3 | +} |
| --- a/skins/default/header.txt | |
| +++ b/skins/default/header.txt | |
| @@ -0,0 +1,3 @@ | |
| --- a/skins/default/header.txt | |
| +++ b/skins/default/header.txt | |
| @@ -0,0 +1,3 @@ | |
| 1 | reportlis� }her} Wiki wideonlhas { |
| 2 | ="her} Wiki wideonly |
| 3 | } |
+1
| --- a/skins/eagle/css.txt | ||
| +++ b/skins/eagle/css.txt | ||
| @@ -0,0 +1 @@ | ||
| 1 | +/#canvas#485D7B |
| --- a/skins/eagle/css.txt | |
| +++ b/skins/eagle/css.txt | |
| @@ -0,0 +1 @@ | |
| --- a/skins/eagle/css.txt | |
| +++ b/skins/eagle/css.txt | |
| @@ -0,0 +1 @@ | |
| 1 | /#canvas#485D7B |
+23
| --- a/skins/eagle/footer.txt | ||
| +++ b/skins/eagle/footer.txt | ||
| @@ -0,0 +1,23 @@ | ||
| 1 | +<div class="footer"> | |
| 2 | + <th1> | |
| 3 | + proc getTclVersion {} { | |
| 4 | + if {[catch {tclEval info patchlevel} tclVersion] == 0} { | |
| 5 | + return "<a href=\"http://www.tcl.tk/\">Tcl</a> version $tclVersion" | |
| 6 | + } | |
| 7 | + return "" | |
| 8 | + } | |
| 9 | + proc getVersion { version } { | |
| 10 | + set length [string length $version] | |
| 11 | + return [string range $version 1 [expr {$length - 2}]] | |
| 12 | + } | |
| 13 | + set version [getVersion $manifest_version] | |
| 14 | + set tclVersion [getTclVersiowww.n] | |
| 15 | + set fossilUrl https://fossil-scm.org | |
| 16 | + e $manifest_date 11 end] | |
| 17 | + </th1> | |
| 18 | + This page was generated in about | |
| 19 | + <th1>puts [expr {([utime]+[stime]+1000)/1000*0.001}]</th1>s by | |
| 20 | + <a href="$fossilUrl/">Fossil</a> | |
| 21 | + version $release_version $tclVersion | |
| 22 | + <a href="$fossilUrl/index.html/info/$version">$manifest_vermanifest_date&div> | |
| 23 | +</body></html> |
| --- a/skins/eagle/footer.txt | |
| +++ b/skins/eagle/footer.txt | |
| @@ -0,0 +1,23 @@ | |
| --- a/skins/eagle/footer.txt | |
| +++ b/skins/eagle/footer.txt | |
| @@ -0,0 +1,23 @@ | |
| 1 | <div class="footer"> |
| 2 | <th1> |
| 3 | proc getTclVersion {} { |
| 4 | if {[catch {tclEval info patchlevel} tclVersion] == 0} { |
| 5 | return "<a href=\"http://www.tcl.tk/\">Tcl</a> version $tclVersion" |
| 6 | } |
| 7 | return "" |
| 8 | } |
| 9 | proc getVersion { version } { |
| 10 | set length [string length $version] |
| 11 | return [string range $version 1 [expr {$length - 2}]] |
| 12 | } |
| 13 | set version [getVersion $manifest_version] |
| 14 | set tclVersion [getTclVersiowww.n] |
| 15 | set fossilUrl https://fossil-scm.org |
| 16 | e $manifest_date 11 end] |
| 17 | </th1> |
| 18 | This page was generated in about |
| 19 | <th1>puts [expr {([utime]+[stime]+1000)/1000*0.001}]</th1>s by |
| 20 | <a href="$fossilUrl/">Fossil</a> |
| 21 | version $release_version $tclVersion |
| 22 | <a href="$fossilUrl/index.html/info/$version">$manifest_vermanifest_date&div> |
| 23 | </body></html> |
+75
| --- a/skins/eagle/header.txt | ||
| +++ b/skins/eagle/header.txt | ||
| @@ -0,0 +1,75 @@ | ||
| 1 | +<html> | |
| 2 | +<head> | |
| 3 | +<base href="$baseurl/$current_page" /> | |
| 4 | +<title>$<project_name>: $<title></title> | |
| 5 | +<link rel="alternate" type="application/rss+xml" title="RSS Feed" | |
| 6 | + href="$home/timeline.rss" /> | |
| 7 | +<link rel="stylesheet" href="$stylesheet_url" type="text/css" | |
| 8 | + media=<div class="header"> | |
| 9 | + <div class="logo"> | |
| 10 | + <th1> | |
| 11 | + ## | |
| 12 | + ## NOTE: The purpose of this procedure is to take the base URL of the | |
| 13 | + ## Fossil project and return the root of the entire web site using | |
| 14 | + ## the same URI scheme as the base URL (e.g. http or https). | |
| 15 | + ## | |
| 16 | + proc getLogoUrl { baseurl } { | |
| 17 | + set idx(first) [string first // $baseurl] | |
| 18 | + if {$idx(first) != -1} { | |
| 19 | + ## | |
| 20 | + ## NOTE: Skip second slash. | |
| 21 | + ## | |
| 22 | + set idx(first+1) [expr {$idx(first) + 2}] | |
| 23 | + ## | |
| 24 | + ## NOTE: (part 1) The [string first] command does NOT actually | |
| 25 | + ## support the optional startIndex argument as specified | |
| 26 | + ## in the TH1 support manual; therefore, we fake it by | |
| 27 | + ## using the [stange] command and then adding the | |
| 28 | + project_nameadding the | |
| 29 | + ## necessary offset to the result<th1> | |
| 30 | +low). In Tc, we could use the following ins} elscript | |
| 31 | + </th1> | |
| 32 | + ## | |
| 33 | + set idx(nextRange) [string range $baseurl $idx(first+1) funcdivif {$iif(e){ | |
| 34 | + e.innerHTML=d.toISOString().replace("T"," ").replace(/:\d\d\.\d+Z/,""ock();"$idx(firste $baseurl $idx> | |
| 35 | + <th1> | |
| 36 | + ## | |
| 37 | + ## NOT | |
| 38 | +<th1> | |
| 39 | +proc menulink {url name} { | |
| 40 | +name</a>\n" | |
| 41 | + } | |
| 42 | +} | |
| 43 | +menindex_page'>Home</a>\n" | |
| 44 | +name</a>\n" | |
| 45 | + } | |
| 46 | +} | |
| 47 | +me/help'>Help<>$name</a>\n" | |
| 48 | + } | |
| 49 | +} | |
| 50 | +me/timeline'>Timeline</a>$name</a>\n" | |
| 51 | + } | |
| 52 | +} | |
| 53 | +me/tree?ci=tip'>Filhas>$name</a>\n" | |
| 54 | + } | |
| 55 | +} | |
| 56 | +me/brlist'>Branches</a>\n" | |
| 57 | +>$name</a>\n" | |
| 58 | + } | |
| 59 | +} | |
| 60 | +hasaglist'>Tags</>$name</a>\n" | |
| 61 | + } | |
| 62 | +} | |
| 63 | +me/ticket'>Tickets</>$name</a>\n" | |
| 64 | + } | |
| 65 | +} | |
| 66 | +me/wikihashas name</a>\n" | |
| 67 | + } | |
| 68 | +} | |
| 69 | +me/setup_ulist'>Users</a>\n"<html>reportlisd> | |
| 70 | +<base href="$baseuse href="$baseurl/$c/login'>Logout</a>\n" | |
| 71 | +} else { | |
| 72 | +>$name</a>\n" | |
| 73 | + } | |
| 74 | +} | |
| 75 | +me |
| --- a/skins/eagle/header.txt | |
| +++ b/skins/eagle/header.txt | |
| @@ -0,0 +1,75 @@ | |
| --- a/skins/eagle/header.txt | |
| +++ b/skins/eagle/header.txt | |
| @@ -0,0 +1,75 @@ | |
| 1 | <html> |
| 2 | <head> |
| 3 | <base href="$baseurl/$current_page" /> |
| 4 | <title>$<project_name>: $<title></title> |
| 5 | <link rel="alternate" type="application/rss+xml" title="RSS Feed" |
| 6 | href="$home/timeline.rss" /> |
| 7 | <link rel="stylesheet" href="$stylesheet_url" type="text/css" |
| 8 | media=<div class="header"> |
| 9 | <div class="logo"> |
| 10 | <th1> |
| 11 | ## |
| 12 | ## NOTE: The purpose of this procedure is to take the base URL of the |
| 13 | ## Fossil project and return the root of the entire web site using |
| 14 | ## the same URI scheme as the base URL (e.g. http or https). |
| 15 | ## |
| 16 | proc getLogoUrl { baseurl } { |
| 17 | set idx(first) [string first // $baseurl] |
| 18 | if {$idx(first) != -1} { |
| 19 | ## |
| 20 | ## NOTE: Skip second slash. |
| 21 | ## |
| 22 | set idx(first+1) [expr {$idx(first) + 2}] |
| 23 | ## |
| 24 | ## NOTE: (part 1) The [string first] command does NOT actually |
| 25 | ## support the optional startIndex argument as specified |
| 26 | ## in the TH1 support manual; therefore, we fake it by |
| 27 | ## using the [stange] command and then adding the |
| 28 | project_nameadding the |
| 29 | ## necessary offset to the result<th1> |
| 30 | low). In Tc, we could use the following ins} elscript |
| 31 | </th1> |
| 32 | ## |
| 33 | set idx(nextRange) [string range $baseurl $idx(first+1) funcdivif {$iif(e){ |
| 34 | e.innerHTML=d.toISOString().replace("T"," ").replace(/:\d\d\.\d+Z/,""ock();"$idx(firste $baseurl $idx> |
| 35 | <th1> |
| 36 | ## |
| 37 | ## NOT |
| 38 | <th1> |
| 39 | proc menulink {url name} { |
| 40 | name</a>\n" |
| 41 | } |
| 42 | } |
| 43 | menindex_page'>Home</a>\n" |
| 44 | name</a>\n" |
| 45 | } |
| 46 | } |
| 47 | me/help'>Help<>$name</a>\n" |
| 48 | } |
| 49 | } |
| 50 | me/timeline'>Timeline</a>$name</a>\n" |
| 51 | } |
| 52 | } |
| 53 | me/tree?ci=tip'>Filhas>$name</a>\n" |
| 54 | } |
| 55 | } |
| 56 | me/brlist'>Branches</a>\n" |
| 57 | >$name</a>\n" |
| 58 | } |
| 59 | } |
| 60 | hasaglist'>Tags</>$name</a>\n" |
| 61 | } |
| 62 | } |
| 63 | me/ticket'>Tickets</>$name</a>\n" |
| 64 | } |
| 65 | } |
| 66 | me/wikihashas name</a>\n" |
| 67 | } |
| 68 | } |
| 69 | me/setup_ulist'>Users</a>\n"<html>reportlisd> |
| 70 | <base href="$baseuse href="$baseurl/$c/login'>Logout</a>\n" |
| 71 | } else { |
| 72 | >$name</a>\n" |
| 73 | } |
| 74 | } |
| 75 | me |
+68
| --- a/skins/enhanced1/css.txt | ||
| +++ b/skins/enhanced1/css.txt | ||
| @@ -0,0 +1,68 @@ | ||
| 1 | +/* General settings for the entire page */ | |
| 2 | +body { | |
| 3 | + margin: 0ex 1ex; | |
| 4 | + padding: 0px; | |
| 5 | + background-color: white; | |
| 6 | + font-family: sans-serif; | |
| 7 | +mx-text-size-adjust: none; | |
| 8 | +} | |
| 9 | + | |
| 10 | +/* The project logo in the upper left-hand corner of each page */ | |
| 11 | +div.logo { | |
| 12 | + display: table-cell; | |
| 13 | + text-align: center; | |
| 14 | + vertical-align: bottom; | |
| 15 | + font-weight: bold; | |
| 16 | + co20or: #558195; | |
| 17 | + min-width: 50px; | |
| 18 | + white-space: nowrap; | |
| 19 | +} | |
| 20 | + | |
| 21 | +/* The page title centered at the top of each page */ | |
| 22 | +div.title { | |
| 23 | + display: table-cell; | |
| 24 | + font-size: 2em; | |
| 25 | + font-weight: bold; | |
| 26 | + text-align: center; | |
| 27 | + padding: 0 0 0 1em; | |
| 28 | + color: #558195; | |
| 29 | + vertical-align: bottom; | |
| 30 | + width: 100%; | |
| 31 | +} | |
| 32 | + | |
| 33 | +/* The login status message in the top right-hand corner */ | |
| 34 | +div.status { | |
| 35 | + display: table-cell; | |
| 36 | + text-align: right; | |
| 37 | + vertical-align: bottom; | |
| 38 | + color: #558195; | |
| 39 | + font-size: 0.8min-width: 20or: #558195e-space: nowrap; | |
| 40 | +} | |
| 41 | + | |
| 42 | +/* The header across the top of the page */ | |
| 43 | +div.header { | |
| 44 | + display: table; | |
| 45 | + width: 100%; | |
| 46 | +} | |
| 47 | + | |
| 48 | +/* The main menu bar that appears at the top of the page beneath | |
| 49 | +** the header */ | |
| 50 | +diisplay: table; | |
| 51 | + winmenu { | |
| 52 | + padding: 5px; | |
| 53 | + font-size: 0.9em; | |
| 54 | + font-weight: bold; | |
| 55 | + text-align: center; | |
| 56 | + letter-spacing: 1px; | |
| 57 | + background-color: #558195; | |
| 58 | + border-top-left-radius: 8px; | |
| 59 | + border-top-right-radius: 8px; | |
| 60 | + color: white; | |
| 61 | +} | |
| 62 | + | |
| 63 | +/* The submenu bar that *sometimes* appedis below the main menu */ | |
| 64 | +div.submenu, div.sectionmenu { | |
| 65 | + padding: 3px 10px 3px 0px; | |
| 66 | + font-size: 0.9em; | |
| 67 | + text-align: center; | |
| 68 | + background-color: div.mainmenu a, div |
| --- a/skins/enhanced1/css.txt | |
| +++ b/skins/enhanced1/css.txt | |
| @@ -0,0 +1,68 @@ | |
| --- a/skins/enhanced1/css.txt | |
| +++ b/skins/enhanced1/css.txt | |
| @@ -0,0 +1,68 @@ | |
| 1 | /* General settings for the entire page */ |
| 2 | body { |
| 3 | margin: 0ex 1ex; |
| 4 | padding: 0px; |
| 5 | background-color: white; |
| 6 | font-family: sans-serif; |
| 7 | mx-text-size-adjust: none; |
| 8 | } |
| 9 | |
| 10 | /* The project logo in the upper left-hand corner of each page */ |
| 11 | div.logo { |
| 12 | display: table-cell; |
| 13 | text-align: center; |
| 14 | vertical-align: bottom; |
| 15 | font-weight: bold; |
| 16 | co20or: #558195; |
| 17 | min-width: 50px; |
| 18 | white-space: nowrap; |
| 19 | } |
| 20 | |
| 21 | /* The page title centered at the top of each page */ |
| 22 | div.title { |
| 23 | display: table-cell; |
| 24 | font-size: 2em; |
| 25 | font-weight: bold; |
| 26 | text-align: center; |
| 27 | padding: 0 0 0 1em; |
| 28 | color: #558195; |
| 29 | vertical-align: bottom; |
| 30 | width: 100%; |
| 31 | } |
| 32 | |
| 33 | /* The login status message in the top right-hand corner */ |
| 34 | div.status { |
| 35 | display: table-cell; |
| 36 | text-align: right; |
| 37 | vertical-align: bottom; |
| 38 | color: #558195; |
| 39 | font-size: 0.8min-width: 20or: #558195e-space: nowrap; |
| 40 | } |
| 41 | |
| 42 | /* The header across the top of the page */ |
| 43 | div.header { |
| 44 | display: table; |
| 45 | width: 100%; |
| 46 | } |
| 47 | |
| 48 | /* The main menu bar that appears at the top of the page beneath |
| 49 | ** the header */ |
| 50 | diisplay: table; |
| 51 | winmenu { |
| 52 | padding: 5px; |
| 53 | font-size: 0.9em; |
| 54 | font-weight: bold; |
| 55 | text-align: center; |
| 56 | letter-spacing: 1px; |
| 57 | background-color: #558195; |
| 58 | border-top-left-radius: 8px; |
| 59 | border-top-right-radius: 8px; |
| 60 | color: white; |
| 61 | } |
| 62 | |
| 63 | /* The submenu bar that *sometimes* appedis below the main menu */ |
| 64 | div.submenu, div.sectionmenu { |
| 65 | padding: 3px 10px 3px 0px; |
| 66 | font-size: 0.9em; |
| 67 | text-align: center; |
| 68 | background-color: div.mainmenu a, div |
| --- a/skins/enhanced1/footer.txt | ||
| +++ b/skins/enhanced1/footer.txt | ||
| @@ -0,0 +1,23 @@ | ||
| 1 | +<div class="footer"> | |
| 2 | + <th1> | |
| 3 | + proc getTclVersion {} { | |
| 4 | + if {[catch {tclEval info patchlevel} tclVersion] == 0} { | |
| 5 | + return "<a href=\"http://www.tcl.tk/\">Tcl</a> version $tclVersion" | |
| 6 | + } | |
| 7 | + return "" | |
| 8 | + } | |
| 9 | + proc getVersion { version } { | |
| 10 | + set length [string length $version] | |
| 11 | + return [string range $version 1 [expr {$length - 2}]] | |
| 12 | + } | |
| 13 | + set version [getVersion $manifest_version] | |
| 14 | + set tclVersion [getTclVersiowww.n] | |
| 15 | + set fossilUrl https://fossil-scm.org | |
| 16 | + e $manifest_date 11 end] | |
| 17 | + </th1> | |
| 18 | + This page was generated in about | |
| 19 | + <th1>puts [expr {([utime]+[stime]+1000)/1000*0.001}]</th1>s by | |
| 20 | + <a href="$fossilUrl/">Fossil</a> | |
| 21 | + version $release_version $tclVersion | |
| 22 | + <a href="$fossilUrl/index.html/info/$version">$manifest_vermanifest_date&div> | |
| 23 | +</body></html> |
| --- a/skins/enhanced1/footer.txt | |
| +++ b/skins/enhanced1/footer.txt | |
| @@ -0,0 +1,23 @@ | |
| --- a/skins/enhanced1/footer.txt | |
| +++ b/skins/enhanced1/footer.txt | |
| @@ -0,0 +1,23 @@ | |
| 1 | <div class="footer"> |
| 2 | <th1> |
| 3 | proc getTclVersion {} { |
| 4 | if {[catch {tclEval info patchlevel} tclVersion] == 0} { |
| 5 | return "<a href=\"http://www.tcl.tk/\">Tcl</a> version $tclVersion" |
| 6 | } |
| 7 | return "" |
| 8 | } |
| 9 | proc getVersion { version } { |
| 10 | set length [string length $version] |
| 11 | return [string range $version 1 [expr {$length - 2}]] |
| 12 | } |
| 13 | set version [getVersion $manifest_version] |
| 14 | set tclVersion [getTclVersiowww.n] |
| 15 | set fossilUrl https://fossil-scm.org |
| 16 | e $manifest_date 11 end] |
| 17 | </th1> |
| 18 | This page was generated in about |
| 19 | <th1>puts [expr {([utime]+[stime]+1000)/1000*0.001}]</th1>s by |
| 20 | <a href="$fossilUrl/">Fossil</a> |
| 21 | version $release_version $tclVersion |
| 22 | <a href="$fossilUrl/index.html/info/$version">$manifest_vermanifest_date&div> |
| 23 | </body></html> |
| --- a/skins/enhanced1/header.txt | ||
| +++ b/skins/enhanced1/header.txt | ||
| @@ -0,0 +1,75 @@ | ||
| 1 | +<html> | |
| 2 | +<head> | |
| 3 | +<base href="$baseurl/$current_page" /> | |
| 4 | +<title>$<project_name>: $<title></title> | |
| 5 | +<link rel="alternate" type="application/rss+xml" title="RSS Feed" | |
| 6 | + href="$home/timeline.rss" /> | |
| 7 | +<link rel="stylesheet" href="$stylesheet_url" type="text/css" | |
| 8 | + media=<div class="header"> | |
| 9 | + <div class="logo"> | |
| 10 | + <th1> | |
| 11 | + ## | |
| 12 | + ## NOTE: The purpose of this procedure is to take the base URL of the | |
| 13 | + ## Fossil project and return the root of the entire web site using | |
| 14 | + ## the same URI scheme as the base URL (e.g. http or https). | |
| 15 | + ## | |
| 16 | + proc getLogoUrl { baseurl } { | |
| 17 | + set idx(first) [string first // $baseurl] | |
| 18 | + if {$idx(first) != -1} { | |
| 19 | + ## | |
| 20 | + ## NOTE: Skip second slash. | |
| 21 | + ## | |
| 22 | + set idx(first+1) [expr {$idx(first) + 2}] | |
| 23 | + ## | |
| 24 | + ## NOTE: (part 1) The [string first] command does NOT actually | |
| 25 | + ## support the optional startIndex argument as specified | |
| 26 | + ## in the TH1 support manual; therefore, we fake it by | |
| 27 | + ## using the [stange] command and then adding the | |
| 28 | + project_nameadding the | |
| 29 | + ## necessary offset to the result<th1> | |
| 30 | +low). In Tc, we could use the following ins} elscript | |
| 31 | + </th1> | |
| 32 | + ## | |
| 33 | + set idx(nextRange) [string range $baseurl $idx(first+1) funcdivif {$iif(e){ | |
| 34 | + e.innerHTML=d.toISOString().replace("T"," ").replace(/:\d\d\.\d+Z/,""ock();"$idx(firste $baseurl $idx> | |
| 35 | + <th1> | |
| 36 | + ## | |
| 37 | + ## NOT | |
| 38 | +<th1> | |
| 39 | +proc menulink {url name} { | |
| 40 | +name</a>\n" | |
| 41 | + } | |
| 42 | +} | |
| 43 | +menindex_page'>Home</a>\n" | |
| 44 | +name</a>\n" | |
| 45 | + } | |
| 46 | +} | |
| 47 | +me/help'>Help<>$name</a>\n" | |
| 48 | + } | |
| 49 | +} | |
| 50 | +me/timeline'>Timeline</a>$name</a>\n" | |
| 51 | + } | |
| 52 | +} | |
| 53 | +me/tree?ci=tip'>Filhas>$name</a>\n" | |
| 54 | + } | |
| 55 | +} | |
| 56 | +me/brlist'>Branches</a>\n" | |
| 57 | +>$name</a>\n" | |
| 58 | + } | |
| 59 | +} | |
| 60 | +hasaglist'>Tags</>$name</a>\n" | |
| 61 | + } | |
| 62 | +} | |
| 63 | +me/ticket'>Tickets</>$name</a>\n" | |
| 64 | + } | |
| 65 | +} | |
| 66 | +me/wikihashas name</a>\n" | |
| 67 | + } | |
| 68 | +} | |
| 69 | +me/setup_ulist'>Users</a>\n"<html>reportlisd> | |
| 70 | +<base href="$baseuse href="$baseurl/$c/login'>Logout</a>\n" | |
| 71 | +} else { | |
| 72 | +>$name</a>\n" | |
| 73 | + } | |
| 74 | +} | |
| 75 | +me |
| --- a/skins/enhanced1/header.txt | |
| +++ b/skins/enhanced1/header.txt | |
| @@ -0,0 +1,75 @@ | |
| --- a/skins/enhanced1/header.txt | |
| +++ b/skins/enhanced1/header.txt | |
| @@ -0,0 +1,75 @@ | |
| 1 | <html> |
| 2 | <head> |
| 3 | <base href="$baseurl/$current_page" /> |
| 4 | <title>$<project_name>: $<title></title> |
| 5 | <link rel="alternate" type="application/rss+xml" title="RSS Feed" |
| 6 | href="$home/timeline.rss" /> |
| 7 | <link rel="stylesheet" href="$stylesheet_url" type="text/css" |
| 8 | media=<div class="header"> |
| 9 | <div class="logo"> |
| 10 | <th1> |
| 11 | ## |
| 12 | ## NOTE: The purpose of this procedure is to take the base URL of the |
| 13 | ## Fossil project and return the root of the entire web site using |
| 14 | ## the same URI scheme as the base URL (e.g. http or https). |
| 15 | ## |
| 16 | proc getLogoUrl { baseurl } { |
| 17 | set idx(first) [string first // $baseurl] |
| 18 | if {$idx(first) != -1} { |
| 19 | ## |
| 20 | ## NOTE: Skip second slash. |
| 21 | ## |
| 22 | set idx(first+1) [expr {$idx(first) + 2}] |
| 23 | ## |
| 24 | ## NOTE: (part 1) The [string first] command does NOT actually |
| 25 | ## support the optional startIndex argument as specified |
| 26 | ## in the TH1 support manual; therefore, we fake it by |
| 27 | ## using the [stange] command and then adding the |
| 28 | project_nameadding the |
| 29 | ## necessary offset to the result<th1> |
| 30 | low). In Tc, we could use the following ins} elscript |
| 31 | </th1> |
| 32 | ## |
| 33 | set idx(nextRange) [string range $baseurl $idx(first+1) funcdivif {$iif(e){ |
| 34 | e.innerHTML=d.toISOString().replace("T"," ").replace(/:\d\d\.\d+Z/,""ock();"$idx(firste $baseurl $idx> |
| 35 | <th1> |
| 36 | ## |
| 37 | ## NOT |
| 38 | <th1> |
| 39 | proc menulink {url name} { |
| 40 | name</a>\n" |
| 41 | } |
| 42 | } |
| 43 | menindex_page'>Home</a>\n" |
| 44 | name</a>\n" |
| 45 | } |
| 46 | } |
| 47 | me/help'>Help<>$name</a>\n" |
| 48 | } |
| 49 | } |
| 50 | me/timeline'>Timeline</a>$name</a>\n" |
| 51 | } |
| 52 | } |
| 53 | me/tree?ci=tip'>Filhas>$name</a>\n" |
| 54 | } |
| 55 | } |
| 56 | me/brlist'>Branches</a>\n" |
| 57 | >$name</a>\n" |
| 58 | } |
| 59 | } |
| 60 | hasaglist'>Tags</>$name</a>\n" |
| 61 | } |
| 62 | } |
| 63 | me/ticket'>Tickets</>$name</a>\n" |
| 64 | } |
| 65 | } |
| 66 | me/wikihashas name</a>\n" |
| 67 | } |
| 68 | } |
| 69 | me/setup_ulist'>Users</a>\n"<html>reportlisd> |
| 70 | <base href="$baseuse href="$baseurl/$c/login'>Logout</a>\n" |
| 71 | } else { |
| 72 | >$name</a>\n" |
| 73 | } |
| 74 | } |
| 75 | me |
| --- a/skins/etienne1/README.md | ||
| +++ b/skins/etienne1/README.md | ||
| @@ -0,0 +1 @@ | ||
| 1 | +This skin was contributed by Étienne Deparis. |
| --- a/skins/etienne1/README.md | |
| +++ b/skins/etienne1/README.md | |
| @@ -0,0 +1 @@ | |
| --- a/skins/etienne1/README.md | |
| +++ b/skins/etienne1/README.md | |
| @@ -0,0 +1 @@ | |
| 1 | This skin was contributed by Étienne Deparis. |
| --- a/skins/etienne1/css.txt | ||
| +++ b/skins/etienne1/css.txt | ||
| @@ -0,0 +1,3 @@ | ||
| 1 | +max-width: 33%.sub30max-width: width: 96max-max-width: 800px;5f9f} | |
| 2 | + | |
| 3 | +.submenu a:hover {bottom: 1px solid #fff;border: 0px,9 |
| --- a/skins/etienne1/css.txt | |
| +++ b/skins/etienne1/css.txt | |
| @@ -0,0 +1,3 @@ | |
| --- a/skins/etienne1/css.txt | |
| +++ b/skins/etienne1/css.txt | |
| @@ -0,0 +1,3 @@ | |
| 1 | max-width: 33%.sub30max-width: width: 96max-max-width: 800px;5f9f} |
| 2 | |
| 3 | .submenu a:hover {bottom: 1px solid #fff;border: 0px,9 |
| --- a/skins/etienne1/footer.txt | ||
| +++ b/skins/etienne1/footer.txt | ||
| @@ -0,0 +1,3 @@ | ||
| 1 | +<div class="footer"> | |
| 2 | +This page was generated in about | |
| 3 | +<th1>puts [expr {([utime]+[stime]+1000)/100 |
| --- a/skins/etienne1/footer.txt | |
| +++ b/skins/etienne1/footer.txt | |
| @@ -0,0 +1,3 @@ | |
| --- a/skins/etienne1/footer.txt | |
| +++ b/skins/etienne1/footer.txt | |
| @@ -0,0 +1,3 @@ | |
| 1 | <div class="footer"> |
| 2 | This page was generated in about |
| 3 | <th1>puts [expr {([utime]+[stime]+1000)/100 |
| --- a/skins/etienne1/header.txt | ||
| +++ b/skins/etienne1/header.txt | ||
| @@ -0,0 +1,27 @@ | ||
| 1 | +<html> | |
| 2 | + <head> | |
| 3 | + <base href="$baseurl/$current_page" /> | |
| 4 | + <title>$<project_name>: $<title></title> | |
| 5 | + <link rel="alternate" type="application/rss+xml" title="RSS Feed" | |
| 6 | + href="$home/timeline.rss" /> | |
| 7 | + <lihome/style.css?default" type="text/css" | |
| 8 | + media="screen" /> | |
| 9 | + </head> | |
| 10 | + | |
| 11 | + <bodyth1> | |
| 12 | + if {[info exheader"> | |
| 13 | + t_name"> | |
| 14 | + </a> | |
| 15 | + <<h1>$<project_name></h1>$<title>us"><th1> | |
| 16 | + 1> | |
| 17 | + if {[info exists login]} { | |
| 18 | + if {[info exists login]} { | |
| 19 | + } els$login — } els} } else { | |
| 20 | + t h$login</a>\n" | |
| 21 | + } | |
| 22 | + h1> | |
| 23 | + if {[info exmainmbtn' href='$proc menulink {url name} { | |
| 24 | + upvar current_page current | |
| 25 | + upvar home homa h <th1> | |
| 26 | +proc isin {val lst} { | |
| 27 | + set tot [llreportlisrep |
| --- a/skins/etienne1/header.txt | |
| +++ b/skins/etienne1/header.txt | |
| @@ -0,0 +1,27 @@ | |
| --- a/skins/etienne1/header.txt | |
| +++ b/skins/etienne1/header.txt | |
| @@ -0,0 +1,27 @@ | |
| 1 | <html> |
| 2 | <head> |
| 3 | <base href="$baseurl/$current_page" /> |
| 4 | <title>$<project_name>: $<title></title> |
| 5 | <link rel="alternate" type="application/rss+xml" title="RSS Feed" |
| 6 | href="$home/timeline.rss" /> |
| 7 | <lihome/style.css?default" type="text/css" |
| 8 | media="screen" /> |
| 9 | </head> |
| 10 | |
| 11 | <bodyth1> |
| 12 | if {[info exheader"> |
| 13 | t_name"> |
| 14 | </a> |
| 15 | <<h1>$<project_name></h1>$<title>us"><th1> |
| 16 | 1> |
| 17 | if {[info exists login]} { |
| 18 | if {[info exists login]} { |
| 19 | } els$login — } els} } else { |
| 20 | t h$login</a>\n" |
| 21 | } |
| 22 | h1> |
| 23 | if {[info exmainmbtn' href='$proc menulink {url name} { |
| 24 | upvar current_page current |
| 25 | upvar home homa h <th1> |
| 26 | proc isin {val lst} { |
| 27 | set tot [llreportlisrep |
+1
| --- a/skins/khaki/css.txt | ||
| +++ b/skins/khaki/css.txt | ||
| @@ -0,0 +1 @@ | ||
| 1 | +/* General settings for t |
| --- a/skins/khaki/css.txt | |
| +++ b/skins/khaki/css.txt | |
| @@ -0,0 +1 @@ | |
| --- a/skins/khaki/css.txt | |
| +++ b/skins/khaki/css.txt | |
| @@ -0,0 +1 @@ | |
| 1 | /* General settings for t |
| --- a/skins/khaki/footer.txt | ||
| +++ b/skins/khaki/footer.txt | ||
| @@ -0,0 +1 @@ | ||
| 1 | +< |
| --- a/skins/khaki/footer.txt | |
| +++ b/skins/khaki/footer.txt | |
| @@ -0,0 +1 @@ | |
| --- a/skins/khaki/footer.txt | |
| +++ b/skins/khaki/footer.txt | |
| @@ -0,0 +1 @@ | |
| 1 | < |
+18
| --- a/skins/khaki/header.txt | ||
| +++ b/skins/khaki/header.txt | ||
| @@ -0,0 +1,18 @@ | ||
| 1 | +<div class="header"> | |
| 2 | + <div class="title">$<title></div> | |
| 3 | + <div class="status"> | |
| 4 | + <div class="logo">$<project_name>if {[info exists login]} { | |
| 5 | + o exists login]} { | |
| 6 | + puts } else { | |
| 7 | + puts "Not logged in" | |
| 8 | + } | |
| 9 | + </th1></div> | |
| 10 | +</he><th1> | |
| 11 | +html "<a id='hbbtndiv> | |
| 12 | +<dime/sitemap' aria-la | |
| 13 | +<th1> | |
| 14 | +home$index_page'>Homehome/timeline'>Timeline</home/tree?ci=tip'>Files<home/brlist'>Branches</a>\n"home/taglist'>Tags</a>\n" | |
| 15 | +} | |
| 16 | +if {[anycap 23456] || [anoncap 2] || [anoncap 3]} {home/forum'>Forum<home/ticket'>Tickets<home/wiki'>Wikihome/setup'>Admin</a>home/setup_ulist'>Users</a>\n" | |
| 17 | +} | |
| 18 | + o exists loginoncap rhascap ohhascap ohascap hasreportlis |
| --- a/skins/khaki/header.txt | |
| +++ b/skins/khaki/header.txt | |
| @@ -0,0 +1,18 @@ | |
| --- a/skins/khaki/header.txt | |
| +++ b/skins/khaki/header.txt | |
| @@ -0,0 +1,18 @@ | |
| 1 | <div class="header"> |
| 2 | <div class="title">$<title></div> |
| 3 | <div class="status"> |
| 4 | <div class="logo">$<project_name>if {[info exists login]} { |
| 5 | o exists login]} { |
| 6 | puts } else { |
| 7 | puts "Not logged in" |
| 8 | } |
| 9 | </th1></div> |
| 10 | </he><th1> |
| 11 | html "<a id='hbbtndiv> |
| 12 | <dime/sitemap' aria-la |
| 13 | <th1> |
| 14 | home$index_page'>Homehome/timeline'>Timeline</home/tree?ci=tip'>Files<home/brlist'>Branches</a>\n"home/taglist'>Tags</a>\n" |
| 15 | } |
| 16 | if {[anycap 23456] || [anoncap 2] || [anoncap 3]} {home/forum'>Forum<home/ticket'>Tickets<home/wiki'>Wikihome/setup'>Admin</a>home/setup_ulist'>Users</a>\n" |
| 17 | } |
| 18 | o exists loginoncap rhascap ohhascap ohascap hasreportlis |
| --- a/skins/plain_gray/css.txt | ||
| +++ b/skins/plain_gray/css.txt | ||
| @@ -0,0 +1,6 @@ | ||
| 1 | +/* General settings for the entire page */ | |
| 2 | +body { | |
| 3 | + margin: 0ex 1ex; | |
| 4 | + padding: 0px; | |
| 5 | + background-color: white; | |
| 6 | + font-family: sans-serif; |
| --- a/skins/plain_gray/css.txt | |
| +++ b/skins/plain_gray/css.txt | |
| @@ -0,0 +1,6 @@ | |
| --- a/skins/plain_gray/css.txt | |
| +++ b/skins/plain_gray/css.txt | |
| @@ -0,0 +1,6 @@ | |
| 1 | /* General settings for the entire page */ |
| 2 | body { |
| 3 | margin: 0ex 1ex; |
| 4 | padding: 0px; |
| 5 | background-color: white; |
| 6 | font-family: sans-serif; |
| --- a/skins/plain_gray/footer.txt | ||
| +++ b/skins/plain_gray/footer.txt | ||
| @@ -0,0 +1 @@ | ||
| 1 | +< |
| --- a/skins/plain_gray/footer.txt | |
| +++ b/skins/plain_gray/footer.txt | |
| @@ -0,0 +1 @@ | |
| --- a/skins/plain_gray/footer.txt | |
| +++ b/skins/plain_gray/footer.txt | |
| @@ -0,0 +1 @@ | |
| 1 | < |
| --- a/skins/plain_gray/header.txt | ||
| +++ b/skins/plain_gray/header.txt | ||
| @@ -0,0 +1,13 @@ | ||
| 1 | +<html> | |
| 2 | +<head> | |
| 3 | +<base href="$baseucap r: $<title></title> | |
| 4 | +<link rel="alternate" type="application/rss+xml" title="RSS Feed" | |
| 5 | + href="$home/timeline.rss"> | |
| 6 | +<link rel="stylesheet" href="$stylesheet_url" type="text/css" | |
| 7 | + media="screen"> | |
| 8 | +</head> | |
| 9 | +<body> | |
| 10 | +<div class="headjoroncap rhashascap oase href="$baseucap r: $<tit<html> | |
| 11 | +<head> | |
| 12 | +<base href="$baseucap r: $<title></title> | |
| 13 | +<link rel="alternathascap hasreportlis |
| --- a/skins/plain_gray/header.txt | |
| +++ b/skins/plain_gray/header.txt | |
| @@ -0,0 +1,13 @@ | |
| --- a/skins/plain_gray/header.txt | |
| +++ b/skins/plain_gray/header.txt | |
| @@ -0,0 +1,13 @@ | |
| 1 | <html> |
| 2 | <head> |
| 3 | <base href="$baseucap r: $<title></title> |
| 4 | <link rel="alternate" type="application/rss+xml" title="RSS Feed" |
| 5 | href="$home/timeline.rss"> |
| 6 | <link rel="stylesheet" href="$stylesheet_url" type="text/css" |
| 7 | media="screen"> |
| 8 | </head> |
| 9 | <body> |
| 10 | <div class="headjoroncap rhashascap oase href="$baseucap r: $<tit<html> |
| 11 | <head> |
| 12 | <base href="$baseucap r: $<title></title> |
| 13 | <link rel="alternathascap hasreportlis |
+105
| --- a/skins/rounded1/css.txt | ||
| +++ b/skins/rounded1/css.txt | ||
| @@ -0,0 +1,105 @@ | ||
| 1 | +/* General settings for the entire page */ | |
| 2 | +html { | |
| 3 | + min-height: 100%; | |
| 4 | +} | |
| 5 | +body { | |
| 6 | + margin: 0ex 1ex; | |
| 7 | + padding: 0px; | |
| 8 | + background-color: white; | |
| 9 | + color: #333; | |
| 10 | + font-family: Verdana, sans-serif; | |
| 11 | + font-size: 0.8em; | |
| 12 | +mx-text-size-adjust: none; | |
| 13 | +} | |
| 14 | + | |
| 15 | +/* The project logo in the upper left-hand corner of each page */ | |
| 16 | +div.logo { | |
| 17 | + display: table-cell; | |
| 18 | + text-align: right; | |
| 19 | + vertical-align: bottom; | |
| 20 | + font-weight: normal; | |
| 21 | + white-space: nowrap; | |
| 22 | +} | |
| 23 | + | |
| 24 | +/* Widths */ | |
| 25 | +div.header, div.mainmenu, div.submenu, div.content, div.footer { | |
| 26 | + max-width: 900px; | |
| 27 | + margin: auto; | |
| 28 | + padding: 3px 20px 3px 20px; | |
| 29 | + clear: both; | |
| 30 | +} | |
| 31 | + | |
| 32 | +/* The page title at the top of each page */ | |
| 33 | +div.title { | |
| 34 | + display: table-cell; | |
| 35 | + padding-left: 10px; | |
| 36 | + font-size: 2em; | |
| 37 | + margin: 10px 0 10px -20px; | |
| 38 | + vertical-align: bottom; | |
| 39 | + text-align: left; | |
| 40 | + width: 80%; | |
| 41 | + font-family: Verdana, sans-serif; | |
| 42 | + font-weight: bold; | |
| 43 | + color: #558195; | |
| 44 | + text-shadow: 0px 2px 2px #999999; | |
| 45 | +} | |
| 46 | + | |
| 47 | +/* The login status message in the top right-hand corner */ | |
| 48 | +div.status { | |
| 49 | + display: table-cell; | |
| 50 | + text-align: right; | |
| 51 | + vertical-align: bottom; | |
| 52 | + color: #333; | |
| 53 | + margin-right: -20px; | |
| 54 | + white-space: nowrap; | |
| 55 | +} | |
| 56 | + | |
| 57 | +/* The main menu bar that appears at the top of the page beneath | |
| 58 | + ** the header */ | |
| 59 | +div.mainmenu { | |
| 60 | + text-align: center; | |
| 61 | + color: white; | |
| 62 | + border-top-left-radius: 5px; | |
| 63 | + border-top-right-radius: 5px; | |
| 64 | + vertical-align: middle; | |
| 65 | + padding-top: 8px; | |
| 66 | + padding-bottom: 8px; | |
| 67 | + background-color: #446979; | |
| 68 | + box-shadow: 0px 3px 4px #333333; | |
| 69 | +} | |
| 70 | + | |
| 71 | +/* The submenu bar that *sometimes* appears below the main menu */ | |
| 72 | +div.submenu { | |
| 73 | + padding-top:10px; | |
| 74 | + padding-bottom:0; | |
| 75 | + text-align: right; | |
| 76 | + color: #000; | |
| 77 | + background-color: #fff; | |
| 78 | + height: 1.5em; | |
| 79 | + vertical-align:middle; | |
| 80 | + box-shadow: 0px 3px 4px #999; | |
| 81 | +} | |
| 82 | +div.mainmenu a, div.mainmenu a:visited { | |
| 83 | + padding: 3px 10px 3px 10px; | |
| 84 | + color: white; | |
| 85 | + text-decoration: none; | |
| 86 | +} | |
| 87 | +div.submenu a, div.submenu a:visited, .button, .button, div.submenu label, | |
| 88 | +div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited { | |
| 89 | + padding: 2px 8px; | |
| 90 | + color: #000; | |
| 91 | + font-family: Arial; | |
| 92 | + text-decoration: none; | |
| 93 | + margin:auto; | |
| 94 | + border-radius: 5px; | |
| 95 | + background-color: #e0e0e0; | |
| 96 | + text-shadow: 0px -1px 0px #eee; | |
| 97 | + border: 1px solid #000; | |
| 98 | +} | |
| 99 | + | |
| 100 | +div.mainmenu a:hover { | |
| 101 | + color: #000; | |
| 102 | + background-co cursor: pointercolor: white; | |
| 103 | +} | |
| 104 | + | |
| 105 | +div.submenu a:hover, div: 10px 0 |
| --- a/skins/rounded1/css.txt | |
| +++ b/skins/rounded1/css.txt | |
| @@ -0,0 +1,105 @@ | |
| --- a/skins/rounded1/css.txt | |
| +++ b/skins/rounded1/css.txt | |
| @@ -0,0 +1,105 @@ | |
| 1 | /* General settings for the entire page */ |
| 2 | html { |
| 3 | min-height: 100%; |
| 4 | } |
| 5 | body { |
| 6 | margin: 0ex 1ex; |
| 7 | padding: 0px; |
| 8 | background-color: white; |
| 9 | color: #333; |
| 10 | font-family: Verdana, sans-serif; |
| 11 | font-size: 0.8em; |
| 12 | mx-text-size-adjust: none; |
| 13 | } |
| 14 | |
| 15 | /* The project logo in the upper left-hand corner of each page */ |
| 16 | div.logo { |
| 17 | display: table-cell; |
| 18 | text-align: right; |
| 19 | vertical-align: bottom; |
| 20 | font-weight: normal; |
| 21 | white-space: nowrap; |
| 22 | } |
| 23 | |
| 24 | /* Widths */ |
| 25 | div.header, div.mainmenu, div.submenu, div.content, div.footer { |
| 26 | max-width: 900px; |
| 27 | margin: auto; |
| 28 | padding: 3px 20px 3px 20px; |
| 29 | clear: both; |
| 30 | } |
| 31 | |
| 32 | /* The page title at the top of each page */ |
| 33 | div.title { |
| 34 | display: table-cell; |
| 35 | padding-left: 10px; |
| 36 | font-size: 2em; |
| 37 | margin: 10px 0 10px -20px; |
| 38 | vertical-align: bottom; |
| 39 | text-align: left; |
| 40 | width: 80%; |
| 41 | font-family: Verdana, sans-serif; |
| 42 | font-weight: bold; |
| 43 | color: #558195; |
| 44 | text-shadow: 0px 2px 2px #999999; |
| 45 | } |
| 46 | |
| 47 | /* The login status message in the top right-hand corner */ |
| 48 | div.status { |
| 49 | display: table-cell; |
| 50 | text-align: right; |
| 51 | vertical-align: bottom; |
| 52 | color: #333; |
| 53 | margin-right: -20px; |
| 54 | white-space: nowrap; |
| 55 | } |
| 56 | |
| 57 | /* The main menu bar that appears at the top of the page beneath |
| 58 | ** the header */ |
| 59 | div.mainmenu { |
| 60 | text-align: center; |
| 61 | color: white; |
| 62 | border-top-left-radius: 5px; |
| 63 | border-top-right-radius: 5px; |
| 64 | vertical-align: middle; |
| 65 | padding-top: 8px; |
| 66 | padding-bottom: 8px; |
| 67 | background-color: #446979; |
| 68 | box-shadow: 0px 3px 4px #333333; |
| 69 | } |
| 70 | |
| 71 | /* The submenu bar that *sometimes* appears below the main menu */ |
| 72 | div.submenu { |
| 73 | padding-top:10px; |
| 74 | padding-bottom:0; |
| 75 | text-align: right; |
| 76 | color: #000; |
| 77 | background-color: #fff; |
| 78 | height: 1.5em; |
| 79 | vertical-align:middle; |
| 80 | box-shadow: 0px 3px 4px #999; |
| 81 | } |
| 82 | div.mainmenu a, div.mainmenu a:visited { |
| 83 | padding: 3px 10px 3px 10px; |
| 84 | color: white; |
| 85 | text-decoration: none; |
| 86 | } |
| 87 | div.submenu a, div.submenu a:visited, .button, .button, div.submenu label, |
| 88 | div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited { |
| 89 | padding: 2px 8px; |
| 90 | color: #000; |
| 91 | font-family: Arial; |
| 92 | text-decoration: none; |
| 93 | margin:auto; |
| 94 | border-radius: 5px; |
| 95 | background-color: #e0e0e0; |
| 96 | text-shadow: 0px -1px 0px #eee; |
| 97 | border: 1px solid #000; |
| 98 | } |
| 99 | |
| 100 | div.mainmenu a:hover { |
| 101 | color: #000; |
| 102 | background-co cursor: pointercolor: white; |
| 103 | } |
| 104 | |
| 105 | div.submenu a:hover, div: 10px 0 |
| --- a/skins/rounded1/footer.txt | ||
| +++ b/skins/rounded1/footer.txt | ||
| @@ -0,0 +1 @@ | ||
| 1 | +< |
| --- a/skins/rounded1/footer.txt | |
| +++ b/skins/rounded1/footer.txt | |
| @@ -0,0 +1 @@ | |
| --- a/skins/rounded1/footer.txt | |
| +++ b/skins/rounded1/footer.txt | |
| @@ -0,0 +1 @@ | |
| 1 | < |
| --- a/skins/rounded1/header.txt | ||
| +++ b/skins/rounded1/header.txt | ||
| @@ -0,0 +1,38 @@ | ||
| 1 | +<div class="header"> | |
| 2 | + <div class="logo"> | |
| 3 | + <img src="$logo_image_url" alt="logo"> | |
| 4 | + <br />$<project_name> | |
| 5 | + </div> | |
| 6 | + <div class="title">$<title></div> | |
| 7 | + <div class="status"><th1> | |
| 8 | + if {[info exists login]} { | |
| 9 | + puts "Logged in as $login" | |
| 10 | + } else { | |
| 11 | + puts "Not logged in" | |
| 12 | + } | |
| 13 | + </th1></div> | |
| 14 | +</div> | |
| 15 | +<div class="mainmenu"> | |
| 16 | +<th1> | |
| 17 | +html "<a href='$home$index_page'>Home</a>\n" | |
| 18 | +if {[anycap jor]} { | |
| 19 | + html "<a href='$home/} { | |
| 20 | + html "<a href='$home/timeline'>Timeline</a>\n" | |
| 21 | +} | |
| 22 | +if {[anoncap oh]} { | |
| 23 | + html "<a href='$home/tree?ci=tip'>Files</a>\n" | |
| 24 | +} | |
| 25 | +if {[anoncap o]} { | |
| 26 | + html "<a href='$home/brlist'>Branches</a>\n" | |
| 27 | + html "<a href='$home/tagoncap r]} { | |
| 28 | + html "<a href='$home/ticket'>Tickets</a>\n" | |
| 29 | +} | |
| 30 | +if {[anoncap j]} { | |
| 31 | + has"header"> | |
| 32 | + <div class="logo"> | |
| 33 | + <img src="$logo_image_url" alt="<div claeif {[hascap a]} { | |
| 34 | + html "<a href='$home/setup_ulist'>Users</a>\n" | |
| 35 | +} | |
| 36 | + clashascap "<a href='$home/ticket'>Ticket} else { | |
| 37 | + html "<a href='$hhase { | |
| 38 | + html "<a href='$reportlislogin'>L |
| --- a/skins/rounded1/header.txt | |
| +++ b/skins/rounded1/header.txt | |
| @@ -0,0 +1,38 @@ | |
| --- a/skins/rounded1/header.txt | |
| +++ b/skins/rounded1/header.txt | |
| @@ -0,0 +1,38 @@ | |
| 1 | <div class="header"> |
| 2 | <div class="logo"> |
| 3 | <img src="$logo_image_url" alt="logo"> |
| 4 | <br />$<project_name> |
| 5 | </div> |
| 6 | <div class="title">$<title></div> |
| 7 | <div class="status"><th1> |
| 8 | if {[info exists login]} { |
| 9 | puts "Logged in as $login" |
| 10 | } else { |
| 11 | puts "Not logged in" |
| 12 | } |
| 13 | </th1></div> |
| 14 | </div> |
| 15 | <div class="mainmenu"> |
| 16 | <th1> |
| 17 | html "<a href='$home$index_page'>Home</a>\n" |
| 18 | if {[anycap jor]} { |
| 19 | html "<a href='$home/} { |
| 20 | html "<a href='$home/timeline'>Timeline</a>\n" |
| 21 | } |
| 22 | if {[anoncap oh]} { |
| 23 | html "<a href='$home/tree?ci=tip'>Files</a>\n" |
| 24 | } |
| 25 | if {[anoncap o]} { |
| 26 | html "<a href='$home/brlist'>Branches</a>\n" |
| 27 | html "<a href='$home/tagoncap r]} { |
| 28 | html "<a href='$home/ticket'>Tickets</a>\n" |
| 29 | } |
| 30 | if {[anoncap j]} { |
| 31 | has"header"> |
| 32 | <div class="logo"> |
| 33 | <img src="$logo_image_url" alt="<div claeif {[hascap a]} { |
| 34 | html "<a href='$home/setup_ulist'>Users</a>\n" |
| 35 | } |
| 36 | clashascap "<a href='$home/ticket'>Ticket} else { |
| 37 | html "<a href='$hhase { |
| 38 | html "<a href='$reportlislogin'>L |
+2
-2
| --- src/attach.c | ||
| +++ src/attach.c | ||
| @@ -90,12 +90,12 @@ | ||
| 90 | 90 | @ <li><p> |
| 91 | 91 | @ Attachment %z(href("%R/ainfo/%s",zUuid))%S(zUuid)</a> |
| 92 | 92 | if( moderation_pending(attachid) ){ |
| 93 | 93 | @ <span class="modpending">*** Awaiting Moderator Approval ***</span> |
| 94 | 94 | } |
| 95 | - @ <br><a href="/attachview?%s(zUrlTail)">%h(zFilename)</a> | |
| 96 | - @ [<a href="/attachdownload/%t(zFilename)?%s(zUrlTail)">download</a>]<br /> | |
| 95 | + @ <br><a href="%R/attachview?%s(zUrlTail)">%h(zFilename)</a> | |
| 96 | + @ [<a href="%R/attachdownload/%t(zFilename)?%s(zUrlTail)">download</a>]<br /> | |
| 97 | 97 | if( zComment ) while( fossil_isspace(zComment[0]) ) zComment++; |
| 98 | 98 | if( zComment && zComment[0] ){ |
| 99 | 99 | @ %!w(zComment)<br /> |
| 100 | 100 | } |
| 101 | 101 | if( zPage==0 && zTkt==0 ){ |
| 102 | 102 |
| --- src/attach.c | |
| +++ src/attach.c | |
| @@ -90,12 +90,12 @@ | |
| 90 | @ <li><p> |
| 91 | @ Attachment %z(href("%R/ainfo/%s",zUuid))%S(zUuid)</a> |
| 92 | if( moderation_pending(attachid) ){ |
| 93 | @ <span class="modpending">*** Awaiting Moderator Approval ***</span> |
| 94 | } |
| 95 | @ <br><a href="/attachview?%s(zUrlTail)">%h(zFilename)</a> |
| 96 | @ [<a href="/attachdownload/%t(zFilename)?%s(zUrlTail)">download</a>]<br /> |
| 97 | if( zComment ) while( fossil_isspace(zComment[0]) ) zComment++; |
| 98 | if( zComment && zComment[0] ){ |
| 99 | @ %!w(zComment)<br /> |
| 100 | } |
| 101 | if( zPage==0 && zTkt==0 ){ |
| 102 |
| --- src/attach.c | |
| +++ src/attach.c | |
| @@ -90,12 +90,12 @@ | |
| 90 | @ <li><p> |
| 91 | @ Attachment %z(href("%R/ainfo/%s",zUuid))%S(zUuid)</a> |
| 92 | if( moderation_pending(attachid) ){ |
| 93 | @ <span class="modpending">*** Awaiting Moderator Approval ***</span> |
| 94 | } |
| 95 | @ <br><a href="%R/attachview?%s(zUrlTail)">%h(zFilename)</a> |
| 96 | @ [<a href="%R/attachdownload/%t(zFilename)?%s(zUrlTail)">download</a>]<br /> |
| 97 | if( zComment ) while( fossil_isspace(zComment[0]) ) zComment++; |
| 98 | if( zComment && zComment[0] ){ |
| 99 | @ %!w(zComment)<br /> |
| 100 | } |
| 101 | if( zPage==0 && zTkt==0 ){ |
| 102 |
+3
-2
| --- src/branch.c | ||
| +++ src/branch.c | ||
| @@ -341,10 +341,11 @@ | ||
| 341 | 341 | Stmt q; |
| 342 | 342 | double rNow; |
| 343 | 343 | login_check_credentials(); |
| 344 | 344 | if( !g.perm.Read ){ login_needed(); return; } |
| 345 | 345 | style_header("Branches"); |
| 346 | + style_adunit_config(ADUNIT_RIGHT_OK); | |
| 346 | 347 | login_anonymous_available(); |
| 347 | 348 | |
| 348 | 349 | db_prepare(&q, brlistQuery/*works-like:""*/); |
| 349 | 350 | rNow = db_double(0.0, "SELECT julianday('now')"); |
| 350 | 351 | @ <div class="brlist"><table id="branchlisttable"> |
| @@ -366,11 +367,11 @@ | ||
| 366 | 367 | sqlite3_int64 iMtime = (sqlite3_int64)(rMtime*86400.0); |
| 367 | 368 | if( zMergeTo && zMergeTo[0]==0 ) zMergeTo = 0; |
| 368 | 369 | @ <tr> |
| 369 | 370 | @ <td>%z(href("%R/timeline?n=100&r=%T",zBranch))%h(zBranch)</a></td> |
| 370 | 371 | @ <td data-sortkey="%016llx(-iMtime)">%s(zAge)</td> |
| 371 | - @ <td data-sortkey="%08x(-nCkin)">%d(nCkin)</td> | |
| 372 | + @ <td>%d(nCkin)</td> | |
| 372 | 373 | fossil_free(zAge); |
| 373 | 374 | @ <td>%s(isClosed?"closed":"")</td> |
| 374 | 375 | if( zMergeTo ){ |
| 375 | 376 | @ <td>merged into |
| 376 | 377 | @ %z(href("%R/timeline?f=%s",zLastCkin))%h(zMergeTo)</a></td> |
| @@ -379,11 +380,11 @@ | ||
| 379 | 380 | } |
| 380 | 381 | @ </tr> |
| 381 | 382 | } |
| 382 | 383 | @ </tbody></table></div> |
| 383 | 384 | db_finalize(&q); |
| 384 | - output_table_sorting_javascript("branchlisttable","tkktt",2); | |
| 385 | + output_table_sorting_javascript("branchlisttable","tkNtt",2); | |
| 385 | 386 | style_footer(); |
| 386 | 387 | } |
| 387 | 388 | |
| 388 | 389 | /* |
| 389 | 390 | ** WEBPAGE: brlist |
| 390 | 391 |
| --- src/branch.c | |
| +++ src/branch.c | |
| @@ -341,10 +341,11 @@ | |
| 341 | Stmt q; |
| 342 | double rNow; |
| 343 | login_check_credentials(); |
| 344 | if( !g.perm.Read ){ login_needed(); return; } |
| 345 | style_header("Branches"); |
| 346 | login_anonymous_available(); |
| 347 | |
| 348 | db_prepare(&q, brlistQuery/*works-like:""*/); |
| 349 | rNow = db_double(0.0, "SELECT julianday('now')"); |
| 350 | @ <div class="brlist"><table id="branchlisttable"> |
| @@ -366,11 +367,11 @@ | |
| 366 | sqlite3_int64 iMtime = (sqlite3_int64)(rMtime*86400.0); |
| 367 | if( zMergeTo && zMergeTo[0]==0 ) zMergeTo = 0; |
| 368 | @ <tr> |
| 369 | @ <td>%z(href("%R/timeline?n=100&r=%T",zBranch))%h(zBranch)</a></td> |
| 370 | @ <td data-sortkey="%016llx(-iMtime)">%s(zAge)</td> |
| 371 | @ <td data-sortkey="%08x(-nCkin)">%d(nCkin)</td> |
| 372 | fossil_free(zAge); |
| 373 | @ <td>%s(isClosed?"closed":"")</td> |
| 374 | if( zMergeTo ){ |
| 375 | @ <td>merged into |
| 376 | @ %z(href("%R/timeline?f=%s",zLastCkin))%h(zMergeTo)</a></td> |
| @@ -379,11 +380,11 @@ | |
| 379 | } |
| 380 | @ </tr> |
| 381 | } |
| 382 | @ </tbody></table></div> |
| 383 | db_finalize(&q); |
| 384 | output_table_sorting_javascript("branchlisttable","tkktt",2); |
| 385 | style_footer(); |
| 386 | } |
| 387 | |
| 388 | /* |
| 389 | ** WEBPAGE: brlist |
| 390 |
| --- src/branch.c | |
| +++ src/branch.c | |
| @@ -341,10 +341,11 @@ | |
| 341 | Stmt q; |
| 342 | double rNow; |
| 343 | login_check_credentials(); |
| 344 | if( !g.perm.Read ){ login_needed(); return; } |
| 345 | style_header("Branches"); |
| 346 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 347 | login_anonymous_available(); |
| 348 | |
| 349 | db_prepare(&q, brlistQuery/*works-like:""*/); |
| 350 | rNow = db_double(0.0, "SELECT julianday('now')"); |
| 351 | @ <div class="brlist"><table id="branchlisttable"> |
| @@ -366,11 +367,11 @@ | |
| 367 | sqlite3_int64 iMtime = (sqlite3_int64)(rMtime*86400.0); |
| 368 | if( zMergeTo && zMergeTo[0]==0 ) zMergeTo = 0; |
| 369 | @ <tr> |
| 370 | @ <td>%z(href("%R/timeline?n=100&r=%T",zBranch))%h(zBranch)</a></td> |
| 371 | @ <td data-sortkey="%016llx(-iMtime)">%s(zAge)</td> |
| 372 | @ <td>%d(nCkin)</td> |
| 373 | fossil_free(zAge); |
| 374 | @ <td>%s(isClosed?"closed":"")</td> |
| 375 | if( zMergeTo ){ |
| 376 | @ <td>merged into |
| 377 | @ %z(href("%R/timeline?f=%s",zLastCkin))%h(zMergeTo)</a></td> |
| @@ -379,11 +380,11 @@ | |
| 380 | } |
| 381 | @ </tr> |
| 382 | } |
| 383 | @ </tbody></table></div> |
| 384 | db_finalize(&q); |
| 385 | output_table_sorting_javascript("branchlisttable","tkNtt",2); |
| 386 | style_footer(); |
| 387 | } |
| 388 | |
| 389 | /* |
| 390 | ** WEBPAGE: brlist |
| 391 |
+7
| --- src/browse.c | ||
| +++ src/browse.c | ||
| @@ -133,10 +133,11 @@ | ||
| 133 | 133 | if( strcmp(PD("type",""),"tree")==0 ){ page_tree(); return; } |
| 134 | 134 | login_check_credentials(); |
| 135 | 135 | if( !g.perm.Read ){ login_needed(); return; } |
| 136 | 136 | while( nD>1 && zD[nD-2]=='/' ){ zD[(--nD)-1] = 0; } |
| 137 | 137 | style_header("File List"); |
| 138 | + style_adunit_config(ADUNIT_RIGHT_OK); | |
| 138 | 139 | sqlite3_create_function(g.db, "pathelement", 2, SQLITE_UTF8, 0, |
| 139 | 140 | pathelementFunc, 0, 0); |
| 140 | 141 | url_initialize(&sURI, "dir"); |
| 141 | 142 | |
| 142 | 143 | /* If the name= parameter is an empty string, make it a NULL pointer */ |
| @@ -555,10 +556,11 @@ | ||
| 555 | 556 | style_header("Folder Hierarchy"); |
| 556 | 557 | }else{ |
| 557 | 558 | showDirOnly = 0; |
| 558 | 559 | style_header("File Tree"); |
| 559 | 560 | } |
| 561 | + style_adunit_config(ADUNIT_RIGHT_OK); | |
| 560 | 562 | if( P("expand")!=0 ){ |
| 561 | 563 | startExpanded = 1; |
| 562 | 564 | url_add_parameter(&sURI, "expand", "1"); |
| 563 | 565 | }else{ |
| 564 | 566 | startExpanded = 0; |
| @@ -635,10 +637,12 @@ | ||
| 635 | 637 | } |
| 636 | 638 | if( linkTip ){ |
| 637 | 639 | style_submenu_element("Tip", "Tip", "%s", |
| 638 | 640 | url_render(&sURI, "ci", "tip", 0, 0)); |
| 639 | 641 | } |
| 642 | + style_submenu_element("Flat-View", "Flat-View", "%s", | |
| 643 | + url_render(&sURI, "type", "flat", 0, 0)); | |
| 640 | 644 | |
| 641 | 645 | /* Compute the file hierarchy. |
| 642 | 646 | */ |
| 643 | 647 | if( zCI ){ |
| 644 | 648 | Stmt q; |
| @@ -652,10 +656,13 @@ | ||
| 652 | 656 | ); |
| 653 | 657 | while( db_step(&q)==SQLITE_ROW ){ |
| 654 | 658 | const char *zFile = db_column_text(&q,0); |
| 655 | 659 | const char *zUuid = db_column_text(&q,1); |
| 656 | 660 | double mtime = db_column_double(&q,2); |
| 661 | + if( nD>0 && (fossil_strncmp(zFile, zD, nD-1)!=0 || zFile[nD-1]!='/') ){ | |
| 662 | + continue; | |
| 663 | + } | |
| 657 | 664 | if( pRE && re_match(pRE, (const unsigned char*)zFile, -1)==0 ) continue; |
| 658 | 665 | tree_add_node(&sTree, zFile, zUuid, mtime); |
| 659 | 666 | nFile++; |
| 660 | 667 | } |
| 661 | 668 | db_finalize(&q); |
| 662 | 669 |
| --- src/browse.c | |
| +++ src/browse.c | |
| @@ -133,10 +133,11 @@ | |
| 133 | if( strcmp(PD("type",""),"tree")==0 ){ page_tree(); return; } |
| 134 | login_check_credentials(); |
| 135 | if( !g.perm.Read ){ login_needed(); return; } |
| 136 | while( nD>1 && zD[nD-2]=='/' ){ zD[(--nD)-1] = 0; } |
| 137 | style_header("File List"); |
| 138 | sqlite3_create_function(g.db, "pathelement", 2, SQLITE_UTF8, 0, |
| 139 | pathelementFunc, 0, 0); |
| 140 | url_initialize(&sURI, "dir"); |
| 141 | |
| 142 | /* If the name= parameter is an empty string, make it a NULL pointer */ |
| @@ -555,10 +556,11 @@ | |
| 555 | style_header("Folder Hierarchy"); |
| 556 | }else{ |
| 557 | showDirOnly = 0; |
| 558 | style_header("File Tree"); |
| 559 | } |
| 560 | if( P("expand")!=0 ){ |
| 561 | startExpanded = 1; |
| 562 | url_add_parameter(&sURI, "expand", "1"); |
| 563 | }else{ |
| 564 | startExpanded = 0; |
| @@ -635,10 +637,12 @@ | |
| 635 | } |
| 636 | if( linkTip ){ |
| 637 | style_submenu_element("Tip", "Tip", "%s", |
| 638 | url_render(&sURI, "ci", "tip", 0, 0)); |
| 639 | } |
| 640 | |
| 641 | /* Compute the file hierarchy. |
| 642 | */ |
| 643 | if( zCI ){ |
| 644 | Stmt q; |
| @@ -652,10 +656,13 @@ | |
| 652 | ); |
| 653 | while( db_step(&q)==SQLITE_ROW ){ |
| 654 | const char *zFile = db_column_text(&q,0); |
| 655 | const char *zUuid = db_column_text(&q,1); |
| 656 | double mtime = db_column_double(&q,2); |
| 657 | if( pRE && re_match(pRE, (const unsigned char*)zFile, -1)==0 ) continue; |
| 658 | tree_add_node(&sTree, zFile, zUuid, mtime); |
| 659 | nFile++; |
| 660 | } |
| 661 | db_finalize(&q); |
| 662 |
| --- src/browse.c | |
| +++ src/browse.c | |
| @@ -133,10 +133,11 @@ | |
| 133 | if( strcmp(PD("type",""),"tree")==0 ){ page_tree(); return; } |
| 134 | login_check_credentials(); |
| 135 | if( !g.perm.Read ){ login_needed(); return; } |
| 136 | while( nD>1 && zD[nD-2]=='/' ){ zD[(--nD)-1] = 0; } |
| 137 | style_header("File List"); |
| 138 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 139 | sqlite3_create_function(g.db, "pathelement", 2, SQLITE_UTF8, 0, |
| 140 | pathelementFunc, 0, 0); |
| 141 | url_initialize(&sURI, "dir"); |
| 142 | |
| 143 | /* If the name= parameter is an empty string, make it a NULL pointer */ |
| @@ -555,10 +556,11 @@ | |
| 556 | style_header("Folder Hierarchy"); |
| 557 | }else{ |
| 558 | showDirOnly = 0; |
| 559 | style_header("File Tree"); |
| 560 | } |
| 561 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 562 | if( P("expand")!=0 ){ |
| 563 | startExpanded = 1; |
| 564 | url_add_parameter(&sURI, "expand", "1"); |
| 565 | }else{ |
| 566 | startExpanded = 0; |
| @@ -635,10 +637,12 @@ | |
| 637 | } |
| 638 | if( linkTip ){ |
| 639 | style_submenu_element("Tip", "Tip", "%s", |
| 640 | url_render(&sURI, "ci", "tip", 0, 0)); |
| 641 | } |
| 642 | style_submenu_element("Flat-View", "Flat-View", "%s", |
| 643 | url_render(&sURI, "type", "flat", 0, 0)); |
| 644 | |
| 645 | /* Compute the file hierarchy. |
| 646 | */ |
| 647 | if( zCI ){ |
| 648 | Stmt q; |
| @@ -652,10 +656,13 @@ | |
| 656 | ); |
| 657 | while( db_step(&q)==SQLITE_ROW ){ |
| 658 | const char *zFile = db_column_text(&q,0); |
| 659 | const char *zUuid = db_column_text(&q,1); |
| 660 | double mtime = db_column_double(&q,2); |
| 661 | if( nD>0 && (fossil_strncmp(zFile, zD, nD-1)!=0 || zFile[nD-1]!='/') ){ |
| 662 | continue; |
| 663 | } |
| 664 | if( pRE && re_match(pRE, (const unsigned char*)zFile, -1)==0 ) continue; |
| 665 | tree_add_node(&sTree, zFile, zUuid, mtime); |
| 666 | nFile++; |
| 667 | } |
| 668 | db_finalize(&q); |
| 669 |
+10
-2
| --- src/builtin.c | ||
| +++ src/builtin.c | ||
| @@ -31,22 +31,30 @@ | ||
| 31 | 31 | |
| 32 | 32 | /* |
| 33 | 33 | ** Return a pointer to built-in content |
| 34 | 34 | */ |
| 35 | 35 | const unsigned char *builtin_file(const char *zFilename, int *piSize){ |
| 36 | - int lwr, upr, i; | |
| 36 | + int lwr, upr, i, c; | |
| 37 | 37 | lwr = 0; |
| 38 | 38 | upr = sizeof(aBuiltinFiles)/sizeof(aBuiltinFiles[0]) - 1; |
| 39 | 39 | while( upr>=lwr ){ |
| 40 | 40 | i = (upr+lwr)/2; |
| 41 | - if( strcmp(aBuiltinFiles[i].zName,zFilename)==0 ){ | |
| 41 | + c = strcmp(aBuiltinFiles[i].zName,zFilename); | |
| 42 | + if( c<0 ){ | |
| 43 | + lwr = i+1; | |
| 44 | + }else if( c>0 ){ | |
| 45 | + upr = i-1; | |
| 46 | + }else{ | |
| 42 | 47 | if( piSize ) *piSize = aBuiltinFiles[i].nByte; |
| 43 | 48 | return aBuiltinFiles[i].pData; |
| 44 | 49 | } |
| 45 | 50 | } |
| 46 | 51 | if( piSize ) *piSize = 0; |
| 47 | 52 | return 0; |
| 53 | +} | |
| 54 | +const char *builtin_text(const char *zFilename){ | |
| 55 | + return (char*)builtin_file(zFilename, 0); | |
| 48 | 56 | } |
| 49 | 57 | |
| 50 | 58 | /* |
| 51 | 59 | ** COMMAND: test-builtin-list |
| 52 | 60 | ** |
| 53 | 61 |
| --- src/builtin.c | |
| +++ src/builtin.c | |
| @@ -31,22 +31,30 @@ | |
| 31 | |
| 32 | /* |
| 33 | ** Return a pointer to built-in content |
| 34 | */ |
| 35 | const unsigned char *builtin_file(const char *zFilename, int *piSize){ |
| 36 | int lwr, upr, i; |
| 37 | lwr = 0; |
| 38 | upr = sizeof(aBuiltinFiles)/sizeof(aBuiltinFiles[0]) - 1; |
| 39 | while( upr>=lwr ){ |
| 40 | i = (upr+lwr)/2; |
| 41 | if( strcmp(aBuiltinFiles[i].zName,zFilename)==0 ){ |
| 42 | if( piSize ) *piSize = aBuiltinFiles[i].nByte; |
| 43 | return aBuiltinFiles[i].pData; |
| 44 | } |
| 45 | } |
| 46 | if( piSize ) *piSize = 0; |
| 47 | return 0; |
| 48 | } |
| 49 | |
| 50 | /* |
| 51 | ** COMMAND: test-builtin-list |
| 52 | ** |
| 53 |
| --- src/builtin.c | |
| +++ src/builtin.c | |
| @@ -31,22 +31,30 @@ | |
| 31 | |
| 32 | /* |
| 33 | ** Return a pointer to built-in content |
| 34 | */ |
| 35 | const unsigned char *builtin_file(const char *zFilename, int *piSize){ |
| 36 | int lwr, upr, i, c; |
| 37 | lwr = 0; |
| 38 | upr = sizeof(aBuiltinFiles)/sizeof(aBuiltinFiles[0]) - 1; |
| 39 | while( upr>=lwr ){ |
| 40 | i = (upr+lwr)/2; |
| 41 | c = strcmp(aBuiltinFiles[i].zName,zFilename); |
| 42 | if( c<0 ){ |
| 43 | lwr = i+1; |
| 44 | }else if( c>0 ){ |
| 45 | upr = i-1; |
| 46 | }else{ |
| 47 | if( piSize ) *piSize = aBuiltinFiles[i].nByte; |
| 48 | return aBuiltinFiles[i].pData; |
| 49 | } |
| 50 | } |
| 51 | if( piSize ) *piSize = 0; |
| 52 | return 0; |
| 53 | } |
| 54 | const char *builtin_text(const char *zFilename){ |
| 55 | return (char*)builtin_file(zFilename, 0); |
| 56 | } |
| 57 | |
| 58 | /* |
| 59 | ** COMMAND: test-builtin-list |
| 60 | ** |
| 61 |
+3
| --- src/cgi.c | ||
| +++ src/cgi.c | ||
| @@ -108,10 +108,13 @@ | ||
| 108 | 108 | ** if it does and false if it does not. |
| 109 | 109 | */ |
| 110 | 110 | int cgi_header_contains(const char *zNeedle){ |
| 111 | 111 | return strstr(blob_str(&cgiContent[0]), zNeedle)!=0; |
| 112 | 112 | } |
| 113 | +int cgi_body_contains(const char *zNeedle){ | |
| 114 | + return strstr(blob_str(&cgiContent[1]), zNeedle)!=0; | |
| 115 | +} | |
| 113 | 116 | |
| 114 | 117 | /* |
| 115 | 118 | ** Append reply content to what already exists. |
| 116 | 119 | */ |
| 117 | 120 | void cgi_append_content(const char *zData, int nAmt){ |
| 118 | 121 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -108,10 +108,13 @@ | |
| 108 | ** if it does and false if it does not. |
| 109 | */ |
| 110 | int cgi_header_contains(const char *zNeedle){ |
| 111 | return strstr(blob_str(&cgiContent[0]), zNeedle)!=0; |
| 112 | } |
| 113 | |
| 114 | /* |
| 115 | ** Append reply content to what already exists. |
| 116 | */ |
| 117 | void cgi_append_content(const char *zData, int nAmt){ |
| 118 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -108,10 +108,13 @@ | |
| 108 | ** if it does and false if it does not. |
| 109 | */ |
| 110 | int cgi_header_contains(const char *zNeedle){ |
| 111 | return strstr(blob_str(&cgiContent[0]), zNeedle)!=0; |
| 112 | } |
| 113 | int cgi_body_contains(const char *zNeedle){ |
| 114 | return strstr(blob_str(&cgiContent[1]), zNeedle)!=0; |
| 115 | } |
| 116 | |
| 117 | /* |
| 118 | ** Append reply content to what already exists. |
| 119 | */ |
| 120 | void cgi_append_content(const char *zData, int nAmt){ |
| 121 |
+4
-4
| --- src/codecheck1.c | ||
| +++ src/codecheck1.c | ||
| @@ -276,11 +276,11 @@ | ||
| 276 | 276 | |
| 277 | 277 | /* Certain functions are guaranteed to return a string that is safe |
| 278 | 278 | ** for use with %s */ |
| 279 | 279 | z = next_non_whitespace(z, &len, &eType); |
| 280 | 280 | for(i=0; i<sizeof(azSafeFunc)/sizeof(azSafeFunc[0]); i++){ |
| 281 | - if( eType==TK_ID | |
| 281 | + if( eType==TK_ID | |
| 282 | 282 | && strncmp(z, azSafeFunc[i], len)==0 |
| 283 | 283 | && strlen(azSafeFunc[i])==len |
| 284 | 284 | ){ |
| 285 | 285 | return 1; |
| 286 | 286 | } |
| @@ -291,11 +291,11 @@ | ||
| 291 | 291 | if( is_string_expr(z) ) return 1; |
| 292 | 292 | |
| 293 | 293 | /* If the "safe-for-%s" comment appears in the argument, then |
| 294 | 294 | ** let it through */ |
| 295 | 295 | if( strstr(z, "/*safe-for-%s*/")!=0 ) return 1; |
| 296 | - | |
| 296 | + | |
| 297 | 297 | return 0; |
| 298 | 298 | } |
| 299 | 299 | |
| 300 | 300 | /* |
| 301 | 301 | ** Processing flags |
| @@ -460,11 +460,11 @@ | ||
| 460 | 460 | for(i=len-1; i>0 && isspace(z[i]); i--){ z[i] = 0; } |
| 461 | 461 | z += len + 1; |
| 462 | 462 | } |
| 463 | 463 | acType = (char*)&azArg[nArg]; |
| 464 | 464 | if( fmtArg>nArg ){ |
| 465 | - printf("%s:%d: too few arguments to %.*s()\n", | |
| 465 | + printf("%s:%d: too few arguments to %.*s()\n", | |
| 466 | 466 | zFilename, lnFCall, szFName, zFCall); |
| 467 | 467 | nErr++; |
| 468 | 468 | }else{ |
| 469 | 469 | const char *zFmt = azArg[fmtArg-1]; |
| 470 | 470 | const char *zOverride = strstr(zFmt, "/*works-like:"); |
| @@ -537,11 +537,11 @@ | ||
| 537 | 537 | nCurly--; |
| 538 | 538 | }else if( nCurly>0 && z[0]=='(' && ePrev==TK_ID |
| 539 | 539 | && (x = isFormatFunc(zPrev,szPrev,&fmtFlags))>0 ){ |
| 540 | 540 | nErr += checkFormatFunc(zName, zPrev, lnPrev, x, fmtFlags); |
| 541 | 541 | } |
| 542 | - } | |
| 542 | + } | |
| 543 | 543 | zPrev = z; |
| 544 | 544 | ePrev = eToken; |
| 545 | 545 | szPrev = szToken; |
| 546 | 546 | lnPrev = ln; |
| 547 | 547 | } |
| 548 | 548 |
| --- src/codecheck1.c | |
| +++ src/codecheck1.c | |
| @@ -276,11 +276,11 @@ | |
| 276 | |
| 277 | /* Certain functions are guaranteed to return a string that is safe |
| 278 | ** for use with %s */ |
| 279 | z = next_non_whitespace(z, &len, &eType); |
| 280 | for(i=0; i<sizeof(azSafeFunc)/sizeof(azSafeFunc[0]); i++){ |
| 281 | if( eType==TK_ID |
| 282 | && strncmp(z, azSafeFunc[i], len)==0 |
| 283 | && strlen(azSafeFunc[i])==len |
| 284 | ){ |
| 285 | return 1; |
| 286 | } |
| @@ -291,11 +291,11 @@ | |
| 291 | if( is_string_expr(z) ) return 1; |
| 292 | |
| 293 | /* If the "safe-for-%s" comment appears in the argument, then |
| 294 | ** let it through */ |
| 295 | if( strstr(z, "/*safe-for-%s*/")!=0 ) return 1; |
| 296 | |
| 297 | return 0; |
| 298 | } |
| 299 | |
| 300 | /* |
| 301 | ** Processing flags |
| @@ -460,11 +460,11 @@ | |
| 460 | for(i=len-1; i>0 && isspace(z[i]); i--){ z[i] = 0; } |
| 461 | z += len + 1; |
| 462 | } |
| 463 | acType = (char*)&azArg[nArg]; |
| 464 | if( fmtArg>nArg ){ |
| 465 | printf("%s:%d: too few arguments to %.*s()\n", |
| 466 | zFilename, lnFCall, szFName, zFCall); |
| 467 | nErr++; |
| 468 | }else{ |
| 469 | const char *zFmt = azArg[fmtArg-1]; |
| 470 | const char *zOverride = strstr(zFmt, "/*works-like:"); |
| @@ -537,11 +537,11 @@ | |
| 537 | nCurly--; |
| 538 | }else if( nCurly>0 && z[0]=='(' && ePrev==TK_ID |
| 539 | && (x = isFormatFunc(zPrev,szPrev,&fmtFlags))>0 ){ |
| 540 | nErr += checkFormatFunc(zName, zPrev, lnPrev, x, fmtFlags); |
| 541 | } |
| 542 | } |
| 543 | zPrev = z; |
| 544 | ePrev = eToken; |
| 545 | szPrev = szToken; |
| 546 | lnPrev = ln; |
| 547 | } |
| 548 |
| --- src/codecheck1.c | |
| +++ src/codecheck1.c | |
| @@ -276,11 +276,11 @@ | |
| 276 | |
| 277 | /* Certain functions are guaranteed to return a string that is safe |
| 278 | ** for use with %s */ |
| 279 | z = next_non_whitespace(z, &len, &eType); |
| 280 | for(i=0; i<sizeof(azSafeFunc)/sizeof(azSafeFunc[0]); i++){ |
| 281 | if( eType==TK_ID |
| 282 | && strncmp(z, azSafeFunc[i], len)==0 |
| 283 | && strlen(azSafeFunc[i])==len |
| 284 | ){ |
| 285 | return 1; |
| 286 | } |
| @@ -291,11 +291,11 @@ | |
| 291 | if( is_string_expr(z) ) return 1; |
| 292 | |
| 293 | /* If the "safe-for-%s" comment appears in the argument, then |
| 294 | ** let it through */ |
| 295 | if( strstr(z, "/*safe-for-%s*/")!=0 ) return 1; |
| 296 | |
| 297 | return 0; |
| 298 | } |
| 299 | |
| 300 | /* |
| 301 | ** Processing flags |
| @@ -460,11 +460,11 @@ | |
| 460 | for(i=len-1; i>0 && isspace(z[i]); i--){ z[i] = 0; } |
| 461 | z += len + 1; |
| 462 | } |
| 463 | acType = (char*)&azArg[nArg]; |
| 464 | if( fmtArg>nArg ){ |
| 465 | printf("%s:%d: too few arguments to %.*s()\n", |
| 466 | zFilename, lnFCall, szFName, zFCall); |
| 467 | nErr++; |
| 468 | }else{ |
| 469 | const char *zFmt = azArg[fmtArg-1]; |
| 470 | const char *zOverride = strstr(zFmt, "/*works-like:"); |
| @@ -537,11 +537,11 @@ | |
| 537 | nCurly--; |
| 538 | }else if( nCurly>0 && z[0]=='(' && ePrev==TK_ID |
| 539 | && (x = isFormatFunc(zPrev,szPrev,&fmtFlags))>0 ){ |
| 540 | nErr += checkFormatFunc(zName, zPrev, lnPrev, x, fmtFlags); |
| 541 | } |
| 542 | } |
| 543 | zPrev = z; |
| 544 | ePrev = eToken; |
| 545 | szPrev = szToken; |
| 546 | lnPrev = ln; |
| 547 | } |
| 548 |
+192
| --- src/configure.c | ||
| +++ src/configure.c | ||
| @@ -97,10 +97,11 @@ | ||
| 97 | 97 | { "timeline-max-comment", CONFIGSET_SKIN }, |
| 98 | 98 | { "timeline-plaintext", CONFIGSET_SKIN }, |
| 99 | 99 | { "adunit", CONFIGSET_SKIN }, |
| 100 | 100 | { "adunit-omit-if-admin", CONFIGSET_SKIN }, |
| 101 | 101 | { "adunit-omit-if-user", CONFIGSET_SKIN }, |
| 102 | + { "white-foreground", CONFIGSET_SKIN }, | |
| 102 | 103 | #ifdef FOSSIL_ENABLE_TH1_DOCS |
| 103 | 104 | { "th1-docs", CONFIGSET_TH1 }, |
| 104 | 105 | #endif |
| 105 | 106 | #ifdef FOSSIL_ENABLE_TH1_HOOKS |
| 106 | 107 | { "th1-hooks", CONFIGSET_TH1 }, |
| @@ -989,5 +990,196 @@ | ||
| 989 | 990 | fossil_fatal("METHOD should be one of:" |
| 990 | 991 | " export import merge pull push reset"); |
| 991 | 992 | } |
| 992 | 993 | configure_rebuild(); |
| 993 | 994 | } |
| 995 | + | |
| 996 | + | |
| 997 | +/* | |
| 998 | +** COMMAND: test-var-list | |
| 999 | +** | |
| 1000 | +** Usage: %fossil test-var-list ?PATTERN? ?--unset? ?--mtime? | |
| 1001 | +** | |
| 1002 | +** Show the content of the CONFIG table in a repository. If PATTERN is | |
| 1003 | +** specified, then only show the entries that match that glob pattern. | |
| 1004 | +** Last modification time is shown if the --mtime option is present. | |
| 1005 | +** | |
| 1006 | +** If the --unset option is included, then entries are deleted rather than | |
| 1007 | +** being displayed. WARNING! This cannot be undone. Be sure you know what | |
| 1008 | +** you are doing! The --unset option only works if there is a PATTERN. | |
| 1009 | +** Probably you should run the command once without --unset to make sure | |
| 1010 | +** you know exactly what is being deleted. | |
| 1011 | +** | |
| 1012 | +** If not in an open check-out, use the -R REPO option to specify a | |
| 1013 | +** a repository. | |
| 1014 | +*/ | |
| 1015 | +void test_var_list_cmd(void){ | |
| 1016 | + Stmt q; | |
| 1017 | + int i, j; | |
| 1018 | + const char *zPattern = 0; | |
| 1019 | + int doUnset; | |
| 1020 | + int showMtime; | |
| 1021 | + Blob sql; | |
| 1022 | + Blob ans; | |
| 1023 | + unsigned char zTrans[1000]; | |
| 1024 | + | |
| 1025 | + doUnset = find_option("unset",0,0)!=0; | |
| 1026 | + showMtime = find_option("mtime",0,0)!=0; | |
| 1027 | + db_find_and_open_repository(OPEN_ANY_SCHEMA, 0); | |
| 1028 | + verify_all_options(); | |
| 1029 | + if( g.argc>=3 ){ | |
| 1030 | + zPattern = g.argv[2]; | |
| 1031 | + } | |
| 1032 | + blob_init(&sql,0,0); | |
| 1033 | + blob_appendf(&sql, "SELECT name, value, datetime(mtime,'unixepoch')" | |
| 1034 | + " FROM config"); | |
| 1035 | + if( zPattern ){ | |
| 1036 | + blob_appendf(&sql, " WHERE name GLOB %Q", zPattern); | |
| 1037 | + } | |
| 1038 | + if( showMtime ){ | |
| 1039 | + blob_appendf(&sql, " ORDER BY mtime, name"); | |
| 1040 | + }else{ | |
| 1041 | + blob_appendf(&sql, " ORDER BY name"); | |
| 1042 | + } | |
| 1043 | + db_prepare(&q, "%s", blob_str(&sql)/*safe-for-%s*/); | |
| 1044 | + blob_reset(&sql); | |
| 1045 | +#define MX_VAL 40 | |
| 1046 | +#define MX_NM 28 | |
| 1047 | +#define MX_LONGNM 60 | |
| 1048 | + while( db_step(&q)==SQLITE_ROW ){ | |
| 1049 | + const char *zName = db_column_text(&q,0); | |
| 1050 | + int nName = db_column_bytes(&q,0); | |
| 1051 | + const char *zValue = db_column_text(&q,1); | |
| 1052 | + int szValue = db_column_bytes(&q,1); | |
| 1053 | + const char *zMTime = db_column_text(&q,2); | |
| 1054 | + for(i=j=0; j<MX_VAL && zValue[i]; i++){ | |
| 1055 | + unsigned char c = (unsigned char)zValue[i]; | |
| 1056 | + if( c>=' ' && c<='~' ){ | |
| 1057 | + zTrans[j++] = c; | |
| 1058 | + }else{ | |
| 1059 | + zTrans[j++] = '\\'; | |
| 1060 | + if( c=='\n' ){ | |
| 1061 | + zTrans[j++] = 'n'; | |
| 1062 | + }else if( c=='\r' ){ | |
| 1063 | + zTrans[j++] = 'r'; | |
| 1064 | + }else if( c=='\t' ){ | |
| 1065 | + zTrans[j++] = 't'; | |
| 1066 | + }else{ | |
| 1067 | + zTrans[j++] = '0' + ((c>>6)&7); | |
| 1068 | + zTrans[j++] = '0' + ((c>>3)&7); | |
| 1069 | + zTrans[j++] = '0' + (c&7); | |
| 1070 | + } | |
| 1071 | + } | |
| 1072 | + } | |
| 1073 | + zTrans[j] = 0; | |
| 1074 | + if( i<szValue ){ | |
| 1075 | + sqlite3_snprintf(sizeof(zTrans)-j, (char*)zTrans+j, "...+%d", szValue-i); | |
| 1076 | + j += (int)strlen((char*)zTrans+j); | |
| 1077 | + } | |
| 1078 | + if( showMtime ){ | |
| 1079 | + fossil_print("%s:%*s%s\n", zName, 58-nName, "", zMTime); | |
| 1080 | + }else if( nName<MX_NM-2 ){ | |
| 1081 | + fossil_print("%s:%*s%s\n", zName, MX_NM-1-nName, "", zTrans); | |
| 1082 | + }else if( nName<MX_LONGNM-2 && j<10 ){ | |
| 1083 | + fossil_print("%s:%*s%s\n", zName, MX_LONGNM-1-nName, "", zTrans); | |
| 1084 | + }else{ | |
| 1085 | + fossil_print("%s:\n%*s%s\n", zName, MX_NM, "", zTrans); | |
| 1086 | + } | |
| 1087 | + } | |
| 1088 | + db_finalize(&q); | |
| 1089 | + if( zPattern && doUnset ){ | |
| 1090 | + prompt_user("Delete all of the above? (y/N)? ", &ans); | |
| 1091 | + if( blob_str(&ans)[0]=='y' || blob_str(&ans)[0]=='Y' ){ | |
| 1092 | + db_multi_exec("DELETE FROM config WHERE name GLOB %Q", zPattern); | |
| 1093 | + } | |
| 1094 | + blob_reset(&ans); | |
| 1095 | + } | |
| 1096 | +} | |
| 1097 | + | |
| 1098 | +/* | |
| 1099 | +** COMMAND: test-var-get | |
| 1100 | +** | |
| 1101 | +** Usage: %fossil test-var-get VAR ?FILE? | |
| 1102 | +** | |
| 1103 | +** Write the text of the VAR variable into FILE. If FILE is "-" | |
| 1104 | +** or is omitted then output goes to standard output. VAR can be a | |
| 1105 | +** GLOB pattern. | |
| 1106 | +** | |
| 1107 | +** If not in an open check-out, use the -R REPO option to specify a | |
| 1108 | +** a repository. | |
| 1109 | +*/ | |
| 1110 | +void test_var_get_cmd(void){ | |
| 1111 | + const char *zVar; | |
| 1112 | + const char *zFile; | |
| 1113 | + int n; | |
| 1114 | + Blob x; | |
| 1115 | + db_find_and_open_repository(OPEN_ANY_SCHEMA, 0); | |
| 1116 | + verify_all_options(); | |
| 1117 | + if( g.argc<3 ){ | |
| 1118 | + usage("VAR ?FILE?"); | |
| 1119 | + } | |
| 1120 | + zVar = g.argv[2]; | |
| 1121 | + zFile = g.argc>=4 ? g.argv[3] : "-"; | |
| 1122 | + n = db_int(0, "SELECT count(*) FROM config WHERE name GLOB %Q", zVar); | |
| 1123 | + if( n==0 ){ | |
| 1124 | + fossil_fatal("no match for %Q", zVar); | |
| 1125 | + } | |
| 1126 | + if( n>1 ){ | |
| 1127 | + fossil_fatal("multiple matches: %s", | |
| 1128 | + db_text(0, "SELECT group_concat(quote(name),', ') FROM (" | |
| 1129 | + " SELECT name FROM config WHERE name GLOB %Q ORDER BY 1)", | |
| 1130 | + zVar)); | |
| 1131 | + } | |
| 1132 | + blob_init(&x,0,0); | |
| 1133 | + db_blob(&x, "SELECT value FROM config WHERE name GLOB %Q", zVar); | |
| 1134 | + blob_write_to_file(&x, zFile); | |
| 1135 | +} | |
| 1136 | + | |
| 1137 | +/* | |
| 1138 | +** COMMAND: test-var-set | |
| 1139 | +** | |
| 1140 | +** Usage: %fossil test-var-set VAR ?VALUE? ?--file FILE? | |
| 1141 | +** | |
| 1142 | +** Store VALUE or the content of FILE (exactly one of which must be | |
| 1143 | +** supplied) into variable VAR. Use a FILE of "-" to read from | |
| 1144 | +** standard input. | |
| 1145 | +** | |
| 1146 | +** WARNING: changing the value of a variable can interfere with the | |
| 1147 | +** operation of Fossil. Be sure you know what you are doing. | |
| 1148 | +** | |
| 1149 | +** Use "--blob FILE" instead of "--file FILE" to load a binary blob | |
| 1150 | +** such as a GIF. | |
| 1151 | +*/ | |
| 1152 | +void test_var_set_cmd(void){ | |
| 1153 | + const char *zVar; | |
| 1154 | + const char *zFile; | |
| 1155 | + const char *zBlob; | |
| 1156 | + Blob x; | |
| 1157 | + Stmt ins; | |
| 1158 | + zFile = find_option("file",0,1); | |
| 1159 | + zBlob = find_option("blob",0,1); | |
| 1160 | + db_find_and_open_repository(OPEN_ANY_SCHEMA, 0); | |
| 1161 | + verify_all_options(); | |
| 1162 | + if( g.argc<3 || (zFile==0 && zBlob==0 && g.argc<4) ){ | |
| 1163 | + usage("VAR ?VALUE? ?--file FILE?"); | |
| 1164 | + } | |
| 1165 | + zVar = g.argv[2]; | |
| 1166 | + if( zFile ){ | |
| 1167 | + if( zBlob ) fossil_fatal("cannot do both --file or --blob"); | |
| 1168 | + blob_read_from_file(&x, zFile); | |
| 1169 | + }else if( zBlob ){ | |
| 1170 | + blob_read_from_file(&x, zBlob); | |
| 1171 | + }else{ | |
| 1172 | + blob_init(&x,g.argv[3],-1); | |
| 1173 | + } | |
| 1174 | + db_prepare(&ins, | |
| 1175 | + "REPLACE INTO config(name,value,mtime)" | |
| 1176 | + "VALUES(%Q,:val,now())", zVar); | |
| 1177 | + if( zBlob ){ | |
| 1178 | + db_bind_blob(&ins, ":val", &x); | |
| 1179 | + }else{ | |
| 1180 | + db_bind_text(&ins, ":val", blob_str(&x)); | |
| 1181 | + } | |
| 1182 | + db_step(&ins); | |
| 1183 | + db_finalize(&ins); | |
| 1184 | + blob_reset(&x); | |
| 1185 | +} | |
| 994 | 1186 |
| --- src/configure.c | |
| +++ src/configure.c | |
| @@ -97,10 +97,11 @@ | |
| 97 | { "timeline-max-comment", CONFIGSET_SKIN }, |
| 98 | { "timeline-plaintext", CONFIGSET_SKIN }, |
| 99 | { "adunit", CONFIGSET_SKIN }, |
| 100 | { "adunit-omit-if-admin", CONFIGSET_SKIN }, |
| 101 | { "adunit-omit-if-user", CONFIGSET_SKIN }, |
| 102 | #ifdef FOSSIL_ENABLE_TH1_DOCS |
| 103 | { "th1-docs", CONFIGSET_TH1 }, |
| 104 | #endif |
| 105 | #ifdef FOSSIL_ENABLE_TH1_HOOKS |
| 106 | { "th1-hooks", CONFIGSET_TH1 }, |
| @@ -989,5 +990,196 @@ | |
| 989 | fossil_fatal("METHOD should be one of:" |
| 990 | " export import merge pull push reset"); |
| 991 | } |
| 992 | configure_rebuild(); |
| 993 | } |
| 994 |
| --- src/configure.c | |
| +++ src/configure.c | |
| @@ -97,10 +97,11 @@ | |
| 97 | { "timeline-max-comment", CONFIGSET_SKIN }, |
| 98 | { "timeline-plaintext", CONFIGSET_SKIN }, |
| 99 | { "adunit", CONFIGSET_SKIN }, |
| 100 | { "adunit-omit-if-admin", CONFIGSET_SKIN }, |
| 101 | { "adunit-omit-if-user", CONFIGSET_SKIN }, |
| 102 | { "white-foreground", CONFIGSET_SKIN }, |
| 103 | #ifdef FOSSIL_ENABLE_TH1_DOCS |
| 104 | { "th1-docs", CONFIGSET_TH1 }, |
| 105 | #endif |
| 106 | #ifdef FOSSIL_ENABLE_TH1_HOOKS |
| 107 | { "th1-hooks", CONFIGSET_TH1 }, |
| @@ -989,5 +990,196 @@ | |
| 990 | fossil_fatal("METHOD should be one of:" |
| 991 | " export import merge pull push reset"); |
| 992 | } |
| 993 | configure_rebuild(); |
| 994 | } |
| 995 | |
| 996 | |
| 997 | /* |
| 998 | ** COMMAND: test-var-list |
| 999 | ** |
| 1000 | ** Usage: %fossil test-var-list ?PATTERN? ?--unset? ?--mtime? |
| 1001 | ** |
| 1002 | ** Show the content of the CONFIG table in a repository. If PATTERN is |
| 1003 | ** specified, then only show the entries that match that glob pattern. |
| 1004 | ** Last modification time is shown if the --mtime option is present. |
| 1005 | ** |
| 1006 | ** If the --unset option is included, then entries are deleted rather than |
| 1007 | ** being displayed. WARNING! This cannot be undone. Be sure you know what |
| 1008 | ** you are doing! The --unset option only works if there is a PATTERN. |
| 1009 | ** Probably you should run the command once without --unset to make sure |
| 1010 | ** you know exactly what is being deleted. |
| 1011 | ** |
| 1012 | ** If not in an open check-out, use the -R REPO option to specify a |
| 1013 | ** a repository. |
| 1014 | */ |
| 1015 | void test_var_list_cmd(void){ |
| 1016 | Stmt q; |
| 1017 | int i, j; |
| 1018 | const char *zPattern = 0; |
| 1019 | int doUnset; |
| 1020 | int showMtime; |
| 1021 | Blob sql; |
| 1022 | Blob ans; |
| 1023 | unsigned char zTrans[1000]; |
| 1024 | |
| 1025 | doUnset = find_option("unset",0,0)!=0; |
| 1026 | showMtime = find_option("mtime",0,0)!=0; |
| 1027 | db_find_and_open_repository(OPEN_ANY_SCHEMA, 0); |
| 1028 | verify_all_options(); |
| 1029 | if( g.argc>=3 ){ |
| 1030 | zPattern = g.argv[2]; |
| 1031 | } |
| 1032 | blob_init(&sql,0,0); |
| 1033 | blob_appendf(&sql, "SELECT name, value, datetime(mtime,'unixepoch')" |
| 1034 | " FROM config"); |
| 1035 | if( zPattern ){ |
| 1036 | blob_appendf(&sql, " WHERE name GLOB %Q", zPattern); |
| 1037 | } |
| 1038 | if( showMtime ){ |
| 1039 | blob_appendf(&sql, " ORDER BY mtime, name"); |
| 1040 | }else{ |
| 1041 | blob_appendf(&sql, " ORDER BY name"); |
| 1042 | } |
| 1043 | db_prepare(&q, "%s", blob_str(&sql)/*safe-for-%s*/); |
| 1044 | blob_reset(&sql); |
| 1045 | #define MX_VAL 40 |
| 1046 | #define MX_NM 28 |
| 1047 | #define MX_LONGNM 60 |
| 1048 | while( db_step(&q)==SQLITE_ROW ){ |
| 1049 | const char *zName = db_column_text(&q,0); |
| 1050 | int nName = db_column_bytes(&q,0); |
| 1051 | const char *zValue = db_column_text(&q,1); |
| 1052 | int szValue = db_column_bytes(&q,1); |
| 1053 | const char *zMTime = db_column_text(&q,2); |
| 1054 | for(i=j=0; j<MX_VAL && zValue[i]; i++){ |
| 1055 | unsigned char c = (unsigned char)zValue[i]; |
| 1056 | if( c>=' ' && c<='~' ){ |
| 1057 | zTrans[j++] = c; |
| 1058 | }else{ |
| 1059 | zTrans[j++] = '\\'; |
| 1060 | if( c=='\n' ){ |
| 1061 | zTrans[j++] = 'n'; |
| 1062 | }else if( c=='\r' ){ |
| 1063 | zTrans[j++] = 'r'; |
| 1064 | }else if( c=='\t' ){ |
| 1065 | zTrans[j++] = 't'; |
| 1066 | }else{ |
| 1067 | zTrans[j++] = '0' + ((c>>6)&7); |
| 1068 | zTrans[j++] = '0' + ((c>>3)&7); |
| 1069 | zTrans[j++] = '0' + (c&7); |
| 1070 | } |
| 1071 | } |
| 1072 | } |
| 1073 | zTrans[j] = 0; |
| 1074 | if( i<szValue ){ |
| 1075 | sqlite3_snprintf(sizeof(zTrans)-j, (char*)zTrans+j, "...+%d", szValue-i); |
| 1076 | j += (int)strlen((char*)zTrans+j); |
| 1077 | } |
| 1078 | if( showMtime ){ |
| 1079 | fossil_print("%s:%*s%s\n", zName, 58-nName, "", zMTime); |
| 1080 | }else if( nName<MX_NM-2 ){ |
| 1081 | fossil_print("%s:%*s%s\n", zName, MX_NM-1-nName, "", zTrans); |
| 1082 | }else if( nName<MX_LONGNM-2 && j<10 ){ |
| 1083 | fossil_print("%s:%*s%s\n", zName, MX_LONGNM-1-nName, "", zTrans); |
| 1084 | }else{ |
| 1085 | fossil_print("%s:\n%*s%s\n", zName, MX_NM, "", zTrans); |
| 1086 | } |
| 1087 | } |
| 1088 | db_finalize(&q); |
| 1089 | if( zPattern && doUnset ){ |
| 1090 | prompt_user("Delete all of the above? (y/N)? ", &ans); |
| 1091 | if( blob_str(&ans)[0]=='y' || blob_str(&ans)[0]=='Y' ){ |
| 1092 | db_multi_exec("DELETE FROM config WHERE name GLOB %Q", zPattern); |
| 1093 | } |
| 1094 | blob_reset(&ans); |
| 1095 | } |
| 1096 | } |
| 1097 | |
| 1098 | /* |
| 1099 | ** COMMAND: test-var-get |
| 1100 | ** |
| 1101 | ** Usage: %fossil test-var-get VAR ?FILE? |
| 1102 | ** |
| 1103 | ** Write the text of the VAR variable into FILE. If FILE is "-" |
| 1104 | ** or is omitted then output goes to standard output. VAR can be a |
| 1105 | ** GLOB pattern. |
| 1106 | ** |
| 1107 | ** If not in an open check-out, use the -R REPO option to specify a |
| 1108 | ** a repository. |
| 1109 | */ |
| 1110 | void test_var_get_cmd(void){ |
| 1111 | const char *zVar; |
| 1112 | const char *zFile; |
| 1113 | int n; |
| 1114 | Blob x; |
| 1115 | db_find_and_open_repository(OPEN_ANY_SCHEMA, 0); |
| 1116 | verify_all_options(); |
| 1117 | if( g.argc<3 ){ |
| 1118 | usage("VAR ?FILE?"); |
| 1119 | } |
| 1120 | zVar = g.argv[2]; |
| 1121 | zFile = g.argc>=4 ? g.argv[3] : "-"; |
| 1122 | n = db_int(0, "SELECT count(*) FROM config WHERE name GLOB %Q", zVar); |
| 1123 | if( n==0 ){ |
| 1124 | fossil_fatal("no match for %Q", zVar); |
| 1125 | } |
| 1126 | if( n>1 ){ |
| 1127 | fossil_fatal("multiple matches: %s", |
| 1128 | db_text(0, "SELECT group_concat(quote(name),', ') FROM (" |
| 1129 | " SELECT name FROM config WHERE name GLOB %Q ORDER BY 1)", |
| 1130 | zVar)); |
| 1131 | } |
| 1132 | blob_init(&x,0,0); |
| 1133 | db_blob(&x, "SELECT value FROM config WHERE name GLOB %Q", zVar); |
| 1134 | blob_write_to_file(&x, zFile); |
| 1135 | } |
| 1136 | |
| 1137 | /* |
| 1138 | ** COMMAND: test-var-set |
| 1139 | ** |
| 1140 | ** Usage: %fossil test-var-set VAR ?VALUE? ?--file FILE? |
| 1141 | ** |
| 1142 | ** Store VALUE or the content of FILE (exactly one of which must be |
| 1143 | ** supplied) into variable VAR. Use a FILE of "-" to read from |
| 1144 | ** standard input. |
| 1145 | ** |
| 1146 | ** WARNING: changing the value of a variable can interfere with the |
| 1147 | ** operation of Fossil. Be sure you know what you are doing. |
| 1148 | ** |
| 1149 | ** Use "--blob FILE" instead of "--file FILE" to load a binary blob |
| 1150 | ** such as a GIF. |
| 1151 | */ |
| 1152 | void test_var_set_cmd(void){ |
| 1153 | const char *zVar; |
| 1154 | const char *zFile; |
| 1155 | const char *zBlob; |
| 1156 | Blob x; |
| 1157 | Stmt ins; |
| 1158 | zFile = find_option("file",0,1); |
| 1159 | zBlob = find_option("blob",0,1); |
| 1160 | db_find_and_open_repository(OPEN_ANY_SCHEMA, 0); |
| 1161 | verify_all_options(); |
| 1162 | if( g.argc<3 || (zFile==0 && zBlob==0 && g.argc<4) ){ |
| 1163 | usage("VAR ?VALUE? ?--file FILE?"); |
| 1164 | } |
| 1165 | zVar = g.argv[2]; |
| 1166 | if( zFile ){ |
| 1167 | if( zBlob ) fossil_fatal("cannot do both --file or --blob"); |
| 1168 | blob_read_from_file(&x, zFile); |
| 1169 | }else if( zBlob ){ |
| 1170 | blob_read_from_file(&x, zBlob); |
| 1171 | }else{ |
| 1172 | blob_init(&x,g.argv[3],-1); |
| 1173 | } |
| 1174 | db_prepare(&ins, |
| 1175 | "REPLACE INTO config(name,value,mtime)" |
| 1176 | "VALUES(%Q,:val,now())", zVar); |
| 1177 | if( zBlob ){ |
| 1178 | db_bind_blob(&ins, ":val", &x); |
| 1179 | }else{ |
| 1180 | db_bind_text(&ins, ":val", blob_str(&x)); |
| 1181 | } |
| 1182 | db_step(&ins); |
| 1183 | db_finalize(&ins); |
| 1184 | blob_reset(&x); |
| 1185 | } |
| 1186 |
M
src/db.c
+41
-24
| --- src/db.c | ||
| +++ src/db.c | ||
| @@ -805,10 +805,12 @@ | ||
| 805 | 805 | db_checkin_mtime_function, 0, 0); |
| 806 | 806 | sqlite3_create_function(db, "symbolic_name_to_rid", 1, SQLITE_UTF8, 0, |
| 807 | 807 | db_sym2rid_function, 0, 0); |
| 808 | 808 | sqlite3_create_function(db, "symbolic_name_to_rid", 2, SQLITE_UTF8, 0, |
| 809 | 809 | db_sym2rid_function, 0, 0); |
| 810 | + sqlite3_create_function(db, "now", 0, SQLITE_UTF8, 0, | |
| 811 | + db_now_function, 0, 0); | |
| 810 | 812 | } |
| 811 | 813 | |
| 812 | 814 | |
| 813 | 815 | /* |
| 814 | 816 | ** Open a database file. Return a pointer to the new database |
| @@ -827,12 +829,10 @@ | ||
| 827 | 829 | if( rc!=SQLITE_OK ){ |
| 828 | 830 | db_err("[%s]: %s", zDbName, sqlite3_errmsg(db)); |
| 829 | 831 | } |
| 830 | 832 | sqlite3_busy_timeout(db, 5000); |
| 831 | 833 | sqlite3_wal_autocheckpoint(db, 1); /* Set to checkpoint frequently */ |
| 832 | - sqlite3_create_function(db, "now", 0, SQLITE_UTF8, 0, | |
| 833 | - db_now_function, 0, 0); | |
| 834 | 834 | sqlite3_create_function(db, "user", 0, SQLITE_UTF8, 0, db_sql_user, 0, 0); |
| 835 | 835 | sqlite3_create_function(db, "cgi", 1, SQLITE_UTF8, 0, db_sql_cgi, 0, 0); |
| 836 | 836 | sqlite3_create_function(db, "cgi", 2, SQLITE_UTF8, 0, db_sql_cgi, 0, 0); |
| 837 | 837 | sqlite3_create_function(db, "print", -1, SQLITE_UTF8, 0,db_sql_print,0,0); |
| 838 | 838 | sqlite3_create_function( |
| @@ -927,30 +927,35 @@ | ||
| 927 | 927 | char *zHome; |
| 928 | 928 | if( g.zConfigDbName ){ |
| 929 | 929 | if( useAttach==g.useAttach ) return; |
| 930 | 930 | db_close_config(); |
| 931 | 931 | } |
| 932 | -#if defined(_WIN32) || defined(__CYGWIN__) | |
| 933 | - zHome = fossil_getenv("LOCALAPPDATA"); | |
| 934 | - if( zHome==0 ){ | |
| 935 | - zHome = fossil_getenv("APPDATA"); | |
| 936 | - if( zHome==0 ){ | |
| 937 | - char *zDrive = fossil_getenv("HOMEDRIVE"); | |
| 938 | - zHome = fossil_getenv("HOMEPATH"); | |
| 939 | - if( zDrive && zHome ) zHome = mprintf("%s%s", zDrive, zHome); | |
| 940 | - } | |
| 941 | - } | |
| 942 | - if( zHome==0 ){ | |
| 943 | - fossil_fatal("cannot locate home directory - " | |
| 944 | - "please set the LOCALAPPDATA or APPDATA or HOMEPATH " | |
| 945 | - "environment variables"); | |
| 946 | - } | |
| 947 | -#else | |
| 948 | - zHome = fossil_getenv("HOME"); | |
| 949 | - if( zHome==0 ){ | |
| 950 | - fossil_fatal("cannot locate home directory - " | |
| 951 | - "please set the HOME environment variable"); | |
| 932 | + zHome = fossil_getenv("FOSSIL_HOME"); | |
| 933 | +#if defined(_WIN32) || defined(__CYGWIN__) | |
| 934 | + if( zHome==0 ){ | |
| 935 | + zHome = fossil_getenv("LOCALAPPDATA"); | |
| 936 | + if( zHome==0 ){ | |
| 937 | + zHome = fossil_getenv("APPDATA"); | |
| 938 | + if( zHome==0 ){ | |
| 939 | + char *zDrive = fossil_getenv("HOMEDRIVE"); | |
| 940 | + char *zPath = fossil_getenv("HOMEPATH"); | |
| 941 | + if( zDrive && zPath ) zHome = mprintf("%s%s", zDrive, zPath); | |
| 942 | + } | |
| 943 | + } | |
| 944 | + } | |
| 945 | + if( zHome==0 ){ | |
| 946 | + fossil_fatal("cannot locate home directory - please set the " | |
| 947 | + "FOSSIL_HOME, LOCALAPPDATA, APPDATA, or HOMEPATH " | |
| 948 | + "environment variables"); | |
| 949 | + } | |
| 950 | +#else | |
| 951 | + if( zHome==0 ){ | |
| 952 | + zHome = fossil_getenv("HOME"); | |
| 953 | + } | |
| 954 | + if( zHome==0 ){ | |
| 955 | + fossil_fatal("cannot locate home directory - please set the " | |
| 956 | + "FOSSIL_HOME or HOME environment variables"); | |
| 952 | 957 | } |
| 953 | 958 | #endif |
| 954 | 959 | if( file_isdir(zHome)!=1 ){ |
| 955 | 960 | fossil_fatal("invalid home directory: %s", zHome); |
| 956 | 961 | } |
| @@ -1355,10 +1360,22 @@ | ||
| 1355 | 1360 | while( (pStmt = sqlite3_next_stmt(g.db, pStmt))!=0 ){ |
| 1356 | 1361 | fossil_warning("unfinalized SQL statement: [%s]", sqlite3_sql(pStmt)); |
| 1357 | 1362 | } |
| 1358 | 1363 | } |
| 1359 | 1364 | db_close_config(); |
| 1365 | + | |
| 1366 | + /* If the localdb (the check-out database) is open and if it has | |
| 1367 | + ** a lot of unused free space, then VACUUM it as we shut down. | |
| 1368 | + */ | |
| 1369 | + if( g.localOpen && strcmp(db_name("localdb"),"main")==0 ){ | |
| 1370 | + int nFree = db_int(0, "PRAGMA main.freelist_count"); | |
| 1371 | + int nTotal = db_int(0, "PRAGMA main.page_count"); | |
| 1372 | + if( nFree>nTotal/4 ){ | |
| 1373 | + db_multi_exec("VACUUM;"); | |
| 1374 | + } | |
| 1375 | + } | |
| 1376 | + | |
| 1360 | 1377 | if( g.db ){ |
| 1361 | 1378 | sqlite3_wal_checkpoint(g.db, 0); |
| 1362 | 1379 | sqlite3_close(g.db); |
| 1363 | 1380 | g.db = 0; |
| 1364 | 1381 | g.zMainDbType = 0; |
| @@ -1422,13 +1439,13 @@ | ||
| 1422 | 1439 | " WHERE login=%Q", zUser |
| 1423 | 1440 | ); |
| 1424 | 1441 | if( !setupUserOnly ){ |
| 1425 | 1442 | db_multi_exec( |
| 1426 | 1443 | "INSERT OR IGNORE INTO user(login,pw,cap,info)" |
| 1427 | - " VALUES('anonymous',hex(randomblob(8)),'hmncz','Anon');" | |
| 1444 | + " VALUES('anonymous',hex(randomblob(8)),'hmnc','Anon');" | |
| 1428 | 1445 | "INSERT OR IGNORE INTO user(login,pw,cap,info)" |
| 1429 | - " VALUES('nobody','','gjor','Nobody');" | |
| 1446 | + " VALUES('nobody','','gjorz','Nobody');" | |
| 1430 | 1447 | "INSERT OR IGNORE INTO user(login,pw,cap,info)" |
| 1431 | 1448 | " VALUES('developer','','dei','Dev');" |
| 1432 | 1449 | "INSERT OR IGNORE INTO user(login,pw,cap,info)" |
| 1433 | 1450 | " VALUES('reader','','kptw','Reader');" |
| 1434 | 1451 | ); |
| 1435 | 1452 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -805,10 +805,12 @@ | |
| 805 | db_checkin_mtime_function, 0, 0); |
| 806 | sqlite3_create_function(db, "symbolic_name_to_rid", 1, SQLITE_UTF8, 0, |
| 807 | db_sym2rid_function, 0, 0); |
| 808 | sqlite3_create_function(db, "symbolic_name_to_rid", 2, SQLITE_UTF8, 0, |
| 809 | db_sym2rid_function, 0, 0); |
| 810 | } |
| 811 | |
| 812 | |
| 813 | /* |
| 814 | ** Open a database file. Return a pointer to the new database |
| @@ -827,12 +829,10 @@ | |
| 827 | if( rc!=SQLITE_OK ){ |
| 828 | db_err("[%s]: %s", zDbName, sqlite3_errmsg(db)); |
| 829 | } |
| 830 | sqlite3_busy_timeout(db, 5000); |
| 831 | sqlite3_wal_autocheckpoint(db, 1); /* Set to checkpoint frequently */ |
| 832 | sqlite3_create_function(db, "now", 0, SQLITE_UTF8, 0, |
| 833 | db_now_function, 0, 0); |
| 834 | sqlite3_create_function(db, "user", 0, SQLITE_UTF8, 0, db_sql_user, 0, 0); |
| 835 | sqlite3_create_function(db, "cgi", 1, SQLITE_UTF8, 0, db_sql_cgi, 0, 0); |
| 836 | sqlite3_create_function(db, "cgi", 2, SQLITE_UTF8, 0, db_sql_cgi, 0, 0); |
| 837 | sqlite3_create_function(db, "print", -1, SQLITE_UTF8, 0,db_sql_print,0,0); |
| 838 | sqlite3_create_function( |
| @@ -927,30 +927,35 @@ | |
| 927 | char *zHome; |
| 928 | if( g.zConfigDbName ){ |
| 929 | if( useAttach==g.useAttach ) return; |
| 930 | db_close_config(); |
| 931 | } |
| 932 | #if defined(_WIN32) || defined(__CYGWIN__) |
| 933 | zHome = fossil_getenv("LOCALAPPDATA"); |
| 934 | if( zHome==0 ){ |
| 935 | zHome = fossil_getenv("APPDATA"); |
| 936 | if( zHome==0 ){ |
| 937 | char *zDrive = fossil_getenv("HOMEDRIVE"); |
| 938 | zHome = fossil_getenv("HOMEPATH"); |
| 939 | if( zDrive && zHome ) zHome = mprintf("%s%s", zDrive, zHome); |
| 940 | } |
| 941 | } |
| 942 | if( zHome==0 ){ |
| 943 | fossil_fatal("cannot locate home directory - " |
| 944 | "please set the LOCALAPPDATA or APPDATA or HOMEPATH " |
| 945 | "environment variables"); |
| 946 | } |
| 947 | #else |
| 948 | zHome = fossil_getenv("HOME"); |
| 949 | if( zHome==0 ){ |
| 950 | fossil_fatal("cannot locate home directory - " |
| 951 | "please set the HOME environment variable"); |
| 952 | } |
| 953 | #endif |
| 954 | if( file_isdir(zHome)!=1 ){ |
| 955 | fossil_fatal("invalid home directory: %s", zHome); |
| 956 | } |
| @@ -1355,10 +1360,22 @@ | |
| 1355 | while( (pStmt = sqlite3_next_stmt(g.db, pStmt))!=0 ){ |
| 1356 | fossil_warning("unfinalized SQL statement: [%s]", sqlite3_sql(pStmt)); |
| 1357 | } |
| 1358 | } |
| 1359 | db_close_config(); |
| 1360 | if( g.db ){ |
| 1361 | sqlite3_wal_checkpoint(g.db, 0); |
| 1362 | sqlite3_close(g.db); |
| 1363 | g.db = 0; |
| 1364 | g.zMainDbType = 0; |
| @@ -1422,13 +1439,13 @@ | |
| 1422 | " WHERE login=%Q", zUser |
| 1423 | ); |
| 1424 | if( !setupUserOnly ){ |
| 1425 | db_multi_exec( |
| 1426 | "INSERT OR IGNORE INTO user(login,pw,cap,info)" |
| 1427 | " VALUES('anonymous',hex(randomblob(8)),'hmncz','Anon');" |
| 1428 | "INSERT OR IGNORE INTO user(login,pw,cap,info)" |
| 1429 | " VALUES('nobody','','gjor','Nobody');" |
| 1430 | "INSERT OR IGNORE INTO user(login,pw,cap,info)" |
| 1431 | " VALUES('developer','','dei','Dev');" |
| 1432 | "INSERT OR IGNORE INTO user(login,pw,cap,info)" |
| 1433 | " VALUES('reader','','kptw','Reader');" |
| 1434 | ); |
| 1435 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -805,10 +805,12 @@ | |
| 805 | db_checkin_mtime_function, 0, 0); |
| 806 | sqlite3_create_function(db, "symbolic_name_to_rid", 1, SQLITE_UTF8, 0, |
| 807 | db_sym2rid_function, 0, 0); |
| 808 | sqlite3_create_function(db, "symbolic_name_to_rid", 2, SQLITE_UTF8, 0, |
| 809 | db_sym2rid_function, 0, 0); |
| 810 | sqlite3_create_function(db, "now", 0, SQLITE_UTF8, 0, |
| 811 | db_now_function, 0, 0); |
| 812 | } |
| 813 | |
| 814 | |
| 815 | /* |
| 816 | ** Open a database file. Return a pointer to the new database |
| @@ -827,12 +829,10 @@ | |
| 829 | if( rc!=SQLITE_OK ){ |
| 830 | db_err("[%s]: %s", zDbName, sqlite3_errmsg(db)); |
| 831 | } |
| 832 | sqlite3_busy_timeout(db, 5000); |
| 833 | sqlite3_wal_autocheckpoint(db, 1); /* Set to checkpoint frequently */ |
| 834 | sqlite3_create_function(db, "user", 0, SQLITE_UTF8, 0, db_sql_user, 0, 0); |
| 835 | sqlite3_create_function(db, "cgi", 1, SQLITE_UTF8, 0, db_sql_cgi, 0, 0); |
| 836 | sqlite3_create_function(db, "cgi", 2, SQLITE_UTF8, 0, db_sql_cgi, 0, 0); |
| 837 | sqlite3_create_function(db, "print", -1, SQLITE_UTF8, 0,db_sql_print,0,0); |
| 838 | sqlite3_create_function( |
| @@ -927,30 +927,35 @@ | |
| 927 | char *zHome; |
| 928 | if( g.zConfigDbName ){ |
| 929 | if( useAttach==g.useAttach ) return; |
| 930 | db_close_config(); |
| 931 | } |
| 932 | zHome = fossil_getenv("FOSSIL_HOME"); |
| 933 | #if defined(_WIN32) || defined(__CYGWIN__) |
| 934 | if( zHome==0 ){ |
| 935 | zHome = fossil_getenv("LOCALAPPDATA"); |
| 936 | if( zHome==0 ){ |
| 937 | zHome = fossil_getenv("APPDATA"); |
| 938 | if( zHome==0 ){ |
| 939 | char *zDrive = fossil_getenv("HOMEDRIVE"); |
| 940 | char *zPath = fossil_getenv("HOMEPATH"); |
| 941 | if( zDrive && zPath ) zHome = mprintf("%s%s", zDrive, zPath); |
| 942 | } |
| 943 | } |
| 944 | } |
| 945 | if( zHome==0 ){ |
| 946 | fossil_fatal("cannot locate home directory - please set the " |
| 947 | "FOSSIL_HOME, LOCALAPPDATA, APPDATA, or HOMEPATH " |
| 948 | "environment variables"); |
| 949 | } |
| 950 | #else |
| 951 | if( zHome==0 ){ |
| 952 | zHome = fossil_getenv("HOME"); |
| 953 | } |
| 954 | if( zHome==0 ){ |
| 955 | fossil_fatal("cannot locate home directory - please set the " |
| 956 | "FOSSIL_HOME or HOME environment variables"); |
| 957 | } |
| 958 | #endif |
| 959 | if( file_isdir(zHome)!=1 ){ |
| 960 | fossil_fatal("invalid home directory: %s", zHome); |
| 961 | } |
| @@ -1355,10 +1360,22 @@ | |
| 1360 | while( (pStmt = sqlite3_next_stmt(g.db, pStmt))!=0 ){ |
| 1361 | fossil_warning("unfinalized SQL statement: [%s]", sqlite3_sql(pStmt)); |
| 1362 | } |
| 1363 | } |
| 1364 | db_close_config(); |
| 1365 | |
| 1366 | /* If the localdb (the check-out database) is open and if it has |
| 1367 | ** a lot of unused free space, then VACUUM it as we shut down. |
| 1368 | */ |
| 1369 | if( g.localOpen && strcmp(db_name("localdb"),"main")==0 ){ |
| 1370 | int nFree = db_int(0, "PRAGMA main.freelist_count"); |
| 1371 | int nTotal = db_int(0, "PRAGMA main.page_count"); |
| 1372 | if( nFree>nTotal/4 ){ |
| 1373 | db_multi_exec("VACUUM;"); |
| 1374 | } |
| 1375 | } |
| 1376 | |
| 1377 | if( g.db ){ |
| 1378 | sqlite3_wal_checkpoint(g.db, 0); |
| 1379 | sqlite3_close(g.db); |
| 1380 | g.db = 0; |
| 1381 | g.zMainDbType = 0; |
| @@ -1422,13 +1439,13 @@ | |
| 1439 | " WHERE login=%Q", zUser |
| 1440 | ); |
| 1441 | if( !setupUserOnly ){ |
| 1442 | db_multi_exec( |
| 1443 | "INSERT OR IGNORE INTO user(login,pw,cap,info)" |
| 1444 | " VALUES('anonymous',hex(randomblob(8)),'hmnc','Anon');" |
| 1445 | "INSERT OR IGNORE INTO user(login,pw,cap,info)" |
| 1446 | " VALUES('nobody','','gjorz','Nobody');" |
| 1447 | "INSERT OR IGNORE INTO user(login,pw,cap,info)" |
| 1448 | " VALUES('developer','','dei','Dev');" |
| 1449 | "INSERT OR IGNORE INTO user(login,pw,cap,info)" |
| 1450 | " VALUES('reader','','kptw','Reader');" |
| 1451 | ); |
| 1452 |
+9
| --- src/diff.tcl | ||
| +++ src/diff.tcl | ||
| @@ -1,5 +1,14 @@ | ||
| 1 | +# The "diff --tk" command outputs prepends a "set fossilcmd {...}" line | |
| 2 | +# to this file, then runs this file using "tclsh" in order to display the | |
| 3 | +# graphical diff in a separate window. A typical "set fossilcmd" line | |
| 4 | +# looks like this: | |
| 5 | +# | |
| 6 | +# set fossilcmd {| "./fossil" diff --html -y -i -v} | |
| 7 | +# | |
| 8 | +# This header comment is stripped off by the "mkbuiltin.c" program. | |
| 9 | +# | |
| 1 | 10 | set prog { |
| 2 | 11 | package require Tk |
| 3 | 12 | |
| 4 | 13 | array set CFG { |
| 5 | 14 | TITLE {Fossil Diff} |
| 6 | 15 |
| --- src/diff.tcl | |
| +++ src/diff.tcl | |
| @@ -1,5 +1,14 @@ | |
| 1 | set prog { |
| 2 | package require Tk |
| 3 | |
| 4 | array set CFG { |
| 5 | TITLE {Fossil Diff} |
| 6 |
| --- src/diff.tcl | |
| +++ src/diff.tcl | |
| @@ -1,5 +1,14 @@ | |
| 1 | # The "diff --tk" command outputs prepends a "set fossilcmd {...}" line |
| 2 | # to this file, then runs this file using "tclsh" in order to display the |
| 3 | # graphical diff in a separate window. A typical "set fossilcmd" line |
| 4 | # looks like this: |
| 5 | # |
| 6 | # set fossilcmd {| "./fossil" diff --html -y -i -v} |
| 7 | # |
| 8 | # This header comment is stripped off by the "mkbuiltin.c" program. |
| 9 | # |
| 10 | set prog { |
| 11 | package require Tk |
| 12 | |
| 13 | array set CFG { |
| 14 | TITLE {Fossil Diff} |
| 15 |
+77
-93
| --- src/doc.c | ||
| +++ src/doc.c | ||
| @@ -353,147 +353,125 @@ | ||
| 353 | 353 | } |
| 354 | 354 | } |
| 355 | 355 | |
| 356 | 356 | /* |
| 357 | 357 | ** WEBPAGE: doc |
| 358 | -** URL: /doc?name=BASELINE/PATH | |
| 359 | -** URL: /doc/BASELINE/PATH | |
| 360 | -** | |
| 361 | -** BASELINE can be either a baseline uuid prefix or magic words "tip" | |
| 362 | -** to mean the most recently checked in baseline or "ckout" to mean the | |
| 363 | -** content of the local checkout, if any. PATH is the relative pathname | |
| 364 | -** of some file. This method returns the file content. | |
| 365 | -** | |
| 366 | -** If PATH matches the patterns *.wiki or *.txt then formatting content | |
| 367 | -** is added before returning the file. For all other names, the content | |
| 368 | -** is returned straight without any interpretation or processing. | |
| 358 | +** URL: /doc?name=CHECKIN/FILE | |
| 359 | +** URL: /doc/CHECKIN/FILE | |
| 360 | +** | |
| 361 | +** CHECKIN can be either tag or SHA1 hash or timestamp identifying a | |
| 362 | +** particular check, or the name of a branch (meaning the most recent | |
| 363 | +** check-in on that branch) or one of various magic words: | |
| 364 | +** | |
| 365 | +** "tip" means the most recent check-in | |
| 366 | +** | |
| 367 | +** "ckout" means the current check-out, if the server is run from | |
| 368 | +** within a check-out, otherwise it is the same as "tip" | |
| 369 | +** | |
| 370 | +** FILE is the name of a file to delivered up as a webpage. FILE is relative | |
| 371 | +** to the root of the source tree of the repository. The FILE must | |
| 372 | +** be a part of CHECKIN, except when CHECKIN=="ckout" when FILE is read | |
| 373 | +** directly from disk and need not be a managed file. | |
| 374 | +** | |
| 375 | +** The "ckout" CHECKIN is intended for development - to provide a mechanism | |
| 376 | +** for looking at what a file will look like using the /doc webpage after | |
| 377 | +** it gets checked in. | |
| 378 | +** | |
| 379 | +** The file extension is used to decide how to render the file. | |
| 369 | 380 | */ |
| 370 | 381 | void doc_page(void){ |
| 371 | 382 | const char *zName; /* Argument to the /doc page */ |
| 383 | + const char *zOrigName; /* Original document name */ | |
| 372 | 384 | const char *zMime; /* Document MIME type */ |
| 373 | - int vid = 0; /* Artifact of baseline */ | |
| 385 | + char *zCheckin; /* The checkin holding the document */ | |
| 386 | + int vid = 0; /* Artifact of checkin */ | |
| 374 | 387 | int rid = 0; /* Artifact of file */ |
| 375 | 388 | int i; /* Loop counter */ |
| 376 | 389 | Blob filebody; /* Content of the documentation file */ |
| 377 | - char zBaseline[UUID_SIZE+1]; /* Baseline UUID */ | |
| 390 | + int nMiss = 0; /* Failed attempts to find the document */ | |
| 378 | 391 | |
| 379 | 392 | login_check_credentials(); |
| 380 | 393 | if( !g.perm.Read ){ login_needed(); return; } |
| 381 | 394 | zName = PD("name", "tip/index.wiki"); |
| 382 | 395 | for(i=0; zName[i] && zName[i]!='/'; i++){} |
| 383 | - if( zName[i]==0 || i>UUID_SIZE ){ | |
| 384 | - zName = "index.html"; | |
| 385 | - goto doc_not_found; | |
| 386 | - } | |
| 387 | - g.zPath = mprintf("%s/%s", g.zPath, zName); | |
| 388 | - memcpy(zBaseline, zName, i); | |
| 389 | - zBaseline[i] = 0; | |
| 390 | - zName += i; | |
| 396 | + zCheckin = mprintf("%.*s", i, zName); | |
| 397 | + if( zName[i]==0 ){ | |
| 398 | + zName = "index.wiki"; | |
| 399 | + }else{ | |
| 400 | + zName += i; | |
| 401 | + } | |
| 391 | 402 | while( zName[0]=='/' ){ zName++; } |
| 403 | + g.zPath = mprintf("%s/%s/%s", g.zPath, zCheckin, zName); | |
| 404 | + zOrigName = zName; | |
| 392 | 405 | if( !file_is_simple_pathname(zName, 1) ){ |
| 393 | - int n = strlen(zName); | |
| 394 | - if( n>0 && zName[n-1]=='/' ){ | |
| 395 | - zName = mprintf("%sindex.html", zName); | |
| 406 | + if( sqlite3_strglob("*/", zName)==0 ){ | |
| 407 | + zOrigName = zName = mprintf("%sindex.wiki", zName); | |
| 396 | 408 | if( !file_is_simple_pathname(zName, 1) ){ |
| 397 | 409 | goto doc_not_found; |
| 398 | 410 | } |
| 399 | 411 | }else{ |
| 400 | 412 | goto doc_not_found; |
| 401 | 413 | } |
| 402 | 414 | } |
| 403 | - if( fossil_strcmp(zBaseline,"ckout")==0 && db_open_local(0)==0 ){ | |
| 404 | - sqlite3_snprintf(sizeof(zBaseline), zBaseline, "tip"); | |
| 415 | + if( fossil_strcmp(zCheckin,"ckout")==0 && db_open_local(0)==0 ){ | |
| 416 | + sqlite3_snprintf(sizeof(zCheckin), zCheckin, "tip"); | |
| 405 | 417 | } |
| 406 | - if( fossil_strcmp(zBaseline,"ckout")==0 ){ | |
| 418 | + if( fossil_strcmp(zCheckin,"ckout")==0 ){ | |
| 407 | 419 | /* Read from the local checkout */ |
| 408 | 420 | char *zFullpath; |
| 409 | 421 | db_must_be_within_tree(); |
| 410 | - zFullpath = mprintf("%s/%s", g.zLocalRoot, zName); | |
| 411 | - if( !file_isfile(zFullpath) ){ | |
| 412 | - goto doc_not_found; | |
| 413 | - } | |
| 414 | - if( blob_read_from_file(&filebody, zFullpath)<0 ){ | |
| 415 | - goto doc_not_found; | |
| 422 | + while( rid==0 && nMiss<2 ){ | |
| 423 | + zFullpath = mprintf("%s/%s", g.zLocalRoot, zName); | |
| 424 | + if( file_isfile(zFullpath) | |
| 425 | + && blob_read_from_file(&filebody, zFullpath)<0 ){ | |
| 426 | + rid = 1; /* Fake RID just to get the loop to end */ | |
| 427 | + } | |
| 428 | + fossil_free(zFullpath); | |
| 429 | + if( rid ) break; | |
| 430 | + nMiss++; | |
| 431 | + zName = "404.md"; | |
| 416 | 432 | } |
| 417 | 433 | }else{ |
| 418 | 434 | db_begin_transaction(); |
| 419 | - if( fossil_strcmp(zBaseline,"tip")==0 ){ | |
| 420 | - vid = db_int(0, "SELECT objid FROM event WHERE type='ci'" | |
| 421 | - " ORDER BY mtime DESC LIMIT 1"); | |
| 422 | - }else{ | |
| 423 | - vid = name_to_typed_rid(zBaseline, "ci"); | |
| 424 | - } | |
| 425 | - | |
| 426 | - /* Create the baseline cache if it does not already exist */ | |
| 435 | + vid = name_to_typed_rid(zCheckin, "ci"); | |
| 427 | 436 | db_multi_exec( |
| 428 | 437 | "CREATE TABLE IF NOT EXISTS vcache(\n" |
| 429 | - " vid INTEGER, -- baseline ID\n" | |
| 438 | + " vid INTEGER, -- checkin ID\n" | |
| 430 | 439 | " fname TEXT, -- filename\n" |
| 431 | 440 | " rid INTEGER, -- artifact ID\n" |
| 432 | - " UNIQUE(vid,fname,rid)\n" | |
| 433 | - ")" | |
| 441 | + " PRIMARY KEY(vid,fname)\n" | |
| 442 | + ") WITHOUT ROWID" | |
| 434 | 443 | ); |
| 435 | - | |
| 436 | - | |
| 437 | - | |
| 438 | - /* Check to see if the documentation file artifact ID is contained | |
| 439 | - ** in the baseline cache */ | |
| 440 | - rid = db_int(0, "SELECT rid FROM vcache" | |
| 441 | - " WHERE vid=%d AND fname=%Q", vid, zName); | |
| 442 | - if( rid==0 && db_exists("SELECT 1 FROM vcache WHERE vid=%d", vid) ){ | |
| 443 | - goto doc_not_found; | |
| 444 | - } | |
| 445 | - | |
| 446 | - if( rid==0 ){ | |
| 447 | - Stmt s; | |
| 448 | - Manifest *pM; | |
| 449 | - ManifestFile *pFile; | |
| 450 | - | |
| 451 | - /* Add the vid baseline to the cache */ | |
| 452 | - if( db_int(0, "SELECT count(*) FROM vcache")>10000 ){ | |
| 453 | - db_multi_exec("DELETE FROM vcache"); | |
| 454 | - } | |
| 455 | - pM = manifest_get(vid, CFTYPE_MANIFEST, 0); | |
| 456 | - if( pM==0 ){ | |
| 457 | - goto doc_not_found; | |
| 458 | - } | |
| 459 | - db_prepare(&s, | |
| 444 | + if( !db_exists("SELECT 1 FROM vcache WHERE vid=%d", vid) ){ | |
| 445 | + db_multi_exec( | |
| 446 | + "DELETE FROM vcache;\n" | |
| 447 | + "CREATE VIRTUAL TABLE temp.foci USING files_of_checkin;\n" | |
| 460 | 448 | "INSERT INTO vcache(vid,fname,rid)" |
| 461 | - " SELECT %d, :fname, rid FROM blob" | |
| 462 | - " WHERE uuid=:uuid", | |
| 449 | + " SELECT checkinID, filename, blob.rid FROM foci, blob" | |
| 450 | + " WHERE blob.uuid=foci.uuid" | |
| 451 | + " AND foci.checkinID=%d;", | |
| 463 | 452 | vid |
| 464 | 453 | ); |
| 465 | - manifest_file_rewind(pM); | |
| 466 | - while( (pFile = manifest_file_next(pM,0))!=0 ){ | |
| 467 | - db_bind_text(&s, ":fname", pFile->zName); | |
| 468 | - db_bind_text(&s, ":uuid", pFile->zUuid); | |
| 469 | - db_step(&s); | |
| 470 | - db_reset(&s); | |
| 471 | - } | |
| 472 | - db_finalize(&s); | |
| 473 | - manifest_destroy(pM); | |
| 474 | - | |
| 475 | - /* Try again to find the file */ | |
| 454 | + } | |
| 455 | + while( rid==0 && nMiss<2 ){ | |
| 476 | 456 | rid = db_int(0, "SELECT rid FROM vcache" |
| 477 | 457 | " WHERE vid=%d AND fname=%Q", vid, zName); |
| 478 | - } | |
| 479 | - if( rid==0 ){ | |
| 480 | - goto doc_not_found; | |
| 458 | + if( rid ) break; | |
| 459 | + nMiss++; | |
| 460 | + zName = "404.md"; | |
| 481 | 461 | } |
| 482 | - | |
| 483 | - /* Get the file content */ | |
| 484 | - if( content_get(rid, &filebody)==0 ){ | |
| 462 | + if( rid==0 || content_get(rid, &filebody)==0 ){ | |
| 485 | 463 | goto doc_not_found; |
| 486 | 464 | } |
| 487 | 465 | db_end_transaction(0); |
| 488 | 466 | } |
| 489 | 467 | blob_to_utf8_no_bom(&filebody, 0); |
| 490 | 468 | |
| 491 | 469 | /* The file is now contained in the filebody blob. Deliver the |
| 492 | 470 | ** file to the user |
| 493 | 471 | */ |
| 494 | - zMime = P("mimetype"); | |
| 472 | + zMime = nMiss==0 ? P("mimetype") : 0; | |
| 495 | 473 | if( zMime==0 ){ |
| 496 | 474 | zMime = mimetype_from_name(zName); |
| 497 | 475 | } |
| 498 | 476 | Th_Store("doc_name", zName); |
| 499 | 477 | Th_Store("doc_version", db_text(0, "SELECT '[' || substr(uuid,1,10) || ']'" |
| @@ -500,10 +478,11 @@ | ||
| 500 | 478 | " FROM blob WHERE rid=%d", vid)); |
| 501 | 479 | Th_Store("doc_date", db_text(0, "SELECT datetime(mtime) FROM event" |
| 502 | 480 | " WHERE objid=%d AND type='ci'", vid)); |
| 503 | 481 | if( fossil_strcmp(zMime, "text/x-fossil-wiki")==0 ){ |
| 504 | 482 | Blob title, tail; |
| 483 | + style_adunit_config(ADUNIT_RIGHT_OK); | |
| 505 | 484 | if( wiki_find_title(&filebody, &title, &tail) ){ |
| 506 | 485 | style_header("%s", blob_str(&title)); |
| 507 | 486 | wiki_convert(&tail, 0, WIKI_BUTTONS); |
| 508 | 487 | }else{ |
| 509 | 488 | style_header("Documentation"); |
| @@ -515,11 +494,11 @@ | ||
| 515 | 494 | Blob tail = BLOB_INITIALIZER; |
| 516 | 495 | markdown_to_html(&filebody, &title, &tail); |
| 517 | 496 | if( blob_size(&title)>0 ){ |
| 518 | 497 | style_header("%s", blob_str(&title)); |
| 519 | 498 | }else{ |
| 520 | - style_header("Documentation"); | |
| 499 | + style_header("%s", nMiss?"Not Found":"Documentation"); | |
| 521 | 500 | } |
| 522 | 501 | blob_append(cgi_output_blob(), blob_buffer(&tail), blob_size(&tail)); |
| 523 | 502 | style_footer(); |
| 524 | 503 | }else if( fossil_strcmp(zMime, "text/plain")==0 ){ |
| 525 | 504 | style_header("Documentation"); |
| @@ -536,17 +515,22 @@ | ||
| 536 | 515 | #endif |
| 537 | 516 | }else{ |
| 538 | 517 | cgi_set_content_type(zMime); |
| 539 | 518 | cgi_set_content(&filebody); |
| 540 | 519 | } |
| 520 | + if( nMiss ) cgi_set_status(404, "Not Found"); | |
| 541 | 521 | return; |
| 542 | 522 | |
| 543 | -doc_not_found: | |
| 544 | 523 | /* Jump here when unable to locate the document */ |
| 524 | +doc_not_found: | |
| 545 | 525 | db_end_transaction(0); |
| 546 | - style_header("Document Not Found"); | |
| 547 | - @ <p>No such document: %h(zName)</p> | |
| 526 | + cgi_set_status(404, "Not Found"); | |
| 527 | + style_header("Not Found"); | |
| 528 | + @ <p>Document %h(zOrigName) not found | |
| 529 | + if( fossil_strcmp(zCheckin,"ckout")!=0 ){ | |
| 530 | + @ in %z(href("%R/tree?ci=%T",zCheckin))%h(zCheckin)</a> | |
| 531 | + } | |
| 548 | 532 | style_footer(); |
| 549 | 533 | return; |
| 550 | 534 | } |
| 551 | 535 | |
| 552 | 536 | /* |
| 553 | 537 |
| --- src/doc.c | |
| +++ src/doc.c | |
| @@ -353,147 +353,125 @@ | |
| 353 | } |
| 354 | } |
| 355 | |
| 356 | /* |
| 357 | ** WEBPAGE: doc |
| 358 | ** URL: /doc?name=BASELINE/PATH |
| 359 | ** URL: /doc/BASELINE/PATH |
| 360 | ** |
| 361 | ** BASELINE can be either a baseline uuid prefix or magic words "tip" |
| 362 | ** to mean the most recently checked in baseline or "ckout" to mean the |
| 363 | ** content of the local checkout, if any. PATH is the relative pathname |
| 364 | ** of some file. This method returns the file content. |
| 365 | ** |
| 366 | ** If PATH matches the patterns *.wiki or *.txt then formatting content |
| 367 | ** is added before returning the file. For all other names, the content |
| 368 | ** is returned straight without any interpretation or processing. |
| 369 | */ |
| 370 | void doc_page(void){ |
| 371 | const char *zName; /* Argument to the /doc page */ |
| 372 | const char *zMime; /* Document MIME type */ |
| 373 | int vid = 0; /* Artifact of baseline */ |
| 374 | int rid = 0; /* Artifact of file */ |
| 375 | int i; /* Loop counter */ |
| 376 | Blob filebody; /* Content of the documentation file */ |
| 377 | char zBaseline[UUID_SIZE+1]; /* Baseline UUID */ |
| 378 | |
| 379 | login_check_credentials(); |
| 380 | if( !g.perm.Read ){ login_needed(); return; } |
| 381 | zName = PD("name", "tip/index.wiki"); |
| 382 | for(i=0; zName[i] && zName[i]!='/'; i++){} |
| 383 | if( zName[i]==0 || i>UUID_SIZE ){ |
| 384 | zName = "index.html"; |
| 385 | goto doc_not_found; |
| 386 | } |
| 387 | g.zPath = mprintf("%s/%s", g.zPath, zName); |
| 388 | memcpy(zBaseline, zName, i); |
| 389 | zBaseline[i] = 0; |
| 390 | zName += i; |
| 391 | while( zName[0]=='/' ){ zName++; } |
| 392 | if( !file_is_simple_pathname(zName, 1) ){ |
| 393 | int n = strlen(zName); |
| 394 | if( n>0 && zName[n-1]=='/' ){ |
| 395 | zName = mprintf("%sindex.html", zName); |
| 396 | if( !file_is_simple_pathname(zName, 1) ){ |
| 397 | goto doc_not_found; |
| 398 | } |
| 399 | }else{ |
| 400 | goto doc_not_found; |
| 401 | } |
| 402 | } |
| 403 | if( fossil_strcmp(zBaseline,"ckout")==0 && db_open_local(0)==0 ){ |
| 404 | sqlite3_snprintf(sizeof(zBaseline), zBaseline, "tip"); |
| 405 | } |
| 406 | if( fossil_strcmp(zBaseline,"ckout")==0 ){ |
| 407 | /* Read from the local checkout */ |
| 408 | char *zFullpath; |
| 409 | db_must_be_within_tree(); |
| 410 | zFullpath = mprintf("%s/%s", g.zLocalRoot, zName); |
| 411 | if( !file_isfile(zFullpath) ){ |
| 412 | goto doc_not_found; |
| 413 | } |
| 414 | if( blob_read_from_file(&filebody, zFullpath)<0 ){ |
| 415 | goto doc_not_found; |
| 416 | } |
| 417 | }else{ |
| 418 | db_begin_transaction(); |
| 419 | if( fossil_strcmp(zBaseline,"tip")==0 ){ |
| 420 | vid = db_int(0, "SELECT objid FROM event WHERE type='ci'" |
| 421 | " ORDER BY mtime DESC LIMIT 1"); |
| 422 | }else{ |
| 423 | vid = name_to_typed_rid(zBaseline, "ci"); |
| 424 | } |
| 425 | |
| 426 | /* Create the baseline cache if it does not already exist */ |
| 427 | db_multi_exec( |
| 428 | "CREATE TABLE IF NOT EXISTS vcache(\n" |
| 429 | " vid INTEGER, -- baseline ID\n" |
| 430 | " fname TEXT, -- filename\n" |
| 431 | " rid INTEGER, -- artifact ID\n" |
| 432 | " UNIQUE(vid,fname,rid)\n" |
| 433 | ")" |
| 434 | ); |
| 435 | |
| 436 | |
| 437 | |
| 438 | /* Check to see if the documentation file artifact ID is contained |
| 439 | ** in the baseline cache */ |
| 440 | rid = db_int(0, "SELECT rid FROM vcache" |
| 441 | " WHERE vid=%d AND fname=%Q", vid, zName); |
| 442 | if( rid==0 && db_exists("SELECT 1 FROM vcache WHERE vid=%d", vid) ){ |
| 443 | goto doc_not_found; |
| 444 | } |
| 445 | |
| 446 | if( rid==0 ){ |
| 447 | Stmt s; |
| 448 | Manifest *pM; |
| 449 | ManifestFile *pFile; |
| 450 | |
| 451 | /* Add the vid baseline to the cache */ |
| 452 | if( db_int(0, "SELECT count(*) FROM vcache")>10000 ){ |
| 453 | db_multi_exec("DELETE FROM vcache"); |
| 454 | } |
| 455 | pM = manifest_get(vid, CFTYPE_MANIFEST, 0); |
| 456 | if( pM==0 ){ |
| 457 | goto doc_not_found; |
| 458 | } |
| 459 | db_prepare(&s, |
| 460 | "INSERT INTO vcache(vid,fname,rid)" |
| 461 | " SELECT %d, :fname, rid FROM blob" |
| 462 | " WHERE uuid=:uuid", |
| 463 | vid |
| 464 | ); |
| 465 | manifest_file_rewind(pM); |
| 466 | while( (pFile = manifest_file_next(pM,0))!=0 ){ |
| 467 | db_bind_text(&s, ":fname", pFile->zName); |
| 468 | db_bind_text(&s, ":uuid", pFile->zUuid); |
| 469 | db_step(&s); |
| 470 | db_reset(&s); |
| 471 | } |
| 472 | db_finalize(&s); |
| 473 | manifest_destroy(pM); |
| 474 | |
| 475 | /* Try again to find the file */ |
| 476 | rid = db_int(0, "SELECT rid FROM vcache" |
| 477 | " WHERE vid=%d AND fname=%Q", vid, zName); |
| 478 | } |
| 479 | if( rid==0 ){ |
| 480 | goto doc_not_found; |
| 481 | } |
| 482 | |
| 483 | /* Get the file content */ |
| 484 | if( content_get(rid, &filebody)==0 ){ |
| 485 | goto doc_not_found; |
| 486 | } |
| 487 | db_end_transaction(0); |
| 488 | } |
| 489 | blob_to_utf8_no_bom(&filebody, 0); |
| 490 | |
| 491 | /* The file is now contained in the filebody blob. Deliver the |
| 492 | ** file to the user |
| 493 | */ |
| 494 | zMime = P("mimetype"); |
| 495 | if( zMime==0 ){ |
| 496 | zMime = mimetype_from_name(zName); |
| 497 | } |
| 498 | Th_Store("doc_name", zName); |
| 499 | Th_Store("doc_version", db_text(0, "SELECT '[' || substr(uuid,1,10) || ']'" |
| @@ -500,10 +478,11 @@ | |
| 500 | " FROM blob WHERE rid=%d", vid)); |
| 501 | Th_Store("doc_date", db_text(0, "SELECT datetime(mtime) FROM event" |
| 502 | " WHERE objid=%d AND type='ci'", vid)); |
| 503 | if( fossil_strcmp(zMime, "text/x-fossil-wiki")==0 ){ |
| 504 | Blob title, tail; |
| 505 | if( wiki_find_title(&filebody, &title, &tail) ){ |
| 506 | style_header("%s", blob_str(&title)); |
| 507 | wiki_convert(&tail, 0, WIKI_BUTTONS); |
| 508 | }else{ |
| 509 | style_header("Documentation"); |
| @@ -515,11 +494,11 @@ | |
| 515 | Blob tail = BLOB_INITIALIZER; |
| 516 | markdown_to_html(&filebody, &title, &tail); |
| 517 | if( blob_size(&title)>0 ){ |
| 518 | style_header("%s", blob_str(&title)); |
| 519 | }else{ |
| 520 | style_header("Documentation"); |
| 521 | } |
| 522 | blob_append(cgi_output_blob(), blob_buffer(&tail), blob_size(&tail)); |
| 523 | style_footer(); |
| 524 | }else if( fossil_strcmp(zMime, "text/plain")==0 ){ |
| 525 | style_header("Documentation"); |
| @@ -536,17 +515,22 @@ | |
| 536 | #endif |
| 537 | }else{ |
| 538 | cgi_set_content_type(zMime); |
| 539 | cgi_set_content(&filebody); |
| 540 | } |
| 541 | return; |
| 542 | |
| 543 | doc_not_found: |
| 544 | /* Jump here when unable to locate the document */ |
| 545 | db_end_transaction(0); |
| 546 | style_header("Document Not Found"); |
| 547 | @ <p>No such document: %h(zName)</p> |
| 548 | style_footer(); |
| 549 | return; |
| 550 | } |
| 551 | |
| 552 | /* |
| 553 |
| --- src/doc.c | |
| +++ src/doc.c | |
| @@ -353,147 +353,125 @@ | |
| 353 | } |
| 354 | } |
| 355 | |
| 356 | /* |
| 357 | ** WEBPAGE: doc |
| 358 | ** URL: /doc?name=CHECKIN/FILE |
| 359 | ** URL: /doc/CHECKIN/FILE |
| 360 | ** |
| 361 | ** CHECKIN can be either tag or SHA1 hash or timestamp identifying a |
| 362 | ** particular check, or the name of a branch (meaning the most recent |
| 363 | ** check-in on that branch) or one of various magic words: |
| 364 | ** |
| 365 | ** "tip" means the most recent check-in |
| 366 | ** |
| 367 | ** "ckout" means the current check-out, if the server is run from |
| 368 | ** within a check-out, otherwise it is the same as "tip" |
| 369 | ** |
| 370 | ** FILE is the name of a file to delivered up as a webpage. FILE is relative |
| 371 | ** to the root of the source tree of the repository. The FILE must |
| 372 | ** be a part of CHECKIN, except when CHECKIN=="ckout" when FILE is read |
| 373 | ** directly from disk and need not be a managed file. |
| 374 | ** |
| 375 | ** The "ckout" CHECKIN is intended for development - to provide a mechanism |
| 376 | ** for looking at what a file will look like using the /doc webpage after |
| 377 | ** it gets checked in. |
| 378 | ** |
| 379 | ** The file extension is used to decide how to render the file. |
| 380 | */ |
| 381 | void doc_page(void){ |
| 382 | const char *zName; /* Argument to the /doc page */ |
| 383 | const char *zOrigName; /* Original document name */ |
| 384 | const char *zMime; /* Document MIME type */ |
| 385 | char *zCheckin; /* The checkin holding the document */ |
| 386 | int vid = 0; /* Artifact of checkin */ |
| 387 | int rid = 0; /* Artifact of file */ |
| 388 | int i; /* Loop counter */ |
| 389 | Blob filebody; /* Content of the documentation file */ |
| 390 | int nMiss = 0; /* Failed attempts to find the document */ |
| 391 | |
| 392 | login_check_credentials(); |
| 393 | if( !g.perm.Read ){ login_needed(); return; } |
| 394 | zName = PD("name", "tip/index.wiki"); |
| 395 | for(i=0; zName[i] && zName[i]!='/'; i++){} |
| 396 | zCheckin = mprintf("%.*s", i, zName); |
| 397 | if( zName[i]==0 ){ |
| 398 | zName = "index.wiki"; |
| 399 | }else{ |
| 400 | zName += i; |
| 401 | } |
| 402 | while( zName[0]=='/' ){ zName++; } |
| 403 | g.zPath = mprintf("%s/%s/%s", g.zPath, zCheckin, zName); |
| 404 | zOrigName = zName; |
| 405 | if( !file_is_simple_pathname(zName, 1) ){ |
| 406 | if( sqlite3_strglob("*/", zName)==0 ){ |
| 407 | zOrigName = zName = mprintf("%sindex.wiki", zName); |
| 408 | if( !file_is_simple_pathname(zName, 1) ){ |
| 409 | goto doc_not_found; |
| 410 | } |
| 411 | }else{ |
| 412 | goto doc_not_found; |
| 413 | } |
| 414 | } |
| 415 | if( fossil_strcmp(zCheckin,"ckout")==0 && db_open_local(0)==0 ){ |
| 416 | sqlite3_snprintf(sizeof(zCheckin), zCheckin, "tip"); |
| 417 | } |
| 418 | if( fossil_strcmp(zCheckin,"ckout")==0 ){ |
| 419 | /* Read from the local checkout */ |
| 420 | char *zFullpath; |
| 421 | db_must_be_within_tree(); |
| 422 | while( rid==0 && nMiss<2 ){ |
| 423 | zFullpath = mprintf("%s/%s", g.zLocalRoot, zName); |
| 424 | if( file_isfile(zFullpath) |
| 425 | && blob_read_from_file(&filebody, zFullpath)<0 ){ |
| 426 | rid = 1; /* Fake RID just to get the loop to end */ |
| 427 | } |
| 428 | fossil_free(zFullpath); |
| 429 | if( rid ) break; |
| 430 | nMiss++; |
| 431 | zName = "404.md"; |
| 432 | } |
| 433 | }else{ |
| 434 | db_begin_transaction(); |
| 435 | vid = name_to_typed_rid(zCheckin, "ci"); |
| 436 | db_multi_exec( |
| 437 | "CREATE TABLE IF NOT EXISTS vcache(\n" |
| 438 | " vid INTEGER, -- checkin ID\n" |
| 439 | " fname TEXT, -- filename\n" |
| 440 | " rid INTEGER, -- artifact ID\n" |
| 441 | " PRIMARY KEY(vid,fname)\n" |
| 442 | ") WITHOUT ROWID" |
| 443 | ); |
| 444 | if( !db_exists("SELECT 1 FROM vcache WHERE vid=%d", vid) ){ |
| 445 | db_multi_exec( |
| 446 | "DELETE FROM vcache;\n" |
| 447 | "CREATE VIRTUAL TABLE temp.foci USING files_of_checkin;\n" |
| 448 | "INSERT INTO vcache(vid,fname,rid)" |
| 449 | " SELECT checkinID, filename, blob.rid FROM foci, blob" |
| 450 | " WHERE blob.uuid=foci.uuid" |
| 451 | " AND foci.checkinID=%d;", |
| 452 | vid |
| 453 | ); |
| 454 | } |
| 455 | while( rid==0 && nMiss<2 ){ |
| 456 | rid = db_int(0, "SELECT rid FROM vcache" |
| 457 | " WHERE vid=%d AND fname=%Q", vid, zName); |
| 458 | if( rid ) break; |
| 459 | nMiss++; |
| 460 | zName = "404.md"; |
| 461 | } |
| 462 | if( rid==0 || content_get(rid, &filebody)==0 ){ |
| 463 | goto doc_not_found; |
| 464 | } |
| 465 | db_end_transaction(0); |
| 466 | } |
| 467 | blob_to_utf8_no_bom(&filebody, 0); |
| 468 | |
| 469 | /* The file is now contained in the filebody blob. Deliver the |
| 470 | ** file to the user |
| 471 | */ |
| 472 | zMime = nMiss==0 ? P("mimetype") : 0; |
| 473 | if( zMime==0 ){ |
| 474 | zMime = mimetype_from_name(zName); |
| 475 | } |
| 476 | Th_Store("doc_name", zName); |
| 477 | Th_Store("doc_version", db_text(0, "SELECT '[' || substr(uuid,1,10) || ']'" |
| @@ -500,10 +478,11 @@ | |
| 478 | " FROM blob WHERE rid=%d", vid)); |
| 479 | Th_Store("doc_date", db_text(0, "SELECT datetime(mtime) FROM event" |
| 480 | " WHERE objid=%d AND type='ci'", vid)); |
| 481 | if( fossil_strcmp(zMime, "text/x-fossil-wiki")==0 ){ |
| 482 | Blob title, tail; |
| 483 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 484 | if( wiki_find_title(&filebody, &title, &tail) ){ |
| 485 | style_header("%s", blob_str(&title)); |
| 486 | wiki_convert(&tail, 0, WIKI_BUTTONS); |
| 487 | }else{ |
| 488 | style_header("Documentation"); |
| @@ -515,11 +494,11 @@ | |
| 494 | Blob tail = BLOB_INITIALIZER; |
| 495 | markdown_to_html(&filebody, &title, &tail); |
| 496 | if( blob_size(&title)>0 ){ |
| 497 | style_header("%s", blob_str(&title)); |
| 498 | }else{ |
| 499 | style_header("%s", nMiss?"Not Found":"Documentation"); |
| 500 | } |
| 501 | blob_append(cgi_output_blob(), blob_buffer(&tail), blob_size(&tail)); |
| 502 | style_footer(); |
| 503 | }else if( fossil_strcmp(zMime, "text/plain")==0 ){ |
| 504 | style_header("Documentation"); |
| @@ -536,17 +515,22 @@ | |
| 515 | #endif |
| 516 | }else{ |
| 517 | cgi_set_content_type(zMime); |
| 518 | cgi_set_content(&filebody); |
| 519 | } |
| 520 | if( nMiss ) cgi_set_status(404, "Not Found"); |
| 521 | return; |
| 522 | |
| 523 | /* Jump here when unable to locate the document */ |
| 524 | doc_not_found: |
| 525 | db_end_transaction(0); |
| 526 | cgi_set_status(404, "Not Found"); |
| 527 | style_header("Not Found"); |
| 528 | @ <p>Document %h(zOrigName) not found |
| 529 | if( fossil_strcmp(zCheckin,"ckout")!=0 ){ |
| 530 | @ in %z(href("%R/tree?ci=%T",zCheckin))%h(zCheckin)</a> |
| 531 | } |
| 532 | style_footer(); |
| 533 | return; |
| 534 | } |
| 535 | |
| 536 | /* |
| 537 |
+19
| --- src/file.c | ||
| +++ src/file.c | ||
| @@ -1262,10 +1262,29 @@ | ||
| 1262 | 1262 | char *zValue = getenv(zName); |
| 1263 | 1263 | #endif |
| 1264 | 1264 | if( zValue ) zValue = fossil_filename_to_utf8(zValue); |
| 1265 | 1265 | return zValue; |
| 1266 | 1266 | } |
| 1267 | + | |
| 1268 | +/* | |
| 1269 | +** Sets the value of an environment variable as UTF8. | |
| 1270 | +*/ | |
| 1271 | +int fossil_setenv(const char *zName, const char *zValue){ | |
| 1272 | + int rc; | |
| 1273 | + char *zString = mprintf("%s=%s", zName, zValue); | |
| 1274 | +#ifdef _WIN32 | |
| 1275 | + wchar_t *uString = fossil_utf8_to_unicode(zString); | |
| 1276 | + rc = _wputenv(uString); | |
| 1277 | + fossil_unicode_free(uString); | |
| 1278 | + fossil_free(zString); | |
| 1279 | +#else | |
| 1280 | + rc = putenv(zString); | |
| 1281 | + /* NOTE: Cannot free the string on POSIX. */ | |
| 1282 | + /* fossil_free(zString); */ | |
| 1283 | +#endif | |
| 1284 | + return rc; | |
| 1285 | +} | |
| 1267 | 1286 | |
| 1268 | 1287 | /* |
| 1269 | 1288 | ** Like fopen() but always takes a UTF8 argument. |
| 1270 | 1289 | */ |
| 1271 | 1290 | FILE *fossil_fopen(const char *zName, const char *zMode){ |
| 1272 | 1291 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -1262,10 +1262,29 @@ | |
| 1262 | char *zValue = getenv(zName); |
| 1263 | #endif |
| 1264 | if( zValue ) zValue = fossil_filename_to_utf8(zValue); |
| 1265 | return zValue; |
| 1266 | } |
| 1267 | |
| 1268 | /* |
| 1269 | ** Like fopen() but always takes a UTF8 argument. |
| 1270 | */ |
| 1271 | FILE *fossil_fopen(const char *zName, const char *zMode){ |
| 1272 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -1262,10 +1262,29 @@ | |
| 1262 | char *zValue = getenv(zName); |
| 1263 | #endif |
| 1264 | if( zValue ) zValue = fossil_filename_to_utf8(zValue); |
| 1265 | return zValue; |
| 1266 | } |
| 1267 | |
| 1268 | /* |
| 1269 | ** Sets the value of an environment variable as UTF8. |
| 1270 | */ |
| 1271 | int fossil_setenv(const char *zName, const char *zValue){ |
| 1272 | int rc; |
| 1273 | char *zString = mprintf("%s=%s", zName, zValue); |
| 1274 | #ifdef _WIN32 |
| 1275 | wchar_t *uString = fossil_utf8_to_unicode(zString); |
| 1276 | rc = _wputenv(uString); |
| 1277 | fossil_unicode_free(uString); |
| 1278 | fossil_free(zString); |
| 1279 | #else |
| 1280 | rc = putenv(zString); |
| 1281 | /* NOTE: Cannot free the string on POSIX. */ |
| 1282 | /* fossil_free(zString); */ |
| 1283 | #endif |
| 1284 | return rc; |
| 1285 | } |
| 1286 | |
| 1287 | /* |
| 1288 | ** Like fopen() but always takes a UTF8 argument. |
| 1289 | */ |
| 1290 | FILE *fossil_fopen(const char *zName, const char *zMode){ |
| 1291 |
+41
-38
| --- src/http_socket.c | ||
| +++ src/http_socket.c | ||
| @@ -27,10 +27,13 @@ | ||
| 27 | 27 | */ |
| 28 | 28 | |
| 29 | 29 | #include "config.h" |
| 30 | 30 | #include "http_socket.h" |
| 31 | 31 | #if defined(_WIN32) |
| 32 | +# if !defined(_WIN32_WINNT) | |
| 33 | +# define _WIN32_WINNT 0x0501 | |
| 34 | +# endif | |
| 32 | 35 | # include <winsock2.h> |
| 33 | 36 | # include <ws2tcpip.h> |
| 34 | 37 | #else |
| 35 | 38 | # include <netinet/in.h> |
| 36 | 39 | # include <arpa/inet.h> |
| @@ -45,11 +48,10 @@ | ||
| 45 | 48 | ** There can only be a single socket connection open at a time. |
| 46 | 49 | ** State information about that socket is stored in the following |
| 47 | 50 | ** local variables: |
| 48 | 51 | */ |
| 49 | 52 | static int socketIsInit = 0; /* True after global initialization */ |
| 50 | -static int addrIsInit = 0; /* True once addr is initialized */ | |
| 51 | 53 | #if defined(_WIN32) |
| 52 | 54 | static WSADATA socketInfo; /* Windows socket initialize data */ |
| 53 | 55 | #endif |
| 54 | 56 | static int iSocket = -1; /* The socket on which we talk to the server */ |
| 55 | 57 | static char *socketErrMsg = 0; /* Text of most recent socket error */ |
| @@ -106,11 +108,10 @@ | ||
| 106 | 108 | WSACleanup(); |
| 107 | 109 | #endif |
| 108 | 110 | socket_clear_errmsg(); |
| 109 | 111 | socketIsInit = 0; |
| 110 | 112 | } |
| 111 | - addrIsInit = 0; | |
| 112 | 113 | } |
| 113 | 114 | |
| 114 | 115 | /* |
| 115 | 116 | ** Close the currently open socket. If no socket is open, this routine |
| 116 | 117 | ** is a no-op. |
| @@ -134,54 +135,56 @@ | ||
| 134 | 135 | ** pUrlDAta->port TCP/IP port to use. Ex: 80 |
| 135 | 136 | ** |
| 136 | 137 | ** Return the number of errors. |
| 137 | 138 | */ |
| 138 | 139 | int socket_open(UrlData *pUrlData){ |
| 139 | - static struct sockaddr_in addr; /* The server address */ | |
| 140 | + int rc = 0; | |
| 141 | + struct addrinfo *ai = 0; | |
| 142 | + struct addrinfo *p; | |
| 143 | + struct addrinfo hints; | |
| 144 | + char zPort[30]; | |
| 145 | + char zRemote[NI_MAXHOST]; | |
| 140 | 146 | |
| 141 | 147 | socket_global_init(); |
| 142 | - if( !addrIsInit ){ | |
| 143 | - memset(&addr, 0, sizeof(addr)); | |
| 144 | - addr.sin_family = AF_INET; | |
| 145 | - addr.sin_port = htons(pUrlData->port); | |
| 146 | - *(int*)&addr.sin_addr = inet_addr(pUrlData->name); | |
| 147 | - if( -1 == *(int*)&addr.sin_addr ){ | |
| 148 | -#ifndef FOSSIL_STATIC_LINK | |
| 149 | - struct hostent *pHost; | |
| 150 | - pHost = gethostbyname(pUrlData->name); | |
| 151 | - if( pHost!=0 ){ | |
| 152 | - memcpy(&addr.sin_addr,pHost->h_addr_list[0],pHost->h_length); | |
| 153 | - }else | |
| 154 | -#endif | |
| 155 | - { | |
| 156 | - socket_set_errmsg("can't resolve host name: %s", pUrlData->name); | |
| 157 | - return 1; | |
| 158 | - } | |
| 159 | - } | |
| 160 | - addrIsInit = 1; | |
| 161 | - | |
| 162 | - /* Set the Global.zIpAddr variable to the server we are talking to. | |
| 163 | - ** This is used to populate the ipaddr column of the rcvfrom table, | |
| 164 | - ** if any files are received from the server. | |
| 165 | - */ | |
| 166 | - g.zIpAddr = mprintf("%s", inet_ntoa(addr.sin_addr)); | |
| 167 | - } | |
| 168 | - iSocket = socket(AF_INET,SOCK_STREAM,0); | |
| 169 | - if( iSocket<0 ){ | |
| 170 | - socket_set_errmsg("cannot create a socket"); | |
| 171 | - return 1; | |
| 172 | - } | |
| 173 | - if( connect(iSocket,(struct sockaddr*)&addr,sizeof(addr))<0 ){ | |
| 148 | + memset(&hints, 0, sizeof(struct addrinfo)); | |
| 149 | + assert( iSocket<0 ); | |
| 150 | + hints.ai_family = g.fIPv4 ? AF_INET : AF_UNSPEC; | |
| 151 | + hints.ai_socktype = SOCK_STREAM; | |
| 152 | + hints.ai_protocol = IPPROTO_TCP; | |
| 153 | + sqlite3_snprintf(sizeof(zPort),zPort,"%d", pUrlData->port); | |
| 154 | + rc = getaddrinfo(pUrlData->name, zPort, &hints, &ai); | |
| 155 | + if( rc ){ | |
| 156 | + socket_set_errmsg("getaddrinfo() fails: %s", gai_strerror(rc)); | |
| 157 | + goto end_socket_open; | |
| 158 | + } | |
| 159 | + for(p=ai; p; p=p->ai_next){ | |
| 160 | + iSocket = socket(p->ai_family, p->ai_socktype, p->ai_protocol); | |
| 161 | + if( iSocket<0 ) continue; | |
| 162 | + if( connect(iSocket,p->ai_addr,p->ai_addrlen)<0 ){ | |
| 163 | + socket_close(); | |
| 164 | + continue; | |
| 165 | + } | |
| 166 | + rc = getnameinfo(p->ai_addr, p->ai_addrlen, zRemote, sizeof(zRemote), | |
| 167 | + 0, 0, NI_NUMERICHOST); | |
| 168 | + if( rc ){ | |
| 169 | + socket_set_errmsg("getnameinfo() failed: %s", gai_strerror(rc)); | |
| 170 | + goto end_socket_open; | |
| 171 | + } | |
| 172 | + g.zIpAddr = mprintf("%s", zRemote); | |
| 173 | + break; | |
| 174 | + } | |
| 175 | + if( p==0 ){ | |
| 174 | 176 | socket_set_errmsg("cannot connect to host %s:%d", pUrlData->name, |
| 175 | 177 | pUrlData->port); |
| 176 | - socket_close(); | |
| 177 | - return 1; | |
| 178 | 178 | } |
| 179 | 179 | #if !defined(_WIN32) |
| 180 | 180 | signal(SIGPIPE, SIG_IGN); |
| 181 | 181 | #endif |
| 182 | - return 0; | |
| 182 | +end_socket_open: | |
| 183 | + if( rc && iSocket>=0 ) socket_close(); | |
| 184 | + if( ai ) freeaddrinfo(ai); | |
| 185 | + return rc; | |
| 183 | 186 | } |
| 184 | 187 | |
| 185 | 188 | /* |
| 186 | 189 | ** Send content out over the open socket connection. |
| 187 | 190 | */ |
| 188 | 191 |
| --- src/http_socket.c | |
| +++ src/http_socket.c | |
| @@ -27,10 +27,13 @@ | |
| 27 | */ |
| 28 | |
| 29 | #include "config.h" |
| 30 | #include "http_socket.h" |
| 31 | #if defined(_WIN32) |
| 32 | # include <winsock2.h> |
| 33 | # include <ws2tcpip.h> |
| 34 | #else |
| 35 | # include <netinet/in.h> |
| 36 | # include <arpa/inet.h> |
| @@ -45,11 +48,10 @@ | |
| 45 | ** There can only be a single socket connection open at a time. |
| 46 | ** State information about that socket is stored in the following |
| 47 | ** local variables: |
| 48 | */ |
| 49 | static int socketIsInit = 0; /* True after global initialization */ |
| 50 | static int addrIsInit = 0; /* True once addr is initialized */ |
| 51 | #if defined(_WIN32) |
| 52 | static WSADATA socketInfo; /* Windows socket initialize data */ |
| 53 | #endif |
| 54 | static int iSocket = -1; /* The socket on which we talk to the server */ |
| 55 | static char *socketErrMsg = 0; /* Text of most recent socket error */ |
| @@ -106,11 +108,10 @@ | |
| 106 | WSACleanup(); |
| 107 | #endif |
| 108 | socket_clear_errmsg(); |
| 109 | socketIsInit = 0; |
| 110 | } |
| 111 | addrIsInit = 0; |
| 112 | } |
| 113 | |
| 114 | /* |
| 115 | ** Close the currently open socket. If no socket is open, this routine |
| 116 | ** is a no-op. |
| @@ -134,54 +135,56 @@ | |
| 134 | ** pUrlDAta->port TCP/IP port to use. Ex: 80 |
| 135 | ** |
| 136 | ** Return the number of errors. |
| 137 | */ |
| 138 | int socket_open(UrlData *pUrlData){ |
| 139 | static struct sockaddr_in addr; /* The server address */ |
| 140 | |
| 141 | socket_global_init(); |
| 142 | if( !addrIsInit ){ |
| 143 | memset(&addr, 0, sizeof(addr)); |
| 144 | addr.sin_family = AF_INET; |
| 145 | addr.sin_port = htons(pUrlData->port); |
| 146 | *(int*)&addr.sin_addr = inet_addr(pUrlData->name); |
| 147 | if( -1 == *(int*)&addr.sin_addr ){ |
| 148 | #ifndef FOSSIL_STATIC_LINK |
| 149 | struct hostent *pHost; |
| 150 | pHost = gethostbyname(pUrlData->name); |
| 151 | if( pHost!=0 ){ |
| 152 | memcpy(&addr.sin_addr,pHost->h_addr_list[0],pHost->h_length); |
| 153 | }else |
| 154 | #endif |
| 155 | { |
| 156 | socket_set_errmsg("can't resolve host name: %s", pUrlData->name); |
| 157 | return 1; |
| 158 | } |
| 159 | } |
| 160 | addrIsInit = 1; |
| 161 | |
| 162 | /* Set the Global.zIpAddr variable to the server we are talking to. |
| 163 | ** This is used to populate the ipaddr column of the rcvfrom table, |
| 164 | ** if any files are received from the server. |
| 165 | */ |
| 166 | g.zIpAddr = mprintf("%s", inet_ntoa(addr.sin_addr)); |
| 167 | } |
| 168 | iSocket = socket(AF_INET,SOCK_STREAM,0); |
| 169 | if( iSocket<0 ){ |
| 170 | socket_set_errmsg("cannot create a socket"); |
| 171 | return 1; |
| 172 | } |
| 173 | if( connect(iSocket,(struct sockaddr*)&addr,sizeof(addr))<0 ){ |
| 174 | socket_set_errmsg("cannot connect to host %s:%d", pUrlData->name, |
| 175 | pUrlData->port); |
| 176 | socket_close(); |
| 177 | return 1; |
| 178 | } |
| 179 | #if !defined(_WIN32) |
| 180 | signal(SIGPIPE, SIG_IGN); |
| 181 | #endif |
| 182 | return 0; |
| 183 | } |
| 184 | |
| 185 | /* |
| 186 | ** Send content out over the open socket connection. |
| 187 | */ |
| 188 |
| --- src/http_socket.c | |
| +++ src/http_socket.c | |
| @@ -27,10 +27,13 @@ | |
| 27 | */ |
| 28 | |
| 29 | #include "config.h" |
| 30 | #include "http_socket.h" |
| 31 | #if defined(_WIN32) |
| 32 | # if !defined(_WIN32_WINNT) |
| 33 | # define _WIN32_WINNT 0x0501 |
| 34 | # endif |
| 35 | # include <winsock2.h> |
| 36 | # include <ws2tcpip.h> |
| 37 | #else |
| 38 | # include <netinet/in.h> |
| 39 | # include <arpa/inet.h> |
| @@ -45,11 +48,10 @@ | |
| 48 | ** There can only be a single socket connection open at a time. |
| 49 | ** State information about that socket is stored in the following |
| 50 | ** local variables: |
| 51 | */ |
| 52 | static int socketIsInit = 0; /* True after global initialization */ |
| 53 | #if defined(_WIN32) |
| 54 | static WSADATA socketInfo; /* Windows socket initialize data */ |
| 55 | #endif |
| 56 | static int iSocket = -1; /* The socket on which we talk to the server */ |
| 57 | static char *socketErrMsg = 0; /* Text of most recent socket error */ |
| @@ -106,11 +108,10 @@ | |
| 108 | WSACleanup(); |
| 109 | #endif |
| 110 | socket_clear_errmsg(); |
| 111 | socketIsInit = 0; |
| 112 | } |
| 113 | } |
| 114 | |
| 115 | /* |
| 116 | ** Close the currently open socket. If no socket is open, this routine |
| 117 | ** is a no-op. |
| @@ -134,54 +135,56 @@ | |
| 135 | ** pUrlDAta->port TCP/IP port to use. Ex: 80 |
| 136 | ** |
| 137 | ** Return the number of errors. |
| 138 | */ |
| 139 | int socket_open(UrlData *pUrlData){ |
| 140 | int rc = 0; |
| 141 | struct addrinfo *ai = 0; |
| 142 | struct addrinfo *p; |
| 143 | struct addrinfo hints; |
| 144 | char zPort[30]; |
| 145 | char zRemote[NI_MAXHOST]; |
| 146 | |
| 147 | socket_global_init(); |
| 148 | memset(&hints, 0, sizeof(struct addrinfo)); |
| 149 | assert( iSocket<0 ); |
| 150 | hints.ai_family = g.fIPv4 ? AF_INET : AF_UNSPEC; |
| 151 | hints.ai_socktype = SOCK_STREAM; |
| 152 | hints.ai_protocol = IPPROTO_TCP; |
| 153 | sqlite3_snprintf(sizeof(zPort),zPort,"%d", pUrlData->port); |
| 154 | rc = getaddrinfo(pUrlData->name, zPort, &hints, &ai); |
| 155 | if( rc ){ |
| 156 | socket_set_errmsg("getaddrinfo() fails: %s", gai_strerror(rc)); |
| 157 | goto end_socket_open; |
| 158 | } |
| 159 | for(p=ai; p; p=p->ai_next){ |
| 160 | iSocket = socket(p->ai_family, p->ai_socktype, p->ai_protocol); |
| 161 | if( iSocket<0 ) continue; |
| 162 | if( connect(iSocket,p->ai_addr,p->ai_addrlen)<0 ){ |
| 163 | socket_close(); |
| 164 | continue; |
| 165 | } |
| 166 | rc = getnameinfo(p->ai_addr, p->ai_addrlen, zRemote, sizeof(zRemote), |
| 167 | 0, 0, NI_NUMERICHOST); |
| 168 | if( rc ){ |
| 169 | socket_set_errmsg("getnameinfo() failed: %s", gai_strerror(rc)); |
| 170 | goto end_socket_open; |
| 171 | } |
| 172 | g.zIpAddr = mprintf("%s", zRemote); |
| 173 | break; |
| 174 | } |
| 175 | if( p==0 ){ |
| 176 | socket_set_errmsg("cannot connect to host %s:%d", pUrlData->name, |
| 177 | pUrlData->port); |
| 178 | } |
| 179 | #if !defined(_WIN32) |
| 180 | signal(SIGPIPE, SIG_IGN); |
| 181 | #endif |
| 182 | end_socket_open: |
| 183 | if( rc && iSocket>=0 ) socket_close(); |
| 184 | if( ai ) freeaddrinfo(ai); |
| 185 | return rc; |
| 186 | } |
| 187 | |
| 188 | /* |
| 189 | ** Send content out over the open socket connection. |
| 190 | */ |
| 191 |
+1
-3
| --- src/info.c | ||
| +++ src/info.c | ||
| @@ -198,13 +198,10 @@ | ||
| 198 | 198 | int verboseFlag = find_option("verbose","v",0)!=0; |
| 199 | 199 | if( !verboseFlag ){ |
| 200 | 200 | verboseFlag = find_option("detail","l",0)!=0; /* deprecated */ |
| 201 | 201 | } |
| 202 | 202 | |
| 203 | - /* We should be done with options.. */ | |
| 204 | - verify_all_options(); | |
| 205 | - | |
| 206 | 203 | if( g.argc==3 && (fsize = file_size(g.argv[2]))>0 && (fsize&0x1ff)==0 ){ |
| 207 | 204 | db_open_config(0); |
| 208 | 205 | db_open_repository(g.argv[2]); |
| 209 | 206 | db_record_repository_filename(g.argv[2]); |
| 210 | 207 | fossil_print("project-name: %s\n", db_get("project-name", "<unnamed>")); |
| @@ -211,10 +208,11 @@ | ||
| 211 | 208 | fossil_print("project-code: %s\n", db_get("project-code", "<none>")); |
| 212 | 209 | extraRepoInfo(); |
| 213 | 210 | return; |
| 214 | 211 | } |
| 215 | 212 | db_find_and_open_repository(0,0); |
| 213 | + verify_all_options(); | |
| 216 | 214 | if( g.argc==2 ){ |
| 217 | 215 | int vid; |
| 218 | 216 | /* 012345678901234 */ |
| 219 | 217 | db_record_repository_filename(0); |
| 220 | 218 | fossil_print("project-name: %s\n", db_get("project-name", "<unnamed>")); |
| 221 | 219 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -198,13 +198,10 @@ | |
| 198 | int verboseFlag = find_option("verbose","v",0)!=0; |
| 199 | if( !verboseFlag ){ |
| 200 | verboseFlag = find_option("detail","l",0)!=0; /* deprecated */ |
| 201 | } |
| 202 | |
| 203 | /* We should be done with options.. */ |
| 204 | verify_all_options(); |
| 205 | |
| 206 | if( g.argc==3 && (fsize = file_size(g.argv[2]))>0 && (fsize&0x1ff)==0 ){ |
| 207 | db_open_config(0); |
| 208 | db_open_repository(g.argv[2]); |
| 209 | db_record_repository_filename(g.argv[2]); |
| 210 | fossil_print("project-name: %s\n", db_get("project-name", "<unnamed>")); |
| @@ -211,10 +208,11 @@ | |
| 211 | fossil_print("project-code: %s\n", db_get("project-code", "<none>")); |
| 212 | extraRepoInfo(); |
| 213 | return; |
| 214 | } |
| 215 | db_find_and_open_repository(0,0); |
| 216 | if( g.argc==2 ){ |
| 217 | int vid; |
| 218 | /* 012345678901234 */ |
| 219 | db_record_repository_filename(0); |
| 220 | fossil_print("project-name: %s\n", db_get("project-name", "<unnamed>")); |
| 221 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -198,13 +198,10 @@ | |
| 198 | int verboseFlag = find_option("verbose","v",0)!=0; |
| 199 | if( !verboseFlag ){ |
| 200 | verboseFlag = find_option("detail","l",0)!=0; /* deprecated */ |
| 201 | } |
| 202 | |
| 203 | if( g.argc==3 && (fsize = file_size(g.argv[2]))>0 && (fsize&0x1ff)==0 ){ |
| 204 | db_open_config(0); |
| 205 | db_open_repository(g.argv[2]); |
| 206 | db_record_repository_filename(g.argv[2]); |
| 207 | fossil_print("project-name: %s\n", db_get("project-name", "<unnamed>")); |
| @@ -211,10 +208,11 @@ | |
| 208 | fossil_print("project-code: %s\n", db_get("project-code", "<none>")); |
| 209 | extraRepoInfo(); |
| 210 | return; |
| 211 | } |
| 212 | db_find_and_open_repository(0,0); |
| 213 | verify_all_options(); |
| 214 | if( g.argc==2 ){ |
| 215 | int vid; |
| 216 | /* 012345678901234 */ |
| 217 | db_record_repository_filename(0); |
| 218 | fossil_print("project-name: %s\n", db_get("project-name", "<unnamed>")); |
| 219 |
+1
| --- src/login.c | ||
| +++ src/login.c | ||
| @@ -575,10 +575,11 @@ | ||
| 575 | 575 | login_set_user_cookie(zUsername, uid, NULL); |
| 576 | 576 | redirect_to_g(); |
| 577 | 577 | } |
| 578 | 578 | } |
| 579 | 579 | style_header("Login/Logout"); |
| 580 | + style_adunit_config(ADUNIT_OFF); | |
| 580 | 581 | @ %s(zErrMsg) |
| 581 | 582 | if( zGoto && P("anon")==0 ){ |
| 582 | 583 | @ <p>A login is required for <a href="%h(zGoto)">%h(zGoto)</a>.</p> |
| 583 | 584 | } |
| 584 | 585 | form_begin(0, "%R/login"); |
| 585 | 586 |
| --- src/login.c | |
| +++ src/login.c | |
| @@ -575,10 +575,11 @@ | |
| 575 | login_set_user_cookie(zUsername, uid, NULL); |
| 576 | redirect_to_g(); |
| 577 | } |
| 578 | } |
| 579 | style_header("Login/Logout"); |
| 580 | @ %s(zErrMsg) |
| 581 | if( zGoto && P("anon")==0 ){ |
| 582 | @ <p>A login is required for <a href="%h(zGoto)">%h(zGoto)</a>.</p> |
| 583 | } |
| 584 | form_begin(0, "%R/login"); |
| 585 |
| --- src/login.c | |
| +++ src/login.c | |
| @@ -575,10 +575,11 @@ | |
| 575 | login_set_user_cookie(zUsername, uid, NULL); |
| 576 | redirect_to_g(); |
| 577 | } |
| 578 | } |
| 579 | style_header("Login/Logout"); |
| 580 | style_adunit_config(ADUNIT_OFF); |
| 581 | @ %s(zErrMsg) |
| 582 | if( zGoto && P("anon")==0 ){ |
| 583 | @ <p>A login is required for <a href="%h(zGoto)">%h(zGoto)</a>.</p> |
| 584 | } |
| 585 | form_begin(0, "%R/login"); |
| 586 |
+77
-14
| --- src/main.c | ||
| +++ src/main.c | ||
| @@ -149,10 +149,11 @@ | ||
| 149 | 149 | int fSystemTrace; /* Trace calls to fossil_system(), --systemtrace */ |
| 150 | 150 | int fSshTrace; /* Trace the SSH setup traffic */ |
| 151 | 151 | int fSshClient; /* HTTP client flags for SSH client */ |
| 152 | 152 | char *zSshCmd; /* SSH command string */ |
| 153 | 153 | int fNoSync; /* Do not do an autosync ever. --nosync */ |
| 154 | + int fIPv4; /* Use only IPv4, not IPv6. --ipv4 */ | |
| 154 | 155 | char *zPath; /* Name of webpage being served */ |
| 155 | 156 | char *zExtra; /* Extra path information past the webpage name */ |
| 156 | 157 | char *zBaseURL; /* Full text of the URL being served */ |
| 157 | 158 | char *zHttpsURL; /* zBaseURL translated to https: */ |
| 158 | 159 | char *zTop; /* Parent directory of zPath */ |
| @@ -1787,57 +1788,119 @@ | ||
| 1787 | 1788 | g.cgiOutput = 1; |
| 1788 | 1789 | blob_read_from_file(&config, zFile); |
| 1789 | 1790 | while( blob_line(&config, &line) ){ |
| 1790 | 1791 | if( !blob_token(&line, &key) ) continue; |
| 1791 | 1792 | if( blob_buffer(&key)[0]=='#' ) continue; |
| 1792 | - if( blob_eq(&key, "debug:") && blob_token(&line, &value) ){ | |
| 1793 | - g.fDebug = fossil_fopen(blob_str(&value), "ab"); | |
| 1794 | - blob_reset(&value); | |
| 1795 | - continue; | |
| 1796 | - } | |
| 1797 | - if( blob_eq(&key, "errorlog:") && blob_token(&line, &value) ){ | |
| 1798 | - g.zErrlog = mprintf("%s", blob_str(&value)); | |
| 1799 | - continue; | |
| 1800 | - } | |
| 1801 | - if( blob_eq(&key, "HOME:") && blob_token(&line, &value) ){ | |
| 1802 | - cgi_setenv("HOME", blob_str(&value)); | |
| 1803 | - blob_reset(&value); | |
| 1804 | - continue; | |
| 1805 | - } | |
| 1806 | 1793 | if( blob_eq(&key, "repository:") && blob_tail(&line, &value) ){ |
| 1794 | + /* repository: FILENAME | |
| 1795 | + ** | |
| 1796 | + ** The name of the Fossil repository to be served via CGI. Most | |
| 1797 | + ** fossil CGI scripts have a single non-comment line that contains | |
| 1798 | + ** this one entry. | |
| 1799 | + */ | |
| 1807 | 1800 | blob_trim(&value); |
| 1808 | 1801 | db_open_repository(blob_str(&value)); |
| 1809 | 1802 | blob_reset(&value); |
| 1810 | 1803 | continue; |
| 1811 | 1804 | } |
| 1812 | 1805 | if( blob_eq(&key, "directory:") && blob_token(&line, &value) ){ |
| 1806 | + /* directory: DIRECTORY | |
| 1807 | + ** | |
| 1808 | + ** If repository: is omitted, then terms of the PATH_INFO cgi parameter | |
| 1809 | + ** are appended to DIRECTORY looking for a repository (whose name ends | |
| 1810 | + ** in ".fossil") or a file in "files:". | |
| 1811 | + */ | |
| 1813 | 1812 | db_close(1); |
| 1814 | 1813 | g.zRepositoryName = mprintf("%s", blob_str(&value)); |
| 1815 | 1814 | blob_reset(&value); |
| 1816 | 1815 | continue; |
| 1817 | 1816 | } |
| 1818 | 1817 | if( blob_eq(&key, "notfound:") && blob_token(&line, &value) ){ |
| 1818 | + /* notfound: URL | |
| 1819 | + ** | |
| 1820 | + ** If using directory: and no suitable repository or file is found, | |
| 1821 | + ** then redirect to URL. | |
| 1822 | + */ | |
| 1819 | 1823 | zNotFound = mprintf("%s", blob_str(&value)); |
| 1820 | 1824 | blob_reset(&value); |
| 1821 | 1825 | continue; |
| 1822 | 1826 | } |
| 1823 | 1827 | if( blob_eq(&key, "localauth") ){ |
| 1828 | + /* localauth | |
| 1829 | + ** | |
| 1830 | + ** Grant "administrator" privileges to users connecting with HTTP | |
| 1831 | + ** from IP address 127.0.0.1. Do not bother checking credentials. | |
| 1832 | + */ | |
| 1824 | 1833 | g.useLocalauth = 1; |
| 1825 | 1834 | continue; |
| 1826 | 1835 | } |
| 1827 | 1836 | if( blob_eq(&key, "redirect:") && blob_token(&line, &value) |
| 1828 | 1837 | && blob_token(&line, &value2) ){ |
| 1838 | + /* See the header comment on the redirect_web_page() function | |
| 1839 | + ** above for details. */ | |
| 1829 | 1840 | nRedirect++; |
| 1830 | 1841 | azRedirect = fossil_realloc(azRedirect, 2*nRedirect*sizeof(char*)); |
| 1831 | 1842 | azRedirect[nRedirect*2-2] = mprintf("%s", blob_str(&value)); |
| 1832 | 1843 | azRedirect[nRedirect*2-1] = mprintf("%s", blob_str(&value2)); |
| 1833 | 1844 | blob_reset(&value); |
| 1834 | 1845 | blob_reset(&value2); |
| 1835 | 1846 | continue; |
| 1836 | 1847 | } |
| 1837 | 1848 | if( blob_eq(&key, "files:") && blob_token(&line, &value) ){ |
| 1849 | + /* files: GLOBLIST | |
| 1850 | + ** | |
| 1851 | + ** GLOBLIST is a comma-separated list of filename globs. For | |
| 1852 | + ** example: *.html,*.css,*.js | |
| 1853 | + ** | |
| 1854 | + ** If the repository: line is omitted and then PATH_INFO is searched | |
| 1855 | + ** for files that match any of these GLOBs and if any such file is | |
| 1856 | + ** found it is returned verbatim. This feature allows "fossil server" | |
| 1857 | + ** to function as a primitive web-server delivering arbitrary content. | |
| 1858 | + */ | |
| 1838 | 1859 | pFileGlob = glob_create(blob_str(&value)); |
| 1860 | + blob_reset(&value); | |
| 1861 | + continue; | |
| 1862 | + } | |
| 1863 | + if( blob_eq(&key, "setenv:") && blob_token(&line, &value) | |
| 1864 | + && blob_token(&line, &value2) ){ | |
| 1865 | + /* setenv: NAME VALUE | |
| 1866 | + ** | |
| 1867 | + ** Sets environment variable NAME to VALUE | |
| 1868 | + */ | |
| 1869 | + fossil_setenv(blob_str(&value), blob_str(&value2)); | |
| 1870 | + blob_reset(&value); | |
| 1871 | + blob_reset(&value2); | |
| 1872 | + continue; | |
| 1873 | + } | |
| 1874 | + if( blob_eq(&key, "debug:") && blob_token(&line, &value) ){ | |
| 1875 | + /* debug: FILENAME | |
| 1876 | + ** | |
| 1877 | + ** Causes output from cgi_debug() and CGIDEBUG(()) calls to go | |
| 1878 | + ** into FILENAME. | |
| 1879 | + */ | |
| 1880 | + g.fDebug = fossil_fopen(blob_str(&value), "ab"); | |
| 1881 | + blob_reset(&value); | |
| 1882 | + continue; | |
| 1883 | + } | |
| 1884 | + if( blob_eq(&key, "errorlog:") && blob_token(&line, &value) ){ | |
| 1885 | + /* errorlog: FILENAME | |
| 1886 | + ** | |
| 1887 | + ** Causes messages from warnings, errors, and panics to be appended | |
| 1888 | + ** to FILENAME. | |
| 1889 | + */ | |
| 1890 | + g.zErrlog = mprintf("%s", blob_str(&value)); | |
| 1891 | + blob_reset(&value); | |
| 1892 | + continue; | |
| 1893 | + } | |
| 1894 | + if( blob_eq(&key, "HOME:") && blob_token(&line, &value) ){ | |
| 1895 | + /* HOME: VALUE | |
| 1896 | + ** | |
| 1897 | + ** Set CGI parameter "HOME" to VALUE. This is legacy. Use | |
| 1898 | + ** setenv: instead. | |
| 1899 | + */ | |
| 1900 | + cgi_setenv("HOME", blob_str(&value)); | |
| 1901 | + blob_reset(&value); | |
| 1839 | 1902 | continue; |
| 1840 | 1903 | } |
| 1841 | 1904 | } |
| 1842 | 1905 | blob_reset(&config); |
| 1843 | 1906 | if( g.db==0 && g.zRepositoryName==0 && nRedirect==0 ){ |
| 1844 | 1907 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -149,10 +149,11 @@ | |
| 149 | int fSystemTrace; /* Trace calls to fossil_system(), --systemtrace */ |
| 150 | int fSshTrace; /* Trace the SSH setup traffic */ |
| 151 | int fSshClient; /* HTTP client flags for SSH client */ |
| 152 | char *zSshCmd; /* SSH command string */ |
| 153 | int fNoSync; /* Do not do an autosync ever. --nosync */ |
| 154 | char *zPath; /* Name of webpage being served */ |
| 155 | char *zExtra; /* Extra path information past the webpage name */ |
| 156 | char *zBaseURL; /* Full text of the URL being served */ |
| 157 | char *zHttpsURL; /* zBaseURL translated to https: */ |
| 158 | char *zTop; /* Parent directory of zPath */ |
| @@ -1787,57 +1788,119 @@ | |
| 1787 | g.cgiOutput = 1; |
| 1788 | blob_read_from_file(&config, zFile); |
| 1789 | while( blob_line(&config, &line) ){ |
| 1790 | if( !blob_token(&line, &key) ) continue; |
| 1791 | if( blob_buffer(&key)[0]=='#' ) continue; |
| 1792 | if( blob_eq(&key, "debug:") && blob_token(&line, &value) ){ |
| 1793 | g.fDebug = fossil_fopen(blob_str(&value), "ab"); |
| 1794 | blob_reset(&value); |
| 1795 | continue; |
| 1796 | } |
| 1797 | if( blob_eq(&key, "errorlog:") && blob_token(&line, &value) ){ |
| 1798 | g.zErrlog = mprintf("%s", blob_str(&value)); |
| 1799 | continue; |
| 1800 | } |
| 1801 | if( blob_eq(&key, "HOME:") && blob_token(&line, &value) ){ |
| 1802 | cgi_setenv("HOME", blob_str(&value)); |
| 1803 | blob_reset(&value); |
| 1804 | continue; |
| 1805 | } |
| 1806 | if( blob_eq(&key, "repository:") && blob_tail(&line, &value) ){ |
| 1807 | blob_trim(&value); |
| 1808 | db_open_repository(blob_str(&value)); |
| 1809 | blob_reset(&value); |
| 1810 | continue; |
| 1811 | } |
| 1812 | if( blob_eq(&key, "directory:") && blob_token(&line, &value) ){ |
| 1813 | db_close(1); |
| 1814 | g.zRepositoryName = mprintf("%s", blob_str(&value)); |
| 1815 | blob_reset(&value); |
| 1816 | continue; |
| 1817 | } |
| 1818 | if( blob_eq(&key, "notfound:") && blob_token(&line, &value) ){ |
| 1819 | zNotFound = mprintf("%s", blob_str(&value)); |
| 1820 | blob_reset(&value); |
| 1821 | continue; |
| 1822 | } |
| 1823 | if( blob_eq(&key, "localauth") ){ |
| 1824 | g.useLocalauth = 1; |
| 1825 | continue; |
| 1826 | } |
| 1827 | if( blob_eq(&key, "redirect:") && blob_token(&line, &value) |
| 1828 | && blob_token(&line, &value2) ){ |
| 1829 | nRedirect++; |
| 1830 | azRedirect = fossil_realloc(azRedirect, 2*nRedirect*sizeof(char*)); |
| 1831 | azRedirect[nRedirect*2-2] = mprintf("%s", blob_str(&value)); |
| 1832 | azRedirect[nRedirect*2-1] = mprintf("%s", blob_str(&value2)); |
| 1833 | blob_reset(&value); |
| 1834 | blob_reset(&value2); |
| 1835 | continue; |
| 1836 | } |
| 1837 | if( blob_eq(&key, "files:") && blob_token(&line, &value) ){ |
| 1838 | pFileGlob = glob_create(blob_str(&value)); |
| 1839 | continue; |
| 1840 | } |
| 1841 | } |
| 1842 | blob_reset(&config); |
| 1843 | if( g.db==0 && g.zRepositoryName==0 && nRedirect==0 ){ |
| 1844 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -149,10 +149,11 @@ | |
| 149 | int fSystemTrace; /* Trace calls to fossil_system(), --systemtrace */ |
| 150 | int fSshTrace; /* Trace the SSH setup traffic */ |
| 151 | int fSshClient; /* HTTP client flags for SSH client */ |
| 152 | char *zSshCmd; /* SSH command string */ |
| 153 | int fNoSync; /* Do not do an autosync ever. --nosync */ |
| 154 | int fIPv4; /* Use only IPv4, not IPv6. --ipv4 */ |
| 155 | char *zPath; /* Name of webpage being served */ |
| 156 | char *zExtra; /* Extra path information past the webpage name */ |
| 157 | char *zBaseURL; /* Full text of the URL being served */ |
| 158 | char *zHttpsURL; /* zBaseURL translated to https: */ |
| 159 | char *zTop; /* Parent directory of zPath */ |
| @@ -1787,57 +1788,119 @@ | |
| 1788 | g.cgiOutput = 1; |
| 1789 | blob_read_from_file(&config, zFile); |
| 1790 | while( blob_line(&config, &line) ){ |
| 1791 | if( !blob_token(&line, &key) ) continue; |
| 1792 | if( blob_buffer(&key)[0]=='#' ) continue; |
| 1793 | if( blob_eq(&key, "repository:") && blob_tail(&line, &value) ){ |
| 1794 | /* repository: FILENAME |
| 1795 | ** |
| 1796 | ** The name of the Fossil repository to be served via CGI. Most |
| 1797 | ** fossil CGI scripts have a single non-comment line that contains |
| 1798 | ** this one entry. |
| 1799 | */ |
| 1800 | blob_trim(&value); |
| 1801 | db_open_repository(blob_str(&value)); |
| 1802 | blob_reset(&value); |
| 1803 | continue; |
| 1804 | } |
| 1805 | if( blob_eq(&key, "directory:") && blob_token(&line, &value) ){ |
| 1806 | /* directory: DIRECTORY |
| 1807 | ** |
| 1808 | ** If repository: is omitted, then terms of the PATH_INFO cgi parameter |
| 1809 | ** are appended to DIRECTORY looking for a repository (whose name ends |
| 1810 | ** in ".fossil") or a file in "files:". |
| 1811 | */ |
| 1812 | db_close(1); |
| 1813 | g.zRepositoryName = mprintf("%s", blob_str(&value)); |
| 1814 | blob_reset(&value); |
| 1815 | continue; |
| 1816 | } |
| 1817 | if( blob_eq(&key, "notfound:") && blob_token(&line, &value) ){ |
| 1818 | /* notfound: URL |
| 1819 | ** |
| 1820 | ** If using directory: and no suitable repository or file is found, |
| 1821 | ** then redirect to URL. |
| 1822 | */ |
| 1823 | zNotFound = mprintf("%s", blob_str(&value)); |
| 1824 | blob_reset(&value); |
| 1825 | continue; |
| 1826 | } |
| 1827 | if( blob_eq(&key, "localauth") ){ |
| 1828 | /* localauth |
| 1829 | ** |
| 1830 | ** Grant "administrator" privileges to users connecting with HTTP |
| 1831 | ** from IP address 127.0.0.1. Do not bother checking credentials. |
| 1832 | */ |
| 1833 | g.useLocalauth = 1; |
| 1834 | continue; |
| 1835 | } |
| 1836 | if( blob_eq(&key, "redirect:") && blob_token(&line, &value) |
| 1837 | && blob_token(&line, &value2) ){ |
| 1838 | /* See the header comment on the redirect_web_page() function |
| 1839 | ** above for details. */ |
| 1840 | nRedirect++; |
| 1841 | azRedirect = fossil_realloc(azRedirect, 2*nRedirect*sizeof(char*)); |
| 1842 | azRedirect[nRedirect*2-2] = mprintf("%s", blob_str(&value)); |
| 1843 | azRedirect[nRedirect*2-1] = mprintf("%s", blob_str(&value2)); |
| 1844 | blob_reset(&value); |
| 1845 | blob_reset(&value2); |
| 1846 | continue; |
| 1847 | } |
| 1848 | if( blob_eq(&key, "files:") && blob_token(&line, &value) ){ |
| 1849 | /* files: GLOBLIST |
| 1850 | ** |
| 1851 | ** GLOBLIST is a comma-separated list of filename globs. For |
| 1852 | ** example: *.html,*.css,*.js |
| 1853 | ** |
| 1854 | ** If the repository: line is omitted and then PATH_INFO is searched |
| 1855 | ** for files that match any of these GLOBs and if any such file is |
| 1856 | ** found it is returned verbatim. This feature allows "fossil server" |
| 1857 | ** to function as a primitive web-server delivering arbitrary content. |
| 1858 | */ |
| 1859 | pFileGlob = glob_create(blob_str(&value)); |
| 1860 | blob_reset(&value); |
| 1861 | continue; |
| 1862 | } |
| 1863 | if( blob_eq(&key, "setenv:") && blob_token(&line, &value) |
| 1864 | && blob_token(&line, &value2) ){ |
| 1865 | /* setenv: NAME VALUE |
| 1866 | ** |
| 1867 | ** Sets environment variable NAME to VALUE |
| 1868 | */ |
| 1869 | fossil_setenv(blob_str(&value), blob_str(&value2)); |
| 1870 | blob_reset(&value); |
| 1871 | blob_reset(&value2); |
| 1872 | continue; |
| 1873 | } |
| 1874 | if( blob_eq(&key, "debug:") && blob_token(&line, &value) ){ |
| 1875 | /* debug: FILENAME |
| 1876 | ** |
| 1877 | ** Causes output from cgi_debug() and CGIDEBUG(()) calls to go |
| 1878 | ** into FILENAME. |
| 1879 | */ |
| 1880 | g.fDebug = fossil_fopen(blob_str(&value), "ab"); |
| 1881 | blob_reset(&value); |
| 1882 | continue; |
| 1883 | } |
| 1884 | if( blob_eq(&key, "errorlog:") && blob_token(&line, &value) ){ |
| 1885 | /* errorlog: FILENAME |
| 1886 | ** |
| 1887 | ** Causes messages from warnings, errors, and panics to be appended |
| 1888 | ** to FILENAME. |
| 1889 | */ |
| 1890 | g.zErrlog = mprintf("%s", blob_str(&value)); |
| 1891 | blob_reset(&value); |
| 1892 | continue; |
| 1893 | } |
| 1894 | if( blob_eq(&key, "HOME:") && blob_token(&line, &value) ){ |
| 1895 | /* HOME: VALUE |
| 1896 | ** |
| 1897 | ** Set CGI parameter "HOME" to VALUE. This is legacy. Use |
| 1898 | ** setenv: instead. |
| 1899 | */ |
| 1900 | cgi_setenv("HOME", blob_str(&value)); |
| 1901 | blob_reset(&value); |
| 1902 | continue; |
| 1903 | } |
| 1904 | } |
| 1905 | blob_reset(&config); |
| 1906 | if( g.db==0 && g.zRepositoryName==0 && nRedirect==0 ){ |
| 1907 |
+24
| --- src/main.mk | ||
| +++ src/main.mk | ||
| @@ -131,10 +131,34 @@ | ||
| 131 | 131 | $(SRCDIR)/xfer.c \ |
| 132 | 132 | $(SRCDIR)/xfersetup.c \ |
| 133 | 133 | $(SRCDIR)/zip.c |
| 134 | 134 | |
| 135 | 135 | EXTRA_FILES = \ |
| 136 | + $(SRCDIR)/../skins/black_and_white/css.txt \ | |
| 137 | + $(SRCDIR)/../skins/black_and_white/footer.txt \ | |
| 138 | + $(SRCDIR)/../skins/black_and_white/header.txt \ | |
| 139 | + $(SRCDIR)/../skins/default/css.txt \ | |
| 140 | + $(SRCDIR)/../skins/default/footer.txt \ | |
| 141 | + $(SRCDIR)/../skins/default/header.txt \ | |
| 142 | + $(SRCDIR)/../skins/eagle/css.txt \ | |
| 143 | + $(SRCDIR)/../skins/eagle/footer.txt \ | |
| 144 | + $(SRCDIR)/../skins/eagle/header.txt \ | |
| 145 | + $(SRCDIR)/../skins/enhanced1/css.txt \ | |
| 146 | + $(SRCDIR)/../skins/enhanced1/footer.txt \ | |
| 147 | + $(SRCDIR)/../skins/enhanced1/header.txt \ | |
| 148 | + $(SRCDIR)/../skins/etienne1/css.txt \ | |
| 149 | + $(SRCDIR)/../skins/etienne1/footer.txt \ | |
| 150 | + $(SRCDIR)/../skins/etienne1/header.txt \ | |
| 151 | + $(SRCDIR)/../skins/khaki/css.txt \ | |
| 152 | + $(SRCDIR)/../skins/khaki/footer.txt \ | |
| 153 | + $(SRCDIR)/../skins/khaki/header.txt \ | |
| 154 | + $(SRCDIR)/../skins/plain_gray/css.txt \ | |
| 155 | + $(SRCDIR)/../skins/plain_gray/footer.txt \ | |
| 156 | + $(SRCDIR)/../skins/plain_gray/header.txt \ | |
| 157 | + $(SRCDIR)/../skins/rounded1/css.txt \ | |
| 158 | + $(SRCDIR)/../skins/rounded1/footer.txt \ | |
| 159 | + $(SRCDIR)/../skins/rounded1/header.txt \ | |
| 136 | 160 | $(SRCDIR)/diff.tcl |
| 137 | 161 | |
| 138 | 162 | TRANS_SRC = \ |
| 139 | 163 | $(OBJDIR)/add_.c \ |
| 140 | 164 | $(OBJDIR)/allrepo_.c \ |
| 141 | 165 |
| --- src/main.mk | |
| +++ src/main.mk | |
| @@ -131,10 +131,34 @@ | |
| 131 | $(SRCDIR)/xfer.c \ |
| 132 | $(SRCDIR)/xfersetup.c \ |
| 133 | $(SRCDIR)/zip.c |
| 134 | |
| 135 | EXTRA_FILES = \ |
| 136 | $(SRCDIR)/diff.tcl |
| 137 | |
| 138 | TRANS_SRC = \ |
| 139 | $(OBJDIR)/add_.c \ |
| 140 | $(OBJDIR)/allrepo_.c \ |
| 141 |
| --- src/main.mk | |
| +++ src/main.mk | |
| @@ -131,10 +131,34 @@ | |
| 131 | $(SRCDIR)/xfer.c \ |
| 132 | $(SRCDIR)/xfersetup.c \ |
| 133 | $(SRCDIR)/zip.c |
| 134 | |
| 135 | EXTRA_FILES = \ |
| 136 | $(SRCDIR)/../skins/black_and_white/css.txt \ |
| 137 | $(SRCDIR)/../skins/black_and_white/footer.txt \ |
| 138 | $(SRCDIR)/../skins/black_and_white/header.txt \ |
| 139 | $(SRCDIR)/../skins/default/css.txt \ |
| 140 | $(SRCDIR)/../skins/default/footer.txt \ |
| 141 | $(SRCDIR)/../skins/default/header.txt \ |
| 142 | $(SRCDIR)/../skins/eagle/css.txt \ |
| 143 | $(SRCDIR)/../skins/eagle/footer.txt \ |
| 144 | $(SRCDIR)/../skins/eagle/header.txt \ |
| 145 | $(SRCDIR)/../skins/enhanced1/css.txt \ |
| 146 | $(SRCDIR)/../skins/enhanced1/footer.txt \ |
| 147 | $(SRCDIR)/../skins/enhanced1/header.txt \ |
| 148 | $(SRCDIR)/../skins/etienne1/css.txt \ |
| 149 | $(SRCDIR)/../skins/etienne1/footer.txt \ |
| 150 | $(SRCDIR)/../skins/etienne1/header.txt \ |
| 151 | $(SRCDIR)/../skins/khaki/css.txt \ |
| 152 | $(SRCDIR)/../skins/khaki/footer.txt \ |
| 153 | $(SRCDIR)/../skins/khaki/header.txt \ |
| 154 | $(SRCDIR)/../skins/plain_gray/css.txt \ |
| 155 | $(SRCDIR)/../skins/plain_gray/footer.txt \ |
| 156 | $(SRCDIR)/../skins/plain_gray/header.txt \ |
| 157 | $(SRCDIR)/../skins/rounded1/css.txt \ |
| 158 | $(SRCDIR)/../skins/rounded1/footer.txt \ |
| 159 | $(SRCDIR)/../skins/rounded1/header.txt \ |
| 160 | $(SRCDIR)/diff.tcl |
| 161 | |
| 162 | TRANS_SRC = \ |
| 163 | $(OBJDIR)/add_.c \ |
| 164 | $(OBJDIR)/allrepo_.c \ |
| 165 |
+59
-59
| --- src/makeheaders.c | ||
| +++ src/makeheaders.c | ||
| @@ -112,19 +112,19 @@ | ||
| 112 | 112 | ** |
| 113 | 113 | ** struct Xyzzy; |
| 114 | 114 | ** |
| 115 | 115 | ** Not every object has a forward declaration. If it does, thought, the |
| 116 | 116 | ** forward declaration will be contained in the zFwd field for C and |
| 117 | -** the zFwdCpp for C++. The zDecl field contains the complete | |
| 118 | -** declaration text. | |
| 117 | +** the zFwdCpp for C++. The zDecl field contains the complete | |
| 118 | +** declaration text. | |
| 119 | 119 | */ |
| 120 | 120 | typedef struct Decl Decl; |
| 121 | 121 | struct Decl { |
| 122 | 122 | char *zName; /* Name of the object being declared. The appearance |
| 123 | 123 | ** of this name is a source file triggers the declaration |
| 124 | 124 | ** to be added to the header for that file. */ |
| 125 | - char *zFile; /* File from which extracted. */ | |
| 125 | + const char *zFile; /* File from which extracted. */ | |
| 126 | 126 | char *zIf; /* Surround the declaration with this #if */ |
| 127 | 127 | char *zFwd; /* A forward declaration. NULL if there is none. */ |
| 128 | 128 | char *zFwdCpp; /* Use this forward declaration for C++. */ |
| 129 | 129 | char *zDecl; /* A full declaration of this object */ |
| 130 | 130 | char *zExtra; /* Extra declaration text inserted into class objects */ |
| @@ -163,11 +163,11 @@ | ||
| 163 | 163 | ** in the output when using the -H option.) |
| 164 | 164 | ** |
| 165 | 165 | ** EXPORT scope The object is visible and usable everywhere. |
| 166 | 166 | ** |
| 167 | 167 | ** The DP_Flag is a temporary use flag that is used during processing to |
| 168 | -** prevent an infinite loop. It's use is localized. | |
| 168 | +** prevent an infinite loop. It's use is localized. | |
| 169 | 169 | ** |
| 170 | 170 | ** The DP_Cplusplus, DP_ExternCReqd and DP_ExternReqd flags are permanent |
| 171 | 171 | ** and are used to specify what type of declaration the object requires. |
| 172 | 172 | */ |
| 173 | 173 | #define DP_Forward 0x001 /* Has a forward declaration in this file */ |
| @@ -201,11 +201,11 @@ | ||
| 201 | 201 | ** Be careful not to confuse PS_Export with DP_Export or |
| 202 | 202 | ** PS_Local with DP_Local. Their names are similar, but the meanings |
| 203 | 203 | ** of these flags are very different. |
| 204 | 204 | */ |
| 205 | 205 | #define PS_Extern 0x000800 /* "extern" has been seen */ |
| 206 | -#define PS_Export 0x001000 /* If between "#if EXPORT_INTERFACE" | |
| 206 | +#define PS_Export 0x001000 /* If between "#if EXPORT_INTERFACE" | |
| 207 | 207 | ** and "#endif" */ |
| 208 | 208 | #define PS_Export2 0x002000 /* If "EXPORT" seen */ |
| 209 | 209 | #define PS_Typedef 0x004000 /* If "typedef" has been seen */ |
| 210 | 210 | #define PS_Static 0x008000 /* If "static" has been seen */ |
| 211 | 211 | #define PS_Interface 0x010000 /* If within #if INTERFACE..#endif */ |
| @@ -231,11 +231,11 @@ | ||
| 231 | 231 | #define TY_Union 0x04000000 |
| 232 | 232 | #define TY_Enumeration 0x08000000 |
| 233 | 233 | #define TY_Defunct 0x10000000 /* Used to erase a declaration */ |
| 234 | 234 | |
| 235 | 235 | /* |
| 236 | -** Each nested #if (or #ifdef or #ifndef) is stored in a stack of | |
| 236 | +** Each nested #if (or #ifdef or #ifndef) is stored in a stack of | |
| 237 | 237 | ** instances of the following structure. |
| 238 | 238 | */ |
| 239 | 239 | typedef struct Ifmacro Ifmacro; |
| 240 | 240 | struct Ifmacro { |
| 241 | 241 | int nLine; /* Line number where this macro occurs */ |
| @@ -293,11 +293,11 @@ | ||
| 293 | 293 | int flags; /* One or more DP_, PS_ and/or TY_ flags */ |
| 294 | 294 | InFile *pNext; /* Next input file in the list of them all */ |
| 295 | 295 | IdentTable idTable; /* All identifiers in this input file */ |
| 296 | 296 | }; |
| 297 | 297 | |
| 298 | -/* | |
| 298 | +/* | |
| 299 | 299 | ** An unbounded string is able to grow without limit. We use these |
| 300 | 300 | ** to construct large in-memory strings from lots of smaller components. |
| 301 | 301 | */ |
| 302 | 302 | typedef struct String String; |
| 303 | 303 | struct String { |
| @@ -332,19 +332,19 @@ | ||
| 332 | 332 | ** never to read a file that it generated itself. |
| 333 | 333 | ** |
| 334 | 334 | ** The "#undef INTERFACE" part is a hack to work around a name collision |
| 335 | 335 | ** in MSVC 2008. |
| 336 | 336 | */ |
| 337 | -const char zTopLine[] = | |
| 337 | +const char zTopLine[] = | |
| 338 | 338 | "/* \aThis file was automatically generated. Do not edit! */\n" |
| 339 | 339 | "#undef INTERFACE\n"; |
| 340 | 340 | #define nTopLine (sizeof(zTopLine)-1) |
| 341 | 341 | |
| 342 | 342 | /* |
| 343 | 343 | ** The name of the file currently being parsed. |
| 344 | 344 | */ |
| 345 | -static char *zFilename; | |
| 345 | +static const char *zFilename; | |
| 346 | 346 | |
| 347 | 347 | /* |
| 348 | 348 | ** The stack of #if macros for the file currently being parsed. |
| 349 | 349 | */ |
| 350 | 350 | static Ifmacro *ifStack = 0; |
| @@ -702,11 +702,11 @@ | ||
| 702 | 702 | struct stat sStat; |
| 703 | 703 | FILE *pIn; |
| 704 | 704 | char *zBuf; |
| 705 | 705 | int n; |
| 706 | 706 | |
| 707 | - if( stat(zFilename,&sStat)!=0 | |
| 707 | + if( stat(zFilename,&sStat)!=0 | |
| 708 | 708 | #ifndef WIN32 |
| 709 | 709 | || !S_ISREG(sStat.st_mode) |
| 710 | 710 | #endif |
| 711 | 711 | ){ |
| 712 | 712 | return 0; |
| @@ -889,12 +889,12 @@ | ||
| 889 | 889 | } |
| 890 | 890 | } |
| 891 | 891 | } |
| 892 | 892 | i++; |
| 893 | 893 | } |
| 894 | - if( z[i] ){ | |
| 895 | - i += 2; | |
| 894 | + if( z[i] ){ | |
| 895 | + i += 2; | |
| 896 | 896 | }else{ |
| 897 | 897 | isBlockComment = 0; |
| 898 | 898 | fprintf(stderr,"%s:%d: Unterminated comment\n", |
| 899 | 899 | zFilename, startLine); |
| 900 | 900 | nErr++; |
| @@ -906,11 +906,11 @@ | ||
| 906 | 906 | pToken->eType = TT_Other; |
| 907 | 907 | pToken->nText = 1 + (z[i+1]=='+'); |
| 908 | 908 | } |
| 909 | 909 | break; |
| 910 | 910 | |
| 911 | - case '0': | |
| 911 | + case '0': | |
| 912 | 912 | if( z[i+1]=='x' || z[i+1]=='X' ){ |
| 913 | 913 | /* A hex constant */ |
| 914 | 914 | i += 2; |
| 915 | 915 | while( isxdigit(z[i]) ){ i++; } |
| 916 | 916 | }else{ |
| @@ -963,11 +963,11 @@ | ||
| 963 | 963 | while( isalnum(z[i]) || z[i]=='_' ){ i++; }; |
| 964 | 964 | pToken->eType = TT_Id; |
| 965 | 965 | pToken->nText = i - pIn->i; |
| 966 | 966 | break; |
| 967 | 967 | |
| 968 | - case ':': | |
| 968 | + case ':': | |
| 969 | 969 | pToken->eType = TT_Other; |
| 970 | 970 | pToken->nText = 1 + (z[i+1]==':'); |
| 971 | 971 | break; |
| 972 | 972 | |
| 973 | 973 | case '=': |
| @@ -977,11 +977,11 @@ | ||
| 977 | 977 | case '-': |
| 978 | 978 | case '*': |
| 979 | 979 | case '%': |
| 980 | 980 | case '^': |
| 981 | 981 | case '&': |
| 982 | - case '|': | |
| 982 | + case '|': | |
| 983 | 983 | pToken->eType = TT_Other; |
| 984 | 984 | pToken->nText = 1 + (z[i+1]=='='); |
| 985 | 985 | break; |
| 986 | 986 | |
| 987 | 987 | default: |
| @@ -1064,11 +1064,11 @@ | ||
| 1064 | 1064 | } |
| 1065 | 1065 | } |
| 1066 | 1066 | /* NOT REACHED */ |
| 1067 | 1067 | } |
| 1068 | 1068 | |
| 1069 | -/* | |
| 1069 | +/* | |
| 1070 | 1070 | ** This routine looks for identifiers (strings of contiguous alphanumeric |
| 1071 | 1071 | ** characters) within a preprocessor directive and adds every such string |
| 1072 | 1072 | ** found to the given identifier table |
| 1073 | 1073 | */ |
| 1074 | 1074 | static void FindIdentifiersInMacro(Token *pToken, IdentTable *pTable){ |
| @@ -1157,11 +1157,11 @@ | ||
| 1157 | 1157 | case TT_Id: |
| 1158 | 1158 | if( pTable ){ |
| 1159 | 1159 | IdentTableInsert(pTable,pToken->zText,pToken->nText); |
| 1160 | 1160 | } |
| 1161 | 1161 | break; |
| 1162 | - | |
| 1162 | + | |
| 1163 | 1163 | case TT_Preprocessor: |
| 1164 | 1164 | if( pTable!=0 ){ |
| 1165 | 1165 | FindIdentifiersInMacro(pToken,pTable); |
| 1166 | 1166 | } |
| 1167 | 1167 | break; |
| @@ -1263,11 +1263,11 @@ | ||
| 1263 | 1263 | exit(1); |
| 1264 | 1264 | } |
| 1265 | 1265 | pList = TokenizeFile(zFile,&sTable); |
| 1266 | 1266 | for(p=pList; p; p=p->pNext){ |
| 1267 | 1267 | int j; |
| 1268 | - switch( p->eType ){ | |
| 1268 | + switch( p->eType ){ | |
| 1269 | 1269 | case TT_Space: |
| 1270 | 1270 | printf("%4d: Space\n",p->nLine); |
| 1271 | 1271 | break; |
| 1272 | 1272 | case TT_Id: |
| 1273 | 1273 | printf("%4d: Id %.*s\n",p->nLine,p->nText,p->zText); |
| @@ -1330,11 +1330,11 @@ | ||
| 1330 | 1330 | needSpace = 1; |
| 1331 | 1331 | break; |
| 1332 | 1332 | |
| 1333 | 1333 | default: |
| 1334 | 1334 | c = pFirst->zText[0]; |
| 1335 | - printf("%s%.*s", | |
| 1335 | + printf("%s%.*s", | |
| 1336 | 1336 | (needSpace && (c=='*' || c=='{')) ? " " : "", |
| 1337 | 1337 | pFirst->nText, pFirst->zText); |
| 1338 | 1338 | needSpace = pFirst->zText[0]==','; |
| 1339 | 1339 | break; |
| 1340 | 1340 | } |
| @@ -1371,13 +1371,13 @@ | ||
| 1371 | 1371 | |
| 1372 | 1372 | StringInit(&str); |
| 1373 | 1373 | pLast = pLast->pNext; |
| 1374 | 1374 | while( pFirst!=pLast ){ |
| 1375 | 1375 | if( pFirst==pSkip ){ iSkip = nSkip; } |
| 1376 | - if( iSkip>0 ){ | |
| 1376 | + if( iSkip>0 ){ | |
| 1377 | 1377 | iSkip--; |
| 1378 | - pFirst=pFirst->pNext; | |
| 1378 | + pFirst=pFirst->pNext; | |
| 1379 | 1379 | continue; |
| 1380 | 1380 | } |
| 1381 | 1381 | switch( pFirst->eType ){ |
| 1382 | 1382 | case TT_Preprocessor: |
| 1383 | 1383 | StringAppend(&str,"\n",1); |
| @@ -1384,13 +1384,13 @@ | ||
| 1384 | 1384 | StringAppend(&str,pFirst->zText,pFirst->nText); |
| 1385 | 1385 | StringAppend(&str,"\n",1); |
| 1386 | 1386 | needSpace = 0; |
| 1387 | 1387 | break; |
| 1388 | 1388 | |
| 1389 | - case TT_Id: | |
| 1389 | + case TT_Id: | |
| 1390 | 1390 | switch( pFirst->zText[0] ){ |
| 1391 | - case 'E': | |
| 1391 | + case 'E': | |
| 1392 | 1392 | if( pFirst->nText==6 && strncmp(pFirst->zText,"EXPORT",6)==0 ){ |
| 1393 | 1393 | skipOne = 1; |
| 1394 | 1394 | } |
| 1395 | 1395 | break; |
| 1396 | 1396 | case 'P': |
| @@ -1645,17 +1645,17 @@ | ||
| 1645 | 1645 | pLast = pLast->pNext; |
| 1646 | 1646 | for(p=pFirst; p && p!=pLast; p=p->pNext){ |
| 1647 | 1647 | if( p->eType==TT_Id ){ |
| 1648 | 1648 | static IdentTable sReserved; |
| 1649 | 1649 | static int isInit = 0; |
| 1650 | - static char *aWords[] = { "char", "class", | |
| 1651 | - "const", "double", "enum", "extern", "EXPORT", "ET_PROC", | |
| 1650 | + static const char *aWords[] = { "char", "class", | |
| 1651 | + "const", "double", "enum", "extern", "EXPORT", "ET_PROC", | |
| 1652 | 1652 | "float", "int", "long", |
| 1653 | 1653 | "PRIVATE", "PROTECTED", "PUBLIC", |
| 1654 | - "register", "static", "struct", "sizeof", "signed", "typedef", | |
| 1654 | + "register", "static", "struct", "sizeof", "signed", "typedef", | |
| 1655 | 1655 | "union", "volatile", "virtual", "void", }; |
| 1656 | - | |
| 1656 | + | |
| 1657 | 1657 | if( !isInit ){ |
| 1658 | 1658 | int i; |
| 1659 | 1659 | for(i=0; i<sizeof(aWords)/sizeof(aWords[0]); i++){ |
| 1660 | 1660 | IdentTableInsert(&sReserved,aWords[i],0); |
| 1661 | 1661 | } |
| @@ -1768,11 +1768,11 @@ | ||
| 1768 | 1768 | pCode = pLast; |
| 1769 | 1769 | while( pLast && pLast!=pFirst && pLast->zText[0]!=')' ){ |
| 1770 | 1770 | pLast = pLast->pPrev; |
| 1771 | 1771 | } |
| 1772 | 1772 | if( pLast==0 || pLast==pFirst || pFirst->pNext==pLast ){ |
| 1773 | - fprintf(stderr,"%s:%d: Unrecognized syntax.\n", | |
| 1773 | + fprintf(stderr,"%s:%d: Unrecognized syntax.\n", | |
| 1774 | 1774 | zFilename, pFirst->nLine); |
| 1775 | 1775 | return 1; |
| 1776 | 1776 | } |
| 1777 | 1777 | if( flags & (PS_Interface|PS_Export|PS_Local) ){ |
| 1778 | 1778 | fprintf(stderr,"%s:%d: Missing \"inline\" on function or procedure.\n", |
| @@ -1849,11 +1849,11 @@ | ||
| 1849 | 1849 | return 1; |
| 1850 | 1850 | } |
| 1851 | 1851 | |
| 1852 | 1852 | #ifdef DEBUG |
| 1853 | 1853 | if( debugMask & PARSER ){ |
| 1854 | - printf("**** Found inline routine: %.*s on line %d...\n", | |
| 1854 | + printf("**** Found inline routine: %.*s on line %d...\n", | |
| 1855 | 1855 | pName->nText, pName->zText, pFirst->nLine); |
| 1856 | 1856 | PrintTokens(pFirst,pEnd); |
| 1857 | 1857 | printf("\n"); |
| 1858 | 1858 | } |
| 1859 | 1859 | #endif |
| @@ -1888,11 +1888,11 @@ | ||
| 1888 | 1888 | ** to search for an occurrence of an ID followed immediately by '('. |
| 1889 | 1889 | ** If found, we have a prototype. Otherwise we are dealing with a |
| 1890 | 1890 | ** variable definition. |
| 1891 | 1891 | */ |
| 1892 | 1892 | static int isVariableDef(Token *pFirst, Token *pEnd){ |
| 1893 | - if( pEnd && pEnd->zText[0]=='=' && | |
| 1893 | + if( pEnd && pEnd->zText[0]=='=' && | |
| 1894 | 1894 | (pEnd->pPrev->nText!=8 || strncmp(pEnd->pPrev->zText,"operator",8)!=0) |
| 1895 | 1895 | ){ |
| 1896 | 1896 | return 1; |
| 1897 | 1897 | } |
| 1898 | 1898 | while( pFirst && pFirst!=pEnd && pFirst->pNext && pFirst->pNext!=pEnd ){ |
| @@ -1949,11 +1949,11 @@ | ||
| 1949 | 1949 | } |
| 1950 | 1950 | while( pFirst!=0 && pFirst->pNext!=pEnd && |
| 1951 | 1951 | ((pFirst->nText==6 && strncmp(pFirst->zText,"static",6)==0) |
| 1952 | 1952 | || (pFirst->nText==5 && strncmp(pFirst->zText,"LOCAL",6)==0)) |
| 1953 | 1953 | ){ |
| 1954 | - /* Lose the initial "static" or local from local variables. | |
| 1954 | + /* Lose the initial "static" or local from local variables. | |
| 1955 | 1955 | ** We'll prepend "extern" later. */ |
| 1956 | 1956 | pFirst = pFirst->pNext; |
| 1957 | 1957 | isLocal = 1; |
| 1958 | 1958 | } |
| 1959 | 1959 | if( pFirst==0 || !isLocal ){ |
| @@ -1962,11 +1962,11 @@ | ||
| 1962 | 1962 | }else if( flags & PS_Method ){ |
| 1963 | 1963 | /* Methods are declared by their class. Don't declare separately. */ |
| 1964 | 1964 | return nErr; |
| 1965 | 1965 | } |
| 1966 | 1966 | isVar = (flags & (PS_Typedef|PS_Method))==0 && isVariableDef(pFirst,pEnd); |
| 1967 | - if( isVar && (flags & (PS_Interface|PS_Export|PS_Local))!=0 | |
| 1967 | + if( isVar && (flags & (PS_Interface|PS_Export|PS_Local))!=0 | |
| 1968 | 1968 | && (flags & PS_Extern)==0 ){ |
| 1969 | 1969 | fprintf(stderr,"%s:%d: Can't define a variable in this context\n", |
| 1970 | 1970 | zFilename, pFirst->nLine); |
| 1971 | 1971 | nErr++; |
| 1972 | 1972 | } |
| @@ -2095,11 +2095,11 @@ | ||
| 2095 | 2095 | nCmd++; |
| 2096 | 2096 | } |
| 2097 | 2097 | |
| 2098 | 2098 | if( nCmd==5 && strncmp(zCmd,"endif",5)==0 ){ |
| 2099 | 2099 | /* |
| 2100 | - ** Pop the if stack | |
| 2100 | + ** Pop the if stack | |
| 2101 | 2101 | */ |
| 2102 | 2102 | pIf = ifStack; |
| 2103 | 2103 | if( pIf==0 ){ |
| 2104 | 2104 | fprintf(stderr,"%s:%d: extra '#endif'.\n",zFilename,pToken->nLine); |
| 2105 | 2105 | return 1; |
| @@ -2106,11 +2106,11 @@ | ||
| 2106 | 2106 | } |
| 2107 | 2107 | ifStack = pIf->pNext; |
| 2108 | 2108 | SafeFree(pIf); |
| 2109 | 2109 | }else if( nCmd==6 && strncmp(zCmd,"define",6)==0 ){ |
| 2110 | 2110 | /* |
| 2111 | - ** Record a #define if we are in PS_Interface or PS_Export | |
| 2111 | + ** Record a #define if we are in PS_Interface or PS_Export | |
| 2112 | 2112 | */ |
| 2113 | 2113 | Decl *pDecl; |
| 2114 | 2114 | if( !(flags & (PS_Local|PS_Interface|PS_Export)) ){ return 0; } |
| 2115 | 2115 | zArg = &zCmd[6]; |
| 2116 | 2116 | while( *zArg && isspace(*zArg) && *zArg!='\n' ){ |
| @@ -2129,11 +2129,11 @@ | ||
| 2129 | 2129 | }else if( flags & PS_Local ){ |
| 2130 | 2130 | DeclSetProperty(pDecl,DP_Local); |
| 2131 | 2131 | } |
| 2132 | 2132 | }else if( nCmd==7 && strncmp(zCmd,"include",7)==0 ){ |
| 2133 | 2133 | /* |
| 2134 | - ** Record an #include if we are in PS_Interface or PS_Export | |
| 2134 | + ** Record an #include if we are in PS_Interface or PS_Export | |
| 2135 | 2135 | */ |
| 2136 | 2136 | Include *pInclude; |
| 2137 | 2137 | char *zIf; |
| 2138 | 2138 | |
| 2139 | 2139 | if( !(flags & (PS_Interface|PS_Export)) ){ return 0; } |
| @@ -2184,11 +2184,11 @@ | ||
| 2184 | 2184 | PushIfMacro(0,0,0,pToken->nLine,PS_Local); |
| 2185 | 2185 | }else{ |
| 2186 | 2186 | PushIfMacro(0,zArg,nArg,pToken->nLine,0); |
| 2187 | 2187 | } |
| 2188 | 2188 | }else if( nCmd==5 && strncmp(zCmd,"ifdef",5)==0 ){ |
| 2189 | - /* | |
| 2189 | + /* | |
| 2190 | 2190 | ** Push an #ifdef. |
| 2191 | 2191 | */ |
| 2192 | 2192 | zArg = &zCmd[5]; |
| 2193 | 2193 | while( *zArg && isspace(*zArg) && *zArg!='\n' ){ |
| 2194 | 2194 | zArg++; |
| @@ -2207,11 +2207,11 @@ | ||
| 2207 | 2207 | if( *zArg==0 || *zArg=='\n' ){ return 0; } |
| 2208 | 2208 | nArg = pToken->nText + (int)(pToken->zText - zArg); |
| 2209 | 2209 | PushIfMacro("!defined",zArg,nArg,pToken->nLine,0); |
| 2210 | 2210 | }else if( nCmd==4 && strncmp(zCmd,"else",4)==0 ){ |
| 2211 | 2211 | /* |
| 2212 | - ** Invert the #if on the top of the stack | |
| 2212 | + ** Invert the #if on the top of the stack | |
| 2213 | 2213 | */ |
| 2214 | 2214 | if( ifStack==0 ){ |
| 2215 | 2215 | fprintf(stderr,"%s:%d: '#else' without an '#if'\n",zFilename, |
| 2216 | 2216 | pToken->nLine); |
| 2217 | 2217 | return 1; |
| @@ -2224,33 +2224,33 @@ | ||
| 2224 | 2224 | }else{ |
| 2225 | 2225 | pIf->flags = 0; |
| 2226 | 2226 | } |
| 2227 | 2227 | }else{ |
| 2228 | 2228 | /* |
| 2229 | - ** This directive can be safely ignored | |
| 2229 | + ** This directive can be safely ignored | |
| 2230 | 2230 | */ |
| 2231 | 2231 | return 0; |
| 2232 | 2232 | } |
| 2233 | 2233 | |
| 2234 | - /* | |
| 2235 | - ** Recompute the preset flags | |
| 2234 | + /* | |
| 2235 | + ** Recompute the preset flags | |
| 2236 | 2236 | */ |
| 2237 | 2237 | *pPresetFlags = 0; |
| 2238 | 2238 | for(pIf = ifStack; pIf; pIf=pIf->pNext){ |
| 2239 | 2239 | *pPresetFlags |= pIf->flags; |
| 2240 | 2240 | } |
| 2241 | - | |
| 2241 | + | |
| 2242 | 2242 | return nErr; |
| 2243 | 2243 | } |
| 2244 | 2244 | |
| 2245 | 2245 | /* |
| 2246 | 2246 | ** Parse an entire file. Return the number of errors. |
| 2247 | 2247 | ** |
| 2248 | 2248 | ** pList is a list of tokens in the file. Whitespace tokens have been |
| 2249 | 2249 | ** eliminated, and text with {...} has been collapsed into a |
| 2250 | 2250 | ** single TT_Brace token. |
| 2251 | -** | |
| 2251 | +** | |
| 2252 | 2252 | ** initFlags are a set of parse flags that should always be set for this |
| 2253 | 2253 | ** file. For .c files this is normally 0. For .h files it is PS_Interface. |
| 2254 | 2254 | */ |
| 2255 | 2255 | static int ParseFile(Token *pList, int initFlags){ |
| 2256 | 2256 | int nErr = 0; |
| @@ -2279,11 +2279,11 @@ | ||
| 2279 | 2279 | pStart = 0; |
| 2280 | 2280 | flags = presetFlags; |
| 2281 | 2281 | break; |
| 2282 | 2282 | |
| 2283 | 2283 | case '=': |
| 2284 | - if( pList->pPrev->nText==8 | |
| 2284 | + if( pList->pPrev->nText==8 | |
| 2285 | 2285 | && strncmp(pList->pPrev->zText,"operator",8)==0 ){ |
| 2286 | 2286 | break; |
| 2287 | 2287 | } |
| 2288 | 2288 | nErr += ProcessDecl(pStart,pList,flags); |
| 2289 | 2289 | pStart = 0; |
| @@ -2471,11 +2471,11 @@ | ||
| 2471 | 2471 | pDecl->zExtra = 0; |
| 2472 | 2472 | } |
| 2473 | 2473 | |
| 2474 | 2474 | /* |
| 2475 | 2475 | ** Reset the DP_Forward and DP_Declared flags on all Decl structures. |
| 2476 | -** Set both flags for anything that is tagged as local and isn't | |
| 2476 | +** Set both flags for anything that is tagged as local and isn't | |
| 2477 | 2477 | ** in the file zFilename so that it won't be printing in other files. |
| 2478 | 2478 | */ |
| 2479 | 2479 | static void ResetDeclFlags(char *zFilename){ |
| 2480 | 2480 | Decl *pDecl; |
| 2481 | 2481 | |
| @@ -2574,11 +2574,11 @@ | ||
| 2574 | 2574 | int flag; |
| 2575 | 2575 | int isCpp; /* True if generating C++ */ |
| 2576 | 2576 | int doneTypedef = 0; /* True if a typedef has been done for this object */ |
| 2577 | 2577 | |
| 2578 | 2578 | /* printf("BEGIN %s of %s\n",needFullDecl?"FULL":"PROTOTYPE",pDecl->zName);*/ |
| 2579 | - /* | |
| 2579 | + /* | |
| 2580 | 2580 | ** For any object that has a forward declaration, go ahead and do the |
| 2581 | 2581 | ** forward declaration first. |
| 2582 | 2582 | */ |
| 2583 | 2583 | isCpp = (pState->flags & DP_Cplusplus) != 0; |
| 2584 | 2584 | for(p=pDecl; p; p=p->pSameName){ |
| @@ -2626,12 +2626,12 @@ | ||
| 2626 | 2626 | ** function on a recursive call with the same pDecl. Hence, recursive |
| 2627 | 2627 | ** calls to this function (through ScanText()) can never change the |
| 2628 | 2628 | ** value of DP_Flag out from under us. |
| 2629 | 2629 | */ |
| 2630 | 2630 | for(p=pDecl; p; p=p->pSameName){ |
| 2631 | - if( !DeclHasProperty(p,DP_Declared) | |
| 2632 | - && (p->zFwd==0 || needFullDecl) | |
| 2631 | + if( !DeclHasProperty(p,DP_Declared) | |
| 2632 | + && (p->zFwd==0 || needFullDecl) | |
| 2633 | 2633 | && p->zDecl!=0 |
| 2634 | 2634 | ){ |
| 2635 | 2635 | DeclSetProperty(p,DP_Forward|DP_Declared|DP_Flag); |
| 2636 | 2636 | }else{ |
| 2637 | 2637 | DeclClearProperty(p,DP_Flag); |
| @@ -2735,12 +2735,12 @@ | ||
| 2735 | 2735 | ** by sToken. |
| 2736 | 2736 | */ |
| 2737 | 2737 | pDecl = FindDecl(sToken.zText,sToken.nText); |
| 2738 | 2738 | if( pDecl==0 ) continue; |
| 2739 | 2739 | |
| 2740 | - /* | |
| 2741 | - ** If we get this far, we've found an identifier that has a | |
| 2740 | + /* | |
| 2741 | + ** If we get this far, we've found an identifier that has a | |
| 2742 | 2742 | ** declaration in the database. Now see if we the full declaration |
| 2743 | 2743 | ** or just a forward declaration. |
| 2744 | 2744 | */ |
| 2745 | 2745 | GetNonspaceToken(&sIn,&sNext); |
| 2746 | 2746 | if( sNext.zText[0]=='*' ){ |
| @@ -2770,12 +2770,12 @@ | ||
| 2770 | 2770 | int progress; |
| 2771 | 2771 | |
| 2772 | 2772 | do{ |
| 2773 | 2773 | progress = 0; |
| 2774 | 2774 | for(pDecl=pDeclFirst; pDecl; pDecl=pDecl->pNext){ |
| 2775 | - if( DeclHasProperty(pDecl,DP_Forward) | |
| 2776 | - && !DeclHasProperty(pDecl,DP_Declared) | |
| 2775 | + if( DeclHasProperty(pDecl,DP_Forward) | |
| 2776 | + && !DeclHasProperty(pDecl,DP_Declared) | |
| 2777 | 2777 | ){ |
| 2778 | 2778 | DeclareObject(pDecl,pState,1); |
| 2779 | 2779 | progress = 1; |
| 2780 | 2780 | assert( DeclHasProperty(pDecl,DP_Declared) ); |
| 2781 | 2781 | } |
| @@ -2842,11 +2842,11 @@ | ||
| 2842 | 2842 | nErr++; |
| 2843 | 2843 | } |
| 2844 | 2844 | }else if( report ){ |
| 2845 | 2845 | fprintf(report,"unchanged\n"); |
| 2846 | 2846 | } |
| 2847 | - SafeFree(zOldVersion); | |
| 2847 | + SafeFree(zOldVersion); | |
| 2848 | 2848 | IdentTableReset(&includeTable); |
| 2849 | 2849 | StringReset(&outStr); |
| 2850 | 2850 | return nErr; |
| 2851 | 2851 | } |
| 2852 | 2852 | |
| @@ -2878,11 +2878,11 @@ | ||
| 2878 | 2878 | } |
| 2879 | 2879 | ChangeIfContext(0,&sState); |
| 2880 | 2880 | printf("%s",StringGet(&outStr)); |
| 2881 | 2881 | IdentTableReset(&includeTable); |
| 2882 | 2882 | StringReset(&outStr); |
| 2883 | - return 0; | |
| 2883 | + return 0; | |
| 2884 | 2884 | } |
| 2885 | 2885 | |
| 2886 | 2886 | #ifdef DEBUG |
| 2887 | 2887 | /* |
| 2888 | 2888 | ** Return the number of characters in the given string prior to the |
| @@ -3040,11 +3040,11 @@ | ||
| 3040 | 3040 | int nSrc; |
| 3041 | 3041 | char *zSrc; |
| 3042 | 3042 | InFile *pFile; |
| 3043 | 3043 | int i; |
| 3044 | 3044 | |
| 3045 | - /* | |
| 3045 | + /* | |
| 3046 | 3046 | ** Get the name of the input file to be scanned. The input file is |
| 3047 | 3047 | ** everything before the first ':' or the whole file if no ':' is seen. |
| 3048 | 3048 | ** |
| 3049 | 3049 | ** Except, on windows, ignore any ':' that occurs as the second character |
| 3050 | 3050 | ** since it might be part of the drive specifier. So really, the ":' has |
| @@ -3099,11 +3099,11 @@ | ||
| 3099 | 3099 | } |
| 3100 | 3100 | } |
| 3101 | 3101 | |
| 3102 | 3102 | /* |
| 3103 | 3103 | ** If pFile->zSrc contains no 'c' or 'C' in its extension, it |
| 3104 | - ** must be a header file. In that case, we need to set the | |
| 3104 | + ** must be a header file. In that case, we need to set the | |
| 3105 | 3105 | ** PS_Interface flag. |
| 3106 | 3106 | */ |
| 3107 | 3107 | pFile->flags |= PS_Interface; |
| 3108 | 3108 | for(i=nSrc-1; i>0 && zSrc[i]!='.'; i--){ |
| 3109 | 3109 | if( zSrc[i]=='c' || zSrc[i]=='C' ){ |
| @@ -3110,11 +3110,11 @@ | ||
| 3110 | 3110 | pFile->flags &= ~PS_Interface; |
| 3111 | 3111 | break; |
| 3112 | 3112 | } |
| 3113 | 3113 | } |
| 3114 | 3114 | |
| 3115 | - /* Done! | |
| 3115 | + /* Done! | |
| 3116 | 3116 | */ |
| 3117 | 3117 | return pFile; |
| 3118 | 3118 | } |
| 3119 | 3119 | |
| 3120 | 3120 | /* MS-Windows and MS-DOS both have the following serious OS bug: the |
| @@ -3162,11 +3162,11 @@ | ||
| 3162 | 3162 | while( c!=EOF ){ |
| 3163 | 3163 | while( c!=EOF && isspace(c) ){ |
| 3164 | 3164 | if( c=='\n' ){ |
| 3165 | 3165 | startOfLine = 1; |
| 3166 | 3166 | } |
| 3167 | - c = getc(in); | |
| 3167 | + c = getc(in); | |
| 3168 | 3168 | if( startOfLine && c=='#' ){ |
| 3169 | 3169 | while( c!=EOF && c!='\n' ){ |
| 3170 | 3170 | c = getc(in); |
| 3171 | 3171 | } |
| 3172 | 3172 | } |
| @@ -3184,11 +3184,11 @@ | ||
| 3184 | 3184 | if( nAlloc==0 ){ |
| 3185 | 3185 | nAlloc = 100 + argc; |
| 3186 | 3186 | zNew = malloc( sizeof(char*) * nAlloc ); |
| 3187 | 3187 | }else{ |
| 3188 | 3188 | nAlloc *= 2; |
| 3189 | - zNew = realloc( zNew, sizeof(char*) * nAlloc ); | |
| 3189 | + zNew = realloc( zNew, sizeof(char*) * nAlloc ); | |
| 3190 | 3190 | } |
| 3191 | 3191 | } |
| 3192 | 3192 | if( zNew ){ |
| 3193 | 3193 | int j = nNew + index; |
| 3194 | 3194 | zNew[j] = malloc( n + 1 ); |
| @@ -3254,11 +3254,11 @@ | ||
| 3254 | 3254 | |
| 3255 | 3255 | /* |
| 3256 | 3256 | ** The following text contains a few simple #defines that we want |
| 3257 | 3257 | ** to be available to every file. |
| 3258 | 3258 | */ |
| 3259 | -static char zInit[] = | |
| 3259 | +static const char zInit[] = | |
| 3260 | 3260 | "#define INTERFACE 0\n" |
| 3261 | 3261 | "#define EXPORT_INTERFACE 0\n" |
| 3262 | 3262 | "#define LOCAL_INTERFACE 0\n" |
| 3263 | 3263 | "#define EXPORT\n" |
| 3264 | 3264 | "#define LOCAL static\n" |
| 3265 | 3265 |
| --- src/makeheaders.c | |
| +++ src/makeheaders.c | |
| @@ -112,19 +112,19 @@ | |
| 112 | ** |
| 113 | ** struct Xyzzy; |
| 114 | ** |
| 115 | ** Not every object has a forward declaration. If it does, thought, the |
| 116 | ** forward declaration will be contained in the zFwd field for C and |
| 117 | ** the zFwdCpp for C++. The zDecl field contains the complete |
| 118 | ** declaration text. |
| 119 | */ |
| 120 | typedef struct Decl Decl; |
| 121 | struct Decl { |
| 122 | char *zName; /* Name of the object being declared. The appearance |
| 123 | ** of this name is a source file triggers the declaration |
| 124 | ** to be added to the header for that file. */ |
| 125 | char *zFile; /* File from which extracted. */ |
| 126 | char *zIf; /* Surround the declaration with this #if */ |
| 127 | char *zFwd; /* A forward declaration. NULL if there is none. */ |
| 128 | char *zFwdCpp; /* Use this forward declaration for C++. */ |
| 129 | char *zDecl; /* A full declaration of this object */ |
| 130 | char *zExtra; /* Extra declaration text inserted into class objects */ |
| @@ -163,11 +163,11 @@ | |
| 163 | ** in the output when using the -H option.) |
| 164 | ** |
| 165 | ** EXPORT scope The object is visible and usable everywhere. |
| 166 | ** |
| 167 | ** The DP_Flag is a temporary use flag that is used during processing to |
| 168 | ** prevent an infinite loop. It's use is localized. |
| 169 | ** |
| 170 | ** The DP_Cplusplus, DP_ExternCReqd and DP_ExternReqd flags are permanent |
| 171 | ** and are used to specify what type of declaration the object requires. |
| 172 | */ |
| 173 | #define DP_Forward 0x001 /* Has a forward declaration in this file */ |
| @@ -201,11 +201,11 @@ | |
| 201 | ** Be careful not to confuse PS_Export with DP_Export or |
| 202 | ** PS_Local with DP_Local. Their names are similar, but the meanings |
| 203 | ** of these flags are very different. |
| 204 | */ |
| 205 | #define PS_Extern 0x000800 /* "extern" has been seen */ |
| 206 | #define PS_Export 0x001000 /* If between "#if EXPORT_INTERFACE" |
| 207 | ** and "#endif" */ |
| 208 | #define PS_Export2 0x002000 /* If "EXPORT" seen */ |
| 209 | #define PS_Typedef 0x004000 /* If "typedef" has been seen */ |
| 210 | #define PS_Static 0x008000 /* If "static" has been seen */ |
| 211 | #define PS_Interface 0x010000 /* If within #if INTERFACE..#endif */ |
| @@ -231,11 +231,11 @@ | |
| 231 | #define TY_Union 0x04000000 |
| 232 | #define TY_Enumeration 0x08000000 |
| 233 | #define TY_Defunct 0x10000000 /* Used to erase a declaration */ |
| 234 | |
| 235 | /* |
| 236 | ** Each nested #if (or #ifdef or #ifndef) is stored in a stack of |
| 237 | ** instances of the following structure. |
| 238 | */ |
| 239 | typedef struct Ifmacro Ifmacro; |
| 240 | struct Ifmacro { |
| 241 | int nLine; /* Line number where this macro occurs */ |
| @@ -293,11 +293,11 @@ | |
| 293 | int flags; /* One or more DP_, PS_ and/or TY_ flags */ |
| 294 | InFile *pNext; /* Next input file in the list of them all */ |
| 295 | IdentTable idTable; /* All identifiers in this input file */ |
| 296 | }; |
| 297 | |
| 298 | /* |
| 299 | ** An unbounded string is able to grow without limit. We use these |
| 300 | ** to construct large in-memory strings from lots of smaller components. |
| 301 | */ |
| 302 | typedef struct String String; |
| 303 | struct String { |
| @@ -332,19 +332,19 @@ | |
| 332 | ** never to read a file that it generated itself. |
| 333 | ** |
| 334 | ** The "#undef INTERFACE" part is a hack to work around a name collision |
| 335 | ** in MSVC 2008. |
| 336 | */ |
| 337 | const char zTopLine[] = |
| 338 | "/* \aThis file was automatically generated. Do not edit! */\n" |
| 339 | "#undef INTERFACE\n"; |
| 340 | #define nTopLine (sizeof(zTopLine)-1) |
| 341 | |
| 342 | /* |
| 343 | ** The name of the file currently being parsed. |
| 344 | */ |
| 345 | static char *zFilename; |
| 346 | |
| 347 | /* |
| 348 | ** The stack of #if macros for the file currently being parsed. |
| 349 | */ |
| 350 | static Ifmacro *ifStack = 0; |
| @@ -702,11 +702,11 @@ | |
| 702 | struct stat sStat; |
| 703 | FILE *pIn; |
| 704 | char *zBuf; |
| 705 | int n; |
| 706 | |
| 707 | if( stat(zFilename,&sStat)!=0 |
| 708 | #ifndef WIN32 |
| 709 | || !S_ISREG(sStat.st_mode) |
| 710 | #endif |
| 711 | ){ |
| 712 | return 0; |
| @@ -889,12 +889,12 @@ | |
| 889 | } |
| 890 | } |
| 891 | } |
| 892 | i++; |
| 893 | } |
| 894 | if( z[i] ){ |
| 895 | i += 2; |
| 896 | }else{ |
| 897 | isBlockComment = 0; |
| 898 | fprintf(stderr,"%s:%d: Unterminated comment\n", |
| 899 | zFilename, startLine); |
| 900 | nErr++; |
| @@ -906,11 +906,11 @@ | |
| 906 | pToken->eType = TT_Other; |
| 907 | pToken->nText = 1 + (z[i+1]=='+'); |
| 908 | } |
| 909 | break; |
| 910 | |
| 911 | case '0': |
| 912 | if( z[i+1]=='x' || z[i+1]=='X' ){ |
| 913 | /* A hex constant */ |
| 914 | i += 2; |
| 915 | while( isxdigit(z[i]) ){ i++; } |
| 916 | }else{ |
| @@ -963,11 +963,11 @@ | |
| 963 | while( isalnum(z[i]) || z[i]=='_' ){ i++; }; |
| 964 | pToken->eType = TT_Id; |
| 965 | pToken->nText = i - pIn->i; |
| 966 | break; |
| 967 | |
| 968 | case ':': |
| 969 | pToken->eType = TT_Other; |
| 970 | pToken->nText = 1 + (z[i+1]==':'); |
| 971 | break; |
| 972 | |
| 973 | case '=': |
| @@ -977,11 +977,11 @@ | |
| 977 | case '-': |
| 978 | case '*': |
| 979 | case '%': |
| 980 | case '^': |
| 981 | case '&': |
| 982 | case '|': |
| 983 | pToken->eType = TT_Other; |
| 984 | pToken->nText = 1 + (z[i+1]=='='); |
| 985 | break; |
| 986 | |
| 987 | default: |
| @@ -1064,11 +1064,11 @@ | |
| 1064 | } |
| 1065 | } |
| 1066 | /* NOT REACHED */ |
| 1067 | } |
| 1068 | |
| 1069 | /* |
| 1070 | ** This routine looks for identifiers (strings of contiguous alphanumeric |
| 1071 | ** characters) within a preprocessor directive and adds every such string |
| 1072 | ** found to the given identifier table |
| 1073 | */ |
| 1074 | static void FindIdentifiersInMacro(Token *pToken, IdentTable *pTable){ |
| @@ -1157,11 +1157,11 @@ | |
| 1157 | case TT_Id: |
| 1158 | if( pTable ){ |
| 1159 | IdentTableInsert(pTable,pToken->zText,pToken->nText); |
| 1160 | } |
| 1161 | break; |
| 1162 | |
| 1163 | case TT_Preprocessor: |
| 1164 | if( pTable!=0 ){ |
| 1165 | FindIdentifiersInMacro(pToken,pTable); |
| 1166 | } |
| 1167 | break; |
| @@ -1263,11 +1263,11 @@ | |
| 1263 | exit(1); |
| 1264 | } |
| 1265 | pList = TokenizeFile(zFile,&sTable); |
| 1266 | for(p=pList; p; p=p->pNext){ |
| 1267 | int j; |
| 1268 | switch( p->eType ){ |
| 1269 | case TT_Space: |
| 1270 | printf("%4d: Space\n",p->nLine); |
| 1271 | break; |
| 1272 | case TT_Id: |
| 1273 | printf("%4d: Id %.*s\n",p->nLine,p->nText,p->zText); |
| @@ -1330,11 +1330,11 @@ | |
| 1330 | needSpace = 1; |
| 1331 | break; |
| 1332 | |
| 1333 | default: |
| 1334 | c = pFirst->zText[0]; |
| 1335 | printf("%s%.*s", |
| 1336 | (needSpace && (c=='*' || c=='{')) ? " " : "", |
| 1337 | pFirst->nText, pFirst->zText); |
| 1338 | needSpace = pFirst->zText[0]==','; |
| 1339 | break; |
| 1340 | } |
| @@ -1371,13 +1371,13 @@ | |
| 1371 | |
| 1372 | StringInit(&str); |
| 1373 | pLast = pLast->pNext; |
| 1374 | while( pFirst!=pLast ){ |
| 1375 | if( pFirst==pSkip ){ iSkip = nSkip; } |
| 1376 | if( iSkip>0 ){ |
| 1377 | iSkip--; |
| 1378 | pFirst=pFirst->pNext; |
| 1379 | continue; |
| 1380 | } |
| 1381 | switch( pFirst->eType ){ |
| 1382 | case TT_Preprocessor: |
| 1383 | StringAppend(&str,"\n",1); |
| @@ -1384,13 +1384,13 @@ | |
| 1384 | StringAppend(&str,pFirst->zText,pFirst->nText); |
| 1385 | StringAppend(&str,"\n",1); |
| 1386 | needSpace = 0; |
| 1387 | break; |
| 1388 | |
| 1389 | case TT_Id: |
| 1390 | switch( pFirst->zText[0] ){ |
| 1391 | case 'E': |
| 1392 | if( pFirst->nText==6 && strncmp(pFirst->zText,"EXPORT",6)==0 ){ |
| 1393 | skipOne = 1; |
| 1394 | } |
| 1395 | break; |
| 1396 | case 'P': |
| @@ -1645,17 +1645,17 @@ | |
| 1645 | pLast = pLast->pNext; |
| 1646 | for(p=pFirst; p && p!=pLast; p=p->pNext){ |
| 1647 | if( p->eType==TT_Id ){ |
| 1648 | static IdentTable sReserved; |
| 1649 | static int isInit = 0; |
| 1650 | static char *aWords[] = { "char", "class", |
| 1651 | "const", "double", "enum", "extern", "EXPORT", "ET_PROC", |
| 1652 | "float", "int", "long", |
| 1653 | "PRIVATE", "PROTECTED", "PUBLIC", |
| 1654 | "register", "static", "struct", "sizeof", "signed", "typedef", |
| 1655 | "union", "volatile", "virtual", "void", }; |
| 1656 | |
| 1657 | if( !isInit ){ |
| 1658 | int i; |
| 1659 | for(i=0; i<sizeof(aWords)/sizeof(aWords[0]); i++){ |
| 1660 | IdentTableInsert(&sReserved,aWords[i],0); |
| 1661 | } |
| @@ -1768,11 +1768,11 @@ | |
| 1768 | pCode = pLast; |
| 1769 | while( pLast && pLast!=pFirst && pLast->zText[0]!=')' ){ |
| 1770 | pLast = pLast->pPrev; |
| 1771 | } |
| 1772 | if( pLast==0 || pLast==pFirst || pFirst->pNext==pLast ){ |
| 1773 | fprintf(stderr,"%s:%d: Unrecognized syntax.\n", |
| 1774 | zFilename, pFirst->nLine); |
| 1775 | return 1; |
| 1776 | } |
| 1777 | if( flags & (PS_Interface|PS_Export|PS_Local) ){ |
| 1778 | fprintf(stderr,"%s:%d: Missing \"inline\" on function or procedure.\n", |
| @@ -1849,11 +1849,11 @@ | |
| 1849 | return 1; |
| 1850 | } |
| 1851 | |
| 1852 | #ifdef DEBUG |
| 1853 | if( debugMask & PARSER ){ |
| 1854 | printf("**** Found inline routine: %.*s on line %d...\n", |
| 1855 | pName->nText, pName->zText, pFirst->nLine); |
| 1856 | PrintTokens(pFirst,pEnd); |
| 1857 | printf("\n"); |
| 1858 | } |
| 1859 | #endif |
| @@ -1888,11 +1888,11 @@ | |
| 1888 | ** to search for an occurrence of an ID followed immediately by '('. |
| 1889 | ** If found, we have a prototype. Otherwise we are dealing with a |
| 1890 | ** variable definition. |
| 1891 | */ |
| 1892 | static int isVariableDef(Token *pFirst, Token *pEnd){ |
| 1893 | if( pEnd && pEnd->zText[0]=='=' && |
| 1894 | (pEnd->pPrev->nText!=8 || strncmp(pEnd->pPrev->zText,"operator",8)!=0) |
| 1895 | ){ |
| 1896 | return 1; |
| 1897 | } |
| 1898 | while( pFirst && pFirst!=pEnd && pFirst->pNext && pFirst->pNext!=pEnd ){ |
| @@ -1949,11 +1949,11 @@ | |
| 1949 | } |
| 1950 | while( pFirst!=0 && pFirst->pNext!=pEnd && |
| 1951 | ((pFirst->nText==6 && strncmp(pFirst->zText,"static",6)==0) |
| 1952 | || (pFirst->nText==5 && strncmp(pFirst->zText,"LOCAL",6)==0)) |
| 1953 | ){ |
| 1954 | /* Lose the initial "static" or local from local variables. |
| 1955 | ** We'll prepend "extern" later. */ |
| 1956 | pFirst = pFirst->pNext; |
| 1957 | isLocal = 1; |
| 1958 | } |
| 1959 | if( pFirst==0 || !isLocal ){ |
| @@ -1962,11 +1962,11 @@ | |
| 1962 | }else if( flags & PS_Method ){ |
| 1963 | /* Methods are declared by their class. Don't declare separately. */ |
| 1964 | return nErr; |
| 1965 | } |
| 1966 | isVar = (flags & (PS_Typedef|PS_Method))==0 && isVariableDef(pFirst,pEnd); |
| 1967 | if( isVar && (flags & (PS_Interface|PS_Export|PS_Local))!=0 |
| 1968 | && (flags & PS_Extern)==0 ){ |
| 1969 | fprintf(stderr,"%s:%d: Can't define a variable in this context\n", |
| 1970 | zFilename, pFirst->nLine); |
| 1971 | nErr++; |
| 1972 | } |
| @@ -2095,11 +2095,11 @@ | |
| 2095 | nCmd++; |
| 2096 | } |
| 2097 | |
| 2098 | if( nCmd==5 && strncmp(zCmd,"endif",5)==0 ){ |
| 2099 | /* |
| 2100 | ** Pop the if stack |
| 2101 | */ |
| 2102 | pIf = ifStack; |
| 2103 | if( pIf==0 ){ |
| 2104 | fprintf(stderr,"%s:%d: extra '#endif'.\n",zFilename,pToken->nLine); |
| 2105 | return 1; |
| @@ -2106,11 +2106,11 @@ | |
| 2106 | } |
| 2107 | ifStack = pIf->pNext; |
| 2108 | SafeFree(pIf); |
| 2109 | }else if( nCmd==6 && strncmp(zCmd,"define",6)==0 ){ |
| 2110 | /* |
| 2111 | ** Record a #define if we are in PS_Interface or PS_Export |
| 2112 | */ |
| 2113 | Decl *pDecl; |
| 2114 | if( !(flags & (PS_Local|PS_Interface|PS_Export)) ){ return 0; } |
| 2115 | zArg = &zCmd[6]; |
| 2116 | while( *zArg && isspace(*zArg) && *zArg!='\n' ){ |
| @@ -2129,11 +2129,11 @@ | |
| 2129 | }else if( flags & PS_Local ){ |
| 2130 | DeclSetProperty(pDecl,DP_Local); |
| 2131 | } |
| 2132 | }else if( nCmd==7 && strncmp(zCmd,"include",7)==0 ){ |
| 2133 | /* |
| 2134 | ** Record an #include if we are in PS_Interface or PS_Export |
| 2135 | */ |
| 2136 | Include *pInclude; |
| 2137 | char *zIf; |
| 2138 | |
| 2139 | if( !(flags & (PS_Interface|PS_Export)) ){ return 0; } |
| @@ -2184,11 +2184,11 @@ | |
| 2184 | PushIfMacro(0,0,0,pToken->nLine,PS_Local); |
| 2185 | }else{ |
| 2186 | PushIfMacro(0,zArg,nArg,pToken->nLine,0); |
| 2187 | } |
| 2188 | }else if( nCmd==5 && strncmp(zCmd,"ifdef",5)==0 ){ |
| 2189 | /* |
| 2190 | ** Push an #ifdef. |
| 2191 | */ |
| 2192 | zArg = &zCmd[5]; |
| 2193 | while( *zArg && isspace(*zArg) && *zArg!='\n' ){ |
| 2194 | zArg++; |
| @@ -2207,11 +2207,11 @@ | |
| 2207 | if( *zArg==0 || *zArg=='\n' ){ return 0; } |
| 2208 | nArg = pToken->nText + (int)(pToken->zText - zArg); |
| 2209 | PushIfMacro("!defined",zArg,nArg,pToken->nLine,0); |
| 2210 | }else if( nCmd==4 && strncmp(zCmd,"else",4)==0 ){ |
| 2211 | /* |
| 2212 | ** Invert the #if on the top of the stack |
| 2213 | */ |
| 2214 | if( ifStack==0 ){ |
| 2215 | fprintf(stderr,"%s:%d: '#else' without an '#if'\n",zFilename, |
| 2216 | pToken->nLine); |
| 2217 | return 1; |
| @@ -2224,33 +2224,33 @@ | |
| 2224 | }else{ |
| 2225 | pIf->flags = 0; |
| 2226 | } |
| 2227 | }else{ |
| 2228 | /* |
| 2229 | ** This directive can be safely ignored |
| 2230 | */ |
| 2231 | return 0; |
| 2232 | } |
| 2233 | |
| 2234 | /* |
| 2235 | ** Recompute the preset flags |
| 2236 | */ |
| 2237 | *pPresetFlags = 0; |
| 2238 | for(pIf = ifStack; pIf; pIf=pIf->pNext){ |
| 2239 | *pPresetFlags |= pIf->flags; |
| 2240 | } |
| 2241 | |
| 2242 | return nErr; |
| 2243 | } |
| 2244 | |
| 2245 | /* |
| 2246 | ** Parse an entire file. Return the number of errors. |
| 2247 | ** |
| 2248 | ** pList is a list of tokens in the file. Whitespace tokens have been |
| 2249 | ** eliminated, and text with {...} has been collapsed into a |
| 2250 | ** single TT_Brace token. |
| 2251 | ** |
| 2252 | ** initFlags are a set of parse flags that should always be set for this |
| 2253 | ** file. For .c files this is normally 0. For .h files it is PS_Interface. |
| 2254 | */ |
| 2255 | static int ParseFile(Token *pList, int initFlags){ |
| 2256 | int nErr = 0; |
| @@ -2279,11 +2279,11 @@ | |
| 2279 | pStart = 0; |
| 2280 | flags = presetFlags; |
| 2281 | break; |
| 2282 | |
| 2283 | case '=': |
| 2284 | if( pList->pPrev->nText==8 |
| 2285 | && strncmp(pList->pPrev->zText,"operator",8)==0 ){ |
| 2286 | break; |
| 2287 | } |
| 2288 | nErr += ProcessDecl(pStart,pList,flags); |
| 2289 | pStart = 0; |
| @@ -2471,11 +2471,11 @@ | |
| 2471 | pDecl->zExtra = 0; |
| 2472 | } |
| 2473 | |
| 2474 | /* |
| 2475 | ** Reset the DP_Forward and DP_Declared flags on all Decl structures. |
| 2476 | ** Set both flags for anything that is tagged as local and isn't |
| 2477 | ** in the file zFilename so that it won't be printing in other files. |
| 2478 | */ |
| 2479 | static void ResetDeclFlags(char *zFilename){ |
| 2480 | Decl *pDecl; |
| 2481 | |
| @@ -2574,11 +2574,11 @@ | |
| 2574 | int flag; |
| 2575 | int isCpp; /* True if generating C++ */ |
| 2576 | int doneTypedef = 0; /* True if a typedef has been done for this object */ |
| 2577 | |
| 2578 | /* printf("BEGIN %s of %s\n",needFullDecl?"FULL":"PROTOTYPE",pDecl->zName);*/ |
| 2579 | /* |
| 2580 | ** For any object that has a forward declaration, go ahead and do the |
| 2581 | ** forward declaration first. |
| 2582 | */ |
| 2583 | isCpp = (pState->flags & DP_Cplusplus) != 0; |
| 2584 | for(p=pDecl; p; p=p->pSameName){ |
| @@ -2626,12 +2626,12 @@ | |
| 2626 | ** function on a recursive call with the same pDecl. Hence, recursive |
| 2627 | ** calls to this function (through ScanText()) can never change the |
| 2628 | ** value of DP_Flag out from under us. |
| 2629 | */ |
| 2630 | for(p=pDecl; p; p=p->pSameName){ |
| 2631 | if( !DeclHasProperty(p,DP_Declared) |
| 2632 | && (p->zFwd==0 || needFullDecl) |
| 2633 | && p->zDecl!=0 |
| 2634 | ){ |
| 2635 | DeclSetProperty(p,DP_Forward|DP_Declared|DP_Flag); |
| 2636 | }else{ |
| 2637 | DeclClearProperty(p,DP_Flag); |
| @@ -2735,12 +2735,12 @@ | |
| 2735 | ** by sToken. |
| 2736 | */ |
| 2737 | pDecl = FindDecl(sToken.zText,sToken.nText); |
| 2738 | if( pDecl==0 ) continue; |
| 2739 | |
| 2740 | /* |
| 2741 | ** If we get this far, we've found an identifier that has a |
| 2742 | ** declaration in the database. Now see if we the full declaration |
| 2743 | ** or just a forward declaration. |
| 2744 | */ |
| 2745 | GetNonspaceToken(&sIn,&sNext); |
| 2746 | if( sNext.zText[0]=='*' ){ |
| @@ -2770,12 +2770,12 @@ | |
| 2770 | int progress; |
| 2771 | |
| 2772 | do{ |
| 2773 | progress = 0; |
| 2774 | for(pDecl=pDeclFirst; pDecl; pDecl=pDecl->pNext){ |
| 2775 | if( DeclHasProperty(pDecl,DP_Forward) |
| 2776 | && !DeclHasProperty(pDecl,DP_Declared) |
| 2777 | ){ |
| 2778 | DeclareObject(pDecl,pState,1); |
| 2779 | progress = 1; |
| 2780 | assert( DeclHasProperty(pDecl,DP_Declared) ); |
| 2781 | } |
| @@ -2842,11 +2842,11 @@ | |
| 2842 | nErr++; |
| 2843 | } |
| 2844 | }else if( report ){ |
| 2845 | fprintf(report,"unchanged\n"); |
| 2846 | } |
| 2847 | SafeFree(zOldVersion); |
| 2848 | IdentTableReset(&includeTable); |
| 2849 | StringReset(&outStr); |
| 2850 | return nErr; |
| 2851 | } |
| 2852 | |
| @@ -2878,11 +2878,11 @@ | |
| 2878 | } |
| 2879 | ChangeIfContext(0,&sState); |
| 2880 | printf("%s",StringGet(&outStr)); |
| 2881 | IdentTableReset(&includeTable); |
| 2882 | StringReset(&outStr); |
| 2883 | return 0; |
| 2884 | } |
| 2885 | |
| 2886 | #ifdef DEBUG |
| 2887 | /* |
| 2888 | ** Return the number of characters in the given string prior to the |
| @@ -3040,11 +3040,11 @@ | |
| 3040 | int nSrc; |
| 3041 | char *zSrc; |
| 3042 | InFile *pFile; |
| 3043 | int i; |
| 3044 | |
| 3045 | /* |
| 3046 | ** Get the name of the input file to be scanned. The input file is |
| 3047 | ** everything before the first ':' or the whole file if no ':' is seen. |
| 3048 | ** |
| 3049 | ** Except, on windows, ignore any ':' that occurs as the second character |
| 3050 | ** since it might be part of the drive specifier. So really, the ":' has |
| @@ -3099,11 +3099,11 @@ | |
| 3099 | } |
| 3100 | } |
| 3101 | |
| 3102 | /* |
| 3103 | ** If pFile->zSrc contains no 'c' or 'C' in its extension, it |
| 3104 | ** must be a header file. In that case, we need to set the |
| 3105 | ** PS_Interface flag. |
| 3106 | */ |
| 3107 | pFile->flags |= PS_Interface; |
| 3108 | for(i=nSrc-1; i>0 && zSrc[i]!='.'; i--){ |
| 3109 | if( zSrc[i]=='c' || zSrc[i]=='C' ){ |
| @@ -3110,11 +3110,11 @@ | |
| 3110 | pFile->flags &= ~PS_Interface; |
| 3111 | break; |
| 3112 | } |
| 3113 | } |
| 3114 | |
| 3115 | /* Done! |
| 3116 | */ |
| 3117 | return pFile; |
| 3118 | } |
| 3119 | |
| 3120 | /* MS-Windows and MS-DOS both have the following serious OS bug: the |
| @@ -3162,11 +3162,11 @@ | |
| 3162 | while( c!=EOF ){ |
| 3163 | while( c!=EOF && isspace(c) ){ |
| 3164 | if( c=='\n' ){ |
| 3165 | startOfLine = 1; |
| 3166 | } |
| 3167 | c = getc(in); |
| 3168 | if( startOfLine && c=='#' ){ |
| 3169 | while( c!=EOF && c!='\n' ){ |
| 3170 | c = getc(in); |
| 3171 | } |
| 3172 | } |
| @@ -3184,11 +3184,11 @@ | |
| 3184 | if( nAlloc==0 ){ |
| 3185 | nAlloc = 100 + argc; |
| 3186 | zNew = malloc( sizeof(char*) * nAlloc ); |
| 3187 | }else{ |
| 3188 | nAlloc *= 2; |
| 3189 | zNew = realloc( zNew, sizeof(char*) * nAlloc ); |
| 3190 | } |
| 3191 | } |
| 3192 | if( zNew ){ |
| 3193 | int j = nNew + index; |
| 3194 | zNew[j] = malloc( n + 1 ); |
| @@ -3254,11 +3254,11 @@ | |
| 3254 | |
| 3255 | /* |
| 3256 | ** The following text contains a few simple #defines that we want |
| 3257 | ** to be available to every file. |
| 3258 | */ |
| 3259 | static char zInit[] = |
| 3260 | "#define INTERFACE 0\n" |
| 3261 | "#define EXPORT_INTERFACE 0\n" |
| 3262 | "#define LOCAL_INTERFACE 0\n" |
| 3263 | "#define EXPORT\n" |
| 3264 | "#define LOCAL static\n" |
| 3265 |
| --- src/makeheaders.c | |
| +++ src/makeheaders.c | |
| @@ -112,19 +112,19 @@ | |
| 112 | ** |
| 113 | ** struct Xyzzy; |
| 114 | ** |
| 115 | ** Not every object has a forward declaration. If it does, thought, the |
| 116 | ** forward declaration will be contained in the zFwd field for C and |
| 117 | ** the zFwdCpp for C++. The zDecl field contains the complete |
| 118 | ** declaration text. |
| 119 | */ |
| 120 | typedef struct Decl Decl; |
| 121 | struct Decl { |
| 122 | char *zName; /* Name of the object being declared. The appearance |
| 123 | ** of this name is a source file triggers the declaration |
| 124 | ** to be added to the header for that file. */ |
| 125 | const char *zFile; /* File from which extracted. */ |
| 126 | char *zIf; /* Surround the declaration with this #if */ |
| 127 | char *zFwd; /* A forward declaration. NULL if there is none. */ |
| 128 | char *zFwdCpp; /* Use this forward declaration for C++. */ |
| 129 | char *zDecl; /* A full declaration of this object */ |
| 130 | char *zExtra; /* Extra declaration text inserted into class objects */ |
| @@ -163,11 +163,11 @@ | |
| 163 | ** in the output when using the -H option.) |
| 164 | ** |
| 165 | ** EXPORT scope The object is visible and usable everywhere. |
| 166 | ** |
| 167 | ** The DP_Flag is a temporary use flag that is used during processing to |
| 168 | ** prevent an infinite loop. It's use is localized. |
| 169 | ** |
| 170 | ** The DP_Cplusplus, DP_ExternCReqd and DP_ExternReqd flags are permanent |
| 171 | ** and are used to specify what type of declaration the object requires. |
| 172 | */ |
| 173 | #define DP_Forward 0x001 /* Has a forward declaration in this file */ |
| @@ -201,11 +201,11 @@ | |
| 201 | ** Be careful not to confuse PS_Export with DP_Export or |
| 202 | ** PS_Local with DP_Local. Their names are similar, but the meanings |
| 203 | ** of these flags are very different. |
| 204 | */ |
| 205 | #define PS_Extern 0x000800 /* "extern" has been seen */ |
| 206 | #define PS_Export 0x001000 /* If between "#if EXPORT_INTERFACE" |
| 207 | ** and "#endif" */ |
| 208 | #define PS_Export2 0x002000 /* If "EXPORT" seen */ |
| 209 | #define PS_Typedef 0x004000 /* If "typedef" has been seen */ |
| 210 | #define PS_Static 0x008000 /* If "static" has been seen */ |
| 211 | #define PS_Interface 0x010000 /* If within #if INTERFACE..#endif */ |
| @@ -231,11 +231,11 @@ | |
| 231 | #define TY_Union 0x04000000 |
| 232 | #define TY_Enumeration 0x08000000 |
| 233 | #define TY_Defunct 0x10000000 /* Used to erase a declaration */ |
| 234 | |
| 235 | /* |
| 236 | ** Each nested #if (or #ifdef or #ifndef) is stored in a stack of |
| 237 | ** instances of the following structure. |
| 238 | */ |
| 239 | typedef struct Ifmacro Ifmacro; |
| 240 | struct Ifmacro { |
| 241 | int nLine; /* Line number where this macro occurs */ |
| @@ -293,11 +293,11 @@ | |
| 293 | int flags; /* One or more DP_, PS_ and/or TY_ flags */ |
| 294 | InFile *pNext; /* Next input file in the list of them all */ |
| 295 | IdentTable idTable; /* All identifiers in this input file */ |
| 296 | }; |
| 297 | |
| 298 | /* |
| 299 | ** An unbounded string is able to grow without limit. We use these |
| 300 | ** to construct large in-memory strings from lots of smaller components. |
| 301 | */ |
| 302 | typedef struct String String; |
| 303 | struct String { |
| @@ -332,19 +332,19 @@ | |
| 332 | ** never to read a file that it generated itself. |
| 333 | ** |
| 334 | ** The "#undef INTERFACE" part is a hack to work around a name collision |
| 335 | ** in MSVC 2008. |
| 336 | */ |
| 337 | const char zTopLine[] = |
| 338 | "/* \aThis file was automatically generated. Do not edit! */\n" |
| 339 | "#undef INTERFACE\n"; |
| 340 | #define nTopLine (sizeof(zTopLine)-1) |
| 341 | |
| 342 | /* |
| 343 | ** The name of the file currently being parsed. |
| 344 | */ |
| 345 | static const char *zFilename; |
| 346 | |
| 347 | /* |
| 348 | ** The stack of #if macros for the file currently being parsed. |
| 349 | */ |
| 350 | static Ifmacro *ifStack = 0; |
| @@ -702,11 +702,11 @@ | |
| 702 | struct stat sStat; |
| 703 | FILE *pIn; |
| 704 | char *zBuf; |
| 705 | int n; |
| 706 | |
| 707 | if( stat(zFilename,&sStat)!=0 |
| 708 | #ifndef WIN32 |
| 709 | || !S_ISREG(sStat.st_mode) |
| 710 | #endif |
| 711 | ){ |
| 712 | return 0; |
| @@ -889,12 +889,12 @@ | |
| 889 | } |
| 890 | } |
| 891 | } |
| 892 | i++; |
| 893 | } |
| 894 | if( z[i] ){ |
| 895 | i += 2; |
| 896 | }else{ |
| 897 | isBlockComment = 0; |
| 898 | fprintf(stderr,"%s:%d: Unterminated comment\n", |
| 899 | zFilename, startLine); |
| 900 | nErr++; |
| @@ -906,11 +906,11 @@ | |
| 906 | pToken->eType = TT_Other; |
| 907 | pToken->nText = 1 + (z[i+1]=='+'); |
| 908 | } |
| 909 | break; |
| 910 | |
| 911 | case '0': |
| 912 | if( z[i+1]=='x' || z[i+1]=='X' ){ |
| 913 | /* A hex constant */ |
| 914 | i += 2; |
| 915 | while( isxdigit(z[i]) ){ i++; } |
| 916 | }else{ |
| @@ -963,11 +963,11 @@ | |
| 963 | while( isalnum(z[i]) || z[i]=='_' ){ i++; }; |
| 964 | pToken->eType = TT_Id; |
| 965 | pToken->nText = i - pIn->i; |
| 966 | break; |
| 967 | |
| 968 | case ':': |
| 969 | pToken->eType = TT_Other; |
| 970 | pToken->nText = 1 + (z[i+1]==':'); |
| 971 | break; |
| 972 | |
| 973 | case '=': |
| @@ -977,11 +977,11 @@ | |
| 977 | case '-': |
| 978 | case '*': |
| 979 | case '%': |
| 980 | case '^': |
| 981 | case '&': |
| 982 | case '|': |
| 983 | pToken->eType = TT_Other; |
| 984 | pToken->nText = 1 + (z[i+1]=='='); |
| 985 | break; |
| 986 | |
| 987 | default: |
| @@ -1064,11 +1064,11 @@ | |
| 1064 | } |
| 1065 | } |
| 1066 | /* NOT REACHED */ |
| 1067 | } |
| 1068 | |
| 1069 | /* |
| 1070 | ** This routine looks for identifiers (strings of contiguous alphanumeric |
| 1071 | ** characters) within a preprocessor directive and adds every such string |
| 1072 | ** found to the given identifier table |
| 1073 | */ |
| 1074 | static void FindIdentifiersInMacro(Token *pToken, IdentTable *pTable){ |
| @@ -1157,11 +1157,11 @@ | |
| 1157 | case TT_Id: |
| 1158 | if( pTable ){ |
| 1159 | IdentTableInsert(pTable,pToken->zText,pToken->nText); |
| 1160 | } |
| 1161 | break; |
| 1162 | |
| 1163 | case TT_Preprocessor: |
| 1164 | if( pTable!=0 ){ |
| 1165 | FindIdentifiersInMacro(pToken,pTable); |
| 1166 | } |
| 1167 | break; |
| @@ -1263,11 +1263,11 @@ | |
| 1263 | exit(1); |
| 1264 | } |
| 1265 | pList = TokenizeFile(zFile,&sTable); |
| 1266 | for(p=pList; p; p=p->pNext){ |
| 1267 | int j; |
| 1268 | switch( p->eType ){ |
| 1269 | case TT_Space: |
| 1270 | printf("%4d: Space\n",p->nLine); |
| 1271 | break; |
| 1272 | case TT_Id: |
| 1273 | printf("%4d: Id %.*s\n",p->nLine,p->nText,p->zText); |
| @@ -1330,11 +1330,11 @@ | |
| 1330 | needSpace = 1; |
| 1331 | break; |
| 1332 | |
| 1333 | default: |
| 1334 | c = pFirst->zText[0]; |
| 1335 | printf("%s%.*s", |
| 1336 | (needSpace && (c=='*' || c=='{')) ? " " : "", |
| 1337 | pFirst->nText, pFirst->zText); |
| 1338 | needSpace = pFirst->zText[0]==','; |
| 1339 | break; |
| 1340 | } |
| @@ -1371,13 +1371,13 @@ | |
| 1371 | |
| 1372 | StringInit(&str); |
| 1373 | pLast = pLast->pNext; |
| 1374 | while( pFirst!=pLast ){ |
| 1375 | if( pFirst==pSkip ){ iSkip = nSkip; } |
| 1376 | if( iSkip>0 ){ |
| 1377 | iSkip--; |
| 1378 | pFirst=pFirst->pNext; |
| 1379 | continue; |
| 1380 | } |
| 1381 | switch( pFirst->eType ){ |
| 1382 | case TT_Preprocessor: |
| 1383 | StringAppend(&str,"\n",1); |
| @@ -1384,13 +1384,13 @@ | |
| 1384 | StringAppend(&str,pFirst->zText,pFirst->nText); |
| 1385 | StringAppend(&str,"\n",1); |
| 1386 | needSpace = 0; |
| 1387 | break; |
| 1388 | |
| 1389 | case TT_Id: |
| 1390 | switch( pFirst->zText[0] ){ |
| 1391 | case 'E': |
| 1392 | if( pFirst->nText==6 && strncmp(pFirst->zText,"EXPORT",6)==0 ){ |
| 1393 | skipOne = 1; |
| 1394 | } |
| 1395 | break; |
| 1396 | case 'P': |
| @@ -1645,17 +1645,17 @@ | |
| 1645 | pLast = pLast->pNext; |
| 1646 | for(p=pFirst; p && p!=pLast; p=p->pNext){ |
| 1647 | if( p->eType==TT_Id ){ |
| 1648 | static IdentTable sReserved; |
| 1649 | static int isInit = 0; |
| 1650 | static const char *aWords[] = { "char", "class", |
| 1651 | "const", "double", "enum", "extern", "EXPORT", "ET_PROC", |
| 1652 | "float", "int", "long", |
| 1653 | "PRIVATE", "PROTECTED", "PUBLIC", |
| 1654 | "register", "static", "struct", "sizeof", "signed", "typedef", |
| 1655 | "union", "volatile", "virtual", "void", }; |
| 1656 | |
| 1657 | if( !isInit ){ |
| 1658 | int i; |
| 1659 | for(i=0; i<sizeof(aWords)/sizeof(aWords[0]); i++){ |
| 1660 | IdentTableInsert(&sReserved,aWords[i],0); |
| 1661 | } |
| @@ -1768,11 +1768,11 @@ | |
| 1768 | pCode = pLast; |
| 1769 | while( pLast && pLast!=pFirst && pLast->zText[0]!=')' ){ |
| 1770 | pLast = pLast->pPrev; |
| 1771 | } |
| 1772 | if( pLast==0 || pLast==pFirst || pFirst->pNext==pLast ){ |
| 1773 | fprintf(stderr,"%s:%d: Unrecognized syntax.\n", |
| 1774 | zFilename, pFirst->nLine); |
| 1775 | return 1; |
| 1776 | } |
| 1777 | if( flags & (PS_Interface|PS_Export|PS_Local) ){ |
| 1778 | fprintf(stderr,"%s:%d: Missing \"inline\" on function or procedure.\n", |
| @@ -1849,11 +1849,11 @@ | |
| 1849 | return 1; |
| 1850 | } |
| 1851 | |
| 1852 | #ifdef DEBUG |
| 1853 | if( debugMask & PARSER ){ |
| 1854 | printf("**** Found inline routine: %.*s on line %d...\n", |
| 1855 | pName->nText, pName->zText, pFirst->nLine); |
| 1856 | PrintTokens(pFirst,pEnd); |
| 1857 | printf("\n"); |
| 1858 | } |
| 1859 | #endif |
| @@ -1888,11 +1888,11 @@ | |
| 1888 | ** to search for an occurrence of an ID followed immediately by '('. |
| 1889 | ** If found, we have a prototype. Otherwise we are dealing with a |
| 1890 | ** variable definition. |
| 1891 | */ |
| 1892 | static int isVariableDef(Token *pFirst, Token *pEnd){ |
| 1893 | if( pEnd && pEnd->zText[0]=='=' && |
| 1894 | (pEnd->pPrev->nText!=8 || strncmp(pEnd->pPrev->zText,"operator",8)!=0) |
| 1895 | ){ |
| 1896 | return 1; |
| 1897 | } |
| 1898 | while( pFirst && pFirst!=pEnd && pFirst->pNext && pFirst->pNext!=pEnd ){ |
| @@ -1949,11 +1949,11 @@ | |
| 1949 | } |
| 1950 | while( pFirst!=0 && pFirst->pNext!=pEnd && |
| 1951 | ((pFirst->nText==6 && strncmp(pFirst->zText,"static",6)==0) |
| 1952 | || (pFirst->nText==5 && strncmp(pFirst->zText,"LOCAL",6)==0)) |
| 1953 | ){ |
| 1954 | /* Lose the initial "static" or local from local variables. |
| 1955 | ** We'll prepend "extern" later. */ |
| 1956 | pFirst = pFirst->pNext; |
| 1957 | isLocal = 1; |
| 1958 | } |
| 1959 | if( pFirst==0 || !isLocal ){ |
| @@ -1962,11 +1962,11 @@ | |
| 1962 | }else if( flags & PS_Method ){ |
| 1963 | /* Methods are declared by their class. Don't declare separately. */ |
| 1964 | return nErr; |
| 1965 | } |
| 1966 | isVar = (flags & (PS_Typedef|PS_Method))==0 && isVariableDef(pFirst,pEnd); |
| 1967 | if( isVar && (flags & (PS_Interface|PS_Export|PS_Local))!=0 |
| 1968 | && (flags & PS_Extern)==0 ){ |
| 1969 | fprintf(stderr,"%s:%d: Can't define a variable in this context\n", |
| 1970 | zFilename, pFirst->nLine); |
| 1971 | nErr++; |
| 1972 | } |
| @@ -2095,11 +2095,11 @@ | |
| 2095 | nCmd++; |
| 2096 | } |
| 2097 | |
| 2098 | if( nCmd==5 && strncmp(zCmd,"endif",5)==0 ){ |
| 2099 | /* |
| 2100 | ** Pop the if stack |
| 2101 | */ |
| 2102 | pIf = ifStack; |
| 2103 | if( pIf==0 ){ |
| 2104 | fprintf(stderr,"%s:%d: extra '#endif'.\n",zFilename,pToken->nLine); |
| 2105 | return 1; |
| @@ -2106,11 +2106,11 @@ | |
| 2106 | } |
| 2107 | ifStack = pIf->pNext; |
| 2108 | SafeFree(pIf); |
| 2109 | }else if( nCmd==6 && strncmp(zCmd,"define",6)==0 ){ |
| 2110 | /* |
| 2111 | ** Record a #define if we are in PS_Interface or PS_Export |
| 2112 | */ |
| 2113 | Decl *pDecl; |
| 2114 | if( !(flags & (PS_Local|PS_Interface|PS_Export)) ){ return 0; } |
| 2115 | zArg = &zCmd[6]; |
| 2116 | while( *zArg && isspace(*zArg) && *zArg!='\n' ){ |
| @@ -2129,11 +2129,11 @@ | |
| 2129 | }else if( flags & PS_Local ){ |
| 2130 | DeclSetProperty(pDecl,DP_Local); |
| 2131 | } |
| 2132 | }else if( nCmd==7 && strncmp(zCmd,"include",7)==0 ){ |
| 2133 | /* |
| 2134 | ** Record an #include if we are in PS_Interface or PS_Export |
| 2135 | */ |
| 2136 | Include *pInclude; |
| 2137 | char *zIf; |
| 2138 | |
| 2139 | if( !(flags & (PS_Interface|PS_Export)) ){ return 0; } |
| @@ -2184,11 +2184,11 @@ | |
| 2184 | PushIfMacro(0,0,0,pToken->nLine,PS_Local); |
| 2185 | }else{ |
| 2186 | PushIfMacro(0,zArg,nArg,pToken->nLine,0); |
| 2187 | } |
| 2188 | }else if( nCmd==5 && strncmp(zCmd,"ifdef",5)==0 ){ |
| 2189 | /* |
| 2190 | ** Push an #ifdef. |
| 2191 | */ |
| 2192 | zArg = &zCmd[5]; |
| 2193 | while( *zArg && isspace(*zArg) && *zArg!='\n' ){ |
| 2194 | zArg++; |
| @@ -2207,11 +2207,11 @@ | |
| 2207 | if( *zArg==0 || *zArg=='\n' ){ return 0; } |
| 2208 | nArg = pToken->nText + (int)(pToken->zText - zArg); |
| 2209 | PushIfMacro("!defined",zArg,nArg,pToken->nLine,0); |
| 2210 | }else if( nCmd==4 && strncmp(zCmd,"else",4)==0 ){ |
| 2211 | /* |
| 2212 | ** Invert the #if on the top of the stack |
| 2213 | */ |
| 2214 | if( ifStack==0 ){ |
| 2215 | fprintf(stderr,"%s:%d: '#else' without an '#if'\n",zFilename, |
| 2216 | pToken->nLine); |
| 2217 | return 1; |
| @@ -2224,33 +2224,33 @@ | |
| 2224 | }else{ |
| 2225 | pIf->flags = 0; |
| 2226 | } |
| 2227 | }else{ |
| 2228 | /* |
| 2229 | ** This directive can be safely ignored |
| 2230 | */ |
| 2231 | return 0; |
| 2232 | } |
| 2233 | |
| 2234 | /* |
| 2235 | ** Recompute the preset flags |
| 2236 | */ |
| 2237 | *pPresetFlags = 0; |
| 2238 | for(pIf = ifStack; pIf; pIf=pIf->pNext){ |
| 2239 | *pPresetFlags |= pIf->flags; |
| 2240 | } |
| 2241 | |
| 2242 | return nErr; |
| 2243 | } |
| 2244 | |
| 2245 | /* |
| 2246 | ** Parse an entire file. Return the number of errors. |
| 2247 | ** |
| 2248 | ** pList is a list of tokens in the file. Whitespace tokens have been |
| 2249 | ** eliminated, and text with {...} has been collapsed into a |
| 2250 | ** single TT_Brace token. |
| 2251 | ** |
| 2252 | ** initFlags are a set of parse flags that should always be set for this |
| 2253 | ** file. For .c files this is normally 0. For .h files it is PS_Interface. |
| 2254 | */ |
| 2255 | static int ParseFile(Token *pList, int initFlags){ |
| 2256 | int nErr = 0; |
| @@ -2279,11 +2279,11 @@ | |
| 2279 | pStart = 0; |
| 2280 | flags = presetFlags; |
| 2281 | break; |
| 2282 | |
| 2283 | case '=': |
| 2284 | if( pList->pPrev->nText==8 |
| 2285 | && strncmp(pList->pPrev->zText,"operator",8)==0 ){ |
| 2286 | break; |
| 2287 | } |
| 2288 | nErr += ProcessDecl(pStart,pList,flags); |
| 2289 | pStart = 0; |
| @@ -2471,11 +2471,11 @@ | |
| 2471 | pDecl->zExtra = 0; |
| 2472 | } |
| 2473 | |
| 2474 | /* |
| 2475 | ** Reset the DP_Forward and DP_Declared flags on all Decl structures. |
| 2476 | ** Set both flags for anything that is tagged as local and isn't |
| 2477 | ** in the file zFilename so that it won't be printing in other files. |
| 2478 | */ |
| 2479 | static void ResetDeclFlags(char *zFilename){ |
| 2480 | Decl *pDecl; |
| 2481 | |
| @@ -2574,11 +2574,11 @@ | |
| 2574 | int flag; |
| 2575 | int isCpp; /* True if generating C++ */ |
| 2576 | int doneTypedef = 0; /* True if a typedef has been done for this object */ |
| 2577 | |
| 2578 | /* printf("BEGIN %s of %s\n",needFullDecl?"FULL":"PROTOTYPE",pDecl->zName);*/ |
| 2579 | /* |
| 2580 | ** For any object that has a forward declaration, go ahead and do the |
| 2581 | ** forward declaration first. |
| 2582 | */ |
| 2583 | isCpp = (pState->flags & DP_Cplusplus) != 0; |
| 2584 | for(p=pDecl; p; p=p->pSameName){ |
| @@ -2626,12 +2626,12 @@ | |
| 2626 | ** function on a recursive call with the same pDecl. Hence, recursive |
| 2627 | ** calls to this function (through ScanText()) can never change the |
| 2628 | ** value of DP_Flag out from under us. |
| 2629 | */ |
| 2630 | for(p=pDecl; p; p=p->pSameName){ |
| 2631 | if( !DeclHasProperty(p,DP_Declared) |
| 2632 | && (p->zFwd==0 || needFullDecl) |
| 2633 | && p->zDecl!=0 |
| 2634 | ){ |
| 2635 | DeclSetProperty(p,DP_Forward|DP_Declared|DP_Flag); |
| 2636 | }else{ |
| 2637 | DeclClearProperty(p,DP_Flag); |
| @@ -2735,12 +2735,12 @@ | |
| 2735 | ** by sToken. |
| 2736 | */ |
| 2737 | pDecl = FindDecl(sToken.zText,sToken.nText); |
| 2738 | if( pDecl==0 ) continue; |
| 2739 | |
| 2740 | /* |
| 2741 | ** If we get this far, we've found an identifier that has a |
| 2742 | ** declaration in the database. Now see if we the full declaration |
| 2743 | ** or just a forward declaration. |
| 2744 | */ |
| 2745 | GetNonspaceToken(&sIn,&sNext); |
| 2746 | if( sNext.zText[0]=='*' ){ |
| @@ -2770,12 +2770,12 @@ | |
| 2770 | int progress; |
| 2771 | |
| 2772 | do{ |
| 2773 | progress = 0; |
| 2774 | for(pDecl=pDeclFirst; pDecl; pDecl=pDecl->pNext){ |
| 2775 | if( DeclHasProperty(pDecl,DP_Forward) |
| 2776 | && !DeclHasProperty(pDecl,DP_Declared) |
| 2777 | ){ |
| 2778 | DeclareObject(pDecl,pState,1); |
| 2779 | progress = 1; |
| 2780 | assert( DeclHasProperty(pDecl,DP_Declared) ); |
| 2781 | } |
| @@ -2842,11 +2842,11 @@ | |
| 2842 | nErr++; |
| 2843 | } |
| 2844 | }else if( report ){ |
| 2845 | fprintf(report,"unchanged\n"); |
| 2846 | } |
| 2847 | SafeFree(zOldVersion); |
| 2848 | IdentTableReset(&includeTable); |
| 2849 | StringReset(&outStr); |
| 2850 | return nErr; |
| 2851 | } |
| 2852 | |
| @@ -2878,11 +2878,11 @@ | |
| 2878 | } |
| 2879 | ChangeIfContext(0,&sState); |
| 2880 | printf("%s",StringGet(&outStr)); |
| 2881 | IdentTableReset(&includeTable); |
| 2882 | StringReset(&outStr); |
| 2883 | return 0; |
| 2884 | } |
| 2885 | |
| 2886 | #ifdef DEBUG |
| 2887 | /* |
| 2888 | ** Return the number of characters in the given string prior to the |
| @@ -3040,11 +3040,11 @@ | |
| 3040 | int nSrc; |
| 3041 | char *zSrc; |
| 3042 | InFile *pFile; |
| 3043 | int i; |
| 3044 | |
| 3045 | /* |
| 3046 | ** Get the name of the input file to be scanned. The input file is |
| 3047 | ** everything before the first ':' or the whole file if no ':' is seen. |
| 3048 | ** |
| 3049 | ** Except, on windows, ignore any ':' that occurs as the second character |
| 3050 | ** since it might be part of the drive specifier. So really, the ":' has |
| @@ -3099,11 +3099,11 @@ | |
| 3099 | } |
| 3100 | } |
| 3101 | |
| 3102 | /* |
| 3103 | ** If pFile->zSrc contains no 'c' or 'C' in its extension, it |
| 3104 | ** must be a header file. In that case, we need to set the |
| 3105 | ** PS_Interface flag. |
| 3106 | */ |
| 3107 | pFile->flags |= PS_Interface; |
| 3108 | for(i=nSrc-1; i>0 && zSrc[i]!='.'; i--){ |
| 3109 | if( zSrc[i]=='c' || zSrc[i]=='C' ){ |
| @@ -3110,11 +3110,11 @@ | |
| 3110 | pFile->flags &= ~PS_Interface; |
| 3111 | break; |
| 3112 | } |
| 3113 | } |
| 3114 | |
| 3115 | /* Done! |
| 3116 | */ |
| 3117 | return pFile; |
| 3118 | } |
| 3119 | |
| 3120 | /* MS-Windows and MS-DOS both have the following serious OS bug: the |
| @@ -3162,11 +3162,11 @@ | |
| 3162 | while( c!=EOF ){ |
| 3163 | while( c!=EOF && isspace(c) ){ |
| 3164 | if( c=='\n' ){ |
| 3165 | startOfLine = 1; |
| 3166 | } |
| 3167 | c = getc(in); |
| 3168 | if( startOfLine && c=='#' ){ |
| 3169 | while( c!=EOF && c!='\n' ){ |
| 3170 | c = getc(in); |
| 3171 | } |
| 3172 | } |
| @@ -3184,11 +3184,11 @@ | |
| 3184 | if( nAlloc==0 ){ |
| 3185 | nAlloc = 100 + argc; |
| 3186 | zNew = malloc( sizeof(char*) * nAlloc ); |
| 3187 | }else{ |
| 3188 | nAlloc *= 2; |
| 3189 | zNew = realloc( zNew, sizeof(char*) * nAlloc ); |
| 3190 | } |
| 3191 | } |
| 3192 | if( zNew ){ |
| 3193 | int j = nNew + index; |
| 3194 | zNew[j] = malloc( n + 1 ); |
| @@ -3254,11 +3254,11 @@ | |
| 3254 | |
| 3255 | /* |
| 3256 | ** The following text contains a few simple #defines that we want |
| 3257 | ** to be available to every file. |
| 3258 | */ |
| 3259 | static const char zInit[] = |
| 3260 | "#define INTERFACE 0\n" |
| 3261 | "#define EXPORT_INTERFACE 0\n" |
| 3262 | "#define LOCAL_INTERFACE 0\n" |
| 3263 | "#define EXPORT\n" |
| 3264 | "#define LOCAL static\n" |
| 3265 |
+15
-4
| --- src/makemake.tcl | ||
| +++ src/makemake.tcl | ||
| @@ -1,8 +1,8 @@ | ||
| 1 | 1 | #!/usr/bin/tclsh |
| 2 | 2 | # |
| 3 | -# Run this TCL script to generate the various makefiles for a variety | |
| 3 | +# Run this Tcl script to generate the various makefiles for a variety | |
| 4 | 4 | # of platforms. Files generated include: |
| 5 | 5 | # |
| 6 | 6 | # src/main.mk # makefile for all unix systems |
| 7 | 7 | # win/Makefile.mingw # makefile for mingw on windows |
| 8 | 8 | # win/Makefile.* # makefiles for other windows compilers |
| @@ -142,10 +142,11 @@ | ||
| 142 | 142 | |
| 143 | 143 | # Additional resource files that get built into the executable. |
| 144 | 144 | # |
| 145 | 145 | set extra_files { |
| 146 | 146 | diff.tcl |
| 147 | + ../skins/*/*.txt | |
| 147 | 148 | } |
| 148 | 149 | |
| 149 | 150 | # Options used to compile the included SQLite library. |
| 150 | 151 | # |
| 151 | 152 | set SQLITE_OPTIONS { |
| @@ -203,10 +204,19 @@ | ||
| 203 | 204 | } |
| 204 | 205 | |
| 205 | 206 | # STOP HERE. |
| 206 | 207 | # Unless the build procedures changes, you should not have to edit anything |
| 207 | 208 | # below this line. |
| 209 | + | |
| 210 | +# Expand any wildcards in "extra_files" | |
| 211 | +set new_extra_files {} | |
| 212 | +foreach file $extra_files { | |
| 213 | + foreach x [glob -nocomplain $file] { | |
| 214 | + lappend new_extra_files $x | |
| 215 | + } | |
| 216 | +} | |
| 217 | +set extra_files $new_extra_files | |
| 208 | 218 | |
| 209 | 219 | ############################################################################## |
| 210 | 220 | ############################################################################## |
| 211 | 221 | ############################################################################## |
| 212 | 222 | # Start by generating the "main.mk" makefile used for all unix systems. |
| @@ -573,12 +583,13 @@ | ||
| 573 | 583 | #### The directories where the OpenSSL include and library files are located. |
| 574 | 584 | # The recommended usage here is to use the Sysinternals junction tool |
| 575 | 585 | # to create a hard link between an "openssl-1.x" sub-directory of the |
| 576 | 586 | # Fossil source code directory and the target OpenSSL source directory. |
| 577 | 587 | # |
| 578 | -OPENSSLINCDIR = $(SRCDIR)/../compat/openssl-1.0.1k/include | |
| 579 | -OPENSSLLIBDIR = $(SRCDIR)/../compat/openssl-1.0.1k | |
| 588 | +OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.1l | |
| 589 | +OPENSSLINCDIR = $(OPENSSLDIR)/include | |
| 590 | +OPENSSLLIBDIR = $(OPENSSLDIR) | |
| 580 | 591 | |
| 581 | 592 | #### Either the directory where the Tcl library is installed or the Tcl |
| 582 | 593 | # source code directory resides (depending on the value of the macro |
| 583 | 594 | # FOSSIL_TCL_SOURCE). If this points to the Tcl install directory, |
| 584 | 595 | # this directory must have "include" and "lib" sub-directories. If |
| @@ -1305,11 +1316,11 @@ | ||
| 1305 | 1316 | |
| 1306 | 1317 | # Uncomment to enable Tcl support |
| 1307 | 1318 | # FOSSIL_ENABLE_TCL = 1 |
| 1308 | 1319 | |
| 1309 | 1320 | !ifdef FOSSIL_ENABLE_SSL |
| 1310 | -SSLDIR = $(B)\compat\openssl-1.0.1k | |
| 1321 | +SSLDIR = $(B)\compat\openssl-1.0.1l | |
| 1311 | 1322 | SSLINCDIR = $(SSLDIR)\inc32 |
| 1312 | 1323 | SSLLIBDIR = $(SSLDIR)\out32 |
| 1313 | 1324 | SSLLFLAGS = /nologo /opt:ref /debug |
| 1314 | 1325 | SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib |
| 1315 | 1326 | !if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64" |
| 1316 | 1327 |
| --- src/makemake.tcl | |
| +++ src/makemake.tcl | |
| @@ -1,8 +1,8 @@ | |
| 1 | #!/usr/bin/tclsh |
| 2 | # |
| 3 | # Run this TCL script to generate the various makefiles for a variety |
| 4 | # of platforms. Files generated include: |
| 5 | # |
| 6 | # src/main.mk # makefile for all unix systems |
| 7 | # win/Makefile.mingw # makefile for mingw on windows |
| 8 | # win/Makefile.* # makefiles for other windows compilers |
| @@ -142,10 +142,11 @@ | |
| 142 | |
| 143 | # Additional resource files that get built into the executable. |
| 144 | # |
| 145 | set extra_files { |
| 146 | diff.tcl |
| 147 | } |
| 148 | |
| 149 | # Options used to compile the included SQLite library. |
| 150 | # |
| 151 | set SQLITE_OPTIONS { |
| @@ -203,10 +204,19 @@ | |
| 203 | } |
| 204 | |
| 205 | # STOP HERE. |
| 206 | # Unless the build procedures changes, you should not have to edit anything |
| 207 | # below this line. |
| 208 | |
| 209 | ############################################################################## |
| 210 | ############################################################################## |
| 211 | ############################################################################## |
| 212 | # Start by generating the "main.mk" makefile used for all unix systems. |
| @@ -573,12 +583,13 @@ | |
| 573 | #### The directories where the OpenSSL include and library files are located. |
| 574 | # The recommended usage here is to use the Sysinternals junction tool |
| 575 | # to create a hard link between an "openssl-1.x" sub-directory of the |
| 576 | # Fossil source code directory and the target OpenSSL source directory. |
| 577 | # |
| 578 | OPENSSLINCDIR = $(SRCDIR)/../compat/openssl-1.0.1k/include |
| 579 | OPENSSLLIBDIR = $(SRCDIR)/../compat/openssl-1.0.1k |
| 580 | |
| 581 | #### Either the directory where the Tcl library is installed or the Tcl |
| 582 | # source code directory resides (depending on the value of the macro |
| 583 | # FOSSIL_TCL_SOURCE). If this points to the Tcl install directory, |
| 584 | # this directory must have "include" and "lib" sub-directories. If |
| @@ -1305,11 +1316,11 @@ | |
| 1305 | |
| 1306 | # Uncomment to enable Tcl support |
| 1307 | # FOSSIL_ENABLE_TCL = 1 |
| 1308 | |
| 1309 | !ifdef FOSSIL_ENABLE_SSL |
| 1310 | SSLDIR = $(B)\compat\openssl-1.0.1k |
| 1311 | SSLINCDIR = $(SSLDIR)\inc32 |
| 1312 | SSLLIBDIR = $(SSLDIR)\out32 |
| 1313 | SSLLFLAGS = /nologo /opt:ref /debug |
| 1314 | SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib |
| 1315 | !if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64" |
| 1316 |
| --- src/makemake.tcl | |
| +++ src/makemake.tcl | |
| @@ -1,8 +1,8 @@ | |
| 1 | #!/usr/bin/tclsh |
| 2 | # |
| 3 | # Run this Tcl script to generate the various makefiles for a variety |
| 4 | # of platforms. Files generated include: |
| 5 | # |
| 6 | # src/main.mk # makefile for all unix systems |
| 7 | # win/Makefile.mingw # makefile for mingw on windows |
| 8 | # win/Makefile.* # makefiles for other windows compilers |
| @@ -142,10 +142,11 @@ | |
| 142 | |
| 143 | # Additional resource files that get built into the executable. |
| 144 | # |
| 145 | set extra_files { |
| 146 | diff.tcl |
| 147 | ../skins/*/*.txt |
| 148 | } |
| 149 | |
| 150 | # Options used to compile the included SQLite library. |
| 151 | # |
| 152 | set SQLITE_OPTIONS { |
| @@ -203,10 +204,19 @@ | |
| 204 | } |
| 205 | |
| 206 | # STOP HERE. |
| 207 | # Unless the build procedures changes, you should not have to edit anything |
| 208 | # below this line. |
| 209 | |
| 210 | # Expand any wildcards in "extra_files" |
| 211 | set new_extra_files {} |
| 212 | foreach file $extra_files { |
| 213 | foreach x [glob -nocomplain $file] { |
| 214 | lappend new_extra_files $x |
| 215 | } |
| 216 | } |
| 217 | set extra_files $new_extra_files |
| 218 | |
| 219 | ############################################################################## |
| 220 | ############################################################################## |
| 221 | ############################################################################## |
| 222 | # Start by generating the "main.mk" makefile used for all unix systems. |
| @@ -573,12 +583,13 @@ | |
| 583 | #### The directories where the OpenSSL include and library files are located. |
| 584 | # The recommended usage here is to use the Sysinternals junction tool |
| 585 | # to create a hard link between an "openssl-1.x" sub-directory of the |
| 586 | # Fossil source code directory and the target OpenSSL source directory. |
| 587 | # |
| 588 | OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.1l |
| 589 | OPENSSLINCDIR = $(OPENSSLDIR)/include |
| 590 | OPENSSLLIBDIR = $(OPENSSLDIR) |
| 591 | |
| 592 | #### Either the directory where the Tcl library is installed or the Tcl |
| 593 | # source code directory resides (depending on the value of the macro |
| 594 | # FOSSIL_TCL_SOURCE). If this points to the Tcl install directory, |
| 595 | # this directory must have "include" and "lib" sub-directories. If |
| @@ -1305,11 +1316,11 @@ | |
| 1316 | |
| 1317 | # Uncomment to enable Tcl support |
| 1318 | # FOSSIL_ENABLE_TCL = 1 |
| 1319 | |
| 1320 | !ifdef FOSSIL_ENABLE_SSL |
| 1321 | SSLDIR = $(B)\compat\openssl-1.0.1l |
| 1322 | SSLINCDIR = $(SSLDIR)\inc32 |
| 1323 | SSLLIBDIR = $(SSLDIR)\out32 |
| 1324 | SSLLFLAGS = /nologo /opt:ref /debug |
| 1325 | SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib |
| 1326 | !if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64" |
| 1327 |
+27
-7
| --- src/mkbuiltin.c | ||
| +++ src/mkbuiltin.c | ||
| @@ -29,11 +29,11 @@ | ||
| 29 | 29 | #include <string.h> |
| 30 | 30 | |
| 31 | 31 | |
| 32 | 32 | /* |
| 33 | 33 | ** Read the entire content of the file named zFilename into memory obtained |
| 34 | -** from malloc() and retur a pointer to that memory. Write the size of the | |
| 34 | +** from malloc() and return a pointer to that memory. Write the size of the | |
| 35 | 35 | ** file into *pnByte. |
| 36 | 36 | */ |
| 37 | 37 | static unsigned char *read_file(const char *zFilename, int *pnByte){ |
| 38 | 38 | FILE *in; |
| 39 | 39 | unsigned char *z; |
| @@ -62,10 +62,11 @@ | ||
| 62 | 62 | */ |
| 63 | 63 | typedef struct Resource Resource; |
| 64 | 64 | struct Resource { |
| 65 | 65 | const char *zName; |
| 66 | 66 | int nByte; |
| 67 | + int idx; | |
| 67 | 68 | }; |
| 68 | 69 | |
| 69 | 70 | /* |
| 70 | 71 | ** Compare two Resource objects for sorting purposes. They sort |
| 71 | 72 | ** in zName order so that Fossil can search for resources using |
| @@ -82,10 +83,11 @@ | ||
| 82 | 83 | int j, n; |
| 83 | 84 | Resource *aRes; |
| 84 | 85 | int nRes = argc-1; |
| 85 | 86 | unsigned char *pData; |
| 86 | 87 | int nErr = 0; |
| 88 | + int nSkip; | |
| 87 | 89 | |
| 88 | 90 | aRes = malloc( nRes*sizeof(aRes[0]) ); |
| 89 | 91 | if( aRes==0 ){ |
| 90 | 92 | fprintf(stderr, "malloc failed\n"); |
| 91 | 93 | return 1; |
| @@ -103,15 +105,24 @@ | ||
| 103 | 105 | if( pData==0 ){ |
| 104 | 106 | fprintf(stderr, "Cannot open file [%s]\n", aRes[i].zName); |
| 105 | 107 | nErr++; |
| 106 | 108 | continue; |
| 107 | 109 | } |
| 108 | - aRes[i].nByte = sz; | |
| 110 | + | |
| 111 | + /* Skip initial lines beginning with # */ | |
| 112 | + nSkip = 0; | |
| 113 | + while( pData[nSkip]=='#' ){ | |
| 114 | + while( pData[nSkip]!=0 && pData[nSkip]!='\n' ){ nSkip++; } | |
| 115 | + if( pData[nSkip]=='\n' ) nSkip++; | |
| 116 | + } | |
| 117 | + | |
| 118 | + aRes[i].nByte = sz - nSkip; | |
| 119 | + aRes[i].idx = i; | |
| 109 | 120 | printf("/* Content of file %s */\n", aRes[i].zName); |
| 110 | 121 | printf("static const unsigned char bidata%d[%d] = {\n ", |
| 111 | - i, sz+1); | |
| 112 | - for(j=n=0; j<=sz; j++){ | |
| 122 | + i, sz+1-nSkip); | |
| 123 | + for(j=nSkip, n=0; j<=sz; j++){ | |
| 113 | 124 | printf("%3d", pData[j]); |
| 114 | 125 | if( j==sz ){ |
| 115 | 126 | printf(" };\n"); |
| 116 | 127 | }else if( n==14 ){ |
| 117 | 128 | printf(",\n "); |
| @@ -129,17 +140,26 @@ | ||
| 129 | 140 | printf(" const unsigned char *pData;\n"); |
| 130 | 141 | printf(" int nByte;\n"); |
| 131 | 142 | printf("};\n"); |
| 132 | 143 | printf("static const BuiltinFileTable aBuiltinFiles[] = {\n"); |
| 133 | 144 | for(i=0; i<nRes; i++){ |
| 134 | - const char *zTail; | |
| 135 | 145 | const char *z = aRes[i].zName; |
| 146 | + const char *zTail; | |
| 147 | + int nSlash = 0; | |
| 136 | 148 | zTail = z; |
| 137 | 149 | while( z && z[0] ){ |
| 138 | - if( z[0]=='/' || z[0]=='\\' ) zTail = &z[1]; | |
| 150 | + if( z[0]=='/' || z[0]=='\\' ){ | |
| 151 | + nSlash++; | |
| 152 | + if( nSlash<=2 || z[-1]=='.' ) zTail = &z[1]; | |
| 153 | + } | |
| 139 | 154 | z++; |
| 140 | 155 | } |
| 141 | - printf(" { \"%s\", bidata%d, %d },\n", zTail, i, aRes[i].nByte); | |
| 156 | + aRes[i].zName = zTail; | |
| 157 | + } | |
| 158 | + qsort(aRes, nRes, sizeof(aRes[0]), compareResource); | |
| 159 | + for(i=0; i<nRes; i++){ | |
| 160 | + printf(" { \"%s\", bidata%d, %d },\n", | |
| 161 | + aRes[i].zName, aRes[i].idx, aRes[i].nByte); | |
| 142 | 162 | } |
| 143 | 163 | printf("};\n"); |
| 144 | 164 | return nErr; |
| 145 | 165 | } |
| 146 | 166 |
| --- src/mkbuiltin.c | |
| +++ src/mkbuiltin.c | |
| @@ -29,11 +29,11 @@ | |
| 29 | #include <string.h> |
| 30 | |
| 31 | |
| 32 | /* |
| 33 | ** Read the entire content of the file named zFilename into memory obtained |
| 34 | ** from malloc() and retur a pointer to that memory. Write the size of the |
| 35 | ** file into *pnByte. |
| 36 | */ |
| 37 | static unsigned char *read_file(const char *zFilename, int *pnByte){ |
| 38 | FILE *in; |
| 39 | unsigned char *z; |
| @@ -62,10 +62,11 @@ | |
| 62 | */ |
| 63 | typedef struct Resource Resource; |
| 64 | struct Resource { |
| 65 | const char *zName; |
| 66 | int nByte; |
| 67 | }; |
| 68 | |
| 69 | /* |
| 70 | ** Compare two Resource objects for sorting purposes. They sort |
| 71 | ** in zName order so that Fossil can search for resources using |
| @@ -82,10 +83,11 @@ | |
| 82 | int j, n; |
| 83 | Resource *aRes; |
| 84 | int nRes = argc-1; |
| 85 | unsigned char *pData; |
| 86 | int nErr = 0; |
| 87 | |
| 88 | aRes = malloc( nRes*sizeof(aRes[0]) ); |
| 89 | if( aRes==0 ){ |
| 90 | fprintf(stderr, "malloc failed\n"); |
| 91 | return 1; |
| @@ -103,15 +105,24 @@ | |
| 103 | if( pData==0 ){ |
| 104 | fprintf(stderr, "Cannot open file [%s]\n", aRes[i].zName); |
| 105 | nErr++; |
| 106 | continue; |
| 107 | } |
| 108 | aRes[i].nByte = sz; |
| 109 | printf("/* Content of file %s */\n", aRes[i].zName); |
| 110 | printf("static const unsigned char bidata%d[%d] = {\n ", |
| 111 | i, sz+1); |
| 112 | for(j=n=0; j<=sz; j++){ |
| 113 | printf("%3d", pData[j]); |
| 114 | if( j==sz ){ |
| 115 | printf(" };\n"); |
| 116 | }else if( n==14 ){ |
| 117 | printf(",\n "); |
| @@ -129,17 +140,26 @@ | |
| 129 | printf(" const unsigned char *pData;\n"); |
| 130 | printf(" int nByte;\n"); |
| 131 | printf("};\n"); |
| 132 | printf("static const BuiltinFileTable aBuiltinFiles[] = {\n"); |
| 133 | for(i=0; i<nRes; i++){ |
| 134 | const char *zTail; |
| 135 | const char *z = aRes[i].zName; |
| 136 | zTail = z; |
| 137 | while( z && z[0] ){ |
| 138 | if( z[0]=='/' || z[0]=='\\' ) zTail = &z[1]; |
| 139 | z++; |
| 140 | } |
| 141 | printf(" { \"%s\", bidata%d, %d },\n", zTail, i, aRes[i].nByte); |
| 142 | } |
| 143 | printf("};\n"); |
| 144 | return nErr; |
| 145 | } |
| 146 |
| --- src/mkbuiltin.c | |
| +++ src/mkbuiltin.c | |
| @@ -29,11 +29,11 @@ | |
| 29 | #include <string.h> |
| 30 | |
| 31 | |
| 32 | /* |
| 33 | ** Read the entire content of the file named zFilename into memory obtained |
| 34 | ** from malloc() and return a pointer to that memory. Write the size of the |
| 35 | ** file into *pnByte. |
| 36 | */ |
| 37 | static unsigned char *read_file(const char *zFilename, int *pnByte){ |
| 38 | FILE *in; |
| 39 | unsigned char *z; |
| @@ -62,10 +62,11 @@ | |
| 62 | */ |
| 63 | typedef struct Resource Resource; |
| 64 | struct Resource { |
| 65 | const char *zName; |
| 66 | int nByte; |
| 67 | int idx; |
| 68 | }; |
| 69 | |
| 70 | /* |
| 71 | ** Compare two Resource objects for sorting purposes. They sort |
| 72 | ** in zName order so that Fossil can search for resources using |
| @@ -82,10 +83,11 @@ | |
| 83 | int j, n; |
| 84 | Resource *aRes; |
| 85 | int nRes = argc-1; |
| 86 | unsigned char *pData; |
| 87 | int nErr = 0; |
| 88 | int nSkip; |
| 89 | |
| 90 | aRes = malloc( nRes*sizeof(aRes[0]) ); |
| 91 | if( aRes==0 ){ |
| 92 | fprintf(stderr, "malloc failed\n"); |
| 93 | return 1; |
| @@ -103,15 +105,24 @@ | |
| 105 | if( pData==0 ){ |
| 106 | fprintf(stderr, "Cannot open file [%s]\n", aRes[i].zName); |
| 107 | nErr++; |
| 108 | continue; |
| 109 | } |
| 110 | |
| 111 | /* Skip initial lines beginning with # */ |
| 112 | nSkip = 0; |
| 113 | while( pData[nSkip]=='#' ){ |
| 114 | while( pData[nSkip]!=0 && pData[nSkip]!='\n' ){ nSkip++; } |
| 115 | if( pData[nSkip]=='\n' ) nSkip++; |
| 116 | } |
| 117 | |
| 118 | aRes[i].nByte = sz - nSkip; |
| 119 | aRes[i].idx = i; |
| 120 | printf("/* Content of file %s */\n", aRes[i].zName); |
| 121 | printf("static const unsigned char bidata%d[%d] = {\n ", |
| 122 | i, sz+1-nSkip); |
| 123 | for(j=nSkip, n=0; j<=sz; j++){ |
| 124 | printf("%3d", pData[j]); |
| 125 | if( j==sz ){ |
| 126 | printf(" };\n"); |
| 127 | }else if( n==14 ){ |
| 128 | printf(",\n "); |
| @@ -129,17 +140,26 @@ | |
| 140 | printf(" const unsigned char *pData;\n"); |
| 141 | printf(" int nByte;\n"); |
| 142 | printf("};\n"); |
| 143 | printf("static const BuiltinFileTable aBuiltinFiles[] = {\n"); |
| 144 | for(i=0; i<nRes; i++){ |
| 145 | const char *z = aRes[i].zName; |
| 146 | const char *zTail; |
| 147 | int nSlash = 0; |
| 148 | zTail = z; |
| 149 | while( z && z[0] ){ |
| 150 | if( z[0]=='/' || z[0]=='\\' ){ |
| 151 | nSlash++; |
| 152 | if( nSlash<=2 || z[-1]=='.' ) zTail = &z[1]; |
| 153 | } |
| 154 | z++; |
| 155 | } |
| 156 | aRes[i].zName = zTail; |
| 157 | } |
| 158 | qsort(aRes, nRes, sizeof(aRes[0]), compareResource); |
| 159 | for(i=0; i<nRes; i++){ |
| 160 | printf(" { \"%s\", bidata%d, %d },\n", |
| 161 | aRes[i].zName, aRes[i].idx, aRes[i].nByte); |
| 162 | } |
| 163 | printf("};\n"); |
| 164 | return nErr; |
| 165 | } |
| 166 |
+3
-3
| --- src/mkindex.c | ||
| +++ src/mkindex.c | ||
| @@ -217,11 +217,11 @@ | ||
| 217 | 217 | if( zLine[i]!='(' ) goto page_skip; |
| 218 | 218 | nFixed = nUsed; |
| 219 | 219 | nHelp = 0; |
| 220 | 220 | return; |
| 221 | 221 | |
| 222 | -page_skip: | |
| 222 | +page_skip: | |
| 223 | 223 | for(i=nFixed; i<nUsed; i++){ |
| 224 | 224 | fprintf(stderr,"%s:%d: skipping page \"%s\"\n", |
| 225 | 225 | zFile, nLine, aEntry[i].zPath); |
| 226 | 226 | } |
| 227 | 227 | nUsed = nFixed; |
| @@ -327,11 +327,11 @@ | ||
| 327 | 327 | aEntry[i].zHelp[0] = 0; |
| 328 | 328 | } |
| 329 | 329 | } |
| 330 | 330 | puts("struct CmdHelp {" |
| 331 | 331 | "int eType; " |
| 332 | - "char const * zText;" | |
| 332 | + "const char *zText;" | |
| 333 | 333 | "};"); |
| 334 | 334 | puts("static struct CmdHelp aCmdHelp[] = {"); |
| 335 | 335 | for(i=0; i<nFixed; i++){ |
| 336 | 336 | if( aEntry[i].zIf ) printf("%s", aEntry[i].zIf); |
| 337 | 337 | if( aEntry[i].zHelp==0 ){ |
| @@ -361,11 +361,11 @@ | ||
| 361 | 361 | scan_for_label("WEBPAGE:",zLine,0); |
| 362 | 362 | scan_for_label("COMMAND:",zLine,1); |
| 363 | 363 | scan_for_func(zLine); |
| 364 | 364 | } |
| 365 | 365 | fclose(in); |
| 366 | - nUsed = nFixed; | |
| 366 | + nUsed = nFixed; | |
| 367 | 367 | } |
| 368 | 368 | |
| 369 | 369 | int main(int argc, char **argv){ |
| 370 | 370 | int i; |
| 371 | 371 | for(i=1; i<argc; i++){ |
| 372 | 372 |
| --- src/mkindex.c | |
| +++ src/mkindex.c | |
| @@ -217,11 +217,11 @@ | |
| 217 | if( zLine[i]!='(' ) goto page_skip; |
| 218 | nFixed = nUsed; |
| 219 | nHelp = 0; |
| 220 | return; |
| 221 | |
| 222 | page_skip: |
| 223 | for(i=nFixed; i<nUsed; i++){ |
| 224 | fprintf(stderr,"%s:%d: skipping page \"%s\"\n", |
| 225 | zFile, nLine, aEntry[i].zPath); |
| 226 | } |
| 227 | nUsed = nFixed; |
| @@ -327,11 +327,11 @@ | |
| 327 | aEntry[i].zHelp[0] = 0; |
| 328 | } |
| 329 | } |
| 330 | puts("struct CmdHelp {" |
| 331 | "int eType; " |
| 332 | "char const * zText;" |
| 333 | "};"); |
| 334 | puts("static struct CmdHelp aCmdHelp[] = {"); |
| 335 | for(i=0; i<nFixed; i++){ |
| 336 | if( aEntry[i].zIf ) printf("%s", aEntry[i].zIf); |
| 337 | if( aEntry[i].zHelp==0 ){ |
| @@ -361,11 +361,11 @@ | |
| 361 | scan_for_label("WEBPAGE:",zLine,0); |
| 362 | scan_for_label("COMMAND:",zLine,1); |
| 363 | scan_for_func(zLine); |
| 364 | } |
| 365 | fclose(in); |
| 366 | nUsed = nFixed; |
| 367 | } |
| 368 | |
| 369 | int main(int argc, char **argv){ |
| 370 | int i; |
| 371 | for(i=1; i<argc; i++){ |
| 372 |
| --- src/mkindex.c | |
| +++ src/mkindex.c | |
| @@ -217,11 +217,11 @@ | |
| 217 | if( zLine[i]!='(' ) goto page_skip; |
| 218 | nFixed = nUsed; |
| 219 | nHelp = 0; |
| 220 | return; |
| 221 | |
| 222 | page_skip: |
| 223 | for(i=nFixed; i<nUsed; i++){ |
| 224 | fprintf(stderr,"%s:%d: skipping page \"%s\"\n", |
| 225 | zFile, nLine, aEntry[i].zPath); |
| 226 | } |
| 227 | nUsed = nFixed; |
| @@ -327,11 +327,11 @@ | |
| 327 | aEntry[i].zHelp[0] = 0; |
| 328 | } |
| 329 | } |
| 330 | puts("struct CmdHelp {" |
| 331 | "int eType; " |
| 332 | "const char *zText;" |
| 333 | "};"); |
| 334 | puts("static struct CmdHelp aCmdHelp[] = {"); |
| 335 | for(i=0; i<nFixed; i++){ |
| 336 | if( aEntry[i].zIf ) printf("%s", aEntry[i].zIf); |
| 337 | if( aEntry[i].zHelp==0 ){ |
| @@ -361,11 +361,11 @@ | |
| 361 | scan_for_label("WEBPAGE:",zLine,0); |
| 362 | scan_for_label("COMMAND:",zLine,1); |
| 363 | scan_for_func(zLine); |
| 364 | } |
| 365 | fclose(in); |
| 366 | nUsed = nFixed; |
| 367 | } |
| 368 | |
| 369 | int main(int argc, char **argv){ |
| 370 | int i; |
| 371 | for(i=1; i<argc; i++){ |
| 372 |
+1
-1
| --- src/mkversion.c | ||
| +++ src/mkversion.c | ||
| @@ -43,11 +43,11 @@ | ||
| 43 | 43 | exit(1); |
| 44 | 44 | } |
| 45 | 45 | fclose(v); |
| 46 | 46 | for(z=b; z[0] && z[0]!='\r' && z[0]!='\n'; z++){} |
| 47 | 47 | *z = 0; |
| 48 | - printf("#define RELEASE_VERSION \"%s\"\n", b); | |
| 48 | + printf("#define RELEASE_VERSION \"%s\"\n", b); | |
| 49 | 49 | x=0; |
| 50 | 50 | i=0; |
| 51 | 51 | z=b; |
| 52 | 52 | while(1){ |
| 53 | 53 | if( z[0]>='0' && z[0]<='9' ){ |
| 54 | 54 |
| --- src/mkversion.c | |
| +++ src/mkversion.c | |
| @@ -43,11 +43,11 @@ | |
| 43 | exit(1); |
| 44 | } |
| 45 | fclose(v); |
| 46 | for(z=b; z[0] && z[0]!='\r' && z[0]!='\n'; z++){} |
| 47 | *z = 0; |
| 48 | printf("#define RELEASE_VERSION \"%s\"\n", b); |
| 49 | x=0; |
| 50 | i=0; |
| 51 | z=b; |
| 52 | while(1){ |
| 53 | if( z[0]>='0' && z[0]<='9' ){ |
| 54 |
| --- src/mkversion.c | |
| +++ src/mkversion.c | |
| @@ -43,11 +43,11 @@ | |
| 43 | exit(1); |
| 44 | } |
| 45 | fclose(v); |
| 46 | for(z=b; z[0] && z[0]!='\r' && z[0]!='\n'; z++){} |
| 47 | *z = 0; |
| 48 | printf("#define RELEASE_VERSION \"%s\"\n", b); |
| 49 | x=0; |
| 50 | i=0; |
| 51 | z=b; |
| 52 | while(1){ |
| 53 | if( z[0]>='0' && z[0]<='9' ){ |
| 54 |
+17
-14
| --- src/report.c | ||
| +++ src/report.c | ||
| @@ -171,10 +171,11 @@ | ||
| 171 | 171 | /* We've already seen an error. No need to continue. */ |
| 172 | 172 | return SQLITE_OK; |
| 173 | 173 | } |
| 174 | 174 | switch( code ){ |
| 175 | 175 | case SQLITE_SELECT: |
| 176 | + case SQLITE_RECURSIVE: | |
| 176 | 177 | case SQLITE_FUNCTION: { |
| 177 | 178 | break; |
| 178 | 179 | } |
| 179 | 180 | case SQLITE_READ: { |
| 180 | 181 | static const char *const azAllowed[] = { |
| @@ -201,15 +202,10 @@ | ||
| 201 | 202 | }else if( !g.perm.RdAddr && strncmp(zArg2, "private_", 8)==0 ){ |
| 202 | 203 | rc = SQLITE_IGNORE; |
| 203 | 204 | } |
| 204 | 205 | break; |
| 205 | 206 | } |
| 206 | - case SQLITE_RECURSIVE: { | |
| 207 | - *(char**)pError = mprintf("recursive queries are not allowed"); | |
| 208 | - rc = SQLITE_DENY; | |
| 209 | - break; | |
| 210 | - } | |
| 211 | 207 | default: { |
| 212 | 208 | *(char**)pError = mprintf("only SELECT statements are allowed"); |
| 213 | 209 | rc = SQLITE_DENY; |
| 214 | 210 | break; |
| 215 | 211 | } |
| @@ -240,15 +236,17 @@ | ||
| 240 | 236 | const char *zTail; |
| 241 | 237 | sqlite3_stmt *pStmt; |
| 242 | 238 | int rc; |
| 243 | 239 | |
| 244 | 240 | /* First make sure the SQL is a single query command by verifying that |
| 245 | - ** the first token is "SELECT" and that there are no unquoted semicolons. | |
| 241 | + ** the first token is "SELECT" or "WITH" and that there are no unquoted | |
| 242 | + ** semicolons. | |
| 246 | 243 | */ |
| 247 | 244 | for(i=0; fossil_isspace(zSql[i]); i++){} |
| 248 | - if( fossil_strnicmp(&zSql[i],"select",6)!=0 ){ | |
| 249 | - return mprintf("The SQL must be a SELECT statement"); | |
| 245 | + if( fossil_strnicmp(&zSql[i], "select", 6)!=0 | |
| 246 | + && fossil_strnicmp(&zSql[i], "with", 4)!=0 ){ | |
| 247 | + return mprintf("The SQL must be a SELECT or WITH statement"); | |
| 250 | 248 | } |
| 251 | 249 | for(i=0; zSql[i]; i++){ |
| 252 | 250 | if( zSql[i]==';' ){ |
| 253 | 251 | int bad; |
| 254 | 252 | int c = zSql[i+1]; |
| @@ -936,10 +934,11 @@ | ||
| 936 | 934 | ** t Sort by text |
| 937 | 935 | ** n Sort numerically |
| 938 | 936 | ** k Sort by the data-sortkey property |
| 939 | 937 | ** x This column is not sortable |
| 940 | 938 | ** |
| 939 | +** Capital letters mean sort in reverse order. | |
| 941 | 940 | ** If there are fewer characters in zColumnTypes[] than their are columns, |
| 942 | 941 | ** the all extra columns assume type "t" (text). |
| 943 | 942 | ** |
| 944 | 943 | ** The third parameter is the column that was initially sorted (using 1-based |
| 945 | 944 | ** column numbers, like SQL). Make this value 0 if none of the columns are |
| @@ -959,14 +958,14 @@ | ||
| 959 | 958 | @ this.columnTypes = columnTypes; |
| 960 | 959 | @ this.sort = function (cell) { |
| 961 | 960 | @ var column = cell.cellIndex; |
| 962 | 961 | @ var sortFn; |
| 963 | 962 | @ switch( cell.sortType ){ |
| 964 | - @ case "n": sortFn = this.sortNumeric; break; | |
| 965 | - @ case "t": sortFn = this.sortText; break; | |
| 966 | - @ case "k": sortFn = this.sortKey; break; | |
| 967 | - @ case "x": return; | |
| 963 | + @ case "N": case "n": sortFn = this.sortNumeric; break; | |
| 964 | + @ case "T": case "t": sortFn = this.sortText; break; | |
| 965 | + @ case "K": case "k": sortFn = this.sortKey; break; | |
| 966 | + @ default: return; | |
| 968 | 967 | @ } |
| 969 | 968 | @ this.sortIndex = column; |
| 970 | 969 | @ var newRows = new Array(); |
| 971 | 970 | @ for (j = 0; j < this.tbody[0].rows.length; j++) { |
| 972 | 971 | @ newRows[j] = this.tbody[0].rows[j]; |
| @@ -975,10 +974,13 @@ | ||
| 975 | 974 | @ newRows.reverse(); |
| 976 | 975 | @ this.prevColumn = -this.prevColumn; |
| 977 | 976 | @ }else{ |
| 978 | 977 | @ newRows.sort(sortFn); |
| 979 | 978 | @ this.prevColumn = this.sortIndex+1; |
| 979 | + @ if( cell.sortType>="A" && cell.sortType<="Z" ){ | |
| 980 | + @ newRows.reverse(); | |
| 981 | + @ } | |
| 980 | 982 | @ } |
| 981 | 983 | @ for (i=0;i<newRows.length;i++) { |
| 982 | 984 | @ this.tbody[0].appendChild(newRows[i]); |
| 983 | 985 | @ } |
| 984 | 986 | @ this.setHdrIcons(); |
| @@ -1002,27 +1004,28 @@ | ||
| 1002 | 1004 | @ } |
| 1003 | 1005 | @ this.sortText = function(a,b) { |
| 1004 | 1006 | @ var i = thisObject.sortIndex; |
| 1005 | 1007 | @ aa = a.cells[i].textContent.replace(/^\W+/,'').toLowerCase(); |
| 1006 | 1008 | @ bb = b.cells[i].textContent.replace(/^\W+/,'').toLowerCase(); |
| 1007 | - @ if(aa==bb) return 0; | |
| 1009 | + @ if(aa==bb) return a.rowIndex-b.rowIndex; | |
| 1008 | 1010 | @ if(aa<bb) return -1; |
| 1009 | 1011 | @ return 1; |
| 1010 | 1012 | @ } |
| 1011 | 1013 | @ this.sortNumeric = function(a,b) { |
| 1012 | 1014 | @ var i = thisObject.sortIndex; |
| 1013 | 1015 | @ aa = parseFloat(a.cells[i].textContent); |
| 1014 | 1016 | @ if (isNaN(aa)) aa = 0; |
| 1015 | 1017 | @ bb = parseFloat(b.cells[i].textContent); |
| 1016 | 1018 | @ if (isNaN(bb)) bb = 0; |
| 1019 | + @ if(aa==bb) return a.rowIndex-b.rowIndex; | |
| 1017 | 1020 | @ return aa-bb; |
| 1018 | 1021 | @ } |
| 1019 | 1022 | @ this.sortKey = function(a,b) { |
| 1020 | 1023 | @ var i = thisObject.sortIndex; |
| 1021 | 1024 | @ aa = a.cells[i].getAttribute("data-sortkey"); |
| 1022 | 1025 | @ bb = b.cells[i].getAttribute("data-sortkey"); |
| 1023 | - @ if(aa==bb) return 0; | |
| 1026 | + @ if(aa==bb) return a.rowIndex-b.rowIndex; | |
| 1024 | 1027 | @ if(aa<bb) return -1; |
| 1025 | 1028 | @ return 1; |
| 1026 | 1029 | @ } |
| 1027 | 1030 | @ var x = tableEl.getElementsByTagName('thead'); |
| 1028 | 1031 | @ if(!(this.tbody && this.tbody[0].rows && this.tbody[0].rows.length>0)){ |
| 1029 | 1032 |
| --- src/report.c | |
| +++ src/report.c | |
| @@ -171,10 +171,11 @@ | |
| 171 | /* We've already seen an error. No need to continue. */ |
| 172 | return SQLITE_OK; |
| 173 | } |
| 174 | switch( code ){ |
| 175 | case SQLITE_SELECT: |
| 176 | case SQLITE_FUNCTION: { |
| 177 | break; |
| 178 | } |
| 179 | case SQLITE_READ: { |
| 180 | static const char *const azAllowed[] = { |
| @@ -201,15 +202,10 @@ | |
| 201 | }else if( !g.perm.RdAddr && strncmp(zArg2, "private_", 8)==0 ){ |
| 202 | rc = SQLITE_IGNORE; |
| 203 | } |
| 204 | break; |
| 205 | } |
| 206 | case SQLITE_RECURSIVE: { |
| 207 | *(char**)pError = mprintf("recursive queries are not allowed"); |
| 208 | rc = SQLITE_DENY; |
| 209 | break; |
| 210 | } |
| 211 | default: { |
| 212 | *(char**)pError = mprintf("only SELECT statements are allowed"); |
| 213 | rc = SQLITE_DENY; |
| 214 | break; |
| 215 | } |
| @@ -240,15 +236,17 @@ | |
| 240 | const char *zTail; |
| 241 | sqlite3_stmt *pStmt; |
| 242 | int rc; |
| 243 | |
| 244 | /* First make sure the SQL is a single query command by verifying that |
| 245 | ** the first token is "SELECT" and that there are no unquoted semicolons. |
| 246 | */ |
| 247 | for(i=0; fossil_isspace(zSql[i]); i++){} |
| 248 | if( fossil_strnicmp(&zSql[i],"select",6)!=0 ){ |
| 249 | return mprintf("The SQL must be a SELECT statement"); |
| 250 | } |
| 251 | for(i=0; zSql[i]; i++){ |
| 252 | if( zSql[i]==';' ){ |
| 253 | int bad; |
| 254 | int c = zSql[i+1]; |
| @@ -936,10 +934,11 @@ | |
| 936 | ** t Sort by text |
| 937 | ** n Sort numerically |
| 938 | ** k Sort by the data-sortkey property |
| 939 | ** x This column is not sortable |
| 940 | ** |
| 941 | ** If there are fewer characters in zColumnTypes[] than their are columns, |
| 942 | ** the all extra columns assume type "t" (text). |
| 943 | ** |
| 944 | ** The third parameter is the column that was initially sorted (using 1-based |
| 945 | ** column numbers, like SQL). Make this value 0 if none of the columns are |
| @@ -959,14 +958,14 @@ | |
| 959 | @ this.columnTypes = columnTypes; |
| 960 | @ this.sort = function (cell) { |
| 961 | @ var column = cell.cellIndex; |
| 962 | @ var sortFn; |
| 963 | @ switch( cell.sortType ){ |
| 964 | @ case "n": sortFn = this.sortNumeric; break; |
| 965 | @ case "t": sortFn = this.sortText; break; |
| 966 | @ case "k": sortFn = this.sortKey; break; |
| 967 | @ case "x": return; |
| 968 | @ } |
| 969 | @ this.sortIndex = column; |
| 970 | @ var newRows = new Array(); |
| 971 | @ for (j = 0; j < this.tbody[0].rows.length; j++) { |
| 972 | @ newRows[j] = this.tbody[0].rows[j]; |
| @@ -975,10 +974,13 @@ | |
| 975 | @ newRows.reverse(); |
| 976 | @ this.prevColumn = -this.prevColumn; |
| 977 | @ }else{ |
| 978 | @ newRows.sort(sortFn); |
| 979 | @ this.prevColumn = this.sortIndex+1; |
| 980 | @ } |
| 981 | @ for (i=0;i<newRows.length;i++) { |
| 982 | @ this.tbody[0].appendChild(newRows[i]); |
| 983 | @ } |
| 984 | @ this.setHdrIcons(); |
| @@ -1002,27 +1004,28 @@ | |
| 1002 | @ } |
| 1003 | @ this.sortText = function(a,b) { |
| 1004 | @ var i = thisObject.sortIndex; |
| 1005 | @ aa = a.cells[i].textContent.replace(/^\W+/,'').toLowerCase(); |
| 1006 | @ bb = b.cells[i].textContent.replace(/^\W+/,'').toLowerCase(); |
| 1007 | @ if(aa==bb) return 0; |
| 1008 | @ if(aa<bb) return -1; |
| 1009 | @ return 1; |
| 1010 | @ } |
| 1011 | @ this.sortNumeric = function(a,b) { |
| 1012 | @ var i = thisObject.sortIndex; |
| 1013 | @ aa = parseFloat(a.cells[i].textContent); |
| 1014 | @ if (isNaN(aa)) aa = 0; |
| 1015 | @ bb = parseFloat(b.cells[i].textContent); |
| 1016 | @ if (isNaN(bb)) bb = 0; |
| 1017 | @ return aa-bb; |
| 1018 | @ } |
| 1019 | @ this.sortKey = function(a,b) { |
| 1020 | @ var i = thisObject.sortIndex; |
| 1021 | @ aa = a.cells[i].getAttribute("data-sortkey"); |
| 1022 | @ bb = b.cells[i].getAttribute("data-sortkey"); |
| 1023 | @ if(aa==bb) return 0; |
| 1024 | @ if(aa<bb) return -1; |
| 1025 | @ return 1; |
| 1026 | @ } |
| 1027 | @ var x = tableEl.getElementsByTagName('thead'); |
| 1028 | @ if(!(this.tbody && this.tbody[0].rows && this.tbody[0].rows.length>0)){ |
| 1029 |
| --- src/report.c | |
| +++ src/report.c | |
| @@ -171,10 +171,11 @@ | |
| 171 | /* We've already seen an error. No need to continue. */ |
| 172 | return SQLITE_OK; |
| 173 | } |
| 174 | switch( code ){ |
| 175 | case SQLITE_SELECT: |
| 176 | case SQLITE_RECURSIVE: |
| 177 | case SQLITE_FUNCTION: { |
| 178 | break; |
| 179 | } |
| 180 | case SQLITE_READ: { |
| 181 | static const char *const azAllowed[] = { |
| @@ -201,15 +202,10 @@ | |
| 202 | }else if( !g.perm.RdAddr && strncmp(zArg2, "private_", 8)==0 ){ |
| 203 | rc = SQLITE_IGNORE; |
| 204 | } |
| 205 | break; |
| 206 | } |
| 207 | default: { |
| 208 | *(char**)pError = mprintf("only SELECT statements are allowed"); |
| 209 | rc = SQLITE_DENY; |
| 210 | break; |
| 211 | } |
| @@ -240,15 +236,17 @@ | |
| 236 | const char *zTail; |
| 237 | sqlite3_stmt *pStmt; |
| 238 | int rc; |
| 239 | |
| 240 | /* First make sure the SQL is a single query command by verifying that |
| 241 | ** the first token is "SELECT" or "WITH" and that there are no unquoted |
| 242 | ** semicolons. |
| 243 | */ |
| 244 | for(i=0; fossil_isspace(zSql[i]); i++){} |
| 245 | if( fossil_strnicmp(&zSql[i], "select", 6)!=0 |
| 246 | && fossil_strnicmp(&zSql[i], "with", 4)!=0 ){ |
| 247 | return mprintf("The SQL must be a SELECT or WITH statement"); |
| 248 | } |
| 249 | for(i=0; zSql[i]; i++){ |
| 250 | if( zSql[i]==';' ){ |
| 251 | int bad; |
| 252 | int c = zSql[i+1]; |
| @@ -936,10 +934,11 @@ | |
| 934 | ** t Sort by text |
| 935 | ** n Sort numerically |
| 936 | ** k Sort by the data-sortkey property |
| 937 | ** x This column is not sortable |
| 938 | ** |
| 939 | ** Capital letters mean sort in reverse order. |
| 940 | ** If there are fewer characters in zColumnTypes[] than their are columns, |
| 941 | ** the all extra columns assume type "t" (text). |
| 942 | ** |
| 943 | ** The third parameter is the column that was initially sorted (using 1-based |
| 944 | ** column numbers, like SQL). Make this value 0 if none of the columns are |
| @@ -959,14 +958,14 @@ | |
| 958 | @ this.columnTypes = columnTypes; |
| 959 | @ this.sort = function (cell) { |
| 960 | @ var column = cell.cellIndex; |
| 961 | @ var sortFn; |
| 962 | @ switch( cell.sortType ){ |
| 963 | @ case "N": case "n": sortFn = this.sortNumeric; break; |
| 964 | @ case "T": case "t": sortFn = this.sortText; break; |
| 965 | @ case "K": case "k": sortFn = this.sortKey; break; |
| 966 | @ default: return; |
| 967 | @ } |
| 968 | @ this.sortIndex = column; |
| 969 | @ var newRows = new Array(); |
| 970 | @ for (j = 0; j < this.tbody[0].rows.length; j++) { |
| 971 | @ newRows[j] = this.tbody[0].rows[j]; |
| @@ -975,10 +974,13 @@ | |
| 974 | @ newRows.reverse(); |
| 975 | @ this.prevColumn = -this.prevColumn; |
| 976 | @ }else{ |
| 977 | @ newRows.sort(sortFn); |
| 978 | @ this.prevColumn = this.sortIndex+1; |
| 979 | @ if( cell.sortType>="A" && cell.sortType<="Z" ){ |
| 980 | @ newRows.reverse(); |
| 981 | @ } |
| 982 | @ } |
| 983 | @ for (i=0;i<newRows.length;i++) { |
| 984 | @ this.tbody[0].appendChild(newRows[i]); |
| 985 | @ } |
| 986 | @ this.setHdrIcons(); |
| @@ -1002,27 +1004,28 @@ | |
| 1004 | @ } |
| 1005 | @ this.sortText = function(a,b) { |
| 1006 | @ var i = thisObject.sortIndex; |
| 1007 | @ aa = a.cells[i].textContent.replace(/^\W+/,'').toLowerCase(); |
| 1008 | @ bb = b.cells[i].textContent.replace(/^\W+/,'').toLowerCase(); |
| 1009 | @ if(aa==bb) return a.rowIndex-b.rowIndex; |
| 1010 | @ if(aa<bb) return -1; |
| 1011 | @ return 1; |
| 1012 | @ } |
| 1013 | @ this.sortNumeric = function(a,b) { |
| 1014 | @ var i = thisObject.sortIndex; |
| 1015 | @ aa = parseFloat(a.cells[i].textContent); |
| 1016 | @ if (isNaN(aa)) aa = 0; |
| 1017 | @ bb = parseFloat(b.cells[i].textContent); |
| 1018 | @ if (isNaN(bb)) bb = 0; |
| 1019 | @ if(aa==bb) return a.rowIndex-b.rowIndex; |
| 1020 | @ return aa-bb; |
| 1021 | @ } |
| 1022 | @ this.sortKey = function(a,b) { |
| 1023 | @ var i = thisObject.sortIndex; |
| 1024 | @ aa = a.cells[i].getAttribute("data-sortkey"); |
| 1025 | @ bb = b.cells[i].getAttribute("data-sortkey"); |
| 1026 | @ if(aa==bb) return a.rowIndex-b.rowIndex; |
| 1027 | @ if(aa<bb) return -1; |
| 1028 | @ return 1; |
| 1029 | @ } |
| 1030 | @ var x = tableEl.getElementsByTagName('thead'); |
| 1031 | @ if(!(this.tbody && this.tbody[0].rows && this.tbody[0].rows.length>0)){ |
| 1032 |
+1
-1
| --- src/search.c | ||
| +++ src/search.c | ||
| @@ -165,11 +165,11 @@ | ||
| 165 | 165 | int i; |
| 166 | 166 | |
| 167 | 167 | azDoc = fossil_malloc( sizeof(const char*)*(argc+1) ); |
| 168 | 168 | for(i=0; i<argc; i++) azDoc[i] = (const char*)sqlite3_value_text(argv[i]); |
| 169 | 169 | score = search_score(p, argc, azDoc); |
| 170 | - fossil_free(azDoc); | |
| 170 | + fossil_free((void *)azDoc); | |
| 171 | 171 | sqlite3_result_int(context, score); |
| 172 | 172 | } |
| 173 | 173 | |
| 174 | 174 | /* |
| 175 | 175 | ** Register the "score()" SQL function to score its input text |
| 176 | 176 |
| --- src/search.c | |
| +++ src/search.c | |
| @@ -165,11 +165,11 @@ | |
| 165 | int i; |
| 166 | |
| 167 | azDoc = fossil_malloc( sizeof(const char*)*(argc+1) ); |
| 168 | for(i=0; i<argc; i++) azDoc[i] = (const char*)sqlite3_value_text(argv[i]); |
| 169 | score = search_score(p, argc, azDoc); |
| 170 | fossil_free(azDoc); |
| 171 | sqlite3_result_int(context, score); |
| 172 | } |
| 173 | |
| 174 | /* |
| 175 | ** Register the "score()" SQL function to score its input text |
| 176 |
| --- src/search.c | |
| +++ src/search.c | |
| @@ -165,11 +165,11 @@ | |
| 165 | int i; |
| 166 | |
| 167 | azDoc = fossil_malloc( sizeof(const char*)*(argc+1) ); |
| 168 | for(i=0; i<argc; i++) azDoc[i] = (const char*)sqlite3_value_text(argv[i]); |
| 169 | score = search_score(p, argc, azDoc); |
| 170 | fossil_free((void *)azDoc); |
| 171 | sqlite3_result_int(context, score); |
| 172 | } |
| 173 | |
| 174 | /* |
| 175 | ** Register the "score()" SQL function to score its input text |
| 176 |
+55
-16
| --- src/setup.c | ||
| +++ src/setup.c | ||
| @@ -1525,24 +1525,26 @@ | ||
| 1525 | 1525 | login_needed(); |
| 1526 | 1526 | } |
| 1527 | 1527 | db_begin_transaction(); |
| 1528 | 1528 | if( P("clear")!=0 ){ |
| 1529 | 1529 | db_multi_exec("DELETE FROM config WHERE name='css'"); |
| 1530 | - cgi_replace_parameter("css", zDefaultCSS); | |
| 1530 | + cgi_replace_parameter("css", builtin_text("skins/default.css")); | |
| 1531 | 1531 | db_end_transaction(0); |
| 1532 | 1532 | cgi_redirect("setup_editcss"); |
| 1533 | 1533 | } |
| 1534 | 1534 | if( P("submit")!=0 ){ |
| 1535 | - textarea_attribute(0, 0, 0, "css", "css", zDefaultCSS, 0); | |
| 1535 | + textarea_attribute(0, 0, 0, "css", "css", | |
| 1536 | + builtin_text("skins/default.css"), 0); | |
| 1536 | 1537 | db_end_transaction(0); |
| 1537 | 1538 | cgi_redirect("setup_editcss"); |
| 1538 | 1539 | } |
| 1539 | 1540 | style_header("Edit CSS"); |
| 1540 | 1541 | @ <form action="%s(g.zTop)/setup_editcss" method="post"><div> |
| 1541 | 1542 | login_insert_csrf_secret(); |
| 1542 | 1543 | @ Edit the CSS below:<br /> |
| 1543 | - textarea_attribute("", 35, 80, "css", "css", zDefaultCSS, 0); | |
| 1544 | + textarea_attribute("", 35, 80, "css", "css", | |
| 1545 | + builtin_text("skins/default.css"), 0); | |
| 1544 | 1546 | @ <br /> |
| 1545 | 1547 | @ <input type="submit" name="submit" value="Apply Changes" /> |
| 1546 | 1548 | @ <input type="submit" name="clear" value="Revert To Default" /> |
| 1547 | 1549 | @ </div></form> |
| 1548 | 1550 | @ <p><span class="note">Note:</span> Press your browser Reload button after |
| @@ -1568,15 +1570,17 @@ | ||
| 1568 | 1570 | login_needed(); |
| 1569 | 1571 | } |
| 1570 | 1572 | db_begin_transaction(); |
| 1571 | 1573 | if( P("clear")!=0 ){ |
| 1572 | 1574 | db_multi_exec("DELETE FROM config WHERE name='header'"); |
| 1573 | - cgi_replace_parameter("header", zDefaultHeader); | |
| 1575 | + cgi_replace_parameter("header", builtin_text("skins/default.header")); | |
| 1574 | 1576 | }else if( P("submit")!=0 ){ |
| 1575 | - textarea_attribute(0, 0, 0, "header", "header", zDefaultHeader, 0); | |
| 1577 | + textarea_attribute(0, 0, 0, "header", "header", | |
| 1578 | + builtin_text("skins/default.header"), 0); | |
| 1576 | 1579 | }else if( P("fixbase")!=0 ){ |
| 1577 | - const char *z = db_get("header", (char*)zDefaultHeader); | |
| 1580 | + const char *z = db_get("header", | |
| 1581 | + (char*)builtin_text("skins/default.header")); | |
| 1578 | 1582 | char *zHead = strstr(z, "<head>"); |
| 1579 | 1583 | if( strstr(z, "<base href=")==0 && zHead!=0 ){ |
| 1580 | 1584 | char *zNew; |
| 1581 | 1585 | char *zTail = &zHead[6]; |
| 1582 | 1586 | while( fossil_isspace(zTail[0]) ) zTail++; |
| @@ -1598,14 +1602,15 @@ | ||
| 1598 | 1602 | @ <tt><head></tt> in the header! |
| 1599 | 1603 | @ <input type="submit" name="fixbase" value="Add <base> Now"></p> |
| 1600 | 1604 | } |
| 1601 | 1605 | |
| 1602 | 1606 | login_insert_csrf_secret(); |
| 1603 | - @ <p>Edit HTML text with embedded TH1 (a TCL dialect) that will be used to | |
| 1607 | + @ <p>Edit HTML text with embedded TH1 (a Tcl dialect) that will be used to | |
| 1604 | 1608 | @ generate the beginning of every page through start of the main |
| 1605 | 1609 | @ menu.</p> |
| 1606 | - textarea_attribute("", 35, 80, "header", "header", zDefaultHeader, 0); | |
| 1610 | + textarea_attribute("", 35, 80, "header", "header", | |
| 1611 | + builtin_text("skins/default.header"), 0); | |
| 1607 | 1612 | @ <br /> |
| 1608 | 1613 | @ <input type="submit" name="submit" value="Apply Changes" /> |
| 1609 | 1614 | @ <input type="submit" name="clear" value="Revert To Default" /> |
| 1610 | 1615 | @ </div></form> |
| 1611 | 1616 | @ <hr /> |
| @@ -1612,11 +1617,11 @@ | ||
| 1612 | 1617 | @ The default header is shown below for reference. Other examples |
| 1613 | 1618 | @ of headers can be seen on the <a href="setup_skin">skins page</a>. |
| 1614 | 1619 | @ See also the <a href="setup_editcss">CSS</a> and |
| 1615 | 1620 | @ <a href="setup_footer">footer</a> editing screens. |
| 1616 | 1621 | @ <blockquote><pre> |
| 1617 | - @ %h(zDefaultHeader) | |
| 1622 | + @ %h(builtin_text("skins/default.header")) | |
| 1618 | 1623 | @ </pre></blockquote> |
| 1619 | 1624 | style_footer(); |
| 1620 | 1625 | db_end_transaction(0); |
| 1621 | 1626 | } |
| 1622 | 1627 | |
| @@ -1629,19 +1634,20 @@ | ||
| 1629 | 1634 | login_needed(); |
| 1630 | 1635 | } |
| 1631 | 1636 | db_begin_transaction(); |
| 1632 | 1637 | if( P("clear")!=0 ){ |
| 1633 | 1638 | db_multi_exec("DELETE FROM config WHERE name='footer'"); |
| 1634 | - cgi_replace_parameter("footer", zDefaultFooter); | |
| 1639 | + cgi_replace_parameter("footer", builtin_text("skins/default.footer")); | |
| 1635 | 1640 | } |
| 1636 | 1641 | |
| 1637 | 1642 | style_header("Edit Page Footer"); |
| 1638 | 1643 | @ <form action="%s(g.zTop)/setup_footer" method="post"><div> |
| 1639 | 1644 | login_insert_csrf_secret(); |
| 1640 | - @ <p>Edit HTML text with embedded TH1 (a TCL dialect) that will be used to | |
| 1645 | + @ <p>Edit HTML text with embedded TH1 (a Tcl dialect) that will be used to | |
| 1641 | 1646 | @ generate the end of every page.</p> |
| 1642 | - textarea_attribute("", 20, 80, "footer", "footer", zDefaultFooter, 0); | |
| 1647 | + textarea_attribute("", 20, 80, "footer", "footer", | |
| 1648 | + builtin_text("skins/default.footer"), 0); | |
| 1643 | 1649 | @ <br /> |
| 1644 | 1650 | @ <input type="submit" name="submit" value="Apply Changes" /> |
| 1645 | 1651 | @ <input type="submit" name="clear" value="Revert To Default" /> |
| 1646 | 1652 | @ </div></form> |
| 1647 | 1653 | @ <hr /> |
| @@ -1648,11 +1654,11 @@ | ||
| 1648 | 1654 | @ The default footer is shown below for reference. Other examples |
| 1649 | 1655 | @ of footers can be seen on the <a href="setup_skin">skins page</a>. |
| 1650 | 1656 | @ See also the <a href="setup_editcss">CSS</a> and |
| 1651 | 1657 | @ <a href="setup_header">header</a> editing screens. |
| 1652 | 1658 | @ <blockquote><pre> |
| 1653 | - @ %h(zDefaultFooter) | |
| 1659 | + @ %h(builtin_text("skins/default.footer")) | |
| 1654 | 1660 | @ </pre></blockquote> |
| 1655 | 1661 | style_footer(); |
| 1656 | 1662 | db_end_transaction(0); |
| 1657 | 1663 | } |
| 1658 | 1664 | |
| @@ -1715,13 +1721,15 @@ | ||
| 1715 | 1721 | } |
| 1716 | 1722 | |
| 1717 | 1723 | style_header("Edit Ad Unit"); |
| 1718 | 1724 | @ <form action="%s(g.zTop)/setup_adunit" method="post"><div> |
| 1719 | 1725 | login_insert_csrf_secret(); |
| 1720 | - @ <p>Edit HTML text for an ad unit that will be inserted after the | |
| 1721 | - @ menu bar and above the content of every page.</p> | |
| 1722 | - textarea_attribute("", 20, 80, "adunit", "adunit", "", 0); | |
| 1726 | + @ <b>Banner Ad-Unit:</b><br /> | |
| 1727 | + textarea_attribute("", 6, 80, "adunit", "adunit", "", 0); | |
| 1728 | + @ <br /> | |
| 1729 | + @ <b>Right-Column Ad-Unit:</b><br /> | |
| 1730 | + textarea_attribute("", 6, 80, "adunit-right", "adright", "", 0); | |
| 1723 | 1731 | @ <br /> |
| 1724 | 1732 | onoff_attribute("Omit ads to administrator", |
| 1725 | 1733 | "adunit-omit-if-admin", "oia", 0, 0); |
| 1726 | 1734 | @ <br /> |
| 1727 | 1735 | onoff_attribute("Omit ads to logged-in users", |
| @@ -1728,10 +1736,41 @@ | ||
| 1728 | 1736 | "adunit-omit-if-user", "oiu", 0, 0); |
| 1729 | 1737 | @ <br /> |
| 1730 | 1738 | @ <input type="submit" name="submit" value="Apply Changes" /> |
| 1731 | 1739 | @ <input type="submit" name="clear" value="Delete Ad-Unit" /> |
| 1732 | 1740 | @ </div></form> |
| 1741 | + @ <hr /> | |
| 1742 | + @ <b>Ad-Unit Notes:</b><ul> | |
| 1743 | + @ <li>Leave both Ad-Units blank to disable all advertising. | |
| 1744 | + @ <li>The "Banner Ad-Unit" is used for wide pages. | |
| 1745 | + @ <li>The "Right-Column Ad-Unit" is used on pages with tall, narrow content. | |
| 1746 | + @ <li>If the "Right-Column Ad-Unit" is blank, the "Banner Ad-Unit" is used on all pages. | |
| 1747 | + @ <li>Suggested <a href="setup_editcss">CSS</a> changes: | |
| 1748 | + @ <blockquote><pre> | |
| 1749 | + @ div.adunit_banner { | |
| 1750 | + @ margin: auto; | |
| 1751 | + @ width: 100%; | |
| 1752 | + @ } | |
| 1753 | + @ div.adunit_right { | |
| 1754 | + @ float: right; | |
| 1755 | + @ } | |
| 1756 | + @ div.adunit_right_container { | |
| 1757 | + @ min-height: <i>height-of-right-column-ad-unit</i>; | |
| 1758 | + @ } | |
| 1759 | + @ </pre></blockquote> | |
| 1760 | + @ <li>For a place-holder Ad-Unit for testing, Copy/Paste the following | |
| 1761 | + @ with appropriate adjustments to "width:" and "height:". | |
| 1762 | + @ <blockquote><pre> | |
| 1763 | + @ <div style=' | |
| 1764 | + @ margin: 0 auto; | |
| 1765 | + @ width: 600px; | |
| 1766 | + @ height: 90px; | |
| 1767 | + @ border: 1px solid #f11; | |
| 1768 | + @ background-color: #fcc; | |
| 1769 | + @ '>Demo Ad</div> | |
| 1770 | + @ </pre></blockquote> | |
| 1771 | + @ </li> | |
| 1733 | 1772 | style_footer(); |
| 1734 | 1773 | db_end_transaction(0); |
| 1735 | 1774 | } |
| 1736 | 1775 | |
| 1737 | 1776 | /* |
| 1738 | 1777 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -1525,24 +1525,26 @@ | |
| 1525 | login_needed(); |
| 1526 | } |
| 1527 | db_begin_transaction(); |
| 1528 | if( P("clear")!=0 ){ |
| 1529 | db_multi_exec("DELETE FROM config WHERE name='css'"); |
| 1530 | cgi_replace_parameter("css", zDefaultCSS); |
| 1531 | db_end_transaction(0); |
| 1532 | cgi_redirect("setup_editcss"); |
| 1533 | } |
| 1534 | if( P("submit")!=0 ){ |
| 1535 | textarea_attribute(0, 0, 0, "css", "css", zDefaultCSS, 0); |
| 1536 | db_end_transaction(0); |
| 1537 | cgi_redirect("setup_editcss"); |
| 1538 | } |
| 1539 | style_header("Edit CSS"); |
| 1540 | @ <form action="%s(g.zTop)/setup_editcss" method="post"><div> |
| 1541 | login_insert_csrf_secret(); |
| 1542 | @ Edit the CSS below:<br /> |
| 1543 | textarea_attribute("", 35, 80, "css", "css", zDefaultCSS, 0); |
| 1544 | @ <br /> |
| 1545 | @ <input type="submit" name="submit" value="Apply Changes" /> |
| 1546 | @ <input type="submit" name="clear" value="Revert To Default" /> |
| 1547 | @ </div></form> |
| 1548 | @ <p><span class="note">Note:</span> Press your browser Reload button after |
| @@ -1568,15 +1570,17 @@ | |
| 1568 | login_needed(); |
| 1569 | } |
| 1570 | db_begin_transaction(); |
| 1571 | if( P("clear")!=0 ){ |
| 1572 | db_multi_exec("DELETE FROM config WHERE name='header'"); |
| 1573 | cgi_replace_parameter("header", zDefaultHeader); |
| 1574 | }else if( P("submit")!=0 ){ |
| 1575 | textarea_attribute(0, 0, 0, "header", "header", zDefaultHeader, 0); |
| 1576 | }else if( P("fixbase")!=0 ){ |
| 1577 | const char *z = db_get("header", (char*)zDefaultHeader); |
| 1578 | char *zHead = strstr(z, "<head>"); |
| 1579 | if( strstr(z, "<base href=")==0 && zHead!=0 ){ |
| 1580 | char *zNew; |
| 1581 | char *zTail = &zHead[6]; |
| 1582 | while( fossil_isspace(zTail[0]) ) zTail++; |
| @@ -1598,14 +1602,15 @@ | |
| 1598 | @ <tt><head></tt> in the header! |
| 1599 | @ <input type="submit" name="fixbase" value="Add <base> Now"></p> |
| 1600 | } |
| 1601 | |
| 1602 | login_insert_csrf_secret(); |
| 1603 | @ <p>Edit HTML text with embedded TH1 (a TCL dialect) that will be used to |
| 1604 | @ generate the beginning of every page through start of the main |
| 1605 | @ menu.</p> |
| 1606 | textarea_attribute("", 35, 80, "header", "header", zDefaultHeader, 0); |
| 1607 | @ <br /> |
| 1608 | @ <input type="submit" name="submit" value="Apply Changes" /> |
| 1609 | @ <input type="submit" name="clear" value="Revert To Default" /> |
| 1610 | @ </div></form> |
| 1611 | @ <hr /> |
| @@ -1612,11 +1617,11 @@ | |
| 1612 | @ The default header is shown below for reference. Other examples |
| 1613 | @ of headers can be seen on the <a href="setup_skin">skins page</a>. |
| 1614 | @ See also the <a href="setup_editcss">CSS</a> and |
| 1615 | @ <a href="setup_footer">footer</a> editing screens. |
| 1616 | @ <blockquote><pre> |
| 1617 | @ %h(zDefaultHeader) |
| 1618 | @ </pre></blockquote> |
| 1619 | style_footer(); |
| 1620 | db_end_transaction(0); |
| 1621 | } |
| 1622 | |
| @@ -1629,19 +1634,20 @@ | |
| 1629 | login_needed(); |
| 1630 | } |
| 1631 | db_begin_transaction(); |
| 1632 | if( P("clear")!=0 ){ |
| 1633 | db_multi_exec("DELETE FROM config WHERE name='footer'"); |
| 1634 | cgi_replace_parameter("footer", zDefaultFooter); |
| 1635 | } |
| 1636 | |
| 1637 | style_header("Edit Page Footer"); |
| 1638 | @ <form action="%s(g.zTop)/setup_footer" method="post"><div> |
| 1639 | login_insert_csrf_secret(); |
| 1640 | @ <p>Edit HTML text with embedded TH1 (a TCL dialect) that will be used to |
| 1641 | @ generate the end of every page.</p> |
| 1642 | textarea_attribute("", 20, 80, "footer", "footer", zDefaultFooter, 0); |
| 1643 | @ <br /> |
| 1644 | @ <input type="submit" name="submit" value="Apply Changes" /> |
| 1645 | @ <input type="submit" name="clear" value="Revert To Default" /> |
| 1646 | @ </div></form> |
| 1647 | @ <hr /> |
| @@ -1648,11 +1654,11 @@ | |
| 1648 | @ The default footer is shown below for reference. Other examples |
| 1649 | @ of footers can be seen on the <a href="setup_skin">skins page</a>. |
| 1650 | @ See also the <a href="setup_editcss">CSS</a> and |
| 1651 | @ <a href="setup_header">header</a> editing screens. |
| 1652 | @ <blockquote><pre> |
| 1653 | @ %h(zDefaultFooter) |
| 1654 | @ </pre></blockquote> |
| 1655 | style_footer(); |
| 1656 | db_end_transaction(0); |
| 1657 | } |
| 1658 | |
| @@ -1715,13 +1721,15 @@ | |
| 1715 | } |
| 1716 | |
| 1717 | style_header("Edit Ad Unit"); |
| 1718 | @ <form action="%s(g.zTop)/setup_adunit" method="post"><div> |
| 1719 | login_insert_csrf_secret(); |
| 1720 | @ <p>Edit HTML text for an ad unit that will be inserted after the |
| 1721 | @ menu bar and above the content of every page.</p> |
| 1722 | textarea_attribute("", 20, 80, "adunit", "adunit", "", 0); |
| 1723 | @ <br /> |
| 1724 | onoff_attribute("Omit ads to administrator", |
| 1725 | "adunit-omit-if-admin", "oia", 0, 0); |
| 1726 | @ <br /> |
| 1727 | onoff_attribute("Omit ads to logged-in users", |
| @@ -1728,10 +1736,41 @@ | |
| 1728 | "adunit-omit-if-user", "oiu", 0, 0); |
| 1729 | @ <br /> |
| 1730 | @ <input type="submit" name="submit" value="Apply Changes" /> |
| 1731 | @ <input type="submit" name="clear" value="Delete Ad-Unit" /> |
| 1732 | @ </div></form> |
| 1733 | style_footer(); |
| 1734 | db_end_transaction(0); |
| 1735 | } |
| 1736 | |
| 1737 | /* |
| 1738 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -1525,24 +1525,26 @@ | |
| 1525 | login_needed(); |
| 1526 | } |
| 1527 | db_begin_transaction(); |
| 1528 | if( P("clear")!=0 ){ |
| 1529 | db_multi_exec("DELETE FROM config WHERE name='css'"); |
| 1530 | cgi_replace_parameter("css", builtin_text("skins/default.css")); |
| 1531 | db_end_transaction(0); |
| 1532 | cgi_redirect("setup_editcss"); |
| 1533 | } |
| 1534 | if( P("submit")!=0 ){ |
| 1535 | textarea_attribute(0, 0, 0, "css", "css", |
| 1536 | builtin_text("skins/default.css"), 0); |
| 1537 | db_end_transaction(0); |
| 1538 | cgi_redirect("setup_editcss"); |
| 1539 | } |
| 1540 | style_header("Edit CSS"); |
| 1541 | @ <form action="%s(g.zTop)/setup_editcss" method="post"><div> |
| 1542 | login_insert_csrf_secret(); |
| 1543 | @ Edit the CSS below:<br /> |
| 1544 | textarea_attribute("", 35, 80, "css", "css", |
| 1545 | builtin_text("skins/default.css"), 0); |
| 1546 | @ <br /> |
| 1547 | @ <input type="submit" name="submit" value="Apply Changes" /> |
| 1548 | @ <input type="submit" name="clear" value="Revert To Default" /> |
| 1549 | @ </div></form> |
| 1550 | @ <p><span class="note">Note:</span> Press your browser Reload button after |
| @@ -1568,15 +1570,17 @@ | |
| 1570 | login_needed(); |
| 1571 | } |
| 1572 | db_begin_transaction(); |
| 1573 | if( P("clear")!=0 ){ |
| 1574 | db_multi_exec("DELETE FROM config WHERE name='header'"); |
| 1575 | cgi_replace_parameter("header", builtin_text("skins/default.header")); |
| 1576 | }else if( P("submit")!=0 ){ |
| 1577 | textarea_attribute(0, 0, 0, "header", "header", |
| 1578 | builtin_text("skins/default.header"), 0); |
| 1579 | }else if( P("fixbase")!=0 ){ |
| 1580 | const char *z = db_get("header", |
| 1581 | (char*)builtin_text("skins/default.header")); |
| 1582 | char *zHead = strstr(z, "<head>"); |
| 1583 | if( strstr(z, "<base href=")==0 && zHead!=0 ){ |
| 1584 | char *zNew; |
| 1585 | char *zTail = &zHead[6]; |
| 1586 | while( fossil_isspace(zTail[0]) ) zTail++; |
| @@ -1598,14 +1602,15 @@ | |
| 1602 | @ <tt><head></tt> in the header! |
| 1603 | @ <input type="submit" name="fixbase" value="Add <base> Now"></p> |
| 1604 | } |
| 1605 | |
| 1606 | login_insert_csrf_secret(); |
| 1607 | @ <p>Edit HTML text with embedded TH1 (a Tcl dialect) that will be used to |
| 1608 | @ generate the beginning of every page through start of the main |
| 1609 | @ menu.</p> |
| 1610 | textarea_attribute("", 35, 80, "header", "header", |
| 1611 | builtin_text("skins/default.header"), 0); |
| 1612 | @ <br /> |
| 1613 | @ <input type="submit" name="submit" value="Apply Changes" /> |
| 1614 | @ <input type="submit" name="clear" value="Revert To Default" /> |
| 1615 | @ </div></form> |
| 1616 | @ <hr /> |
| @@ -1612,11 +1617,11 @@ | |
| 1617 | @ The default header is shown below for reference. Other examples |
| 1618 | @ of headers can be seen on the <a href="setup_skin">skins page</a>. |
| 1619 | @ See also the <a href="setup_editcss">CSS</a> and |
| 1620 | @ <a href="setup_footer">footer</a> editing screens. |
| 1621 | @ <blockquote><pre> |
| 1622 | @ %h(builtin_text("skins/default.header")) |
| 1623 | @ </pre></blockquote> |
| 1624 | style_footer(); |
| 1625 | db_end_transaction(0); |
| 1626 | } |
| 1627 | |
| @@ -1629,19 +1634,20 @@ | |
| 1634 | login_needed(); |
| 1635 | } |
| 1636 | db_begin_transaction(); |
| 1637 | if( P("clear")!=0 ){ |
| 1638 | db_multi_exec("DELETE FROM config WHERE name='footer'"); |
| 1639 | cgi_replace_parameter("footer", builtin_text("skins/default.footer")); |
| 1640 | } |
| 1641 | |
| 1642 | style_header("Edit Page Footer"); |
| 1643 | @ <form action="%s(g.zTop)/setup_footer" method="post"><div> |
| 1644 | login_insert_csrf_secret(); |
| 1645 | @ <p>Edit HTML text with embedded TH1 (a Tcl dialect) that will be used to |
| 1646 | @ generate the end of every page.</p> |
| 1647 | textarea_attribute("", 20, 80, "footer", "footer", |
| 1648 | builtin_text("skins/default.footer"), 0); |
| 1649 | @ <br /> |
| 1650 | @ <input type="submit" name="submit" value="Apply Changes" /> |
| 1651 | @ <input type="submit" name="clear" value="Revert To Default" /> |
| 1652 | @ </div></form> |
| 1653 | @ <hr /> |
| @@ -1648,11 +1654,11 @@ | |
| 1654 | @ The default footer is shown below for reference. Other examples |
| 1655 | @ of footers can be seen on the <a href="setup_skin">skins page</a>. |
| 1656 | @ See also the <a href="setup_editcss">CSS</a> and |
| 1657 | @ <a href="setup_header">header</a> editing screens. |
| 1658 | @ <blockquote><pre> |
| 1659 | @ %h(builtin_text("skins/default.footer")) |
| 1660 | @ </pre></blockquote> |
| 1661 | style_footer(); |
| 1662 | db_end_transaction(0); |
| 1663 | } |
| 1664 | |
| @@ -1715,13 +1721,15 @@ | |
| 1721 | } |
| 1722 | |
| 1723 | style_header("Edit Ad Unit"); |
| 1724 | @ <form action="%s(g.zTop)/setup_adunit" method="post"><div> |
| 1725 | login_insert_csrf_secret(); |
| 1726 | @ <b>Banner Ad-Unit:</b><br /> |
| 1727 | textarea_attribute("", 6, 80, "adunit", "adunit", "", 0); |
| 1728 | @ <br /> |
| 1729 | @ <b>Right-Column Ad-Unit:</b><br /> |
| 1730 | textarea_attribute("", 6, 80, "adunit-right", "adright", "", 0); |
| 1731 | @ <br /> |
| 1732 | onoff_attribute("Omit ads to administrator", |
| 1733 | "adunit-omit-if-admin", "oia", 0, 0); |
| 1734 | @ <br /> |
| 1735 | onoff_attribute("Omit ads to logged-in users", |
| @@ -1728,10 +1736,41 @@ | |
| 1736 | "adunit-omit-if-user", "oiu", 0, 0); |
| 1737 | @ <br /> |
| 1738 | @ <input type="submit" name="submit" value="Apply Changes" /> |
| 1739 | @ <input type="submit" name="clear" value="Delete Ad-Unit" /> |
| 1740 | @ </div></form> |
| 1741 | @ <hr /> |
| 1742 | @ <b>Ad-Unit Notes:</b><ul> |
| 1743 | @ <li>Leave both Ad-Units blank to disable all advertising. |
| 1744 | @ <li>The "Banner Ad-Unit" is used for wide pages. |
| 1745 | @ <li>The "Right-Column Ad-Unit" is used on pages with tall, narrow content. |
| 1746 | @ <li>If the "Right-Column Ad-Unit" is blank, the "Banner Ad-Unit" is used on all pages. |
| 1747 | @ <li>Suggested <a href="setup_editcss">CSS</a> changes: |
| 1748 | @ <blockquote><pre> |
| 1749 | @ div.adunit_banner { |
| 1750 | @ margin: auto; |
| 1751 | @ width: 100%; |
| 1752 | @ } |
| 1753 | @ div.adunit_right { |
| 1754 | @ float: right; |
| 1755 | @ } |
| 1756 | @ div.adunit_right_container { |
| 1757 | @ min-height: <i>height-of-right-column-ad-unit</i>; |
| 1758 | @ } |
| 1759 | @ </pre></blockquote> |
| 1760 | @ <li>For a place-holder Ad-Unit for testing, Copy/Paste the following |
| 1761 | @ with appropriate adjustments to "width:" and "height:". |
| 1762 | @ <blockquote><pre> |
| 1763 | @ <div style=' |
| 1764 | @ margin: 0 auto; |
| 1765 | @ width: 600px; |
| 1766 | @ height: 90px; |
| 1767 | @ border: 1px solid #f11; |
| 1768 | @ background-color: #fcc; |
| 1769 | @ '>Demo Ad</div> |
| 1770 | @ </pre></blockquote> |
| 1771 | @ </li> |
| 1772 | style_footer(); |
| 1773 | db_end_transaction(0); |
| 1774 | } |
| 1775 | |
| 1776 | /* |
| 1777 |
+1
| --- src/sitemap.c | ||
| +++ src/sitemap.c | ||
| @@ -27,10 +27,11 @@ | ||
| 27 | 27 | ** Show an incomplete list of web pages offered by the Fossil web engine. |
| 28 | 28 | */ |
| 29 | 29 | void sitemap_page(void){ |
| 30 | 30 | login_check_credentials(); |
| 31 | 31 | style_header("Site Map"); |
| 32 | + style_adunit_config(ADUNIT_RIGHT_OK); | |
| 32 | 33 | @ <p> |
| 33 | 34 | @ The following links are just a few of the many web-pages available for |
| 34 | 35 | @ this Fossil repository: |
| 35 | 36 | @ </p> |
| 36 | 37 | @ |
| 37 | 38 |
| --- src/sitemap.c | |
| +++ src/sitemap.c | |
| @@ -27,10 +27,11 @@ | |
| 27 | ** Show an incomplete list of web pages offered by the Fossil web engine. |
| 28 | */ |
| 29 | void sitemap_page(void){ |
| 30 | login_check_credentials(); |
| 31 | style_header("Site Map"); |
| 32 | @ <p> |
| 33 | @ The following links are just a few of the many web-pages available for |
| 34 | @ this Fossil repository: |
| 35 | @ </p> |
| 36 | @ |
| 37 |
| --- src/sitemap.c | |
| +++ src/sitemap.c | |
| @@ -27,10 +27,11 @@ | |
| 27 | ** Show an incomplete list of web pages offered by the Fossil web engine. |
| 28 | */ |
| 29 | void sitemap_page(void){ |
| 30 | login_check_credentials(); |
| 31 | style_header("Site Map"); |
| 32 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 33 | @ <p> |
| 34 | @ The following links are just a few of the many web-pages available for |
| 35 | @ this Fossil repository: |
| 36 | @ </p> |
| 37 | @ |
| 38 |
+196
-1310
| --- src/skins.c | ||
| +++ src/skins.c | ||
| @@ -19,1255 +19,38 @@ | ||
| 19 | 19 | */ |
| 20 | 20 | #include "config.h" |
| 21 | 21 | #include <assert.h> |
| 22 | 22 | #include "skins.h" |
| 23 | 23 | |
| 24 | -/* @-comment: ## */ | |
| 25 | -/* | |
| 26 | -** A black-and-white theme with the project title in a bar across the top | |
| 27 | -** and no logo image. | |
| 28 | -*/ | |
| 29 | -static const char zBuiltinSkin1[] = | |
| 30 | -@ REPLACE INTO config(name,mtime,value) | |
| 31 | -@ VALUES('css',now(),'/* General settings for the entire page */ | |
| 32 | -@ body { | |
| 33 | -@ margin: 0ex 1ex; | |
| 34 | -@ padding: 0px; | |
| 35 | -@ background-color: white; | |
| 36 | -@ font-family: sans-serif; | |
| 37 | -@ } | |
| 38 | -@ | |
| 39 | -@ /* The project logo in the upper left-hand corner of each page */ | |
| 40 | -@ div.logo { | |
| 41 | -@ display: table-row; | |
| 42 | -@ text-align: center; | |
| 43 | -@ /* vertical-align: bottom;*/ | |
| 44 | -@ font-size: 2em; | |
| 45 | -@ font-weight: bold; | |
| 46 | -@ background-color: #707070; | |
| 47 | -@ color: #ffffff; | |
| 48 | -@ min-width: 200px; | |
| 49 | -@ white-space: nowrap; | |
| 50 | -@ } | |
| 51 | -@ | |
| 52 | -@ /* The page title centered at the top of each page */ | |
| 53 | -@ div.title { | |
| 54 | -@ display: table-cell; | |
| 55 | -@ font-size: 1.5em; | |
| 56 | -@ font-weight: bold; | |
| 57 | -@ text-align: center; | |
| 58 | -@ padding: 0 0 0 10px; | |
| 59 | -@ color: #404040; | |
| 60 | -@ vertical-align: bottom; | |
| 61 | -@ width: 100%; | |
| 62 | -@ } | |
| 63 | -@ | |
| 64 | -@ /* The login status message in the top right-hand corner */ | |
| 65 | -@ div.status { | |
| 66 | -@ display: table-cell; | |
| 67 | -@ text-align: right; | |
| 68 | -@ vertical-align: bottom; | |
| 69 | -@ color: #404040; | |
| 70 | -@ font-size: 0.8em; | |
| 71 | -@ font-weight: bold; | |
| 72 | -@ min-width: 200px; | |
| 73 | -@ white-space: nowrap; | |
| 74 | -@ } | |
| 75 | -@ | |
| 76 | -@ /* The header across the top of the page */ | |
| 77 | -@ div.header { | |
| 78 | -@ display: table; | |
| 79 | -@ width: 100%; | |
| 80 | -@ } | |
| 81 | -@ | |
| 82 | -@ /* The main menu bar that appears at the top of the page beneath | |
| 83 | -@ ** the header */ | |
| 84 | -@ div.mainmenu { | |
| 85 | -@ padding: 5px 10px 5px 10px; | |
| 86 | -@ font-size: 0.9em; | |
| 87 | -@ font-weight: bold; | |
| 88 | -@ text-align: center; | |
| 89 | -@ letter-spacing: 1px; | |
| 90 | -@ background-color: #404040; | |
| 91 | -@ color: white; | |
| 92 | -@ } | |
| 93 | -@ | |
| 94 | -@ /* The submenu bar that *sometimes* appears below the main menu */ | |
| 95 | -@ div.submenu, div.sectionmenu { | |
| 96 | -@ padding: 3px 10px 3px 0px; | |
| 97 | -@ font-size: 0.9em; | |
| 98 | -@ text-align: center; | |
| 99 | -@ background-color: #606060; | |
| 100 | -@ color: white; | |
| 101 | -@ } | |
| 102 | -@ div.mainmenu a, div.mainmenu a:visited, div.submenu a, div.submenu a:visited, | |
| 103 | -@ div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited { | |
| 104 | -@ padding: 3px 10px 3px 10px; | |
| 105 | -@ color: white; | |
| 106 | -@ text-decoration: none; | |
| 107 | -@ } | |
| 108 | -@ div.mainmenu a:hover, div.submenu a:hover, div.sectionmenu>a.button:hover { | |
| 109 | -@ color: #404040; | |
| 110 | -@ background-color: white; | |
| 111 | -@ } | |
| 112 | -@ | |
| 113 | -@ /* All page content from the bottom of the menu or submenu down to | |
| 114 | -@ ** the footer */ | |
| 115 | -@ div.content { | |
| 116 | -@ padding: 0ex 0ex 0ex 0ex; | |
| 117 | -@ } | |
| 118 | -@ /* Hyperlink colors */ | |
| 119 | -@ div.content a { color: #604000; } | |
| 120 | -@ div.content a:link { color: #604000;} | |
| 121 | -@ div.content a:visited { color: #600000; } | |
| 122 | -@ | |
| 123 | -@ /* <verbatim> blocks */ | |
| 124 | -@ pre.verbatim { | |
| 125 | -@ background-color: #ffffff; | |
| 126 | -@ padding: 0.5em; | |
| 127 | -@ white-space: pre-wrap; | |
| 128 | -@ } | |
| 129 | -@ | |
| 130 | -@ /* Some pages have section dividers */ | |
| 131 | -@ div.section { | |
| 132 | -@ margin-bottom: 0px; | |
| 133 | -@ margin-top: 1em; | |
| 134 | -@ padding: 1px 1px 1px 1px; | |
| 135 | -@ font-size: 1.2em; | |
| 136 | -@ font-weight: bold; | |
| 137 | -@ background-color: #404040; | |
| 138 | -@ color: white; | |
| 139 | -@ white-space: nowrap; | |
| 140 | -@ } | |
| 141 | -@ | |
| 142 | -@ /* The "Date" that occurs on the left hand side of timelines */ | |
| 143 | -@ div.divider { | |
| 144 | -@ background: #a0a0a0; | |
| 145 | -@ border: 2px #505050 solid; | |
| 146 | -@ font-size: 1em; font-weight: normal; | |
| 147 | -@ padding: .25em; | |
| 148 | -@ margin: .2em 0 .2em 0; | |
| 149 | -@ float: left; | |
| 150 | -@ clear: left; | |
| 151 | -@ white-space: nowrap; | |
| 152 | -@ } | |
| 153 | -@ | |
| 154 | -@ /* The footer at the very bottom of the page */ | |
| 155 | -@ div.footer { | |
| 156 | -@ font-size: 0.8em; | |
| 157 | -@ margin-top: 12px; | |
| 158 | -@ padding: 5px 10px 5px 10px; | |
| 159 | -@ text-align: right; | |
| 160 | -@ background-color: #404040; | |
| 161 | -@ color: white; | |
| 162 | -@ } | |
| 163 | -@ | |
| 164 | -@ /* The label/value pairs on (for example) the vinfo page */ | |
| 165 | -@ table.label-value th { | |
| 166 | -@ vertical-align: top; | |
| 167 | -@ text-align: right; | |
| 168 | -@ padding: 0.2ex 2ex; | |
| 169 | -@ }'); | |
| 170 | -@ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html> | |
| 171 | -@ <head> | |
| 172 | -@ <base href="$baseurl/$current_page" /> | |
| 173 | -@ <title>$<project_name>: $<title></title> | |
| 174 | -@ <link rel="alternate" type="application/rss+xml" title="RSS Feed" | |
| 175 | -@ href="$home/timeline.rss"> | |
| 176 | -@ <link rel="stylesheet" href="$stylesheet_url" type="text/css" | |
| 177 | -@ media="screen"> | |
| 178 | -@ </head> | |
| 179 | -@ <body> | |
| 180 | -@ <div class="header"> | |
| 181 | -@ <div class="title"><small>$<project_name></small><br />$<title></div> | |
| 182 | -@ <div class="status"><th1> | |
| 183 | -@ if {[info exists login]} { | |
| 184 | -@ puts "Logged in as $login" | |
| 185 | -@ } else { | |
| 186 | -@ puts "Not logged in" | |
| 187 | -@ } | |
| 188 | -@ </th1></div> | |
| 189 | -@ </div> | |
| 190 | -@ <div class="mainmenu"> | |
| 191 | -@ <th1> | |
| 192 | -@ html "<a href=''$home$index_page''>Home</a>\n" | |
| 193 | -@ if {[anycap jor]} { | |
| 194 | -@ html "<a href=''$home/timeline''>Timeline</a>\n" | |
| 195 | -@ } | |
| 196 | -@ if {[hascap oh]} { | |
| 197 | -@ html "<a href=''$home/tree?ci=tip''>Files</a>\n" | |
| 198 | -@ } | |
| 199 | -@ if {[hascap o]} { | |
| 200 | -@ html "<a href=''$home/brlist''>Branches</a>\n" | |
| 201 | -@ html "<a href=''$home/taglist''>Tags</a>\n" | |
| 202 | -@ } | |
| 203 | -@ if {[hascap r]} { | |
| 204 | -@ html "<a href=''$home/reportlist''>Tickets</a>\n" | |
| 205 | -@ } | |
| 206 | -@ if {[hascap j]} { | |
| 207 | -@ html "<a href=''$home/wiki''>Wiki</a>\n" | |
| 208 | -@ } | |
| 209 | -@ if {[hascap s]} { | |
| 210 | -@ html "<a href=''$home/setup''>Admin</a>\n" | |
| 211 | -@ } elseif {[hascap a]} { | |
| 212 | -@ html "<a href=''$home/setup_ulist''>Users</a>\n" | |
| 213 | -@ } | |
| 214 | -@ if {[info exists login]} { | |
| 215 | -@ html "<a href=''$home/login''>Logout</a>\n" | |
| 216 | -@ } else { | |
| 217 | -@ html "<a href=''$home/login''>Login</a>\n" | |
| 218 | -@ } | |
| 219 | -@ </th1></div> | |
| 220 | -@ '); | |
| 221 | -@ REPLACE INTO config(name,mtime,value) | |
| 222 | -@ VALUES('footer',now(),'<div class="footer"> | |
| 223 | -@ Fossil version $manifest_version $manifest_date | |
| 224 | -@ </div> | |
| 225 | -@ </body></html> | |
| 226 | -@ '); | |
| 227 | -; | |
| 228 | - | |
| 229 | -/* | |
| 230 | -** A tan theme with the project title above the user identification | |
| 231 | -** and no logo image. | |
| 232 | -*/ | |
| 233 | -static const char zBuiltinSkin2[] = | |
| 234 | -@ REPLACE INTO config(name,mtime,value) | |
| 235 | -@ VALUES('css',now(),'/* General settings for the entire page */ | |
| 236 | -@ body { | |
| 237 | -@ margin: 0ex 0ex; | |
| 238 | -@ padding: 0px; | |
| 239 | -@ background-color: #fef3bc; | |
| 240 | -@ font-family: sans-serif; | |
| 241 | -@ } | |
| 242 | -@ | |
| 243 | -@ /* The project logo in the upper left-hand corner of each page */ | |
| 244 | -@ div.logo { | |
| 245 | -@ display: inline; | |
| 246 | -@ text-align: center; | |
| 247 | -@ vertical-align: bottom; | |
| 248 | -@ font-weight: bold; | |
| 249 | -@ font-size: 2.5em; | |
| 250 | -@ color: #a09048; | |
| 251 | -@ white-space: nowrap; | |
| 252 | -@ } | |
| 253 | -@ | |
| 254 | -@ /* The page title centered at the top of each page */ | |
| 255 | -@ div.title { | |
| 256 | -@ display: table-cell; | |
| 257 | -@ font-size: 2em; | |
| 258 | -@ font-weight: bold; | |
| 259 | -@ text-align: left; | |
| 260 | -@ padding: 0 0 0 5px; | |
| 261 | -@ color: #a09048; | |
| 262 | -@ vertical-align: bottom; | |
| 263 | -@ width: 100%; | |
| 264 | -@ } | |
| 265 | -@ | |
| 266 | -@ /* The login status message in the top right-hand corner */ | |
| 267 | -@ div.status { | |
| 268 | -@ display: table-cell; | |
| 269 | -@ text-align: right; | |
| 270 | -@ vertical-align: bottom; | |
| 271 | -@ color: #a09048; | |
| 272 | -@ padding: 5px 5px 0 0; | |
| 273 | -@ font-size: 0.8em; | |
| 274 | -@ font-weight: bold; | |
| 275 | -@ white-space: nowrap; | |
| 276 | -@ } | |
| 277 | -@ | |
| 278 | -@ /* The header across the top of the page */ | |
| 279 | -@ div.header { | |
| 280 | -@ display: table; | |
| 281 | -@ width: 100%; | |
| 282 | -@ } | |
| 283 | -@ | |
| 284 | -@ /* The main menu bar that appears at the top of the page beneath | |
| 285 | -@ ** the header */ | |
| 286 | -@ div.mainmenu { | |
| 287 | -@ padding: 5px 10px 5px 10px; | |
| 288 | -@ font-size: 0.9em; | |
| 289 | -@ font-weight: bold; | |
| 290 | -@ text-align: center; | |
| 291 | -@ letter-spacing: 1px; | |
| 292 | -@ background-color: #a09048; | |
| 293 | -@ color: black; | |
| 294 | -@ } | |
| 295 | -@ | |
| 296 | -@ /* The submenu bar that *sometimes* appears below the main menu */ | |
| 297 | -@ div.submenu, div.sectionmenu { | |
| 298 | -@ padding: 3px 10px 3px 0px; | |
| 299 | -@ font-size: 0.9em; | |
| 300 | -@ text-align: center; | |
| 301 | -@ background-color: #c0af58; | |
| 302 | -@ color: white; | |
| 303 | -@ } | |
| 304 | -@ div.mainmenu a, div.mainmenu a:visited, div.submenu a, div.submenu a:visited, | |
| 305 | -@ div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited { | |
| 306 | -@ padding: 3px 10px 3px 10px; | |
| 307 | -@ color: white; | |
| 308 | -@ text-decoration: none; | |
| 309 | -@ } | |
| 310 | -@ div.mainmenu a:hover, div.submenu a:hover, div.sectionmenu>a.button:hover { | |
| 311 | -@ color: #a09048; | |
| 312 | -@ background-color: white; | |
| 313 | -@ } | |
| 314 | -@ | |
| 315 | -@ /* All page content from the bottom of the menu or submenu down to | |
| 316 | -@ ** the footer */ | |
| 317 | -@ div.content { | |
| 318 | -@ padding: 1ex 5px; | |
| 319 | -@ } | |
| 320 | -@ div.content a { color: #706532; } | |
| 321 | -@ div.content a:link { color: #706532; } | |
| 322 | -@ div.content a:visited { color: #704032; } | |
| 323 | -@ div.content a:hover { background-color: white; color: #706532; } | |
| 324 | -@ | |
| 325 | -@ /* Some pages have section dividers */ | |
| 326 | -@ div.section { | |
| 327 | -@ margin-bottom: 0px; | |
| 328 | -@ margin-top: 1em; | |
| 329 | -@ padding: 3px 3px 0 3px; | |
| 330 | -@ font-size: 1.2em; | |
| 331 | -@ font-weight: bold; | |
| 332 | -@ background-color: #a09048; | |
| 333 | -@ color: white; | |
| 334 | -@ white-space: nowrap; | |
| 335 | -@ } | |
| 336 | -@ | |
| 337 | -@ /* The "Date" that occurs on the left hand side of timelines */ | |
| 338 | -@ div.divider { | |
| 339 | -@ background: #e1d498; | |
| 340 | -@ border: 2px #a09048 solid; | |
| 341 | -@ font-size: 1em; font-weight: normal; | |
| 342 | -@ padding: .25em; | |
| 343 | -@ margin: .2em 0 .2em 0; | |
| 344 | -@ float: left; | |
| 345 | -@ clear: left; | |
| 346 | -@ white-space: nowrap; | |
| 347 | -@ } | |
| 348 | -@ | |
| 349 | -@ /* The footer at the very bottom of the page */ | |
| 350 | -@ div.footer { | |
| 351 | -@ font-size: 0.8em; | |
| 352 | -@ margin-top: 12px; | |
| 353 | -@ padding: 5px 10px 5px 10px; | |
| 354 | -@ text-align: right; | |
| 355 | -@ background-color: #a09048; | |
| 356 | -@ color: white; | |
| 357 | -@ } | |
| 358 | -@ | |
| 359 | -@ /* Hyperlink colors */ | |
| 360 | -@ div.footer a { color: white; } | |
| 361 | -@ div.footer a:link { color: white; } | |
| 362 | -@ div.footer a:visited { color: white; } | |
| 363 | -@ div.footer a:hover { background-color: white; color: #558195; } | |
| 364 | -@ | |
| 365 | -@ /* <verbatim> blocks */ | |
| 366 | -@ pre.verbatim { | |
| 367 | -@ background-color: #f5f5f5; | |
| 368 | -@ padding: 0.5em; | |
| 369 | -@ white-space: pre-wrap; | |
| 370 | -@ } | |
| 371 | -@ | |
| 372 | -@ /* The label/value pairs on (for example) the ci page */ | |
| 373 | -@ table.label-value th { | |
| 374 | -@ vertical-align: top; | |
| 375 | -@ text-align: right; | |
| 376 | -@ padding: 0.2ex 2ex; | |
| 377 | -@ }'); | |
| 378 | -@ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html> | |
| 379 | -@ <head> | |
| 380 | -@ <base href="$baseurl/$current_page" /> | |
| 381 | -@ <title>$<project_name>: $<title></title> | |
| 382 | -@ <link rel="alternate" type="application/rss+xml" title="RSS Feed" | |
| 383 | -@ href="$home/timeline.rss"> | |
| 384 | -@ <link rel="stylesheet" href="$stylesheet_url" type="text/css" | |
| 385 | -@ media="screen"> | |
| 386 | -@ </head> | |
| 387 | -@ <body> | |
| 388 | -@ <div class="header"> | |
| 389 | -@ <div class="title">$<title></div> | |
| 390 | -@ <div class="status"> | |
| 391 | -@ <div class="logo">$<project_name></div><br/> | |
| 392 | -@ <th1> | |
| 393 | -@ if {[info exists login]} { | |
| 394 | -@ puts "Logged in as $login" | |
| 395 | -@ } else { | |
| 396 | -@ puts "Not logged in" | |
| 397 | -@ } | |
| 398 | -@ </th1></div> | |
| 399 | -@ </div> | |
| 400 | -@ <div class="mainmenu"> | |
| 401 | -@ <th1> | |
| 402 | -@ html "<a href=''$home$index_page''>Home</a>\n" | |
| 403 | -@ if {[anycap jor]} { | |
| 404 | -@ html "<a href=''$home/timeline''>Timeline</a>\n" | |
| 405 | -@ } | |
| 406 | -@ if {[hascap oh]} { | |
| 407 | -@ html "<a href=''$home/tree?ci=tip''>Files</a>\n" | |
| 408 | -@ } | |
| 409 | -@ if {[hascap o]} { | |
| 410 | -@ html "<a href=''$home/brlist''>Branches</a>\n" | |
| 411 | -@ html "<a href=''$home/taglist''>Tags</a>\n" | |
| 412 | -@ } | |
| 413 | -@ if {[hascap r]} { | |
| 414 | -@ html "<a href=''$home/reportlist''>Tickets</a>\n" | |
| 415 | -@ } | |
| 416 | -@ if {[hascap j]} { | |
| 417 | -@ html "<a href=''$home/wiki''>Wiki</a>\n" | |
| 418 | -@ } | |
| 419 | -@ if {[hascap s]} { | |
| 420 | -@ html "<a href=''$home/setup''>Admin</a>\n" | |
| 421 | -@ } elseif {[hascap a]} { | |
| 422 | -@ html "<a href=''$home/setup_ulist''>Users</a>\n" | |
| 423 | -@ } | |
| 424 | -@ if {[info exists login]} { | |
| 425 | -@ html "<a href=''$home/login''>Logout</a>\n" | |
| 426 | -@ } else { | |
| 427 | -@ html "<a href=''$home/login''>Login</a>\n" | |
| 428 | -@ } | |
| 429 | -@ </th1></div> | |
| 430 | -@ '); | |
| 431 | -@ REPLACE INTO config(name,mtime,value) | |
| 432 | -@ VALUES('footer',now(),'<div class="footer"> | |
| 433 | -@ Fossil version $manifest_version $manifest_date | |
| 434 | -@ </div> | |
| 435 | -@ </body></html> | |
| 436 | -@ '); | |
| 437 | -; | |
| 438 | - | |
| 439 | -/* | |
| 440 | -** Black letters on a white or cream background with the main menu | |
| 441 | -** stuck on the left-hand side. | |
| 442 | -*/ | |
| 443 | -static const char zBuiltinSkin3[] = | |
| 444 | -@ REPLACE INTO config(name,mtime,value) | |
| 445 | -@ VALUES('css',now(),'/* General settings for the entire page */ | |
| 446 | -@ body { | |
| 447 | -@ margin:0px 0px 0px 0px; | |
| 448 | -@ padding:0px; | |
| 449 | -@ font-family:verdana, arial, helvetica, "sans serif"; | |
| 450 | -@ color:#333; | |
| 451 | -@ background-color:white; | |
| 452 | -@ } | |
| 453 | -@ | |
| 454 | -@ /* consistent colours */ | |
| 455 | -@ h2 { | |
| 456 | -@ color: #333; | |
| 457 | -@ } | |
| 458 | -@ h3 { | |
| 459 | -@ color: #333; | |
| 460 | -@ } | |
| 461 | -@ | |
| 462 | -@ /* The project logo in the upper left-hand corner of each page */ | |
| 463 | -@ div.logo { | |
| 464 | -@ display: table-cell; | |
| 465 | -@ text-align: left; | |
| 466 | -@ vertical-align: bottom; | |
| 467 | -@ font-weight: bold; | |
| 468 | -@ color: #333; | |
| 469 | -@ white-space: nowrap; | |
| 470 | -@ } | |
| 471 | -@ | |
| 472 | -@ /* The page title centered at the top of each page */ | |
| 473 | -@ div.title { | |
| 474 | -@ display: table-cell; | |
| 475 | -@ font-size: 2em; | |
| 476 | -@ font-weight: bold; | |
| 477 | -@ text-align: center; | |
| 478 | -@ color: #333; | |
| 479 | -@ vertical-align: bottom; | |
| 480 | -@ width: 100%; | |
| 481 | -@ } | |
| 482 | -@ | |
| 483 | -@ /* The login status message in the top right-hand corner */ | |
| 484 | -@ div.status { | |
| 485 | -@ display: table-cell; | |
| 486 | -@ padding-right: 10px; | |
| 487 | -@ text-align: right; | |
| 488 | -@ vertical-align: bottom; | |
| 489 | -@ padding-bottom: 5px; | |
| 490 | -@ color: #333; | |
| 491 | -@ font-size: 0.8em; | |
| 492 | -@ font-weight: bold; | |
| 493 | -@ white-space: nowrap; | |
| 494 | -@ } | |
| 495 | -@ | |
| 496 | -@ /* The header across the top of the page */ | |
| 497 | -@ div.header { | |
| 498 | -@ margin:10px 0px 10px 0px; | |
| 499 | -@ padding:1px 0px 0px 20px; | |
| 500 | -@ border-style:solid; | |
| 501 | -@ border-color:black; | |
| 502 | -@ border-width:1px 0px; | |
| 503 | -@ background-color:#eee; | |
| 504 | -@ } | |
| 505 | -@ | |
| 506 | -@ /* The main menu bar that appears at the top left of the page beneath | |
| 507 | -@ ** the header. Width must be co-ordinated with the container below */ | |
| 508 | -@ div.mainmenu { | |
| 509 | -@ float: left; | |
| 510 | -@ margin-left: 10px; | |
| 511 | -@ margin-right: 10px; | |
| 512 | -@ font-size: 0.9em; | |
| 513 | -@ font-weight: bold; | |
| 514 | -@ padding:5px; | |
| 515 | -@ background-color:#eee; | |
| 516 | -@ border:1px solid #999; | |
| 517 | -@ width:8em; | |
| 518 | -@ } | |
| 519 | -@ | |
| 520 | -@ /* Main menu is now a list */ | |
| 521 | -@ div.mainmenu ul { | |
| 522 | -@ padding: 0; | |
| 523 | -@ list-style:none; | |
| 524 | -@ } | |
| 525 | -@ div.mainmenu a, div.mainmenu a:visited{ | |
| 526 | -@ padding: 1px 10px 1px 10px; | |
| 527 | -@ color: #333; | |
| 528 | -@ text-decoration: none; | |
| 529 | -@ } | |
| 530 | -@ div.mainmenu a:hover { | |
| 531 | -@ color: #eee; | |
| 532 | -@ background-color: #333; | |
| 533 | -@ } | |
| 534 | -@ | |
| 535 | -@ /* Container for the sub-menu and content so they don''t spread | |
| 536 | -@ ** out underneath the main menu */ | |
| 537 | -@ #container { | |
| 538 | -@ padding-left: 9em; | |
| 539 | -@ } | |
| 540 | -@ | |
| 541 | -@ /* The submenu bar that *sometimes* appears below the main menu */ | |
| 542 | -@ div.submenu, div.sectionmenu { | |
| 543 | -@ padding: 3px 10px 3px 10px; | |
| 544 | -@ font-size: 0.9em; | |
| 545 | -@ text-align: center; | |
| 546 | -@ border:1px solid #999; | |
| 547 | -@ border-width:1px 0px; | |
| 548 | -@ background-color: #eee; | |
| 549 | -@ color: #333; | |
| 550 | -@ } | |
| 551 | -@ div.submenu a, div.submenu a:visited, div.sectionmenu>a.button:link, | |
| 552 | -@ div.sectionmenu>a.button:visited { | |
| 553 | -@ padding: 3px 10px 3px 10px; | |
| 554 | -@ color: #333; | |
| 555 | -@ text-decoration: none; | |
| 556 | -@ } | |
| 557 | -@ div.submenu a:hover, div.sectionmenu>a.button:hover { | |
| 558 | -@ color: #eee; | |
| 559 | -@ background-color: #333; | |
| 560 | -@ } | |
| 561 | -@ | |
| 562 | -@ /* All page content from the bottom of the menu or submenu down to | |
| 563 | -@ ** the footer */ | |
| 564 | -@ div.content { | |
| 565 | -@ padding: 2ex 1ex 0ex 2ex; | |
| 566 | -@ } | |
| 567 | -@ | |
| 568 | -@ /* Some pages have section dividers */ | |
| 569 | -@ div.section { | |
| 570 | -@ margin-bottom: 0px; | |
| 571 | -@ margin-top: 1em; | |
| 572 | -@ padding: 1px 1px 1px 1px; | |
| 573 | -@ font-size: 1.2em; | |
| 574 | -@ font-weight: bold; | |
| 575 | -@ border-style:solid; | |
| 576 | -@ border-color:#999; | |
| 577 | -@ border-width:1px 0px; | |
| 578 | -@ background-color: #eee; | |
| 579 | -@ color: #333; | |
| 580 | -@ white-space: nowrap; | |
| 581 | -@ } | |
| 582 | -@ | |
| 583 | -@ /* The "Date" that occurs on the left hand side of timelines */ | |
| 584 | -@ div.divider { | |
| 585 | -@ background: #eee; | |
| 586 | -@ border: 2px #999 solid; | |
| 587 | -@ font-size: 1em; font-weight: normal; | |
| 588 | -@ padding: .25em; | |
| 589 | -@ margin: .2em 0 .2em 0; | |
| 590 | -@ float: left; | |
| 591 | -@ clear: left; | |
| 592 | -@ color: #333; | |
| 593 | -@ white-space: nowrap; | |
| 594 | -@ } | |
| 595 | -@ | |
| 596 | -@ /* The footer at the very bottom of the page */ | |
| 597 | -@ div.footer { | |
| 598 | -@ font-size: 0.8em; | |
| 599 | -@ margin-top: 12px; | |
| 600 | -@ padding: 5px 10px 5px 10px; | |
| 601 | -@ text-align: right; | |
| 602 | -@ background-color: #eee; | |
| 603 | -@ color: #555; | |
| 604 | -@ } | |
| 605 | -@ | |
| 606 | -@ /* <verbatim> blocks */ | |
| 607 | -@ pre.verbatim { | |
| 608 | -@ background-color: #f5f5f5; | |
| 609 | -@ padding: 0.5em; | |
| 610 | -@ white-space: pre-wrap; | |
| 611 | -@ } | |
| 612 | -@ | |
| 613 | -@ /* The label/value pairs on (for example) the ci page */ | |
| 614 | -@ table.label-value th { | |
| 615 | -@ vertical-align: top; | |
| 616 | -@ text-align: right; | |
| 617 | -@ padding: 0.2ex 2ex; | |
| 618 | -@ }'); | |
| 619 | -@ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html> | |
| 620 | -@ <head> | |
| 621 | -@ <base href="$baseurl/$current_page" /> | |
| 622 | -@ <title>$<project_name>: $<title></title> | |
| 623 | -@ <link rel="alternate" type="application/rss+xml" title="RSS Feed" | |
| 624 | -@ href="$home/timeline.rss"> | |
| 625 | -@ <link rel="stylesheet" href="$stylesheet_url" type="text/css" | |
| 626 | -@ media="screen"> | |
| 627 | -@ </head> | |
| 628 | -@ <body> | |
| 629 | -@ <div class="header"> | |
| 630 | -@ <div class="logo"> | |
| 631 | -@ <img src="$logo_image_url" alt="logo"> | |
| 632 | -@ <br />$<project_name> | |
| 633 | -@ </div> | |
| 634 | -@ <div class="title">$<title></div> | |
| 635 | -@ <div class="status"><th1> | |
| 636 | -@ if {[info exists login]} { | |
| 637 | -@ puts "Logged in as $login" | |
| 638 | -@ } else { | |
| 639 | -@ puts "Not logged in" | |
| 640 | -@ } | |
| 641 | -@ </th1></div> | |
| 642 | -@ </div> | |
| 643 | -@ <div class="mainmenu"> | |
| 644 | -@ <th1> | |
| 645 | -@ html "<a href=''$home$index_page''>Home</a>\n" | |
| 646 | -@ if {[anycap jor]} { | |
| 647 | -@ html "<a href=''$home/timeline''>Timeline</a>\n" | |
| 648 | -@ } | |
| 649 | -@ if {[hascap oh]} { | |
| 650 | -@ html "<a href=''$home/tree?ci=tip''>Files</a>\n" | |
| 651 | -@ } | |
| 652 | -@ if {[hascap o]} { | |
| 653 | -@ html "<a href=''$home/brlist''>Branches</a>\n" | |
| 654 | -@ html "<a href=''$home/taglist''>Tags</a>\n" | |
| 655 | -@ } | |
| 656 | -@ if {[hascap r]} { | |
| 657 | -@ html "<a href=''$home/reportlist''>Tickets</a>\n" | |
| 658 | -@ } | |
| 659 | -@ if {[hascap j]} { | |
| 660 | -@ html "<a href=''$home/wiki''>Wiki</a>\n" | |
| 661 | -@ } | |
| 662 | -@ if {[hascap s]} { | |
| 663 | -@ html "<a href=''$home/setup''>Admin</a>\n" | |
| 664 | -@ } elseif {[hascap a]} { | |
| 665 | -@ html "<a href=''$home/setup_ulist''>Users</a>\n" | |
| 666 | -@ } | |
| 667 | -@ if {[info exists login]} { | |
| 668 | -@ html "<a href=''$home/login''>Logout</a>\n" | |
| 669 | -@ } else { | |
| 670 | -@ html "<a href=''$home/login''>Login</a>\n" | |
| 671 | -@ } | |
| 672 | -@ </th1></ul></div> | |
| 673 | -@ <div id="container"> | |
| 674 | -@ '); | |
| 675 | -@ REPLACE INTO config(name,mtime,value) VALUES('footer',now(),'</div> | |
| 676 | -@ <div class="footer"> | |
| 677 | -@ Fossil version $manifest_version $manifest_date | |
| 678 | -@ </div> | |
| 679 | -@ </body></html> | |
| 680 | -@ '); | |
| 681 | -; | |
| 682 | - | |
| 683 | - | |
| 684 | -/* | |
| 685 | -** Shadow boxes and rounded corners. | |
| 686 | -*/ | |
| 687 | -static const char zBuiltinSkin4[] = | |
| 688 | -@ REPLACE INTO config(name,mtime,value) | |
| 689 | -@ VALUES('css',now(),'/* General settings for the entire page */ | |
| 690 | -@ html { | |
| 691 | -@ min-height: 100%; | |
| 692 | -@ } | |
| 693 | -@ body { | |
| 694 | -@ margin: 0ex 1ex; | |
| 695 | -@ padding: 0px; | |
| 696 | -@ background-color: white; | |
| 697 | -@ color: #333; | |
| 698 | -@ font-family: Verdana, sans-serif; | |
| 699 | -@ font-size: 0.8em; | |
| 700 | -@ } | |
| 701 | -@ | |
| 702 | -@ /* The project logo in the upper left-hand corner of each page */ | |
| 703 | -@ div.logo { | |
| 704 | -@ display: table-cell; | |
| 705 | -@ text-align: right; | |
| 706 | -@ vertical-align: bottom; | |
| 707 | -@ font-weight: normal; | |
| 708 | -@ white-space: nowrap; | |
| 709 | -@ } | |
| 710 | -@ | |
| 711 | -@ /* Widths */ | |
| 712 | -@ div.header, div.mainmenu, div.submenu, div.content, div.footer { | |
| 713 | -@ max-width: 900px; | |
| 714 | -@ margin: auto; | |
| 715 | -@ padding: 3px 20px 3px 20px; | |
| 716 | -@ clear: both; | |
| 717 | -@ } | |
| 718 | -@ | |
| 719 | -@ /* The page title at the top of each page */ | |
| 720 | -@ div.title { | |
| 721 | -@ display: table-cell; | |
| 722 | -@ padding-left: 10px; | |
| 723 | -@ font-size: 2em; | |
| 724 | -@ margin: 10px 0 10px -20px; | |
| 725 | -@ vertical-align: bottom; | |
| 726 | -@ text-align: left; | |
| 727 | -@ width: 80%; | |
| 728 | -@ font-family: Verdana, sans-serif; | |
| 729 | -@ font-weight: bold; | |
| 730 | -@ color: #558195; | |
| 731 | -@ text-shadow: 0px 2px 2px #999999; | |
| 732 | -@ } | |
| 733 | -@ | |
| 734 | -@ /* The login status message in the top right-hand corner */ | |
| 735 | -@ div.status { | |
| 736 | -@ display: table-cell; | |
| 737 | -@ text-align: right; | |
| 738 | -@ vertical-align: bottom; | |
| 739 | -@ color: #333; | |
| 740 | -@ margin-right: -20px; | |
| 741 | -@ white-space: nowrap; | |
| 742 | -@ } | |
| 743 | -@ | |
| 744 | -@ /* The main menu bar that appears at the top of the page beneath | |
| 745 | -@ ** the header */ | |
| 746 | -@ div.mainmenu { | |
| 747 | -@ text-align: center; | |
| 748 | -@ color: white; | |
| 749 | -@ border-top-left-radius: 5px; | |
| 750 | -@ border-top-right-radius: 5px; | |
| 751 | -@ vertical-align: middle; | |
| 752 | -@ padding-top: 8px; | |
| 753 | -@ padding-bottom: 8px; | |
| 754 | -@ background-color: #446979; | |
| 755 | -@ box-shadow: 0px 3px 4px #333333; | |
| 756 | -@ } | |
| 757 | -@ | |
| 758 | -@ /* The submenu bar that *sometimes* appears below the main menu */ | |
| 759 | -@ div.submenu { | |
| 760 | -@ padding-top:10px; | |
| 761 | -@ padding-bottom:0; | |
| 762 | -@ text-align: right; | |
| 763 | -@ color: #000; | |
| 764 | -@ background-color: #fff; | |
| 765 | -@ height: 1.5em; | |
| 766 | -@ vertical-align:middle; | |
| 767 | -@ box-shadow: 0px 3px 4px #999; | |
| 768 | -@ } | |
| 769 | -@ div.mainmenu a, div.mainmenu a:visited { | |
| 770 | -@ padding: 3px 10px 3px 10px; | |
| 771 | -@ color: white; | |
| 772 | -@ text-decoration: none; | |
| 773 | -@ } | |
| 774 | -@ div.submenu a, div.submenu a:visited, a.button, | |
| 775 | -@ div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited { | |
| 776 | -@ padding: 2px 8px; | |
| 777 | -@ color: #000; | |
| 778 | -@ font-family: Arial; | |
| 779 | -@ text-decoration: none; | |
| 780 | -@ margin:auto; | |
| 781 | -@ border-radius: 5px; | |
| 782 | -@ background-color: #e0e0e0; | |
| 783 | -@ text-shadow: 0px -1px 0px #eee; | |
| 784 | -@ border: 1px solid #000; | |
| 785 | -@ } | |
| 786 | -@ | |
| 787 | -@ div.mainmenu a:hover { | |
| 788 | -@ color: #000; | |
| 789 | -@ background-color: white; | |
| 790 | -@ } | |
| 791 | -@ | |
| 792 | -@ div.submenu a:hover, div.sectionmenu>a.button:hover { | |
| 793 | -@ background-color: #c0c0c0; | |
| 794 | -@ } | |
| 795 | -@ | |
| 796 | -@ /* All page content from the bottom of the menu or submenu down to | |
| 797 | -@ ** the footer */ | |
| 798 | -@ div.content { | |
| 799 | -@ background-color: #fff; | |
| 800 | -@ box-shadow: 0px 3px 4px #999; | |
| 801 | -@ border-bottom-right-radius: 5px; | |
| 802 | -@ border-bottom-left-radius: 5px; | |
| 803 | -@ padding-bottom: 1em; | |
| 804 | -@ min-height:40%; | |
| 805 | -@ } | |
| 806 | -@ | |
| 807 | -@ | |
| 808 | -@ /* Some pages have section dividers */ | |
| 809 | -@ div.section { | |
| 810 | -@ margin-bottom: 0.5em; | |
| 811 | -@ margin-top: 1em; | |
| 812 | -@ margin-right: auto; | |
| 813 | -@ padding: 1px 1px 1px 1px; | |
| 814 | -@ font-size: 1.2em; | |
| 815 | -@ font-weight: bold; | |
| 816 | -@ text-align: center; | |
| 817 | -@ color: white; | |
| 818 | -@ border-radius: 5px; | |
| 819 | -@ background-color: #446979; | |
| 820 | -@ box-shadow: 0px 3px 4px #333333; | |
| 821 | -@ white-space: nowrap; | |
| 822 | -@ } | |
| 823 | -@ | |
| 824 | -@ /* The "Date" that occurs on the left hand side of timelines */ | |
| 825 | -@ div.divider { | |
| 826 | -@ font-size: 1.2em; | |
| 827 | -@ font-family: Georgia, serif; | |
| 828 | -@ font-weight: bold; | |
| 829 | -@ margin-top: 1em; | |
| 830 | -@ white-space: nowrap; | |
| 831 | -@ } | |
| 832 | -@ | |
| 833 | -@ /* The footer at the very bottom of the page */ | |
| 834 | -@ div.footer { | |
| 835 | -@ font-size: 0.9em; | |
| 836 | -@ text-align: right; | |
| 837 | -@ margin-bottom: 1em; | |
| 838 | -@ color: #666; | |
| 839 | -@ } | |
| 840 | -@ | |
| 841 | -@ /* Hyperlink colors in the footer */ | |
| 842 | -@ div.footer a { color: white; } | |
| 843 | -@ div.footer a:link { color: white; } | |
| 844 | -@ div.footer a:visited { color: white; } | |
| 845 | -@ div.footer a:hover { background-color: white; color: #558195; } | |
| 846 | -@ | |
| 847 | -@ /* <verbatim> blocks */ | |
| 848 | -@ pre.verbatim, blockquote pre { | |
| 849 | -@ font-family: Dejavu Sans Mono, Monaco, Lucida Console, monospace; | |
| 850 | -@ background-color: #f3f3f3; | |
| 851 | -@ padding: 0.5em; | |
| 852 | -@ white-space: pre-wrap; | |
| 853 | -@ } | |
| 854 | -@ | |
| 855 | -@ blockquote pre { | |
| 856 | -@ border: 1px #000 dashed; | |
| 857 | -@ } | |
| 858 | -@ | |
| 859 | -@ /* The label/value pairs on (for example) the ci page */ | |
| 860 | -@ table.label-value th { | |
| 861 | -@ vertical-align: top; | |
| 862 | -@ text-align: right; | |
| 863 | -@ padding: 0.2ex 2ex; | |
| 864 | -@ } | |
| 865 | -@ | |
| 866 | -@ table.report tr th { | |
| 867 | -@ padding: 3px 5px; | |
| 868 | -@ text-transform: capitalize; | |
| 869 | -@ cursor: pointer; | |
| 870 | -@ } | |
| 871 | -@ | |
| 872 | -@ table.report tr td { | |
| 873 | -@ padding: 3px 5px; | |
| 874 | -@ cursor: pointer; | |
| 875 | -@ } | |
| 876 | -@ | |
| 877 | -@ textarea { | |
| 878 | -@ font-size: 1em; | |
| 879 | -@ } | |
| 880 | -@ | |
| 881 | -@ .fullsize-text { | |
| 882 | -@ font-size: 1.25em; | |
| 883 | -@ }'); | |
| 884 | -@ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html> | |
| 885 | -@ <head> | |
| 886 | -@ <base href="$baseurl/$current_page" /> | |
| 887 | -@ <title>$<project_name>: $<title></title> | |
| 888 | -@ <link rel="alternate" type="application/rss+xml" title="RSS Feed" | |
| 889 | -@ href="$home/timeline.rss"> | |
| 890 | -@ <link rel="stylesheet" href="$stylesheet_url" type="text/css" | |
| 891 | -@ media="screen"> | |
| 892 | -@ </head> | |
| 893 | -@ <body> | |
| 894 | -@ <div class="header"> | |
| 895 | -@ <div class="logo"> | |
| 896 | -@ <img src="$logo_image_url" alt="logo"> | |
| 897 | -@ <br />$<project_name> | |
| 898 | -@ </div> | |
| 899 | -@ <div class="title">$<title></div> | |
| 900 | -@ <div class="status"><th1> | |
| 901 | -@ if {[info exists login]} { | |
| 902 | -@ puts "Logged in as $login" | |
| 903 | -@ } else { | |
| 904 | -@ puts "Not logged in" | |
| 905 | -@ } | |
| 906 | -@ </th1></div> | |
| 907 | -@ </div> | |
| 908 | -@ <div class="mainmenu"> | |
| 909 | -@ <th1> | |
| 910 | -@ html "<a href=''$home$index_page''>Home</a>\n" | |
| 911 | -@ if {[anycap jor]} { | |
| 912 | -@ html "<a href=''$home/timeline''>Timeline</a>\n" | |
| 913 | -@ } | |
| 914 | -@ if {[hascap oh]} { | |
| 915 | -@ html "<a href=''$home/tree?ci=tip''>Files</a>\n" | |
| 916 | -@ } | |
| 917 | -@ if {[hascap o]} { | |
| 918 | -@ html "<a href=''$home/brlist''>Branches</a>\n" | |
| 919 | -@ html "<a href=''$home/taglist''>Tags</a>\n" | |
| 920 | -@ } | |
| 921 | -@ if {[hascap r]} { | |
| 922 | -@ html "<a href=''$home/reportlist''>Tickets</a>\n" | |
| 923 | -@ } | |
| 924 | -@ if {[hascap j]} { | |
| 925 | -@ html "<a href=''$home/wiki''>Wiki</a>\n" | |
| 926 | -@ } | |
| 927 | -@ if {[hascap s]} { | |
| 928 | -@ html "<a href=''$home/setup''>Admin</a>\n" | |
| 929 | -@ } elseif {[hascap a]} { | |
| 930 | -@ html "<a href=''$home/setup_ulist''>Users</a>\n" | |
| 931 | -@ } | |
| 932 | -@ if {[info exists login]} { | |
| 933 | -@ html "<a href=''$home/login''>Logout</a>\n" | |
| 934 | -@ } else { | |
| 935 | -@ html "<a href=''$home/login''>Login</a>\n" | |
| 936 | -@ } | |
| 937 | -@ </th1></div> | |
| 938 | -@ <div id="container"> | |
| 939 | -@ '); | |
| 940 | -@ REPLACE INTO config(name,mtime,value) VALUES('footer',now(),'</div> | |
| 941 | -@ <div class="footer"> | |
| 942 | -@ Fossil version $manifest_version $manifest_date | |
| 943 | -@ </div> | |
| 944 | -@ </body></html> | |
| 945 | -@ '); | |
| 946 | -; | |
| 947 | - | |
| 948 | - | |
| 949 | -/* | |
| 950 | -** This skin is intended to be almost identical to the default one, with the | |
| 951 | -** following changes to the header and footer: | |
| 952 | -** | |
| 953 | -** 1. The logo image in the header has been modified to be a hyperlink to the | |
| 954 | -** root of the web site containing the repository using the same scheme | |
| 955 | -** (i.e. HTTP or HTTPS) as the base URL for the repository. The header | |
| 956 | -** contains a TH1 script block to help accomplish these tasks. | |
| 957 | -** | |
| 958 | -** 2. The Fossil version information in the footer has been augmented with | |
| 959 | -** hyperlinks to the corresponding points on the timeline in the official | |
| 960 | -** Fossil repository. Additionally, if the Tcl integration feature is | |
| 961 | -** enabled, the loaded version of Tcl is included, with a hyperlink to the | |
| 962 | -** official Tcl/Tk web site. The footer also contains a TH1 script block | |
| 963 | -** to help accomplish these tasks. | |
| 964 | -*/ | |
| 965 | -static const char zBuiltinSkin5[] = | |
| 966 | -@ REPLACE INTO config(name,mtime,value) | |
| 967 | -@ VALUES('css',now(),'/* General settings for the entire page */ | |
| 968 | -@ body { | |
| 969 | -@ margin: 0ex 1ex; | |
| 970 | -@ padding: 0px; | |
| 971 | -@ background-color: white; | |
| 972 | -@ font-family: sans-serif; | |
| 973 | -@ } | |
| 974 | -@ | |
| 975 | -@ /* The project logo in the upper left-hand corner of each page */ | |
| 976 | -@ div.logo { | |
| 977 | -@ display: table-cell; | |
| 978 | -@ text-align: center; | |
| 979 | -@ vertical-align: bottom; | |
| 980 | -@ font-weight: bold; | |
| 981 | -@ color: #558195; | |
| 982 | -@ min-width: 200px; | |
| 983 | -@ white-space: nowrap; | |
| 984 | -@ } | |
| 985 | -@ | |
| 986 | -@ /* The page title centered at the top of each page */ | |
| 987 | -@ div.title { | |
| 988 | -@ display: table-cell; | |
| 989 | -@ font-size: 2em; | |
| 990 | -@ font-weight: bold; | |
| 991 | -@ text-align: center; | |
| 992 | -@ padding: 0 0 0 1em; | |
| 993 | -@ color: #558195; | |
| 994 | -@ vertical-align: bottom; | |
| 995 | -@ width: 100%; | |
| 996 | -@ } | |
| 997 | -@ | |
| 998 | -@ /* The login status message in the top right-hand corner */ | |
| 999 | -@ div.status { | |
| 1000 | -@ display: table-cell; | |
| 1001 | -@ text-align: right; | |
| 1002 | -@ vertical-align: bottom; | |
| 1003 | -@ color: #558195; | |
| 1004 | -@ font-size: 0.8em; | |
| 1005 | -@ font-weight: bold; | |
| 1006 | -@ min-width: 200px; | |
| 1007 | -@ white-space: nowrap; | |
| 1008 | -@ } | |
| 1009 | -@ | |
| 1010 | -@ /* The header across the top of the page */ | |
| 1011 | -@ div.header { | |
| 1012 | -@ display: table; | |
| 1013 | -@ width: 100%; | |
| 1014 | -@ } | |
| 1015 | -@ | |
| 1016 | -@ /* The main menu bar that appears at the top of the page beneath | |
| 1017 | -@ ** the header */ | |
| 1018 | -@ div.mainmenu { | |
| 1019 | -@ padding: 5px 10px 5px 10px; | |
| 1020 | -@ font-size: 0.9em; | |
| 1021 | -@ font-weight: bold; | |
| 1022 | -@ text-align: center; | |
| 1023 | -@ letter-spacing: 1px; | |
| 1024 | -@ background-color: #558195; | |
| 1025 | -@ border-top-left-radius: 8px; | |
| 1026 | -@ border-top-right-radius: 8px; | |
| 1027 | -@ color: white; | |
| 1028 | -@ } | |
| 1029 | -@ | |
| 1030 | -@ /* The submenu bar that *sometimes* appears below the main menu */ | |
| 1031 | -@ div.submenu, div.sectionmenu { | |
| 1032 | -@ padding: 3px 10px 3px 0px; | |
| 1033 | -@ font-size: 0.9em; | |
| 1034 | -@ text-align: center; | |
| 1035 | -@ background-color: #456878; | |
| 1036 | -@ color: white; | |
| 1037 | -@ } | |
| 1038 | -@ div.mainmenu a, div.mainmenu a:visited, div.submenu a, div.submenu a:visited, | |
| 1039 | -@ div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited { | |
| 1040 | -@ padding: 3px 10px 3px 10px; | |
| 1041 | -@ color: white; | |
| 1042 | -@ text-decoration: none; | |
| 1043 | -@ } | |
| 1044 | -@ div.mainmenu a:hover, div.submenu a:hover, div.sectionmenu>a.button:hover { | |
| 1045 | -@ color: #558195; | |
| 1046 | -@ background-color: white; | |
| 1047 | -@ } | |
| 1048 | -@ | |
| 1049 | -@ /* All page content from the bottom of the menu or submenu down to | |
| 1050 | -@ ** the footer */ | |
| 1051 | -@ div.content { | |
| 1052 | -@ padding: 0ex 1ex 1ex 1ex; | |
| 1053 | -@ border: solid #aaa; | |
| 1054 | -@ border-width: 1px; | |
| 1055 | -@ } | |
| 1056 | -@ | |
| 1057 | -@ /* Some pages have section dividers */ | |
| 1058 | -@ div.section { | |
| 1059 | -@ margin-bottom: 0px; | |
| 1060 | -@ margin-top: 1em; | |
| 1061 | -@ padding: 1px 1px 1px 1px; | |
| 1062 | -@ font-size: 1.2em; | |
| 1063 | -@ font-weight: bold; | |
| 1064 | -@ background-color: #558195; | |
| 1065 | -@ color: white; | |
| 1066 | -@ white-space: nowrap; | |
| 1067 | -@ } | |
| 1068 | -@ | |
| 1069 | -@ /* The "Date" that occurs on the left hand side of timelines */ | |
| 1070 | -@ div.divider { | |
| 1071 | -@ background: #a1c4d4; | |
| 1072 | -@ border: 2px #558195 solid; | |
| 1073 | -@ font-size: 1em; font-weight: normal; | |
| 1074 | -@ padding: .25em; | |
| 1075 | -@ margin: .2em 0 .2em 0; | |
| 1076 | -@ float: left; | |
| 1077 | -@ clear: left; | |
| 1078 | -@ white-space: nowrap; | |
| 1079 | -@ } | |
| 1080 | -@ | |
| 1081 | -@ /* The footer at the very bottom of the page */ | |
| 1082 | -@ div.footer { | |
| 1083 | -@ clear: both; | |
| 1084 | -@ font-size: 0.8em; | |
| 1085 | -@ padding: 5px 10px 5px 10px; | |
| 1086 | -@ text-align: right; | |
| 1087 | -@ background-color: #558195; | |
| 1088 | -@ border-bottom-left-radius: 8px; | |
| 1089 | -@ border-bottom-right-radius: 8px; | |
| 1090 | -@ color: white; | |
| 1091 | -@ } | |
| 1092 | -@ | |
| 1093 | -@ /* Hyperlink colors in the footer */ | |
| 1094 | -@ div.footer a { color: white; } | |
| 1095 | -@ div.footer a:link { color: white; } | |
| 1096 | -@ div.footer a:visited { color: white; } | |
| 1097 | -@ div.footer a:hover { background-color: white; color: #558195; } | |
| 1098 | -@ | |
| 1099 | -@ /* verbatim blocks */ | |
| 1100 | -@ pre.verbatim { | |
| 1101 | -@ background-color: #f5f5f5; | |
| 1102 | -@ padding: 0.5em; | |
| 1103 | -@ white-space: pre-wrap; | |
| 1104 | -@ } | |
| 1105 | -@ | |
| 1106 | -@ /* The label/value pairs on (for example) the ci page */ | |
| 1107 | -@ table.label-value th { | |
| 1108 | -@ vertical-align: top; | |
| 1109 | -@ text-align: right; | |
| 1110 | -@ padding: 0.2ex 2ex; | |
| 1111 | -@ }'); | |
| 1112 | -@ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html> | |
| 1113 | -@ <head> | |
| 1114 | -@ <base href="$baseurl/$current_page" /> | |
| 1115 | -@ <title>$<project_name>: $<title></title> | |
| 1116 | -@ <link rel="alternate" type="application/rss+xml" title="RSS Feed" | |
| 1117 | -@ href="$home/timeline.rss" /> | |
| 1118 | -@ <link rel="stylesheet" href="$stylesheet_url" type="text/css" | |
| 1119 | -@ media="screen" /> | |
| 1120 | -@ </head> | |
| 1121 | -@ <body> | |
| 1122 | -@ <div class="header"> | |
| 1123 | -@ <div class="logo"> | |
| 1124 | -@ <th1> | |
| 1125 | -@ ## | |
| 1126 | -@ ## NOTE: The purpose of this procedure is to take the base URL of the | |
| 1127 | -@ ## Fossil project and return the root of the entire web site using | |
| 1128 | -@ ## the same URI scheme as the base URL (e.g. http or https). | |
| 1129 | -@ ## | |
| 1130 | -@ proc getLogoUrl { baseurl } { | |
| 1131 | -@ set idx(first) [string first // $baseurl] | |
| 1132 | -@ if {$idx(first) != -1} { | |
| 1133 | -@ ## | |
| 1134 | -@ ## NOTE: Skip second slash. | |
| 1135 | -@ ## | |
| 1136 | -@ set idx(first+1) [expr {$idx(first) + 2}] | |
| 1137 | -@ ## | |
| 1138 | -@ ## NOTE: (part 1) The [string first] command does NOT actually | |
| 1139 | -@ ## the optional startIndex argument as specified in the | |
| 1140 | -@ ## TH1 support manual; therefore, we fake it by using the | |
| 1141 | -@ ## [string range] command and then adding the necessary | |
| 1142 | -@ ## offset to the resulting index manually (below). In Tcl, | |
| 1143 | -@ ## we could use the following instead: | |
| 1144 | -@ ## | |
| 1145 | -@ ## set idx(next) [string first / $baseurl $idx(first+1)] | |
| 1146 | -@ ## | |
| 1147 | -@ set idx(nextRange) [string range $baseurl $idx(first+1) end] | |
| 1148 | -@ set idx(next) [string first / $idx(nextRange)] | |
| 1149 | -@ if {$idx(next) != -1} { | |
| 1150 | -@ ## | |
| 1151 | -@ ## NOTE: (part 2) Add the necessary offset to the result of the | |
| 1152 | -@ ## search for the next slash (i.e. the one after the initial | |
| 1153 | -@ ## search for the two slashes). | |
| 1154 | -@ ## | |
| 1155 | -@ set idx(next) [expr {$idx(next) + $idx(first+1)}] | |
| 1156 | -@ ## | |
| 1157 | -@ ## NOTE: Back up one character from the next slash. | |
| 1158 | -@ ## | |
| 1159 | -@ set idx(next-1) [expr {$idx(next) - 1}] | |
| 1160 | -@ ## | |
| 1161 | -@ ## NOTE: Extract the URI scheme and host from the base URL. | |
| 1162 | -@ ## | |
| 1163 | -@ set scheme [string range $baseurl 0 $idx(first)] | |
| 1164 | -@ set host [string range $baseurl $idx(first+1) $idx(next-1)] | |
| 1165 | -@ ## | |
| 1166 | -@ ## NOTE: Try to stay in SSL mode if we are there now. | |
| 1167 | -@ ## | |
| 1168 | -@ if {[string compare $scheme http:/] == 0} { | |
| 1169 | -@ set scheme http:// | |
| 1170 | -@ } else { | |
| 1171 | -@ set scheme https:// | |
| 1172 | -@ } | |
| 1173 | -@ set logourl $scheme$host/ | |
| 1174 | -@ } else { | |
| 1175 | -@ set logourl $baseurl | |
| 1176 | -@ } | |
| 1177 | -@ } else { | |
| 1178 | -@ set logourl $baseurl | |
| 1179 | -@ } | |
| 1180 | -@ return $logourl | |
| 1181 | -@ } | |
| 1182 | -@ set logourl [getLogoUrl $baseurl] | |
| 1183 | -@ </th1> | |
| 1184 | -@ <a href="$logourl"> | |
| 1185 | -@ <img src="$logo_image_url" border="0" alt="$project_name"> | |
| 1186 | -@ </a> | |
| 1187 | -@ </div> | |
| 1188 | -@ <div class="title"><small>$<project_name></small><br />$<title></div> | |
| 1189 | -@ <div class="status"><th1> | |
| 1190 | -@ if {[info exists login]} { | |
| 1191 | -@ puts "Logged in as $login" | |
| 1192 | -@ } else { | |
| 1193 | -@ puts "Not logged in" | |
| 1194 | -@ } | |
| 1195 | -@ </th1></div> | |
| 1196 | -@ </div> | |
| 1197 | -@ <div class="mainmenu"> | |
| 1198 | -@ <th1> | |
| 1199 | -@ html "<a href=''$home$index_page''>Home</a>\n" | |
| 1200 | -@ if {[anycap jor]} { | |
| 1201 | -@ html "<a href=''$home/timeline''>Timeline</a>\n" | |
| 1202 | -@ } | |
| 1203 | -@ if {[hascap oh]} { | |
| 1204 | -@ html "<a href=''$home/tree?ci=tip''>Files</a>\n" | |
| 1205 | -@ } | |
| 1206 | -@ if {[hascap o]} { | |
| 1207 | -@ html "<a href=''$home/brlist''>Branches</a>\n" | |
| 1208 | -@ html "<a href=''$home/taglist''>Tags</a>\n" | |
| 1209 | -@ } | |
| 1210 | -@ if {[hascap r]} { | |
| 1211 | -@ html "<a href=''$home/reportlist''>Tickets</a>\n" | |
| 1212 | -@ } | |
| 1213 | -@ if {[hascap j]} { | |
| 1214 | -@ html "<a href=''$home/wiki''>Wiki</a>\n" | |
| 1215 | -@ } | |
| 1216 | -@ if {[hascap s]} { | |
| 1217 | -@ html "<a href=''$home/setup''>Admin</a>\n" | |
| 1218 | -@ } elseif {[hascap a]} { | |
| 1219 | -@ html "<a href=''$home/setup_ulist''>Users</a>\n" | |
| 1220 | -@ } | |
| 1221 | -@ if {[info exists login]} { | |
| 1222 | -@ html "<a href=''$home/login''>Logout</a>\n" | |
| 1223 | -@ } else { | |
| 1224 | -@ html "<a href=''$home/login''>Login</a>\n" | |
| 1225 | -@ } | |
| 1226 | -@ </th1></div> | |
| 1227 | -@ '); | |
| 1228 | -@ REPLACE INTO config(name,mtime,value) | |
| 1229 | -@ VALUES('footer',now(),'<div class="footer"> | |
| 1230 | -@ <th1> | |
| 1231 | -@ proc getTclVersion {} { | |
| 1232 | -@ if {[catch {tclEval info patchlevel} tclVersion] == 0} { | |
| 1233 | -@ return "<a href=\"http://www.tcl.tk/\">Tcl</a> version $tclVersion" | |
| 1234 | -@ } | |
| 1235 | -@ return "" | |
| 1236 | -@ } | |
| 1237 | -@ proc getVersion { version } { | |
| 1238 | -@ set length [string length $version] | |
| 1239 | -@ return [string range $version 1 [expr {$length - 2}]] | |
| 1240 | -@ } | |
| 1241 | -@ set version [getVersion $manifest_version] | |
| 1242 | -@ set tclVersion [getTclVersion] | |
| 1243 | -@ set fossilUrl http://www.fossil-scm.org | |
| 1244 | -@ </th1> | |
| 1245 | -@ This page was generated in about | |
| 1246 | -@ <th1>puts [expr {([utime]+[stime]+1000)/1000*0.001}]</th1>s by | |
| 1247 | -@ <a href="$fossilUrl/">Fossil</a> | |
| 1248 | -@ version $release_version $tclVersion | |
| 1249 | -@ <a href="$fossilUrl/index.html/info/$version">$manifest_version</a> | |
| 1250 | -@ <a href="$fossilUrl/index.html/timeline?c=$manifest_date&y=ci">$manifest_date</a> | |
| 1251 | -@ </div> | |
| 1252 | -@ </body></html> | |
| 1253 | -@ '); | |
| 1254 | -; | |
| 1255 | - | |
| 1256 | 24 | /* |
| 1257 | 25 | ** An array of available built-in skins. |
| 26 | +** | |
| 27 | +** To add new built-in skins: | |
| 28 | +** | |
| 29 | +** 1. Pick a name for the new skin. (Here we use "xyzzy"). | |
| 30 | +** | |
| 31 | +** 2. Install files skins/xyzzy/css.txt, skins/xyzzy/header.txt, | |
| 32 | +** and skins/xyzzy/footer.txt into the source tree. | |
| 33 | +** | |
| 34 | +** 3. Rerun "tclsh makemake.tcl" in the src/ folder in order to | |
| 35 | +** rebuild the makefiles to reference the new CSS, headers, and footers. | |
| 36 | +** | |
| 37 | +** 4. Make an entry in the following array for the new skin. | |
| 1258 | 38 | */ |
| 1259 | 39 | static struct BuiltinSkin { |
| 1260 | - const char *zName; | |
| 1261 | - const char *zValue; | |
| 40 | + const char *zDesc; /* Description of this skin */ | |
| 41 | + const char *zLabel; /* The directory under skins/ holding this skin */ | |
| 42 | + char *zSQL; /* Filled in at run-time with SQL to insert this skin */ | |
| 1262 | 43 | } aBuiltinSkin[] = { |
| 1263 | - { "Default", 0 /* Filled in at runtime */ }, | |
| 1264 | - { "Plain Gray, No Logo", zBuiltinSkin1 }, | |
| 1265 | - { "Khaki, No Logo", zBuiltinSkin2 }, | |
| 1266 | - { "Black & White, Menu on Left", zBuiltinSkin3 }, | |
| 1267 | - { "Shadow boxes & Rounded Corners", zBuiltinSkin4 }, | |
| 1268 | - { "Enhanced Default", zBuiltinSkin5 }, | |
| 44 | + { "Default", "default", 0 }, | |
| 45 | + { "Plain Gray, No Logo", "plain_gray", 0 }, | |
| 46 | + { "Khaki, No Logo", "khaki", 0 }, | |
| 47 | + { "Black & White, Menu on Left", "black_and_white", 0 }, | |
| 48 | + { "Shadow boxes & Rounded Corners", "rounded1", 0 }, | |
| 49 | + { "Enhanced Default", "enhanced1", 0 }, | |
| 50 | + { "San Francisco Modern", "etienne1", 0 }, | |
| 51 | + { "Eagle", "eagle", 0 }, | |
| 1269 | 52 | }; |
| 1270 | 53 | |
| 1271 | 54 | /* |
| 1272 | 55 | ** For a skin named zSkinName, compute the name of the CONFIG table |
| 1273 | 56 | ** entry where that skin is stored and return it. |
| @@ -1286,57 +69,158 @@ | ||
| 1286 | 69 | } |
| 1287 | 70 | return z; |
| 1288 | 71 | } |
| 1289 | 72 | |
| 1290 | 73 | /* |
| 1291 | -** Construct and return a string that represents the current skin if | |
| 1292 | -** useDefault==0 or a string for the default skin if useDefault==1. | |
| 74 | +** Return true if there exists a skin name "zSkinName". | |
| 75 | +*/ | |
| 76 | +static int skinExists(const char *zSkinName){ | |
| 77 | + int i; | |
| 78 | + if( zSkinName==0 ) return 0; | |
| 79 | + for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){ | |
| 80 | + if( fossil_strcmp(zSkinName, aBuiltinSkin[i].zDesc)==0 ) return 1; | |
| 81 | + } | |
| 82 | + return db_exists("SELECT 1 FROM config WHERE name='skin:%q'", zSkinName); | |
| 83 | +} | |
| 84 | + | |
| 85 | +/* | |
| 86 | +** Construct and return an string of SQL statements that represents | |
| 87 | +** a "skin" setting. If zName==0 then return the skin currently | |
| 88 | +** installed. Otherwise, return one of the built-in skins designated | |
| 89 | +** by zName. | |
| 1293 | 90 | ** |
| 1294 | 91 | ** Memory to hold the returned string is obtained from malloc. |
| 1295 | 92 | */ |
| 1296 | -static char *getSkin(int useDefault){ | |
| 93 | +static char *getSkin(const char *zName){ | |
| 94 | + const char *z; | |
| 95 | + char *zLabel; | |
| 96 | + static const char *azType[] = { "css", "header", "footer" }; | |
| 97 | + int i; | |
| 1297 | 98 | Blob val; |
| 1298 | 99 | blob_zero(&val); |
| 1299 | - blob_appendf(&val, | |
| 1300 | - "REPLACE INTO config(name,value,mtime) VALUES('css',%Q,now());\n", | |
| 1301 | - useDefault ? zDefaultCSS : db_get("css", (char*)zDefaultCSS) | |
| 1302 | - ); | |
| 1303 | - blob_appendf(&val, | |
| 1304 | - "REPLACE INTO config(name,value,mtime) VALUES('header',%Q,now());\n", | |
| 1305 | - useDefault ? zDefaultHeader : db_get("header", (char*)zDefaultHeader) | |
| 1306 | - ); | |
| 1307 | - blob_appendf(&val, | |
| 1308 | - "REPLACE INTO config(name,value,mtime) VALUES('footer',%Q,now());\n", | |
| 1309 | - useDefault ? zDefaultFooter : db_get("footer", (char*)zDefaultFooter) | |
| 1310 | - ); | |
| 100 | + for(i=0; i<sizeof(azType)/sizeof(azType[0]); i++){ | |
| 101 | + if( zName ){ | |
| 102 | + zLabel = mprintf("skins/%s/%s.txt", zName, azType[i]); | |
| 103 | + z = builtin_text(zLabel); | |
| 104 | + fossil_free(zLabel); | |
| 105 | + }else{ | |
| 106 | + z = db_get(azType[i], 0); | |
| 107 | + if( z==0 ){ | |
| 108 | + zLabel = mprintf("skins/default/%s.txt", azType[i]); | |
| 109 | + z = builtin_text(zLabel); | |
| 110 | + fossil_free(zLabel); | |
| 111 | + } | |
| 112 | + } | |
| 113 | + blob_appendf(&val, | |
| 114 | + "REPLACE INTO config(name,value,mtime) VALUES(%Q,%Q,now());\n", | |
| 115 | + azType[i], z | |
| 116 | + ); | |
| 117 | + } | |
| 1311 | 118 | return blob_str(&val); |
| 1312 | 119 | } |
| 1313 | 120 | |
| 1314 | 121 | /* |
| 1315 | -** Construct the default skin string and fill in the corresponding | |
| 1316 | -** entry in aBuildinSkin[] | |
| 122 | +** Respond to a Rename button press. Return TRUE if a dialog was painted. | |
| 123 | +** Return FALSE to continue with the main Skins page. | |
| 124 | +*/ | |
| 125 | +static int skinRename(void){ | |
| 126 | + const char *zOldName; | |
| 127 | + const char *zNewName; | |
| 128 | + int ex = 0; | |
| 129 | + if( P("rename")==0 ) return 0; | |
| 130 | + zOldName = P("sn"); | |
| 131 | + zNewName = P("newname"); | |
| 132 | + if( zOldName==0 ) return 0; | |
| 133 | + if( zNewName==0 || zNewName[0]==0 || (ex = skinExists(zNewName))!=0 ){ | |
| 134 | + if( zNewName==0 ) zNewName = zOldName; | |
| 135 | + style_header("Rename A Skin"); | |
| 136 | + if( ex ){ | |
| 137 | + @ <p><span class="generalError">There is already another skin | |
| 138 | + @ named "%h(zNewName)". Choose a different name.</span></p> | |
| 139 | + } | |
| 140 | + @ <form action="%s(g.zTop)/setup_skin" method="post"><div> | |
| 141 | + @ <table border="0"><tr> | |
| 142 | + @ <tr><td align="right">Current name:<td align="left"><b>%h(zOldName)</b> | |
| 143 | + @ <tr><td align="right">New name:<td align="left"> | |
| 144 | + @ <input type="text" size="35" name="newname" value="%h(zNewName)"> | |
| 145 | + @ <tr><td><td> | |
| 146 | + @ <input type="hidden" name="sn" value="%h(zOldName)"> | |
| 147 | + @ <input type="submit" name="rename" value="Rename"> | |
| 148 | + @ <input type="submit" name="canren" value="Cancel"> | |
| 149 | + @ </table> | |
| 150 | + login_insert_csrf_secret(); | |
| 151 | + @ </div></form> | |
| 152 | + style_footer(); | |
| 153 | + return 1; | |
| 154 | + } | |
| 155 | + db_multi_exec( | |
| 156 | + "UPDATE config SET name='skin:%q' WHERE name='skin:%q';", | |
| 157 | + zNewName, zOldName | |
| 158 | + ); | |
| 159 | + return 0; | |
| 160 | +} | |
| 161 | + | |
| 162 | +/* | |
| 163 | +** Respond to a Save button press. Return TRUE if a dialog was painted. | |
| 164 | +** Return FALSE to continue with the main Skins page. | |
| 1317 | 165 | */ |
| 1318 | -static void setDefaultSkin(void){ | |
| 1319 | - aBuiltinSkin[0].zValue = getSkin(1); | |
| 166 | +static int skinSave(const char *zCurrent){ | |
| 167 | + const char *zNewName; | |
| 168 | + int ex = 0; | |
| 169 | + if( P("save")==0 ) return 0; | |
| 170 | + zNewName = P("svname"); | |
| 171 | + if( zNewName && zNewName[0]!=0 ){ | |
| 172 | + } | |
| 173 | + if( zNewName==0 || zNewName[0]==0 || (ex = skinExists(zNewName))!=0 ){ | |
| 174 | + if( zNewName==0 ) zNewName = ""; | |
| 175 | + style_header("Save Current Skin"); | |
| 176 | + if( ex ){ | |
| 177 | + @ <p><span class="generalError">There is already another skin | |
| 178 | + @ named "%h(zNewName)". Choose a different name.</span></p> | |
| 179 | + } | |
| 180 | + @ <form action="%s(g.zTop)/setup_skin" method="post"><div> | |
| 181 | + @ <table border="0"><tr> | |
| 182 | + @ <tr><td align="right">Name for this skin:<td align="left"> | |
| 183 | + @ <input type="text" size="35" name="svname" value="%h(zNewName)"> | |
| 184 | + @ <tr><td><td> | |
| 185 | + @ <input type="submit" name="save" value="Save"> | |
| 186 | + @ <input type="submit" name="cansave" value="Cancel"> | |
| 187 | + @ </table> | |
| 188 | + login_insert_csrf_secret(); | |
| 189 | + @ </div></form> | |
| 190 | + style_footer(); | |
| 191 | + return 1; | |
| 192 | + } | |
| 193 | + db_multi_exec( | |
| 194 | + "INSERT OR IGNORE INTO config(name, value, mtime)" | |
| 195 | + "VALUES('skin:%q',%Q,now())", | |
| 196 | + zNewName, zCurrent | |
| 197 | + ); | |
| 198 | + return 0; | |
| 1320 | 199 | } |
| 1321 | 200 | |
| 1322 | 201 | /* |
| 1323 | 202 | ** WEBPAGE: setup_skin |
| 1324 | 203 | */ |
| 1325 | 204 | void setup_skin(void){ |
| 1326 | 205 | const char *z; |
| 1327 | 206 | char *zName; |
| 1328 | 207 | char *zErr = 0; |
| 1329 | - const char *zCurrent; /* Current skin */ | |
| 1330 | - int i; /* Loop counter */ | |
| 208 | + const char *zCurrent = 0; /* Current skin */ | |
| 209 | + int i; /* Loop counter */ | |
| 1331 | 210 | Stmt q; |
| 211 | + int seenCurrent = 0; | |
| 1332 | 212 | |
| 1333 | 213 | login_check_credentials(); |
| 1334 | 214 | if( !g.perm.Setup ){ |
| 1335 | 215 | login_needed(); |
| 1336 | 216 | } |
| 1337 | 217 | db_begin_transaction(); |
| 218 | + zCurrent = getSkin(0); | |
| 219 | + for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){ | |
| 220 | + aBuiltinSkin[i].zSQL = getSkin(aBuiltinSkin[i].zLabel); | |
| 221 | + } | |
| 1338 | 222 | |
| 1339 | 223 | /* Process requests to delete a user-defined skin */ |
| 1340 | 224 | if( P("del1") && (zName = skinVarName(P("sn"), 1))!=0 ){ |
| 1341 | 225 | style_header("Confirm Custom Skin Delete"); |
| 1342 | 226 | @ <form action="%s(g.zTop)/setup_skin" method="post"><div> |
| @@ -1351,51 +235,42 @@ | ||
| 1351 | 235 | return; |
| 1352 | 236 | } |
| 1353 | 237 | if( P("del2")!=0 && (zName = skinVarName(P("sn"), 1))!=0 ){ |
| 1354 | 238 | db_multi_exec("DELETE FROM config WHERE name=%Q", zName); |
| 1355 | 239 | } |
| 1356 | - | |
| 1357 | - setDefaultSkin(); | |
| 1358 | - zCurrent = getSkin(0); | |
| 1359 | - | |
| 1360 | - if( P("save")!=0 && (zName = skinVarName(P("save"),0))!=0 ){ | |
| 1361 | - if( db_exists("SELECT 1 FROM config WHERE name=%Q", zName) | |
| 1362 | - || fossil_strcmp(zName, "Default")==0 ){ | |
| 1363 | - zErr = mprintf("Skin name \"%h\" already exists. " | |
| 1364 | - "Choose a different name.", P("sn")); | |
| 1365 | - }else{ | |
| 1366 | - db_multi_exec("INSERT INTO config(name,value,mtime) VALUES(%Q,%Q,now())", | |
| 1367 | - zName, zCurrent | |
| 1368 | - ); | |
| 1369 | - } | |
| 1370 | - } | |
| 1371 | - | |
| 1372 | - /* The user pressed the "Use This Skin" button. */ | |
| 240 | + if( skinRename() ) return; | |
| 241 | + if( skinSave(zCurrent) ) return; | |
| 242 | + | |
| 243 | + /* The user pressed one of the "Install" buttons. */ | |
| 1373 | 244 | if( P("load") && (z = P("sn"))!=0 && z[0] ){ |
| 1374 | 245 | int seen = 0; |
| 246 | + | |
| 247 | + /* Check to see if the current skin is already saved. If it is, there | |
| 248 | + ** is no need to create a backup */ | |
| 249 | + zCurrent = getSkin(0); | |
| 1375 | 250 | for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){ |
| 1376 | - if( fossil_strcmp(aBuiltinSkin[i].zValue, zCurrent)==0 ){ | |
| 251 | + if( fossil_strcmp(aBuiltinSkin[i].zSQL, zCurrent)==0 ){ | |
| 1377 | 252 | seen = 1; |
| 1378 | 253 | break; |
| 1379 | 254 | } |
| 1380 | 255 | } |
| 1381 | 256 | if( !seen ){ |
| 1382 | 257 | seen = db_exists("SELECT 1 FROM config WHERE name GLOB 'skin:*'" |
| 1383 | 258 | " AND value=%Q", zCurrent); |
| 1384 | - } | |
| 1385 | - if( !seen ){ | |
| 1386 | - db_multi_exec( | |
| 1387 | - "INSERT INTO config(name,value,mtime) VALUES(" | |
| 1388 | - " strftime('skin:Backup On %%Y-%%m-%%d %%H:%%M:%%S')," | |
| 1389 | - " %Q,now())", zCurrent | |
| 1390 | - ); | |
| 259 | + if( !seen ){ | |
| 260 | + db_multi_exec( | |
| 261 | + "INSERT INTO config(name,value,mtime) VALUES(" | |
| 262 | + " strftime('skin:Backup On %%Y-%%m-%%d %%H:%%M:%%S')," | |
| 263 | + " %Q,now())", zCurrent | |
| 264 | + ); | |
| 265 | + } | |
| 1391 | 266 | } |
| 1392 | 267 | seen = 0; |
| 1393 | 268 | for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){ |
| 1394 | - if( fossil_strcmp(aBuiltinSkin[i].zName, z)==0 ){ | |
| 269 | + if( fossil_strcmp(aBuiltinSkin[i].zDesc, z)==0 ){ | |
| 1395 | 270 | seen = 1; |
| 1396 | - zCurrent = aBuiltinSkin[i].zValue; | |
| 271 | + zCurrent = aBuiltinSkin[i].zSQL; | |
| 1397 | 272 | db_multi_exec("%s", zCurrent/*safe-for-%s*/); |
| 1398 | 273 | break; |
| 1399 | 274 | } |
| 1400 | 275 | } |
| 1401 | 276 | if( !seen ){ |
| @@ -1409,48 +284,59 @@ | ||
| 1409 | 284 | if( zErr ){ |
| 1410 | 285 | @ <p><font color="red">%h(zErr)</font></p> |
| 1411 | 286 | } |
| 1412 | 287 | @ <p>A "skin" is a combination of |
| 1413 | 288 | @ <a href="setup_editcss">CSS</a>, |
| 1414 | - @ <a href="setup_header">Header</a>, | |
| 1415 | - @ <a href="setup_footer">Footer</a>, and | |
| 1416 | - @ <a href="setup_logo">Logo</a> that determines the look and feel | |
| 289 | + @ <a href="setup_header">Header</a>, and | |
| 290 | + @ <a href="setup_footer">Footer</a> that determines the look and feel | |
| 1417 | 291 | @ of the web interface.</p> |
| 1418 | 292 | @ |
| 1419 | 293 | @ <h2>Available Skins:</h2> |
| 1420 | - @ <ol> | |
| 294 | + @ <table border="0"> | |
| 1421 | 295 | for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){ |
| 1422 | - z = aBuiltinSkin[i].zName; | |
| 1423 | - if( fossil_strcmp(aBuiltinSkin[i].zValue, zCurrent)==0 ){ | |
| 1424 | - @ <li><p>%h(z). <b>Currently In Use</b></p> | |
| 296 | + z = aBuiltinSkin[i].zDesc; | |
| 297 | + @ <tr><td>%d(i+1).<td>%h(z)<td> <td> | |
| 298 | + if( fossil_strcmp(aBuiltinSkin[i].zSQL, zCurrent)==0 ){ | |
| 299 | + @ (Currently In Use) | |
| 300 | + seenCurrent = 1; | |
| 1425 | 301 | }else{ |
| 1426 | - @ <li><form action="%s(g.zTop)/setup_skin" method="post"><div> | |
| 1427 | - @ %h(z). | |
| 302 | + @ <form action="%s(g.zTop)/setup_skin" method="post"> | |
| 1428 | 303 | @ <input type="hidden" name="sn" value="%h(z)" /> |
| 1429 | - @ <input type="submit" name="load" value="Use This Skin" /> | |
| 1430 | - @ </div></form></li> | |
| 304 | + @ <input type="submit" name="load" value="Install" /> | |
| 305 | + @ </form> | |
| 1431 | 306 | } |
| 307 | + @ </tr> | |
| 1432 | 308 | } |
| 1433 | 309 | db_prepare(&q, |
| 1434 | 310 | "SELECT substr(name, 6), value FROM config" |
| 1435 | 311 | " WHERE name GLOB 'skin:*'" |
| 1436 | 312 | " ORDER BY name" |
| 1437 | 313 | ); |
| 1438 | 314 | while( db_step(&q)==SQLITE_ROW ){ |
| 1439 | 315 | const char *zN = db_column_text(&q, 0); |
| 1440 | 316 | const char *zV = db_column_text(&q, 1); |
| 1441 | - if( fossil_strcmp(zV, zCurrent)==0 ){ | |
| 1442 | - @ <li><p>%h(zN). <b>Currently In Use</b></p> | |
| 1443 | - }else{ | |
| 1444 | - @ <li><form action="%s(g.zTop)/setup_skin" method="post"> | |
| 1445 | - @ %h(zN). | |
| 1446 | - @ <input type="hidden" name="sn" value="%h(zN)"> | |
| 1447 | - @ <input type="submit" name="load" value="Use This Skin"> | |
| 1448 | - @ <input type="submit" name="del1" value="Delete This Skin"> | |
| 1449 | - @ </form></li> | |
| 1450 | - } | |
| 317 | + i++; | |
| 318 | + @ <tr><td>%d(i).<td>%h(zN)<td> <td> | |
| 319 | + @ <form action="%s(g.zTop)/setup_skin" method="post"> | |
| 320 | + if( fossil_strcmp(zV, zCurrent)==0 ){ | |
| 321 | + @ (Currently In Use) | |
| 322 | + seenCurrent = 1; | |
| 323 | + }else{ | |
| 324 | + @ <input type="submit" name="load" value="Install"> | |
| 325 | + @ <input type="submit" name="del1" value="Delete"> | |
| 326 | + } | |
| 327 | + @ <input type="submit" name="rename" value="Rename"> | |
| 328 | + @ <input type="hidden" name="sn" value="%h(zN)"> | |
| 329 | + @ </form></tr> | |
| 1451 | 330 | } |
| 1452 | 331 | db_finalize(&q); |
| 1453 | - @ </ol> | |
| 332 | + if( !seenCurrent ){ | |
| 333 | + i++; | |
| 334 | + @ <tr><td>%d(i).<td><i>Current Configuration</i><td> <td> | |
| 335 | + @ <form action="%s(g.zTop)/setup_skin" method="post"> | |
| 336 | + @ <input type="submit" name="save" value="Save"> | |
| 337 | + @ </form> | |
| 338 | + } | |
| 339 | + @ </table> | |
| 1454 | 340 | style_footer(); |
| 1455 | 341 | db_end_transaction(0); |
| 1456 | 342 | } |
| 1457 | 343 |
| --- src/skins.c | |
| +++ src/skins.c | |
| @@ -19,1255 +19,38 @@ | |
| 19 | */ |
| 20 | #include "config.h" |
| 21 | #include <assert.h> |
| 22 | #include "skins.h" |
| 23 | |
| 24 | /* @-comment: ## */ |
| 25 | /* |
| 26 | ** A black-and-white theme with the project title in a bar across the top |
| 27 | ** and no logo image. |
| 28 | */ |
| 29 | static const char zBuiltinSkin1[] = |
| 30 | @ REPLACE INTO config(name,mtime,value) |
| 31 | @ VALUES('css',now(),'/* General settings for the entire page */ |
| 32 | @ body { |
| 33 | @ margin: 0ex 1ex; |
| 34 | @ padding: 0px; |
| 35 | @ background-color: white; |
| 36 | @ font-family: sans-serif; |
| 37 | @ } |
| 38 | @ |
| 39 | @ /* The project logo in the upper left-hand corner of each page */ |
| 40 | @ div.logo { |
| 41 | @ display: table-row; |
| 42 | @ text-align: center; |
| 43 | @ /* vertical-align: bottom;*/ |
| 44 | @ font-size: 2em; |
| 45 | @ font-weight: bold; |
| 46 | @ background-color: #707070; |
| 47 | @ color: #ffffff; |
| 48 | @ min-width: 200px; |
| 49 | @ white-space: nowrap; |
| 50 | @ } |
| 51 | @ |
| 52 | @ /* The page title centered at the top of each page */ |
| 53 | @ div.title { |
| 54 | @ display: table-cell; |
| 55 | @ font-size: 1.5em; |
| 56 | @ font-weight: bold; |
| 57 | @ text-align: center; |
| 58 | @ padding: 0 0 0 10px; |
| 59 | @ color: #404040; |
| 60 | @ vertical-align: bottom; |
| 61 | @ width: 100%; |
| 62 | @ } |
| 63 | @ |
| 64 | @ /* The login status message in the top right-hand corner */ |
| 65 | @ div.status { |
| 66 | @ display: table-cell; |
| 67 | @ text-align: right; |
| 68 | @ vertical-align: bottom; |
| 69 | @ color: #404040; |
| 70 | @ font-size: 0.8em; |
| 71 | @ font-weight: bold; |
| 72 | @ min-width: 200px; |
| 73 | @ white-space: nowrap; |
| 74 | @ } |
| 75 | @ |
| 76 | @ /* The header across the top of the page */ |
| 77 | @ div.header { |
| 78 | @ display: table; |
| 79 | @ width: 100%; |
| 80 | @ } |
| 81 | @ |
| 82 | @ /* The main menu bar that appears at the top of the page beneath |
| 83 | @ ** the header */ |
| 84 | @ div.mainmenu { |
| 85 | @ padding: 5px 10px 5px 10px; |
| 86 | @ font-size: 0.9em; |
| 87 | @ font-weight: bold; |
| 88 | @ text-align: center; |
| 89 | @ letter-spacing: 1px; |
| 90 | @ background-color: #404040; |
| 91 | @ color: white; |
| 92 | @ } |
| 93 | @ |
| 94 | @ /* The submenu bar that *sometimes* appears below the main menu */ |
| 95 | @ div.submenu, div.sectionmenu { |
| 96 | @ padding: 3px 10px 3px 0px; |
| 97 | @ font-size: 0.9em; |
| 98 | @ text-align: center; |
| 99 | @ background-color: #606060; |
| 100 | @ color: white; |
| 101 | @ } |
| 102 | @ div.mainmenu a, div.mainmenu a:visited, div.submenu a, div.submenu a:visited, |
| 103 | @ div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited { |
| 104 | @ padding: 3px 10px 3px 10px; |
| 105 | @ color: white; |
| 106 | @ text-decoration: none; |
| 107 | @ } |
| 108 | @ div.mainmenu a:hover, div.submenu a:hover, div.sectionmenu>a.button:hover { |
| 109 | @ color: #404040; |
| 110 | @ background-color: white; |
| 111 | @ } |
| 112 | @ |
| 113 | @ /* All page content from the bottom of the menu or submenu down to |
| 114 | @ ** the footer */ |
| 115 | @ div.content { |
| 116 | @ padding: 0ex 0ex 0ex 0ex; |
| 117 | @ } |
| 118 | @ /* Hyperlink colors */ |
| 119 | @ div.content a { color: #604000; } |
| 120 | @ div.content a:link { color: #604000;} |
| 121 | @ div.content a:visited { color: #600000; } |
| 122 | @ |
| 123 | @ /* <verbatim> blocks */ |
| 124 | @ pre.verbatim { |
| 125 | @ background-color: #ffffff; |
| 126 | @ padding: 0.5em; |
| 127 | @ white-space: pre-wrap; |
| 128 | @ } |
| 129 | @ |
| 130 | @ /* Some pages have section dividers */ |
| 131 | @ div.section { |
| 132 | @ margin-bottom: 0px; |
| 133 | @ margin-top: 1em; |
| 134 | @ padding: 1px 1px 1px 1px; |
| 135 | @ font-size: 1.2em; |
| 136 | @ font-weight: bold; |
| 137 | @ background-color: #404040; |
| 138 | @ color: white; |
| 139 | @ white-space: nowrap; |
| 140 | @ } |
| 141 | @ |
| 142 | @ /* The "Date" that occurs on the left hand side of timelines */ |
| 143 | @ div.divider { |
| 144 | @ background: #a0a0a0; |
| 145 | @ border: 2px #505050 solid; |
| 146 | @ font-size: 1em; font-weight: normal; |
| 147 | @ padding: .25em; |
| 148 | @ margin: .2em 0 .2em 0; |
| 149 | @ float: left; |
| 150 | @ clear: left; |
| 151 | @ white-space: nowrap; |
| 152 | @ } |
| 153 | @ |
| 154 | @ /* The footer at the very bottom of the page */ |
| 155 | @ div.footer { |
| 156 | @ font-size: 0.8em; |
| 157 | @ margin-top: 12px; |
| 158 | @ padding: 5px 10px 5px 10px; |
| 159 | @ text-align: right; |
| 160 | @ background-color: #404040; |
| 161 | @ color: white; |
| 162 | @ } |
| 163 | @ |
| 164 | @ /* The label/value pairs on (for example) the vinfo page */ |
| 165 | @ table.label-value th { |
| 166 | @ vertical-align: top; |
| 167 | @ text-align: right; |
| 168 | @ padding: 0.2ex 2ex; |
| 169 | @ }'); |
| 170 | @ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html> |
| 171 | @ <head> |
| 172 | @ <base href="$baseurl/$current_page" /> |
| 173 | @ <title>$<project_name>: $<title></title> |
| 174 | @ <link rel="alternate" type="application/rss+xml" title="RSS Feed" |
| 175 | @ href="$home/timeline.rss"> |
| 176 | @ <link rel="stylesheet" href="$stylesheet_url" type="text/css" |
| 177 | @ media="screen"> |
| 178 | @ </head> |
| 179 | @ <body> |
| 180 | @ <div class="header"> |
| 181 | @ <div class="title"><small>$<project_name></small><br />$<title></div> |
| 182 | @ <div class="status"><th1> |
| 183 | @ if {[info exists login]} { |
| 184 | @ puts "Logged in as $login" |
| 185 | @ } else { |
| 186 | @ puts "Not logged in" |
| 187 | @ } |
| 188 | @ </th1></div> |
| 189 | @ </div> |
| 190 | @ <div class="mainmenu"> |
| 191 | @ <th1> |
| 192 | @ html "<a href=''$home$index_page''>Home</a>\n" |
| 193 | @ if {[anycap jor]} { |
| 194 | @ html "<a href=''$home/timeline''>Timeline</a>\n" |
| 195 | @ } |
| 196 | @ if {[hascap oh]} { |
| 197 | @ html "<a href=''$home/tree?ci=tip''>Files</a>\n" |
| 198 | @ } |
| 199 | @ if {[hascap o]} { |
| 200 | @ html "<a href=''$home/brlist''>Branches</a>\n" |
| 201 | @ html "<a href=''$home/taglist''>Tags</a>\n" |
| 202 | @ } |
| 203 | @ if {[hascap r]} { |
| 204 | @ html "<a href=''$home/reportlist''>Tickets</a>\n" |
| 205 | @ } |
| 206 | @ if {[hascap j]} { |
| 207 | @ html "<a href=''$home/wiki''>Wiki</a>\n" |
| 208 | @ } |
| 209 | @ if {[hascap s]} { |
| 210 | @ html "<a href=''$home/setup''>Admin</a>\n" |
| 211 | @ } elseif {[hascap a]} { |
| 212 | @ html "<a href=''$home/setup_ulist''>Users</a>\n" |
| 213 | @ } |
| 214 | @ if {[info exists login]} { |
| 215 | @ html "<a href=''$home/login''>Logout</a>\n" |
| 216 | @ } else { |
| 217 | @ html "<a href=''$home/login''>Login</a>\n" |
| 218 | @ } |
| 219 | @ </th1></div> |
| 220 | @ '); |
| 221 | @ REPLACE INTO config(name,mtime,value) |
| 222 | @ VALUES('footer',now(),'<div class="footer"> |
| 223 | @ Fossil version $manifest_version $manifest_date |
| 224 | @ </div> |
| 225 | @ </body></html> |
| 226 | @ '); |
| 227 | ; |
| 228 | |
| 229 | /* |
| 230 | ** A tan theme with the project title above the user identification |
| 231 | ** and no logo image. |
| 232 | */ |
| 233 | static const char zBuiltinSkin2[] = |
| 234 | @ REPLACE INTO config(name,mtime,value) |
| 235 | @ VALUES('css',now(),'/* General settings for the entire page */ |
| 236 | @ body { |
| 237 | @ margin: 0ex 0ex; |
| 238 | @ padding: 0px; |
| 239 | @ background-color: #fef3bc; |
| 240 | @ font-family: sans-serif; |
| 241 | @ } |
| 242 | @ |
| 243 | @ /* The project logo in the upper left-hand corner of each page */ |
| 244 | @ div.logo { |
| 245 | @ display: inline; |
| 246 | @ text-align: center; |
| 247 | @ vertical-align: bottom; |
| 248 | @ font-weight: bold; |
| 249 | @ font-size: 2.5em; |
| 250 | @ color: #a09048; |
| 251 | @ white-space: nowrap; |
| 252 | @ } |
| 253 | @ |
| 254 | @ /* The page title centered at the top of each page */ |
| 255 | @ div.title { |
| 256 | @ display: table-cell; |
| 257 | @ font-size: 2em; |
| 258 | @ font-weight: bold; |
| 259 | @ text-align: left; |
| 260 | @ padding: 0 0 0 5px; |
| 261 | @ color: #a09048; |
| 262 | @ vertical-align: bottom; |
| 263 | @ width: 100%; |
| 264 | @ } |
| 265 | @ |
| 266 | @ /* The login status message in the top right-hand corner */ |
| 267 | @ div.status { |
| 268 | @ display: table-cell; |
| 269 | @ text-align: right; |
| 270 | @ vertical-align: bottom; |
| 271 | @ color: #a09048; |
| 272 | @ padding: 5px 5px 0 0; |
| 273 | @ font-size: 0.8em; |
| 274 | @ font-weight: bold; |
| 275 | @ white-space: nowrap; |
| 276 | @ } |
| 277 | @ |
| 278 | @ /* The header across the top of the page */ |
| 279 | @ div.header { |
| 280 | @ display: table; |
| 281 | @ width: 100%; |
| 282 | @ } |
| 283 | @ |
| 284 | @ /* The main menu bar that appears at the top of the page beneath |
| 285 | @ ** the header */ |
| 286 | @ div.mainmenu { |
| 287 | @ padding: 5px 10px 5px 10px; |
| 288 | @ font-size: 0.9em; |
| 289 | @ font-weight: bold; |
| 290 | @ text-align: center; |
| 291 | @ letter-spacing: 1px; |
| 292 | @ background-color: #a09048; |
| 293 | @ color: black; |
| 294 | @ } |
| 295 | @ |
| 296 | @ /* The submenu bar that *sometimes* appears below the main menu */ |
| 297 | @ div.submenu, div.sectionmenu { |
| 298 | @ padding: 3px 10px 3px 0px; |
| 299 | @ font-size: 0.9em; |
| 300 | @ text-align: center; |
| 301 | @ background-color: #c0af58; |
| 302 | @ color: white; |
| 303 | @ } |
| 304 | @ div.mainmenu a, div.mainmenu a:visited, div.submenu a, div.submenu a:visited, |
| 305 | @ div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited { |
| 306 | @ padding: 3px 10px 3px 10px; |
| 307 | @ color: white; |
| 308 | @ text-decoration: none; |
| 309 | @ } |
| 310 | @ div.mainmenu a:hover, div.submenu a:hover, div.sectionmenu>a.button:hover { |
| 311 | @ color: #a09048; |
| 312 | @ background-color: white; |
| 313 | @ } |
| 314 | @ |
| 315 | @ /* All page content from the bottom of the menu or submenu down to |
| 316 | @ ** the footer */ |
| 317 | @ div.content { |
| 318 | @ padding: 1ex 5px; |
| 319 | @ } |
| 320 | @ div.content a { color: #706532; } |
| 321 | @ div.content a:link { color: #706532; } |
| 322 | @ div.content a:visited { color: #704032; } |
| 323 | @ div.content a:hover { background-color: white; color: #706532; } |
| 324 | @ |
| 325 | @ /* Some pages have section dividers */ |
| 326 | @ div.section { |
| 327 | @ margin-bottom: 0px; |
| 328 | @ margin-top: 1em; |
| 329 | @ padding: 3px 3px 0 3px; |
| 330 | @ font-size: 1.2em; |
| 331 | @ font-weight: bold; |
| 332 | @ background-color: #a09048; |
| 333 | @ color: white; |
| 334 | @ white-space: nowrap; |
| 335 | @ } |
| 336 | @ |
| 337 | @ /* The "Date" that occurs on the left hand side of timelines */ |
| 338 | @ div.divider { |
| 339 | @ background: #e1d498; |
| 340 | @ border: 2px #a09048 solid; |
| 341 | @ font-size: 1em; font-weight: normal; |
| 342 | @ padding: .25em; |
| 343 | @ margin: .2em 0 .2em 0; |
| 344 | @ float: left; |
| 345 | @ clear: left; |
| 346 | @ white-space: nowrap; |
| 347 | @ } |
| 348 | @ |
| 349 | @ /* The footer at the very bottom of the page */ |
| 350 | @ div.footer { |
| 351 | @ font-size: 0.8em; |
| 352 | @ margin-top: 12px; |
| 353 | @ padding: 5px 10px 5px 10px; |
| 354 | @ text-align: right; |
| 355 | @ background-color: #a09048; |
| 356 | @ color: white; |
| 357 | @ } |
| 358 | @ |
| 359 | @ /* Hyperlink colors */ |
| 360 | @ div.footer a { color: white; } |
| 361 | @ div.footer a:link { color: white; } |
| 362 | @ div.footer a:visited { color: white; } |
| 363 | @ div.footer a:hover { background-color: white; color: #558195; } |
| 364 | @ |
| 365 | @ /* <verbatim> blocks */ |
| 366 | @ pre.verbatim { |
| 367 | @ background-color: #f5f5f5; |
| 368 | @ padding: 0.5em; |
| 369 | @ white-space: pre-wrap; |
| 370 | @ } |
| 371 | @ |
| 372 | @ /* The label/value pairs on (for example) the ci page */ |
| 373 | @ table.label-value th { |
| 374 | @ vertical-align: top; |
| 375 | @ text-align: right; |
| 376 | @ padding: 0.2ex 2ex; |
| 377 | @ }'); |
| 378 | @ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html> |
| 379 | @ <head> |
| 380 | @ <base href="$baseurl/$current_page" /> |
| 381 | @ <title>$<project_name>: $<title></title> |
| 382 | @ <link rel="alternate" type="application/rss+xml" title="RSS Feed" |
| 383 | @ href="$home/timeline.rss"> |
| 384 | @ <link rel="stylesheet" href="$stylesheet_url" type="text/css" |
| 385 | @ media="screen"> |
| 386 | @ </head> |
| 387 | @ <body> |
| 388 | @ <div class="header"> |
| 389 | @ <div class="title">$<title></div> |
| 390 | @ <div class="status"> |
| 391 | @ <div class="logo">$<project_name></div><br/> |
| 392 | @ <th1> |
| 393 | @ if {[info exists login]} { |
| 394 | @ puts "Logged in as $login" |
| 395 | @ } else { |
| 396 | @ puts "Not logged in" |
| 397 | @ } |
| 398 | @ </th1></div> |
| 399 | @ </div> |
| 400 | @ <div class="mainmenu"> |
| 401 | @ <th1> |
| 402 | @ html "<a href=''$home$index_page''>Home</a>\n" |
| 403 | @ if {[anycap jor]} { |
| 404 | @ html "<a href=''$home/timeline''>Timeline</a>\n" |
| 405 | @ } |
| 406 | @ if {[hascap oh]} { |
| 407 | @ html "<a href=''$home/tree?ci=tip''>Files</a>\n" |
| 408 | @ } |
| 409 | @ if {[hascap o]} { |
| 410 | @ html "<a href=''$home/brlist''>Branches</a>\n" |
| 411 | @ html "<a href=''$home/taglist''>Tags</a>\n" |
| 412 | @ } |
| 413 | @ if {[hascap r]} { |
| 414 | @ html "<a href=''$home/reportlist''>Tickets</a>\n" |
| 415 | @ } |
| 416 | @ if {[hascap j]} { |
| 417 | @ html "<a href=''$home/wiki''>Wiki</a>\n" |
| 418 | @ } |
| 419 | @ if {[hascap s]} { |
| 420 | @ html "<a href=''$home/setup''>Admin</a>\n" |
| 421 | @ } elseif {[hascap a]} { |
| 422 | @ html "<a href=''$home/setup_ulist''>Users</a>\n" |
| 423 | @ } |
| 424 | @ if {[info exists login]} { |
| 425 | @ html "<a href=''$home/login''>Logout</a>\n" |
| 426 | @ } else { |
| 427 | @ html "<a href=''$home/login''>Login</a>\n" |
| 428 | @ } |
| 429 | @ </th1></div> |
| 430 | @ '); |
| 431 | @ REPLACE INTO config(name,mtime,value) |
| 432 | @ VALUES('footer',now(),'<div class="footer"> |
| 433 | @ Fossil version $manifest_version $manifest_date |
| 434 | @ </div> |
| 435 | @ </body></html> |
| 436 | @ '); |
| 437 | ; |
| 438 | |
| 439 | /* |
| 440 | ** Black letters on a white or cream background with the main menu |
| 441 | ** stuck on the left-hand side. |
| 442 | */ |
| 443 | static const char zBuiltinSkin3[] = |
| 444 | @ REPLACE INTO config(name,mtime,value) |
| 445 | @ VALUES('css',now(),'/* General settings for the entire page */ |
| 446 | @ body { |
| 447 | @ margin:0px 0px 0px 0px; |
| 448 | @ padding:0px; |
| 449 | @ font-family:verdana, arial, helvetica, "sans serif"; |
| 450 | @ color:#333; |
| 451 | @ background-color:white; |
| 452 | @ } |
| 453 | @ |
| 454 | @ /* consistent colours */ |
| 455 | @ h2 { |
| 456 | @ color: #333; |
| 457 | @ } |
| 458 | @ h3 { |
| 459 | @ color: #333; |
| 460 | @ } |
| 461 | @ |
| 462 | @ /* The project logo in the upper left-hand corner of each page */ |
| 463 | @ div.logo { |
| 464 | @ display: table-cell; |
| 465 | @ text-align: left; |
| 466 | @ vertical-align: bottom; |
| 467 | @ font-weight: bold; |
| 468 | @ color: #333; |
| 469 | @ white-space: nowrap; |
| 470 | @ } |
| 471 | @ |
| 472 | @ /* The page title centered at the top of each page */ |
| 473 | @ div.title { |
| 474 | @ display: table-cell; |
| 475 | @ font-size: 2em; |
| 476 | @ font-weight: bold; |
| 477 | @ text-align: center; |
| 478 | @ color: #333; |
| 479 | @ vertical-align: bottom; |
| 480 | @ width: 100%; |
| 481 | @ } |
| 482 | @ |
| 483 | @ /* The login status message in the top right-hand corner */ |
| 484 | @ div.status { |
| 485 | @ display: table-cell; |
| 486 | @ padding-right: 10px; |
| 487 | @ text-align: right; |
| 488 | @ vertical-align: bottom; |
| 489 | @ padding-bottom: 5px; |
| 490 | @ color: #333; |
| 491 | @ font-size: 0.8em; |
| 492 | @ font-weight: bold; |
| 493 | @ white-space: nowrap; |
| 494 | @ } |
| 495 | @ |
| 496 | @ /* The header across the top of the page */ |
| 497 | @ div.header { |
| 498 | @ margin:10px 0px 10px 0px; |
| 499 | @ padding:1px 0px 0px 20px; |
| 500 | @ border-style:solid; |
| 501 | @ border-color:black; |
| 502 | @ border-width:1px 0px; |
| 503 | @ background-color:#eee; |
| 504 | @ } |
| 505 | @ |
| 506 | @ /* The main menu bar that appears at the top left of the page beneath |
| 507 | @ ** the header. Width must be co-ordinated with the container below */ |
| 508 | @ div.mainmenu { |
| 509 | @ float: left; |
| 510 | @ margin-left: 10px; |
| 511 | @ margin-right: 10px; |
| 512 | @ font-size: 0.9em; |
| 513 | @ font-weight: bold; |
| 514 | @ padding:5px; |
| 515 | @ background-color:#eee; |
| 516 | @ border:1px solid #999; |
| 517 | @ width:8em; |
| 518 | @ } |
| 519 | @ |
| 520 | @ /* Main menu is now a list */ |
| 521 | @ div.mainmenu ul { |
| 522 | @ padding: 0; |
| 523 | @ list-style:none; |
| 524 | @ } |
| 525 | @ div.mainmenu a, div.mainmenu a:visited{ |
| 526 | @ padding: 1px 10px 1px 10px; |
| 527 | @ color: #333; |
| 528 | @ text-decoration: none; |
| 529 | @ } |
| 530 | @ div.mainmenu a:hover { |
| 531 | @ color: #eee; |
| 532 | @ background-color: #333; |
| 533 | @ } |
| 534 | @ |
| 535 | @ /* Container for the sub-menu and content so they don''t spread |
| 536 | @ ** out underneath the main menu */ |
| 537 | @ #container { |
| 538 | @ padding-left: 9em; |
| 539 | @ } |
| 540 | @ |
| 541 | @ /* The submenu bar that *sometimes* appears below the main menu */ |
| 542 | @ div.submenu, div.sectionmenu { |
| 543 | @ padding: 3px 10px 3px 10px; |
| 544 | @ font-size: 0.9em; |
| 545 | @ text-align: center; |
| 546 | @ border:1px solid #999; |
| 547 | @ border-width:1px 0px; |
| 548 | @ background-color: #eee; |
| 549 | @ color: #333; |
| 550 | @ } |
| 551 | @ div.submenu a, div.submenu a:visited, div.sectionmenu>a.button:link, |
| 552 | @ div.sectionmenu>a.button:visited { |
| 553 | @ padding: 3px 10px 3px 10px; |
| 554 | @ color: #333; |
| 555 | @ text-decoration: none; |
| 556 | @ } |
| 557 | @ div.submenu a:hover, div.sectionmenu>a.button:hover { |
| 558 | @ color: #eee; |
| 559 | @ background-color: #333; |
| 560 | @ } |
| 561 | @ |
| 562 | @ /* All page content from the bottom of the menu or submenu down to |
| 563 | @ ** the footer */ |
| 564 | @ div.content { |
| 565 | @ padding: 2ex 1ex 0ex 2ex; |
| 566 | @ } |
| 567 | @ |
| 568 | @ /* Some pages have section dividers */ |
| 569 | @ div.section { |
| 570 | @ margin-bottom: 0px; |
| 571 | @ margin-top: 1em; |
| 572 | @ padding: 1px 1px 1px 1px; |
| 573 | @ font-size: 1.2em; |
| 574 | @ font-weight: bold; |
| 575 | @ border-style:solid; |
| 576 | @ border-color:#999; |
| 577 | @ border-width:1px 0px; |
| 578 | @ background-color: #eee; |
| 579 | @ color: #333; |
| 580 | @ white-space: nowrap; |
| 581 | @ } |
| 582 | @ |
| 583 | @ /* The "Date" that occurs on the left hand side of timelines */ |
| 584 | @ div.divider { |
| 585 | @ background: #eee; |
| 586 | @ border: 2px #999 solid; |
| 587 | @ font-size: 1em; font-weight: normal; |
| 588 | @ padding: .25em; |
| 589 | @ margin: .2em 0 .2em 0; |
| 590 | @ float: left; |
| 591 | @ clear: left; |
| 592 | @ color: #333; |
| 593 | @ white-space: nowrap; |
| 594 | @ } |
| 595 | @ |
| 596 | @ /* The footer at the very bottom of the page */ |
| 597 | @ div.footer { |
| 598 | @ font-size: 0.8em; |
| 599 | @ margin-top: 12px; |
| 600 | @ padding: 5px 10px 5px 10px; |
| 601 | @ text-align: right; |
| 602 | @ background-color: #eee; |
| 603 | @ color: #555; |
| 604 | @ } |
| 605 | @ |
| 606 | @ /* <verbatim> blocks */ |
| 607 | @ pre.verbatim { |
| 608 | @ background-color: #f5f5f5; |
| 609 | @ padding: 0.5em; |
| 610 | @ white-space: pre-wrap; |
| 611 | @ } |
| 612 | @ |
| 613 | @ /* The label/value pairs on (for example) the ci page */ |
| 614 | @ table.label-value th { |
| 615 | @ vertical-align: top; |
| 616 | @ text-align: right; |
| 617 | @ padding: 0.2ex 2ex; |
| 618 | @ }'); |
| 619 | @ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html> |
| 620 | @ <head> |
| 621 | @ <base href="$baseurl/$current_page" /> |
| 622 | @ <title>$<project_name>: $<title></title> |
| 623 | @ <link rel="alternate" type="application/rss+xml" title="RSS Feed" |
| 624 | @ href="$home/timeline.rss"> |
| 625 | @ <link rel="stylesheet" href="$stylesheet_url" type="text/css" |
| 626 | @ media="screen"> |
| 627 | @ </head> |
| 628 | @ <body> |
| 629 | @ <div class="header"> |
| 630 | @ <div class="logo"> |
| 631 | @ <img src="$logo_image_url" alt="logo"> |
| 632 | @ <br />$<project_name> |
| 633 | @ </div> |
| 634 | @ <div class="title">$<title></div> |
| 635 | @ <div class="status"><th1> |
| 636 | @ if {[info exists login]} { |
| 637 | @ puts "Logged in as $login" |
| 638 | @ } else { |
| 639 | @ puts "Not logged in" |
| 640 | @ } |
| 641 | @ </th1></div> |
| 642 | @ </div> |
| 643 | @ <div class="mainmenu"> |
| 644 | @ <th1> |
| 645 | @ html "<a href=''$home$index_page''>Home</a>\n" |
| 646 | @ if {[anycap jor]} { |
| 647 | @ html "<a href=''$home/timeline''>Timeline</a>\n" |
| 648 | @ } |
| 649 | @ if {[hascap oh]} { |
| 650 | @ html "<a href=''$home/tree?ci=tip''>Files</a>\n" |
| 651 | @ } |
| 652 | @ if {[hascap o]} { |
| 653 | @ html "<a href=''$home/brlist''>Branches</a>\n" |
| 654 | @ html "<a href=''$home/taglist''>Tags</a>\n" |
| 655 | @ } |
| 656 | @ if {[hascap r]} { |
| 657 | @ html "<a href=''$home/reportlist''>Tickets</a>\n" |
| 658 | @ } |
| 659 | @ if {[hascap j]} { |
| 660 | @ html "<a href=''$home/wiki''>Wiki</a>\n" |
| 661 | @ } |
| 662 | @ if {[hascap s]} { |
| 663 | @ html "<a href=''$home/setup''>Admin</a>\n" |
| 664 | @ } elseif {[hascap a]} { |
| 665 | @ html "<a href=''$home/setup_ulist''>Users</a>\n" |
| 666 | @ } |
| 667 | @ if {[info exists login]} { |
| 668 | @ html "<a href=''$home/login''>Logout</a>\n" |
| 669 | @ } else { |
| 670 | @ html "<a href=''$home/login''>Login</a>\n" |
| 671 | @ } |
| 672 | @ </th1></ul></div> |
| 673 | @ <div id="container"> |
| 674 | @ '); |
| 675 | @ REPLACE INTO config(name,mtime,value) VALUES('footer',now(),'</div> |
| 676 | @ <div class="footer"> |
| 677 | @ Fossil version $manifest_version $manifest_date |
| 678 | @ </div> |
| 679 | @ </body></html> |
| 680 | @ '); |
| 681 | ; |
| 682 | |
| 683 | |
| 684 | /* |
| 685 | ** Shadow boxes and rounded corners. |
| 686 | */ |
| 687 | static const char zBuiltinSkin4[] = |
| 688 | @ REPLACE INTO config(name,mtime,value) |
| 689 | @ VALUES('css',now(),'/* General settings for the entire page */ |
| 690 | @ html { |
| 691 | @ min-height: 100%; |
| 692 | @ } |
| 693 | @ body { |
| 694 | @ margin: 0ex 1ex; |
| 695 | @ padding: 0px; |
| 696 | @ background-color: white; |
| 697 | @ color: #333; |
| 698 | @ font-family: Verdana, sans-serif; |
| 699 | @ font-size: 0.8em; |
| 700 | @ } |
| 701 | @ |
| 702 | @ /* The project logo in the upper left-hand corner of each page */ |
| 703 | @ div.logo { |
| 704 | @ display: table-cell; |
| 705 | @ text-align: right; |
| 706 | @ vertical-align: bottom; |
| 707 | @ font-weight: normal; |
| 708 | @ white-space: nowrap; |
| 709 | @ } |
| 710 | @ |
| 711 | @ /* Widths */ |
| 712 | @ div.header, div.mainmenu, div.submenu, div.content, div.footer { |
| 713 | @ max-width: 900px; |
| 714 | @ margin: auto; |
| 715 | @ padding: 3px 20px 3px 20px; |
| 716 | @ clear: both; |
| 717 | @ } |
| 718 | @ |
| 719 | @ /* The page title at the top of each page */ |
| 720 | @ div.title { |
| 721 | @ display: table-cell; |
| 722 | @ padding-left: 10px; |
| 723 | @ font-size: 2em; |
| 724 | @ margin: 10px 0 10px -20px; |
| 725 | @ vertical-align: bottom; |
| 726 | @ text-align: left; |
| 727 | @ width: 80%; |
| 728 | @ font-family: Verdana, sans-serif; |
| 729 | @ font-weight: bold; |
| 730 | @ color: #558195; |
| 731 | @ text-shadow: 0px 2px 2px #999999; |
| 732 | @ } |
| 733 | @ |
| 734 | @ /* The login status message in the top right-hand corner */ |
| 735 | @ div.status { |
| 736 | @ display: table-cell; |
| 737 | @ text-align: right; |
| 738 | @ vertical-align: bottom; |
| 739 | @ color: #333; |
| 740 | @ margin-right: -20px; |
| 741 | @ white-space: nowrap; |
| 742 | @ } |
| 743 | @ |
| 744 | @ /* The main menu bar that appears at the top of the page beneath |
| 745 | @ ** the header */ |
| 746 | @ div.mainmenu { |
| 747 | @ text-align: center; |
| 748 | @ color: white; |
| 749 | @ border-top-left-radius: 5px; |
| 750 | @ border-top-right-radius: 5px; |
| 751 | @ vertical-align: middle; |
| 752 | @ padding-top: 8px; |
| 753 | @ padding-bottom: 8px; |
| 754 | @ background-color: #446979; |
| 755 | @ box-shadow: 0px 3px 4px #333333; |
| 756 | @ } |
| 757 | @ |
| 758 | @ /* The submenu bar that *sometimes* appears below the main menu */ |
| 759 | @ div.submenu { |
| 760 | @ padding-top:10px; |
| 761 | @ padding-bottom:0; |
| 762 | @ text-align: right; |
| 763 | @ color: #000; |
| 764 | @ background-color: #fff; |
| 765 | @ height: 1.5em; |
| 766 | @ vertical-align:middle; |
| 767 | @ box-shadow: 0px 3px 4px #999; |
| 768 | @ } |
| 769 | @ div.mainmenu a, div.mainmenu a:visited { |
| 770 | @ padding: 3px 10px 3px 10px; |
| 771 | @ color: white; |
| 772 | @ text-decoration: none; |
| 773 | @ } |
| 774 | @ div.submenu a, div.submenu a:visited, a.button, |
| 775 | @ div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited { |
| 776 | @ padding: 2px 8px; |
| 777 | @ color: #000; |
| 778 | @ font-family: Arial; |
| 779 | @ text-decoration: none; |
| 780 | @ margin:auto; |
| 781 | @ border-radius: 5px; |
| 782 | @ background-color: #e0e0e0; |
| 783 | @ text-shadow: 0px -1px 0px #eee; |
| 784 | @ border: 1px solid #000; |
| 785 | @ } |
| 786 | @ |
| 787 | @ div.mainmenu a:hover { |
| 788 | @ color: #000; |
| 789 | @ background-color: white; |
| 790 | @ } |
| 791 | @ |
| 792 | @ div.submenu a:hover, div.sectionmenu>a.button:hover { |
| 793 | @ background-color: #c0c0c0; |
| 794 | @ } |
| 795 | @ |
| 796 | @ /* All page content from the bottom of the menu or submenu down to |
| 797 | @ ** the footer */ |
| 798 | @ div.content { |
| 799 | @ background-color: #fff; |
| 800 | @ box-shadow: 0px 3px 4px #999; |
| 801 | @ border-bottom-right-radius: 5px; |
| 802 | @ border-bottom-left-radius: 5px; |
| 803 | @ padding-bottom: 1em; |
| 804 | @ min-height:40%; |
| 805 | @ } |
| 806 | @ |
| 807 | @ |
| 808 | @ /* Some pages have section dividers */ |
| 809 | @ div.section { |
| 810 | @ margin-bottom: 0.5em; |
| 811 | @ margin-top: 1em; |
| 812 | @ margin-right: auto; |
| 813 | @ padding: 1px 1px 1px 1px; |
| 814 | @ font-size: 1.2em; |
| 815 | @ font-weight: bold; |
| 816 | @ text-align: center; |
| 817 | @ color: white; |
| 818 | @ border-radius: 5px; |
| 819 | @ background-color: #446979; |
| 820 | @ box-shadow: 0px 3px 4px #333333; |
| 821 | @ white-space: nowrap; |
| 822 | @ } |
| 823 | @ |
| 824 | @ /* The "Date" that occurs on the left hand side of timelines */ |
| 825 | @ div.divider { |
| 826 | @ font-size: 1.2em; |
| 827 | @ font-family: Georgia, serif; |
| 828 | @ font-weight: bold; |
| 829 | @ margin-top: 1em; |
| 830 | @ white-space: nowrap; |
| 831 | @ } |
| 832 | @ |
| 833 | @ /* The footer at the very bottom of the page */ |
| 834 | @ div.footer { |
| 835 | @ font-size: 0.9em; |
| 836 | @ text-align: right; |
| 837 | @ margin-bottom: 1em; |
| 838 | @ color: #666; |
| 839 | @ } |
| 840 | @ |
| 841 | @ /* Hyperlink colors in the footer */ |
| 842 | @ div.footer a { color: white; } |
| 843 | @ div.footer a:link { color: white; } |
| 844 | @ div.footer a:visited { color: white; } |
| 845 | @ div.footer a:hover { background-color: white; color: #558195; } |
| 846 | @ |
| 847 | @ /* <verbatim> blocks */ |
| 848 | @ pre.verbatim, blockquote pre { |
| 849 | @ font-family: Dejavu Sans Mono, Monaco, Lucida Console, monospace; |
| 850 | @ background-color: #f3f3f3; |
| 851 | @ padding: 0.5em; |
| 852 | @ white-space: pre-wrap; |
| 853 | @ } |
| 854 | @ |
| 855 | @ blockquote pre { |
| 856 | @ border: 1px #000 dashed; |
| 857 | @ } |
| 858 | @ |
| 859 | @ /* The label/value pairs on (for example) the ci page */ |
| 860 | @ table.label-value th { |
| 861 | @ vertical-align: top; |
| 862 | @ text-align: right; |
| 863 | @ padding: 0.2ex 2ex; |
| 864 | @ } |
| 865 | @ |
| 866 | @ table.report tr th { |
| 867 | @ padding: 3px 5px; |
| 868 | @ text-transform: capitalize; |
| 869 | @ cursor: pointer; |
| 870 | @ } |
| 871 | @ |
| 872 | @ table.report tr td { |
| 873 | @ padding: 3px 5px; |
| 874 | @ cursor: pointer; |
| 875 | @ } |
| 876 | @ |
| 877 | @ textarea { |
| 878 | @ font-size: 1em; |
| 879 | @ } |
| 880 | @ |
| 881 | @ .fullsize-text { |
| 882 | @ font-size: 1.25em; |
| 883 | @ }'); |
| 884 | @ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html> |
| 885 | @ <head> |
| 886 | @ <base href="$baseurl/$current_page" /> |
| 887 | @ <title>$<project_name>: $<title></title> |
| 888 | @ <link rel="alternate" type="application/rss+xml" title="RSS Feed" |
| 889 | @ href="$home/timeline.rss"> |
| 890 | @ <link rel="stylesheet" href="$stylesheet_url" type="text/css" |
| 891 | @ media="screen"> |
| 892 | @ </head> |
| 893 | @ <body> |
| 894 | @ <div class="header"> |
| 895 | @ <div class="logo"> |
| 896 | @ <img src="$logo_image_url" alt="logo"> |
| 897 | @ <br />$<project_name> |
| 898 | @ </div> |
| 899 | @ <div class="title">$<title></div> |
| 900 | @ <div class="status"><th1> |
| 901 | @ if {[info exists login]} { |
| 902 | @ puts "Logged in as $login" |
| 903 | @ } else { |
| 904 | @ puts "Not logged in" |
| 905 | @ } |
| 906 | @ </th1></div> |
| 907 | @ </div> |
| 908 | @ <div class="mainmenu"> |
| 909 | @ <th1> |
| 910 | @ html "<a href=''$home$index_page''>Home</a>\n" |
| 911 | @ if {[anycap jor]} { |
| 912 | @ html "<a href=''$home/timeline''>Timeline</a>\n" |
| 913 | @ } |
| 914 | @ if {[hascap oh]} { |
| 915 | @ html "<a href=''$home/tree?ci=tip''>Files</a>\n" |
| 916 | @ } |
| 917 | @ if {[hascap o]} { |
| 918 | @ html "<a href=''$home/brlist''>Branches</a>\n" |
| 919 | @ html "<a href=''$home/taglist''>Tags</a>\n" |
| 920 | @ } |
| 921 | @ if {[hascap r]} { |
| 922 | @ html "<a href=''$home/reportlist''>Tickets</a>\n" |
| 923 | @ } |
| 924 | @ if {[hascap j]} { |
| 925 | @ html "<a href=''$home/wiki''>Wiki</a>\n" |
| 926 | @ } |
| 927 | @ if {[hascap s]} { |
| 928 | @ html "<a href=''$home/setup''>Admin</a>\n" |
| 929 | @ } elseif {[hascap a]} { |
| 930 | @ html "<a href=''$home/setup_ulist''>Users</a>\n" |
| 931 | @ } |
| 932 | @ if {[info exists login]} { |
| 933 | @ html "<a href=''$home/login''>Logout</a>\n" |
| 934 | @ } else { |
| 935 | @ html "<a href=''$home/login''>Login</a>\n" |
| 936 | @ } |
| 937 | @ </th1></div> |
| 938 | @ <div id="container"> |
| 939 | @ '); |
| 940 | @ REPLACE INTO config(name,mtime,value) VALUES('footer',now(),'</div> |
| 941 | @ <div class="footer"> |
| 942 | @ Fossil version $manifest_version $manifest_date |
| 943 | @ </div> |
| 944 | @ </body></html> |
| 945 | @ '); |
| 946 | ; |
| 947 | |
| 948 | |
| 949 | /* |
| 950 | ** This skin is intended to be almost identical to the default one, with the |
| 951 | ** following changes to the header and footer: |
| 952 | ** |
| 953 | ** 1. The logo image in the header has been modified to be a hyperlink to the |
| 954 | ** root of the web site containing the repository using the same scheme |
| 955 | ** (i.e. HTTP or HTTPS) as the base URL for the repository. The header |
| 956 | ** contains a TH1 script block to help accomplish these tasks. |
| 957 | ** |
| 958 | ** 2. The Fossil version information in the footer has been augmented with |
| 959 | ** hyperlinks to the corresponding points on the timeline in the official |
| 960 | ** Fossil repository. Additionally, if the Tcl integration feature is |
| 961 | ** enabled, the loaded version of Tcl is included, with a hyperlink to the |
| 962 | ** official Tcl/Tk web site. The footer also contains a TH1 script block |
| 963 | ** to help accomplish these tasks. |
| 964 | */ |
| 965 | static const char zBuiltinSkin5[] = |
| 966 | @ REPLACE INTO config(name,mtime,value) |
| 967 | @ VALUES('css',now(),'/* General settings for the entire page */ |
| 968 | @ body { |
| 969 | @ margin: 0ex 1ex; |
| 970 | @ padding: 0px; |
| 971 | @ background-color: white; |
| 972 | @ font-family: sans-serif; |
| 973 | @ } |
| 974 | @ |
| 975 | @ /* The project logo in the upper left-hand corner of each page */ |
| 976 | @ div.logo { |
| 977 | @ display: table-cell; |
| 978 | @ text-align: center; |
| 979 | @ vertical-align: bottom; |
| 980 | @ font-weight: bold; |
| 981 | @ color: #558195; |
| 982 | @ min-width: 200px; |
| 983 | @ white-space: nowrap; |
| 984 | @ } |
| 985 | @ |
| 986 | @ /* The page title centered at the top of each page */ |
| 987 | @ div.title { |
| 988 | @ display: table-cell; |
| 989 | @ font-size: 2em; |
| 990 | @ font-weight: bold; |
| 991 | @ text-align: center; |
| 992 | @ padding: 0 0 0 1em; |
| 993 | @ color: #558195; |
| 994 | @ vertical-align: bottom; |
| 995 | @ width: 100%; |
| 996 | @ } |
| 997 | @ |
| 998 | @ /* The login status message in the top right-hand corner */ |
| 999 | @ div.status { |
| 1000 | @ display: table-cell; |
| 1001 | @ text-align: right; |
| 1002 | @ vertical-align: bottom; |
| 1003 | @ color: #558195; |
| 1004 | @ font-size: 0.8em; |
| 1005 | @ font-weight: bold; |
| 1006 | @ min-width: 200px; |
| 1007 | @ white-space: nowrap; |
| 1008 | @ } |
| 1009 | @ |
| 1010 | @ /* The header across the top of the page */ |
| 1011 | @ div.header { |
| 1012 | @ display: table; |
| 1013 | @ width: 100%; |
| 1014 | @ } |
| 1015 | @ |
| 1016 | @ /* The main menu bar that appears at the top of the page beneath |
| 1017 | @ ** the header */ |
| 1018 | @ div.mainmenu { |
| 1019 | @ padding: 5px 10px 5px 10px; |
| 1020 | @ font-size: 0.9em; |
| 1021 | @ font-weight: bold; |
| 1022 | @ text-align: center; |
| 1023 | @ letter-spacing: 1px; |
| 1024 | @ background-color: #558195; |
| 1025 | @ border-top-left-radius: 8px; |
| 1026 | @ border-top-right-radius: 8px; |
| 1027 | @ color: white; |
| 1028 | @ } |
| 1029 | @ |
| 1030 | @ /* The submenu bar that *sometimes* appears below the main menu */ |
| 1031 | @ div.submenu, div.sectionmenu { |
| 1032 | @ padding: 3px 10px 3px 0px; |
| 1033 | @ font-size: 0.9em; |
| 1034 | @ text-align: center; |
| 1035 | @ background-color: #456878; |
| 1036 | @ color: white; |
| 1037 | @ } |
| 1038 | @ div.mainmenu a, div.mainmenu a:visited, div.submenu a, div.submenu a:visited, |
| 1039 | @ div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited { |
| 1040 | @ padding: 3px 10px 3px 10px; |
| 1041 | @ color: white; |
| 1042 | @ text-decoration: none; |
| 1043 | @ } |
| 1044 | @ div.mainmenu a:hover, div.submenu a:hover, div.sectionmenu>a.button:hover { |
| 1045 | @ color: #558195; |
| 1046 | @ background-color: white; |
| 1047 | @ } |
| 1048 | @ |
| 1049 | @ /* All page content from the bottom of the menu or submenu down to |
| 1050 | @ ** the footer */ |
| 1051 | @ div.content { |
| 1052 | @ padding: 0ex 1ex 1ex 1ex; |
| 1053 | @ border: solid #aaa; |
| 1054 | @ border-width: 1px; |
| 1055 | @ } |
| 1056 | @ |
| 1057 | @ /* Some pages have section dividers */ |
| 1058 | @ div.section { |
| 1059 | @ margin-bottom: 0px; |
| 1060 | @ margin-top: 1em; |
| 1061 | @ padding: 1px 1px 1px 1px; |
| 1062 | @ font-size: 1.2em; |
| 1063 | @ font-weight: bold; |
| 1064 | @ background-color: #558195; |
| 1065 | @ color: white; |
| 1066 | @ white-space: nowrap; |
| 1067 | @ } |
| 1068 | @ |
| 1069 | @ /* The "Date" that occurs on the left hand side of timelines */ |
| 1070 | @ div.divider { |
| 1071 | @ background: #a1c4d4; |
| 1072 | @ border: 2px #558195 solid; |
| 1073 | @ font-size: 1em; font-weight: normal; |
| 1074 | @ padding: .25em; |
| 1075 | @ margin: .2em 0 .2em 0; |
| 1076 | @ float: left; |
| 1077 | @ clear: left; |
| 1078 | @ white-space: nowrap; |
| 1079 | @ } |
| 1080 | @ |
| 1081 | @ /* The footer at the very bottom of the page */ |
| 1082 | @ div.footer { |
| 1083 | @ clear: both; |
| 1084 | @ font-size: 0.8em; |
| 1085 | @ padding: 5px 10px 5px 10px; |
| 1086 | @ text-align: right; |
| 1087 | @ background-color: #558195; |
| 1088 | @ border-bottom-left-radius: 8px; |
| 1089 | @ border-bottom-right-radius: 8px; |
| 1090 | @ color: white; |
| 1091 | @ } |
| 1092 | @ |
| 1093 | @ /* Hyperlink colors in the footer */ |
| 1094 | @ div.footer a { color: white; } |
| 1095 | @ div.footer a:link { color: white; } |
| 1096 | @ div.footer a:visited { color: white; } |
| 1097 | @ div.footer a:hover { background-color: white; color: #558195; } |
| 1098 | @ |
| 1099 | @ /* verbatim blocks */ |
| 1100 | @ pre.verbatim { |
| 1101 | @ background-color: #f5f5f5; |
| 1102 | @ padding: 0.5em; |
| 1103 | @ white-space: pre-wrap; |
| 1104 | @ } |
| 1105 | @ |
| 1106 | @ /* The label/value pairs on (for example) the ci page */ |
| 1107 | @ table.label-value th { |
| 1108 | @ vertical-align: top; |
| 1109 | @ text-align: right; |
| 1110 | @ padding: 0.2ex 2ex; |
| 1111 | @ }'); |
| 1112 | @ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html> |
| 1113 | @ <head> |
| 1114 | @ <base href="$baseurl/$current_page" /> |
| 1115 | @ <title>$<project_name>: $<title></title> |
| 1116 | @ <link rel="alternate" type="application/rss+xml" title="RSS Feed" |
| 1117 | @ href="$home/timeline.rss" /> |
| 1118 | @ <link rel="stylesheet" href="$stylesheet_url" type="text/css" |
| 1119 | @ media="screen" /> |
| 1120 | @ </head> |
| 1121 | @ <body> |
| 1122 | @ <div class="header"> |
| 1123 | @ <div class="logo"> |
| 1124 | @ <th1> |
| 1125 | @ ## |
| 1126 | @ ## NOTE: The purpose of this procedure is to take the base URL of the |
| 1127 | @ ## Fossil project and return the root of the entire web site using |
| 1128 | @ ## the same URI scheme as the base URL (e.g. http or https). |
| 1129 | @ ## |
| 1130 | @ proc getLogoUrl { baseurl } { |
| 1131 | @ set idx(first) [string first // $baseurl] |
| 1132 | @ if {$idx(first) != -1} { |
| 1133 | @ ## |
| 1134 | @ ## NOTE: Skip second slash. |
| 1135 | @ ## |
| 1136 | @ set idx(first+1) [expr {$idx(first) + 2}] |
| 1137 | @ ## |
| 1138 | @ ## NOTE: (part 1) The [string first] command does NOT actually |
| 1139 | @ ## the optional startIndex argument as specified in the |
| 1140 | @ ## TH1 support manual; therefore, we fake it by using the |
| 1141 | @ ## [string range] command and then adding the necessary |
| 1142 | @ ## offset to the resulting index manually (below). In Tcl, |
| 1143 | @ ## we could use the following instead: |
| 1144 | @ ## |
| 1145 | @ ## set idx(next) [string first / $baseurl $idx(first+1)] |
| 1146 | @ ## |
| 1147 | @ set idx(nextRange) [string range $baseurl $idx(first+1) end] |
| 1148 | @ set idx(next) [string first / $idx(nextRange)] |
| 1149 | @ if {$idx(next) != -1} { |
| 1150 | @ ## |
| 1151 | @ ## NOTE: (part 2) Add the necessary offset to the result of the |
| 1152 | @ ## search for the next slash (i.e. the one after the initial |
| 1153 | @ ## search for the two slashes). |
| 1154 | @ ## |
| 1155 | @ set idx(next) [expr {$idx(next) + $idx(first+1)}] |
| 1156 | @ ## |
| 1157 | @ ## NOTE: Back up one character from the next slash. |
| 1158 | @ ## |
| 1159 | @ set idx(next-1) [expr {$idx(next) - 1}] |
| 1160 | @ ## |
| 1161 | @ ## NOTE: Extract the URI scheme and host from the base URL. |
| 1162 | @ ## |
| 1163 | @ set scheme [string range $baseurl 0 $idx(first)] |
| 1164 | @ set host [string range $baseurl $idx(first+1) $idx(next-1)] |
| 1165 | @ ## |
| 1166 | @ ## NOTE: Try to stay in SSL mode if we are there now. |
| 1167 | @ ## |
| 1168 | @ if {[string compare $scheme http:/] == 0} { |
| 1169 | @ set scheme http:// |
| 1170 | @ } else { |
| 1171 | @ set scheme https:// |
| 1172 | @ } |
| 1173 | @ set logourl $scheme$host/ |
| 1174 | @ } else { |
| 1175 | @ set logourl $baseurl |
| 1176 | @ } |
| 1177 | @ } else { |
| 1178 | @ set logourl $baseurl |
| 1179 | @ } |
| 1180 | @ return $logourl |
| 1181 | @ } |
| 1182 | @ set logourl [getLogoUrl $baseurl] |
| 1183 | @ </th1> |
| 1184 | @ <a href="$logourl"> |
| 1185 | @ <img src="$logo_image_url" border="0" alt="$project_name"> |
| 1186 | @ </a> |
| 1187 | @ </div> |
| 1188 | @ <div class="title"><small>$<project_name></small><br />$<title></div> |
| 1189 | @ <div class="status"><th1> |
| 1190 | @ if {[info exists login]} { |
| 1191 | @ puts "Logged in as $login" |
| 1192 | @ } else { |
| 1193 | @ puts "Not logged in" |
| 1194 | @ } |
| 1195 | @ </th1></div> |
| 1196 | @ </div> |
| 1197 | @ <div class="mainmenu"> |
| 1198 | @ <th1> |
| 1199 | @ html "<a href=''$home$index_page''>Home</a>\n" |
| 1200 | @ if {[anycap jor]} { |
| 1201 | @ html "<a href=''$home/timeline''>Timeline</a>\n" |
| 1202 | @ } |
| 1203 | @ if {[hascap oh]} { |
| 1204 | @ html "<a href=''$home/tree?ci=tip''>Files</a>\n" |
| 1205 | @ } |
| 1206 | @ if {[hascap o]} { |
| 1207 | @ html "<a href=''$home/brlist''>Branches</a>\n" |
| 1208 | @ html "<a href=''$home/taglist''>Tags</a>\n" |
| 1209 | @ } |
| 1210 | @ if {[hascap r]} { |
| 1211 | @ html "<a href=''$home/reportlist''>Tickets</a>\n" |
| 1212 | @ } |
| 1213 | @ if {[hascap j]} { |
| 1214 | @ html "<a href=''$home/wiki''>Wiki</a>\n" |
| 1215 | @ } |
| 1216 | @ if {[hascap s]} { |
| 1217 | @ html "<a href=''$home/setup''>Admin</a>\n" |
| 1218 | @ } elseif {[hascap a]} { |
| 1219 | @ html "<a href=''$home/setup_ulist''>Users</a>\n" |
| 1220 | @ } |
| 1221 | @ if {[info exists login]} { |
| 1222 | @ html "<a href=''$home/login''>Logout</a>\n" |
| 1223 | @ } else { |
| 1224 | @ html "<a href=''$home/login''>Login</a>\n" |
| 1225 | @ } |
| 1226 | @ </th1></div> |
| 1227 | @ '); |
| 1228 | @ REPLACE INTO config(name,mtime,value) |
| 1229 | @ VALUES('footer',now(),'<div class="footer"> |
| 1230 | @ <th1> |
| 1231 | @ proc getTclVersion {} { |
| 1232 | @ if {[catch {tclEval info patchlevel} tclVersion] == 0} { |
| 1233 | @ return "<a href=\"http://www.tcl.tk/\">Tcl</a> version $tclVersion" |
| 1234 | @ } |
| 1235 | @ return "" |
| 1236 | @ } |
| 1237 | @ proc getVersion { version } { |
| 1238 | @ set length [string length $version] |
| 1239 | @ return [string range $version 1 [expr {$length - 2}]] |
| 1240 | @ } |
| 1241 | @ set version [getVersion $manifest_version] |
| 1242 | @ set tclVersion [getTclVersion] |
| 1243 | @ set fossilUrl http://www.fossil-scm.org |
| 1244 | @ </th1> |
| 1245 | @ This page was generated in about |
| 1246 | @ <th1>puts [expr {([utime]+[stime]+1000)/1000*0.001}]</th1>s by |
| 1247 | @ <a href="$fossilUrl/">Fossil</a> |
| 1248 | @ version $release_version $tclVersion |
| 1249 | @ <a href="$fossilUrl/index.html/info/$version">$manifest_version</a> |
| 1250 | @ <a href="$fossilUrl/index.html/timeline?c=$manifest_date&y=ci">$manifest_date</a> |
| 1251 | @ </div> |
| 1252 | @ </body></html> |
| 1253 | @ '); |
| 1254 | ; |
| 1255 | |
| 1256 | /* |
| 1257 | ** An array of available built-in skins. |
| 1258 | */ |
| 1259 | static struct BuiltinSkin { |
| 1260 | const char *zName; |
| 1261 | const char *zValue; |
| 1262 | } aBuiltinSkin[] = { |
| 1263 | { "Default", 0 /* Filled in at runtime */ }, |
| 1264 | { "Plain Gray, No Logo", zBuiltinSkin1 }, |
| 1265 | { "Khaki, No Logo", zBuiltinSkin2 }, |
| 1266 | { "Black & White, Menu on Left", zBuiltinSkin3 }, |
| 1267 | { "Shadow boxes & Rounded Corners", zBuiltinSkin4 }, |
| 1268 | { "Enhanced Default", zBuiltinSkin5 }, |
| 1269 | }; |
| 1270 | |
| 1271 | /* |
| 1272 | ** For a skin named zSkinName, compute the name of the CONFIG table |
| 1273 | ** entry where that skin is stored and return it. |
| @@ -1286,57 +69,158 @@ | |
| 1286 | } |
| 1287 | return z; |
| 1288 | } |
| 1289 | |
| 1290 | /* |
| 1291 | ** Construct and return a string that represents the current skin if |
| 1292 | ** useDefault==0 or a string for the default skin if useDefault==1. |
| 1293 | ** |
| 1294 | ** Memory to hold the returned string is obtained from malloc. |
| 1295 | */ |
| 1296 | static char *getSkin(int useDefault){ |
| 1297 | Blob val; |
| 1298 | blob_zero(&val); |
| 1299 | blob_appendf(&val, |
| 1300 | "REPLACE INTO config(name,value,mtime) VALUES('css',%Q,now());\n", |
| 1301 | useDefault ? zDefaultCSS : db_get("css", (char*)zDefaultCSS) |
| 1302 | ); |
| 1303 | blob_appendf(&val, |
| 1304 | "REPLACE INTO config(name,value,mtime) VALUES('header',%Q,now());\n", |
| 1305 | useDefault ? zDefaultHeader : db_get("header", (char*)zDefaultHeader) |
| 1306 | ); |
| 1307 | blob_appendf(&val, |
| 1308 | "REPLACE INTO config(name,value,mtime) VALUES('footer',%Q,now());\n", |
| 1309 | useDefault ? zDefaultFooter : db_get("footer", (char*)zDefaultFooter) |
| 1310 | ); |
| 1311 | return blob_str(&val); |
| 1312 | } |
| 1313 | |
| 1314 | /* |
| 1315 | ** Construct the default skin string and fill in the corresponding |
| 1316 | ** entry in aBuildinSkin[] |
| 1317 | */ |
| 1318 | static void setDefaultSkin(void){ |
| 1319 | aBuiltinSkin[0].zValue = getSkin(1); |
| 1320 | } |
| 1321 | |
| 1322 | /* |
| 1323 | ** WEBPAGE: setup_skin |
| 1324 | */ |
| 1325 | void setup_skin(void){ |
| 1326 | const char *z; |
| 1327 | char *zName; |
| 1328 | char *zErr = 0; |
| 1329 | const char *zCurrent; /* Current skin */ |
| 1330 | int i; /* Loop counter */ |
| 1331 | Stmt q; |
| 1332 | |
| 1333 | login_check_credentials(); |
| 1334 | if( !g.perm.Setup ){ |
| 1335 | login_needed(); |
| 1336 | } |
| 1337 | db_begin_transaction(); |
| 1338 | |
| 1339 | /* Process requests to delete a user-defined skin */ |
| 1340 | if( P("del1") && (zName = skinVarName(P("sn"), 1))!=0 ){ |
| 1341 | style_header("Confirm Custom Skin Delete"); |
| 1342 | @ <form action="%s(g.zTop)/setup_skin" method="post"><div> |
| @@ -1351,51 +235,42 @@ | |
| 1351 | return; |
| 1352 | } |
| 1353 | if( P("del2")!=0 && (zName = skinVarName(P("sn"), 1))!=0 ){ |
| 1354 | db_multi_exec("DELETE FROM config WHERE name=%Q", zName); |
| 1355 | } |
| 1356 | |
| 1357 | setDefaultSkin(); |
| 1358 | zCurrent = getSkin(0); |
| 1359 | |
| 1360 | if( P("save")!=0 && (zName = skinVarName(P("save"),0))!=0 ){ |
| 1361 | if( db_exists("SELECT 1 FROM config WHERE name=%Q", zName) |
| 1362 | || fossil_strcmp(zName, "Default")==0 ){ |
| 1363 | zErr = mprintf("Skin name \"%h\" already exists. " |
| 1364 | "Choose a different name.", P("sn")); |
| 1365 | }else{ |
| 1366 | db_multi_exec("INSERT INTO config(name,value,mtime) VALUES(%Q,%Q,now())", |
| 1367 | zName, zCurrent |
| 1368 | ); |
| 1369 | } |
| 1370 | } |
| 1371 | |
| 1372 | /* The user pressed the "Use This Skin" button. */ |
| 1373 | if( P("load") && (z = P("sn"))!=0 && z[0] ){ |
| 1374 | int seen = 0; |
| 1375 | for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){ |
| 1376 | if( fossil_strcmp(aBuiltinSkin[i].zValue, zCurrent)==0 ){ |
| 1377 | seen = 1; |
| 1378 | break; |
| 1379 | } |
| 1380 | } |
| 1381 | if( !seen ){ |
| 1382 | seen = db_exists("SELECT 1 FROM config WHERE name GLOB 'skin:*'" |
| 1383 | " AND value=%Q", zCurrent); |
| 1384 | } |
| 1385 | if( !seen ){ |
| 1386 | db_multi_exec( |
| 1387 | "INSERT INTO config(name,value,mtime) VALUES(" |
| 1388 | " strftime('skin:Backup On %%Y-%%m-%%d %%H:%%M:%%S')," |
| 1389 | " %Q,now())", zCurrent |
| 1390 | ); |
| 1391 | } |
| 1392 | seen = 0; |
| 1393 | for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){ |
| 1394 | if( fossil_strcmp(aBuiltinSkin[i].zName, z)==0 ){ |
| 1395 | seen = 1; |
| 1396 | zCurrent = aBuiltinSkin[i].zValue; |
| 1397 | db_multi_exec("%s", zCurrent/*safe-for-%s*/); |
| 1398 | break; |
| 1399 | } |
| 1400 | } |
| 1401 | if( !seen ){ |
| @@ -1409,48 +284,59 @@ | |
| 1409 | if( zErr ){ |
| 1410 | @ <p><font color="red">%h(zErr)</font></p> |
| 1411 | } |
| 1412 | @ <p>A "skin" is a combination of |
| 1413 | @ <a href="setup_editcss">CSS</a>, |
| 1414 | @ <a href="setup_header">Header</a>, |
| 1415 | @ <a href="setup_footer">Footer</a>, and |
| 1416 | @ <a href="setup_logo">Logo</a> that determines the look and feel |
| 1417 | @ of the web interface.</p> |
| 1418 | @ |
| 1419 | @ <h2>Available Skins:</h2> |
| 1420 | @ <ol> |
| 1421 | for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){ |
| 1422 | z = aBuiltinSkin[i].zName; |
| 1423 | if( fossil_strcmp(aBuiltinSkin[i].zValue, zCurrent)==0 ){ |
| 1424 | @ <li><p>%h(z). <b>Currently In Use</b></p> |
| 1425 | }else{ |
| 1426 | @ <li><form action="%s(g.zTop)/setup_skin" method="post"><div> |
| 1427 | @ %h(z). |
| 1428 | @ <input type="hidden" name="sn" value="%h(z)" /> |
| 1429 | @ <input type="submit" name="load" value="Use This Skin" /> |
| 1430 | @ </div></form></li> |
| 1431 | } |
| 1432 | } |
| 1433 | db_prepare(&q, |
| 1434 | "SELECT substr(name, 6), value FROM config" |
| 1435 | " WHERE name GLOB 'skin:*'" |
| 1436 | " ORDER BY name" |
| 1437 | ); |
| 1438 | while( db_step(&q)==SQLITE_ROW ){ |
| 1439 | const char *zN = db_column_text(&q, 0); |
| 1440 | const char *zV = db_column_text(&q, 1); |
| 1441 | if( fossil_strcmp(zV, zCurrent)==0 ){ |
| 1442 | @ <li><p>%h(zN). <b>Currently In Use</b></p> |
| 1443 | }else{ |
| 1444 | @ <li><form action="%s(g.zTop)/setup_skin" method="post"> |
| 1445 | @ %h(zN). |
| 1446 | @ <input type="hidden" name="sn" value="%h(zN)"> |
| 1447 | @ <input type="submit" name="load" value="Use This Skin"> |
| 1448 | @ <input type="submit" name="del1" value="Delete This Skin"> |
| 1449 | @ </form></li> |
| 1450 | } |
| 1451 | } |
| 1452 | db_finalize(&q); |
| 1453 | @ </ol> |
| 1454 | style_footer(); |
| 1455 | db_end_transaction(0); |
| 1456 | } |
| 1457 |
| --- src/skins.c | |
| +++ src/skins.c | |
| @@ -19,1255 +19,38 @@ | |
| 19 | */ |
| 20 | #include "config.h" |
| 21 | #include <assert.h> |
| 22 | #include "skins.h" |
| 23 | |
| 24 | /* |
| 25 | ** An array of available built-in skins. |
| 26 | ** |
| 27 | ** To add new built-in skins: |
| 28 | ** |
| 29 | ** 1. Pick a name for the new skin. (Here we use "xyzzy"). |
| 30 | ** |
| 31 | ** 2. Install files skins/xyzzy/css.txt, skins/xyzzy/header.txt, |
| 32 | ** and skins/xyzzy/footer.txt into the source tree. |
| 33 | ** |
| 34 | ** 3. Rerun "tclsh makemake.tcl" in the src/ folder in order to |
| 35 | ** rebuild the makefiles to reference the new CSS, headers, and footers. |
| 36 | ** |
| 37 | ** 4. Make an entry in the following array for the new skin. |
| 38 | */ |
| 39 | static struct BuiltinSkin { |
| 40 | const char *zDesc; /* Description of this skin */ |
| 41 | const char *zLabel; /* The directory under skins/ holding this skin */ |
| 42 | char *zSQL; /* Filled in at run-time with SQL to insert this skin */ |
| 43 | } aBuiltinSkin[] = { |
| 44 | { "Default", "default", 0 }, |
| 45 | { "Plain Gray, No Logo", "plain_gray", 0 }, |
| 46 | { "Khaki, No Logo", "khaki", 0 }, |
| 47 | { "Black & White, Menu on Left", "black_and_white", 0 }, |
| 48 | { "Shadow boxes & Rounded Corners", "rounded1", 0 }, |
| 49 | { "Enhanced Default", "enhanced1", 0 }, |
| 50 | { "San Francisco Modern", "etienne1", 0 }, |
| 51 | { "Eagle", "eagle", 0 }, |
| 52 | }; |
| 53 | |
| 54 | /* |
| 55 | ** For a skin named zSkinName, compute the name of the CONFIG table |
| 56 | ** entry where that skin is stored and return it. |
| @@ -1286,57 +69,158 @@ | |
| 69 | } |
| 70 | return z; |
| 71 | } |
| 72 | |
| 73 | /* |
| 74 | ** Return true if there exists a skin name "zSkinName". |
| 75 | */ |
| 76 | static int skinExists(const char *zSkinName){ |
| 77 | int i; |
| 78 | if( zSkinName==0 ) return 0; |
| 79 | for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){ |
| 80 | if( fossil_strcmp(zSkinName, aBuiltinSkin[i].zDesc)==0 ) return 1; |
| 81 | } |
| 82 | return db_exists("SELECT 1 FROM config WHERE name='skin:%q'", zSkinName); |
| 83 | } |
| 84 | |
| 85 | /* |
| 86 | ** Construct and return an string of SQL statements that represents |
| 87 | ** a "skin" setting. If zName==0 then return the skin currently |
| 88 | ** installed. Otherwise, return one of the built-in skins designated |
| 89 | ** by zName. |
| 90 | ** |
| 91 | ** Memory to hold the returned string is obtained from malloc. |
| 92 | */ |
| 93 | static char *getSkin(const char *zName){ |
| 94 | const char *z; |
| 95 | char *zLabel; |
| 96 | static const char *azType[] = { "css", "header", "footer" }; |
| 97 | int i; |
| 98 | Blob val; |
| 99 | blob_zero(&val); |
| 100 | for(i=0; i<sizeof(azType)/sizeof(azType[0]); i++){ |
| 101 | if( zName ){ |
| 102 | zLabel = mprintf("skins/%s/%s.txt", zName, azType[i]); |
| 103 | z = builtin_text(zLabel); |
| 104 | fossil_free(zLabel); |
| 105 | }else{ |
| 106 | z = db_get(azType[i], 0); |
| 107 | if( z==0 ){ |
| 108 | zLabel = mprintf("skins/default/%s.txt", azType[i]); |
| 109 | z = builtin_text(zLabel); |
| 110 | fossil_free(zLabel); |
| 111 | } |
| 112 | } |
| 113 | blob_appendf(&val, |
| 114 | "REPLACE INTO config(name,value,mtime) VALUES(%Q,%Q,now());\n", |
| 115 | azType[i], z |
| 116 | ); |
| 117 | } |
| 118 | return blob_str(&val); |
| 119 | } |
| 120 | |
| 121 | /* |
| 122 | ** Respond to a Rename button press. Return TRUE if a dialog was painted. |
| 123 | ** Return FALSE to continue with the main Skins page. |
| 124 | */ |
| 125 | static int skinRename(void){ |
| 126 | const char *zOldName; |
| 127 | const char *zNewName; |
| 128 | int ex = 0; |
| 129 | if( P("rename")==0 ) return 0; |
| 130 | zOldName = P("sn"); |
| 131 | zNewName = P("newname"); |
| 132 | if( zOldName==0 ) return 0; |
| 133 | if( zNewName==0 || zNewName[0]==0 || (ex = skinExists(zNewName))!=0 ){ |
| 134 | if( zNewName==0 ) zNewName = zOldName; |
| 135 | style_header("Rename A Skin"); |
| 136 | if( ex ){ |
| 137 | @ <p><span class="generalError">There is already another skin |
| 138 | @ named "%h(zNewName)". Choose a different name.</span></p> |
| 139 | } |
| 140 | @ <form action="%s(g.zTop)/setup_skin" method="post"><div> |
| 141 | @ <table border="0"><tr> |
| 142 | @ <tr><td align="right">Current name:<td align="left"><b>%h(zOldName)</b> |
| 143 | @ <tr><td align="right">New name:<td align="left"> |
| 144 | @ <input type="text" size="35" name="newname" value="%h(zNewName)"> |
| 145 | @ <tr><td><td> |
| 146 | @ <input type="hidden" name="sn" value="%h(zOldName)"> |
| 147 | @ <input type="submit" name="rename" value="Rename"> |
| 148 | @ <input type="submit" name="canren" value="Cancel"> |
| 149 | @ </table> |
| 150 | login_insert_csrf_secret(); |
| 151 | @ </div></form> |
| 152 | style_footer(); |
| 153 | return 1; |
| 154 | } |
| 155 | db_multi_exec( |
| 156 | "UPDATE config SET name='skin:%q' WHERE name='skin:%q';", |
| 157 | zNewName, zOldName |
| 158 | ); |
| 159 | return 0; |
| 160 | } |
| 161 | |
| 162 | /* |
| 163 | ** Respond to a Save button press. Return TRUE if a dialog was painted. |
| 164 | ** Return FALSE to continue with the main Skins page. |
| 165 | */ |
| 166 | static int skinSave(const char *zCurrent){ |
| 167 | const char *zNewName; |
| 168 | int ex = 0; |
| 169 | if( P("save")==0 ) return 0; |
| 170 | zNewName = P("svname"); |
| 171 | if( zNewName && zNewName[0]!=0 ){ |
| 172 | } |
| 173 | if( zNewName==0 || zNewName[0]==0 || (ex = skinExists(zNewName))!=0 ){ |
| 174 | if( zNewName==0 ) zNewName = ""; |
| 175 | style_header("Save Current Skin"); |
| 176 | if( ex ){ |
| 177 | @ <p><span class="generalError">There is already another skin |
| 178 | @ named "%h(zNewName)". Choose a different name.</span></p> |
| 179 | } |
| 180 | @ <form action="%s(g.zTop)/setup_skin" method="post"><div> |
| 181 | @ <table border="0"><tr> |
| 182 | @ <tr><td align="right">Name for this skin:<td align="left"> |
| 183 | @ <input type="text" size="35" name="svname" value="%h(zNewName)"> |
| 184 | @ <tr><td><td> |
| 185 | @ <input type="submit" name="save" value="Save"> |
| 186 | @ <input type="submit" name="cansave" value="Cancel"> |
| 187 | @ </table> |
| 188 | login_insert_csrf_secret(); |
| 189 | @ </div></form> |
| 190 | style_footer(); |
| 191 | return 1; |
| 192 | } |
| 193 | db_multi_exec( |
| 194 | "INSERT OR IGNORE INTO config(name, value, mtime)" |
| 195 | "VALUES('skin:%q',%Q,now())", |
| 196 | zNewName, zCurrent |
| 197 | ); |
| 198 | return 0; |
| 199 | } |
| 200 | |
| 201 | /* |
| 202 | ** WEBPAGE: setup_skin |
| 203 | */ |
| 204 | void setup_skin(void){ |
| 205 | const char *z; |
| 206 | char *zName; |
| 207 | char *zErr = 0; |
| 208 | const char *zCurrent = 0; /* Current skin */ |
| 209 | int i; /* Loop counter */ |
| 210 | Stmt q; |
| 211 | int seenCurrent = 0; |
| 212 | |
| 213 | login_check_credentials(); |
| 214 | if( !g.perm.Setup ){ |
| 215 | login_needed(); |
| 216 | } |
| 217 | db_begin_transaction(); |
| 218 | zCurrent = getSkin(0); |
| 219 | for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){ |
| 220 | aBuiltinSkin[i].zSQL = getSkin(aBuiltinSkin[i].zLabel); |
| 221 | } |
| 222 | |
| 223 | /* Process requests to delete a user-defined skin */ |
| 224 | if( P("del1") && (zName = skinVarName(P("sn"), 1))!=0 ){ |
| 225 | style_header("Confirm Custom Skin Delete"); |
| 226 | @ <form action="%s(g.zTop)/setup_skin" method="post"><div> |
| @@ -1351,51 +235,42 @@ | |
| 235 | return; |
| 236 | } |
| 237 | if( P("del2")!=0 && (zName = skinVarName(P("sn"), 1))!=0 ){ |
| 238 | db_multi_exec("DELETE FROM config WHERE name=%Q", zName); |
| 239 | } |
| 240 | if( skinRename() ) return; |
| 241 | if( skinSave(zCurrent) ) return; |
| 242 | |
| 243 | /* The user pressed one of the "Install" buttons. */ |
| 244 | if( P("load") && (z = P("sn"))!=0 && z[0] ){ |
| 245 | int seen = 0; |
| 246 | |
| 247 | /* Check to see if the current skin is already saved. If it is, there |
| 248 | ** is no need to create a backup */ |
| 249 | zCurrent = getSkin(0); |
| 250 | for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){ |
| 251 | if( fossil_strcmp(aBuiltinSkin[i].zSQL, zCurrent)==0 ){ |
| 252 | seen = 1; |
| 253 | break; |
| 254 | } |
| 255 | } |
| 256 | if( !seen ){ |
| 257 | seen = db_exists("SELECT 1 FROM config WHERE name GLOB 'skin:*'" |
| 258 | " AND value=%Q", zCurrent); |
| 259 | if( !seen ){ |
| 260 | db_multi_exec( |
| 261 | "INSERT INTO config(name,value,mtime) VALUES(" |
| 262 | " strftime('skin:Backup On %%Y-%%m-%%d %%H:%%M:%%S')," |
| 263 | " %Q,now())", zCurrent |
| 264 | ); |
| 265 | } |
| 266 | } |
| 267 | seen = 0; |
| 268 | for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){ |
| 269 | if( fossil_strcmp(aBuiltinSkin[i].zDesc, z)==0 ){ |
| 270 | seen = 1; |
| 271 | zCurrent = aBuiltinSkin[i].zSQL; |
| 272 | db_multi_exec("%s", zCurrent/*safe-for-%s*/); |
| 273 | break; |
| 274 | } |
| 275 | } |
| 276 | if( !seen ){ |
| @@ -1409,48 +284,59 @@ | |
| 284 | if( zErr ){ |
| 285 | @ <p><font color="red">%h(zErr)</font></p> |
| 286 | } |
| 287 | @ <p>A "skin" is a combination of |
| 288 | @ <a href="setup_editcss">CSS</a>, |
| 289 | @ <a href="setup_header">Header</a>, and |
| 290 | @ <a href="setup_footer">Footer</a> that determines the look and feel |
| 291 | @ of the web interface.</p> |
| 292 | @ |
| 293 | @ <h2>Available Skins:</h2> |
| 294 | @ <table border="0"> |
| 295 | for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){ |
| 296 | z = aBuiltinSkin[i].zDesc; |
| 297 | @ <tr><td>%d(i+1).<td>%h(z)<td> <td> |
| 298 | if( fossil_strcmp(aBuiltinSkin[i].zSQL, zCurrent)==0 ){ |
| 299 | @ (Currently In Use) |
| 300 | seenCurrent = 1; |
| 301 | }else{ |
| 302 | @ <form action="%s(g.zTop)/setup_skin" method="post"> |
| 303 | @ <input type="hidden" name="sn" value="%h(z)" /> |
| 304 | @ <input type="submit" name="load" value="Install" /> |
| 305 | @ </form> |
| 306 | } |
| 307 | @ </tr> |
| 308 | } |
| 309 | db_prepare(&q, |
| 310 | "SELECT substr(name, 6), value FROM config" |
| 311 | " WHERE name GLOB 'skin:*'" |
| 312 | " ORDER BY name" |
| 313 | ); |
| 314 | while( db_step(&q)==SQLITE_ROW ){ |
| 315 | const char *zN = db_column_text(&q, 0); |
| 316 | const char *zV = db_column_text(&q, 1); |
| 317 | i++; |
| 318 | @ <tr><td>%d(i).<td>%h(zN)<td> <td> |
| 319 | @ <form action="%s(g.zTop)/setup_skin" method="post"> |
| 320 | if( fossil_strcmp(zV, zCurrent)==0 ){ |
| 321 | @ (Currently In Use) |
| 322 | seenCurrent = 1; |
| 323 | }else{ |
| 324 | @ <input type="submit" name="load" value="Install"> |
| 325 | @ <input type="submit" name="del1" value="Delete"> |
| 326 | } |
| 327 | @ <input type="submit" name="rename" value="Rename"> |
| 328 | @ <input type="hidden" name="sn" value="%h(zN)"> |
| 329 | @ </form></tr> |
| 330 | } |
| 331 | db_finalize(&q); |
| 332 | if( !seenCurrent ){ |
| 333 | i++; |
| 334 | @ <tr><td>%d(i).<td><i>Current Configuration</i><td> <td> |
| 335 | @ <form action="%s(g.zTop)/setup_skin" method="post"> |
| 336 | @ <input type="submit" name="save" value="Save"> |
| 337 | @ </form> |
| 338 | } |
| 339 | @ </table> |
| 340 | style_footer(); |
| 341 | db_end_transaction(0); |
| 342 | } |
| 343 |
+2
| --- src/sqlcmd.c | ||
| +++ src/sqlcmd.c | ||
| @@ -170,10 +170,12 @@ | ||
| 170 | 170 | ** checkin_mtime(X,Y) Return the mtime for the file Y (a BLOB.RID) |
| 171 | 171 | ** found in check-in X (another BLOB.RID value). |
| 172 | 172 | ** |
| 173 | 173 | ** symbolic_name_to_rid(X) Return a the BLOB.RID corresponding to symbolic |
| 174 | 174 | ** name X. |
| 175 | +** | |
| 176 | +** now() Return the number of seconds since 1970. | |
| 175 | 177 | ** |
| 176 | 178 | ** REGEXP The REGEXP operator works, unlike in |
| 177 | 179 | ** standard SQLite. |
| 178 | 180 | ** |
| 179 | 181 | ** files_of_checkin The "files_of_check" virtual table is |
| 180 | 182 |
| --- src/sqlcmd.c | |
| +++ src/sqlcmd.c | |
| @@ -170,10 +170,12 @@ | |
| 170 | ** checkin_mtime(X,Y) Return the mtime for the file Y (a BLOB.RID) |
| 171 | ** found in check-in X (another BLOB.RID value). |
| 172 | ** |
| 173 | ** symbolic_name_to_rid(X) Return a the BLOB.RID corresponding to symbolic |
| 174 | ** name X. |
| 175 | ** |
| 176 | ** REGEXP The REGEXP operator works, unlike in |
| 177 | ** standard SQLite. |
| 178 | ** |
| 179 | ** files_of_checkin The "files_of_check" virtual table is |
| 180 |
| --- src/sqlcmd.c | |
| +++ src/sqlcmd.c | |
| @@ -170,10 +170,12 @@ | |
| 170 | ** checkin_mtime(X,Y) Return the mtime for the file Y (a BLOB.RID) |
| 171 | ** found in check-in X (another BLOB.RID value). |
| 172 | ** |
| 173 | ** symbolic_name_to_rid(X) Return a the BLOB.RID corresponding to symbolic |
| 174 | ** name X. |
| 175 | ** |
| 176 | ** now() Return the number of seconds since 1970. |
| 177 | ** |
| 178 | ** REGEXP The REGEXP operator works, unlike in |
| 179 | ** standard SQLite. |
| 180 | ** |
| 181 | ** files_of_checkin The "files_of_check" virtual table is |
| 182 |
+59
-9
| --- src/sqlite3.c | ||
| +++ src/sqlite3.c | ||
| @@ -1,8 +1,8 @@ | ||
| 1 | 1 | /****************************************************************************** |
| 2 | 2 | ** This file is an amalgamation of many separate C source files from SQLite |
| 3 | -** version 3.8.8. By combining all the individual C code files into this | |
| 3 | +** version 3.8.8.1. By combining all the individual C code files into this | |
| 4 | 4 | ** single large file, the entire code can be compiled as a single translation |
| 5 | 5 | ** unit. This allows many compilers to do optimizations that would not be |
| 6 | 6 | ** possible if the files were compiled separately. Performance improvements |
| 7 | 7 | ** of 5% or more are commonly seen when SQLite is compiled as a single |
| 8 | 8 | ** translation unit. |
| @@ -276,13 +276,13 @@ | ||
| 276 | 276 | ** |
| 277 | 277 | ** See also: [sqlite3_libversion()], |
| 278 | 278 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 279 | 279 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 280 | 280 | */ |
| 281 | -#define SQLITE_VERSION "3.8.8" | |
| 281 | +#define SQLITE_VERSION "3.8.8.1" | |
| 282 | 282 | #define SQLITE_VERSION_NUMBER 3008008 |
| 283 | -#define SQLITE_SOURCE_ID "2015-01-16 12:08:06 7d68a42face3ab14ed88407d4331872f5b243fdf" | |
| 283 | +#define SQLITE_SOURCE_ID "2015-01-20 16:51:25 f73337e3e289915a76ca96e7a05a1a8d4e890d55" | |
| 284 | 284 | |
| 285 | 285 | /* |
| 286 | 286 | ** CAPI3REF: Run-Time Library Version Numbers |
| 287 | 287 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 288 | 288 | ** |
| @@ -19870,10 +19870,21 @@ | ||
| 19870 | 19870 | # define SQLITE_WIN32_VOLATILE |
| 19871 | 19871 | #else |
| 19872 | 19872 | # define SQLITE_WIN32_VOLATILE volatile |
| 19873 | 19873 | #endif |
| 19874 | 19874 | |
| 19875 | +/* | |
| 19876 | +** For some Windows sub-platforms, the _beginthreadex() / _endthreadex() | |
| 19877 | +** functions are not available (e.g. those not using MSVC, Cygwin, etc). | |
| 19878 | +*/ | |
| 19879 | +#if SQLITE_OS_WIN && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && \ | |
| 19880 | + SQLITE_THREADSAFE>0 && !defined(__CYGWIN__) | |
| 19881 | +# define SQLITE_OS_WIN_THREADS 1 | |
| 19882 | +#else | |
| 19883 | +# define SQLITE_OS_WIN_THREADS 0 | |
| 19884 | +#endif | |
| 19885 | + | |
| 19875 | 19886 | #endif /* _OS_WIN_H_ */ |
| 19876 | 19887 | |
| 19877 | 19888 | /************** End of os_win.h **********************************************/ |
| 19878 | 19889 | /************** Continuing where we left off in mutex_w32.c ******************/ |
| 19879 | 19890 | #endif |
| @@ -22433,11 +22444,11 @@ | ||
| 22433 | 22444 | #endif /* SQLITE_OS_UNIX && defined(SQLITE_MUTEX_PTHREADS) */ |
| 22434 | 22445 | /******************************** End Unix Pthreads *************************/ |
| 22435 | 22446 | |
| 22436 | 22447 | |
| 22437 | 22448 | /********************************* Win32 Threads ****************************/ |
| 22438 | -#if SQLITE_OS_WIN && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_THREADSAFE>0 | |
| 22449 | +#if SQLITE_OS_WIN_THREADS | |
| 22439 | 22450 | |
| 22440 | 22451 | #define SQLITE_THREADS_IMPLEMENTED 1 /* Prevent the single-thread code below */ |
| 22441 | 22452 | #include <process.h> |
| 22442 | 22453 | |
| 22443 | 22454 | /* A running thread */ |
| @@ -22526,11 +22537,11 @@ | ||
| 22526 | 22537 | if( rc==WAIT_OBJECT_0 ) *ppOut = p->pResult; |
| 22527 | 22538 | sqlite3_free(p); |
| 22528 | 22539 | return (rc==WAIT_OBJECT_0) ? SQLITE_OK : SQLITE_ERROR; |
| 22529 | 22540 | } |
| 22530 | 22541 | |
| 22531 | -#endif /* SQLITE_OS_WIN && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT */ | |
| 22542 | +#endif /* SQLITE_OS_WIN_THREADS */ | |
| 22532 | 22543 | /******************************** End Win32 Threads *************************/ |
| 22533 | 22544 | |
| 22534 | 22545 | |
| 22535 | 22546 | /********************************* Single-Threaded **************************/ |
| 22536 | 22547 | #ifndef SQLITE_THREADS_IMPLEMENTED |
| @@ -67496,10 +67507,45 @@ | ||
| 67496 | 67507 | if( pKeyInfo->db->mallocFailed ) return 1; |
| 67497 | 67508 | return 0; |
| 67498 | 67509 | } |
| 67499 | 67510 | #endif |
| 67500 | 67511 | |
| 67512 | +#if SQLITE_DEBUG | |
| 67513 | +/* | |
| 67514 | +** Count the number of fields (a.k.a. columns) in the record given by | |
| 67515 | +** pKey,nKey. The verify that this count is less than or equal to the | |
| 67516 | +** limit given by pKeyInfo->nField + pKeyInfo->nXField. | |
| 67517 | +** | |
| 67518 | +** If this constraint is not satisfied, it means that the high-speed | |
| 67519 | +** vdbeRecordCompareInt() and vdbeRecordCompareString() routines will | |
| 67520 | +** not work correctly. If this assert() ever fires, it probably means | |
| 67521 | +** that the KeyInfo.nField or KeyInfo.nXField values were computed | |
| 67522 | +** incorrectly. | |
| 67523 | +*/ | |
| 67524 | +static void vdbeAssertFieldCountWithinLimits( | |
| 67525 | + int nKey, const void *pKey, /* The record to verify */ | |
| 67526 | + const KeyInfo *pKeyInfo /* Compare size with this KeyInfo */ | |
| 67527 | +){ | |
| 67528 | + int nField = 0; | |
| 67529 | + u32 szHdr; | |
| 67530 | + u32 idx; | |
| 67531 | + u32 notUsed; | |
| 67532 | + const unsigned char *aKey = (const unsigned char*)pKey; | |
| 67533 | + | |
| 67534 | + if( CORRUPT_DB ) return; | |
| 67535 | + idx = getVarint32(aKey, szHdr); | |
| 67536 | + assert( szHdr<=nKey ); | |
| 67537 | + while( idx<szHdr ){ | |
| 67538 | + idx += getVarint32(aKey+idx, notUsed); | |
| 67539 | + nField++; | |
| 67540 | + } | |
| 67541 | + assert( nField <= pKeyInfo->nField+pKeyInfo->nXField ); | |
| 67542 | +} | |
| 67543 | +#else | |
| 67544 | +# define vdbeAssertFieldCountWithinLimits(A,B,C) | |
| 67545 | +#endif | |
| 67546 | + | |
| 67501 | 67547 | /* |
| 67502 | 67548 | ** Both *pMem1 and *pMem2 contain string values. Compare the two values |
| 67503 | 67549 | ** using the collation sequence pColl. As usual, return a negative , zero |
| 67504 | 67550 | ** or positive value if *pMem1 is less than, equal to or greater than |
| 67505 | 67551 | ** *pMem2, respectively. Similar in spirit to "rc = (*pMem1) - (*pMem2);". |
| @@ -67907,10 +67953,11 @@ | ||
| 67907 | 67953 | u32 y; |
| 67908 | 67954 | u64 x; |
| 67909 | 67955 | i64 v = pPKey2->aMem[0].u.i; |
| 67910 | 67956 | i64 lhs; |
| 67911 | 67957 | |
| 67958 | + vdbeAssertFieldCountWithinLimits(nKey1, pKey1, pPKey2->pKeyInfo); | |
| 67912 | 67959 | assert( (*(u8*)pKey1)<=0x3F || CORRUPT_DB ); |
| 67913 | 67960 | switch( serial_type ){ |
| 67914 | 67961 | case 1: { /* 1-byte signed integer */ |
| 67915 | 67962 | lhs = ONE_BYTE_INT(aKey); |
| 67916 | 67963 | testcase( lhs<0 ); |
| @@ -67994,10 +68041,11 @@ | ||
| 67994 | 68041 | ){ |
| 67995 | 68042 | const u8 *aKey1 = (const u8*)pKey1; |
| 67996 | 68043 | int serial_type; |
| 67997 | 68044 | int res; |
| 67998 | 68045 | |
| 68046 | + vdbeAssertFieldCountWithinLimits(nKey1, pKey1, pPKey2->pKeyInfo); | |
| 67999 | 68047 | getVarint32(&aKey1[1], serial_type); |
| 68000 | 68048 | if( serial_type<12 ){ |
| 68001 | 68049 | res = pPKey2->r1; /* (pKey1/nKey1) is a number or a null */ |
| 68002 | 68050 | }else if( !(serial_type & 0x01) ){ |
| 68003 | 68051 | res = pPKey2->r2; /* (pKey1/nKey1) is a blob */ |
| @@ -105795,11 +105843,13 @@ | ||
| 105795 | 105843 | if( pParse->db->mallocFailed ) return; |
| 105796 | 105844 | pOp->p2 = nKey + nData; |
| 105797 | 105845 | pKI = pOp->p4.pKeyInfo; |
| 105798 | 105846 | memset(pKI->aSortOrder, 0, pKI->nField); /* Makes OP_Jump below testable */ |
| 105799 | 105847 | sqlite3VdbeChangeP4(v, -1, (char*)pKI, P4_KEYINFO); |
| 105800 | - pOp->p4.pKeyInfo = keyInfoFromExprList(pParse, pSort->pOrderBy, nOBSat, 1); | |
| 105848 | + testcase( pKI->nXField>2 ); | |
| 105849 | + pOp->p4.pKeyInfo = keyInfoFromExprList(pParse, pSort->pOrderBy, nOBSat, | |
| 105850 | + pKI->nXField-1); | |
| 105801 | 105851 | addrJmp = sqlite3VdbeCurrentAddr(v); |
| 105802 | 105852 | sqlite3VdbeAddOp3(v, OP_Jump, addrJmp+1, 0, addrJmp+1); VdbeCoverage(v); |
| 105803 | 105853 | pSort->labelBkOut = sqlite3VdbeMakeLabel(v); |
| 105804 | 105854 | pSort->regReturn = ++pParse->nMem; |
| 105805 | 105855 | sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut); |
| @@ -106306,11 +106356,11 @@ | ||
| 106306 | 106356 | struct ExprList_item *pItem; |
| 106307 | 106357 | sqlite3 *db = pParse->db; |
| 106308 | 106358 | int i; |
| 106309 | 106359 | |
| 106310 | 106360 | nExpr = pList->nExpr; |
| 106311 | - pInfo = sqlite3KeyInfoAlloc(db, nExpr+nExtra-iStart, 1); | |
| 106361 | + pInfo = sqlite3KeyInfoAlloc(db, nExpr-iStart, nExtra+1); | |
| 106312 | 106362 | if( pInfo ){ |
| 106313 | 106363 | assert( sqlite3KeyInfoIsWriteable(pInfo) ); |
| 106314 | 106364 | for(i=iStart, pItem=pList->a+iStart; i<nExpr; i++, pItem++){ |
| 106315 | 106365 | CollSeq *pColl; |
| 106316 | 106366 | pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr); |
| @@ -110176,11 +110226,11 @@ | ||
| 110176 | 110226 | ** we figure out that the sorting index is not needed. The addrSortIndex |
| 110177 | 110227 | ** variable is used to facilitate that change. |
| 110178 | 110228 | */ |
| 110179 | 110229 | if( sSort.pOrderBy ){ |
| 110180 | 110230 | KeyInfo *pKeyInfo; |
| 110181 | - pKeyInfo = keyInfoFromExprList(pParse, sSort.pOrderBy, 0, 0); | |
| 110231 | + pKeyInfo = keyInfoFromExprList(pParse, sSort.pOrderBy, 0, pEList->nExpr); | |
| 110182 | 110232 | sSort.iECursor = pParse->nTab++; |
| 110183 | 110233 | sSort.addrSortIndex = |
| 110184 | 110234 | sqlite3VdbeAddOp4(v, OP_OpenEphemeral, |
| 110185 | 110235 | sSort.iECursor, sSort.pOrderBy->nExpr+1+pEList->nExpr, 0, |
| 110186 | 110236 | (char*)pKeyInfo, P4_KEYINFO |
| @@ -110350,11 +110400,11 @@ | ||
| 110350 | 110400 | ** implement it. Allocate that sorting index now. If it turns out |
| 110351 | 110401 | ** that we do not need it after all, the OP_SorterOpen instruction |
| 110352 | 110402 | ** will be converted into a Noop. |
| 110353 | 110403 | */ |
| 110354 | 110404 | sAggInfo.sortingIdx = pParse->nTab++; |
| 110355 | - pKeyInfo = keyInfoFromExprList(pParse, pGroupBy, 0, 0); | |
| 110405 | + pKeyInfo = keyInfoFromExprList(pParse, pGroupBy, 0, sAggInfo.nColumn); | |
| 110356 | 110406 | addrSortingIdx = sqlite3VdbeAddOp4(v, OP_SorterOpen, |
| 110357 | 110407 | sAggInfo.sortingIdx, sAggInfo.nSortingColumn, |
| 110358 | 110408 | 0, (char*)pKeyInfo, P4_KEYINFO); |
| 110359 | 110409 | |
| 110360 | 110410 | /* Initialize memory locations used by GROUP BY aggregate processing |
| 110361 | 110411 |
| --- src/sqlite3.c | |
| +++ src/sqlite3.c | |
| @@ -1,8 +1,8 @@ | |
| 1 | /****************************************************************************** |
| 2 | ** This file is an amalgamation of many separate C source files from SQLite |
| 3 | ** version 3.8.8. By combining all the individual C code files into this |
| 4 | ** single large file, the entire code can be compiled as a single translation |
| 5 | ** unit. This allows many compilers to do optimizations that would not be |
| 6 | ** possible if the files were compiled separately. Performance improvements |
| 7 | ** of 5% or more are commonly seen when SQLite is compiled as a single |
| 8 | ** translation unit. |
| @@ -276,13 +276,13 @@ | |
| 276 | ** |
| 277 | ** See also: [sqlite3_libversion()], |
| 278 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 279 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 280 | */ |
| 281 | #define SQLITE_VERSION "3.8.8" |
| 282 | #define SQLITE_VERSION_NUMBER 3008008 |
| 283 | #define SQLITE_SOURCE_ID "2015-01-16 12:08:06 7d68a42face3ab14ed88407d4331872f5b243fdf" |
| 284 | |
| 285 | /* |
| 286 | ** CAPI3REF: Run-Time Library Version Numbers |
| 287 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 288 | ** |
| @@ -19870,10 +19870,21 @@ | |
| 19870 | # define SQLITE_WIN32_VOLATILE |
| 19871 | #else |
| 19872 | # define SQLITE_WIN32_VOLATILE volatile |
| 19873 | #endif |
| 19874 | |
| 19875 | #endif /* _OS_WIN_H_ */ |
| 19876 | |
| 19877 | /************** End of os_win.h **********************************************/ |
| 19878 | /************** Continuing where we left off in mutex_w32.c ******************/ |
| 19879 | #endif |
| @@ -22433,11 +22444,11 @@ | |
| 22433 | #endif /* SQLITE_OS_UNIX && defined(SQLITE_MUTEX_PTHREADS) */ |
| 22434 | /******************************** End Unix Pthreads *************************/ |
| 22435 | |
| 22436 | |
| 22437 | /********************************* Win32 Threads ****************************/ |
| 22438 | #if SQLITE_OS_WIN && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_THREADSAFE>0 |
| 22439 | |
| 22440 | #define SQLITE_THREADS_IMPLEMENTED 1 /* Prevent the single-thread code below */ |
| 22441 | #include <process.h> |
| 22442 | |
| 22443 | /* A running thread */ |
| @@ -22526,11 +22537,11 @@ | |
| 22526 | if( rc==WAIT_OBJECT_0 ) *ppOut = p->pResult; |
| 22527 | sqlite3_free(p); |
| 22528 | return (rc==WAIT_OBJECT_0) ? SQLITE_OK : SQLITE_ERROR; |
| 22529 | } |
| 22530 | |
| 22531 | #endif /* SQLITE_OS_WIN && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT */ |
| 22532 | /******************************** End Win32 Threads *************************/ |
| 22533 | |
| 22534 | |
| 22535 | /********************************* Single-Threaded **************************/ |
| 22536 | #ifndef SQLITE_THREADS_IMPLEMENTED |
| @@ -67496,10 +67507,45 @@ | |
| 67496 | if( pKeyInfo->db->mallocFailed ) return 1; |
| 67497 | return 0; |
| 67498 | } |
| 67499 | #endif |
| 67500 | |
| 67501 | /* |
| 67502 | ** Both *pMem1 and *pMem2 contain string values. Compare the two values |
| 67503 | ** using the collation sequence pColl. As usual, return a negative , zero |
| 67504 | ** or positive value if *pMem1 is less than, equal to or greater than |
| 67505 | ** *pMem2, respectively. Similar in spirit to "rc = (*pMem1) - (*pMem2);". |
| @@ -67907,10 +67953,11 @@ | |
| 67907 | u32 y; |
| 67908 | u64 x; |
| 67909 | i64 v = pPKey2->aMem[0].u.i; |
| 67910 | i64 lhs; |
| 67911 | |
| 67912 | assert( (*(u8*)pKey1)<=0x3F || CORRUPT_DB ); |
| 67913 | switch( serial_type ){ |
| 67914 | case 1: { /* 1-byte signed integer */ |
| 67915 | lhs = ONE_BYTE_INT(aKey); |
| 67916 | testcase( lhs<0 ); |
| @@ -67994,10 +68041,11 @@ | |
| 67994 | ){ |
| 67995 | const u8 *aKey1 = (const u8*)pKey1; |
| 67996 | int serial_type; |
| 67997 | int res; |
| 67998 | |
| 67999 | getVarint32(&aKey1[1], serial_type); |
| 68000 | if( serial_type<12 ){ |
| 68001 | res = pPKey2->r1; /* (pKey1/nKey1) is a number or a null */ |
| 68002 | }else if( !(serial_type & 0x01) ){ |
| 68003 | res = pPKey2->r2; /* (pKey1/nKey1) is a blob */ |
| @@ -105795,11 +105843,13 @@ | |
| 105795 | if( pParse->db->mallocFailed ) return; |
| 105796 | pOp->p2 = nKey + nData; |
| 105797 | pKI = pOp->p4.pKeyInfo; |
| 105798 | memset(pKI->aSortOrder, 0, pKI->nField); /* Makes OP_Jump below testable */ |
| 105799 | sqlite3VdbeChangeP4(v, -1, (char*)pKI, P4_KEYINFO); |
| 105800 | pOp->p4.pKeyInfo = keyInfoFromExprList(pParse, pSort->pOrderBy, nOBSat, 1); |
| 105801 | addrJmp = sqlite3VdbeCurrentAddr(v); |
| 105802 | sqlite3VdbeAddOp3(v, OP_Jump, addrJmp+1, 0, addrJmp+1); VdbeCoverage(v); |
| 105803 | pSort->labelBkOut = sqlite3VdbeMakeLabel(v); |
| 105804 | pSort->regReturn = ++pParse->nMem; |
| 105805 | sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut); |
| @@ -106306,11 +106356,11 @@ | |
| 106306 | struct ExprList_item *pItem; |
| 106307 | sqlite3 *db = pParse->db; |
| 106308 | int i; |
| 106309 | |
| 106310 | nExpr = pList->nExpr; |
| 106311 | pInfo = sqlite3KeyInfoAlloc(db, nExpr+nExtra-iStart, 1); |
| 106312 | if( pInfo ){ |
| 106313 | assert( sqlite3KeyInfoIsWriteable(pInfo) ); |
| 106314 | for(i=iStart, pItem=pList->a+iStart; i<nExpr; i++, pItem++){ |
| 106315 | CollSeq *pColl; |
| 106316 | pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr); |
| @@ -110176,11 +110226,11 @@ | |
| 110176 | ** we figure out that the sorting index is not needed. The addrSortIndex |
| 110177 | ** variable is used to facilitate that change. |
| 110178 | */ |
| 110179 | if( sSort.pOrderBy ){ |
| 110180 | KeyInfo *pKeyInfo; |
| 110181 | pKeyInfo = keyInfoFromExprList(pParse, sSort.pOrderBy, 0, 0); |
| 110182 | sSort.iECursor = pParse->nTab++; |
| 110183 | sSort.addrSortIndex = |
| 110184 | sqlite3VdbeAddOp4(v, OP_OpenEphemeral, |
| 110185 | sSort.iECursor, sSort.pOrderBy->nExpr+1+pEList->nExpr, 0, |
| 110186 | (char*)pKeyInfo, P4_KEYINFO |
| @@ -110350,11 +110400,11 @@ | |
| 110350 | ** implement it. Allocate that sorting index now. If it turns out |
| 110351 | ** that we do not need it after all, the OP_SorterOpen instruction |
| 110352 | ** will be converted into a Noop. |
| 110353 | */ |
| 110354 | sAggInfo.sortingIdx = pParse->nTab++; |
| 110355 | pKeyInfo = keyInfoFromExprList(pParse, pGroupBy, 0, 0); |
| 110356 | addrSortingIdx = sqlite3VdbeAddOp4(v, OP_SorterOpen, |
| 110357 | sAggInfo.sortingIdx, sAggInfo.nSortingColumn, |
| 110358 | 0, (char*)pKeyInfo, P4_KEYINFO); |
| 110359 | |
| 110360 | /* Initialize memory locations used by GROUP BY aggregate processing |
| 110361 |
| --- src/sqlite3.c | |
| +++ src/sqlite3.c | |
| @@ -1,8 +1,8 @@ | |
| 1 | /****************************************************************************** |
| 2 | ** This file is an amalgamation of many separate C source files from SQLite |
| 3 | ** version 3.8.8.1. By combining all the individual C code files into this |
| 4 | ** single large file, the entire code can be compiled as a single translation |
| 5 | ** unit. This allows many compilers to do optimizations that would not be |
| 6 | ** possible if the files were compiled separately. Performance improvements |
| 7 | ** of 5% or more are commonly seen when SQLite is compiled as a single |
| 8 | ** translation unit. |
| @@ -276,13 +276,13 @@ | |
| 276 | ** |
| 277 | ** See also: [sqlite3_libversion()], |
| 278 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 279 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 280 | */ |
| 281 | #define SQLITE_VERSION "3.8.8.1" |
| 282 | #define SQLITE_VERSION_NUMBER 3008008 |
| 283 | #define SQLITE_SOURCE_ID "2015-01-20 16:51:25 f73337e3e289915a76ca96e7a05a1a8d4e890d55" |
| 284 | |
| 285 | /* |
| 286 | ** CAPI3REF: Run-Time Library Version Numbers |
| 287 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 288 | ** |
| @@ -19870,10 +19870,21 @@ | |
| 19870 | # define SQLITE_WIN32_VOLATILE |
| 19871 | #else |
| 19872 | # define SQLITE_WIN32_VOLATILE volatile |
| 19873 | #endif |
| 19874 | |
| 19875 | /* |
| 19876 | ** For some Windows sub-platforms, the _beginthreadex() / _endthreadex() |
| 19877 | ** functions are not available (e.g. those not using MSVC, Cygwin, etc). |
| 19878 | */ |
| 19879 | #if SQLITE_OS_WIN && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && \ |
| 19880 | SQLITE_THREADSAFE>0 && !defined(__CYGWIN__) |
| 19881 | # define SQLITE_OS_WIN_THREADS 1 |
| 19882 | #else |
| 19883 | # define SQLITE_OS_WIN_THREADS 0 |
| 19884 | #endif |
| 19885 | |
| 19886 | #endif /* _OS_WIN_H_ */ |
| 19887 | |
| 19888 | /************** End of os_win.h **********************************************/ |
| 19889 | /************** Continuing where we left off in mutex_w32.c ******************/ |
| 19890 | #endif |
| @@ -22433,11 +22444,11 @@ | |
| 22444 | #endif /* SQLITE_OS_UNIX && defined(SQLITE_MUTEX_PTHREADS) */ |
| 22445 | /******************************** End Unix Pthreads *************************/ |
| 22446 | |
| 22447 | |
| 22448 | /********************************* Win32 Threads ****************************/ |
| 22449 | #if SQLITE_OS_WIN_THREADS |
| 22450 | |
| 22451 | #define SQLITE_THREADS_IMPLEMENTED 1 /* Prevent the single-thread code below */ |
| 22452 | #include <process.h> |
| 22453 | |
| 22454 | /* A running thread */ |
| @@ -22526,11 +22537,11 @@ | |
| 22537 | if( rc==WAIT_OBJECT_0 ) *ppOut = p->pResult; |
| 22538 | sqlite3_free(p); |
| 22539 | return (rc==WAIT_OBJECT_0) ? SQLITE_OK : SQLITE_ERROR; |
| 22540 | } |
| 22541 | |
| 22542 | #endif /* SQLITE_OS_WIN_THREADS */ |
| 22543 | /******************************** End Win32 Threads *************************/ |
| 22544 | |
| 22545 | |
| 22546 | /********************************* Single-Threaded **************************/ |
| 22547 | #ifndef SQLITE_THREADS_IMPLEMENTED |
| @@ -67496,10 +67507,45 @@ | |
| 67507 | if( pKeyInfo->db->mallocFailed ) return 1; |
| 67508 | return 0; |
| 67509 | } |
| 67510 | #endif |
| 67511 | |
| 67512 | #if SQLITE_DEBUG |
| 67513 | /* |
| 67514 | ** Count the number of fields (a.k.a. columns) in the record given by |
| 67515 | ** pKey,nKey. The verify that this count is less than or equal to the |
| 67516 | ** limit given by pKeyInfo->nField + pKeyInfo->nXField. |
| 67517 | ** |
| 67518 | ** If this constraint is not satisfied, it means that the high-speed |
| 67519 | ** vdbeRecordCompareInt() and vdbeRecordCompareString() routines will |
| 67520 | ** not work correctly. If this assert() ever fires, it probably means |
| 67521 | ** that the KeyInfo.nField or KeyInfo.nXField values were computed |
| 67522 | ** incorrectly. |
| 67523 | */ |
| 67524 | static void vdbeAssertFieldCountWithinLimits( |
| 67525 | int nKey, const void *pKey, /* The record to verify */ |
| 67526 | const KeyInfo *pKeyInfo /* Compare size with this KeyInfo */ |
| 67527 | ){ |
| 67528 | int nField = 0; |
| 67529 | u32 szHdr; |
| 67530 | u32 idx; |
| 67531 | u32 notUsed; |
| 67532 | const unsigned char *aKey = (const unsigned char*)pKey; |
| 67533 | |
| 67534 | if( CORRUPT_DB ) return; |
| 67535 | idx = getVarint32(aKey, szHdr); |
| 67536 | assert( szHdr<=nKey ); |
| 67537 | while( idx<szHdr ){ |
| 67538 | idx += getVarint32(aKey+idx, notUsed); |
| 67539 | nField++; |
| 67540 | } |
| 67541 | assert( nField <= pKeyInfo->nField+pKeyInfo->nXField ); |
| 67542 | } |
| 67543 | #else |
| 67544 | # define vdbeAssertFieldCountWithinLimits(A,B,C) |
| 67545 | #endif |
| 67546 | |
| 67547 | /* |
| 67548 | ** Both *pMem1 and *pMem2 contain string values. Compare the two values |
| 67549 | ** using the collation sequence pColl. As usual, return a negative , zero |
| 67550 | ** or positive value if *pMem1 is less than, equal to or greater than |
| 67551 | ** *pMem2, respectively. Similar in spirit to "rc = (*pMem1) - (*pMem2);". |
| @@ -67907,10 +67953,11 @@ | |
| 67953 | u32 y; |
| 67954 | u64 x; |
| 67955 | i64 v = pPKey2->aMem[0].u.i; |
| 67956 | i64 lhs; |
| 67957 | |
| 67958 | vdbeAssertFieldCountWithinLimits(nKey1, pKey1, pPKey2->pKeyInfo); |
| 67959 | assert( (*(u8*)pKey1)<=0x3F || CORRUPT_DB ); |
| 67960 | switch( serial_type ){ |
| 67961 | case 1: { /* 1-byte signed integer */ |
| 67962 | lhs = ONE_BYTE_INT(aKey); |
| 67963 | testcase( lhs<0 ); |
| @@ -67994,10 +68041,11 @@ | |
| 68041 | ){ |
| 68042 | const u8 *aKey1 = (const u8*)pKey1; |
| 68043 | int serial_type; |
| 68044 | int res; |
| 68045 | |
| 68046 | vdbeAssertFieldCountWithinLimits(nKey1, pKey1, pPKey2->pKeyInfo); |
| 68047 | getVarint32(&aKey1[1], serial_type); |
| 68048 | if( serial_type<12 ){ |
| 68049 | res = pPKey2->r1; /* (pKey1/nKey1) is a number or a null */ |
| 68050 | }else if( !(serial_type & 0x01) ){ |
| 68051 | res = pPKey2->r2; /* (pKey1/nKey1) is a blob */ |
| @@ -105795,11 +105843,13 @@ | |
| 105843 | if( pParse->db->mallocFailed ) return; |
| 105844 | pOp->p2 = nKey + nData; |
| 105845 | pKI = pOp->p4.pKeyInfo; |
| 105846 | memset(pKI->aSortOrder, 0, pKI->nField); /* Makes OP_Jump below testable */ |
| 105847 | sqlite3VdbeChangeP4(v, -1, (char*)pKI, P4_KEYINFO); |
| 105848 | testcase( pKI->nXField>2 ); |
| 105849 | pOp->p4.pKeyInfo = keyInfoFromExprList(pParse, pSort->pOrderBy, nOBSat, |
| 105850 | pKI->nXField-1); |
| 105851 | addrJmp = sqlite3VdbeCurrentAddr(v); |
| 105852 | sqlite3VdbeAddOp3(v, OP_Jump, addrJmp+1, 0, addrJmp+1); VdbeCoverage(v); |
| 105853 | pSort->labelBkOut = sqlite3VdbeMakeLabel(v); |
| 105854 | pSort->regReturn = ++pParse->nMem; |
| 105855 | sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut); |
| @@ -106306,11 +106356,11 @@ | |
| 106356 | struct ExprList_item *pItem; |
| 106357 | sqlite3 *db = pParse->db; |
| 106358 | int i; |
| 106359 | |
| 106360 | nExpr = pList->nExpr; |
| 106361 | pInfo = sqlite3KeyInfoAlloc(db, nExpr-iStart, nExtra+1); |
| 106362 | if( pInfo ){ |
| 106363 | assert( sqlite3KeyInfoIsWriteable(pInfo) ); |
| 106364 | for(i=iStart, pItem=pList->a+iStart; i<nExpr; i++, pItem++){ |
| 106365 | CollSeq *pColl; |
| 106366 | pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr); |
| @@ -110176,11 +110226,11 @@ | |
| 110226 | ** we figure out that the sorting index is not needed. The addrSortIndex |
| 110227 | ** variable is used to facilitate that change. |
| 110228 | */ |
| 110229 | if( sSort.pOrderBy ){ |
| 110230 | KeyInfo *pKeyInfo; |
| 110231 | pKeyInfo = keyInfoFromExprList(pParse, sSort.pOrderBy, 0, pEList->nExpr); |
| 110232 | sSort.iECursor = pParse->nTab++; |
| 110233 | sSort.addrSortIndex = |
| 110234 | sqlite3VdbeAddOp4(v, OP_OpenEphemeral, |
| 110235 | sSort.iECursor, sSort.pOrderBy->nExpr+1+pEList->nExpr, 0, |
| 110236 | (char*)pKeyInfo, P4_KEYINFO |
| @@ -110350,11 +110400,11 @@ | |
| 110400 | ** implement it. Allocate that sorting index now. If it turns out |
| 110401 | ** that we do not need it after all, the OP_SorterOpen instruction |
| 110402 | ** will be converted into a Noop. |
| 110403 | */ |
| 110404 | sAggInfo.sortingIdx = pParse->nTab++; |
| 110405 | pKeyInfo = keyInfoFromExprList(pParse, pGroupBy, 0, sAggInfo.nColumn); |
| 110406 | addrSortingIdx = sqlite3VdbeAddOp4(v, OP_SorterOpen, |
| 110407 | sAggInfo.sortingIdx, sAggInfo.nSortingColumn, |
| 110408 | 0, (char*)pKeyInfo, P4_KEYINFO); |
| 110409 | |
| 110410 | /* Initialize memory locations used by GROUP BY aggregate processing |
| 110411 |
+2
-2
| --- src/sqlite3.h | ||
| +++ src/sqlite3.h | ||
| @@ -105,13 +105,13 @@ | ||
| 105 | 105 | ** |
| 106 | 106 | ** See also: [sqlite3_libversion()], |
| 107 | 107 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 108 | 108 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 109 | 109 | */ |
| 110 | -#define SQLITE_VERSION "3.8.8" | |
| 110 | +#define SQLITE_VERSION "3.8.8.1" | |
| 111 | 111 | #define SQLITE_VERSION_NUMBER 3008008 |
| 112 | -#define SQLITE_SOURCE_ID "2015-01-16 12:08:06 7d68a42face3ab14ed88407d4331872f5b243fdf" | |
| 112 | +#define SQLITE_SOURCE_ID "2015-01-20 16:51:25 f73337e3e289915a76ca96e7a05a1a8d4e890d55" | |
| 113 | 113 | |
| 114 | 114 | /* |
| 115 | 115 | ** CAPI3REF: Run-Time Library Version Numbers |
| 116 | 116 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 117 | 117 | ** |
| 118 | 118 |
| --- src/sqlite3.h | |
| +++ src/sqlite3.h | |
| @@ -105,13 +105,13 @@ | |
| 105 | ** |
| 106 | ** See also: [sqlite3_libversion()], |
| 107 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 108 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 109 | */ |
| 110 | #define SQLITE_VERSION "3.8.8" |
| 111 | #define SQLITE_VERSION_NUMBER 3008008 |
| 112 | #define SQLITE_SOURCE_ID "2015-01-16 12:08:06 7d68a42face3ab14ed88407d4331872f5b243fdf" |
| 113 | |
| 114 | /* |
| 115 | ** CAPI3REF: Run-Time Library Version Numbers |
| 116 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 117 | ** |
| 118 |
| --- src/sqlite3.h | |
| +++ src/sqlite3.h | |
| @@ -105,13 +105,13 @@ | |
| 105 | ** |
| 106 | ** See also: [sqlite3_libversion()], |
| 107 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 108 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 109 | */ |
| 110 | #define SQLITE_VERSION "3.8.8.1" |
| 111 | #define SQLITE_VERSION_NUMBER 3008008 |
| 112 | #define SQLITE_SOURCE_ID "2015-01-20 16:51:25 f73337e3e289915a76ca96e7a05a1a8d4e890d55" |
| 113 | |
| 114 | /* |
| 115 | ** CAPI3REF: Run-Time Library Version Numbers |
| 116 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 117 | ** |
| 118 |
+3
| --- src/stat.c | ||
| +++ src/stat.c | ||
| @@ -55,10 +55,11 @@ | ||
| 55 | 55 | |
| 56 | 56 | login_check_credentials(); |
| 57 | 57 | if( !g.perm.Read ){ login_needed(); return; } |
| 58 | 58 | brief = P("brief")!=0; |
| 59 | 59 | style_header("Repository Statistics"); |
| 60 | + style_adunit_config(ADUNIT_RIGHT_OK); | |
| 60 | 61 | if( g.perm.Admin ){ |
| 61 | 62 | style_submenu_element("URLs", "URLs and Checkouts", "urllist"); |
| 62 | 63 | style_submenu_element("Schema", "Repository Schema", "repo_schema"); |
| 63 | 64 | style_submenu_element("Web-Cache", "Web-Cache Stats", "cachestat"); |
| 64 | 65 | } |
| @@ -290,10 +291,11 @@ | ||
| 290 | 291 | int cnt; |
| 291 | 292 | login_check_credentials(); |
| 292 | 293 | if( !g.perm.Admin ){ login_needed(); return; } |
| 293 | 294 | |
| 294 | 295 | style_header("URLs and Checkouts"); |
| 296 | + style_adunit_config(ADUNIT_RIGHT_OK); | |
| 295 | 297 | style_submenu_element("Stat", "Repository Stats", "stat"); |
| 296 | 298 | style_submenu_element("Schema", "Repository Schema", "repo_schema"); |
| 297 | 299 | @ <div class="section">URLs</div> |
| 298 | 300 | @ <table border="0" width='100%%'> |
| 299 | 301 | db_prepare(&q, "SELECT substr(name,9), datetime(mtime,'unixepoch')" |
| @@ -336,10 +338,11 @@ | ||
| 336 | 338 | Stmt q; |
| 337 | 339 | login_check_credentials(); |
| 338 | 340 | if( !g.perm.Admin ){ login_needed(); return; } |
| 339 | 341 | |
| 340 | 342 | style_header("Repository Schema"); |
| 343 | + style_adunit_config(ADUNIT_RIGHT_OK); | |
| 341 | 344 | style_submenu_element("Stat", "Repository Stats", "stat"); |
| 342 | 345 | style_submenu_element("URLs", "URLs and Checkouts", "urllist"); |
| 343 | 346 | db_prepare(&q, "SELECT sql FROM %s.sqlite_master WHERE sql IS NOT NULL", |
| 344 | 347 | db_name("repository")); |
| 345 | 348 | @ <pre> |
| 346 | 349 |
| --- src/stat.c | |
| +++ src/stat.c | |
| @@ -55,10 +55,11 @@ | |
| 55 | |
| 56 | login_check_credentials(); |
| 57 | if( !g.perm.Read ){ login_needed(); return; } |
| 58 | brief = P("brief")!=0; |
| 59 | style_header("Repository Statistics"); |
| 60 | if( g.perm.Admin ){ |
| 61 | style_submenu_element("URLs", "URLs and Checkouts", "urllist"); |
| 62 | style_submenu_element("Schema", "Repository Schema", "repo_schema"); |
| 63 | style_submenu_element("Web-Cache", "Web-Cache Stats", "cachestat"); |
| 64 | } |
| @@ -290,10 +291,11 @@ | |
| 290 | int cnt; |
| 291 | login_check_credentials(); |
| 292 | if( !g.perm.Admin ){ login_needed(); return; } |
| 293 | |
| 294 | style_header("URLs and Checkouts"); |
| 295 | style_submenu_element("Stat", "Repository Stats", "stat"); |
| 296 | style_submenu_element("Schema", "Repository Schema", "repo_schema"); |
| 297 | @ <div class="section">URLs</div> |
| 298 | @ <table border="0" width='100%%'> |
| 299 | db_prepare(&q, "SELECT substr(name,9), datetime(mtime,'unixepoch')" |
| @@ -336,10 +338,11 @@ | |
| 336 | Stmt q; |
| 337 | login_check_credentials(); |
| 338 | if( !g.perm.Admin ){ login_needed(); return; } |
| 339 | |
| 340 | style_header("Repository Schema"); |
| 341 | style_submenu_element("Stat", "Repository Stats", "stat"); |
| 342 | style_submenu_element("URLs", "URLs and Checkouts", "urllist"); |
| 343 | db_prepare(&q, "SELECT sql FROM %s.sqlite_master WHERE sql IS NOT NULL", |
| 344 | db_name("repository")); |
| 345 | @ <pre> |
| 346 |
| --- src/stat.c | |
| +++ src/stat.c | |
| @@ -55,10 +55,11 @@ | |
| 55 | |
| 56 | login_check_credentials(); |
| 57 | if( !g.perm.Read ){ login_needed(); return; } |
| 58 | brief = P("brief")!=0; |
| 59 | style_header("Repository Statistics"); |
| 60 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 61 | if( g.perm.Admin ){ |
| 62 | style_submenu_element("URLs", "URLs and Checkouts", "urllist"); |
| 63 | style_submenu_element("Schema", "Repository Schema", "repo_schema"); |
| 64 | style_submenu_element("Web-Cache", "Web-Cache Stats", "cachestat"); |
| 65 | } |
| @@ -290,10 +291,11 @@ | |
| 291 | int cnt; |
| 292 | login_check_credentials(); |
| 293 | if( !g.perm.Admin ){ login_needed(); return; } |
| 294 | |
| 295 | style_header("URLs and Checkouts"); |
| 296 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 297 | style_submenu_element("Stat", "Repository Stats", "stat"); |
| 298 | style_submenu_element("Schema", "Repository Schema", "repo_schema"); |
| 299 | @ <div class="section">URLs</div> |
| 300 | @ <table border="0" width='100%%'> |
| 301 | db_prepare(&q, "SELECT substr(name,9), datetime(mtime,'unixepoch')" |
| @@ -336,10 +338,11 @@ | |
| 338 | Stmt q; |
| 339 | login_check_credentials(); |
| 340 | if( !g.perm.Admin ){ login_needed(); return; } |
| 341 | |
| 342 | style_header("Repository Schema"); |
| 343 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 344 | style_submenu_element("Stat", "Repository Stats", "stat"); |
| 345 | style_submenu_element("URLs", "URLs and Checkouts", "urllist"); |
| 346 | db_prepare(&q, "SELECT sql FROM %s.sqlite_master WHERE sql IS NOT NULL", |
| 347 | db_name("repository")); |
| 348 | @ <pre> |
| 349 |
+64
-240
| --- src/style.c | ||
| +++ src/style.c | ||
| @@ -46,10 +46,15 @@ | ||
| 46 | 46 | /* |
| 47 | 47 | ** remember, if a sidebox was used |
| 48 | 48 | */ |
| 49 | 49 | static int sideboxUsed = 0; |
| 50 | 50 | |
| 51 | +/* | |
| 52 | +** Ad-unit styles. | |
| 53 | +*/ | |
| 54 | +static unsigned adUnitFlags = 0; | |
| 55 | + | |
| 51 | 56 | |
| 52 | 57 | /* |
| 53 | 58 | ** List of hyperlinks and forms that need to be resolved by javascript in |
| 54 | 59 | ** the footer. |
| 55 | 60 | */ |
| @@ -284,11 +289,12 @@ | ||
| 284 | 289 | ** Draw the header. |
| 285 | 290 | */ |
| 286 | 291 | void style_header(const char *zTitleFormat, ...){ |
| 287 | 292 | va_list ap; |
| 288 | 293 | char *zTitle; |
| 289 | - const char *zHeader = db_get("header", (char*)zDefaultHeader); | |
| 294 | + const char *zHeader = db_get("header", 0); | |
| 295 | + if( zHeader==0 ) zHeader = builtin_text("skins/default/header.txt"); | |
| 290 | 296 | login_check_credentials(); |
| 291 | 297 | |
| 292 | 298 | va_start(ap, zTitleFormat); |
| 293 | 299 | zTitle = vmprintf(zTitleFormat, ap); |
| 294 | 300 | va_end(ap); |
| @@ -343,34 +349,64 @@ | ||
| 343 | 349 | @ var e = document.getElementById(x); |
| 344 | 350 | @ if(!e) throw new Error("Expecting element with ID "+x); |
| 345 | 351 | @ else return e;} |
| 346 | 352 | @ </script> |
| 347 | 353 | } |
| 354 | + | |
| 355 | +#if INTERFACE | |
| 356 | +/* Allowed parameters for style_adunit() */ | |
| 357 | +#define ADUNIT_OFF 0x0001 /* Do not allow ads on this page */ | |
| 358 | +#define ADUNIT_RIGHT_OK 0x0002 /* Right-side vertical ads ok here */ | |
| 359 | +#endif | |
| 360 | + | |
| 361 | +/* | |
| 362 | +** Various page implementations can invoke this interface to let the | |
| 363 | +** style manager know what kinds of ads are appropriate for this page. | |
| 364 | +*/ | |
| 365 | +void style_adunit_config(unsigned int mFlags){ | |
| 366 | + adUnitFlags = mFlags; | |
| 367 | +} | |
| 348 | 368 | |
| 349 | 369 | /* |
| 350 | -** Append ad unit text if appropriate. | |
| 370 | +** Return the text of an ad-unit, if one should be rendered. Return | |
| 371 | +** NULL if no ad-unit is desired. | |
| 372 | +** | |
| 373 | +** The *pAdFlag value might be set to ADUNIT_RIGHT_OK if this is | |
| 374 | +** a right-hand vertical ad. | |
| 351 | 375 | */ |
| 352 | -static void style_ad_unit(void){ | |
| 353 | - const char *zAd; | |
| 376 | +static const char *style_adunit_text(unsigned int *pAdFlag){ | |
| 377 | + const char *zAd = 0; | |
| 378 | + *pAdFlag = 0; | |
| 379 | + if( adUnitFlags & ADUNIT_OFF ) return 0; /* Disallow ads on this page */ | |
| 354 | 380 | if( g.perm.Admin && db_get_boolean("adunit-omit-if-admin",0) ){ |
| 355 | - return; | |
| 381 | + return 0; | |
| 356 | 382 | } |
| 357 | 383 | if( !login_is_nobody() |
| 358 | 384 | && fossil_strcmp(g.zLogin,"anonymous")!=0 |
| 359 | 385 | && db_get_boolean("adunit-omit-if-user",0) |
| 360 | 386 | ){ |
| 361 | - return; | |
| 387 | + return 0; | |
| 388 | + } | |
| 389 | + if( (adUnitFlags & ADUNIT_RIGHT_OK)!=0 | |
| 390 | + && !fossil_all_whitespace(zAd = db_get("adunit-right", 0)) | |
| 391 | + && !cgi_body_contains("<table") | |
| 392 | + ){ | |
| 393 | + *pAdFlag = ADUNIT_RIGHT_OK; | |
| 394 | + return zAd; | |
| 395 | + }else if( !fossil_all_whitespace(zAd = db_get("adunit",0)) ){ | |
| 396 | + return zAd; | |
| 362 | 397 | } |
| 363 | - zAd = db_get("adunit", 0); | |
| 364 | - if( zAd ) cgi_append_content(zAd, -1); | |
| 398 | + return 0; | |
| 365 | 399 | } |
| 366 | 400 | |
| 367 | 401 | /* |
| 368 | 402 | ** Draw the footer at the bottom of the page. |
| 369 | 403 | */ |
| 370 | 404 | void style_footer(void){ |
| 371 | 405 | const char *zFooter; |
| 406 | + const char *zAd = 0; | |
| 407 | + unsigned int mAdFlags = 0; | |
| 372 | 408 | |
| 373 | 409 | if( !headerHasBeenGenerated ) return; |
| 374 | 410 | |
| 375 | 411 | /* Go back and put the submenu at the top of the page. We delay the |
| 376 | 412 | ** creation of the submenu until the end so that we can add elements |
| @@ -389,12 +425,25 @@ | ||
| 389 | 425 | @ <a class="label" href="%h(p->zLink)">%h(p->zLabel)</a> |
| 390 | 426 | } |
| 391 | 427 | } |
| 392 | 428 | @ </div> |
| 393 | 429 | } |
| 394 | - style_ad_unit(); | |
| 395 | - @ <div class="content"> | |
| 430 | + | |
| 431 | + zAd = style_adunit_text(&mAdFlags); | |
| 432 | + if( (mAdFlags & ADUNIT_RIGHT_OK)!=0 ){ | |
| 433 | + @ <div class="content adunit_right_container"> | |
| 434 | + @ <div class="adunit_right"> | |
| 435 | + cgi_append_content(zAd, -1); | |
| 436 | + @ </div> | |
| 437 | + }else{ | |
| 438 | + if( zAd ){ | |
| 439 | + @ <div class="adunit_banner"> | |
| 440 | + cgi_append_content(zAd, -1); | |
| 441 | + @ </div> | |
| 442 | + } | |
| 443 | + @ <div class="content"> | |
| 444 | + } | |
| 396 | 445 | cgi_destination(CGI_BODY); |
| 397 | 446 | |
| 398 | 447 | if( sideboxUsed ){ |
| 399 | 448 | /* Put the footer at the bottom of the page. |
| 400 | 449 | ** the additional clear/both is needed to extend the content |
| @@ -406,11 +455,12 @@ | ||
| 406 | 455 | |
| 407 | 456 | /* Set the href= field on hyperlinks. Do this before the footer since |
| 408 | 457 | ** the footer will be generating </html> */ |
| 409 | 458 | style_resolve_href(); |
| 410 | 459 | |
| 411 | - zFooter = db_get("footer", (char*)zDefaultFooter); | |
| 460 | + zFooter = db_get("footer", 0); | |
| 461 | + if( zFooter==0 ) zFooter = builtin_text("skins/default/footer.txt"); | |
| 412 | 462 | if( g.thTrace ) Th_Trace("BEGIN_FOOTER<br />\n", -1); |
| 413 | 463 | Th_Render(zFooter); |
| 414 | 464 | if( g.thTrace ) Th_Trace("END_FOOTER<br />\n", -1); |
| 415 | 465 | |
| 416 | 466 | /* Render trace log if TH1 tracing is enabled. */ |
| @@ -436,230 +486,10 @@ | ||
| 436 | 486 | */ |
| 437 | 487 | void style_sidebox_end(void){ |
| 438 | 488 | @ </div> |
| 439 | 489 | } |
| 440 | 490 | |
| 441 | -/* @-comment: // */ | |
| 442 | -/* | |
| 443 | -** The default page header. | |
| 444 | -*/ | |
| 445 | -const char zDefaultHeader[] = | |
| 446 | -@ <html> | |
| 447 | -@ <head> | |
| 448 | -@ <base href="$baseurl/$current_page" /> | |
| 449 | -@ <title>$<project_name>: $<title></title> | |
| 450 | -@ <link rel="alternate" type="application/rss+xml" title="RSS Feed" | |
| 451 | -@ href="$home/timeline.rss" /> | |
| 452 | -@ <link rel="stylesheet" href="$stylesheet_url" type="text/css" | |
| 453 | -@ media="screen" /> | |
| 454 | -@ </head> | |
| 455 | -@ <body> | |
| 456 | -@ <div class="header"> | |
| 457 | -@ <div class="logo"> | |
| 458 | -@ <img src="$logo_image_url" alt="logo" /> | |
| 459 | -@ </div> | |
| 460 | -@ <div class="title"><small>$<project_name></small><br />$<title></div> | |
| 461 | -@ <div class="status"><th1> | |
| 462 | -@ if {[info exists login]} { | |
| 463 | -@ puts "Logged in as $login" | |
| 464 | -@ } else { | |
| 465 | -@ puts "Not logged in" | |
| 466 | -@ } | |
| 467 | -@ </th1></div> | |
| 468 | -@ </div> | |
| 469 | -@ <div class="mainmenu"> | |
| 470 | -@ <th1> | |
| 471 | -@ html "<a href='$home$index_page'>Home</a>\n" | |
| 472 | -@ if {[anycap jor]} { | |
| 473 | -@ html "<a href='$home/timeline'>Timeline</a>\n" | |
| 474 | -@ } | |
| 475 | -@ if {[hascap oh]} { | |
| 476 | -@ html "<a href='$home/tree?ci=tip'>Files</a>\n" | |
| 477 | -@ } | |
| 478 | -@ if {[hascap o]} { | |
| 479 | -@ html "<a href='$home/brlist'>Branches</a>\n" | |
| 480 | -@ html "<a href='$home/taglist'>Tags</a>\n" | |
| 481 | -@ } | |
| 482 | -@ if {[hascap r]} { | |
| 483 | -@ html "<a href='$home/reportlist'>Tickets</a>\n" | |
| 484 | -@ } | |
| 485 | -@ if {[hascap j]} { | |
| 486 | -@ html "<a href='$home/wiki'>Wiki</a>\n" | |
| 487 | -@ } | |
| 488 | -@ if {[hascap s]} { | |
| 489 | -@ html "<a href='$home/setup'>Admin</a>\n" | |
| 490 | -@ } elseif {[hascap a]} { | |
| 491 | -@ html "<a href='$home/setup_ulist'>Users</a>\n" | |
| 492 | -@ } | |
| 493 | -@ if {[info exists login]} { | |
| 494 | -@ html "<a href='$home/login'>Logout</a>\n" | |
| 495 | -@ } else { | |
| 496 | -@ html "<a href='$home/login'>Login</a>\n" | |
| 497 | -@ } | |
| 498 | -@ </th1></div> | |
| 499 | -; | |
| 500 | - | |
| 501 | -/* | |
| 502 | -** The default page footer | |
| 503 | -*/ | |
| 504 | -const char zDefaultFooter[] = | |
| 505 | -@ <div class="footer"> | |
| 506 | -@ This page was generated in about | |
| 507 | -@ <th1>puts [expr {([utime]+[stime]+1000)/1000*0.001}]</th1>s by | |
| 508 | -@ Fossil version $manifest_version $manifest_date | |
| 509 | -@ </div> | |
| 510 | -@ </body></html> | |
| 511 | -; | |
| 512 | - | |
| 513 | -/* | |
| 514 | -** The default Cascading Style Sheet. | |
| 515 | -** It's assembled by different strings for each class. | |
| 516 | -** The default css contains all definitions. | |
| 517 | -** The style sheet, send to the client only contains the ones, | |
| 518 | -** not defined in the user defined css. | |
| 519 | -*/ | |
| 520 | -const char zDefaultCSS[] = | |
| 521 | -@ /* General settings for the entire page */ | |
| 522 | -@ body { | |
| 523 | -@ margin: 0ex 1ex; | |
| 524 | -@ padding: 0px; | |
| 525 | -@ background-color: white; | |
| 526 | -@ font-family: sans-serif; | |
| 527 | -@ } | |
| 528 | -@ | |
| 529 | -@ /* The project logo in the upper left-hand corner of each page */ | |
| 530 | -@ div.logo { | |
| 531 | -@ display: table-cell; | |
| 532 | -@ text-align: center; | |
| 533 | -@ vertical-align: bottom; | |
| 534 | -@ font-weight: bold; | |
| 535 | -@ color: #558195; | |
| 536 | -@ min-width: 200px; | |
| 537 | -@ white-space: nowrap; | |
| 538 | -@ } | |
| 539 | -@ | |
| 540 | -@ /* The page title centered at the top of each page */ | |
| 541 | -@ div.title { | |
| 542 | -@ display: table-cell; | |
| 543 | -@ font-size: 2em; | |
| 544 | -@ font-weight: bold; | |
| 545 | -@ text-align: center; | |
| 546 | -@ padding: 0 0 0 1em; | |
| 547 | -@ color: #558195; | |
| 548 | -@ vertical-align: bottom; | |
| 549 | -@ width: 100%; | |
| 550 | -@ } | |
| 551 | -@ | |
| 552 | -@ /* The login status message in the top right-hand corner */ | |
| 553 | -@ div.status { | |
| 554 | -@ display: table-cell; | |
| 555 | -@ text-align: right; | |
| 556 | -@ vertical-align: bottom; | |
| 557 | -@ color: #558195; | |
| 558 | -@ font-size: 0.8em; | |
| 559 | -@ font-weight: bold; | |
| 560 | -@ min-width: 200px; | |
| 561 | -@ white-space: nowrap; | |
| 562 | -@ } | |
| 563 | -@ | |
| 564 | -@ /* The header across the top of the page */ | |
| 565 | -@ div.header { | |
| 566 | -@ display: table; | |
| 567 | -@ width: 100%; | |
| 568 | -@ } | |
| 569 | -@ | |
| 570 | -@ /* The main menu bar that appears at the top of the page beneath | |
| 571 | -@ ** the header */ | |
| 572 | -@ div.mainmenu { | |
| 573 | -@ padding: 5px 10px 5px 10px; | |
| 574 | -@ font-size: 0.9em; | |
| 575 | -@ font-weight: bold; | |
| 576 | -@ text-align: center; | |
| 577 | -@ letter-spacing: 1px; | |
| 578 | -@ background-color: #558195; | |
| 579 | -@ border-top-left-radius: 8px; | |
| 580 | -@ border-top-right-radius: 8px; | |
| 581 | -@ color: white; | |
| 582 | -@ } | |
| 583 | -@ | |
| 584 | -@ /* The submenu bar that *sometimes* appears below the main menu */ | |
| 585 | -@ div.submenu, div.sectionmenu { | |
| 586 | -@ padding: 3px 10px 3px 0px; | |
| 587 | -@ font-size: 0.9em; | |
| 588 | -@ text-align: center; | |
| 589 | -@ background-color: #456878; | |
| 590 | -@ color: white; | |
| 591 | -@ } | |
| 592 | -@ div.mainmenu a, div.mainmenu a:visited, div.submenu a, div.submenu a:visited, | |
| 593 | -@ div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited { | |
| 594 | -@ padding: 3px 10px 3px 10px; | |
| 595 | -@ color: white; | |
| 596 | -@ text-decoration: none; | |
| 597 | -@ } | |
| 598 | -@ div.mainmenu a:hover, div.submenu a:hover, div.sectionmenu>a.button:hover { | |
| 599 | -@ color: #558195; | |
| 600 | -@ background-color: white; | |
| 601 | -@ } | |
| 602 | -@ | |
| 603 | -@ /* All page content from the bottom of the menu or submenu down to | |
| 604 | -@ ** the footer */ | |
| 605 | -@ div.content { | |
| 606 | -@ padding: 0ex 1ex 1ex 1ex; | |
| 607 | -@ border: solid #aaa; | |
| 608 | -@ border-width: 1px; | |
| 609 | -@ } | |
| 610 | -@ | |
| 611 | -@ /* Some pages have section dividers */ | |
| 612 | -@ div.section { | |
| 613 | -@ margin-bottom: 0px; | |
| 614 | -@ margin-top: 1em; | |
| 615 | -@ padding: 1px 1px 1px 1px; | |
| 616 | -@ font-size: 1.2em; | |
| 617 | -@ font-weight: bold; | |
| 618 | -@ background-color: #558195; | |
| 619 | -@ color: white; | |
| 620 | -@ white-space: nowrap; | |
| 621 | -@ } | |
| 622 | -@ | |
| 623 | -@ /* The "Date" that occurs on the left hand side of timelines */ | |
| 624 | -@ div.divider { | |
| 625 | -@ background: #a1c4d4; | |
| 626 | -@ border: 2px #558195 solid; | |
| 627 | -@ font-size: 1em; font-weight: normal; | |
| 628 | -@ padding: .25em; | |
| 629 | -@ margin: .2em 0 .2em 0; | |
| 630 | -@ float: left; | |
| 631 | -@ clear: left; | |
| 632 | -@ white-space: nowrap; | |
| 633 | -@ } | |
| 634 | -@ | |
| 635 | -@ /* The footer at the very bottom of the page */ | |
| 636 | -@ div.footer { | |
| 637 | -@ clear: both; | |
| 638 | -@ font-size: 0.8em; | |
| 639 | -@ padding: 5px 10px 5px 10px; | |
| 640 | -@ text-align: right; | |
| 641 | -@ background-color: #558195; | |
| 642 | -@ border-bottom-left-radius: 8px; | |
| 643 | -@ border-bottom-right-radius: 8px; | |
| 644 | -@ color: white; | |
| 645 | -@ } | |
| 646 | -@ | |
| 647 | -@ /* Hyperlink colors in the footer */ | |
| 648 | -@ div.footer a { color: white; } | |
| 649 | -@ div.footer a:link { color: white; } | |
| 650 | -@ div.footer a:visited { color: white; } | |
| 651 | -@ div.footer a:hover { background-color: white; color: #558195; } | |
| 652 | -@ | |
| 653 | -@ /* verbatim blocks */ | |
| 654 | -@ pre.verbatim { | |
| 655 | -@ background-color: #f5f5f5; | |
| 656 | -@ padding: 0.5em; | |
| 657 | -@ white-space: pre-wrap; | |
| 658 | -@} | |
| 659 | -; | |
| 660 | - | |
| 661 | 491 | |
| 662 | 492 | /* The following table contains bits of default CSS that must |
| 663 | 493 | ** be included if they are not found in the application-defined |
| 664 | 494 | ** CSS. |
| 665 | 495 | */ |
| @@ -666,14 +496,10 @@ | ||
| 666 | 496 | const struct strctCssDefaults { |
| 667 | 497 | const char *elementClass; /* Name of element needed */ |
| 668 | 498 | const char *comment; /* Comment text */ |
| 669 | 499 | const char *value; /* CSS text */ |
| 670 | 500 | } cssDefaultList[] = { |
| 671 | - { "", | |
| 672 | - "", | |
| 673 | - zDefaultCSS | |
| 674 | - }, | |
| 675 | 501 | { "div.sidebox", |
| 676 | 502 | "The nomenclature sidebox for branches,..", |
| 677 | 503 | @ float: right; |
| 678 | 504 | @ background-color: white; |
| 679 | 505 | @ border-width: medium; |
| @@ -1279,10 +1105,11 @@ | ||
| 1279 | 1105 | @ text-align: left; |
| 1280 | 1106 | @ padding: 0px 1em 0.5ex 0px; |
| 1281 | 1107 | }, |
| 1282 | 1108 | { ".brlist table td", "Branch list table headers", |
| 1283 | 1109 | @ padding: 0px 2em 0px 0px; |
| 1110 | + @ white-space: nowrap; | |
| 1284 | 1111 | }, |
| 1285 | 1112 | { "th.sort:after", |
| 1286 | 1113 | "General styles for sortable column marker", |
| 1287 | 1114 | @ margin-left: .4em; |
| 1288 | 1115 | @ cursor: pointer; |
| @@ -1310,19 +1137,16 @@ | ||
| 1310 | 1137 | ** Append all of the default CSS to the CGI output. |
| 1311 | 1138 | */ |
| 1312 | 1139 | void cgi_append_default_css(void) { |
| 1313 | 1140 | int i; |
| 1314 | 1141 | |
| 1142 | + cgi_printf("%s", builtin_text("skins/default/css.txt")); | |
| 1315 | 1143 | for( i=0; cssDefaultList[i].elementClass; i++ ){ |
| 1316 | 1144 | if( cssDefaultList[i].elementClass[0] ){ |
| 1317 | 1145 | cgi_printf("/* %s */\n%s {\n%s\n}\n\n", |
| 1318 | 1146 | cssDefaultList[i].comment, |
| 1319 | 1147 | cssDefaultList[i].elementClass, |
| 1320 | - cssDefaultList[i].value | |
| 1321 | - ); | |
| 1322 | - }else{ | |
| 1323 | - cgi_printf("%s", | |
| 1324 | 1148 | cssDefaultList[i].value |
| 1325 | 1149 | ); |
| 1326 | 1150 | } |
| 1327 | 1151 | } |
| 1328 | 1152 | } |
| @@ -1333,11 +1157,11 @@ | ||
| 1333 | 1157 | void page_style_css(void){ |
| 1334 | 1158 | Blob css; |
| 1335 | 1159 | int i; |
| 1336 | 1160 | |
| 1337 | 1161 | cgi_set_content_type("text/css"); |
| 1338 | - blob_init(&css, db_get("css",(char*)zDefaultCSS), -1); | |
| 1162 | + blob_init(&css, db_get("css",(char*)builtin_text("skins/default/css.txt")), -1); | |
| 1339 | 1163 | |
| 1340 | 1164 | /* add special missing definitions */ |
| 1341 | 1165 | for(i=1; cssDefaultList[i].elementClass; i++){ |
| 1342 | 1166 | if( strstr(blob_str(&css), cssDefaultList[i].elementClass)==0 ){ |
| 1343 | 1167 | blob_appendf(&css, "/* %s */\n%s {\n%s}\n", |
| 1344 | 1168 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -46,10 +46,15 @@ | |
| 46 | /* |
| 47 | ** remember, if a sidebox was used |
| 48 | */ |
| 49 | static int sideboxUsed = 0; |
| 50 | |
| 51 | |
| 52 | /* |
| 53 | ** List of hyperlinks and forms that need to be resolved by javascript in |
| 54 | ** the footer. |
| 55 | */ |
| @@ -284,11 +289,12 @@ | |
| 284 | ** Draw the header. |
| 285 | */ |
| 286 | void style_header(const char *zTitleFormat, ...){ |
| 287 | va_list ap; |
| 288 | char *zTitle; |
| 289 | const char *zHeader = db_get("header", (char*)zDefaultHeader); |
| 290 | login_check_credentials(); |
| 291 | |
| 292 | va_start(ap, zTitleFormat); |
| 293 | zTitle = vmprintf(zTitleFormat, ap); |
| 294 | va_end(ap); |
| @@ -343,34 +349,64 @@ | |
| 343 | @ var e = document.getElementById(x); |
| 344 | @ if(!e) throw new Error("Expecting element with ID "+x); |
| 345 | @ else return e;} |
| 346 | @ </script> |
| 347 | } |
| 348 | |
| 349 | /* |
| 350 | ** Append ad unit text if appropriate. |
| 351 | */ |
| 352 | static void style_ad_unit(void){ |
| 353 | const char *zAd; |
| 354 | if( g.perm.Admin && db_get_boolean("adunit-omit-if-admin",0) ){ |
| 355 | return; |
| 356 | } |
| 357 | if( !login_is_nobody() |
| 358 | && fossil_strcmp(g.zLogin,"anonymous")!=0 |
| 359 | && db_get_boolean("adunit-omit-if-user",0) |
| 360 | ){ |
| 361 | return; |
| 362 | } |
| 363 | zAd = db_get("adunit", 0); |
| 364 | if( zAd ) cgi_append_content(zAd, -1); |
| 365 | } |
| 366 | |
| 367 | /* |
| 368 | ** Draw the footer at the bottom of the page. |
| 369 | */ |
| 370 | void style_footer(void){ |
| 371 | const char *zFooter; |
| 372 | |
| 373 | if( !headerHasBeenGenerated ) return; |
| 374 | |
| 375 | /* Go back and put the submenu at the top of the page. We delay the |
| 376 | ** creation of the submenu until the end so that we can add elements |
| @@ -389,12 +425,25 @@ | |
| 389 | @ <a class="label" href="%h(p->zLink)">%h(p->zLabel)</a> |
| 390 | } |
| 391 | } |
| 392 | @ </div> |
| 393 | } |
| 394 | style_ad_unit(); |
| 395 | @ <div class="content"> |
| 396 | cgi_destination(CGI_BODY); |
| 397 | |
| 398 | if( sideboxUsed ){ |
| 399 | /* Put the footer at the bottom of the page. |
| 400 | ** the additional clear/both is needed to extend the content |
| @@ -406,11 +455,12 @@ | |
| 406 | |
| 407 | /* Set the href= field on hyperlinks. Do this before the footer since |
| 408 | ** the footer will be generating </html> */ |
| 409 | style_resolve_href(); |
| 410 | |
| 411 | zFooter = db_get("footer", (char*)zDefaultFooter); |
| 412 | if( g.thTrace ) Th_Trace("BEGIN_FOOTER<br />\n", -1); |
| 413 | Th_Render(zFooter); |
| 414 | if( g.thTrace ) Th_Trace("END_FOOTER<br />\n", -1); |
| 415 | |
| 416 | /* Render trace log if TH1 tracing is enabled. */ |
| @@ -436,230 +486,10 @@ | |
| 436 | */ |
| 437 | void style_sidebox_end(void){ |
| 438 | @ </div> |
| 439 | } |
| 440 | |
| 441 | /* @-comment: // */ |
| 442 | /* |
| 443 | ** The default page header. |
| 444 | */ |
| 445 | const char zDefaultHeader[] = |
| 446 | @ <html> |
| 447 | @ <head> |
| 448 | @ <base href="$baseurl/$current_page" /> |
| 449 | @ <title>$<project_name>: $<title></title> |
| 450 | @ <link rel="alternate" type="application/rss+xml" title="RSS Feed" |
| 451 | @ href="$home/timeline.rss" /> |
| 452 | @ <link rel="stylesheet" href="$stylesheet_url" type="text/css" |
| 453 | @ media="screen" /> |
| 454 | @ </head> |
| 455 | @ <body> |
| 456 | @ <div class="header"> |
| 457 | @ <div class="logo"> |
| 458 | @ <img src="$logo_image_url" alt="logo" /> |
| 459 | @ </div> |
| 460 | @ <div class="title"><small>$<project_name></small><br />$<title></div> |
| 461 | @ <div class="status"><th1> |
| 462 | @ if {[info exists login]} { |
| 463 | @ puts "Logged in as $login" |
| 464 | @ } else { |
| 465 | @ puts "Not logged in" |
| 466 | @ } |
| 467 | @ </th1></div> |
| 468 | @ </div> |
| 469 | @ <div class="mainmenu"> |
| 470 | @ <th1> |
| 471 | @ html "<a href='$home$index_page'>Home</a>\n" |
| 472 | @ if {[anycap jor]} { |
| 473 | @ html "<a href='$home/timeline'>Timeline</a>\n" |
| 474 | @ } |
| 475 | @ if {[hascap oh]} { |
| 476 | @ html "<a href='$home/tree?ci=tip'>Files</a>\n" |
| 477 | @ } |
| 478 | @ if {[hascap o]} { |
| 479 | @ html "<a href='$home/brlist'>Branches</a>\n" |
| 480 | @ html "<a href='$home/taglist'>Tags</a>\n" |
| 481 | @ } |
| 482 | @ if {[hascap r]} { |
| 483 | @ html "<a href='$home/reportlist'>Tickets</a>\n" |
| 484 | @ } |
| 485 | @ if {[hascap j]} { |
| 486 | @ html "<a href='$home/wiki'>Wiki</a>\n" |
| 487 | @ } |
| 488 | @ if {[hascap s]} { |
| 489 | @ html "<a href='$home/setup'>Admin</a>\n" |
| 490 | @ } elseif {[hascap a]} { |
| 491 | @ html "<a href='$home/setup_ulist'>Users</a>\n" |
| 492 | @ } |
| 493 | @ if {[info exists login]} { |
| 494 | @ html "<a href='$home/login'>Logout</a>\n" |
| 495 | @ } else { |
| 496 | @ html "<a href='$home/login'>Login</a>\n" |
| 497 | @ } |
| 498 | @ </th1></div> |
| 499 | ; |
| 500 | |
| 501 | /* |
| 502 | ** The default page footer |
| 503 | */ |
| 504 | const char zDefaultFooter[] = |
| 505 | @ <div class="footer"> |
| 506 | @ This page was generated in about |
| 507 | @ <th1>puts [expr {([utime]+[stime]+1000)/1000*0.001}]</th1>s by |
| 508 | @ Fossil version $manifest_version $manifest_date |
| 509 | @ </div> |
| 510 | @ </body></html> |
| 511 | ; |
| 512 | |
| 513 | /* |
| 514 | ** The default Cascading Style Sheet. |
| 515 | ** It's assembled by different strings for each class. |
| 516 | ** The default css contains all definitions. |
| 517 | ** The style sheet, send to the client only contains the ones, |
| 518 | ** not defined in the user defined css. |
| 519 | */ |
| 520 | const char zDefaultCSS[] = |
| 521 | @ /* General settings for the entire page */ |
| 522 | @ body { |
| 523 | @ margin: 0ex 1ex; |
| 524 | @ padding: 0px; |
| 525 | @ background-color: white; |
| 526 | @ font-family: sans-serif; |
| 527 | @ } |
| 528 | @ |
| 529 | @ /* The project logo in the upper left-hand corner of each page */ |
| 530 | @ div.logo { |
| 531 | @ display: table-cell; |
| 532 | @ text-align: center; |
| 533 | @ vertical-align: bottom; |
| 534 | @ font-weight: bold; |
| 535 | @ color: #558195; |
| 536 | @ min-width: 200px; |
| 537 | @ white-space: nowrap; |
| 538 | @ } |
| 539 | @ |
| 540 | @ /* The page title centered at the top of each page */ |
| 541 | @ div.title { |
| 542 | @ display: table-cell; |
| 543 | @ font-size: 2em; |
| 544 | @ font-weight: bold; |
| 545 | @ text-align: center; |
| 546 | @ padding: 0 0 0 1em; |
| 547 | @ color: #558195; |
| 548 | @ vertical-align: bottom; |
| 549 | @ width: 100%; |
| 550 | @ } |
| 551 | @ |
| 552 | @ /* The login status message in the top right-hand corner */ |
| 553 | @ div.status { |
| 554 | @ display: table-cell; |
| 555 | @ text-align: right; |
| 556 | @ vertical-align: bottom; |
| 557 | @ color: #558195; |
| 558 | @ font-size: 0.8em; |
| 559 | @ font-weight: bold; |
| 560 | @ min-width: 200px; |
| 561 | @ white-space: nowrap; |
| 562 | @ } |
| 563 | @ |
| 564 | @ /* The header across the top of the page */ |
| 565 | @ div.header { |
| 566 | @ display: table; |
| 567 | @ width: 100%; |
| 568 | @ } |
| 569 | @ |
| 570 | @ /* The main menu bar that appears at the top of the page beneath |
| 571 | @ ** the header */ |
| 572 | @ div.mainmenu { |
| 573 | @ padding: 5px 10px 5px 10px; |
| 574 | @ font-size: 0.9em; |
| 575 | @ font-weight: bold; |
| 576 | @ text-align: center; |
| 577 | @ letter-spacing: 1px; |
| 578 | @ background-color: #558195; |
| 579 | @ border-top-left-radius: 8px; |
| 580 | @ border-top-right-radius: 8px; |
| 581 | @ color: white; |
| 582 | @ } |
| 583 | @ |
| 584 | @ /* The submenu bar that *sometimes* appears below the main menu */ |
| 585 | @ div.submenu, div.sectionmenu { |
| 586 | @ padding: 3px 10px 3px 0px; |
| 587 | @ font-size: 0.9em; |
| 588 | @ text-align: center; |
| 589 | @ background-color: #456878; |
| 590 | @ color: white; |
| 591 | @ } |
| 592 | @ div.mainmenu a, div.mainmenu a:visited, div.submenu a, div.submenu a:visited, |
| 593 | @ div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited { |
| 594 | @ padding: 3px 10px 3px 10px; |
| 595 | @ color: white; |
| 596 | @ text-decoration: none; |
| 597 | @ } |
| 598 | @ div.mainmenu a:hover, div.submenu a:hover, div.sectionmenu>a.button:hover { |
| 599 | @ color: #558195; |
| 600 | @ background-color: white; |
| 601 | @ } |
| 602 | @ |
| 603 | @ /* All page content from the bottom of the menu or submenu down to |
| 604 | @ ** the footer */ |
| 605 | @ div.content { |
| 606 | @ padding: 0ex 1ex 1ex 1ex; |
| 607 | @ border: solid #aaa; |
| 608 | @ border-width: 1px; |
| 609 | @ } |
| 610 | @ |
| 611 | @ /* Some pages have section dividers */ |
| 612 | @ div.section { |
| 613 | @ margin-bottom: 0px; |
| 614 | @ margin-top: 1em; |
| 615 | @ padding: 1px 1px 1px 1px; |
| 616 | @ font-size: 1.2em; |
| 617 | @ font-weight: bold; |
| 618 | @ background-color: #558195; |
| 619 | @ color: white; |
| 620 | @ white-space: nowrap; |
| 621 | @ } |
| 622 | @ |
| 623 | @ /* The "Date" that occurs on the left hand side of timelines */ |
| 624 | @ div.divider { |
| 625 | @ background: #a1c4d4; |
| 626 | @ border: 2px #558195 solid; |
| 627 | @ font-size: 1em; font-weight: normal; |
| 628 | @ padding: .25em; |
| 629 | @ margin: .2em 0 .2em 0; |
| 630 | @ float: left; |
| 631 | @ clear: left; |
| 632 | @ white-space: nowrap; |
| 633 | @ } |
| 634 | @ |
| 635 | @ /* The footer at the very bottom of the page */ |
| 636 | @ div.footer { |
| 637 | @ clear: both; |
| 638 | @ font-size: 0.8em; |
| 639 | @ padding: 5px 10px 5px 10px; |
| 640 | @ text-align: right; |
| 641 | @ background-color: #558195; |
| 642 | @ border-bottom-left-radius: 8px; |
| 643 | @ border-bottom-right-radius: 8px; |
| 644 | @ color: white; |
| 645 | @ } |
| 646 | @ |
| 647 | @ /* Hyperlink colors in the footer */ |
| 648 | @ div.footer a { color: white; } |
| 649 | @ div.footer a:link { color: white; } |
| 650 | @ div.footer a:visited { color: white; } |
| 651 | @ div.footer a:hover { background-color: white; color: #558195; } |
| 652 | @ |
| 653 | @ /* verbatim blocks */ |
| 654 | @ pre.verbatim { |
| 655 | @ background-color: #f5f5f5; |
| 656 | @ padding: 0.5em; |
| 657 | @ white-space: pre-wrap; |
| 658 | @} |
| 659 | ; |
| 660 | |
| 661 | |
| 662 | /* The following table contains bits of default CSS that must |
| 663 | ** be included if they are not found in the application-defined |
| 664 | ** CSS. |
| 665 | */ |
| @@ -666,14 +496,10 @@ | |
| 666 | const struct strctCssDefaults { |
| 667 | const char *elementClass; /* Name of element needed */ |
| 668 | const char *comment; /* Comment text */ |
| 669 | const char *value; /* CSS text */ |
| 670 | } cssDefaultList[] = { |
| 671 | { "", |
| 672 | "", |
| 673 | zDefaultCSS |
| 674 | }, |
| 675 | { "div.sidebox", |
| 676 | "The nomenclature sidebox for branches,..", |
| 677 | @ float: right; |
| 678 | @ background-color: white; |
| 679 | @ border-width: medium; |
| @@ -1279,10 +1105,11 @@ | |
| 1279 | @ text-align: left; |
| 1280 | @ padding: 0px 1em 0.5ex 0px; |
| 1281 | }, |
| 1282 | { ".brlist table td", "Branch list table headers", |
| 1283 | @ padding: 0px 2em 0px 0px; |
| 1284 | }, |
| 1285 | { "th.sort:after", |
| 1286 | "General styles for sortable column marker", |
| 1287 | @ margin-left: .4em; |
| 1288 | @ cursor: pointer; |
| @@ -1310,19 +1137,16 @@ | |
| 1310 | ** Append all of the default CSS to the CGI output. |
| 1311 | */ |
| 1312 | void cgi_append_default_css(void) { |
| 1313 | int i; |
| 1314 | |
| 1315 | for( i=0; cssDefaultList[i].elementClass; i++ ){ |
| 1316 | if( cssDefaultList[i].elementClass[0] ){ |
| 1317 | cgi_printf("/* %s */\n%s {\n%s\n}\n\n", |
| 1318 | cssDefaultList[i].comment, |
| 1319 | cssDefaultList[i].elementClass, |
| 1320 | cssDefaultList[i].value |
| 1321 | ); |
| 1322 | }else{ |
| 1323 | cgi_printf("%s", |
| 1324 | cssDefaultList[i].value |
| 1325 | ); |
| 1326 | } |
| 1327 | } |
| 1328 | } |
| @@ -1333,11 +1157,11 @@ | |
| 1333 | void page_style_css(void){ |
| 1334 | Blob css; |
| 1335 | int i; |
| 1336 | |
| 1337 | cgi_set_content_type("text/css"); |
| 1338 | blob_init(&css, db_get("css",(char*)zDefaultCSS), -1); |
| 1339 | |
| 1340 | /* add special missing definitions */ |
| 1341 | for(i=1; cssDefaultList[i].elementClass; i++){ |
| 1342 | if( strstr(blob_str(&css), cssDefaultList[i].elementClass)==0 ){ |
| 1343 | blob_appendf(&css, "/* %s */\n%s {\n%s}\n", |
| 1344 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -46,10 +46,15 @@ | |
| 46 | /* |
| 47 | ** remember, if a sidebox was used |
| 48 | */ |
| 49 | static int sideboxUsed = 0; |
| 50 | |
| 51 | /* |
| 52 | ** Ad-unit styles. |
| 53 | */ |
| 54 | static unsigned adUnitFlags = 0; |
| 55 | |
| 56 | |
| 57 | /* |
| 58 | ** List of hyperlinks and forms that need to be resolved by javascript in |
| 59 | ** the footer. |
| 60 | */ |
| @@ -284,11 +289,12 @@ | |
| 289 | ** Draw the header. |
| 290 | */ |
| 291 | void style_header(const char *zTitleFormat, ...){ |
| 292 | va_list ap; |
| 293 | char *zTitle; |
| 294 | const char *zHeader = db_get("header", 0); |
| 295 | if( zHeader==0 ) zHeader = builtin_text("skins/default/header.txt"); |
| 296 | login_check_credentials(); |
| 297 | |
| 298 | va_start(ap, zTitleFormat); |
| 299 | zTitle = vmprintf(zTitleFormat, ap); |
| 300 | va_end(ap); |
| @@ -343,34 +349,64 @@ | |
| 349 | @ var e = document.getElementById(x); |
| 350 | @ if(!e) throw new Error("Expecting element with ID "+x); |
| 351 | @ else return e;} |
| 352 | @ </script> |
| 353 | } |
| 354 | |
| 355 | #if INTERFACE |
| 356 | /* Allowed parameters for style_adunit() */ |
| 357 | #define ADUNIT_OFF 0x0001 /* Do not allow ads on this page */ |
| 358 | #define ADUNIT_RIGHT_OK 0x0002 /* Right-side vertical ads ok here */ |
| 359 | #endif |
| 360 | |
| 361 | /* |
| 362 | ** Various page implementations can invoke this interface to let the |
| 363 | ** style manager know what kinds of ads are appropriate for this page. |
| 364 | */ |
| 365 | void style_adunit_config(unsigned int mFlags){ |
| 366 | adUnitFlags = mFlags; |
| 367 | } |
| 368 | |
| 369 | /* |
| 370 | ** Return the text of an ad-unit, if one should be rendered. Return |
| 371 | ** NULL if no ad-unit is desired. |
| 372 | ** |
| 373 | ** The *pAdFlag value might be set to ADUNIT_RIGHT_OK if this is |
| 374 | ** a right-hand vertical ad. |
| 375 | */ |
| 376 | static const char *style_adunit_text(unsigned int *pAdFlag){ |
| 377 | const char *zAd = 0; |
| 378 | *pAdFlag = 0; |
| 379 | if( adUnitFlags & ADUNIT_OFF ) return 0; /* Disallow ads on this page */ |
| 380 | if( g.perm.Admin && db_get_boolean("adunit-omit-if-admin",0) ){ |
| 381 | return 0; |
| 382 | } |
| 383 | if( !login_is_nobody() |
| 384 | && fossil_strcmp(g.zLogin,"anonymous")!=0 |
| 385 | && db_get_boolean("adunit-omit-if-user",0) |
| 386 | ){ |
| 387 | return 0; |
| 388 | } |
| 389 | if( (adUnitFlags & ADUNIT_RIGHT_OK)!=0 |
| 390 | && !fossil_all_whitespace(zAd = db_get("adunit-right", 0)) |
| 391 | && !cgi_body_contains("<table") |
| 392 | ){ |
| 393 | *pAdFlag = ADUNIT_RIGHT_OK; |
| 394 | return zAd; |
| 395 | }else if( !fossil_all_whitespace(zAd = db_get("adunit",0)) ){ |
| 396 | return zAd; |
| 397 | } |
| 398 | return 0; |
| 399 | } |
| 400 | |
| 401 | /* |
| 402 | ** Draw the footer at the bottom of the page. |
| 403 | */ |
| 404 | void style_footer(void){ |
| 405 | const char *zFooter; |
| 406 | const char *zAd = 0; |
| 407 | unsigned int mAdFlags = 0; |
| 408 | |
| 409 | if( !headerHasBeenGenerated ) return; |
| 410 | |
| 411 | /* Go back and put the submenu at the top of the page. We delay the |
| 412 | ** creation of the submenu until the end so that we can add elements |
| @@ -389,12 +425,25 @@ | |
| 425 | @ <a class="label" href="%h(p->zLink)">%h(p->zLabel)</a> |
| 426 | } |
| 427 | } |
| 428 | @ </div> |
| 429 | } |
| 430 | |
| 431 | zAd = style_adunit_text(&mAdFlags); |
| 432 | if( (mAdFlags & ADUNIT_RIGHT_OK)!=0 ){ |
| 433 | @ <div class="content adunit_right_container"> |
| 434 | @ <div class="adunit_right"> |
| 435 | cgi_append_content(zAd, -1); |
| 436 | @ </div> |
| 437 | }else{ |
| 438 | if( zAd ){ |
| 439 | @ <div class="adunit_banner"> |
| 440 | cgi_append_content(zAd, -1); |
| 441 | @ </div> |
| 442 | } |
| 443 | @ <div class="content"> |
| 444 | } |
| 445 | cgi_destination(CGI_BODY); |
| 446 | |
| 447 | if( sideboxUsed ){ |
| 448 | /* Put the footer at the bottom of the page. |
| 449 | ** the additional clear/both is needed to extend the content |
| @@ -406,11 +455,12 @@ | |
| 455 | |
| 456 | /* Set the href= field on hyperlinks. Do this before the footer since |
| 457 | ** the footer will be generating </html> */ |
| 458 | style_resolve_href(); |
| 459 | |
| 460 | zFooter = db_get("footer", 0); |
| 461 | if( zFooter==0 ) zFooter = builtin_text("skins/default/footer.txt"); |
| 462 | if( g.thTrace ) Th_Trace("BEGIN_FOOTER<br />\n", -1); |
| 463 | Th_Render(zFooter); |
| 464 | if( g.thTrace ) Th_Trace("END_FOOTER<br />\n", -1); |
| 465 | |
| 466 | /* Render trace log if TH1 tracing is enabled. */ |
| @@ -436,230 +486,10 @@ | |
| 486 | */ |
| 487 | void style_sidebox_end(void){ |
| 488 | @ </div> |
| 489 | } |
| 490 | |
| 491 | |
| 492 | /* The following table contains bits of default CSS that must |
| 493 | ** be included if they are not found in the application-defined |
| 494 | ** CSS. |
| 495 | */ |
| @@ -666,14 +496,10 @@ | |
| 496 | const struct strctCssDefaults { |
| 497 | const char *elementClass; /* Name of element needed */ |
| 498 | const char *comment; /* Comment text */ |
| 499 | const char *value; /* CSS text */ |
| 500 | } cssDefaultList[] = { |
| 501 | { "div.sidebox", |
| 502 | "The nomenclature sidebox for branches,..", |
| 503 | @ float: right; |
| 504 | @ background-color: white; |
| 505 | @ border-width: medium; |
| @@ -1279,10 +1105,11 @@ | |
| 1105 | @ text-align: left; |
| 1106 | @ padding: 0px 1em 0.5ex 0px; |
| 1107 | }, |
| 1108 | { ".brlist table td", "Branch list table headers", |
| 1109 | @ padding: 0px 2em 0px 0px; |
| 1110 | @ white-space: nowrap; |
| 1111 | }, |
| 1112 | { "th.sort:after", |
| 1113 | "General styles for sortable column marker", |
| 1114 | @ margin-left: .4em; |
| 1115 | @ cursor: pointer; |
| @@ -1310,19 +1137,16 @@ | |
| 1137 | ** Append all of the default CSS to the CGI output. |
| 1138 | */ |
| 1139 | void cgi_append_default_css(void) { |
| 1140 | int i; |
| 1141 | |
| 1142 | cgi_printf("%s", builtin_text("skins/default/css.txt")); |
| 1143 | for( i=0; cssDefaultList[i].elementClass; i++ ){ |
| 1144 | if( cssDefaultList[i].elementClass[0] ){ |
| 1145 | cgi_printf("/* %s */\n%s {\n%s\n}\n\n", |
| 1146 | cssDefaultList[i].comment, |
| 1147 | cssDefaultList[i].elementClass, |
| 1148 | cssDefaultList[i].value |
| 1149 | ); |
| 1150 | } |
| 1151 | } |
| 1152 | } |
| @@ -1333,11 +1157,11 @@ | |
| 1157 | void page_style_css(void){ |
| 1158 | Blob css; |
| 1159 | int i; |
| 1160 | |
| 1161 | cgi_set_content_type("text/css"); |
| 1162 | blob_init(&css, db_get("css",(char*)builtin_text("skins/default/css.txt")), -1); |
| 1163 | |
| 1164 | /* add special missing definitions */ |
| 1165 | for(i=1; cssDefaultList[i].elementClass; i++){ |
| 1166 | if( strstr(blob_str(&css), cssDefaultList[i].elementClass)==0 ){ |
| 1167 | blob_appendf(&css, "/* %s */\n%s {\n%s}\n", |
| 1168 |
+2
-1
| --- src/tag.c | ||
| +++ src/tag.c | ||
| @@ -535,11 +535,11 @@ | ||
| 535 | 535 | tag_cmd_usage: |
| 536 | 536 | usage("add|cancel|find|list ..."); |
| 537 | 537 | } |
| 538 | 538 | |
| 539 | 539 | /* |
| 540 | -** WEBPAGE: /taglist | |
| 540 | +** WEBPAGE: taglist | |
| 541 | 541 | */ |
| 542 | 542 | void taglist_page(void){ |
| 543 | 543 | Stmt q; |
| 544 | 544 | |
| 545 | 545 | login_check_credentials(); |
| @@ -546,10 +546,11 @@ | ||
| 546 | 546 | if( !g.perm.Read ){ |
| 547 | 547 | login_needed(); |
| 548 | 548 | } |
| 549 | 549 | login_anonymous_available(); |
| 550 | 550 | style_header("Tags"); |
| 551 | + style_adunit_config(ADUNIT_RIGHT_OK); | |
| 551 | 552 | style_submenu_element("Timeline", "Timeline", "tagtimeline"); |
| 552 | 553 | @ <h2>Non-propagating tags:</h2> |
| 553 | 554 | db_prepare(&q, |
| 554 | 555 | "SELECT substr(tagname,5)" |
| 555 | 556 | " FROM tag" |
| 556 | 557 |
| --- src/tag.c | |
| +++ src/tag.c | |
| @@ -535,11 +535,11 @@ | |
| 535 | tag_cmd_usage: |
| 536 | usage("add|cancel|find|list ..."); |
| 537 | } |
| 538 | |
| 539 | /* |
| 540 | ** WEBPAGE: /taglist |
| 541 | */ |
| 542 | void taglist_page(void){ |
| 543 | Stmt q; |
| 544 | |
| 545 | login_check_credentials(); |
| @@ -546,10 +546,11 @@ | |
| 546 | if( !g.perm.Read ){ |
| 547 | login_needed(); |
| 548 | } |
| 549 | login_anonymous_available(); |
| 550 | style_header("Tags"); |
| 551 | style_submenu_element("Timeline", "Timeline", "tagtimeline"); |
| 552 | @ <h2>Non-propagating tags:</h2> |
| 553 | db_prepare(&q, |
| 554 | "SELECT substr(tagname,5)" |
| 555 | " FROM tag" |
| 556 |
| --- src/tag.c | |
| +++ src/tag.c | |
| @@ -535,11 +535,11 @@ | |
| 535 | tag_cmd_usage: |
| 536 | usage("add|cancel|find|list ..."); |
| 537 | } |
| 538 | |
| 539 | /* |
| 540 | ** WEBPAGE: taglist |
| 541 | */ |
| 542 | void taglist_page(void){ |
| 543 | Stmt q; |
| 544 | |
| 545 | login_check_credentials(); |
| @@ -546,10 +546,11 @@ | |
| 546 | if( !g.perm.Read ){ |
| 547 | login_needed(); |
| 548 | } |
| 549 | login_anonymous_available(); |
| 550 | style_header("Tags"); |
| 551 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 552 | style_submenu_element("Timeline", "Timeline", "tagtimeline"); |
| 553 | @ <h2>Non-propagating tags:</h2> |
| 554 | db_prepare(&q, |
| 555 | "SELECT substr(tagname,5)" |
| 556 | " FROM tag" |
| 557 |
M
src/th.h
+1
-1
| --- src/th.h | ||
| +++ src/th.h | ||
| @@ -1,8 +1,8 @@ | ||
| 1 | 1 | |
| 2 | 2 | /* This header file defines the external interface to the custom Scripting |
| 3 | -** Language (TH) interpreter. TH is very similar to TCL but is not an | |
| 3 | +** Language (TH) interpreter. TH is very similar to Tcl but is not an | |
| 4 | 4 | ** exact clone. |
| 5 | 5 | */ |
| 6 | 6 | |
| 7 | 7 | /* |
| 8 | 8 | ** Before creating an interpreter, the application must allocate and |
| 9 | 9 |
| --- src/th.h | |
| +++ src/th.h | |
| @@ -1,8 +1,8 @@ | |
| 1 | |
| 2 | /* This header file defines the external interface to the custom Scripting |
| 3 | ** Language (TH) interpreter. TH is very similar to TCL but is not an |
| 4 | ** exact clone. |
| 5 | */ |
| 6 | |
| 7 | /* |
| 8 | ** Before creating an interpreter, the application must allocate and |
| 9 |
| --- src/th.h | |
| +++ src/th.h | |
| @@ -1,8 +1,8 @@ | |
| 1 | |
| 2 | /* This header file defines the external interface to the custom Scripting |
| 3 | ** Language (TH) interpreter. TH is very similar to Tcl but is not an |
| 4 | ** exact clone. |
| 5 | */ |
| 6 | |
| 7 | /* |
| 8 | ** Before creating an interpreter, the application must allocate and |
| 9 |
+1
-1
| --- src/translate.c | ||
| +++ src/translate.c | ||
| @@ -42,11 +42,11 @@ | ||
| 42 | 42 | ** |
| 43 | 43 | ** Enhancement #2: |
| 44 | 44 | ** |
| 45 | 45 | ** Comments of the form: "/* @-comment: CC" cause CC to become a |
| 46 | 46 | ** comment character for the @-substitution. Typical values for CC are |
| 47 | -** "--" (for SQL text) or "#" (for TCL script) or "//" (for C++ code). | |
| 47 | +** "--" (for SQL text) or "#" (for Tcl script) or "//" (for C++ code). | |
| 48 | 48 | ** Lines of subsequent @-blocks that begin with CC are omitted from the |
| 49 | 49 | ** output. |
| 50 | 50 | ** |
| 51 | 51 | */ |
| 52 | 52 | #include <stdio.h> |
| 53 | 53 |
| --- src/translate.c | |
| +++ src/translate.c | |
| @@ -42,11 +42,11 @@ | |
| 42 | ** |
| 43 | ** Enhancement #2: |
| 44 | ** |
| 45 | ** Comments of the form: "/* @-comment: CC" cause CC to become a |
| 46 | ** comment character for the @-substitution. Typical values for CC are |
| 47 | ** "--" (for SQL text) or "#" (for TCL script) or "//" (for C++ code). |
| 48 | ** Lines of subsequent @-blocks that begin with CC are omitted from the |
| 49 | ** output. |
| 50 | ** |
| 51 | */ |
| 52 | #include <stdio.h> |
| 53 |
| --- src/translate.c | |
| +++ src/translate.c | |
| @@ -42,11 +42,11 @@ | |
| 42 | ** |
| 43 | ** Enhancement #2: |
| 44 | ** |
| 45 | ** Comments of the form: "/* @-comment: CC" cause CC to become a |
| 46 | ** comment character for the @-substitution. Typical values for CC are |
| 47 | ** "--" (for SQL text) or "#" (for Tcl script) or "//" (for C++ code). |
| 48 | ** Lines of subsequent @-blocks that begin with CC are omitted from the |
| 49 | ** output. |
| 50 | ** |
| 51 | */ |
| 52 | #include <stdio.h> |
| 53 |
+1
| --- src/url.c | ||
| +++ src/url.c | ||
| @@ -362,10 +362,11 @@ | ||
| 362 | 362 | ** feature. |
| 363 | 363 | */ |
| 364 | 364 | void url_proxy_options(void){ |
| 365 | 365 | zProxyOpt = find_option("proxy", 0, 1); |
| 366 | 366 | if( find_option("nosync",0,0) ) g.fNoSync = 1; |
| 367 | + if( find_option("ipv4",0,0) ) g.fIPv4 = 1; | |
| 367 | 368 | } |
| 368 | 369 | |
| 369 | 370 | /* |
| 370 | 371 | ** If the "proxy" setting is defined, then change the URL settings |
| 371 | 372 | ** (initialized by a prior call to url_parse()) so that the HTTP |
| 372 | 373 |
| --- src/url.c | |
| +++ src/url.c | |
| @@ -362,10 +362,11 @@ | |
| 362 | ** feature. |
| 363 | */ |
| 364 | void url_proxy_options(void){ |
| 365 | zProxyOpt = find_option("proxy", 0, 1); |
| 366 | if( find_option("nosync",0,0) ) g.fNoSync = 1; |
| 367 | } |
| 368 | |
| 369 | /* |
| 370 | ** If the "proxy" setting is defined, then change the URL settings |
| 371 | ** (initialized by a prior call to url_parse()) so that the HTTP |
| 372 |
| --- src/url.c | |
| +++ src/url.c | |
| @@ -362,10 +362,11 @@ | |
| 362 | ** feature. |
| 363 | */ |
| 364 | void url_proxy_options(void){ |
| 365 | zProxyOpt = find_option("proxy", 0, 1); |
| 366 | if( find_option("nosync",0,0) ) g.fNoSync = 1; |
| 367 | if( find_option("ipv4",0,0) ) g.fIPv4 = 1; |
| 368 | } |
| 369 | |
| 370 | /* |
| 371 | ** If the "proxy" setting is defined, then change the URL settings |
| 372 | ** (initialized by a prior call to url_parse()) so that the HTTP |
| 373 |
+5
-4
| --- src/user.c | ||
| +++ src/user.c | ||
| @@ -467,13 +467,13 @@ | ||
| 467 | 467 | style_submenu_element("Newer", "Newer entries", |
| 468 | 468 | "%s/access_log?o=%d&n=%d&y=%d", g.zTop, skip>=n ? skip-n : 0, |
| 469 | 469 | n, y); |
| 470 | 470 | } |
| 471 | 471 | rc = db_prepare_ignore_error(&q, "%s", blob_sql_text(&sql)); |
| 472 | - @ <center><table border="1" cellpadding="5"> | |
| 473 | - @ <tr><th width="33%%">Date</th><th width="34%%">User</th> | |
| 474 | - @ <th width="33%%">IP Address</th></tr> | |
| 472 | + @ <center><table border="1" cellpadding="5" id='logtable'> | |
| 473 | + @ <thead><tr><th width="33%%">Date</th><th width="34%%">User</th> | |
| 474 | + @ <th width="33%%">IP Address</th></tr></thead><tbody> | |
| 475 | 475 | while( rc==SQLITE_OK && db_step(&q)==SQLITE_ROW ){ |
| 476 | 476 | const char *zName = db_column_text(&q, 0); |
| 477 | 477 | const char *zIP = db_column_text(&q, 1); |
| 478 | 478 | const char *zDate = db_column_text(&q, 2); |
| 479 | 479 | int bSuccess = db_column_int(&q, 3); |
| @@ -492,11 +492,11 @@ | ||
| 492 | 492 | } |
| 493 | 493 | if( skip>0 || cnt>n ){ |
| 494 | 494 | style_submenu_element("All", "All entries", |
| 495 | 495 | "%s/access_log?n=10000000", g.zTop); |
| 496 | 496 | } |
| 497 | - @ </table></center> | |
| 497 | + @ </tbody></table></center> | |
| 498 | 498 | db_finalize(&q); |
| 499 | 499 | @ <hr> |
| 500 | 500 | @ <form method="post" action="%s(g.zTop)/access_log"> |
| 501 | 501 | @ <label><input type="checkbox" name="delold"> |
| 502 | 502 | @ Delete all but the most recent 200 entries</input></label> |
| @@ -515,7 +515,8 @@ | ||
| 515 | 515 | @ <form method="post" action="%s(g.zTop)/access_log"> |
| 516 | 516 | @ <label><input type="checkbox" name="delall"> |
| 517 | 517 | @ Delete all entries</input></label> |
| 518 | 518 | @ <input type="submit" name="delallbtn" value="Delete"></input> |
| 519 | 519 | @ </form> |
| 520 | + output_table_sorting_javascript("logtable", "Ttt", 1); | |
| 520 | 521 | style_footer(); |
| 521 | 522 | } |
| 522 | 523 |
| --- src/user.c | |
| +++ src/user.c | |
| @@ -467,13 +467,13 @@ | |
| 467 | style_submenu_element("Newer", "Newer entries", |
| 468 | "%s/access_log?o=%d&n=%d&y=%d", g.zTop, skip>=n ? skip-n : 0, |
| 469 | n, y); |
| 470 | } |
| 471 | rc = db_prepare_ignore_error(&q, "%s", blob_sql_text(&sql)); |
| 472 | @ <center><table border="1" cellpadding="5"> |
| 473 | @ <tr><th width="33%%">Date</th><th width="34%%">User</th> |
| 474 | @ <th width="33%%">IP Address</th></tr> |
| 475 | while( rc==SQLITE_OK && db_step(&q)==SQLITE_ROW ){ |
| 476 | const char *zName = db_column_text(&q, 0); |
| 477 | const char *zIP = db_column_text(&q, 1); |
| 478 | const char *zDate = db_column_text(&q, 2); |
| 479 | int bSuccess = db_column_int(&q, 3); |
| @@ -492,11 +492,11 @@ | |
| 492 | } |
| 493 | if( skip>0 || cnt>n ){ |
| 494 | style_submenu_element("All", "All entries", |
| 495 | "%s/access_log?n=10000000", g.zTop); |
| 496 | } |
| 497 | @ </table></center> |
| 498 | db_finalize(&q); |
| 499 | @ <hr> |
| 500 | @ <form method="post" action="%s(g.zTop)/access_log"> |
| 501 | @ <label><input type="checkbox" name="delold"> |
| 502 | @ Delete all but the most recent 200 entries</input></label> |
| @@ -515,7 +515,8 @@ | |
| 515 | @ <form method="post" action="%s(g.zTop)/access_log"> |
| 516 | @ <label><input type="checkbox" name="delall"> |
| 517 | @ Delete all entries</input></label> |
| 518 | @ <input type="submit" name="delallbtn" value="Delete"></input> |
| 519 | @ </form> |
| 520 | style_footer(); |
| 521 | } |
| 522 |
| --- src/user.c | |
| +++ src/user.c | |
| @@ -467,13 +467,13 @@ | |
| 467 | style_submenu_element("Newer", "Newer entries", |
| 468 | "%s/access_log?o=%d&n=%d&y=%d", g.zTop, skip>=n ? skip-n : 0, |
| 469 | n, y); |
| 470 | } |
| 471 | rc = db_prepare_ignore_error(&q, "%s", blob_sql_text(&sql)); |
| 472 | @ <center><table border="1" cellpadding="5" id='logtable'> |
| 473 | @ <thead><tr><th width="33%%">Date</th><th width="34%%">User</th> |
| 474 | @ <th width="33%%">IP Address</th></tr></thead><tbody> |
| 475 | while( rc==SQLITE_OK && db_step(&q)==SQLITE_ROW ){ |
| 476 | const char *zName = db_column_text(&q, 0); |
| 477 | const char *zIP = db_column_text(&q, 1); |
| 478 | const char *zDate = db_column_text(&q, 2); |
| 479 | int bSuccess = db_column_int(&q, 3); |
| @@ -492,11 +492,11 @@ | |
| 492 | } |
| 493 | if( skip>0 || cnt>n ){ |
| 494 | style_submenu_element("All", "All entries", |
| 495 | "%s/access_log?n=10000000", g.zTop); |
| 496 | } |
| 497 | @ </tbody></table></center> |
| 498 | db_finalize(&q); |
| 499 | @ <hr> |
| 500 | @ <form method="post" action="%s(g.zTop)/access_log"> |
| 501 | @ <label><input type="checkbox" name="delold"> |
| 502 | @ Delete all but the most recent 200 entries</input></label> |
| @@ -515,7 +515,8 @@ | |
| 515 | @ <form method="post" action="%s(g.zTop)/access_log"> |
| 516 | @ <label><input type="checkbox" name="delall"> |
| 517 | @ Delete all entries</input></label> |
| 518 | @ <input type="submit" name="delallbtn" value="Delete"></input> |
| 519 | @ </form> |
| 520 | output_table_sorting_javascript("logtable", "Ttt", 1); |
| 521 | style_footer(); |
| 522 | } |
| 523 |
+10
| --- src/util.c | ||
| +++ src/util.c | ||
| @@ -331,5 +331,15 @@ | ||
| 331 | 331 | int fossil_is_uuid(const char *zSym){ |
| 332 | 332 | return zSym |
| 333 | 333 | && (UUID_SIZE==strlen(zSym)) |
| 334 | 334 | && validate16(zSym, UUID_SIZE); |
| 335 | 335 | } |
| 336 | + | |
| 337 | +/* | |
| 338 | +** Return true if the input string is NULL or all whitespace. | |
| 339 | +** Return false if the input string contains text. | |
| 340 | +*/ | |
| 341 | +int fossil_all_whitespace(const char *z){ | |
| 342 | + if( z==0 ) return 1; | |
| 343 | + while( fossil_isspace(z[0]) ){ z++; } | |
| 344 | + return z[0]==0; | |
| 345 | +} | |
| 336 | 346 |
| --- src/util.c | |
| +++ src/util.c | |
| @@ -331,5 +331,15 @@ | |
| 331 | int fossil_is_uuid(const char *zSym){ |
| 332 | return zSym |
| 333 | && (UUID_SIZE==strlen(zSym)) |
| 334 | && validate16(zSym, UUID_SIZE); |
| 335 | } |
| 336 |
| --- src/util.c | |
| +++ src/util.c | |
| @@ -331,5 +331,15 @@ | |
| 331 | int fossil_is_uuid(const char *zSym){ |
| 332 | return zSym |
| 333 | && (UUID_SIZE==strlen(zSym)) |
| 334 | && validate16(zSym, UUID_SIZE); |
| 335 | } |
| 336 | |
| 337 | /* |
| 338 | ** Return true if the input string is NULL or all whitespace. |
| 339 | ** Return false if the input string contains text. |
| 340 | */ |
| 341 | int fossil_all_whitespace(const char *z){ |
| 342 | if( z==0 ) return 1; |
| 343 | while( fossil_isspace(z[0]) ){ z++; } |
| 344 | return z[0]==0; |
| 345 | } |
| 346 |
+2
-2
| --- src/xfer.c | ||
| +++ src/xfer.c | ||
| @@ -1966,12 +1966,12 @@ | ||
| 1966 | 1966 | g.clockSkewSeen = 1; |
| 1967 | 1967 | } |
| 1968 | 1968 | |
| 1969 | 1969 | fossil_force_newline(); |
| 1970 | 1970 | fossil_print( |
| 1971 | - "%s finished with %lld bytes sent, %lld bytes received\n", | |
| 1972 | - zOpType, nSent, nRcvd); | |
| 1971 | + "%s done, sent: %lld received: %lld ip: %s\n", | |
| 1972 | + zOpType, nSent, nRcvd, g.zIpAddr); | |
| 1973 | 1973 | transport_close(&g.url); |
| 1974 | 1974 | transport_global_shutdown(&g.url); |
| 1975 | 1975 | if( nErr && go==2 ){ |
| 1976 | 1976 | db_multi_exec("DROP TABLE onremote"); |
| 1977 | 1977 | manifest_crosslink_end(MC_PERMIT_HOOKS); |
| 1978 | 1978 |
| --- src/xfer.c | |
| +++ src/xfer.c | |
| @@ -1966,12 +1966,12 @@ | |
| 1966 | g.clockSkewSeen = 1; |
| 1967 | } |
| 1968 | |
| 1969 | fossil_force_newline(); |
| 1970 | fossil_print( |
| 1971 | "%s finished with %lld bytes sent, %lld bytes received\n", |
| 1972 | zOpType, nSent, nRcvd); |
| 1973 | transport_close(&g.url); |
| 1974 | transport_global_shutdown(&g.url); |
| 1975 | if( nErr && go==2 ){ |
| 1976 | db_multi_exec("DROP TABLE onremote"); |
| 1977 | manifest_crosslink_end(MC_PERMIT_HOOKS); |
| 1978 |
| --- src/xfer.c | |
| +++ src/xfer.c | |
| @@ -1966,12 +1966,12 @@ | |
| 1966 | g.clockSkewSeen = 1; |
| 1967 | } |
| 1968 | |
| 1969 | fossil_force_newline(); |
| 1970 | fossil_print( |
| 1971 | "%s done, sent: %lld received: %lld ip: %s\n", |
| 1972 | zOpType, nSent, nRcvd, g.zIpAddr); |
| 1973 | transport_close(&g.url); |
| 1974 | transport_global_shutdown(&g.url); |
| 1975 | if( nErr && go==2 ){ |
| 1976 | db_multi_exec("DROP TABLE onremote"); |
| 1977 | manifest_crosslink_end(MC_PERMIT_HOOKS); |
| 1978 |
+27
-2
| --- win/Makefile.mingw | ||
| +++ win/Makefile.mingw | ||
| @@ -146,12 +146,13 @@ | ||
| 146 | 146 | #### The directories where the OpenSSL include and library files are located. |
| 147 | 147 | # The recommended usage here is to use the Sysinternals junction tool |
| 148 | 148 | # to create a hard link between an "openssl-1.x" sub-directory of the |
| 149 | 149 | # Fossil source code directory and the target OpenSSL source directory. |
| 150 | 150 | # |
| 151 | -OPENSSLINCDIR = $(SRCDIR)/../compat/openssl-1.0.1k/include | |
| 152 | -OPENSSLLIBDIR = $(SRCDIR)/../compat/openssl-1.0.1k | |
| 151 | +OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.1l | |
| 152 | +OPENSSLINCDIR = $(OPENSSLDIR)/include | |
| 153 | +OPENSSLLIBDIR = $(OPENSSLDIR) | |
| 153 | 154 | |
| 154 | 155 | #### Either the directory where the Tcl library is installed or the Tcl |
| 155 | 156 | # source code directory resides (depending on the value of the macro |
| 156 | 157 | # FOSSIL_TCL_SOURCE). If this points to the Tcl install directory, |
| 157 | 158 | # this directory must have "include" and "lib" sub-directories. If |
| @@ -483,10 +484,34 @@ | ||
| 483 | 484 | $(SRCDIR)/xfer.c \ |
| 484 | 485 | $(SRCDIR)/xfersetup.c \ |
| 485 | 486 | $(SRCDIR)/zip.c |
| 486 | 487 | |
| 487 | 488 | EXTRA_FILES = \ |
| 489 | + $(SRCDIR)/../skins/black_and_white/css.txt \ | |
| 490 | + $(SRCDIR)/../skins/black_and_white/footer.txt \ | |
| 491 | + $(SRCDIR)/../skins/black_and_white/header.txt \ | |
| 492 | + $(SRCDIR)/../skins/default/css.txt \ | |
| 493 | + $(SRCDIR)/../skins/default/footer.txt \ | |
| 494 | + $(SRCDIR)/../skins/default/header.txt \ | |
| 495 | + $(SRCDIR)/../skins/eagle/css.txt \ | |
| 496 | + $(SRCDIR)/../skins/eagle/footer.txt \ | |
| 497 | + $(SRCDIR)/../skins/eagle/header.txt \ | |
| 498 | + $(SRCDIR)/../skins/enhanced1/css.txt \ | |
| 499 | + $(SRCDIR)/../skins/enhanced1/footer.txt \ | |
| 500 | + $(SRCDIR)/../skins/enhanced1/header.txt \ | |
| 501 | + $(SRCDIR)/../skins/etienne1/css.txt \ | |
| 502 | + $(SRCDIR)/../skins/etienne1/footer.txt \ | |
| 503 | + $(SRCDIR)/../skins/etienne1/header.txt \ | |
| 504 | + $(SRCDIR)/../skins/khaki/css.txt \ | |
| 505 | + $(SRCDIR)/../skins/khaki/footer.txt \ | |
| 506 | + $(SRCDIR)/../skins/khaki/header.txt \ | |
| 507 | + $(SRCDIR)/../skins/plain_gray/css.txt \ | |
| 508 | + $(SRCDIR)/../skins/plain_gray/footer.txt \ | |
| 509 | + $(SRCDIR)/../skins/plain_gray/header.txt \ | |
| 510 | + $(SRCDIR)/../skins/rounded1/css.txt \ | |
| 511 | + $(SRCDIR)/../skins/rounded1/footer.txt \ | |
| 512 | + $(SRCDIR)/../skins/rounded1/header.txt \ | |
| 488 | 513 | $(SRCDIR)/diff.tcl |
| 489 | 514 | |
| 490 | 515 | TRANS_SRC = \ |
| 491 | 516 | $(OBJDIR)/add_.c \ |
| 492 | 517 | $(OBJDIR)/allrepo_.c \ |
| 493 | 518 |
| --- win/Makefile.mingw | |
| +++ win/Makefile.mingw | |
| @@ -146,12 +146,13 @@ | |
| 146 | #### The directories where the OpenSSL include and library files are located. |
| 147 | # The recommended usage here is to use the Sysinternals junction tool |
| 148 | # to create a hard link between an "openssl-1.x" sub-directory of the |
| 149 | # Fossil source code directory and the target OpenSSL source directory. |
| 150 | # |
| 151 | OPENSSLINCDIR = $(SRCDIR)/../compat/openssl-1.0.1k/include |
| 152 | OPENSSLLIBDIR = $(SRCDIR)/../compat/openssl-1.0.1k |
| 153 | |
| 154 | #### Either the directory where the Tcl library is installed or the Tcl |
| 155 | # source code directory resides (depending on the value of the macro |
| 156 | # FOSSIL_TCL_SOURCE). If this points to the Tcl install directory, |
| 157 | # this directory must have "include" and "lib" sub-directories. If |
| @@ -483,10 +484,34 @@ | |
| 483 | $(SRCDIR)/xfer.c \ |
| 484 | $(SRCDIR)/xfersetup.c \ |
| 485 | $(SRCDIR)/zip.c |
| 486 | |
| 487 | EXTRA_FILES = \ |
| 488 | $(SRCDIR)/diff.tcl |
| 489 | |
| 490 | TRANS_SRC = \ |
| 491 | $(OBJDIR)/add_.c \ |
| 492 | $(OBJDIR)/allrepo_.c \ |
| 493 |
| --- win/Makefile.mingw | |
| +++ win/Makefile.mingw | |
| @@ -146,12 +146,13 @@ | |
| 146 | #### The directories where the OpenSSL include and library files are located. |
| 147 | # The recommended usage here is to use the Sysinternals junction tool |
| 148 | # to create a hard link between an "openssl-1.x" sub-directory of the |
| 149 | # Fossil source code directory and the target OpenSSL source directory. |
| 150 | # |
| 151 | OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.1l |
| 152 | OPENSSLINCDIR = $(OPENSSLDIR)/include |
| 153 | OPENSSLLIBDIR = $(OPENSSLDIR) |
| 154 | |
| 155 | #### Either the directory where the Tcl library is installed or the Tcl |
| 156 | # source code directory resides (depending on the value of the macro |
| 157 | # FOSSIL_TCL_SOURCE). If this points to the Tcl install directory, |
| 158 | # this directory must have "include" and "lib" sub-directories. If |
| @@ -483,10 +484,34 @@ | |
| 484 | $(SRCDIR)/xfer.c \ |
| 485 | $(SRCDIR)/xfersetup.c \ |
| 486 | $(SRCDIR)/zip.c |
| 487 | |
| 488 | EXTRA_FILES = \ |
| 489 | $(SRCDIR)/../skins/black_and_white/css.txt \ |
| 490 | $(SRCDIR)/../skins/black_and_white/footer.txt \ |
| 491 | $(SRCDIR)/../skins/black_and_white/header.txt \ |
| 492 | $(SRCDIR)/../skins/default/css.txt \ |
| 493 | $(SRCDIR)/../skins/default/footer.txt \ |
| 494 | $(SRCDIR)/../skins/default/header.txt \ |
| 495 | $(SRCDIR)/../skins/eagle/css.txt \ |
| 496 | $(SRCDIR)/../skins/eagle/footer.txt \ |
| 497 | $(SRCDIR)/../skins/eagle/header.txt \ |
| 498 | $(SRCDIR)/../skins/enhanced1/css.txt \ |
| 499 | $(SRCDIR)/../skins/enhanced1/footer.txt \ |
| 500 | $(SRCDIR)/../skins/enhanced1/header.txt \ |
| 501 | $(SRCDIR)/../skins/etienne1/css.txt \ |
| 502 | $(SRCDIR)/../skins/etienne1/footer.txt \ |
| 503 | $(SRCDIR)/../skins/etienne1/header.txt \ |
| 504 | $(SRCDIR)/../skins/khaki/css.txt \ |
| 505 | $(SRCDIR)/../skins/khaki/footer.txt \ |
| 506 | $(SRCDIR)/../skins/khaki/header.txt \ |
| 507 | $(SRCDIR)/../skins/plain_gray/css.txt \ |
| 508 | $(SRCDIR)/../skins/plain_gray/footer.txt \ |
| 509 | $(SRCDIR)/../skins/plain_gray/header.txt \ |
| 510 | $(SRCDIR)/../skins/rounded1/css.txt \ |
| 511 | $(SRCDIR)/../skins/rounded1/footer.txt \ |
| 512 | $(SRCDIR)/../skins/rounded1/header.txt \ |
| 513 | $(SRCDIR)/diff.tcl |
| 514 | |
| 515 | TRANS_SRC = \ |
| 516 | $(OBJDIR)/add_.c \ |
| 517 | $(OBJDIR)/allrepo_.c \ |
| 518 |
+24
-2
| --- win/Makefile.mingw.mistachkin | ||
| +++ win/Makefile.mingw.mistachkin | ||
| @@ -146,12 +146,13 @@ | ||
| 146 | 146 | #### The directories where the OpenSSL include and library files are located. |
| 147 | 147 | # The recommended usage here is to use the Sysinternals junction tool |
| 148 | 148 | # to create a hard link between an "openssl-1.x" sub-directory of the |
| 149 | 149 | # Fossil source code directory and the target OpenSSL source directory. |
| 150 | 150 | # |
| 151 | -OPENSSLINCDIR = $(SRCDIR)/../compat/openssl-1.0.1k/include | |
| 152 | -OPENSSLLIBDIR = $(SRCDIR)/../compat/openssl-1.0.1k | |
| 151 | +OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.1l | |
| 152 | +OPENSSLINCDIR = $(OPENSSLDIR)/include | |
| 153 | +OPENSSLLIBDIR = $(OPENSSLDIR) | |
| 153 | 154 | |
| 154 | 155 | #### Either the directory where the Tcl library is installed or the Tcl |
| 155 | 156 | # source code directory resides (depending on the value of the macro |
| 156 | 157 | # FOSSIL_TCL_SOURCE). If this points to the Tcl install directory, |
| 157 | 158 | # this directory must have "include" and "lib" sub-directories. If |
| @@ -483,10 +484,31 @@ | ||
| 483 | 484 | $(SRCDIR)/xfer.c \ |
| 484 | 485 | $(SRCDIR)/xfersetup.c \ |
| 485 | 486 | $(SRCDIR)/zip.c |
| 486 | 487 | |
| 487 | 488 | EXTRA_FILES = \ |
| 489 | + $(SRCDIR)/../skins/black_and_white/css.txt \ | |
| 490 | + $(SRCDIR)/../skins/black_and_white/footer.txt \ | |
| 491 | + $(SRCDIR)/../skins/black_and_white/header.txt \ | |
| 492 | + $(SRCDIR)/../skins/default/css.txt \ | |
| 493 | + $(SRCDIR)/../skins/default/footer.txt \ | |
| 494 | + $(SRCDIR)/../skins/default/header.txt \ | |
| 495 | + $(SRCDIR)/../skins/eagle/css.txt \ | |
| 496 | + $(SRCDIR)/../skins/eagle/footer.txt \ | |
| 497 | + $(SRCDIR)/../skins/eagle/header.txt \ | |
| 498 | + $(SRCDIR)/../skins/enhanced1/css.txt \ | |
| 499 | + $(SRCDIR)/../skins/enhanced1/footer.txt \ | |
| 500 | + $(SRCDIR)/../skins/enhanced1/header.txt \ | |
| 501 | + $(SRCDIR)/../skins/khaki/css.txt \ | |
| 502 | + $(SRCDIR)/../skins/khaki/footer.txt \ | |
| 503 | + $(SRCDIR)/../skins/khaki/header.txt \ | |
| 504 | + $(SRCDIR)/../skins/plain_gray/css.txt \ | |
| 505 | + $(SRCDIR)/../skins/plain_gray/footer.txt \ | |
| 506 | + $(SRCDIR)/../skins/plain_gray/header.txt \ | |
| 507 | + $(SRCDIR)/../skins/rounded1/css.txt \ | |
| 508 | + $(SRCDIR)/../skins/rounded1/footer.txt \ | |
| 509 | + $(SRCDIR)/../skins/rounded1/header.txt \ | |
| 488 | 510 | $(SRCDIR)/diff.tcl |
| 489 | 511 | |
| 490 | 512 | TRANS_SRC = \ |
| 491 | 513 | $(OBJDIR)/add_.c \ |
| 492 | 514 | $(OBJDIR)/allrepo_.c \ |
| 493 | 515 |
| --- win/Makefile.mingw.mistachkin | |
| +++ win/Makefile.mingw.mistachkin | |
| @@ -146,12 +146,13 @@ | |
| 146 | #### The directories where the OpenSSL include and library files are located. |
| 147 | # The recommended usage here is to use the Sysinternals junction tool |
| 148 | # to create a hard link between an "openssl-1.x" sub-directory of the |
| 149 | # Fossil source code directory and the target OpenSSL source directory. |
| 150 | # |
| 151 | OPENSSLINCDIR = $(SRCDIR)/../compat/openssl-1.0.1k/include |
| 152 | OPENSSLLIBDIR = $(SRCDIR)/../compat/openssl-1.0.1k |
| 153 | |
| 154 | #### Either the directory where the Tcl library is installed or the Tcl |
| 155 | # source code directory resides (depending on the value of the macro |
| 156 | # FOSSIL_TCL_SOURCE). If this points to the Tcl install directory, |
| 157 | # this directory must have "include" and "lib" sub-directories. If |
| @@ -483,10 +484,31 @@ | |
| 483 | $(SRCDIR)/xfer.c \ |
| 484 | $(SRCDIR)/xfersetup.c \ |
| 485 | $(SRCDIR)/zip.c |
| 486 | |
| 487 | EXTRA_FILES = \ |
| 488 | $(SRCDIR)/diff.tcl |
| 489 | |
| 490 | TRANS_SRC = \ |
| 491 | $(OBJDIR)/add_.c \ |
| 492 | $(OBJDIR)/allrepo_.c \ |
| 493 |
| --- win/Makefile.mingw.mistachkin | |
| +++ win/Makefile.mingw.mistachkin | |
| @@ -146,12 +146,13 @@ | |
| 146 | #### The directories where the OpenSSL include and library files are located. |
| 147 | # The recommended usage here is to use the Sysinternals junction tool |
| 148 | # to create a hard link between an "openssl-1.x" sub-directory of the |
| 149 | # Fossil source code directory and the target OpenSSL source directory. |
| 150 | # |
| 151 | OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.1l |
| 152 | OPENSSLINCDIR = $(OPENSSLDIR)/include |
| 153 | OPENSSLLIBDIR = $(OPENSSLDIR) |
| 154 | |
| 155 | #### Either the directory where the Tcl library is installed or the Tcl |
| 156 | # source code directory resides (depending on the value of the macro |
| 157 | # FOSSIL_TCL_SOURCE). If this points to the Tcl install directory, |
| 158 | # this directory must have "include" and "lib" sub-directories. If |
| @@ -483,10 +484,31 @@ | |
| 484 | $(SRCDIR)/xfer.c \ |
| 485 | $(SRCDIR)/xfersetup.c \ |
| 486 | $(SRCDIR)/zip.c |
| 487 | |
| 488 | EXTRA_FILES = \ |
| 489 | $(SRCDIR)/../skins/black_and_white/css.txt \ |
| 490 | $(SRCDIR)/../skins/black_and_white/footer.txt \ |
| 491 | $(SRCDIR)/../skins/black_and_white/header.txt \ |
| 492 | $(SRCDIR)/../skins/default/css.txt \ |
| 493 | $(SRCDIR)/../skins/default/footer.txt \ |
| 494 | $(SRCDIR)/../skins/default/header.txt \ |
| 495 | $(SRCDIR)/../skins/eagle/css.txt \ |
| 496 | $(SRCDIR)/../skins/eagle/footer.txt \ |
| 497 | $(SRCDIR)/../skins/eagle/header.txt \ |
| 498 | $(SRCDIR)/../skins/enhanced1/css.txt \ |
| 499 | $(SRCDIR)/../skins/enhanced1/footer.txt \ |
| 500 | $(SRCDIR)/../skins/enhanced1/header.txt \ |
| 501 | $(SRCDIR)/../skins/khaki/css.txt \ |
| 502 | $(SRCDIR)/../skins/khaki/footer.txt \ |
| 503 | $(SRCDIR)/../skins/khaki/header.txt \ |
| 504 | $(SRCDIR)/../skins/plain_gray/css.txt \ |
| 505 | $(SRCDIR)/../skins/plain_gray/footer.txt \ |
| 506 | $(SRCDIR)/../skins/plain_gray/header.txt \ |
| 507 | $(SRCDIR)/../skins/rounded1/css.txt \ |
| 508 | $(SRCDIR)/../skins/rounded1/footer.txt \ |
| 509 | $(SRCDIR)/../skins/rounded1/header.txt \ |
| 510 | $(SRCDIR)/diff.tcl |
| 511 | |
| 512 | TRANS_SRC = \ |
| 513 | $(OBJDIR)/add_.c \ |
| 514 | $(OBJDIR)/allrepo_.c \ |
| 515 |
+26
-2
| --- win/Makefile.msc | ||
| +++ win/Makefile.msc | ||
| @@ -55,11 +55,11 @@ | ||
| 55 | 55 | |
| 56 | 56 | # Uncomment to enable Tcl support |
| 57 | 57 | # FOSSIL_ENABLE_TCL = 1 |
| 58 | 58 | |
| 59 | 59 | !ifdef FOSSIL_ENABLE_SSL |
| 60 | -SSLDIR = $(B)\compat\openssl-1.0.1k | |
| 60 | +SSLDIR = $(B)\compat\openssl-1.0.1l | |
| 61 | 61 | SSLINCDIR = $(SSLDIR)\inc32 |
| 62 | 62 | SSLLIBDIR = $(SSLDIR)\out32 |
| 63 | 63 | SSLLFLAGS = /nologo /opt:ref /debug |
| 64 | 64 | SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib |
| 65 | 65 | !if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64" |
| @@ -322,11 +322,35 @@ | ||
| 322 | 322 | wysiwyg_.c \ |
| 323 | 323 | xfer_.c \ |
| 324 | 324 | xfersetup_.c \ |
| 325 | 325 | zip_.c |
| 326 | 326 | |
| 327 | -EXTRA_FILES = $(SRCDIR)\diff.tcl | |
| 327 | +EXTRA_FILES = $(SRCDIR)\../skins/black_and_white/css.txt \ | |
| 328 | + $(SRCDIR)\../skins/black_and_white/footer.txt \ | |
| 329 | + $(SRCDIR)\../skins/black_and_white/header.txt \ | |
| 330 | + $(SRCDIR)\../skins/default/css.txt \ | |
| 331 | + $(SRCDIR)\../skins/default/footer.txt \ | |
| 332 | + $(SRCDIR)\../skins/default/header.txt \ | |
| 333 | + $(SRCDIR)\../skins/eagle/css.txt \ | |
| 334 | + $(SRCDIR)\../skins/eagle/footer.txt \ | |
| 335 | + $(SRCDIR)\../skins/eagle/header.txt \ | |
| 336 | + $(SRCDIR)\../skins/enhanced1/css.txt \ | |
| 337 | + $(SRCDIR)\../skins/enhanced1/footer.txt \ | |
| 338 | + $(SRCDIR)\../skins/enhanced1/header.txt \ | |
| 339 | + $(SRCDIR)\../skins/etienne1/css.txt \ | |
| 340 | + $(SRCDIR)\../skins/etienne1/footer.txt \ | |
| 341 | + $(SRCDIR)\../skins/etienne1/header.txt \ | |
| 342 | + $(SRCDIR)\../skins/khaki/css.txt \ | |
| 343 | + $(SRCDIR)\../skins/khaki/footer.txt \ | |
| 344 | + $(SRCDIR)\../skins/khaki/header.txt \ | |
| 345 | + $(SRCDIR)\../skins/plain_gray/css.txt \ | |
| 346 | + $(SRCDIR)\../skins/plain_gray/footer.txt \ | |
| 347 | + $(SRCDIR)\../skins/plain_gray/header.txt \ | |
| 348 | + $(SRCDIR)\../skins/rounded1/css.txt \ | |
| 349 | + $(SRCDIR)\../skins/rounded1/footer.txt \ | |
| 350 | + $(SRCDIR)\../skins/rounded1/header.txt \ | |
| 351 | + $(SRCDIR)\diff.tcl | |
| 328 | 352 | |
| 329 | 353 | OBJ = $(OX)\add$O \ |
| 330 | 354 | $(OX)\allrepo$O \ |
| 331 | 355 | $(OX)\attach$O \ |
| 332 | 356 | $(OX)\bag$O \ |
| 333 | 357 |
| --- win/Makefile.msc | |
| +++ win/Makefile.msc | |
| @@ -55,11 +55,11 @@ | |
| 55 | |
| 56 | # Uncomment to enable Tcl support |
| 57 | # FOSSIL_ENABLE_TCL = 1 |
| 58 | |
| 59 | !ifdef FOSSIL_ENABLE_SSL |
| 60 | SSLDIR = $(B)\compat\openssl-1.0.1k |
| 61 | SSLINCDIR = $(SSLDIR)\inc32 |
| 62 | SSLLIBDIR = $(SSLDIR)\out32 |
| 63 | SSLLFLAGS = /nologo /opt:ref /debug |
| 64 | SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib |
| 65 | !if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64" |
| @@ -322,11 +322,35 @@ | |
| 322 | wysiwyg_.c \ |
| 323 | xfer_.c \ |
| 324 | xfersetup_.c \ |
| 325 | zip_.c |
| 326 | |
| 327 | EXTRA_FILES = $(SRCDIR)\diff.tcl |
| 328 | |
| 329 | OBJ = $(OX)\add$O \ |
| 330 | $(OX)\allrepo$O \ |
| 331 | $(OX)\attach$O \ |
| 332 | $(OX)\bag$O \ |
| 333 |
| --- win/Makefile.msc | |
| +++ win/Makefile.msc | |
| @@ -55,11 +55,11 @@ | |
| 55 | |
| 56 | # Uncomment to enable Tcl support |
| 57 | # FOSSIL_ENABLE_TCL = 1 |
| 58 | |
| 59 | !ifdef FOSSIL_ENABLE_SSL |
| 60 | SSLDIR = $(B)\compat\openssl-1.0.1l |
| 61 | SSLINCDIR = $(SSLDIR)\inc32 |
| 62 | SSLLIBDIR = $(SSLDIR)\out32 |
| 63 | SSLLFLAGS = /nologo /opt:ref /debug |
| 64 | SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib |
| 65 | !if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64" |
| @@ -322,11 +322,35 @@ | |
| 322 | wysiwyg_.c \ |
| 323 | xfer_.c \ |
| 324 | xfersetup_.c \ |
| 325 | zip_.c |
| 326 | |
| 327 | EXTRA_FILES = $(SRCDIR)\../skins/black_and_white/css.txt \ |
| 328 | $(SRCDIR)\../skins/black_and_white/footer.txt \ |
| 329 | $(SRCDIR)\../skins/black_and_white/header.txt \ |
| 330 | $(SRCDIR)\../skins/default/css.txt \ |
| 331 | $(SRCDIR)\../skins/default/footer.txt \ |
| 332 | $(SRCDIR)\../skins/default/header.txt \ |
| 333 | $(SRCDIR)\../skins/eagle/css.txt \ |
| 334 | $(SRCDIR)\../skins/eagle/footer.txt \ |
| 335 | $(SRCDIR)\../skins/eagle/header.txt \ |
| 336 | $(SRCDIR)\../skins/enhanced1/css.txt \ |
| 337 | $(SRCDIR)\../skins/enhanced1/footer.txt \ |
| 338 | $(SRCDIR)\../skins/enhanced1/header.txt \ |
| 339 | $(SRCDIR)\../skins/etienne1/css.txt \ |
| 340 | $(SRCDIR)\../skins/etienne1/footer.txt \ |
| 341 | $(SRCDIR)\../skins/etienne1/header.txt \ |
| 342 | $(SRCDIR)\../skins/khaki/css.txt \ |
| 343 | $(SRCDIR)\../skins/khaki/footer.txt \ |
| 344 | $(SRCDIR)\../skins/khaki/header.txt \ |
| 345 | $(SRCDIR)\../skins/plain_gray/css.txt \ |
| 346 | $(SRCDIR)\../skins/plain_gray/footer.txt \ |
| 347 | $(SRCDIR)\../skins/plain_gray/header.txt \ |
| 348 | $(SRCDIR)\../skins/rounded1/css.txt \ |
| 349 | $(SRCDIR)\../skins/rounded1/footer.txt \ |
| 350 | $(SRCDIR)\../skins/rounded1/header.txt \ |
| 351 | $(SRCDIR)\diff.tcl |
| 352 | |
| 353 | OBJ = $(OX)\add$O \ |
| 354 | $(OX)\allrepo$O \ |
| 355 | $(OX)\attach$O \ |
| 356 | $(OX)\bag$O \ |
| 357 |
+2
-2
| --- win/include/unistd.h | ||
| +++ win/include/unistd.h | ||
| @@ -1,11 +1,11 @@ | ||
| 1 | 1 | #ifndef _UNISTD_H |
| 2 | 2 | #define _UNISTD_H 1 |
| 3 | 3 | |
| 4 | -/* This file intended to serve as a drop-in replacement for | |
| 4 | +/* This file intended to serve as a drop-in replacement for | |
| 5 | 5 | * unistd.h on Windows |
| 6 | - * Please add functionality as neeeded | |
| 6 | + * Please add functionality as neeeded | |
| 7 | 7 | */ |
| 8 | 8 | |
| 9 | 9 | #include <stdlib.h> |
| 10 | 10 | #include <io.h> |
| 11 | 11 | #define srandom srand |
| 12 | 12 |
| --- win/include/unistd.h | |
| +++ win/include/unistd.h | |
| @@ -1,11 +1,11 @@ | |
| 1 | #ifndef _UNISTD_H |
| 2 | #define _UNISTD_H 1 |
| 3 | |
| 4 | /* This file intended to serve as a drop-in replacement for |
| 5 | * unistd.h on Windows |
| 6 | * Please add functionality as neeeded |
| 7 | */ |
| 8 | |
| 9 | #include <stdlib.h> |
| 10 | #include <io.h> |
| 11 | #define srandom srand |
| 12 |
| --- win/include/unistd.h | |
| +++ win/include/unistd.h | |
| @@ -1,11 +1,11 @@ | |
| 1 | #ifndef _UNISTD_H |
| 2 | #define _UNISTD_H 1 |
| 3 | |
| 4 | /* This file intended to serve as a drop-in replacement for |
| 5 | * unistd.h on Windows |
| 6 | * Please add functionality as neeeded |
| 7 | */ |
| 8 | |
| 9 | #include <stdlib.h> |
| 10 | #include <io.h> |
| 11 | #define srandom srand |
| 12 |
+1
-1
| --- www/build.wiki | ||
| +++ www/build.wiki | ||
| @@ -122,11 +122,11 @@ | ||
| 122 | 122 | the optional <a href="https://www.openssl.org/">OpenSSL</a> support, |
| 123 | 123 | first <a href="https://www.openssl.org/source/">download the official |
| 124 | 124 | source code for OpenSSL</a> and extract it to an appropriately named |
| 125 | 125 | "<b>openssl-X.Y.ZA</b>" subdirectory within the local |
| 126 | 126 | [/tree?ci=trunk&name=compat | compat] directory (e.g. |
| 127 | -"<b>compat/openssl-1.0.1k</b>"), then make sure that some recent | |
| 127 | +"<b>compat/openssl-1.0.1l</b>"), then make sure that some recent | |
| 128 | 128 | <a href="http://www.perl.org/">Perl</a> binaries are installed locally, |
| 129 | 129 | and finally run one of the following commands: |
| 130 | 130 | <blockquote><pre> |
| 131 | 131 | nmake /f Makefile.msc FOSSIL_ENABLE_SSL=1 FOSSIL_BUILD_SSL=1 PERLDIR=C:\full\path\to\Perl\bin |
| 132 | 132 | </pre></blockquote> |
| 133 | 133 |
| --- www/build.wiki | |
| +++ www/build.wiki | |
| @@ -122,11 +122,11 @@ | |
| 122 | the optional <a href="https://www.openssl.org/">OpenSSL</a> support, |
| 123 | first <a href="https://www.openssl.org/source/">download the official |
| 124 | source code for OpenSSL</a> and extract it to an appropriately named |
| 125 | "<b>openssl-X.Y.ZA</b>" subdirectory within the local |
| 126 | [/tree?ci=trunk&name=compat | compat] directory (e.g. |
| 127 | "<b>compat/openssl-1.0.1k</b>"), then make sure that some recent |
| 128 | <a href="http://www.perl.org/">Perl</a> binaries are installed locally, |
| 129 | and finally run one of the following commands: |
| 130 | <blockquote><pre> |
| 131 | nmake /f Makefile.msc FOSSIL_ENABLE_SSL=1 FOSSIL_BUILD_SSL=1 PERLDIR=C:\full\path\to\Perl\bin |
| 132 | </pre></blockquote> |
| 133 |
| --- www/build.wiki | |
| +++ www/build.wiki | |
| @@ -122,11 +122,11 @@ | |
| 122 | the optional <a href="https://www.openssl.org/">OpenSSL</a> support, |
| 123 | first <a href="https://www.openssl.org/source/">download the official |
| 124 | source code for OpenSSL</a> and extract it to an appropriately named |
| 125 | "<b>openssl-X.Y.ZA</b>" subdirectory within the local |
| 126 | [/tree?ci=trunk&name=compat | compat] directory (e.g. |
| 127 | "<b>compat/openssl-1.0.1l</b>"), then make sure that some recent |
| 128 | <a href="http://www.perl.org/">Perl</a> binaries are installed locally, |
| 129 | and finally run one of the following commands: |
| 130 | <blockquote><pre> |
| 131 | nmake /f Makefile.msc FOSSIL_ENABLE_SSL=1 FOSSIL_BUILD_SSL=1 PERLDIR=C:\full\path\to\Perl\bin |
| 132 | </pre></blockquote> |
| 133 |