Fossil SCM

Merge latest trunk

baruch 2015-01-25 09:54 svn-import merge
Commit befd44c747405c1abb9264a14fe796cc648ffb40
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
--- 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 @@
22
# Dockerfile for Fossil
33
###
44
FROM fedora:21
55
66
### 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
88
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
1111
1212
RUN curl "http://www.fossil-scm.org/index.html/tarball/fossil-src.tar.gz?name=fossil-src&uuid=${FOSSIL_INSTALL_VERSION}" | tar zx
1313
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;
1414
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
1515
1616
### 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
1818
1919
USER fossil
2020
2121
ENV HOME /opt/fossil
2222
2323
2424
ADDED skins/README.md
2525
ADDED skins/black_and_white/css.txt
2626
ADDED skins/black_and_white/footer.txt
2727
ADDED skins/black_and_white/header.txt
2828
ADDED skins/default/css.txt
2929
ADDED skins/default/footer.txt
3030
ADDED skins/default/header.txt
3131
ADDED skins/eagle/css.txt
3232
ADDED skins/eagle/footer.txt
3333
ADDED skins/eagle/header.txt
3434
ADDED skins/enhanced1/css.txt
3535
ADDED skins/enhanced1/footer.txt
3636
ADDED skins/enhanced1/header.txt
3737
ADDED skins/etienne1/README.md
3838
ADDED skins/etienne1/css.txt
3939
ADDED skins/etienne1/footer.txt
4040
ADDED skins/etienne1/header.txt
4141
ADDED skins/khaki/css.txt
4242
ADDED skins/khaki/footer.txt
4343
ADDED skins/khaki/header.txt
4444
ADDED skins/plain_gray/css.txt
4545
ADDED skins/plain_gray/footer.txt
4646
ADDED skins/plain_gray/header.txt
4747
ADDED skins/rounded1/css.txt
4848
ADDED skins/rounded1/footer.txt
4949
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
--- 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
--- 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 }
--- 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
--- 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&amp;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&amp;div>
23 </body></html>
--- 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
--- 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&amp;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&amp;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
--- 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 <
--- 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
--- 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 @@
9090
@ <li><p>
9191
@ Attachment %z(href("%R/ainfo/%s",zUuid))%S(zUuid)</a>
9292
if( moderation_pending(attachid) ){
9393
@ <span class="modpending">*** Awaiting Moderator Approval ***</span>
9494
}
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 />
9797
if( zComment ) while( fossil_isspace(zComment[0]) ) zComment++;
9898
if( zComment && zComment[0] ){
9999
@ %!w(zComment)<br />
100100
}
101101
if( zPage==0 && zTkt==0 ){
102102
--- 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 @@
341341
Stmt q;
342342
double rNow;
343343
login_check_credentials();
344344
if( !g.perm.Read ){ login_needed(); return; }
345345
style_header("Branches");
346
+ style_adunit_config(ADUNIT_RIGHT_OK);
346347
login_anonymous_available();
347348
348349
db_prepare(&q, brlistQuery/*works-like:""*/);
349350
rNow = db_double(0.0, "SELECT julianday('now')");
350351
@ <div class="brlist"><table id="branchlisttable">
@@ -366,11 +367,11 @@
366367
sqlite3_int64 iMtime = (sqlite3_int64)(rMtime*86400.0);
367368
if( zMergeTo && zMergeTo[0]==0 ) zMergeTo = 0;
368369
@ <tr>
369370
@ <td>%z(href("%R/timeline?n=100&r=%T",zBranch))%h(zBranch)</a></td>
370371
@ <td data-sortkey="%016llx(-iMtime)">%s(zAge)</td>
371
- @ <td data-sortkey="%08x(-nCkin)">%d(nCkin)</td>
372
+ @ <td>%d(nCkin)</td>
372373
fossil_free(zAge);
373374
@ <td>%s(isClosed?"closed":"")</td>
374375
if( zMergeTo ){
375376
@ <td>merged into
376377
@ %z(href("%R/timeline?f=%s",zLastCkin))%h(zMergeTo)</a></td>
@@ -379,11 +380,11 @@
379380
}
380381
@ </tr>
381382
}
382383
@ </tbody></table></div>
383384
db_finalize(&q);
384
- output_table_sorting_javascript("branchlisttable","tkktt",2);
385
+ output_table_sorting_javascript("branchlisttable","tkNtt",2);
385386
style_footer();
386387
}
387388
388389
/*
389390
** WEBPAGE: brlist
390391
--- 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
--- src/browse.c
+++ src/browse.c
@@ -133,10 +133,11 @@
133133
if( strcmp(PD("type",""),"tree")==0 ){ page_tree(); return; }
134134
login_check_credentials();
135135
if( !g.perm.Read ){ login_needed(); return; }
136136
while( nD>1 && zD[nD-2]=='/' ){ zD[(--nD)-1] = 0; }
137137
style_header("File List");
138
+ style_adunit_config(ADUNIT_RIGHT_OK);
138139
sqlite3_create_function(g.db, "pathelement", 2, SQLITE_UTF8, 0,
139140
pathelementFunc, 0, 0);
140141
url_initialize(&sURI, "dir");
141142
142143
/* If the name= parameter is an empty string, make it a NULL pointer */
@@ -555,10 +556,11 @@
555556
style_header("Folder Hierarchy");
556557
}else{
557558
showDirOnly = 0;
558559
style_header("File Tree");
559560
}
561
+ style_adunit_config(ADUNIT_RIGHT_OK);
560562
if( P("expand")!=0 ){
561563
startExpanded = 1;
562564
url_add_parameter(&sURI, "expand", "1");
563565
}else{
564566
startExpanded = 0;
@@ -635,10 +637,12 @@
635637
}
636638
if( linkTip ){
637639
style_submenu_element("Tip", "Tip", "%s",
638640
url_render(&sURI, "ci", "tip", 0, 0));
639641
}
642
+ style_submenu_element("Flat-View", "Flat-View", "%s",
643
+ url_render(&sURI, "type", "flat", 0, 0));
640644
641645
/* Compute the file hierarchy.
642646
*/
643647
if( zCI ){
644648
Stmt q;
@@ -652,10 +656,13 @@
652656
);
653657
while( db_step(&q)==SQLITE_ROW ){
654658
const char *zFile = db_column_text(&q,0);
655659
const char *zUuid = db_column_text(&q,1);
656660
double mtime = db_column_double(&q,2);
661
+ if( nD>0 && (fossil_strncmp(zFile, zD, nD-1)!=0 || zFile[nD-1]!='/') ){
662
+ continue;
663
+ }
657664
if( pRE && re_match(pRE, (const unsigned char*)zFile, -1)==0 ) continue;
658665
tree_add_node(&sTree, zFile, zUuid, mtime);
659666
nFile++;
660667
}
661668
db_finalize(&q);
662669
--- 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 @@
3131
3232
/*
3333
** Return a pointer to built-in content
3434
*/
3535
const unsigned char *builtin_file(const char *zFilename, int *piSize){
36
- int lwr, upr, i;
36
+ int lwr, upr, i, c;
3737
lwr = 0;
3838
upr = sizeof(aBuiltinFiles)/sizeof(aBuiltinFiles[0]) - 1;
3939
while( upr>=lwr ){
4040
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{
4247
if( piSize ) *piSize = aBuiltinFiles[i].nByte;
4348
return aBuiltinFiles[i].pData;
4449
}
4550
}
4651
if( piSize ) *piSize = 0;
4752
return 0;
53
+}
54
+const char *builtin_text(const char *zFilename){
55
+ return (char*)builtin_file(zFilename, 0);
4856
}
4957
5058
/*
5159
** COMMAND: test-builtin-list
5260
**
5361
--- 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 @@
108108
** if it does and false if it does not.
109109
*/
110110
int cgi_header_contains(const char *zNeedle){
111111
return strstr(blob_str(&cgiContent[0]), zNeedle)!=0;
112112
}
113
+int cgi_body_contains(const char *zNeedle){
114
+ return strstr(blob_str(&cgiContent[1]), zNeedle)!=0;
115
+}
113116
114117
/*
115118
** Append reply content to what already exists.
116119
*/
117120
void cgi_append_content(const char *zData, int nAmt){
118121
--- 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
--- src/codecheck1.c
+++ src/codecheck1.c
@@ -276,11 +276,11 @@
276276
277277
/* Certain functions are guaranteed to return a string that is safe
278278
** for use with %s */
279279
z = next_non_whitespace(z, &len, &eType);
280280
for(i=0; i<sizeof(azSafeFunc)/sizeof(azSafeFunc[0]); i++){
281
- if( eType==TK_ID
281
+ if( eType==TK_ID
282282
&& strncmp(z, azSafeFunc[i], len)==0
283283
&& strlen(azSafeFunc[i])==len
284284
){
285285
return 1;
286286
}
@@ -291,11 +291,11 @@
291291
if( is_string_expr(z) ) return 1;
292292
293293
/* If the "safe-for-%s" comment appears in the argument, then
294294
** let it through */
295295
if( strstr(z, "/*safe-for-%s*/")!=0 ) return 1;
296
-
296
+
297297
return 0;
298298
}
299299
300300
/*
301301
** Processing flags
@@ -460,11 +460,11 @@
460460
for(i=len-1; i>0 && isspace(z[i]); i--){ z[i] = 0; }
461461
z += len + 1;
462462
}
463463
acType = (char*)&azArg[nArg];
464464
if( fmtArg>nArg ){
465
- printf("%s:%d: too few arguments to %.*s()\n",
465
+ printf("%s:%d: too few arguments to %.*s()\n",
466466
zFilename, lnFCall, szFName, zFCall);
467467
nErr++;
468468
}else{
469469
const char *zFmt = azArg[fmtArg-1];
470470
const char *zOverride = strstr(zFmt, "/*works-like:");
@@ -537,11 +537,11 @@
537537
nCurly--;
538538
}else if( nCurly>0 && z[0]=='(' && ePrev==TK_ID
539539
&& (x = isFormatFunc(zPrev,szPrev,&fmtFlags))>0 ){
540540
nErr += checkFormatFunc(zName, zPrev, lnPrev, x, fmtFlags);
541541
}
542
- }
542
+ }
543543
zPrev = z;
544544
ePrev = eToken;
545545
szPrev = szToken;
546546
lnPrev = ln;
547547
}
548548
--- 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
--- src/configure.c
+++ src/configure.c
@@ -97,10 +97,11 @@
9797
{ "timeline-max-comment", CONFIGSET_SKIN },
9898
{ "timeline-plaintext", CONFIGSET_SKIN },
9999
{ "adunit", CONFIGSET_SKIN },
100100
{ "adunit-omit-if-admin", CONFIGSET_SKIN },
101101
{ "adunit-omit-if-user", CONFIGSET_SKIN },
102
+ { "white-foreground", CONFIGSET_SKIN },
102103
#ifdef FOSSIL_ENABLE_TH1_DOCS
103104
{ "th1-docs", CONFIGSET_TH1 },
104105
#endif
105106
#ifdef FOSSIL_ENABLE_TH1_HOOKS
106107
{ "th1-hooks", CONFIGSET_TH1 },
@@ -989,5 +990,196 @@
989990
fossil_fatal("METHOD should be one of:"
990991
" export import merge pull push reset");
991992
}
992993
configure_rebuild();
993994
}
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
+}
9941186
--- 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
+41 -24
--- src/db.c
+++ src/db.c
@@ -805,10 +805,12 @@
805805
db_checkin_mtime_function, 0, 0);
806806
sqlite3_create_function(db, "symbolic_name_to_rid", 1, SQLITE_UTF8, 0,
807807
db_sym2rid_function, 0, 0);
808808
sqlite3_create_function(db, "symbolic_name_to_rid", 2, SQLITE_UTF8, 0,
809809
db_sym2rid_function, 0, 0);
810
+ sqlite3_create_function(db, "now", 0, SQLITE_UTF8, 0,
811
+ db_now_function, 0, 0);
810812
}
811813
812814
813815
/*
814816
** Open a database file. Return a pointer to the new database
@@ -827,12 +829,10 @@
827829
if( rc!=SQLITE_OK ){
828830
db_err("[%s]: %s", zDbName, sqlite3_errmsg(db));
829831
}
830832
sqlite3_busy_timeout(db, 5000);
831833
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);
834834
sqlite3_create_function(db, "user", 0, SQLITE_UTF8, 0, db_sql_user, 0, 0);
835835
sqlite3_create_function(db, "cgi", 1, SQLITE_UTF8, 0, db_sql_cgi, 0, 0);
836836
sqlite3_create_function(db, "cgi", 2, SQLITE_UTF8, 0, db_sql_cgi, 0, 0);
837837
sqlite3_create_function(db, "print", -1, SQLITE_UTF8, 0,db_sql_print,0,0);
838838
sqlite3_create_function(
@@ -927,30 +927,35 @@
927927
char *zHome;
928928
if( g.zConfigDbName ){
929929
if( useAttach==g.useAttach ) return;
930930
db_close_config();
931931
}
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");
952957
}
953958
#endif
954959
if( file_isdir(zHome)!=1 ){
955960
fossil_fatal("invalid home directory: %s", zHome);
956961
}
@@ -1355,10 +1360,22 @@
13551360
while( (pStmt = sqlite3_next_stmt(g.db, pStmt))!=0 ){
13561361
fossil_warning("unfinalized SQL statement: [%s]", sqlite3_sql(pStmt));
13571362
}
13581363
}
13591364
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
+
13601377
if( g.db ){
13611378
sqlite3_wal_checkpoint(g.db, 0);
13621379
sqlite3_close(g.db);
13631380
g.db = 0;
13641381
g.zMainDbType = 0;
@@ -1422,13 +1439,13 @@
14221439
" WHERE login=%Q", zUser
14231440
);
14241441
if( !setupUserOnly ){
14251442
db_multi_exec(
14261443
"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');"
14281445
"INSERT OR IGNORE INTO user(login,pw,cap,info)"
1429
- " VALUES('nobody','','gjor','Nobody');"
1446
+ " VALUES('nobody','','gjorz','Nobody');"
14301447
"INSERT OR IGNORE INTO user(login,pw,cap,info)"
14311448
" VALUES('developer','','dei','Dev');"
14321449
"INSERT OR IGNORE INTO user(login,pw,cap,info)"
14331450
" VALUES('reader','','kptw','Reader');"
14341451
);
14351452
--- 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
--- 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
+#
110
set prog {
211
package require Tk
312
413
array set CFG {
514
TITLE {Fossil Diff}
615
--- 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 @@
353353
}
354354
}
355355
356356
/*
357357
** 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.
369380
*/
370381
void doc_page(void){
371382
const char *zName; /* Argument to the /doc page */
383
+ const char *zOrigName; /* Original document name */
372384
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 */
374387
int rid = 0; /* Artifact of file */
375388
int i; /* Loop counter */
376389
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 */
378391
379392
login_check_credentials();
380393
if( !g.perm.Read ){ login_needed(); return; }
381394
zName = PD("name", "tip/index.wiki");
382395
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
+ }
391402
while( zName[0]=='/' ){ zName++; }
403
+ g.zPath = mprintf("%s/%s/%s", g.zPath, zCheckin, zName);
404
+ zOrigName = zName;
392405
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);
396408
if( !file_is_simple_pathname(zName, 1) ){
397409
goto doc_not_found;
398410
}
399411
}else{
400412
goto doc_not_found;
401413
}
402414
}
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");
405417
}
406
- if( fossil_strcmp(zBaseline,"ckout")==0 ){
418
+ if( fossil_strcmp(zCheckin,"ckout")==0 ){
407419
/* Read from the local checkout */
408420
char *zFullpath;
409421
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";
416432
}
417433
}else{
418434
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");
427436
db_multi_exec(
428437
"CREATE TABLE IF NOT EXISTS vcache(\n"
429
- " vid INTEGER, -- baseline ID\n"
438
+ " vid INTEGER, -- checkin ID\n"
430439
" fname TEXT, -- filename\n"
431440
" rid INTEGER, -- artifact ID\n"
432
- " UNIQUE(vid,fname,rid)\n"
433
- ")"
441
+ " PRIMARY KEY(vid,fname)\n"
442
+ ") WITHOUT ROWID"
434443
);
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"
460448
"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;",
463452
vid
464453
);
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 ){
476456
rid = db_int(0, "SELECT rid FROM vcache"
477457
" 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";
481461
}
482
-
483
- /* Get the file content */
484
- if( content_get(rid, &filebody)==0 ){
462
+ if( rid==0 || content_get(rid, &filebody)==0 ){
485463
goto doc_not_found;
486464
}
487465
db_end_transaction(0);
488466
}
489467
blob_to_utf8_no_bom(&filebody, 0);
490468
491469
/* The file is now contained in the filebody blob. Deliver the
492470
** file to the user
493471
*/
494
- zMime = P("mimetype");
472
+ zMime = nMiss==0 ? P("mimetype") : 0;
495473
if( zMime==0 ){
496474
zMime = mimetype_from_name(zName);
497475
}
498476
Th_Store("doc_name", zName);
499477
Th_Store("doc_version", db_text(0, "SELECT '[' || substr(uuid,1,10) || ']'"
@@ -500,10 +478,11 @@
500478
" FROM blob WHERE rid=%d", vid));
501479
Th_Store("doc_date", db_text(0, "SELECT datetime(mtime) FROM event"
502480
" WHERE objid=%d AND type='ci'", vid));
503481
if( fossil_strcmp(zMime, "text/x-fossil-wiki")==0 ){
504482
Blob title, tail;
483
+ style_adunit_config(ADUNIT_RIGHT_OK);
505484
if( wiki_find_title(&filebody, &title, &tail) ){
506485
style_header("%s", blob_str(&title));
507486
wiki_convert(&tail, 0, WIKI_BUTTONS);
508487
}else{
509488
style_header("Documentation");
@@ -515,11 +494,11 @@
515494
Blob tail = BLOB_INITIALIZER;
516495
markdown_to_html(&filebody, &title, &tail);
517496
if( blob_size(&title)>0 ){
518497
style_header("%s", blob_str(&title));
519498
}else{
520
- style_header("Documentation");
499
+ style_header("%s", nMiss?"Not Found":"Documentation");
521500
}
522501
blob_append(cgi_output_blob(), blob_buffer(&tail), blob_size(&tail));
523502
style_footer();
524503
}else if( fossil_strcmp(zMime, "text/plain")==0 ){
525504
style_header("Documentation");
@@ -536,17 +515,22 @@
536515
#endif
537516
}else{
538517
cgi_set_content_type(zMime);
539518
cgi_set_content(&filebody);
540519
}
520
+ if( nMiss ) cgi_set_status(404, "Not Found");
541521
return;
542522
543
-doc_not_found:
544523
/* Jump here when unable to locate the document */
524
+doc_not_found:
545525
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
+ }
548532
style_footer();
549533
return;
550534
}
551535
552536
/*
553537
--- 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 @@
12621262
char *zValue = getenv(zName);
12631263
#endif
12641264
if( zValue ) zValue = fossil_filename_to_utf8(zValue);
12651265
return zValue;
12661266
}
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
+}
12671286
12681287
/*
12691288
** Like fopen() but always takes a UTF8 argument.
12701289
*/
12711290
FILE *fossil_fopen(const char *zName, const char *zMode){
12721291
--- 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 @@
2727
*/
2828
2929
#include "config.h"
3030
#include "http_socket.h"
3131
#if defined(_WIN32)
32
+# if !defined(_WIN32_WINNT)
33
+# define _WIN32_WINNT 0x0501
34
+# endif
3235
# include <winsock2.h>
3336
# include <ws2tcpip.h>
3437
#else
3538
# include <netinet/in.h>
3639
# include <arpa/inet.h>
@@ -45,11 +48,10 @@
4548
** There can only be a single socket connection open at a time.
4649
** State information about that socket is stored in the following
4750
** local variables:
4851
*/
4952
static int socketIsInit = 0; /* True after global initialization */
50
-static int addrIsInit = 0; /* True once addr is initialized */
5153
#if defined(_WIN32)
5254
static WSADATA socketInfo; /* Windows socket initialize data */
5355
#endif
5456
static int iSocket = -1; /* The socket on which we talk to the server */
5557
static char *socketErrMsg = 0; /* Text of most recent socket error */
@@ -106,11 +108,10 @@
106108
WSACleanup();
107109
#endif
108110
socket_clear_errmsg();
109111
socketIsInit = 0;
110112
}
111
- addrIsInit = 0;
112113
}
113114
114115
/*
115116
** Close the currently open socket. If no socket is open, this routine
116117
** is a no-op.
@@ -134,54 +135,56 @@
134135
** pUrlDAta->port TCP/IP port to use. Ex: 80
135136
**
136137
** Return the number of errors.
137138
*/
138139
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];
140146
141147
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 ){
174176
socket_set_errmsg("cannot connect to host %s:%d", pUrlData->name,
175177
pUrlData->port);
176
- socket_close();
177
- return 1;
178178
}
179179
#if !defined(_WIN32)
180180
signal(SIGPIPE, SIG_IGN);
181181
#endif
182
- return 0;
182
+end_socket_open:
183
+ if( rc && iSocket>=0 ) socket_close();
184
+ if( ai ) freeaddrinfo(ai);
185
+ return rc;
183186
}
184187
185188
/*
186189
** Send content out over the open socket connection.
187190
*/
188191
--- 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 @@
198198
int verboseFlag = find_option("verbose","v",0)!=0;
199199
if( !verboseFlag ){
200200
verboseFlag = find_option("detail","l",0)!=0; /* deprecated */
201201
}
202202
203
- /* We should be done with options.. */
204
- verify_all_options();
205
-
206203
if( g.argc==3 && (fsize = file_size(g.argv[2]))>0 && (fsize&0x1ff)==0 ){
207204
db_open_config(0);
208205
db_open_repository(g.argv[2]);
209206
db_record_repository_filename(g.argv[2]);
210207
fossil_print("project-name: %s\n", db_get("project-name", "<unnamed>"));
@@ -211,10 +208,11 @@
211208
fossil_print("project-code: %s\n", db_get("project-code", "<none>"));
212209
extraRepoInfo();
213210
return;
214211
}
215212
db_find_and_open_repository(0,0);
213
+ verify_all_options();
216214
if( g.argc==2 ){
217215
int vid;
218216
/* 012345678901234 */
219217
db_record_repository_filename(0);
220218
fossil_print("project-name: %s\n", db_get("project-name", "<unnamed>"));
221219
--- 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
--- src/login.c
+++ src/login.c
@@ -575,10 +575,11 @@
575575
login_set_user_cookie(zUsername, uid, NULL);
576576
redirect_to_g();
577577
}
578578
}
579579
style_header("Login/Logout");
580
+ style_adunit_config(ADUNIT_OFF);
580581
@ %s(zErrMsg)
581582
if( zGoto && P("anon")==0 ){
582583
@ <p>A login is required for <a href="%h(zGoto)">%h(zGoto)</a>.</p>
583584
}
584585
form_begin(0, "%R/login");
585586
--- 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 @@
149149
int fSystemTrace; /* Trace calls to fossil_system(), --systemtrace */
150150
int fSshTrace; /* Trace the SSH setup traffic */
151151
int fSshClient; /* HTTP client flags for SSH client */
152152
char *zSshCmd; /* SSH command string */
153153
int fNoSync; /* Do not do an autosync ever. --nosync */
154
+ int fIPv4; /* Use only IPv4, not IPv6. --ipv4 */
154155
char *zPath; /* Name of webpage being served */
155156
char *zExtra; /* Extra path information past the webpage name */
156157
char *zBaseURL; /* Full text of the URL being served */
157158
char *zHttpsURL; /* zBaseURL translated to https: */
158159
char *zTop; /* Parent directory of zPath */
@@ -1787,57 +1788,119 @@
17871788
g.cgiOutput = 1;
17881789
blob_read_from_file(&config, zFile);
17891790
while( blob_line(&config, &line) ){
17901791
if( !blob_token(&line, &key) ) continue;
17911792
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
- }
18061793
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
+ */
18071800
blob_trim(&value);
18081801
db_open_repository(blob_str(&value));
18091802
blob_reset(&value);
18101803
continue;
18111804
}
18121805
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
+ */
18131812
db_close(1);
18141813
g.zRepositoryName = mprintf("%s", blob_str(&value));
18151814
blob_reset(&value);
18161815
continue;
18171816
}
18181817
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
+ */
18191823
zNotFound = mprintf("%s", blob_str(&value));
18201824
blob_reset(&value);
18211825
continue;
18221826
}
18231827
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
+ */
18241833
g.useLocalauth = 1;
18251834
continue;
18261835
}
18271836
if( blob_eq(&key, "redirect:") && blob_token(&line, &value)
18281837
&& blob_token(&line, &value2) ){
1838
+ /* See the header comment on the redirect_web_page() function
1839
+ ** above for details. */
18291840
nRedirect++;
18301841
azRedirect = fossil_realloc(azRedirect, 2*nRedirect*sizeof(char*));
18311842
azRedirect[nRedirect*2-2] = mprintf("%s", blob_str(&value));
18321843
azRedirect[nRedirect*2-1] = mprintf("%s", blob_str(&value2));
18331844
blob_reset(&value);
18341845
blob_reset(&value2);
18351846
continue;
18361847
}
18371848
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
+ */
18381859
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);
18391902
continue;
18401903
}
18411904
}
18421905
blob_reset(&config);
18431906
if( g.db==0 && g.zRepositoryName==0 && nRedirect==0 ){
18441907
--- 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 @@
131131
$(SRCDIR)/xfer.c \
132132
$(SRCDIR)/xfersetup.c \
133133
$(SRCDIR)/zip.c
134134
135135
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 \
136160
$(SRCDIR)/diff.tcl
137161
138162
TRANS_SRC = \
139163
$(OBJDIR)/add_.c \
140164
$(OBJDIR)/allrepo_.c \
141165
--- 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 @@
112112
**
113113
** struct Xyzzy;
114114
**
115115
** Not every object has a forward declaration. If it does, thought, the
116116
** 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.
119119
*/
120120
typedef struct Decl Decl;
121121
struct Decl {
122122
char *zName; /* Name of the object being declared. The appearance
123123
** of this name is a source file triggers the declaration
124124
** to be added to the header for that file. */
125
- char *zFile; /* File from which extracted. */
125
+ const char *zFile; /* File from which extracted. */
126126
char *zIf; /* Surround the declaration with this #if */
127127
char *zFwd; /* A forward declaration. NULL if there is none. */
128128
char *zFwdCpp; /* Use this forward declaration for C++. */
129129
char *zDecl; /* A full declaration of this object */
130130
char *zExtra; /* Extra declaration text inserted into class objects */
@@ -163,11 +163,11 @@
163163
** in the output when using the -H option.)
164164
**
165165
** EXPORT scope The object is visible and usable everywhere.
166166
**
167167
** 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.
169169
**
170170
** The DP_Cplusplus, DP_ExternCReqd and DP_ExternReqd flags are permanent
171171
** and are used to specify what type of declaration the object requires.
172172
*/
173173
#define DP_Forward 0x001 /* Has a forward declaration in this file */
@@ -201,11 +201,11 @@
201201
** Be careful not to confuse PS_Export with DP_Export or
202202
** PS_Local with DP_Local. Their names are similar, but the meanings
203203
** of these flags are very different.
204204
*/
205205
#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"
207207
** and "#endif" */
208208
#define PS_Export2 0x002000 /* If "EXPORT" seen */
209209
#define PS_Typedef 0x004000 /* If "typedef" has been seen */
210210
#define PS_Static 0x008000 /* If "static" has been seen */
211211
#define PS_Interface 0x010000 /* If within #if INTERFACE..#endif */
@@ -231,11 +231,11 @@
231231
#define TY_Union 0x04000000
232232
#define TY_Enumeration 0x08000000
233233
#define TY_Defunct 0x10000000 /* Used to erase a declaration */
234234
235235
/*
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
237237
** instances of the following structure.
238238
*/
239239
typedef struct Ifmacro Ifmacro;
240240
struct Ifmacro {
241241
int nLine; /* Line number where this macro occurs */
@@ -293,11 +293,11 @@
293293
int flags; /* One or more DP_, PS_ and/or TY_ flags */
294294
InFile *pNext; /* Next input file in the list of them all */
295295
IdentTable idTable; /* All identifiers in this input file */
296296
};
297297
298
-/*
298
+/*
299299
** An unbounded string is able to grow without limit. We use these
300300
** to construct large in-memory strings from lots of smaller components.
301301
*/
302302
typedef struct String String;
303303
struct String {
@@ -332,19 +332,19 @@
332332
** never to read a file that it generated itself.
333333
**
334334
** The "#undef INTERFACE" part is a hack to work around a name collision
335335
** in MSVC 2008.
336336
*/
337
-const char zTopLine[] =
337
+const char zTopLine[] =
338338
"/* \aThis file was automatically generated. Do not edit! */\n"
339339
"#undef INTERFACE\n";
340340
#define nTopLine (sizeof(zTopLine)-1)
341341
342342
/*
343343
** The name of the file currently being parsed.
344344
*/
345
-static char *zFilename;
345
+static const char *zFilename;
346346
347347
/*
348348
** The stack of #if macros for the file currently being parsed.
349349
*/
350350
static Ifmacro *ifStack = 0;
@@ -702,11 +702,11 @@
702702
struct stat sStat;
703703
FILE *pIn;
704704
char *zBuf;
705705
int n;
706706
707
- if( stat(zFilename,&sStat)!=0
707
+ if( stat(zFilename,&sStat)!=0
708708
#ifndef WIN32
709709
|| !S_ISREG(sStat.st_mode)
710710
#endif
711711
){
712712
return 0;
@@ -889,12 +889,12 @@
889889
}
890890
}
891891
}
892892
i++;
893893
}
894
- if( z[i] ){
895
- i += 2;
894
+ if( z[i] ){
895
+ i += 2;
896896
}else{
897897
isBlockComment = 0;
898898
fprintf(stderr,"%s:%d: Unterminated comment\n",
899899
zFilename, startLine);
900900
nErr++;
@@ -906,11 +906,11 @@
906906
pToken->eType = TT_Other;
907907
pToken->nText = 1 + (z[i+1]=='+');
908908
}
909909
break;
910910
911
- case '0':
911
+ case '0':
912912
if( z[i+1]=='x' || z[i+1]=='X' ){
913913
/* A hex constant */
914914
i += 2;
915915
while( isxdigit(z[i]) ){ i++; }
916916
}else{
@@ -963,11 +963,11 @@
963963
while( isalnum(z[i]) || z[i]=='_' ){ i++; };
964964
pToken->eType = TT_Id;
965965
pToken->nText = i - pIn->i;
966966
break;
967967
968
- case ':':
968
+ case ':':
969969
pToken->eType = TT_Other;
970970
pToken->nText = 1 + (z[i+1]==':');
971971
break;
972972
973973
case '=':
@@ -977,11 +977,11 @@
977977
case '-':
978978
case '*':
979979
case '%':
980980
case '^':
981981
case '&':
982
- case '|':
982
+ case '|':
983983
pToken->eType = TT_Other;
984984
pToken->nText = 1 + (z[i+1]=='=');
985985
break;
986986
987987
default:
@@ -1064,11 +1064,11 @@
10641064
}
10651065
}
10661066
/* NOT REACHED */
10671067
}
10681068
1069
-/*
1069
+/*
10701070
** This routine looks for identifiers (strings of contiguous alphanumeric
10711071
** characters) within a preprocessor directive and adds every such string
10721072
** found to the given identifier table
10731073
*/
10741074
static void FindIdentifiersInMacro(Token *pToken, IdentTable *pTable){
@@ -1157,11 +1157,11 @@
11571157
case TT_Id:
11581158
if( pTable ){
11591159
IdentTableInsert(pTable,pToken->zText,pToken->nText);
11601160
}
11611161
break;
1162
-
1162
+
11631163
case TT_Preprocessor:
11641164
if( pTable!=0 ){
11651165
FindIdentifiersInMacro(pToken,pTable);
11661166
}
11671167
break;
@@ -1263,11 +1263,11 @@
12631263
exit(1);
12641264
}
12651265
pList = TokenizeFile(zFile,&sTable);
12661266
for(p=pList; p; p=p->pNext){
12671267
int j;
1268
- switch( p->eType ){
1268
+ switch( p->eType ){
12691269
case TT_Space:
12701270
printf("%4d: Space\n",p->nLine);
12711271
break;
12721272
case TT_Id:
12731273
printf("%4d: Id %.*s\n",p->nLine,p->nText,p->zText);
@@ -1330,11 +1330,11 @@
13301330
needSpace = 1;
13311331
break;
13321332
13331333
default:
13341334
c = pFirst->zText[0];
1335
- printf("%s%.*s",
1335
+ printf("%s%.*s",
13361336
(needSpace && (c=='*' || c=='{')) ? " " : "",
13371337
pFirst->nText, pFirst->zText);
13381338
needSpace = pFirst->zText[0]==',';
13391339
break;
13401340
}
@@ -1371,13 +1371,13 @@
13711371
13721372
StringInit(&str);
13731373
pLast = pLast->pNext;
13741374
while( pFirst!=pLast ){
13751375
if( pFirst==pSkip ){ iSkip = nSkip; }
1376
- if( iSkip>0 ){
1376
+ if( iSkip>0 ){
13771377
iSkip--;
1378
- pFirst=pFirst->pNext;
1378
+ pFirst=pFirst->pNext;
13791379
continue;
13801380
}
13811381
switch( pFirst->eType ){
13821382
case TT_Preprocessor:
13831383
StringAppend(&str,"\n",1);
@@ -1384,13 +1384,13 @@
13841384
StringAppend(&str,pFirst->zText,pFirst->nText);
13851385
StringAppend(&str,"\n",1);
13861386
needSpace = 0;
13871387
break;
13881388
1389
- case TT_Id:
1389
+ case TT_Id:
13901390
switch( pFirst->zText[0] ){
1391
- case 'E':
1391
+ case 'E':
13921392
if( pFirst->nText==6 && strncmp(pFirst->zText,"EXPORT",6)==0 ){
13931393
skipOne = 1;
13941394
}
13951395
break;
13961396
case 'P':
@@ -1645,17 +1645,17 @@
16451645
pLast = pLast->pNext;
16461646
for(p=pFirst; p && p!=pLast; p=p->pNext){
16471647
if( p->eType==TT_Id ){
16481648
static IdentTable sReserved;
16491649
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",
16521652
"float", "int", "long",
16531653
"PRIVATE", "PROTECTED", "PUBLIC",
1654
- "register", "static", "struct", "sizeof", "signed", "typedef",
1654
+ "register", "static", "struct", "sizeof", "signed", "typedef",
16551655
"union", "volatile", "virtual", "void", };
1656
-
1656
+
16571657
if( !isInit ){
16581658
int i;
16591659
for(i=0; i<sizeof(aWords)/sizeof(aWords[0]); i++){
16601660
IdentTableInsert(&sReserved,aWords[i],0);
16611661
}
@@ -1768,11 +1768,11 @@
17681768
pCode = pLast;
17691769
while( pLast && pLast!=pFirst && pLast->zText[0]!=')' ){
17701770
pLast = pLast->pPrev;
17711771
}
17721772
if( pLast==0 || pLast==pFirst || pFirst->pNext==pLast ){
1773
- fprintf(stderr,"%s:%d: Unrecognized syntax.\n",
1773
+ fprintf(stderr,"%s:%d: Unrecognized syntax.\n",
17741774
zFilename, pFirst->nLine);
17751775
return 1;
17761776
}
17771777
if( flags & (PS_Interface|PS_Export|PS_Local) ){
17781778
fprintf(stderr,"%s:%d: Missing \"inline\" on function or procedure.\n",
@@ -1849,11 +1849,11 @@
18491849
return 1;
18501850
}
18511851
18521852
#ifdef DEBUG
18531853
if( debugMask & PARSER ){
1854
- printf("**** Found inline routine: %.*s on line %d...\n",
1854
+ printf("**** Found inline routine: %.*s on line %d...\n",
18551855
pName->nText, pName->zText, pFirst->nLine);
18561856
PrintTokens(pFirst,pEnd);
18571857
printf("\n");
18581858
}
18591859
#endif
@@ -1888,11 +1888,11 @@
18881888
** to search for an occurrence of an ID followed immediately by '('.
18891889
** If found, we have a prototype. Otherwise we are dealing with a
18901890
** variable definition.
18911891
*/
18921892
static int isVariableDef(Token *pFirst, Token *pEnd){
1893
- if( pEnd && pEnd->zText[0]=='=' &&
1893
+ if( pEnd && pEnd->zText[0]=='=' &&
18941894
(pEnd->pPrev->nText!=8 || strncmp(pEnd->pPrev->zText,"operator",8)!=0)
18951895
){
18961896
return 1;
18971897
}
18981898
while( pFirst && pFirst!=pEnd && pFirst->pNext && pFirst->pNext!=pEnd ){
@@ -1949,11 +1949,11 @@
19491949
}
19501950
while( pFirst!=0 && pFirst->pNext!=pEnd &&
19511951
((pFirst->nText==6 && strncmp(pFirst->zText,"static",6)==0)
19521952
|| (pFirst->nText==5 && strncmp(pFirst->zText,"LOCAL",6)==0))
19531953
){
1954
- /* Lose the initial "static" or local from local variables.
1954
+ /* Lose the initial "static" or local from local variables.
19551955
** We'll prepend "extern" later. */
19561956
pFirst = pFirst->pNext;
19571957
isLocal = 1;
19581958
}
19591959
if( pFirst==0 || !isLocal ){
@@ -1962,11 +1962,11 @@
19621962
}else if( flags & PS_Method ){
19631963
/* Methods are declared by their class. Don't declare separately. */
19641964
return nErr;
19651965
}
19661966
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
19681968
&& (flags & PS_Extern)==0 ){
19691969
fprintf(stderr,"%s:%d: Can't define a variable in this context\n",
19701970
zFilename, pFirst->nLine);
19711971
nErr++;
19721972
}
@@ -2095,11 +2095,11 @@
20952095
nCmd++;
20962096
}
20972097
20982098
if( nCmd==5 && strncmp(zCmd,"endif",5)==0 ){
20992099
/*
2100
- ** Pop the if stack
2100
+ ** Pop the if stack
21012101
*/
21022102
pIf = ifStack;
21032103
if( pIf==0 ){
21042104
fprintf(stderr,"%s:%d: extra '#endif'.\n",zFilename,pToken->nLine);
21052105
return 1;
@@ -2106,11 +2106,11 @@
21062106
}
21072107
ifStack = pIf->pNext;
21082108
SafeFree(pIf);
21092109
}else if( nCmd==6 && strncmp(zCmd,"define",6)==0 ){
21102110
/*
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
21122112
*/
21132113
Decl *pDecl;
21142114
if( !(flags & (PS_Local|PS_Interface|PS_Export)) ){ return 0; }
21152115
zArg = &zCmd[6];
21162116
while( *zArg && isspace(*zArg) && *zArg!='\n' ){
@@ -2129,11 +2129,11 @@
21292129
}else if( flags & PS_Local ){
21302130
DeclSetProperty(pDecl,DP_Local);
21312131
}
21322132
}else if( nCmd==7 && strncmp(zCmd,"include",7)==0 ){
21332133
/*
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
21352135
*/
21362136
Include *pInclude;
21372137
char *zIf;
21382138
21392139
if( !(flags & (PS_Interface|PS_Export)) ){ return 0; }
@@ -2184,11 +2184,11 @@
21842184
PushIfMacro(0,0,0,pToken->nLine,PS_Local);
21852185
}else{
21862186
PushIfMacro(0,zArg,nArg,pToken->nLine,0);
21872187
}
21882188
}else if( nCmd==5 && strncmp(zCmd,"ifdef",5)==0 ){
2189
- /*
2189
+ /*
21902190
** Push an #ifdef.
21912191
*/
21922192
zArg = &zCmd[5];
21932193
while( *zArg && isspace(*zArg) && *zArg!='\n' ){
21942194
zArg++;
@@ -2207,11 +2207,11 @@
22072207
if( *zArg==0 || *zArg=='\n' ){ return 0; }
22082208
nArg = pToken->nText + (int)(pToken->zText - zArg);
22092209
PushIfMacro("!defined",zArg,nArg,pToken->nLine,0);
22102210
}else if( nCmd==4 && strncmp(zCmd,"else",4)==0 ){
22112211
/*
2212
- ** Invert the #if on the top of the stack
2212
+ ** Invert the #if on the top of the stack
22132213
*/
22142214
if( ifStack==0 ){
22152215
fprintf(stderr,"%s:%d: '#else' without an '#if'\n",zFilename,
22162216
pToken->nLine);
22172217
return 1;
@@ -2224,33 +2224,33 @@
22242224
}else{
22252225
pIf->flags = 0;
22262226
}
22272227
}else{
22282228
/*
2229
- ** This directive can be safely ignored
2229
+ ** This directive can be safely ignored
22302230
*/
22312231
return 0;
22322232
}
22332233
2234
- /*
2235
- ** Recompute the preset flags
2234
+ /*
2235
+ ** Recompute the preset flags
22362236
*/
22372237
*pPresetFlags = 0;
22382238
for(pIf = ifStack; pIf; pIf=pIf->pNext){
22392239
*pPresetFlags |= pIf->flags;
22402240
}
2241
-
2241
+
22422242
return nErr;
22432243
}
22442244
22452245
/*
22462246
** Parse an entire file. Return the number of errors.
22472247
**
22482248
** pList is a list of tokens in the file. Whitespace tokens have been
22492249
** eliminated, and text with {...} has been collapsed into a
22502250
** single TT_Brace token.
2251
-**
2251
+**
22522252
** initFlags are a set of parse flags that should always be set for this
22532253
** file. For .c files this is normally 0. For .h files it is PS_Interface.
22542254
*/
22552255
static int ParseFile(Token *pList, int initFlags){
22562256
int nErr = 0;
@@ -2279,11 +2279,11 @@
22792279
pStart = 0;
22802280
flags = presetFlags;
22812281
break;
22822282
22832283
case '=':
2284
- if( pList->pPrev->nText==8
2284
+ if( pList->pPrev->nText==8
22852285
&& strncmp(pList->pPrev->zText,"operator",8)==0 ){
22862286
break;
22872287
}
22882288
nErr += ProcessDecl(pStart,pList,flags);
22892289
pStart = 0;
@@ -2471,11 +2471,11 @@
24712471
pDecl->zExtra = 0;
24722472
}
24732473
24742474
/*
24752475
** 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
24772477
** in the file zFilename so that it won't be printing in other files.
24782478
*/
24792479
static void ResetDeclFlags(char *zFilename){
24802480
Decl *pDecl;
24812481
@@ -2574,11 +2574,11 @@
25742574
int flag;
25752575
int isCpp; /* True if generating C++ */
25762576
int doneTypedef = 0; /* True if a typedef has been done for this object */
25772577
25782578
/* printf("BEGIN %s of %s\n",needFullDecl?"FULL":"PROTOTYPE",pDecl->zName);*/
2579
- /*
2579
+ /*
25802580
** For any object that has a forward declaration, go ahead and do the
25812581
** forward declaration first.
25822582
*/
25832583
isCpp = (pState->flags & DP_Cplusplus) != 0;
25842584
for(p=pDecl; p; p=p->pSameName){
@@ -2626,12 +2626,12 @@
26262626
** function on a recursive call with the same pDecl. Hence, recursive
26272627
** calls to this function (through ScanText()) can never change the
26282628
** value of DP_Flag out from under us.
26292629
*/
26302630
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)
26332633
&& p->zDecl!=0
26342634
){
26352635
DeclSetProperty(p,DP_Forward|DP_Declared|DP_Flag);
26362636
}else{
26372637
DeclClearProperty(p,DP_Flag);
@@ -2735,12 +2735,12 @@
27352735
** by sToken.
27362736
*/
27372737
pDecl = FindDecl(sToken.zText,sToken.nText);
27382738
if( pDecl==0 ) continue;
27392739
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
27422742
** declaration in the database. Now see if we the full declaration
27432743
** or just a forward declaration.
27442744
*/
27452745
GetNonspaceToken(&sIn,&sNext);
27462746
if( sNext.zText[0]=='*' ){
@@ -2770,12 +2770,12 @@
27702770
int progress;
27712771
27722772
do{
27732773
progress = 0;
27742774
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)
27772777
){
27782778
DeclareObject(pDecl,pState,1);
27792779
progress = 1;
27802780
assert( DeclHasProperty(pDecl,DP_Declared) );
27812781
}
@@ -2842,11 +2842,11 @@
28422842
nErr++;
28432843
}
28442844
}else if( report ){
28452845
fprintf(report,"unchanged\n");
28462846
}
2847
- SafeFree(zOldVersion);
2847
+ SafeFree(zOldVersion);
28482848
IdentTableReset(&includeTable);
28492849
StringReset(&outStr);
28502850
return nErr;
28512851
}
28522852
@@ -2878,11 +2878,11 @@
28782878
}
28792879
ChangeIfContext(0,&sState);
28802880
printf("%s",StringGet(&outStr));
28812881
IdentTableReset(&includeTable);
28822882
StringReset(&outStr);
2883
- return 0;
2883
+ return 0;
28842884
}
28852885
28862886
#ifdef DEBUG
28872887
/*
28882888
** Return the number of characters in the given string prior to the
@@ -3040,11 +3040,11 @@
30403040
int nSrc;
30413041
char *zSrc;
30423042
InFile *pFile;
30433043
int i;
30443044
3045
- /*
3045
+ /*
30463046
** Get the name of the input file to be scanned. The input file is
30473047
** everything before the first ':' or the whole file if no ':' is seen.
30483048
**
30493049
** Except, on windows, ignore any ':' that occurs as the second character
30503050
** since it might be part of the drive specifier. So really, the ":' has
@@ -3099,11 +3099,11 @@
30993099
}
31003100
}
31013101
31023102
/*
31033103
** 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
31053105
** PS_Interface flag.
31063106
*/
31073107
pFile->flags |= PS_Interface;
31083108
for(i=nSrc-1; i>0 && zSrc[i]!='.'; i--){
31093109
if( zSrc[i]=='c' || zSrc[i]=='C' ){
@@ -3110,11 +3110,11 @@
31103110
pFile->flags &= ~PS_Interface;
31113111
break;
31123112
}
31133113
}
31143114
3115
- /* Done!
3115
+ /* Done!
31163116
*/
31173117
return pFile;
31183118
}
31193119
31203120
/* MS-Windows and MS-DOS both have the following serious OS bug: the
@@ -3162,11 +3162,11 @@
31623162
while( c!=EOF ){
31633163
while( c!=EOF && isspace(c) ){
31643164
if( c=='\n' ){
31653165
startOfLine = 1;
31663166
}
3167
- c = getc(in);
3167
+ c = getc(in);
31683168
if( startOfLine && c=='#' ){
31693169
while( c!=EOF && c!='\n' ){
31703170
c = getc(in);
31713171
}
31723172
}
@@ -3184,11 +3184,11 @@
31843184
if( nAlloc==0 ){
31853185
nAlloc = 100 + argc;
31863186
zNew = malloc( sizeof(char*) * nAlloc );
31873187
}else{
31883188
nAlloc *= 2;
3189
- zNew = realloc( zNew, sizeof(char*) * nAlloc );
3189
+ zNew = realloc( zNew, sizeof(char*) * nAlloc );
31903190
}
31913191
}
31923192
if( zNew ){
31933193
int j = nNew + index;
31943194
zNew[j] = malloc( n + 1 );
@@ -3254,11 +3254,11 @@
32543254
32553255
/*
32563256
** The following text contains a few simple #defines that we want
32573257
** to be available to every file.
32583258
*/
3259
-static char zInit[] =
3259
+static const char zInit[] =
32603260
"#define INTERFACE 0\n"
32613261
"#define EXPORT_INTERFACE 0\n"
32623262
"#define LOCAL_INTERFACE 0\n"
32633263
"#define EXPORT\n"
32643264
"#define LOCAL static\n"
32653265
--- 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 @@
11
#!/usr/bin/tclsh
22
#
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
44
# of platforms. Files generated include:
55
#
66
# src/main.mk # makefile for all unix systems
77
# win/Makefile.mingw # makefile for mingw on windows
88
# win/Makefile.* # makefiles for other windows compilers
@@ -142,10 +142,11 @@
142142
143143
# Additional resource files that get built into the executable.
144144
#
145145
set extra_files {
146146
diff.tcl
147
+ ../skins/*/*.txt
147148
}
148149
149150
# Options used to compile the included SQLite library.
150151
#
151152
set SQLITE_OPTIONS {
@@ -203,10 +204,19 @@
203204
}
204205
205206
# STOP HERE.
206207
# Unless the build procedures changes, you should not have to edit anything
207208
# 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
208218
209219
##############################################################################
210220
##############################################################################
211221
##############################################################################
212222
# Start by generating the "main.mk" makefile used for all unix systems.
@@ -573,12 +583,13 @@
573583
#### The directories where the OpenSSL include and library files are located.
574584
# The recommended usage here is to use the Sysinternals junction tool
575585
# to create a hard link between an "openssl-1.x" sub-directory of the
576586
# Fossil source code directory and the target OpenSSL source directory.
577587
#
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)
580591
581592
#### Either the directory where the Tcl library is installed or the Tcl
582593
# source code directory resides (depending on the value of the macro
583594
# FOSSIL_TCL_SOURCE). If this points to the Tcl install directory,
584595
# this directory must have "include" and "lib" sub-directories. If
@@ -1305,11 +1316,11 @@
13051316
13061317
# Uncomment to enable Tcl support
13071318
# FOSSIL_ENABLE_TCL = 1
13081319
13091320
!ifdef FOSSIL_ENABLE_SSL
1310
-SSLDIR = $(B)\compat\openssl-1.0.1k
1321
+SSLDIR = $(B)\compat\openssl-1.0.1l
13111322
SSLINCDIR = $(SSLDIR)\inc32
13121323
SSLLIBDIR = $(SSLDIR)\out32
13131324
SSLLFLAGS = /nologo /opt:ref /debug
13141325
SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib
13151326
!if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64"
13161327
--- 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 @@
2929
#include <string.h>
3030
3131
3232
/*
3333
** 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
3535
** file into *pnByte.
3636
*/
3737
static unsigned char *read_file(const char *zFilename, int *pnByte){
3838
FILE *in;
3939
unsigned char *z;
@@ -62,10 +62,11 @@
6262
*/
6363
typedef struct Resource Resource;
6464
struct Resource {
6565
const char *zName;
6666
int nByte;
67
+ int idx;
6768
};
6869
6970
/*
7071
** Compare two Resource objects for sorting purposes. They sort
7172
** in zName order so that Fossil can search for resources using
@@ -82,10 +83,11 @@
8283
int j, n;
8384
Resource *aRes;
8485
int nRes = argc-1;
8586
unsigned char *pData;
8687
int nErr = 0;
88
+ int nSkip;
8789
8890
aRes = malloc( nRes*sizeof(aRes[0]) );
8991
if( aRes==0 ){
9092
fprintf(stderr, "malloc failed\n");
9193
return 1;
@@ -103,15 +105,24 @@
103105
if( pData==0 ){
104106
fprintf(stderr, "Cannot open file [%s]\n", aRes[i].zName);
105107
nErr++;
106108
continue;
107109
}
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;
109120
printf("/* Content of file %s */\n", aRes[i].zName);
110121
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++){
113124
printf("%3d", pData[j]);
114125
if( j==sz ){
115126
printf(" };\n");
116127
}else if( n==14 ){
117128
printf(",\n ");
@@ -129,17 +140,26 @@
129140
printf(" const unsigned char *pData;\n");
130141
printf(" int nByte;\n");
131142
printf("};\n");
132143
printf("static const BuiltinFileTable aBuiltinFiles[] = {\n");
133144
for(i=0; i<nRes; i++){
134
- const char *zTail;
135145
const char *z = aRes[i].zName;
146
+ const char *zTail;
147
+ int nSlash = 0;
136148
zTail = z;
137149
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
+ }
139154
z++;
140155
}
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);
142162
}
143163
printf("};\n");
144164
return nErr;
145165
}
146166
--- 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 @@
217217
if( zLine[i]!='(' ) goto page_skip;
218218
nFixed = nUsed;
219219
nHelp = 0;
220220
return;
221221
222
-page_skip:
222
+page_skip:
223223
for(i=nFixed; i<nUsed; i++){
224224
fprintf(stderr,"%s:%d: skipping page \"%s\"\n",
225225
zFile, nLine, aEntry[i].zPath);
226226
}
227227
nUsed = nFixed;
@@ -327,11 +327,11 @@
327327
aEntry[i].zHelp[0] = 0;
328328
}
329329
}
330330
puts("struct CmdHelp {"
331331
"int eType; "
332
- "char const * zText;"
332
+ "const char *zText;"
333333
"};");
334334
puts("static struct CmdHelp aCmdHelp[] = {");
335335
for(i=0; i<nFixed; i++){
336336
if( aEntry[i].zIf ) printf("%s", aEntry[i].zIf);
337337
if( aEntry[i].zHelp==0 ){
@@ -361,11 +361,11 @@
361361
scan_for_label("WEBPAGE:",zLine,0);
362362
scan_for_label("COMMAND:",zLine,1);
363363
scan_for_func(zLine);
364364
}
365365
fclose(in);
366
- nUsed = nFixed;
366
+ nUsed = nFixed;
367367
}
368368
369369
int main(int argc, char **argv){
370370
int i;
371371
for(i=1; i<argc; i++){
372372
--- 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 @@
4343
exit(1);
4444
}
4545
fclose(v);
4646
for(z=b; z[0] && z[0]!='\r' && z[0]!='\n'; z++){}
4747
*z = 0;
48
- printf("#define RELEASE_VERSION \"%s\"\n", b);
48
+ printf("#define RELEASE_VERSION \"%s\"\n", b);
4949
x=0;
5050
i=0;
5151
z=b;
5252
while(1){
5353
if( z[0]>='0' && z[0]<='9' ){
5454
--- 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 @@
171171
/* We've already seen an error. No need to continue. */
172172
return SQLITE_OK;
173173
}
174174
switch( code ){
175175
case SQLITE_SELECT:
176
+ case SQLITE_RECURSIVE:
176177
case SQLITE_FUNCTION: {
177178
break;
178179
}
179180
case SQLITE_READ: {
180181
static const char *const azAllowed[] = {
@@ -201,15 +202,10 @@
201202
}else if( !g.perm.RdAddr && strncmp(zArg2, "private_", 8)==0 ){
202203
rc = SQLITE_IGNORE;
203204
}
204205
break;
205206
}
206
- case SQLITE_RECURSIVE: {
207
- *(char**)pError = mprintf("recursive queries are not allowed");
208
- rc = SQLITE_DENY;
209
- break;
210
- }
211207
default: {
212208
*(char**)pError = mprintf("only SELECT statements are allowed");
213209
rc = SQLITE_DENY;
214210
break;
215211
}
@@ -240,15 +236,17 @@
240236
const char *zTail;
241237
sqlite3_stmt *pStmt;
242238
int rc;
243239
244240
/* 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.
246243
*/
247244
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");
250248
}
251249
for(i=0; zSql[i]; i++){
252250
if( zSql[i]==';' ){
253251
int bad;
254252
int c = zSql[i+1];
@@ -936,10 +934,11 @@
936934
** t Sort by text
937935
** n Sort numerically
938936
** k Sort by the data-sortkey property
939937
** x This column is not sortable
940938
**
939
+** Capital letters mean sort in reverse order.
941940
** If there are fewer characters in zColumnTypes[] than their are columns,
942941
** the all extra columns assume type "t" (text).
943942
**
944943
** The third parameter is the column that was initially sorted (using 1-based
945944
** column numbers, like SQL). Make this value 0 if none of the columns are
@@ -959,14 +958,14 @@
959958
@ this.columnTypes = columnTypes;
960959
@ this.sort = function (cell) {
961960
@ var column = cell.cellIndex;
962961
@ var sortFn;
963962
@ 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;
968967
@ }
969968
@ this.sortIndex = column;
970969
@ var newRows = new Array();
971970
@ for (j = 0; j < this.tbody[0].rows.length; j++) {
972971
@ newRows[j] = this.tbody[0].rows[j];
@@ -975,10 +974,13 @@
975974
@ newRows.reverse();
976975
@ this.prevColumn = -this.prevColumn;
977976
@ }else{
978977
@ newRows.sort(sortFn);
979978
@ this.prevColumn = this.sortIndex+1;
979
+ @ if( cell.sortType>="A" && cell.sortType<="Z" ){
980
+ @ newRows.reverse();
981
+ @ }
980982
@ }
981983
@ for (i=0;i<newRows.length;i++) {
982984
@ this.tbody[0].appendChild(newRows[i]);
983985
@ }
984986
@ this.setHdrIcons();
@@ -1002,27 +1004,28 @@
10021004
@ }
10031005
@ this.sortText = function(a,b) {
10041006
@ var i = thisObject.sortIndex;
10051007
@ aa = a.cells[i].textContent.replace(/^\W+/,'').toLowerCase();
10061008
@ bb = b.cells[i].textContent.replace(/^\W+/,'').toLowerCase();
1007
- @ if(aa==bb) return 0;
1009
+ @ if(aa==bb) return a.rowIndex-b.rowIndex;
10081010
@ if(aa<bb) return -1;
10091011
@ return 1;
10101012
@ }
10111013
@ this.sortNumeric = function(a,b) {
10121014
@ var i = thisObject.sortIndex;
10131015
@ aa = parseFloat(a.cells[i].textContent);
10141016
@ if (isNaN(aa)) aa = 0;
10151017
@ bb = parseFloat(b.cells[i].textContent);
10161018
@ if (isNaN(bb)) bb = 0;
1019
+ @ if(aa==bb) return a.rowIndex-b.rowIndex;
10171020
@ return aa-bb;
10181021
@ }
10191022
@ this.sortKey = function(a,b) {
10201023
@ var i = thisObject.sortIndex;
10211024
@ aa = a.cells[i].getAttribute("data-sortkey");
10221025
@ bb = b.cells[i].getAttribute("data-sortkey");
1023
- @ if(aa==bb) return 0;
1026
+ @ if(aa==bb) return a.rowIndex-b.rowIndex;
10241027
@ if(aa<bb) return -1;
10251028
@ return 1;
10261029
@ }
10271030
@ var x = tableEl.getElementsByTagName('thead');
10281031
@ if(!(this.tbody && this.tbody[0].rows && this.tbody[0].rows.length>0)){
10291032
--- 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 @@
165165
int i;
166166
167167
azDoc = fossil_malloc( sizeof(const char*)*(argc+1) );
168168
for(i=0; i<argc; i++) azDoc[i] = (const char*)sqlite3_value_text(argv[i]);
169169
score = search_score(p, argc, azDoc);
170
- fossil_free(azDoc);
170
+ fossil_free((void *)azDoc);
171171
sqlite3_result_int(context, score);
172172
}
173173
174174
/*
175175
** Register the "score()" SQL function to score its input text
176176
--- 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 @@
15251525
login_needed();
15261526
}
15271527
db_begin_transaction();
15281528
if( P("clear")!=0 ){
15291529
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"));
15311531
db_end_transaction(0);
15321532
cgi_redirect("setup_editcss");
15331533
}
15341534
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);
15361537
db_end_transaction(0);
15371538
cgi_redirect("setup_editcss");
15381539
}
15391540
style_header("Edit CSS");
15401541
@ <form action="%s(g.zTop)/setup_editcss" method="post"><div>
15411542
login_insert_csrf_secret();
15421543
@ 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);
15441546
@ <br />
15451547
@ <input type="submit" name="submit" value="Apply Changes" />
15461548
@ <input type="submit" name="clear" value="Revert To Default" />
15471549
@ </div></form>
15481550
@ <p><span class="note">Note:</span> Press your browser Reload button after
@@ -1568,15 +1570,17 @@
15681570
login_needed();
15691571
}
15701572
db_begin_transaction();
15711573
if( P("clear")!=0 ){
15721574
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"));
15741576
}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);
15761579
}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"));
15781582
char *zHead = strstr(z, "<head>");
15791583
if( strstr(z, "<base href=")==0 && zHead!=0 ){
15801584
char *zNew;
15811585
char *zTail = &zHead[6];
15821586
while( fossil_isspace(zTail[0]) ) zTail++;
@@ -1598,14 +1602,15 @@
15981602
@ <tt>&lt;head&gt;</tt> in the header!
15991603
@ <input type="submit" name="fixbase" value="Add &lt;base&gt; Now"></p>
16001604
}
16011605
16021606
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
16041608
@ generate the beginning of every page through start of the main
16051609
@ 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);
16071612
@ <br />
16081613
@ <input type="submit" name="submit" value="Apply Changes" />
16091614
@ <input type="submit" name="clear" value="Revert To Default" />
16101615
@ </div></form>
16111616
@ <hr />
@@ -1612,11 +1617,11 @@
16121617
@ The default header is shown below for reference. Other examples
16131618
@ of headers can be seen on the <a href="setup_skin">skins page</a>.
16141619
@ See also the <a href="setup_editcss">CSS</a> and
16151620
@ <a href="setup_footer">footer</a> editing screens.
16161621
@ <blockquote><pre>
1617
- @ %h(zDefaultHeader)
1622
+ @ %h(builtin_text("skins/default.header"))
16181623
@ </pre></blockquote>
16191624
style_footer();
16201625
db_end_transaction(0);
16211626
}
16221627
@@ -1629,19 +1634,20 @@
16291634
login_needed();
16301635
}
16311636
db_begin_transaction();
16321637
if( P("clear")!=0 ){
16331638
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"));
16351640
}
16361641
16371642
style_header("Edit Page Footer");
16381643
@ <form action="%s(g.zTop)/setup_footer" method="post"><div>
16391644
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
16411646
@ 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);
16431649
@ <br />
16441650
@ <input type="submit" name="submit" value="Apply Changes" />
16451651
@ <input type="submit" name="clear" value="Revert To Default" />
16461652
@ </div></form>
16471653
@ <hr />
@@ -1648,11 +1654,11 @@
16481654
@ The default footer is shown below for reference. Other examples
16491655
@ of footers can be seen on the <a href="setup_skin">skins page</a>.
16501656
@ See also the <a href="setup_editcss">CSS</a> and
16511657
@ <a href="setup_header">header</a> editing screens.
16521658
@ <blockquote><pre>
1653
- @ %h(zDefaultFooter)
1659
+ @ %h(builtin_text("skins/default.footer"))
16541660
@ </pre></blockquote>
16551661
style_footer();
16561662
db_end_transaction(0);
16571663
}
16581664
@@ -1715,13 +1721,15 @@
17151721
}
17161722
17171723
style_header("Edit Ad Unit");
17181724
@ <form action="%s(g.zTop)/setup_adunit" method="post"><div>
17191725
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);
17231731
@ <br />
17241732
onoff_attribute("Omit ads to administrator",
17251733
"adunit-omit-if-admin", "oia", 0, 0);
17261734
@ <br />
17271735
onoff_attribute("Omit ads to logged-in users",
@@ -1728,10 +1736,41 @@
17281736
"adunit-omit-if-user", "oiu", 0, 0);
17291737
@ <br />
17301738
@ <input type="submit" name="submit" value="Apply Changes" />
17311739
@ <input type="submit" name="clear" value="Delete Ad-Unit" />
17321740
@ </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
+ @ &lt;div style='
1764
+ @ margin: 0 auto;
1765
+ @ width: 600px;
1766
+ @ height: 90px;
1767
+ @ border: 1px solid #f11;
1768
+ @ background-color: #fcc;
1769
+ @ '&gt;Demo Ad&lt;/div&gt;
1770
+ @ </pre></blockquote>
1771
+ @ </li>
17331772
style_footer();
17341773
db_end_transaction(0);
17351774
}
17361775
17371776
/*
17381777
--- 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>&lt;head&gt;</tt> in the header!
1599 @ <input type="submit" name="fixbase" value="Add &lt;base&gt; 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>&lt;head&gt;</tt> in the header!
1603 @ <input type="submit" name="fixbase" value="Add &lt;base&gt; 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 @ &lt;div style='
1764 @ margin: 0 auto;
1765 @ width: 600px;
1766 @ height: 90px;
1767 @ border: 1px solid #f11;
1768 @ background-color: #fcc;
1769 @ '&gt;Demo Ad&lt;/div&gt;
1770 @ </pre></blockquote>
1771 @ </li>
1772 style_footer();
1773 db_end_transaction(0);
1774 }
1775
1776 /*
1777
--- src/sitemap.c
+++ src/sitemap.c
@@ -27,10 +27,11 @@
2727
** Show an incomplete list of web pages offered by the Fossil web engine.
2828
*/
2929
void sitemap_page(void){
3030
login_check_credentials();
3131
style_header("Site Map");
32
+ style_adunit_config(ADUNIT_RIGHT_OK);
3233
@ <p>
3334
@ The following links are just a few of the many web-pages available for
3435
@ this Fossil repository:
3536
@ </p>
3637
@
3738
--- 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 @@
1919
*/
2020
#include "config.h"
2121
#include <assert.h>
2222
#include "skins.h"
2323
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&amp;y=ci">$manifest_date</a>
1251
-@ </div>
1252
-@ </body></html>
1253
-@ ');
1254
-;
1255
-
125624
/*
125725
** 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.
125838
*/
125939
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 */
126243
} 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 },
126952
};
127053
127154
/*
127255
** For a skin named zSkinName, compute the name of the CONFIG table
127356
** entry where that skin is stored and return it.
@@ -1286,57 +69,158 @@
128669
}
128770
return z;
128871
}
128972
129073
/*
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.
129390
**
129491
** Memory to hold the returned string is obtained from malloc.
129592
*/
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;
129798
Blob val;
129899
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
+ }
1311118
return blob_str(&val);
1312119
}
1313120
1314121
/*
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.
1317165
*/
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;
1320199
}
1321200
1322201
/*
1323202
** WEBPAGE: setup_skin
1324203
*/
1325204
void setup_skin(void){
1326205
const char *z;
1327206
char *zName;
1328207
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 */
1331210
Stmt q;
211
+ int seenCurrent = 0;
1332212
1333213
login_check_credentials();
1334214
if( !g.perm.Setup ){
1335215
login_needed();
1336216
}
1337217
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
+ }
1338222
1339223
/* Process requests to delete a user-defined skin */
1340224
if( P("del1") && (zName = skinVarName(P("sn"), 1))!=0 ){
1341225
style_header("Confirm Custom Skin Delete");
1342226
@ <form action="%s(g.zTop)/setup_skin" method="post"><div>
@@ -1351,51 +235,42 @@
1351235
return;
1352236
}
1353237
if( P("del2")!=0 && (zName = skinVarName(P("sn"), 1))!=0 ){
1354238
db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
1355239
}
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. */
1373244
if( P("load") && (z = P("sn"))!=0 && z[0] ){
1374245
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);
1375250
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 ){
1377252
seen = 1;
1378253
break;
1379254
}
1380255
}
1381256
if( !seen ){
1382257
seen = db_exists("SELECT 1 FROM config WHERE name GLOB 'skin:*'"
1383258
" 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
+ }
1391266
}
1392267
seen = 0;
1393268
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 ){
1395270
seen = 1;
1396
- zCurrent = aBuiltinSkin[i].zValue;
271
+ zCurrent = aBuiltinSkin[i].zSQL;
1397272
db_multi_exec("%s", zCurrent/*safe-for-%s*/);
1398273
break;
1399274
}
1400275
}
1401276
if( !seen ){
@@ -1409,48 +284,59 @@
1409284
if( zErr ){
1410285
@ <p><font color="red">%h(zErr)</font></p>
1411286
}
1412287
@ <p>A "skin" is a combination of
1413288
@ <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
1417291
@ of the web interface.</p>
1418292
@
1419293
@ <h2>Available Skins:</h2>
1420
- @ <ol>
294
+ @ <table border="0">
1421295
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).&nbsp;&nbsp; <b>Currently In Use</b></p>
296
+ z = aBuiltinSkin[i].zDesc;
297
+ @ <tr><td>%d(i+1).<td>%h(z)<td>&nbsp;&nbsp;<td>
298
+ if( fossil_strcmp(aBuiltinSkin[i].zSQL, zCurrent)==0 ){
299
+ @ (Currently In Use)
300
+ seenCurrent = 1;
1425301
}else{
1426
- @ <li><form action="%s(g.zTop)/setup_skin" method="post"><div>
1427
- @ %h(z).&nbsp;&nbsp;
302
+ @ <form action="%s(g.zTop)/setup_skin" method="post">
1428303
@ <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>
1431306
}
307
+ @ </tr>
1432308
}
1433309
db_prepare(&q,
1434310
"SELECT substr(name, 6), value FROM config"
1435311
" WHERE name GLOB 'skin:*'"
1436312
" ORDER BY name"
1437313
);
1438314
while( db_step(&q)==SQLITE_ROW ){
1439315
const char *zN = db_column_text(&q, 0);
1440316
const char *zV = db_column_text(&q, 1);
1441
- if( fossil_strcmp(zV, zCurrent)==0 ){
1442
- @ <li><p>%h(zN).&nbsp;&nbsp; <b>Currently In Use</b></p>
1443
- }else{
1444
- @ <li><form action="%s(g.zTop)/setup_skin" method="post">
1445
- @ %h(zN).&nbsp;&nbsp;
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>&nbsp;&nbsp;<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>
1451330
}
1452331
db_finalize(&q);
1453
- @ </ol>
332
+ if( !seenCurrent ){
333
+ i++;
334
+ @ <tr><td>%d(i).<td><i>Current Configuration</i><td>&nbsp;&nbsp;<td>
335
+ @ <form action="%s(g.zTop)/setup_skin" method="post">
336
+ @ <input type="submit" name="save" value="Save">
337
+ @ </form>
338
+ }
339
+ @ </table>
1454340
style_footer();
1455341
db_end_transaction(0);
1456342
}
1457343
--- 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&amp;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).&nbsp;&nbsp; <b>Currently In Use</b></p>
 
 
1425 }else{
1426 @ <li><form action="%s(g.zTop)/setup_skin" method="post"><div>
1427 @ %h(z).&nbsp;&nbsp;
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).&nbsp;&nbsp; <b>Currently In Use</b></p>
1443 }else{
1444 @ <li><form action="%s(g.zTop)/setup_skin" method="post">
1445 @ %h(zN).&nbsp;&nbsp;
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>&nbsp;&nbsp;<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>&nbsp;&nbsp;<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>&nbsp;&nbsp;<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
--- src/sqlcmd.c
+++ src/sqlcmd.c
@@ -170,10 +170,12 @@
170170
** checkin_mtime(X,Y) Return the mtime for the file Y (a BLOB.RID)
171171
** found in check-in X (another BLOB.RID value).
172172
**
173173
** symbolic_name_to_rid(X) Return a the BLOB.RID corresponding to symbolic
174174
** name X.
175
+**
176
+** now() Return the number of seconds since 1970.
175177
**
176178
** REGEXP The REGEXP operator works, unlike in
177179
** standard SQLite.
178180
**
179181
** files_of_checkin The "files_of_check" virtual table is
180182
--- 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 @@
11
/******************************************************************************
22
** 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
44
** single large file, the entire code can be compiled as a single translation
55
** unit. This allows many compilers to do optimizations that would not be
66
** possible if the files were compiled separately. Performance improvements
77
** of 5% or more are commonly seen when SQLite is compiled as a single
88
** translation unit.
@@ -276,13 +276,13 @@
276276
**
277277
** See also: [sqlite3_libversion()],
278278
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
279279
** [sqlite_version()] and [sqlite_source_id()].
280280
*/
281
-#define SQLITE_VERSION "3.8.8"
281
+#define SQLITE_VERSION "3.8.8.1"
282282
#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"
284284
285285
/*
286286
** CAPI3REF: Run-Time Library Version Numbers
287287
** KEYWORDS: sqlite3_version, sqlite3_sourceid
288288
**
@@ -19870,10 +19870,21 @@
1987019870
# define SQLITE_WIN32_VOLATILE
1987119871
#else
1987219872
# define SQLITE_WIN32_VOLATILE volatile
1987319873
#endif
1987419874
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
+
1987519886
#endif /* _OS_WIN_H_ */
1987619887
1987719888
/************** End of os_win.h **********************************************/
1987819889
/************** Continuing where we left off in mutex_w32.c ******************/
1987919890
#endif
@@ -22433,11 +22444,11 @@
2243322444
#endif /* SQLITE_OS_UNIX && defined(SQLITE_MUTEX_PTHREADS) */
2243422445
/******************************** End Unix Pthreads *************************/
2243522446
2243622447
2243722448
/********************************* Win32 Threads ****************************/
22438
-#if SQLITE_OS_WIN && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_THREADSAFE>0
22449
+#if SQLITE_OS_WIN_THREADS
2243922450
2244022451
#define SQLITE_THREADS_IMPLEMENTED 1 /* Prevent the single-thread code below */
2244122452
#include <process.h>
2244222453
2244322454
/* A running thread */
@@ -22526,11 +22537,11 @@
2252622537
if( rc==WAIT_OBJECT_0 ) *ppOut = p->pResult;
2252722538
sqlite3_free(p);
2252822539
return (rc==WAIT_OBJECT_0) ? SQLITE_OK : SQLITE_ERROR;
2252922540
}
2253022541
22531
-#endif /* SQLITE_OS_WIN && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT */
22542
+#endif /* SQLITE_OS_WIN_THREADS */
2253222543
/******************************** End Win32 Threads *************************/
2253322544
2253422545
2253522546
/********************************* Single-Threaded **************************/
2253622547
#ifndef SQLITE_THREADS_IMPLEMENTED
@@ -67496,10 +67507,45 @@
6749667507
if( pKeyInfo->db->mallocFailed ) return 1;
6749767508
return 0;
6749867509
}
6749967510
#endif
6750067511
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
+
6750167547
/*
6750267548
** Both *pMem1 and *pMem2 contain string values. Compare the two values
6750367549
** using the collation sequence pColl. As usual, return a negative , zero
6750467550
** or positive value if *pMem1 is less than, equal to or greater than
6750567551
** *pMem2, respectively. Similar in spirit to "rc = (*pMem1) - (*pMem2);".
@@ -67907,10 +67953,11 @@
6790767953
u32 y;
6790867954
u64 x;
6790967955
i64 v = pPKey2->aMem[0].u.i;
6791067956
i64 lhs;
6791167957
67958
+ vdbeAssertFieldCountWithinLimits(nKey1, pKey1, pPKey2->pKeyInfo);
6791267959
assert( (*(u8*)pKey1)<=0x3F || CORRUPT_DB );
6791367960
switch( serial_type ){
6791467961
case 1: { /* 1-byte signed integer */
6791567962
lhs = ONE_BYTE_INT(aKey);
6791667963
testcase( lhs<0 );
@@ -67994,10 +68041,11 @@
6799468041
){
6799568042
const u8 *aKey1 = (const u8*)pKey1;
6799668043
int serial_type;
6799768044
int res;
6799868045
68046
+ vdbeAssertFieldCountWithinLimits(nKey1, pKey1, pPKey2->pKeyInfo);
6799968047
getVarint32(&aKey1[1], serial_type);
6800068048
if( serial_type<12 ){
6800168049
res = pPKey2->r1; /* (pKey1/nKey1) is a number or a null */
6800268050
}else if( !(serial_type & 0x01) ){
6800368051
res = pPKey2->r2; /* (pKey1/nKey1) is a blob */
@@ -105795,11 +105843,13 @@
105795105843
if( pParse->db->mallocFailed ) return;
105796105844
pOp->p2 = nKey + nData;
105797105845
pKI = pOp->p4.pKeyInfo;
105798105846
memset(pKI->aSortOrder, 0, pKI->nField); /* Makes OP_Jump below testable */
105799105847
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);
105801105851
addrJmp = sqlite3VdbeCurrentAddr(v);
105802105852
sqlite3VdbeAddOp3(v, OP_Jump, addrJmp+1, 0, addrJmp+1); VdbeCoverage(v);
105803105853
pSort->labelBkOut = sqlite3VdbeMakeLabel(v);
105804105854
pSort->regReturn = ++pParse->nMem;
105805105855
sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut);
@@ -106306,11 +106356,11 @@
106306106356
struct ExprList_item *pItem;
106307106357
sqlite3 *db = pParse->db;
106308106358
int i;
106309106359
106310106360
nExpr = pList->nExpr;
106311
- pInfo = sqlite3KeyInfoAlloc(db, nExpr+nExtra-iStart, 1);
106361
+ pInfo = sqlite3KeyInfoAlloc(db, nExpr-iStart, nExtra+1);
106312106362
if( pInfo ){
106313106363
assert( sqlite3KeyInfoIsWriteable(pInfo) );
106314106364
for(i=iStart, pItem=pList->a+iStart; i<nExpr; i++, pItem++){
106315106365
CollSeq *pColl;
106316106366
pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr);
@@ -110176,11 +110226,11 @@
110176110226
** we figure out that the sorting index is not needed. The addrSortIndex
110177110227
** variable is used to facilitate that change.
110178110228
*/
110179110229
if( sSort.pOrderBy ){
110180110230
KeyInfo *pKeyInfo;
110181
- pKeyInfo = keyInfoFromExprList(pParse, sSort.pOrderBy, 0, 0);
110231
+ pKeyInfo = keyInfoFromExprList(pParse, sSort.pOrderBy, 0, pEList->nExpr);
110182110232
sSort.iECursor = pParse->nTab++;
110183110233
sSort.addrSortIndex =
110184110234
sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
110185110235
sSort.iECursor, sSort.pOrderBy->nExpr+1+pEList->nExpr, 0,
110186110236
(char*)pKeyInfo, P4_KEYINFO
@@ -110350,11 +110400,11 @@
110350110400
** implement it. Allocate that sorting index now. If it turns out
110351110401
** that we do not need it after all, the OP_SorterOpen instruction
110352110402
** will be converted into a Noop.
110353110403
*/
110354110404
sAggInfo.sortingIdx = pParse->nTab++;
110355
- pKeyInfo = keyInfoFromExprList(pParse, pGroupBy, 0, 0);
110405
+ pKeyInfo = keyInfoFromExprList(pParse, pGroupBy, 0, sAggInfo.nColumn);
110356110406
addrSortingIdx = sqlite3VdbeAddOp4(v, OP_SorterOpen,
110357110407
sAggInfo.sortingIdx, sAggInfo.nSortingColumn,
110358110408
0, (char*)pKeyInfo, P4_KEYINFO);
110359110409
110360110410
/* Initialize memory locations used by GROUP BY aggregate processing
110361110411
--- 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 @@
105105
**
106106
** See also: [sqlite3_libversion()],
107107
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
108108
** [sqlite_version()] and [sqlite_source_id()].
109109
*/
110
-#define SQLITE_VERSION "3.8.8"
110
+#define SQLITE_VERSION "3.8.8.1"
111111
#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"
113113
114114
/*
115115
** CAPI3REF: Run-Time Library Version Numbers
116116
** KEYWORDS: sqlite3_version, sqlite3_sourceid
117117
**
118118
--- 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 @@
5555
5656
login_check_credentials();
5757
if( !g.perm.Read ){ login_needed(); return; }
5858
brief = P("brief")!=0;
5959
style_header("Repository Statistics");
60
+ style_adunit_config(ADUNIT_RIGHT_OK);
6061
if( g.perm.Admin ){
6162
style_submenu_element("URLs", "URLs and Checkouts", "urllist");
6263
style_submenu_element("Schema", "Repository Schema", "repo_schema");
6364
style_submenu_element("Web-Cache", "Web-Cache Stats", "cachestat");
6465
}
@@ -290,10 +291,11 @@
290291
int cnt;
291292
login_check_credentials();
292293
if( !g.perm.Admin ){ login_needed(); return; }
293294
294295
style_header("URLs and Checkouts");
296
+ style_adunit_config(ADUNIT_RIGHT_OK);
295297
style_submenu_element("Stat", "Repository Stats", "stat");
296298
style_submenu_element("Schema", "Repository Schema", "repo_schema");
297299
@ <div class="section">URLs</div>
298300
@ <table border="0" width='100%%'>
299301
db_prepare(&q, "SELECT substr(name,9), datetime(mtime,'unixepoch')"
@@ -336,10 +338,11 @@
336338
Stmt q;
337339
login_check_credentials();
338340
if( !g.perm.Admin ){ login_needed(); return; }
339341
340342
style_header("Repository Schema");
343
+ style_adunit_config(ADUNIT_RIGHT_OK);
341344
style_submenu_element("Stat", "Repository Stats", "stat");
342345
style_submenu_element("URLs", "URLs and Checkouts", "urllist");
343346
db_prepare(&q, "SELECT sql FROM %s.sqlite_master WHERE sql IS NOT NULL",
344347
db_name("repository"));
345348
@ <pre>
346349
--- 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 @@
4646
/*
4747
** remember, if a sidebox was used
4848
*/
4949
static int sideboxUsed = 0;
5050
51
+/*
52
+** Ad-unit styles.
53
+*/
54
+static unsigned adUnitFlags = 0;
55
+
5156
5257
/*
5358
** List of hyperlinks and forms that need to be resolved by javascript in
5459
** the footer.
5560
*/
@@ -284,11 +289,12 @@
284289
** Draw the header.
285290
*/
286291
void style_header(const char *zTitleFormat, ...){
287292
va_list ap;
288293
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");
290296
login_check_credentials();
291297
292298
va_start(ap, zTitleFormat);
293299
zTitle = vmprintf(zTitleFormat, ap);
294300
va_end(ap);
@@ -343,34 +349,64 @@
343349
@ var e = document.getElementById(x);
344350
@ if(!e) throw new Error("Expecting element with ID "+x);
345351
@ else return e;}
346352
@ </script>
347353
}
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
+}
348368
349369
/*
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.
351375
*/
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 */
354380
if( g.perm.Admin && db_get_boolean("adunit-omit-if-admin",0) ){
355
- return;
381
+ return 0;
356382
}
357383
if( !login_is_nobody()
358384
&& fossil_strcmp(g.zLogin,"anonymous")!=0
359385
&& db_get_boolean("adunit-omit-if-user",0)
360386
){
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;
362397
}
363
- zAd = db_get("adunit", 0);
364
- if( zAd ) cgi_append_content(zAd, -1);
398
+ return 0;
365399
}
366400
367401
/*
368402
** Draw the footer at the bottom of the page.
369403
*/
370404
void style_footer(void){
371405
const char *zFooter;
406
+ const char *zAd = 0;
407
+ unsigned int mAdFlags = 0;
372408
373409
if( !headerHasBeenGenerated ) return;
374410
375411
/* Go back and put the submenu at the top of the page. We delay the
376412
** creation of the submenu until the end so that we can add elements
@@ -389,12 +425,25 @@
389425
@ <a class="label" href="%h(p->zLink)">%h(p->zLabel)</a>
390426
}
391427
}
392428
@ </div>
393429
}
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
+ }
396445
cgi_destination(CGI_BODY);
397446
398447
if( sideboxUsed ){
399448
/* Put the footer at the bottom of the page.
400449
** the additional clear/both is needed to extend the content
@@ -406,11 +455,12 @@
406455
407456
/* Set the href= field on hyperlinks. Do this before the footer since
408457
** the footer will be generating </html> */
409458
style_resolve_href();
410459
411
- zFooter = db_get("footer", (char*)zDefaultFooter);
460
+ zFooter = db_get("footer", 0);
461
+ if( zFooter==0 ) zFooter = builtin_text("skins/default/footer.txt");
412462
if( g.thTrace ) Th_Trace("BEGIN_FOOTER<br />\n", -1);
413463
Th_Render(zFooter);
414464
if( g.thTrace ) Th_Trace("END_FOOTER<br />\n", -1);
415465
416466
/* Render trace log if TH1 tracing is enabled. */
@@ -436,230 +486,10 @@
436486
*/
437487
void style_sidebox_end(void){
438488
@ </div>
439489
}
440490
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
-
661491
662492
/* The following table contains bits of default CSS that must
663493
** be included if they are not found in the application-defined
664494
** CSS.
665495
*/
@@ -666,14 +496,10 @@
666496
const struct strctCssDefaults {
667497
const char *elementClass; /* Name of element needed */
668498
const char *comment; /* Comment text */
669499
const char *value; /* CSS text */
670500
} cssDefaultList[] = {
671
- { "",
672
- "",
673
- zDefaultCSS
674
- },
675501
{ "div.sidebox",
676502
"The nomenclature sidebox for branches,..",
677503
@ float: right;
678504
@ background-color: white;
679505
@ border-width: medium;
@@ -1279,10 +1105,11 @@
12791105
@ text-align: left;
12801106
@ padding: 0px 1em 0.5ex 0px;
12811107
},
12821108
{ ".brlist table td", "Branch list table headers",
12831109
@ padding: 0px 2em 0px 0px;
1110
+ @ white-space: nowrap;
12841111
},
12851112
{ "th.sort:after",
12861113
"General styles for sortable column marker",
12871114
@ margin-left: .4em;
12881115
@ cursor: pointer;
@@ -1310,19 +1137,16 @@
13101137
** Append all of the default CSS to the CGI output.
13111138
*/
13121139
void cgi_append_default_css(void) {
13131140
int i;
13141141
1142
+ cgi_printf("%s", builtin_text("skins/default/css.txt"));
13151143
for( i=0; cssDefaultList[i].elementClass; i++ ){
13161144
if( cssDefaultList[i].elementClass[0] ){
13171145
cgi_printf("/* %s */\n%s {\n%s\n}\n\n",
13181146
cssDefaultList[i].comment,
13191147
cssDefaultList[i].elementClass,
1320
- cssDefaultList[i].value
1321
- );
1322
- }else{
1323
- cgi_printf("%s",
13241148
cssDefaultList[i].value
13251149
);
13261150
}
13271151
}
13281152
}
@@ -1333,11 +1157,11 @@
13331157
void page_style_css(void){
13341158
Blob css;
13351159
int i;
13361160
13371161
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);
13391163
13401164
/* add special missing definitions */
13411165
for(i=1; cssDefaultList[i].elementClass; i++){
13421166
if( strstr(blob_str(&css), cssDefaultList[i].elementClass)==0 ){
13431167
blob_appendf(&css, "/* %s */\n%s {\n%s}\n",
13441168
--- 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 @@
535535
tag_cmd_usage:
536536
usage("add|cancel|find|list ...");
537537
}
538538
539539
/*
540
-** WEBPAGE: /taglist
540
+** WEBPAGE: taglist
541541
*/
542542
void taglist_page(void){
543543
Stmt q;
544544
545545
login_check_credentials();
@@ -546,10 +546,11 @@
546546
if( !g.perm.Read ){
547547
login_needed();
548548
}
549549
login_anonymous_available();
550550
style_header("Tags");
551
+ style_adunit_config(ADUNIT_RIGHT_OK);
551552
style_submenu_element("Timeline", "Timeline", "tagtimeline");
552553
@ <h2>Non-propagating tags:</h2>
553554
db_prepare(&q,
554555
"SELECT substr(tagname,5)"
555556
" FROM tag"
556557
--- 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
+1 -1
--- src/th.h
+++ src/th.h
@@ -1,8 +1,8 @@
11
22
/* 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
44
** exact clone.
55
*/
66
77
/*
88
** Before creating an interpreter, the application must allocate and
99
--- 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 @@
4242
**
4343
** Enhancement #2:
4444
**
4545
** Comments of the form: "/* @-comment: CC" cause CC to become a
4646
** 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).
4848
** Lines of subsequent @-blocks that begin with CC are omitted from the
4949
** output.
5050
**
5151
*/
5252
#include <stdio.h>
5353
--- 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 @@
362362
** feature.
363363
*/
364364
void url_proxy_options(void){
365365
zProxyOpt = find_option("proxy", 0, 1);
366366
if( find_option("nosync",0,0) ) g.fNoSync = 1;
367
+ if( find_option("ipv4",0,0) ) g.fIPv4 = 1;
367368
}
368369
369370
/*
370371
** If the "proxy" setting is defined, then change the URL settings
371372
** (initialized by a prior call to url_parse()) so that the HTTP
372373
--- 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 @@
467467
style_submenu_element("Newer", "Newer entries",
468468
"%s/access_log?o=%d&n=%d&y=%d", g.zTop, skip>=n ? skip-n : 0,
469469
n, y);
470470
}
471471
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>
475475
while( rc==SQLITE_OK && db_step(&q)==SQLITE_ROW ){
476476
const char *zName = db_column_text(&q, 0);
477477
const char *zIP = db_column_text(&q, 1);
478478
const char *zDate = db_column_text(&q, 2);
479479
int bSuccess = db_column_int(&q, 3);
@@ -492,11 +492,11 @@
492492
}
493493
if( skip>0 || cnt>n ){
494494
style_submenu_element("All", "All entries",
495495
"%s/access_log?n=10000000", g.zTop);
496496
}
497
- @ </table></center>
497
+ @ </tbody></table></center>
498498
db_finalize(&q);
499499
@ <hr>
500500
@ <form method="post" action="%s(g.zTop)/access_log">
501501
@ <label><input type="checkbox" name="delold">
502502
@ Delete all but the most recent 200 entries</input></label>
@@ -515,7 +515,8 @@
515515
@ <form method="post" action="%s(g.zTop)/access_log">
516516
@ <label><input type="checkbox" name="delall">
517517
@ Delete all entries</input></label>
518518
@ <input type="submit" name="delallbtn" value="Delete"></input>
519519
@ </form>
520
+ output_table_sorting_javascript("logtable", "Ttt", 1);
520521
style_footer();
521522
}
522523
--- 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 @@
331331
int fossil_is_uuid(const char *zSym){
332332
return zSym
333333
&& (UUID_SIZE==strlen(zSym))
334334
&& validate16(zSym, UUID_SIZE);
335335
}
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
+}
336346
--- 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 @@
19661966
g.clockSkewSeen = 1;
19671967
}
19681968
19691969
fossil_force_newline();
19701970
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);
19731973
transport_close(&g.url);
19741974
transport_global_shutdown(&g.url);
19751975
if( nErr && go==2 ){
19761976
db_multi_exec("DROP TABLE onremote");
19771977
manifest_crosslink_end(MC_PERMIT_HOOKS);
19781978
--- 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
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -146,12 +146,13 @@
146146
#### The directories where the OpenSSL include and library files are located.
147147
# The recommended usage here is to use the Sysinternals junction tool
148148
# to create a hard link between an "openssl-1.x" sub-directory of the
149149
# Fossil source code directory and the target OpenSSL source directory.
150150
#
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)
153154
154155
#### Either the directory where the Tcl library is installed or the Tcl
155156
# source code directory resides (depending on the value of the macro
156157
# FOSSIL_TCL_SOURCE). If this points to the Tcl install directory,
157158
# this directory must have "include" and "lib" sub-directories. If
@@ -483,10 +484,34 @@
483484
$(SRCDIR)/xfer.c \
484485
$(SRCDIR)/xfersetup.c \
485486
$(SRCDIR)/zip.c
486487
487488
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 \
488513
$(SRCDIR)/diff.tcl
489514
490515
TRANS_SRC = \
491516
$(OBJDIR)/add_.c \
492517
$(OBJDIR)/allrepo_.c \
493518
--- 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
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -146,12 +146,13 @@
146146
#### The directories where the OpenSSL include and library files are located.
147147
# The recommended usage here is to use the Sysinternals junction tool
148148
# to create a hard link between an "openssl-1.x" sub-directory of the
149149
# Fossil source code directory and the target OpenSSL source directory.
150150
#
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)
153154
154155
#### Either the directory where the Tcl library is installed or the Tcl
155156
# source code directory resides (depending on the value of the macro
156157
# FOSSIL_TCL_SOURCE). If this points to the Tcl install directory,
157158
# this directory must have "include" and "lib" sub-directories. If
@@ -483,10 +484,31 @@
483484
$(SRCDIR)/xfer.c \
484485
$(SRCDIR)/xfersetup.c \
485486
$(SRCDIR)/zip.c
486487
487488
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 \
488510
$(SRCDIR)/diff.tcl
489511
490512
TRANS_SRC = \
491513
$(OBJDIR)/add_.c \
492514
$(OBJDIR)/allrepo_.c \
493515
--- 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 @@
5555
5656
# Uncomment to enable Tcl support
5757
# FOSSIL_ENABLE_TCL = 1
5858
5959
!ifdef FOSSIL_ENABLE_SSL
60
-SSLDIR = $(B)\compat\openssl-1.0.1k
60
+SSLDIR = $(B)\compat\openssl-1.0.1l
6161
SSLINCDIR = $(SSLDIR)\inc32
6262
SSLLIBDIR = $(SSLDIR)\out32
6363
SSLLFLAGS = /nologo /opt:ref /debug
6464
SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib
6565
!if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64"
@@ -322,11 +322,35 @@
322322
wysiwyg_.c \
323323
xfer_.c \
324324
xfersetup_.c \
325325
zip_.c
326326
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
328352
329353
OBJ = $(OX)\add$O \
330354
$(OX)\allrepo$O \
331355
$(OX)\attach$O \
332356
$(OX)\bag$O \
333357
--- 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
--- win/include/unistd.h
+++ win/include/unistd.h
@@ -1,11 +1,11 @@
11
#ifndef _UNISTD_H
22
#define _UNISTD_H 1
33
4
-/* This file intended to serve as a drop-in replacement for
4
+/* This file intended to serve as a drop-in replacement for
55
* unistd.h on Windows
6
- * Please add functionality as neeeded
6
+ * Please add functionality as neeeded
77
*/
88
99
#include <stdlib.h>
1010
#include <io.h>
1111
#define srandom srand
1212
--- 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 @@
122122
the optional <a href="https://www.openssl.org/">OpenSSL</a> support,
123123
first <a href="https://www.openssl.org/source/">download the official
124124
source code for OpenSSL</a> and extract it to an appropriately named
125125
"<b>openssl-X.Y.ZA</b>" subdirectory within the local
126126
[/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
128128
<a href="http://www.perl.org/">Perl</a> binaries are installed locally,
129129
and finally run one of the following commands:
130130
<blockquote><pre>
131131
nmake /f Makefile.msc FOSSIL_ENABLE_SSL=1 FOSSIL_BUILD_SSL=1 PERLDIR=C:\full\path\to\Perl\bin
132132
</pre></blockquote>
133133
--- 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

Keyboard Shortcuts

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