Fossil SCM

Improvements to login/logout processing: (1) When the user is "nobody", show hyperlinks to pages that require "anonymous" but have those links redirect to the /login page. (2) Clean up the /login page - less verbage. (3) Redirects from /login to /tarball or /zip provide a button to press, rather than immediately starting the download.

drh 2015-02-14 15:06 trunk merge
Commit 653dd402eafe152df9168ebf4a680fcac1ff6078
--- skins/black_and_white/header.txt
+++ skins/black_and_white/header.txt
@@ -26,21 +26,21 @@
2626
<th1>
2727
html "<a href='$home$index_page'>Home</a>\n"
2828
if {[anycap jor]} {
2929
html "<a href='$home/timeline'>Timeline</a>\n"
3030
}
31
-if {[hascap oh]} {
31
+if {[anoncap oh]} {
3232
html "<a href='$home/tree?ci=tip'>Files</a>\n"
3333
}
34
-if {[hascap o]} {
34
+if {[anoncap o]} {
3535
html "<a href='$home/brlist'>Branches</a>\n"
3636
html "<a href='$home/taglist'>Tags</a>\n"
3737
}
38
-if {[hascap r]} {
38
+if {[anoncap r]} {
3939
html "<a href='$home/ticket'>Tickets</a>\n"
4040
}
41
-if {[hascap j]} {
41
+if {[anoncap j]} {
4242
html "<a href='$home/wiki'>Wiki</a>\n"
4343
}
4444
if {[hascap s]} {
4545
html "<a href='$home/setup'>Admin</a>\n"
4646
} elseif {[hascap a]} {
4747
--- skins/black_and_white/header.txt
+++ skins/black_and_white/header.txt
@@ -26,21 +26,21 @@
26 <th1>
27 html "<a href='$home$index_page'>Home</a>\n"
28 if {[anycap jor]} {
29 html "<a href='$home/timeline'>Timeline</a>\n"
30 }
31 if {[hascap oh]} {
32 html "<a href='$home/tree?ci=tip'>Files</a>\n"
33 }
34 if {[hascap o]} {
35 html "<a href='$home/brlist'>Branches</a>\n"
36 html "<a href='$home/taglist'>Tags</a>\n"
37 }
38 if {[hascap r]} {
39 html "<a href='$home/ticket'>Tickets</a>\n"
40 }
41 if {[hascap j]} {
42 html "<a href='$home/wiki'>Wiki</a>\n"
43 }
44 if {[hascap s]} {
45 html "<a href='$home/setup'>Admin</a>\n"
46 } elseif {[hascap a]} {
47
--- skins/black_and_white/header.txt
+++ skins/black_and_white/header.txt
@@ -26,21 +26,21 @@
26 <th1>
27 html "<a href='$home$index_page'>Home</a>\n"
28 if {[anycap jor]} {
29 html "<a href='$home/timeline'>Timeline</a>\n"
30 }
31 if {[anoncap oh]} {
32 html "<a href='$home/tree?ci=tip'>Files</a>\n"
33 }
34 if {[anoncap o]} {
35 html "<a href='$home/brlist'>Branches</a>\n"
36 html "<a href='$home/taglist'>Tags</a>\n"
37 }
38 if {[anoncap r]} {
39 html "<a href='$home/ticket'>Tickets</a>\n"
40 }
41 if {[anoncap j]} {
42 html "<a href='$home/wiki'>Wiki</a>\n"
43 }
44 if {[hascap s]} {
45 html "<a href='$home/setup'>Admin</a>\n"
46 } elseif {[hascap a]} {
47
--- skins/default/header.txt
+++ skins/default/header.txt
@@ -25,21 +25,21 @@
2525
<th1>
2626
html "<a href='$home$index_page'>Home</a>\n"
2727
if {[anycap jor]} {
2828
html "<a href='$home/timeline'>Timeline</a>\n"
2929
}
30
-if {[hascap oh]} {
30
+if {[anoncap oh]} {
3131
html "<a href='$home/tree?ci=tip'>Files</a>\n"
3232
}
33
-if {[hascap o]} {
33
+if {[anoncap o]} {
3434
html "<a href='$home/brlist'>Branches</a>\n"
3535
html "<a href='$home/taglist'>Tags</a>\n"
3636
}
37
-if {[hascap r]} {
37
+if {[anoncap r]} {
3838
html "<a href='$home/ticket'>Tickets</a>\n"
3939
}
40
-if {[hascap j]} {
40
+if {[anoncap j]} {
4141
html "<a href='$home/wiki'>Wiki</a>\n"
4242
}
4343
if {[hascap s]} {
4444
html "<a href='$home/setup'>Admin</a>\n"
4545
} elseif {[hascap a]} {
4646
--- skins/default/header.txt
+++ skins/default/header.txt
@@ -25,21 +25,21 @@
25 <th1>
26 html "<a href='$home$index_page'>Home</a>\n"
27 if {[anycap jor]} {
28 html "<a href='$home/timeline'>Timeline</a>\n"
29 }
30 if {[hascap oh]} {
31 html "<a href='$home/tree?ci=tip'>Files</a>\n"
32 }
33 if {[hascap o]} {
34 html "<a href='$home/brlist'>Branches</a>\n"
35 html "<a href='$home/taglist'>Tags</a>\n"
36 }
37 if {[hascap r]} {
38 html "<a href='$home/ticket'>Tickets</a>\n"
39 }
40 if {[hascap j]} {
41 html "<a href='$home/wiki'>Wiki</a>\n"
42 }
43 if {[hascap s]} {
44 html "<a href='$home/setup'>Admin</a>\n"
45 } elseif {[hascap a]} {
46
--- skins/default/header.txt
+++ skins/default/header.txt
@@ -25,21 +25,21 @@
25 <th1>
26 html "<a href='$home$index_page'>Home</a>\n"
27 if {[anycap jor]} {
28 html "<a href='$home/timeline'>Timeline</a>\n"
29 }
30 if {[anoncap oh]} {
31 html "<a href='$home/tree?ci=tip'>Files</a>\n"
32 }
33 if {[anoncap o]} {
34 html "<a href='$home/brlist'>Branches</a>\n"
35 html "<a href='$home/taglist'>Tags</a>\n"
36 }
37 if {[anoncap r]} {
38 html "<a href='$home/ticket'>Tickets</a>\n"
39 }
40 if {[anoncap j]} {
41 html "<a href='$home/wiki'>Wiki</a>\n"
42 }
43 if {[hascap s]} {
44 html "<a href='$home/setup'>Admin</a>\n"
45 } elseif {[hascap a]} {
46
--- skins/eagle/header.txt
+++ skins/eagle/header.txt
@@ -106,21 +106,21 @@
106106
html "<a href='$home$index_page'>Home</a>\n"
107107
html "<a href='$home/help'>Help</a>\n"
108108
if {[anycap jor]} {
109109
html "<a href='$home/timeline'>Timeline</a>\n"
110110
}
111
-if {[hascap oh]} {
111
+if {[anoncap oh]} {
112112
html "<a href='$home/tree?ci=tip'>Files</a>\n"
113113
}
114
-if {[hascap o]} {
114
+if {[anoncap o]} {
115115
html "<a href='$home/brlist'>Branches</a>\n"
116116
html "<a href='$home/taglist'>Tags</a>\n"
117117
}
118
-if {[hascap r]} {
118
+if {[anoncap r]} {
119119
html "<a href='$home/ticket'>Tickets</a>\n"
120120
}
121
-if {[hascap j]} {
121
+if {[anoncap j]} {
122122
html "<a href='$home/wiki'>Wiki</a>\n"
123123
}
124124
if {[hascap s]} {
125125
html "<a href='$home/setup'>Admin</a>\n"
126126
} elseif {[hascap a]} {
127127
--- skins/eagle/header.txt
+++ skins/eagle/header.txt
@@ -106,21 +106,21 @@
106 html "<a href='$home$index_page'>Home</a>\n"
107 html "<a href='$home/help'>Help</a>\n"
108 if {[anycap jor]} {
109 html "<a href='$home/timeline'>Timeline</a>\n"
110 }
111 if {[hascap oh]} {
112 html "<a href='$home/tree?ci=tip'>Files</a>\n"
113 }
114 if {[hascap o]} {
115 html "<a href='$home/brlist'>Branches</a>\n"
116 html "<a href='$home/taglist'>Tags</a>\n"
117 }
118 if {[hascap r]} {
119 html "<a href='$home/ticket'>Tickets</a>\n"
120 }
121 if {[hascap j]} {
122 html "<a href='$home/wiki'>Wiki</a>\n"
123 }
124 if {[hascap s]} {
125 html "<a href='$home/setup'>Admin</a>\n"
126 } elseif {[hascap a]} {
127
--- skins/eagle/header.txt
+++ skins/eagle/header.txt
@@ -106,21 +106,21 @@
106 html "<a href='$home$index_page'>Home</a>\n"
107 html "<a href='$home/help'>Help</a>\n"
108 if {[anycap jor]} {
109 html "<a href='$home/timeline'>Timeline</a>\n"
110 }
111 if {[anoncap oh]} {
112 html "<a href='$home/tree?ci=tip'>Files</a>\n"
113 }
114 if {[anoncap o]} {
115 html "<a href='$home/brlist'>Branches</a>\n"
116 html "<a href='$home/taglist'>Tags</a>\n"
117 }
118 if {[anoncap r]} {
119 html "<a href='$home/ticket'>Tickets</a>\n"
120 }
121 if {[anoncap j]} {
122 html "<a href='$home/wiki'>Wiki</a>\n"
123 }
124 if {[hascap s]} {
125 html "<a href='$home/setup'>Admin</a>\n"
126 } elseif {[hascap a]} {
127
--- skins/enhanced1/header.txt
+++ skins/enhanced1/header.txt
@@ -106,21 +106,21 @@
106106
html "<a href='$home$index_page'>Home</a>\n"
107107
html "<a href='$home/help'>Help</a>\n"
108108
if {[anycap jor]} {
109109
html "<a href='$home/timeline'>Timeline</a>\n"
110110
}
111
-if {[hascap oh]} {
111
+if {[anoncap oh]} {
112112
html "<a href='$home/tree?ci=tip'>Files</a>\n"
113113
}
114
-if {[hascap o]} {
114
+if {[anoncap o]} {
115115
html "<a href='$home/brlist'>Branches</a>\n"
116116
html "<a href='$home/taglist'>Tags</a>\n"
117117
}
118
-if {[hascap r]} {
118
+if {[anoncap r]} {
119119
html "<a href='$home/ticket'>Tickets</a>\n"
120120
}
121
-if {[hascap j]} {
121
+if {[anoncap j]} {
122122
html "<a href='$home/wiki'>Wiki</a>\n"
123123
}
124124
if {[hascap s]} {
125125
html "<a href='$home/setup'>Admin</a>\n"
126126
} elseif {[hascap a]} {
127127
--- skins/enhanced1/header.txt
+++ skins/enhanced1/header.txt
@@ -106,21 +106,21 @@
106 html "<a href='$home$index_page'>Home</a>\n"
107 html "<a href='$home/help'>Help</a>\n"
108 if {[anycap jor]} {
109 html "<a href='$home/timeline'>Timeline</a>\n"
110 }
111 if {[hascap oh]} {
112 html "<a href='$home/tree?ci=tip'>Files</a>\n"
113 }
114 if {[hascap o]} {
115 html "<a href='$home/brlist'>Branches</a>\n"
116 html "<a href='$home/taglist'>Tags</a>\n"
117 }
118 if {[hascap r]} {
119 html "<a href='$home/ticket'>Tickets</a>\n"
120 }
121 if {[hascap j]} {
122 html "<a href='$home/wiki'>Wiki</a>\n"
123 }
124 if {[hascap s]} {
125 html "<a href='$home/setup'>Admin</a>\n"
126 } elseif {[hascap a]} {
127
--- skins/enhanced1/header.txt
+++ skins/enhanced1/header.txt
@@ -106,21 +106,21 @@
106 html "<a href='$home$index_page'>Home</a>\n"
107 html "<a href='$home/help'>Help</a>\n"
108 if {[anycap jor]} {
109 html "<a href='$home/timeline'>Timeline</a>\n"
110 }
111 if {[anoncap oh]} {
112 html "<a href='$home/tree?ci=tip'>Files</a>\n"
113 }
114 if {[anoncap o]} {
115 html "<a href='$home/brlist'>Branches</a>\n"
116 html "<a href='$home/taglist'>Tags</a>\n"
117 }
118 if {[anoncap r]} {
119 html "<a href='$home/ticket'>Tickets</a>\n"
120 }
121 if {[anoncap j]} {
122 html "<a href='$home/wiki'>Wiki</a>\n"
123 }
124 if {[hascap s]} {
125 html "<a href='$home/setup'>Admin</a>\n"
126 } elseif {[hascap a]} {
127
--- skins/etienne1/header.txt
+++ skins/etienne1/header.txt
@@ -65,21 +65,21 @@
6565
menulink "home" $index_page Home
6666
6767
if {[anycap jor]} {
6868
menulink "timeline" "/timeline" Timeline
6969
}
70
-if {[hascap oh]} {
70
+if {[anoncap oh]} {
7171
menulink "dir" "/dir?ci=tip" Files
7272
}
73
-if {[hascap o]} {
73
+if {[anoncap o]} {
7474
menulink "brlist" "/brlist" Branches
7575
menulink "taglist" "/taglist" Tags
7676
}
77
-if {[hascap r]} {
77
+if {[anoncap r]} {
7878
menulink "ticket" "/ticket" Tickets
7979
}
80
-if {[hascap j]} {
80
+if {[anoncap j]} {
8181
menulink "wiki" "/wiki" Wiki
8282
}
8383
if {[hascap s]} {
8484
menulink "setup" "/setup" Admin
8585
} elseif {[hascap a]} {
8686
--- skins/etienne1/header.txt
+++ skins/etienne1/header.txt
@@ -65,21 +65,21 @@
65 menulink "home" $index_page Home
66
67 if {[anycap jor]} {
68 menulink "timeline" "/timeline" Timeline
69 }
70 if {[hascap oh]} {
71 menulink "dir" "/dir?ci=tip" Files
72 }
73 if {[hascap o]} {
74 menulink "brlist" "/brlist" Branches
75 menulink "taglist" "/taglist" Tags
76 }
77 if {[hascap r]} {
78 menulink "ticket" "/ticket" Tickets
79 }
80 if {[hascap j]} {
81 menulink "wiki" "/wiki" Wiki
82 }
83 if {[hascap s]} {
84 menulink "setup" "/setup" Admin
85 } elseif {[hascap a]} {
86
--- skins/etienne1/header.txt
+++ skins/etienne1/header.txt
@@ -65,21 +65,21 @@
65 menulink "home" $index_page Home
66
67 if {[anycap jor]} {
68 menulink "timeline" "/timeline" Timeline
69 }
70 if {[anoncap oh]} {
71 menulink "dir" "/dir?ci=tip" Files
72 }
73 if {[anoncap o]} {
74 menulink "brlist" "/brlist" Branches
75 menulink "taglist" "/taglist" Tags
76 }
77 if {[anoncap r]} {
78 menulink "ticket" "/ticket" Tickets
79 }
80 if {[anoncap j]} {
81 menulink "wiki" "/wiki" Wiki
82 }
83 if {[hascap s]} {
84 menulink "setup" "/setup" Admin
85 } elseif {[hascap a]} {
86
--- skins/khaki/header.txt
+++ skins/khaki/header.txt
@@ -24,21 +24,21 @@
2424
<th1>
2525
html "<a href='$home$index_page'>Home</a>\n"
2626
if {[anycap jor]} {
2727
html "<a href='$home/timeline'>Timeline</a>\n"
2828
}
29
-if {[hascap oh]} {
29
+if {[anoncap oh]} {
3030
html "<a href='$home/tree?ci=tip'>Files</a>\n"
3131
}
32
-if {[hascap o]} {
32
+if {[anoncap o]} {
3333
html "<a href='$home/brlist'>Branches</a>\n"
3434
html "<a href='$home/taglist'>Tags</a>\n"
3535
}
36
-if {[hascap r]} {
36
+if {[anoncap r]} {
3737
html "<a href='$home/ticket'>Tickets</a>\n"
3838
}
39
-if {[hascap j]} {
39
+if {[anoncap j]} {
4040
html "<a href='$home/wiki'>Wiki</a>\n"
4141
}
4242
if {[hascap s]} {
4343
html "<a href='$home/setup'>Admin</a>\n"
4444
} elseif {[hascap a]} {
4545
--- skins/khaki/header.txt
+++ skins/khaki/header.txt
@@ -24,21 +24,21 @@
24 <th1>
25 html "<a href='$home$index_page'>Home</a>\n"
26 if {[anycap jor]} {
27 html "<a href='$home/timeline'>Timeline</a>\n"
28 }
29 if {[hascap oh]} {
30 html "<a href='$home/tree?ci=tip'>Files</a>\n"
31 }
32 if {[hascap o]} {
33 html "<a href='$home/brlist'>Branches</a>\n"
34 html "<a href='$home/taglist'>Tags</a>\n"
35 }
36 if {[hascap r]} {
37 html "<a href='$home/ticket'>Tickets</a>\n"
38 }
39 if {[hascap j]} {
40 html "<a href='$home/wiki'>Wiki</a>\n"
41 }
42 if {[hascap s]} {
43 html "<a href='$home/setup'>Admin</a>\n"
44 } elseif {[hascap a]} {
45
--- skins/khaki/header.txt
+++ skins/khaki/header.txt
@@ -24,21 +24,21 @@
24 <th1>
25 html "<a href='$home$index_page'>Home</a>\n"
26 if {[anycap jor]} {
27 html "<a href='$home/timeline'>Timeline</a>\n"
28 }
29 if {[anoncap oh]} {
30 html "<a href='$home/tree?ci=tip'>Files</a>\n"
31 }
32 if {[anoncap o]} {
33 html "<a href='$home/brlist'>Branches</a>\n"
34 html "<a href='$home/taglist'>Tags</a>\n"
35 }
36 if {[anoncap r]} {
37 html "<a href='$home/ticket'>Tickets</a>\n"
38 }
39 if {[anoncap j]} {
40 html "<a href='$home/wiki'>Wiki</a>\n"
41 }
42 if {[hascap s]} {
43 html "<a href='$home/setup'>Admin</a>\n"
44 } elseif {[hascap a]} {
45
--- skins/plain_gray/header.txt
+++ skins/plain_gray/header.txt
@@ -22,21 +22,21 @@
2222
<th1>
2323
html "<a href='$home$index_page'>Home</a>\n"
2424
if {[anycap jor]} {
2525
html "<a href='$home/timeline'>Timeline</a>\n"
2626
}
27
-if {[hascap oh]} {
27
+if {[anoncap oh]} {
2828
html "<a href='$home/tree?ci=tip'>Files</a>\n"
2929
}
30
-if {[hascap o]} {
30
+if {[anoncap o]} {
3131
html "<a href='$home/brlist'>Branches</a>\n"
3232
html "<a href='$home/taglist'>Tags</a>\n"
3333
}
34
-if {[hascap r]} {
34
+if {[anoncap r]} {
3535
html "<a href='$home/ticket'>Tickets</a>\n"
3636
}
37
-if {[hascap j]} {
37
+if {[anoncap j]} {
3838
html "<a href='$home/wiki'>Wiki</a>\n"
3939
}
4040
if {[hascap s]} {
4141
html "<a href='$home/setup'>Admin</a>\n"
4242
} elseif {[hascap a]} {
4343
--- skins/plain_gray/header.txt
+++ skins/plain_gray/header.txt
@@ -22,21 +22,21 @@
22 <th1>
23 html "<a href='$home$index_page'>Home</a>\n"
24 if {[anycap jor]} {
25 html "<a href='$home/timeline'>Timeline</a>\n"
26 }
27 if {[hascap oh]} {
28 html "<a href='$home/tree?ci=tip'>Files</a>\n"
29 }
30 if {[hascap o]} {
31 html "<a href='$home/brlist'>Branches</a>\n"
32 html "<a href='$home/taglist'>Tags</a>\n"
33 }
34 if {[hascap r]} {
35 html "<a href='$home/ticket'>Tickets</a>\n"
36 }
37 if {[hascap j]} {
38 html "<a href='$home/wiki'>Wiki</a>\n"
39 }
40 if {[hascap s]} {
41 html "<a href='$home/setup'>Admin</a>\n"
42 } elseif {[hascap a]} {
43
--- skins/plain_gray/header.txt
+++ skins/plain_gray/header.txt
@@ -22,21 +22,21 @@
22 <th1>
23 html "<a href='$home$index_page'>Home</a>\n"
24 if {[anycap jor]} {
25 html "<a href='$home/timeline'>Timeline</a>\n"
26 }
27 if {[anoncap oh]} {
28 html "<a href='$home/tree?ci=tip'>Files</a>\n"
29 }
30 if {[anoncap o]} {
31 html "<a href='$home/brlist'>Branches</a>\n"
32 html "<a href='$home/taglist'>Tags</a>\n"
33 }
34 if {[anoncap r]} {
35 html "<a href='$home/ticket'>Tickets</a>\n"
36 }
37 if {[anoncap j]} {
38 html "<a href='$home/wiki'>Wiki</a>\n"
39 }
40 if {[hascap s]} {
41 html "<a href='$home/setup'>Admin</a>\n"
42 } elseif {[hascap a]} {
43
--- skins/rounded1/header.txt
+++ skins/rounded1/header.txt
@@ -26,21 +26,21 @@
2626
<th1>
2727
html "<a href='$home$index_page'>Home</a>\n"
2828
if {[anycap jor]} {
2929
html "<a href='$home/timeline'>Timeline</a>\n"
3030
}
31
-if {[hascap oh]} {
31
+if {[anoncap oh]} {
3232
html "<a href='$home/tree?ci=tip'>Files</a>\n"
3333
}
34
-if {[hascap o]} {
34
+if {[anoncap o]} {
3535
html "<a href='$home/brlist'>Branches</a>\n"
3636
html "<a href='$home/taglist'>Tags</a>\n"
3737
}
38
-if {[hascap r]} {
38
+if {[anoncap r]} {
3939
html "<a href='$home/ticket'>Tickets</a>\n"
4040
}
41
-if {[hascap j]} {
41
+if {[anoncap j]} {
4242
html "<a href='$home/wiki'>Wiki</a>\n"
4343
}
4444
if {[hascap s]} {
4545
html "<a href='$home/setup'>Admin</a>\n"
4646
} elseif {[hascap a]} {
4747
--- skins/rounded1/header.txt
+++ skins/rounded1/header.txt
@@ -26,21 +26,21 @@
26 <th1>
27 html "<a href='$home$index_page'>Home</a>\n"
28 if {[anycap jor]} {
29 html "<a href='$home/timeline'>Timeline</a>\n"
30 }
31 if {[hascap oh]} {
32 html "<a href='$home/tree?ci=tip'>Files</a>\n"
33 }
34 if {[hascap o]} {
35 html "<a href='$home/brlist'>Branches</a>\n"
36 html "<a href='$home/taglist'>Tags</a>\n"
37 }
38 if {[hascap r]} {
39 html "<a href='$home/ticket'>Tickets</a>\n"
40 }
41 if {[hascap j]} {
42 html "<a href='$home/wiki'>Wiki</a>\n"
43 }
44 if {[hascap s]} {
45 html "<a href='$home/setup'>Admin</a>\n"
46 } elseif {[hascap a]} {
47
--- skins/rounded1/header.txt
+++ skins/rounded1/header.txt
@@ -26,21 +26,21 @@
26 <th1>
27 html "<a href='$home$index_page'>Home</a>\n"
28 if {[anycap jor]} {
29 html "<a href='$home/timeline'>Timeline</a>\n"
30 }
31 if {[anoncap oh]} {
32 html "<a href='$home/tree?ci=tip'>Files</a>\n"
33 }
34 if {[anoncap o]} {
35 html "<a href='$home/brlist'>Branches</a>\n"
36 html "<a href='$home/taglist'>Tags</a>\n"
37 }
38 if {[anoncap r]} {
39 html "<a href='$home/ticket'>Tickets</a>\n"
40 }
41 if {[anoncap j]} {
42 html "<a href='$home/wiki'>Wiki</a>\n"
43 }
44 if {[hascap s]} {
45 html "<a href='$home/setup'>Admin</a>\n"
46 } elseif {[hascap a]} {
47
+22 -10
--- src/attach.c
+++ src/attach.c
@@ -48,19 +48,22 @@
4848
" (SELECT uuid FROM blob WHERE rid=attachid), attachid"
4949
" FROM attachment",
5050
timeline_utc()
5151
);
5252
if( zPage ){
53
- if( g.perm.RdWiki==0 ) login_needed();
53
+ if( g.perm.RdWiki==0 ){ login_needed(g.anon.RdWiki); return; }
5454
style_header("Attachments To %h", zPage);
5555
blob_append_sql(&sql, " WHERE target=%Q", zPage);
5656
}else if( zTkt ){
57
- if( g.perm.RdTkt==0 ) login_needed();
57
+ if( g.perm.RdTkt==0 ){ login_needed(g.anon.RdTkt); return; }
5858
style_header("Attachments To Ticket %S", zTkt);
5959
blob_append_sql(&sql, " WHERE target GLOB '%q*'", zTkt);
6060
}else{
61
- if( g.perm.RdTkt==0 && g.perm.RdWiki==0 ) login_needed();
61
+ if( g.perm.RdTkt==0 && g.perm.RdWiki==0 ){
62
+ login_needed(g.anon.RdTkt || g.anon.RdWiki);
63
+ return;
64
+ }
6265
style_header("All Attachments");
6366
}
6467
blob_append_sql(&sql, " ORDER BY mtime DESC");
6568
db_prepare(&q, "%s", blob_sql_text(&sql));
6669
@ <ol>
@@ -150,14 +153,14 @@
150153
151154
if( zPage && zTkt ) zTkt = 0;
152155
if( zFile==0 ) fossil_redirect_home();
153156
login_check_credentials();
154157
if( zPage ){
155
- if( g.perm.RdWiki==0 ) login_needed();
158
+ if( g.perm.RdWiki==0 ){ login_needed(g.anon.RdWiki); return; }
156159
zTarget = zPage;
157160
}else if( zTkt ){
158
- if( g.perm.RdTkt==0 ) login_needed();
161
+ if( g.perm.RdTkt==0 ){ login_needed(g.anon.RdTkt); return; }
159162
zTarget = zTkt;
160163
}else{
161164
fossil_redirect_home();
162165
}
163166
if( attachid>0 ){
@@ -243,19 +246,25 @@
243246
if( P("cancel") ) cgi_redirect(zFrom);
244247
if( zPage && zTkt ) fossil_redirect_home();
245248
if( zPage==0 && zTkt==0 ) fossil_redirect_home();
246249
login_check_credentials();
247250
if( zPage ){
248
- if( g.perm.ApndWiki==0 || g.perm.Attach==0 ) login_needed();
251
+ if( g.perm.ApndWiki==0 || g.perm.Attach==0 ){
252
+ login_needed(g.anon.ApndWiki && g.anon.Attach);
253
+ return;
254
+ }
249255
if( !db_exists("SELECT 1 FROM tag WHERE tagname='wiki-%q'", zPage) ){
250256
fossil_redirect_home();
251257
}
252258
zTarget = zPage;
253259
zTargetType = mprintf("Wiki Page <a href=\"%R/wiki?name=%h\">%h</a>",
254260
zPage, zPage);
255261
}else{
256
- if( g.perm.ApndTkt==0 || g.perm.Attach==0 ) login_needed();
262
+ if( g.perm.ApndTkt==0 || g.perm.Attach==0 ){
263
+ login_needed(g.anon.ApndTkt && g.anon.Attach);
264
+ return;
265
+ }
257266
if( !db_exists("SELECT 1 FROM tag WHERE tagname='tkt-%q'", zTkt) ){
258267
zTkt = db_text(0, "SELECT substr(tagname,5) FROM tag"
259268
" WHERE tagname GLOB 'tkt-%q*'", zTkt);
260269
if( zTkt==0 ) fossil_redirect_home();
261270
}
@@ -369,11 +378,14 @@
369378
Blob attach; /* Content of the attachment */
370379
int fShowContent = 0;
371380
const char *zLn = P("ln");
372381
373382
login_check_credentials();
374
- if( !g.perm.RdTkt && !g.perm.RdWiki ){ login_needed(); return; }
383
+ if( !g.perm.RdTkt && !g.perm.RdWiki ){
384
+ login_needed(g.anon.RdTkt || g.anon.RdWiki);
385
+ return;
386
+ }
375387
rid = name_to_rid_www("name");
376388
if( rid==0 ){ fossil_redirect_home(); }
377389
zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
378390
#if 0
379391
/* Shunning here needs to get both the attachment control artifact and
@@ -399,17 +411,17 @@
399411
fShowContent = zMime ? strncmp(zMime,"text/", 5)==0 : 0;
400412
if( validate16(zTarget, strlen(zTarget))
401413
&& db_exists("SELECT 1 FROM ticket WHERE tkt_uuid='%q'", zTarget)
402414
){
403415
zTktUuid = zTarget;
404
- if( !g.perm.RdTkt ){ login_needed(); return; }
416
+ if( !g.perm.RdTkt ){ login_needed(g.anon.RdTkt); return; }
405417
if( g.perm.WrTkt ){
406418
style_submenu_element("Delete","Delete","%R/ainfo/%s?del", zUuid);
407419
}
408420
}else if( db_exists("SELECT 1 FROM tag WHERE tagname='wiki-%q'",zTarget) ){
409421
zWikiName = zTarget;
410
- if( !g.perm.RdWiki ){ login_needed(); return; }
422
+ if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; }
411423
if( g.perm.WrWiki ){
412424
style_submenu_element("Delete","Delete","%R/ainfo/%s?del", zUuid);
413425
}
414426
}
415427
zDate = db_text(0, "SELECT datetime(%.12f)", pAttach->rDate);
416428
--- src/attach.c
+++ src/attach.c
@@ -48,19 +48,22 @@
48 " (SELECT uuid FROM blob WHERE rid=attachid), attachid"
49 " FROM attachment",
50 timeline_utc()
51 );
52 if( zPage ){
53 if( g.perm.RdWiki==0 ) login_needed();
54 style_header("Attachments To %h", zPage);
55 blob_append_sql(&sql, " WHERE target=%Q", zPage);
56 }else if( zTkt ){
57 if( g.perm.RdTkt==0 ) login_needed();
58 style_header("Attachments To Ticket %S", zTkt);
59 blob_append_sql(&sql, " WHERE target GLOB '%q*'", zTkt);
60 }else{
61 if( g.perm.RdTkt==0 && g.perm.RdWiki==0 ) login_needed();
 
 
 
62 style_header("All Attachments");
63 }
64 blob_append_sql(&sql, " ORDER BY mtime DESC");
65 db_prepare(&q, "%s", blob_sql_text(&sql));
66 @ <ol>
@@ -150,14 +153,14 @@
150
151 if( zPage && zTkt ) zTkt = 0;
152 if( zFile==0 ) fossil_redirect_home();
153 login_check_credentials();
154 if( zPage ){
155 if( g.perm.RdWiki==0 ) login_needed();
156 zTarget = zPage;
157 }else if( zTkt ){
158 if( g.perm.RdTkt==0 ) login_needed();
159 zTarget = zTkt;
160 }else{
161 fossil_redirect_home();
162 }
163 if( attachid>0 ){
@@ -243,19 +246,25 @@
243 if( P("cancel") ) cgi_redirect(zFrom);
244 if( zPage && zTkt ) fossil_redirect_home();
245 if( zPage==0 && zTkt==0 ) fossil_redirect_home();
246 login_check_credentials();
247 if( zPage ){
248 if( g.perm.ApndWiki==0 || g.perm.Attach==0 ) login_needed();
 
 
 
249 if( !db_exists("SELECT 1 FROM tag WHERE tagname='wiki-%q'", zPage) ){
250 fossil_redirect_home();
251 }
252 zTarget = zPage;
253 zTargetType = mprintf("Wiki Page <a href=\"%R/wiki?name=%h\">%h</a>",
254 zPage, zPage);
255 }else{
256 if( g.perm.ApndTkt==0 || g.perm.Attach==0 ) login_needed();
 
 
 
257 if( !db_exists("SELECT 1 FROM tag WHERE tagname='tkt-%q'", zTkt) ){
258 zTkt = db_text(0, "SELECT substr(tagname,5) FROM tag"
259 " WHERE tagname GLOB 'tkt-%q*'", zTkt);
260 if( zTkt==0 ) fossil_redirect_home();
261 }
@@ -369,11 +378,14 @@
369 Blob attach; /* Content of the attachment */
370 int fShowContent = 0;
371 const char *zLn = P("ln");
372
373 login_check_credentials();
374 if( !g.perm.RdTkt && !g.perm.RdWiki ){ login_needed(); return; }
 
 
 
375 rid = name_to_rid_www("name");
376 if( rid==0 ){ fossil_redirect_home(); }
377 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
378 #if 0
379 /* Shunning here needs to get both the attachment control artifact and
@@ -399,17 +411,17 @@
399 fShowContent = zMime ? strncmp(zMime,"text/", 5)==0 : 0;
400 if( validate16(zTarget, strlen(zTarget))
401 && db_exists("SELECT 1 FROM ticket WHERE tkt_uuid='%q'", zTarget)
402 ){
403 zTktUuid = zTarget;
404 if( !g.perm.RdTkt ){ login_needed(); return; }
405 if( g.perm.WrTkt ){
406 style_submenu_element("Delete","Delete","%R/ainfo/%s?del", zUuid);
407 }
408 }else if( db_exists("SELECT 1 FROM tag WHERE tagname='wiki-%q'",zTarget) ){
409 zWikiName = zTarget;
410 if( !g.perm.RdWiki ){ login_needed(); return; }
411 if( g.perm.WrWiki ){
412 style_submenu_element("Delete","Delete","%R/ainfo/%s?del", zUuid);
413 }
414 }
415 zDate = db_text(0, "SELECT datetime(%.12f)", pAttach->rDate);
416
--- src/attach.c
+++ src/attach.c
@@ -48,19 +48,22 @@
48 " (SELECT uuid FROM blob WHERE rid=attachid), attachid"
49 " FROM attachment",
50 timeline_utc()
51 );
52 if( zPage ){
53 if( g.perm.RdWiki==0 ){ login_needed(g.anon.RdWiki); return; }
54 style_header("Attachments To %h", zPage);
55 blob_append_sql(&sql, " WHERE target=%Q", zPage);
56 }else if( zTkt ){
57 if( g.perm.RdTkt==0 ){ login_needed(g.anon.RdTkt); return; }
58 style_header("Attachments To Ticket %S", zTkt);
59 blob_append_sql(&sql, " WHERE target GLOB '%q*'", zTkt);
60 }else{
61 if( g.perm.RdTkt==0 && g.perm.RdWiki==0 ){
62 login_needed(g.anon.RdTkt || g.anon.RdWiki);
63 return;
64 }
65 style_header("All Attachments");
66 }
67 blob_append_sql(&sql, " ORDER BY mtime DESC");
68 db_prepare(&q, "%s", blob_sql_text(&sql));
69 @ <ol>
@@ -150,14 +153,14 @@
153
154 if( zPage && zTkt ) zTkt = 0;
155 if( zFile==0 ) fossil_redirect_home();
156 login_check_credentials();
157 if( zPage ){
158 if( g.perm.RdWiki==0 ){ login_needed(g.anon.RdWiki); return; }
159 zTarget = zPage;
160 }else if( zTkt ){
161 if( g.perm.RdTkt==0 ){ login_needed(g.anon.RdTkt); return; }
162 zTarget = zTkt;
163 }else{
164 fossil_redirect_home();
165 }
166 if( attachid>0 ){
@@ -243,19 +246,25 @@
246 if( P("cancel") ) cgi_redirect(zFrom);
247 if( zPage && zTkt ) fossil_redirect_home();
248 if( zPage==0 && zTkt==0 ) fossil_redirect_home();
249 login_check_credentials();
250 if( zPage ){
251 if( g.perm.ApndWiki==0 || g.perm.Attach==0 ){
252 login_needed(g.anon.ApndWiki && g.anon.Attach);
253 return;
254 }
255 if( !db_exists("SELECT 1 FROM tag WHERE tagname='wiki-%q'", zPage) ){
256 fossil_redirect_home();
257 }
258 zTarget = zPage;
259 zTargetType = mprintf("Wiki Page <a href=\"%R/wiki?name=%h\">%h</a>",
260 zPage, zPage);
261 }else{
262 if( g.perm.ApndTkt==0 || g.perm.Attach==0 ){
263 login_needed(g.anon.ApndTkt && g.anon.Attach);
264 return;
265 }
266 if( !db_exists("SELECT 1 FROM tag WHERE tagname='tkt-%q'", zTkt) ){
267 zTkt = db_text(0, "SELECT substr(tagname,5) FROM tag"
268 " WHERE tagname GLOB 'tkt-%q*'", zTkt);
269 if( zTkt==0 ) fossil_redirect_home();
270 }
@@ -369,11 +378,14 @@
378 Blob attach; /* Content of the attachment */
379 int fShowContent = 0;
380 const char *zLn = P("ln");
381
382 login_check_credentials();
383 if( !g.perm.RdTkt && !g.perm.RdWiki ){
384 login_needed(g.anon.RdTkt || g.anon.RdWiki);
385 return;
386 }
387 rid = name_to_rid_www("name");
388 if( rid==0 ){ fossil_redirect_home(); }
389 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
390 #if 0
391 /* Shunning here needs to get both the attachment control artifact and
@@ -399,17 +411,17 @@
411 fShowContent = zMime ? strncmp(zMime,"text/", 5)==0 : 0;
412 if( validate16(zTarget, strlen(zTarget))
413 && db_exists("SELECT 1 FROM ticket WHERE tkt_uuid='%q'", zTarget)
414 ){
415 zTktUuid = zTarget;
416 if( !g.perm.RdTkt ){ login_needed(g.anon.RdTkt); return; }
417 if( g.perm.WrTkt ){
418 style_submenu_element("Delete","Delete","%R/ainfo/%s?del", zUuid);
419 }
420 }else if( db_exists("SELECT 1 FROM tag WHERE tagname='wiki-%q'",zTarget) ){
421 zWikiName = zTarget;
422 if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; }
423 if( g.perm.WrWiki ){
424 style_submenu_element("Delete","Delete","%R/ainfo/%s?del", zUuid);
425 }
426 }
427 zDate = db_text(0, "SELECT datetime(%.12f)", pAttach->rDate);
428
+3 -3
--- src/branch.c
+++ src/branch.c
@@ -339,11 +339,11 @@
339339
*/
340340
static void new_brlist_page(void){
341341
Stmt q;
342342
double rNow;
343343
login_check_credentials();
344
- if( !g.perm.Read ){ login_needed(); return; }
344
+ if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
345345
style_header("Branches");
346346
style_adunit_config(ADUNIT_RIGHT_OK);
347347
login_anonymous_available();
348348
349349
db_prepare(&q, brlistQuery/*works-like:""*/);
@@ -408,11 +408,11 @@
408408
if( showClosed==0 && showAll==0 && showOpen==0 && colorTest==0 ){
409409
new_brlist_page();
410410
return;
411411
}
412412
login_check_credentials();
413
- if( !g.perm.Read ){ login_needed(); return; }
413
+ if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
414414
if( colorTest ){
415415
showClosed = 0;
416416
showAll = 1;
417417
}
418418
if( showAll ) brFlags = BRL_BOTH;
@@ -515,11 +515,11 @@
515515
*/
516516
void brtimeline_page(void){
517517
Stmt q;
518518
519519
login_check_credentials();
520
- if( !g.perm.Read ){ login_needed(); return; }
520
+ if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
521521
522522
style_header("Branches");
523523
style_submenu_element("List", "List", "brlist");
524524
login_anonymous_available();
525525
@ <h2>The initial check-in for each branch:</h2>
526526
--- src/branch.c
+++ src/branch.c
@@ -339,11 +339,11 @@
339 */
340 static void new_brlist_page(void){
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:""*/);
@@ -408,11 +408,11 @@
408 if( showClosed==0 && showAll==0 && showOpen==0 && colorTest==0 ){
409 new_brlist_page();
410 return;
411 }
412 login_check_credentials();
413 if( !g.perm.Read ){ login_needed(); return; }
414 if( colorTest ){
415 showClosed = 0;
416 showAll = 1;
417 }
418 if( showAll ) brFlags = BRL_BOTH;
@@ -515,11 +515,11 @@
515 */
516 void brtimeline_page(void){
517 Stmt q;
518
519 login_check_credentials();
520 if( !g.perm.Read ){ login_needed(); return; }
521
522 style_header("Branches");
523 style_submenu_element("List", "List", "brlist");
524 login_anonymous_available();
525 @ <h2>The initial check-in for each branch:</h2>
526
--- src/branch.c
+++ src/branch.c
@@ -339,11 +339,11 @@
339 */
340 static void new_brlist_page(void){
341 Stmt q;
342 double rNow;
343 login_check_credentials();
344 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
345 style_header("Branches");
346 style_adunit_config(ADUNIT_RIGHT_OK);
347 login_anonymous_available();
348
349 db_prepare(&q, brlistQuery/*works-like:""*/);
@@ -408,11 +408,11 @@
408 if( showClosed==0 && showAll==0 && showOpen==0 && colorTest==0 ){
409 new_brlist_page();
410 return;
411 }
412 login_check_credentials();
413 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
414 if( colorTest ){
415 showClosed = 0;
416 showAll = 1;
417 }
418 if( showAll ) brFlags = BRL_BOTH;
@@ -515,11 +515,11 @@
515 */
516 void brtimeline_page(void){
517 Stmt q;
518
519 login_check_credentials();
520 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
521
522 style_header("Branches");
523 style_submenu_element("List", "List", "brlist");
524 login_anonymous_available();
525 @ <h2>The initial check-in for each branch:</h2>
526
+3 -3
--- src/browse.c
+++ src/browse.c
@@ -130,11 +130,11 @@
130130
int linkTip = 1;
131131
HQuery sURI;
132132
133133
if( strcmp(PD("type","flat"),"tree")==0 ){ page_tree(); return; }
134134
login_check_credentials();
135
- if( !g.perm.Read ){ login_needed(); return; }
135
+ if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
136136
while( nD>1 && zD[nD-2]=='/' ){ zD[(--nD)-1] = 0; }
137137
style_header("File List");
138138
style_adunit_config(ADUNIT_RIGHT_OK);
139139
sqlite3_create_function(g.db, "pathelement", 2, SQLITE_UTF8, 0,
140140
pathelementFunc, 0, 0);
@@ -542,11 +542,11 @@
542542
char *zProjectName = db_get("project-name", 0);
543543
544544
if( strcmp(PD("type","flat"),"flat")==0 ){ page_dir(); return; }
545545
memset(&sTree, 0, sizeof(sTree));
546546
login_check_credentials();
547
- if( !g.perm.Read ){ login_needed(); return; }
547
+ if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
548548
while( nD>1 && zD[nD-2]=='/' ){ zD[(--nD)-1] = 0; }
549549
sqlite3_create_function(g.db, "pathelement", 2, SQLITE_UTF8, 0,
550550
pathelementFunc, 0, 0);
551551
url_initialize(&sURI, "tree");
552552
cgi_query_parameters_to_url(&sURI);
@@ -1002,11 +1002,11 @@
10021002
const char *zNow; /* Time of checkin */
10031003
int showId = PB("showid");
10041004
Stmt q1, q2;
10051005
double baseTime;
10061006
login_check_credentials();
1007
- if( !g.perm.Read ){ login_needed(); return; }
1007
+ if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
10081008
zName = P("name");
10091009
if( zName==0 ) zName = "tip";
10101010
rid = symbolic_name_to_rid(zName, "ci");
10111011
if( rid==0 ){
10121012
fossil_fatal("not a valid check-in: %s", zName);
10131013
--- src/browse.c
+++ src/browse.c
@@ -130,11 +130,11 @@
130 int linkTip = 1;
131 HQuery sURI;
132
133 if( strcmp(PD("type","flat"),"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);
@@ -542,11 +542,11 @@
542 char *zProjectName = db_get("project-name", 0);
543
544 if( strcmp(PD("type","flat"),"flat")==0 ){ page_dir(); return; }
545 memset(&sTree, 0, sizeof(sTree));
546 login_check_credentials();
547 if( !g.perm.Read ){ login_needed(); return; }
548 while( nD>1 && zD[nD-2]=='/' ){ zD[(--nD)-1] = 0; }
549 sqlite3_create_function(g.db, "pathelement", 2, SQLITE_UTF8, 0,
550 pathelementFunc, 0, 0);
551 url_initialize(&sURI, "tree");
552 cgi_query_parameters_to_url(&sURI);
@@ -1002,11 +1002,11 @@
1002 const char *zNow; /* Time of checkin */
1003 int showId = PB("showid");
1004 Stmt q1, q2;
1005 double baseTime;
1006 login_check_credentials();
1007 if( !g.perm.Read ){ login_needed(); return; }
1008 zName = P("name");
1009 if( zName==0 ) zName = "tip";
1010 rid = symbolic_name_to_rid(zName, "ci");
1011 if( rid==0 ){
1012 fossil_fatal("not a valid check-in: %s", zName);
1013
--- src/browse.c
+++ src/browse.c
@@ -130,11 +130,11 @@
130 int linkTip = 1;
131 HQuery sURI;
132
133 if( strcmp(PD("type","flat"),"tree")==0 ){ page_tree(); return; }
134 login_check_credentials();
135 if( !g.perm.Read ){ login_needed(g.anon.Read); 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);
@@ -542,11 +542,11 @@
542 char *zProjectName = db_get("project-name", 0);
543
544 if( strcmp(PD("type","flat"),"flat")==0 ){ page_dir(); return; }
545 memset(&sTree, 0, sizeof(sTree));
546 login_check_credentials();
547 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
548 while( nD>1 && zD[nD-2]=='/' ){ zD[(--nD)-1] = 0; }
549 sqlite3_create_function(g.db, "pathelement", 2, SQLITE_UTF8, 0,
550 pathelementFunc, 0, 0);
551 url_initialize(&sURI, "tree");
552 cgi_query_parameters_to_url(&sURI);
@@ -1002,11 +1002,11 @@
1002 const char *zNow; /* Time of checkin */
1003 int showId = PB("showid");
1004 Stmt q1, q2;
1005 double baseTime;
1006 login_check_credentials();
1007 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1008 zName = P("name");
1009 if( zName==0 ) zName = "tip";
1010 rid = symbolic_name_to_rid(zName, "ci");
1011 if( rid==0 ){
1012 fossil_fatal("not a valid check-in: %s", zName);
1013
+2 -2
--- src/cache.c
+++ src/cache.c
@@ -330,11 +330,11 @@
330330
sqlite3 *db;
331331
sqlite3_stmt *pStmt;
332332
char zBuf[100];
333333
334334
login_check_credentials();
335
- if( !g.perm.Setup ){ login_needed(); return; }
335
+ if( !g.perm.Setup ){ login_needed(0); return; }
336336
style_header("Web Cache Status");
337337
db = cacheOpen(0);
338338
if( db==0 ){
339339
@ The web-page cache is disabled for this repository
340340
}else{
@@ -378,11 +378,11 @@
378378
void cache_getpage(void){
379379
const char *zKey;
380380
Blob content;
381381
382382
login_check_credentials();
383
- if( !g.perm.Setup ){ login_needed(); return; }
383
+ if( !g.perm.Setup ){ login_needed(0); return; }
384384
zKey = PD("key","");
385385
blob_zero(&content);
386386
if( cache_read(&content, zKey)==0 ){
387387
style_header("Cache Download Error");
388388
@ The cache does not contain any entry with this key: "%h(zKey)"
389389
--- src/cache.c
+++ src/cache.c
@@ -330,11 +330,11 @@
330 sqlite3 *db;
331 sqlite3_stmt *pStmt;
332 char zBuf[100];
333
334 login_check_credentials();
335 if( !g.perm.Setup ){ login_needed(); return; }
336 style_header("Web Cache Status");
337 db = cacheOpen(0);
338 if( db==0 ){
339 @ The web-page cache is disabled for this repository
340 }else{
@@ -378,11 +378,11 @@
378 void cache_getpage(void){
379 const char *zKey;
380 Blob content;
381
382 login_check_credentials();
383 if( !g.perm.Setup ){ login_needed(); return; }
384 zKey = PD("key","");
385 blob_zero(&content);
386 if( cache_read(&content, zKey)==0 ){
387 style_header("Cache Download Error");
388 @ The cache does not contain any entry with this key: "%h(zKey)"
389
--- src/cache.c
+++ src/cache.c
@@ -330,11 +330,11 @@
330 sqlite3 *db;
331 sqlite3_stmt *pStmt;
332 char zBuf[100];
333
334 login_check_credentials();
335 if( !g.perm.Setup ){ login_needed(0); return; }
336 style_header("Web Cache Status");
337 db = cacheOpen(0);
338 if( db==0 ){
339 @ The web-page cache is disabled for this repository
340 }else{
@@ -378,11 +378,11 @@
378 void cache_getpage(void){
379 const char *zKey;
380 Blob content;
381
382 login_check_credentials();
383 if( !g.perm.Setup ){ login_needed(0); return; }
384 zKey = PD("key","");
385 blob_zero(&content);
386 if( cache_read(&content, zKey)==0 ){
387 style_header("Cache Download Error");
388 @ The cache does not contain any entry with this key: "%h(zKey)"
389
--- src/descendants.c
+++ src/descendants.c
@@ -439,11 +439,11 @@
439439
Stmt q;
440440
int showAll = P("all")!=0;
441441
int showClosed = P("closed")!=0;
442442
443443
login_check_credentials();
444
- if( !g.perm.Read ){ login_needed(); return; }
444
+ if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
445445
446446
if( !showAll ){
447447
style_submenu_element("All", "All", "leaves?all");
448448
}
449449
if( !showClosed ){
450450
--- src/descendants.c
+++ src/descendants.c
@@ -439,11 +439,11 @@
439 Stmt q;
440 int showAll = P("all")!=0;
441 int showClosed = P("closed")!=0;
442
443 login_check_credentials();
444 if( !g.perm.Read ){ login_needed(); return; }
445
446 if( !showAll ){
447 style_submenu_element("All", "All", "leaves?all");
448 }
449 if( !showClosed ){
450
--- src/descendants.c
+++ src/descendants.c
@@ -439,11 +439,11 @@
439 Stmt q;
440 int showAll = P("all")!=0;
441 int showClosed = P("closed")!=0;
442
443 login_check_credentials();
444 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
445
446 if( !showAll ){
447 style_submenu_element("All", "All", "leaves?all");
448 }
449 if( !showClosed ){
450
+1 -1
--- src/diff.c
+++ src/diff.c
@@ -2234,11 +2234,11 @@
22342234
int bBlame = g.zPath[0]!='a';/* True for BLAME output. False for ANNOTATE. */
22352235
22362236
/* Gather query parameters */
22372237
showLog = atoi(PD("log","1"));
22382238
login_check_credentials();
2239
- if( !g.perm.Read ){ login_needed(); return; }
2239
+ if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
22402240
if( exclude_spiders("annotate") ) return;
22412241
load_control();
22422242
mid = name_to_typed_rid(PD("checkin","0"),"ci");
22432243
zFilename = P("filename");
22442244
fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename);
22452245
--- src/diff.c
+++ src/diff.c
@@ -2234,11 +2234,11 @@
2234 int bBlame = g.zPath[0]!='a';/* True for BLAME output. False for ANNOTATE. */
2235
2236 /* Gather query parameters */
2237 showLog = atoi(PD("log","1"));
2238 login_check_credentials();
2239 if( !g.perm.Read ){ login_needed(); return; }
2240 if( exclude_spiders("annotate") ) return;
2241 load_control();
2242 mid = name_to_typed_rid(PD("checkin","0"),"ci");
2243 zFilename = P("filename");
2244 fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename);
2245
--- src/diff.c
+++ src/diff.c
@@ -2234,11 +2234,11 @@
2234 int bBlame = g.zPath[0]!='a';/* True for BLAME output. False for ANNOTATE. */
2235
2236 /* Gather query parameters */
2237 showLog = atoi(PD("log","1"));
2238 login_check_credentials();
2239 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
2240 if( exclude_spiders("annotate") ) return;
2241 load_control();
2242 mid = name_to_typed_rid(PD("checkin","0"),"ci");
2243 zFilename = P("filename");
2244 fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename);
2245
+1 -1
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -841,11 +841,11 @@
841841
*/
842842
void vpatch_page(void){
843843
const char *zFrom = P("from");
844844
const char *zTo = P("to");
845845
login_check_credentials();
846
- if( !g.perm.Read ){ login_needed(); return; }
846
+ if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
847847
if( zFrom==0 || zTo==0 ) fossil_redirect_home();
848848
849849
cgi_set_content_type("text/plain");
850850
diff_all_two_versions(zFrom, zTo, 0, 0, 0, DIFF_VERBOSE);
851851
}
852852
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -841,11 +841,11 @@
841 */
842 void vpatch_page(void){
843 const char *zFrom = P("from");
844 const char *zTo = P("to");
845 login_check_credentials();
846 if( !g.perm.Read ){ login_needed(); return; }
847 if( zFrom==0 || zTo==0 ) fossil_redirect_home();
848
849 cgi_set_content_type("text/plain");
850 diff_all_two_versions(zFrom, zTo, 0, 0, 0, DIFF_VERBOSE);
851 }
852
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -841,11 +841,11 @@
841 */
842 void vpatch_page(void){
843 const char *zFrom = P("from");
844 const char *zTo = P("to");
845 login_check_credentials();
846 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
847 if( zFrom==0 || zTo==0 ) fossil_redirect_home();
848
849 cgi_set_content_type("text/plain");
850 diff_all_two_versions(zFrom, zTo, 0, 0, 0, DIFF_VERBOSE);
851 }
852
+1 -1
--- src/doc.c
+++ src/doc.c
@@ -543,11 +543,11 @@
543543
static const char *const azSuffix[] = {
544544
"index.html", "index.wiki", "index.md"
545545
};
546546
547547
login_check_credentials();
548
- if( !g.perm.Read ){ login_needed(); return; }
548
+ if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
549549
blob_init(&title, 0, 0);
550550
db_begin_transaction();
551551
while( rid==0 && (++nMiss)<=ArraySize(azSuffix) ){
552552
zName = PD("name", "tip/index.wiki");
553553
for(i=0; zName[i] && zName[i]!='/'; i++){}
554554
--- src/doc.c
+++ src/doc.c
@@ -543,11 +543,11 @@
543 static const char *const azSuffix[] = {
544 "index.html", "index.wiki", "index.md"
545 };
546
547 login_check_credentials();
548 if( !g.perm.Read ){ login_needed(); return; }
549 blob_init(&title, 0, 0);
550 db_begin_transaction();
551 while( rid==0 && (++nMiss)<=ArraySize(azSuffix) ){
552 zName = PD("name", "tip/index.wiki");
553 for(i=0; zName[i] && zName[i]!='/'; i++){}
554
--- src/doc.c
+++ src/doc.c
@@ -543,11 +543,11 @@
543 static const char *const azSuffix[] = {
544 "index.html", "index.wiki", "index.md"
545 };
546
547 login_check_credentials();
548 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
549 blob_init(&title, 0, 0);
550 db_begin_transaction();
551 while( rid==0 && (++nMiss)<=ArraySize(azSuffix) ){
552 zName = PD("name", "tip/index.wiki");
553 for(i=0; zName[i] && zName[i]!='/'; i++){}
554
+2 -2
--- src/event.c
+++ src/event.c
@@ -69,11 +69,11 @@
6969
7070
/* wiki-read privilege is needed in order to read events.
7171
*/
7272
login_check_credentials();
7373
if( !g.perm.RdWiki ){
74
- login_needed();
74
+ login_needed(g.anon.RdWiki);
7575
return;
7676
}
7777
7878
zEventId = P("name");
7979
if( zEventId==0 ){ fossil_redirect_home(); return; }
@@ -233,11 +233,11 @@
233233
234234
/* Need both check-in and wiki-write or wiki-create privileges in order
235235
** to edit/create an event.
236236
*/
237237
if( !g.perm.Write || (rid && !g.perm.WrWiki) || (!rid && !g.perm.NewWiki) ){
238
- login_needed();
238
+ login_needed(g.anon.Write && (rid ? g.anon.WrWiki : g.anon.NewWiki));
239239
return;
240240
}
241241
242242
/* Figure out the color */
243243
if( rid ){
244244
--- src/event.c
+++ src/event.c
@@ -69,11 +69,11 @@
69
70 /* wiki-read privilege is needed in order to read events.
71 */
72 login_check_credentials();
73 if( !g.perm.RdWiki ){
74 login_needed();
75 return;
76 }
77
78 zEventId = P("name");
79 if( zEventId==0 ){ fossil_redirect_home(); return; }
@@ -233,11 +233,11 @@
233
234 /* Need both check-in and wiki-write or wiki-create privileges in order
235 ** to edit/create an event.
236 */
237 if( !g.perm.Write || (rid && !g.perm.WrWiki) || (!rid && !g.perm.NewWiki) ){
238 login_needed();
239 return;
240 }
241
242 /* Figure out the color */
243 if( rid ){
244
--- src/event.c
+++ src/event.c
@@ -69,11 +69,11 @@
69
70 /* wiki-read privilege is needed in order to read events.
71 */
72 login_check_credentials();
73 if( !g.perm.RdWiki ){
74 login_needed(g.anon.RdWiki);
75 return;
76 }
77
78 zEventId = P("name");
79 if( zEventId==0 ){ fossil_redirect_home(); return; }
@@ -233,11 +233,11 @@
233
234 /* Need both check-in and wiki-write or wiki-create privileges in order
235 ** to edit/create an event.
236 */
237 if( !g.perm.Write || (rid && !g.perm.WrWiki) || (!rid && !g.perm.NewWiki) ){
238 login_needed(g.anon.Write && (rid ? g.anon.WrWiki : g.anon.NewWiki));
239 return;
240 }
241
242 /* Figure out the color */
243 if( rid ){
244
+1 -1
--- src/finfo.c
+++ src/finfo.c
@@ -305,11 +305,11 @@
305305
int uBg = P("ubg")!=0;
306306
int fDebug = atoi(PD("debug","0"));
307307
int fShowId = P("showid")!=0;
308308
309309
login_check_credentials();
310
- if( !g.perm.Read ){ login_needed(); return; }
310
+ if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
311311
style_header("File History");
312312
login_anonymous_available();
313313
url_initialize(&url, "finfo");
314314
if( brBg ) url_add_parameter(&url, "brbg", 0);
315315
if( uBg ) url_add_parameter(&url, "ubg", 0);
316316
--- src/finfo.c
+++ src/finfo.c
@@ -305,11 +305,11 @@
305 int uBg = P("ubg")!=0;
306 int fDebug = atoi(PD("debug","0"));
307 int fShowId = P("showid")!=0;
308
309 login_check_credentials();
310 if( !g.perm.Read ){ login_needed(); return; }
311 style_header("File History");
312 login_anonymous_available();
313 url_initialize(&url, "finfo");
314 if( brBg ) url_add_parameter(&url, "brbg", 0);
315 if( uBg ) url_add_parameter(&url, "ubg", 0);
316
--- src/finfo.c
+++ src/finfo.c
@@ -305,11 +305,11 @@
305 int uBg = P("ubg")!=0;
306 int fDebug = atoi(PD("debug","0"));
307 int fShowId = P("showid")!=0;
308
309 login_check_credentials();
310 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
311 style_header("File History");
312 login_anonymous_available();
313 url_initialize(&url, "finfo");
314 if( brBg ) url_add_parameter(&url, "brbg", 0);
315 if( uBg ) url_add_parameter(&url, "ubg", 0);
316
+13 -13
--- src/info.c
+++ src/info.c
@@ -527,11 +527,11 @@
527527
const char *zW; /* URL param for ignoring whitespace */
528528
const char *zPage = "vinfo"; /* Page that shows diffs */
529529
const char *zPageHide = "ci"; /* Page that hides diffs */
530530
531531
login_check_credentials();
532
- if( !g.perm.Read ){ login_needed(); return; }
532
+ if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
533533
zName = P("name");
534534
rid = name_to_rid_www("name");
535535
if( rid==0 ){
536536
style_header("Check-in Information Error");
537537
@ No such object: %h(g.argv[2])
@@ -657,11 +657,11 @@
657657
}
658658
db_finalize(&q2);
659659
660660
661661
/* The Download: line */
662
- if( g.perm.Zip ){
662
+ if( g.anon.Zip ){
663663
char *zUrl = mprintf("%R/tarball/%t-%S.tar.gz?uuid=%s",
664664
zPJ, zUuid, zUuid);
665665
@ </td></tr>
666666
@ <tr><th>Downloads:</th><td>
667667
@ %z(href("%s",zUrl))Tarball</a>
@@ -674,11 +674,11 @@
674674
@ <td>
675675
@ %z(href("%R/tree?ci=%!S",zUuid))files</a>
676676
@ | %z(href("%R/fileage?name=%!S",zUuid))file ages</a>
677677
@ | %z(href("%R/tree?nofiles&type=tree&ci=%!S",zUuid))folders</a>
678678
@ | %z(href("%R/artifact/%!S",zUuid))manifest</a>
679
- if( g.perm.Write ){
679
+ if( g.anon.Write ){
680680
@ | %z(href("%R/ci_edit?r=%!S",zUuid))edit</a>
681681
}
682682
@ </td>
683683
@ </tr>
684684
blob_reset(&projName);
@@ -773,11 +773,11 @@
773773
Blob wiki;
774774
int modPending;
775775
const char *zModAction;
776776
777777
login_check_credentials();
778
- if( !g.perm.RdWiki ){ login_needed(); return; }
778
+ if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; }
779779
rid = name_to_rid_www("name");
780780
if( rid==0 || (pWiki = manifest_get(rid, CFTYPE_WIKI, 0))==0 ){
781781
style_header("Wiki Page Information Error");
782782
@ No such object: %h(P("name"))
783783
style_footer();
@@ -991,11 +991,11 @@
991991
const char *zW;
992992
const char *zVerbose;
993993
const char *zGlob;
994994
ReCompiled *pRe = 0;
995995
login_check_credentials();
996
- if( !g.perm.Read ){ login_needed(); return; }
996
+ if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
997997
login_anonymous_available();
998998
zRe = P("regex");
999999
if( zRe ) re_compile(&pRe, zRe, 0);
10001000
zBranch = P("branch");
10011001
if( zBranch && zBranch[0] ){
@@ -1363,17 +1363,17 @@
13631363
}else{
13641364
@ Attachment "%h(zFilename)" to
13651365
}
13661366
objType |= OBJTYPE_ATTACHMENT;
13671367
if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){
1368
- if( g.perm.Hyperlink && g.perm.RdTkt ){
1368
+ if( g.perm.Hyperlink && g.anon.RdTkt ){
13691369
@ ticket [%z(href("%R/tktview?name=%!S",zTarget))%S(zTarget)</a>]
13701370
}else{
13711371
@ ticket [%S(zTarget)]
13721372
}
13731373
}else{
1374
- if( g.perm.Hyperlink && g.perm.RdWiki ){
1374
+ if( g.perm.Hyperlink && g.anon.RdWiki ){
13751375
@ wiki page [%z(href("%R/wiki?name=%t",zTarget))%h(zTarget)</a>]
13761376
}else{
13771377
@ wiki page [%h(zTarget)]
13781378
}
13791379
}
@@ -1421,11 +1421,11 @@
14211421
ReCompiled *pRe = 0;
14221422
u64 diffFlags;
14231423
u32 objdescFlags = 0;
14241424
14251425
login_check_credentials();
1426
- if( !g.perm.Read ){ login_needed(); return; }
1426
+ if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
14271427
v1 = name_to_rid_www("v1");
14281428
v2 = name_to_rid_www("v2");
14291429
if( v1==0 || v2==0 ) fossil_redirect_home();
14301430
zRe = P("regex");
14311431
if( zRe ) re_compile(&pRe, zRe, 0);
@@ -1506,11 +1506,11 @@
15061506
const char *zMime;
15071507
Blob content;
15081508
15091509
rid = name_to_rid_www("name");
15101510
login_check_credentials();
1511
- if( !g.perm.Read ){ login_needed(); return; }
1511
+ if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
15121512
if( rid==0 ) fossil_redirect_home();
15131513
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
15141514
if( fossil_strcmp(P("name"), zUuid)==0 && login_is_nobody() ){
15151515
g.isConst = 1;
15161516
}
@@ -1603,11 +1603,11 @@
16031603
char *zUuid;
16041604
u32 objdescFlags = 0;
16051605
16061606
rid = name_to_rid_www("name");
16071607
login_check_credentials();
1608
- if( !g.perm.Read ){ login_needed(); return; }
1608
+ if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
16091609
if( rid==0 ) fossil_redirect_home();
16101610
if( g.perm.Admin ){
16111611
const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
16121612
if( db_exists("SELECT 1 FROM shun WHERE uuid=%Q", zUuid) ){
16131613
style_submenu_element("Unshun","Unshun", "%s/shun?accept=%s&sub=1#delshun",
@@ -1789,11 +1789,11 @@
17891789
if( rid==0 ){
17901790
rid = name_to_rid_www("name");
17911791
}
17921792
17931793
login_check_credentials();
1794
- if( !g.perm.Read ){ login_needed(); return; }
1794
+ if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
17951795
if( rid==0 ) fossil_redirect_home();
17961796
if( g.perm.Admin ){
17971797
const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
17981798
if( db_exists("SELECT 1 FROM shun WHERE uuid=%Q", zUuid) ){
17991799
style_submenu_element("Unshun","Unshun", "%s/shun?accept=%s&sub=1#accshun",
@@ -1904,11 +1904,11 @@
19041904
Manifest *pTktChng;
19051905
int modPending;
19061906
const char *zModAction;
19071907
char *zTktTitle;
19081908
login_check_credentials();
1909
- if( !g.perm.RdTkt ){ login_needed(); return; }
1909
+ if( !g.perm.RdTkt ){ login_needed(g.anon.RdTkt); return; }
19101910
rid = name_to_rid_www("name");
19111911
if( rid==0 ){ fossil_redirect_home(); }
19121912
zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
19131913
if( g.perm.Admin ){
19141914
if( db_exists("SELECT 1 FROM shun WHERE uuid=%Q", zUuid) ){
@@ -2276,11 +2276,11 @@
22762276
Blob comment;
22772277
char *zBranchName = 0;
22782278
Stmt q;
22792279
22802280
login_check_credentials();
2281
- if( !g.perm.Write ){ login_needed(); return; }
2281
+ if( !g.perm.Write ){ login_needed(g.anon.Write); return; }
22822282
rid = name_to_typed_rid(P("r"), "ci");
22832283
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
22842284
zComment = db_text(0, "SELECT coalesce(ecomment,comment)"
22852285
" FROM event WHERE objid=%d", rid);
22862286
if( zComment==0 ) fossil_redirect_home();
22872287
--- src/info.c
+++ src/info.c
@@ -527,11 +527,11 @@
527 const char *zW; /* URL param for ignoring whitespace */
528 const char *zPage = "vinfo"; /* Page that shows diffs */
529 const char *zPageHide = "ci"; /* Page that hides diffs */
530
531 login_check_credentials();
532 if( !g.perm.Read ){ login_needed(); return; }
533 zName = P("name");
534 rid = name_to_rid_www("name");
535 if( rid==0 ){
536 style_header("Check-in Information Error");
537 @ No such object: %h(g.argv[2])
@@ -657,11 +657,11 @@
657 }
658 db_finalize(&q2);
659
660
661 /* The Download: line */
662 if( g.perm.Zip ){
663 char *zUrl = mprintf("%R/tarball/%t-%S.tar.gz?uuid=%s",
664 zPJ, zUuid, zUuid);
665 @ </td></tr>
666 @ <tr><th>Downloads:</th><td>
667 @ %z(href("%s",zUrl))Tarball</a>
@@ -674,11 +674,11 @@
674 @ <td>
675 @ %z(href("%R/tree?ci=%!S",zUuid))files</a>
676 @ | %z(href("%R/fileage?name=%!S",zUuid))file ages</a>
677 @ | %z(href("%R/tree?nofiles&type=tree&ci=%!S",zUuid))folders</a>
678 @ | %z(href("%R/artifact/%!S",zUuid))manifest</a>
679 if( g.perm.Write ){
680 @ | %z(href("%R/ci_edit?r=%!S",zUuid))edit</a>
681 }
682 @ </td>
683 @ </tr>
684 blob_reset(&projName);
@@ -773,11 +773,11 @@
773 Blob wiki;
774 int modPending;
775 const char *zModAction;
776
777 login_check_credentials();
778 if( !g.perm.RdWiki ){ login_needed(); return; }
779 rid = name_to_rid_www("name");
780 if( rid==0 || (pWiki = manifest_get(rid, CFTYPE_WIKI, 0))==0 ){
781 style_header("Wiki Page Information Error");
782 @ No such object: %h(P("name"))
783 style_footer();
@@ -991,11 +991,11 @@
991 const char *zW;
992 const char *zVerbose;
993 const char *zGlob;
994 ReCompiled *pRe = 0;
995 login_check_credentials();
996 if( !g.perm.Read ){ login_needed(); return; }
997 login_anonymous_available();
998 zRe = P("regex");
999 if( zRe ) re_compile(&pRe, zRe, 0);
1000 zBranch = P("branch");
1001 if( zBranch && zBranch[0] ){
@@ -1363,17 +1363,17 @@
1363 }else{
1364 @ Attachment "%h(zFilename)" to
1365 }
1366 objType |= OBJTYPE_ATTACHMENT;
1367 if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){
1368 if( g.perm.Hyperlink && g.perm.RdTkt ){
1369 @ ticket [%z(href("%R/tktview?name=%!S",zTarget))%S(zTarget)</a>]
1370 }else{
1371 @ ticket [%S(zTarget)]
1372 }
1373 }else{
1374 if( g.perm.Hyperlink && g.perm.RdWiki ){
1375 @ wiki page [%z(href("%R/wiki?name=%t",zTarget))%h(zTarget)</a>]
1376 }else{
1377 @ wiki page [%h(zTarget)]
1378 }
1379 }
@@ -1421,11 +1421,11 @@
1421 ReCompiled *pRe = 0;
1422 u64 diffFlags;
1423 u32 objdescFlags = 0;
1424
1425 login_check_credentials();
1426 if( !g.perm.Read ){ login_needed(); return; }
1427 v1 = name_to_rid_www("v1");
1428 v2 = name_to_rid_www("v2");
1429 if( v1==0 || v2==0 ) fossil_redirect_home();
1430 zRe = P("regex");
1431 if( zRe ) re_compile(&pRe, zRe, 0);
@@ -1506,11 +1506,11 @@
1506 const char *zMime;
1507 Blob content;
1508
1509 rid = name_to_rid_www("name");
1510 login_check_credentials();
1511 if( !g.perm.Read ){ login_needed(); return; }
1512 if( rid==0 ) fossil_redirect_home();
1513 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
1514 if( fossil_strcmp(P("name"), zUuid)==0 && login_is_nobody() ){
1515 g.isConst = 1;
1516 }
@@ -1603,11 +1603,11 @@
1603 char *zUuid;
1604 u32 objdescFlags = 0;
1605
1606 rid = name_to_rid_www("name");
1607 login_check_credentials();
1608 if( !g.perm.Read ){ login_needed(); return; }
1609 if( rid==0 ) fossil_redirect_home();
1610 if( g.perm.Admin ){
1611 const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
1612 if( db_exists("SELECT 1 FROM shun WHERE uuid=%Q", zUuid) ){
1613 style_submenu_element("Unshun","Unshun", "%s/shun?accept=%s&sub=1#delshun",
@@ -1789,11 +1789,11 @@
1789 if( rid==0 ){
1790 rid = name_to_rid_www("name");
1791 }
1792
1793 login_check_credentials();
1794 if( !g.perm.Read ){ login_needed(); return; }
1795 if( rid==0 ) fossil_redirect_home();
1796 if( g.perm.Admin ){
1797 const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
1798 if( db_exists("SELECT 1 FROM shun WHERE uuid=%Q", zUuid) ){
1799 style_submenu_element("Unshun","Unshun", "%s/shun?accept=%s&sub=1#accshun",
@@ -1904,11 +1904,11 @@
1904 Manifest *pTktChng;
1905 int modPending;
1906 const char *zModAction;
1907 char *zTktTitle;
1908 login_check_credentials();
1909 if( !g.perm.RdTkt ){ login_needed(); return; }
1910 rid = name_to_rid_www("name");
1911 if( rid==0 ){ fossil_redirect_home(); }
1912 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
1913 if( g.perm.Admin ){
1914 if( db_exists("SELECT 1 FROM shun WHERE uuid=%Q", zUuid) ){
@@ -2276,11 +2276,11 @@
2276 Blob comment;
2277 char *zBranchName = 0;
2278 Stmt q;
2279
2280 login_check_credentials();
2281 if( !g.perm.Write ){ login_needed(); return; }
2282 rid = name_to_typed_rid(P("r"), "ci");
2283 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
2284 zComment = db_text(0, "SELECT coalesce(ecomment,comment)"
2285 " FROM event WHERE objid=%d", rid);
2286 if( zComment==0 ) fossil_redirect_home();
2287
--- src/info.c
+++ src/info.c
@@ -527,11 +527,11 @@
527 const char *zW; /* URL param for ignoring whitespace */
528 const char *zPage = "vinfo"; /* Page that shows diffs */
529 const char *zPageHide = "ci"; /* Page that hides diffs */
530
531 login_check_credentials();
532 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
533 zName = P("name");
534 rid = name_to_rid_www("name");
535 if( rid==0 ){
536 style_header("Check-in Information Error");
537 @ No such object: %h(g.argv[2])
@@ -657,11 +657,11 @@
657 }
658 db_finalize(&q2);
659
660
661 /* The Download: line */
662 if( g.anon.Zip ){
663 char *zUrl = mprintf("%R/tarball/%t-%S.tar.gz?uuid=%s",
664 zPJ, zUuid, zUuid);
665 @ </td></tr>
666 @ <tr><th>Downloads:</th><td>
667 @ %z(href("%s",zUrl))Tarball</a>
@@ -674,11 +674,11 @@
674 @ <td>
675 @ %z(href("%R/tree?ci=%!S",zUuid))files</a>
676 @ | %z(href("%R/fileage?name=%!S",zUuid))file ages</a>
677 @ | %z(href("%R/tree?nofiles&type=tree&ci=%!S",zUuid))folders</a>
678 @ | %z(href("%R/artifact/%!S",zUuid))manifest</a>
679 if( g.anon.Write ){
680 @ | %z(href("%R/ci_edit?r=%!S",zUuid))edit</a>
681 }
682 @ </td>
683 @ </tr>
684 blob_reset(&projName);
@@ -773,11 +773,11 @@
773 Blob wiki;
774 int modPending;
775 const char *zModAction;
776
777 login_check_credentials();
778 if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; }
779 rid = name_to_rid_www("name");
780 if( rid==0 || (pWiki = manifest_get(rid, CFTYPE_WIKI, 0))==0 ){
781 style_header("Wiki Page Information Error");
782 @ No such object: %h(P("name"))
783 style_footer();
@@ -991,11 +991,11 @@
991 const char *zW;
992 const char *zVerbose;
993 const char *zGlob;
994 ReCompiled *pRe = 0;
995 login_check_credentials();
996 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
997 login_anonymous_available();
998 zRe = P("regex");
999 if( zRe ) re_compile(&pRe, zRe, 0);
1000 zBranch = P("branch");
1001 if( zBranch && zBranch[0] ){
@@ -1363,17 +1363,17 @@
1363 }else{
1364 @ Attachment "%h(zFilename)" to
1365 }
1366 objType |= OBJTYPE_ATTACHMENT;
1367 if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){
1368 if( g.perm.Hyperlink && g.anon.RdTkt ){
1369 @ ticket [%z(href("%R/tktview?name=%!S",zTarget))%S(zTarget)</a>]
1370 }else{
1371 @ ticket [%S(zTarget)]
1372 }
1373 }else{
1374 if( g.perm.Hyperlink && g.anon.RdWiki ){
1375 @ wiki page [%z(href("%R/wiki?name=%t",zTarget))%h(zTarget)</a>]
1376 }else{
1377 @ wiki page [%h(zTarget)]
1378 }
1379 }
@@ -1421,11 +1421,11 @@
1421 ReCompiled *pRe = 0;
1422 u64 diffFlags;
1423 u32 objdescFlags = 0;
1424
1425 login_check_credentials();
1426 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1427 v1 = name_to_rid_www("v1");
1428 v2 = name_to_rid_www("v2");
1429 if( v1==0 || v2==0 ) fossil_redirect_home();
1430 zRe = P("regex");
1431 if( zRe ) re_compile(&pRe, zRe, 0);
@@ -1506,11 +1506,11 @@
1506 const char *zMime;
1507 Blob content;
1508
1509 rid = name_to_rid_www("name");
1510 login_check_credentials();
1511 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1512 if( rid==0 ) fossil_redirect_home();
1513 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
1514 if( fossil_strcmp(P("name"), zUuid)==0 && login_is_nobody() ){
1515 g.isConst = 1;
1516 }
@@ -1603,11 +1603,11 @@
1603 char *zUuid;
1604 u32 objdescFlags = 0;
1605
1606 rid = name_to_rid_www("name");
1607 login_check_credentials();
1608 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1609 if( rid==0 ) fossil_redirect_home();
1610 if( g.perm.Admin ){
1611 const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
1612 if( db_exists("SELECT 1 FROM shun WHERE uuid=%Q", zUuid) ){
1613 style_submenu_element("Unshun","Unshun", "%s/shun?accept=%s&sub=1#delshun",
@@ -1789,11 +1789,11 @@
1789 if( rid==0 ){
1790 rid = name_to_rid_www("name");
1791 }
1792
1793 login_check_credentials();
1794 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1795 if( rid==0 ) fossil_redirect_home();
1796 if( g.perm.Admin ){
1797 const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
1798 if( db_exists("SELECT 1 FROM shun WHERE uuid=%Q", zUuid) ){
1799 style_submenu_element("Unshun","Unshun", "%s/shun?accept=%s&sub=1#accshun",
@@ -1904,11 +1904,11 @@
1904 Manifest *pTktChng;
1905 int modPending;
1906 const char *zModAction;
1907 char *zTktTitle;
1908 login_check_credentials();
1909 if( !g.perm.RdTkt ){ login_needed(g.anon.RdTkt); return; }
1910 rid = name_to_rid_www("name");
1911 if( rid==0 ){ fossil_redirect_home(); }
1912 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
1913 if( g.perm.Admin ){
1914 if( db_exists("SELECT 1 FROM shun WHERE uuid=%Q", zUuid) ){
@@ -2276,11 +2276,11 @@
2276 Blob comment;
2277 char *zBranchName = 0;
2278 Stmt q;
2279
2280 login_check_credentials();
2281 if( !g.perm.Write ){ login_needed(g.anon.Write); return; }
2282 rid = name_to_typed_rid(P("r"), "ci");
2283 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
2284 zComment = db_text(0, "SELECT coalesce(ecomment,comment)"
2285 " FROM event WHERE objid=%d", rid);
2286 if( zComment==0 ) fossil_redirect_home();
2287
+152 -106
--- src/login.c
+++ src/login.c
@@ -352,16 +352,12 @@
352352
login_cookie_path(), -86400);
353353
db_multi_exec("UPDATE user SET cookie=NULL, ipaddr=NULL, "
354354
" cexpire=0 WHERE uid=%d"
355355
" AND login NOT IN ('anonymous','nobody',"
356356
" 'developer','reader')", g.userUid);
357
- cgi_replace_parameter(cookie, NULL)
358
- /* At the time of this writing, cgi_replace_parameter() was
359
- ** "NULL-value-safe", and I'm hoping the NULL doesn't cause any
360
- ** downstream problems here. We could alternately use "" here.
361
- */
362
- ;
357
+ cgi_replace_parameter(cookie, NULL);
358
+ cgi_replace_parameter("anon", NULL);
363359
}
364360
}
365361
366362
/*
367363
** Return true if the prefix of zStr matches zPattern. Return false if
@@ -451,27 +447,46 @@
451447
}
452448
sqlite3_result_int(context, rc);
453449
}
454450
455451
/*
456
-** WEBPAGE: login
457
-** WEBPAGE: logout
458
-** WEBPAGE: my
459
-**
460
-** Generate the login page.
461
-**
452
+** Return true if the current page was reached by a redirect from the /login
453
+** page.
454
+*/
455
+int referred_from_login(void){
456
+ const char *zReferer = P("HTTP_REFERER");
457
+ char *zPattern;
458
+ int rc;
459
+ if( zReferer==0 ) return 0;
460
+ zPattern = mprintf("%s/login*", g.zBaseURL);
461
+ rc = sqlite3_strglob(zPattern, zReferer)==0;
462
+ fossil_free(zPattern);
463
+ return rc;
464
+}
465
+
466
+/*
462467
** There used to be a page named "my" that was designed to show information
463468
** about a specific user. The "my" page was linked from the "Logged in as USER"
464469
** line on the title bar. The "my" page was never completed so it is now
465470
** removed. Use this page as a placeholder in older installations.
471
+**
472
+** WEBPAGE: login
473
+** WEBPAGE: logout
474
+** WEBPAGE: my
475
+**
476
+** The login/logout page. Parameters:
477
+**
478
+** g=URL Jump back to this URL after login completes
479
+** anon The g=URL is not accessible by "nobody" but is
480
+** accessible by "anonymous"
466481
*/
467482
void login_page(void){
468483
const char *zUsername, *zPasswd;
469484
const char *zNew1, *zNew2;
470485
const char *zAnonPw = 0;
471486
const char *zGoto = P("g");
472
- int anonFlag;
487
+ int anonFlag; /* Login as "anonymous" would be useful */
473488
char *zErrMsg = "";
474489
int uid; /* User id logged in user */
475490
char *zSha1Pw;
476491
const char *zIpAddr; /* IP address of requestor */
477492
const char *zReferer;
@@ -489,15 +504,20 @@
489504
}
490505
sqlite3_create_function(g.db, "constant_time_cmp", 2, SQLITE_UTF8, 0,
491506
constant_time_cmp_function, 0, 0);
492507
zUsername = P("u");
493508
zPasswd = P("p");
494
- anonFlag = P("anon")!=0;
495
- if( P("out")!=0 ){
509
+ anonFlag = g.zLogin==0 && PB("anon");
510
+
511
+ /* Handle log-out requests */
512
+ if( P("out") ){
496513
login_clear_login_data();
497514
redirect_to_g();
515
+ return;
498516
}
517
+
518
+ /* Deal with password-change requests */
499519
if( g.perm.Password && zPasswd
500520
&& (zNew1 = P("n1"))!=0 && (zNew2 = P("n2"))!=0
501521
){
502522
/* The user requests a password change */
503523
zSha1Pw = sha1_shared_secret(zPasswd, g.zLogin, 0);
@@ -577,19 +597,40 @@
577597
}
578598
}
579599
style_header("Login/Logout");
580600
style_adunit_config(ADUNIT_OFF);
581601
@ %s(zErrMsg)
582
- if( zGoto && P("anon")==0 ){
583
- @ <p>A login is required for <a href="%h(zGoto)">%h(zGoto)</a>.</p>
602
+ if( zGoto ){
603
+ char *zAbbrev = fossil_strdup(zGoto);
604
+ int i;
605
+ for(i=0; zAbbrev[i] && zAbbrev[i]!='?'; i++){}
606
+ zAbbrev[i] = 0;
607
+ if( g.zLogin ){
608
+ @ <p>Use a different login with greater privilege that <b>%h(g.zLogin)</b>
609
+ @ to access <b>%h(zAbbrev)</b>.
610
+ }else if( anonFlag ){
611
+ @ <p>Login as <b>anonymous</b> or any named user
612
+ @ to access page <b>%h(zAbbrev)</b>.
613
+ }else{
614
+ @ <p>Login as a named user to access page <b>%h(zAbbrev)</b>.
615
+ }
584616
}
585617
form_begin(0, "%R/login");
586618
if( zGoto ){
587619
@ <input type="hidden" name="g" value="%h(zGoto)" />
588620
}else if( zReferer && strncmp(g.zBaseURL, zReferer, strlen(g.zBaseURL))==0 ){
589621
@ <input type="hidden" name="g" value="%h(zReferer)" />
590622
}
623
+ if( anonFlag ){
624
+ @ <input type="hidden" name="anon" value="1" />
625
+ }
626
+ if( g.zLogin ){
627
+ @ <p>Currently logged in as <b>%h(g.zLogin)</b>.
628
+ @ <input type="submit" name="out" value="Logout"></p>
629
+ @ <hr />
630
+ @ <p>Change user:
631
+ }
591632
@ <table class="login_out">
592633
@ <tr>
593634
@ <td class="login_out_label">User ID:</td>
594635
if( anonFlag ){
595636
@ <td><input type="text" id="u" name="u" value="anonymous" size="30" /></td>
@@ -599,11 +640,11 @@
599640
@ </tr>
600641
@ <tr>
601642
@ <td class="login_out_label">Password:</td>
602643
@ <td><input type="password" id="p" name="p" value="" size="30" /></td>
603644
@ </tr>
604
- if( g.zLogin==0 ){
645
+ if( g.zLogin==0 && (anonFlag || zGoto==0) ){
605646
zAnonPw = db_text(0, "SELECT pw FROM user"
606647
" WHERE login='anonymous'"
607648
" AND cap!=''");
608649
}
609650
@ <tr>
@@ -624,20 +665,11 @@
624665
@ form.action = "%h(zSSL)/login";
625666
@ }
626667
}
627668
@ }
628669
@ </script>
629
- if( g.zLogin==0 ){
630
- @ <p>Enter
631
- }else{
632
- @ <p>You are currently logged in as <b>%h(g.zLogin)</b></p>
633
- @ <p>To change your login to a different user, enter
634
- }
635
- @ your user-id and password at the left and press the
636
- @ "Login" button. Your user name will be stored in a browser cookie.
637
- @ You must configure your web browser to accept cookies in order for
638
- @ the login to take.</p>
670
+ @ <p>Pressing the Login button grants permission to store a cookie.</p>
639671
if( db_get_boolean("self-register", 0) ){
640672
@ <p>If you do not have an account, you can
641673
@ <a href="%R/register?g=%T(P("G"))">create one</a>.
642674
}
643675
if( zAnonPw ){
@@ -657,22 +689,14 @@
657689
@ onclick="gebi('u').value='anonymous'; gebi('p').value='%s(zDecoded)';" />
658690
}
659691
@ </div>
660692
free(zCaptcha);
661693
}
662
- if( g.zLogin ){
663
- @ <hr />
664
- @ <p>To log off the system (and delete your login cookie)
665
- @ press the following button:<br />
666
- @ <input type="submit" name="out" value="Logout" /></p>
667
- }
668694
@ </form>
669695
if( g.perm.Password ){
670696
@ <hr />
671
- @ <p>To change your password, enter your old password and your
672
- @ new password twice below then press the "Change Password"
673
- @ button.</p>
697
+ @ <p>Change Password for user <b>%h(g.zLogin)</b>:</p>
674698
form_begin(0, "%R/login");
675699
@ <table>
676700
@ <tr><td class="login_out_label">Old Password:</td>
677701
@ <td><input type="password" name="p" size="30" /></td></tr>
678702
@ <tr><td class="login_out_label">New Password:</td>
@@ -811,10 +835,11 @@
811835
** variables appropriately.
812836
**
813837
** g.userUid Database USER.UID value. Might be -1 for "nobody"
814838
** g.zLogin Database USER.LOGIN value. NULL for user "nobody"
815839
** g.perm Permissions granted to this user
840
+** g.anon Permissions that would be available to anonymous
816841
** g.isHuman True if the user is human, not a spider or robot
817842
**
818843
*/
819844
void login_check_credentials(void){
820845
int uid = 0; /* User id */
@@ -1002,23 +1027,32 @@
10021027
** Memory of settings
10031028
*/
10041029
static int login_anon_once = 1;
10051030
10061031
/*
1007
-** Add the default privileges of users "nobody" and "anonymous" as appropriate
1008
-** for the user g.zLogin.
1032
+** Add to g.perm the default privileges of users "nobody" and/or "anonymous"
1033
+** as appropriate for the user g.zLogin.
1034
+**
1035
+** This routine also sets up g.anon to be either a copy of g.perm for
1036
+** all logged in uses, or the privileges that would be available to "anonymous"
1037
+** if g.zLogin==0 (meaning that the user is "nobody").
10091038
*/
10101039
void login_set_anon_nobody_capabilities(void){
1011
- if( g.zLogin && login_anon_once ){
1040
+ if( login_anon_once ){
10121041
const char *zCap;
1013
- /* All logged-in users inherit privileges from "nobody" */
1042
+ /* All users get privileges from "nobody" */
10141043
zCap = db_text("", "SELECT cap FROM user WHERE login = 'nobody'");
10151044
login_set_capabilities(zCap, 0);
1016
- if( fossil_strcmp(g.zLogin, "nobody")!=0 ){
1045
+ zCap = db_text("", "SELECT cap FROM user WHERE login = 'anonymous'");
1046
+ if( g.zLogin && fossil_strcmp(g.zLogin, "nobody")!=0 ){
10171047
/* All logged-in users inherit privileges from "anonymous" */
1018
- zCap = db_text("", "SELECT cap FROM user WHERE login = 'anonymous'");
10191048
login_set_capabilities(zCap, 0);
1049
+ g.anon = g.perm;
1050
+ }else{
1051
+ /* Record the privileges of anonymous in g.anon */
1052
+ g.anon = g.perm;
1053
+ login_set_capabilities(zCap, LOGIN_ANON);
10201054
}
10211055
login_anon_once = 0;
10221056
}
10231057
}
10241058
@@ -1025,55 +1059,57 @@
10251059
/*
10261060
** Flags passed into the 2nd argument of login_set/replace_capabilities().
10271061
*/
10281062
#if INTERFACE
10291063
#define LOGIN_IGNORE_UV 0x01 /* Ignore "u" and "v" */
1064
+#define LOGIN_ANON 0x02 /* Use g.anon instead of g.perm */
10301065
#endif
10311066
10321067
/*
1033
-** Adds all capability flags in zCap to g.perm.
1068
+** Adds all capability flags in zCap to g.perm or g.anon.
10341069
*/
10351070
void login_set_capabilities(const char *zCap, unsigned flags){
10361071
int i;
1072
+ FossilUserPerms *p = (flags & LOGIN_ANON) ? &g.anon : &g.perm;
10371073
if(NULL==zCap){
10381074
return;
10391075
}
10401076
for(i=0; zCap[i]; i++){
10411077
switch( zCap[i] ){
1042
- case 's': g.perm.Setup = 1; /* Fall thru into Admin */
1043
- case 'a': g.perm.Admin = g.perm.RdTkt = g.perm.WrTkt = g.perm.Zip =
1044
- g.perm.RdWiki = g.perm.WrWiki = g.perm.NewWiki =
1045
- g.perm.ApndWiki = g.perm.Hyperlink = g.perm.Clone =
1046
- g.perm.NewTkt = g.perm.Password = g.perm.RdAddr =
1047
- g.perm.TktFmt = g.perm.Attach = g.perm.ApndTkt =
1048
- g.perm.ModWiki = g.perm.ModTkt = 1;
1078
+ case 's': p->Setup = 1; /* Fall thru into Admin */
1079
+ case 'a': p->Admin = p->RdTkt = p->WrTkt = p->Zip =
1080
+ p->RdWiki = p->WrWiki = p->NewWiki =
1081
+ p->ApndWiki = p->Hyperlink = p->Clone =
1082
+ p->NewTkt = p->Password = p->RdAddr =
1083
+ p->TktFmt = p->Attach = p->ApndTkt =
1084
+ p->ModWiki = p->ModTkt = 1;
10491085
/* Fall thru into Read/Write */
1050
- case 'i': g.perm.Read = g.perm.Write = 1; break;
1051
- case 'o': g.perm.Read = 1; break;
1052
- case 'z': g.perm.Zip = 1; break;
1053
-
1054
- case 'd': g.perm.Delete = 1; break;
1055
- case 'h': g.perm.Hyperlink = 1; break;
1056
- case 'g': g.perm.Clone = 1; break;
1057
- case 'p': g.perm.Password = 1; break;
1058
-
1059
- case 'j': g.perm.RdWiki = 1; break;
1060
- case 'k': g.perm.WrWiki = g.perm.RdWiki = g.perm.ApndWiki =1; break;
1061
- case 'm': g.perm.ApndWiki = 1; break;
1062
- case 'f': g.perm.NewWiki = 1; break;
1063
- case 'l': g.perm.ModWiki = 1; break;
1064
-
1065
- case 'e': g.perm.RdAddr = 1; break;
1066
- case 'r': g.perm.RdTkt = 1; break;
1067
- case 'n': g.perm.NewTkt = 1; break;
1068
- case 'w': g.perm.WrTkt = g.perm.RdTkt = g.perm.NewTkt =
1069
- g.perm.ApndTkt = 1; break;
1070
- case 'c': g.perm.ApndTkt = 1; break;
1071
- case 'q': g.perm.ModTkt = 1; break;
1072
- case 't': g.perm.TktFmt = 1; break;
1073
- case 'b': g.perm.Attach = 1; break;
1074
- case 'x': g.perm.Private = 1; break;
1086
+ case 'i': p->Read = p->Write = 1; break;
1087
+ case 'o': p->Read = 1; break;
1088
+ case 'z': p->Zip = 1; break;
1089
+
1090
+ case 'd': p->Delete = 1; break;
1091
+ case 'h': p->Hyperlink = 1; break;
1092
+ case 'g': p->Clone = 1; break;
1093
+ case 'p': p->Password = 1; break;
1094
+
1095
+ case 'j': p->RdWiki = 1; break;
1096
+ case 'k': p->WrWiki = p->RdWiki = p->ApndWiki =1; break;
1097
+ case 'm': p->ApndWiki = 1; break;
1098
+ case 'f': p->NewWiki = 1; break;
1099
+ case 'l': p->ModWiki = 1; break;
1100
+
1101
+ case 'e': p->RdAddr = 1; break;
1102
+ case 'r': p->RdTkt = 1; break;
1103
+ case 'n': p->NewTkt = 1; break;
1104
+ case 'w': p->WrTkt = p->RdTkt = p->NewTkt =
1105
+ p->ApndTkt = 1; break;
1106
+ case 'c': p->ApndTkt = 1; break;
1107
+ case 'q': p->ModTkt = 1; break;
1108
+ case 't': p->TktFmt = 1; break;
1109
+ case 'b': p->Attach = 1; break;
1110
+ case 'x': p->Private = 1; break;
10751111
10761112
/* The "u" privileges is a little different. It recursively
10771113
** inherits all privileges of the user named "reader" */
10781114
case 'u': {
10791115
if( (flags & LOGIN_IGNORE_UV)==0 ){
@@ -1110,42 +1146,43 @@
11101146
/*
11111147
** If the current login lacks any of the capabilities listed in
11121148
** the input, then return 0. If all capabilities are present, then
11131149
** return 1.
11141150
*/
1115
-int login_has_capability(const char *zCap, int nCap){
1151
+int login_has_capability(const char *zCap, int nCap, u32 flgs){
11161152
int i;
11171153
int rc = 1;
1154
+ FossilUserPerms *p = (flgs & LOGIN_ANON) ? &g.anon : &g.perm;
11181155
if( nCap<0 ) nCap = strlen(zCap);
11191156
for(i=0; i<nCap && rc && zCap[i]; i++){
11201157
switch( zCap[i] ){
1121
- case 'a': rc = g.perm.Admin; break;
1122
- case 'b': rc = g.perm.Attach; break;
1123
- case 'c': rc = g.perm.ApndTkt; break;
1124
- case 'd': rc = g.perm.Delete; break;
1125
- case 'e': rc = g.perm.RdAddr; break;
1126
- case 'f': rc = g.perm.NewWiki; break;
1127
- case 'g': rc = g.perm.Clone; break;
1128
- case 'h': rc = g.perm.Hyperlink; break;
1129
- case 'i': rc = g.perm.Write; break;
1130
- case 'j': rc = g.perm.RdWiki; break;
1131
- case 'k': rc = g.perm.WrWiki; break;
1132
- case 'l': rc = g.perm.ModWiki; break;
1133
- case 'm': rc = g.perm.ApndWiki; break;
1134
- case 'n': rc = g.perm.NewTkt; break;
1135
- case 'o': rc = g.perm.Read; break;
1136
- case 'p': rc = g.perm.Password; break;
1137
- case 'q': rc = g.perm.ModTkt; break;
1138
- case 'r': rc = g.perm.RdTkt; break;
1139
- case 's': rc = g.perm.Setup; break;
1140
- case 't': rc = g.perm.TktFmt; break;
1158
+ case 'a': rc = p->Admin; break;
1159
+ case 'b': rc = p->Attach; break;
1160
+ case 'c': rc = p->ApndTkt; break;
1161
+ case 'd': rc = p->Delete; break;
1162
+ case 'e': rc = p->RdAddr; break;
1163
+ case 'f': rc = p->NewWiki; break;
1164
+ case 'g': rc = p->Clone; break;
1165
+ case 'h': rc = p->Hyperlink; break;
1166
+ case 'i': rc = p->Write; break;
1167
+ case 'j': rc = p->RdWiki; break;
1168
+ case 'k': rc = p->WrWiki; break;
1169
+ case 'l': rc = p->ModWiki; break;
1170
+ case 'm': rc = p->ApndWiki; break;
1171
+ case 'n': rc = p->NewTkt; break;
1172
+ case 'o': rc = p->Read; break;
1173
+ case 'p': rc = p->Password; break;
1174
+ case 'q': rc = p->ModTkt; break;
1175
+ case 'r': rc = p->RdTkt; break;
1176
+ case 's': rc = p->Setup; break;
1177
+ case 't': rc = p->TktFmt; break;
11411178
/* case 'u': READER */
11421179
/* case 'v': DEVELOPER */
1143
- case 'w': rc = g.perm.WrTkt; break;
1144
- case 'x': rc = g.perm.Private; break;
1180
+ case 'w': rc = p->WrTkt; break;
1181
+ case 'x': rc = p->Private; break;
11451182
/* case 'y': */
1146
- case 'z': rc = g.perm.Zip; break;
1183
+ case 'z': rc = p->Zip; break;
11471184
default: rc = 0; break;
11481185
}
11491186
}
11501187
return rc;
11511188
}
@@ -1195,11 +1232,11 @@
11951232
11961233
/*
11971234
** Call this routine when the credential check fails. It causes
11981235
** a redirect to the "login" page.
11991236
*/
1200
-void login_needed(void){
1237
+void login_needed(int anonOk){
12011238
#ifdef FOSSIL_ENABLE_JSON
12021239
if(g.json.isJsonMode){
12031240
json_err( FSL_JSON_E_DENIED, NULL, 1 );
12041241
fossil_exit(0);
12051242
/* NOTREACHED */
@@ -1206,11 +1243,23 @@
12061243
assert(0);
12071244
}else
12081245
#endif /* FOSSIL_ENABLE_JSON */
12091246
{
12101247
const char *zUrl = PD("REQUEST_URI", "index");
1211
- cgi_redirect(mprintf("login?g=%T", zUrl));
1248
+ const char *zQS = P("QUERY_STRING");
1249
+ Blob redir;
1250
+ blob_init(&redir, 0, 0);
1251
+ if( login_wants_https_redirect() ){
1252
+ blob_appendf(&redir, "%s/login?g=%T", g.zHttpsURL, zUrl);
1253
+ }else{
1254
+ blob_appendf(&redir, "%R/login?g=%T", zUrl);
1255
+ }
1256
+ if( anonOk ) blob_append(&redir, "&anon", 5);
1257
+ if( zQS && zQS[0] ){
1258
+ blob_appendf(&redir, "&%s", zQS);
1259
+ }
1260
+ cgi_redirect(blob_str(&redir));
12121261
/* NOTREACHED */
12131262
assert(0);
12141263
}
12151264
}
12161265
@@ -1219,14 +1268,11 @@
12191268
** the anonymous user has Hyperlink permission, then paint a mesage
12201269
** to inform the user that much more information is available by
12211270
** logging in as anonymous.
12221271
*/
12231272
void login_anonymous_available(void){
1224
- if( !g.perm.Hyperlink &&
1225
- db_exists("SELECT 1 FROM user"
1226
- " WHERE login='anonymous'"
1227
- " AND cap LIKE '%%h%%'") ){
1273
+ if( !g.perm.Hyperlink && g.anon.Hyperlink ){
12281274
const char *zUrl = PD("REQUEST_URI", "index");
12291275
@ <p>Many <span class="disabled">hyperlinks are disabled.</span><br />
12301276
@ Use <a href="%R/login?anon=1&amp;g=%T(zUrl)">anonymous login</a>
12311277
@ to enable hyperlinks.</p>
12321278
}
12331279
--- src/login.c
+++ src/login.c
@@ -352,16 +352,12 @@
352 login_cookie_path(), -86400);
353 db_multi_exec("UPDATE user SET cookie=NULL, ipaddr=NULL, "
354 " cexpire=0 WHERE uid=%d"
355 " AND login NOT IN ('anonymous','nobody',"
356 " 'developer','reader')", g.userUid);
357 cgi_replace_parameter(cookie, NULL)
358 /* At the time of this writing, cgi_replace_parameter() was
359 ** "NULL-value-safe", and I'm hoping the NULL doesn't cause any
360 ** downstream problems here. We could alternately use "" here.
361 */
362 ;
363 }
364 }
365
366 /*
367 ** Return true if the prefix of zStr matches zPattern. Return false if
@@ -451,27 +447,46 @@
451 }
452 sqlite3_result_int(context, rc);
453 }
454
455 /*
456 ** WEBPAGE: login
457 ** WEBPAGE: logout
458 ** WEBPAGE: my
459 **
460 ** Generate the login page.
461 **
 
 
 
 
 
 
 
 
 
462 ** There used to be a page named "my" that was designed to show information
463 ** about a specific user. The "my" page was linked from the "Logged in as USER"
464 ** line on the title bar. The "my" page was never completed so it is now
465 ** removed. Use this page as a placeholder in older installations.
 
 
 
 
 
 
 
 
 
 
466 */
467 void login_page(void){
468 const char *zUsername, *zPasswd;
469 const char *zNew1, *zNew2;
470 const char *zAnonPw = 0;
471 const char *zGoto = P("g");
472 int anonFlag;
473 char *zErrMsg = "";
474 int uid; /* User id logged in user */
475 char *zSha1Pw;
476 const char *zIpAddr; /* IP address of requestor */
477 const char *zReferer;
@@ -489,15 +504,20 @@
489 }
490 sqlite3_create_function(g.db, "constant_time_cmp", 2, SQLITE_UTF8, 0,
491 constant_time_cmp_function, 0, 0);
492 zUsername = P("u");
493 zPasswd = P("p");
494 anonFlag = P("anon")!=0;
495 if( P("out")!=0 ){
 
 
496 login_clear_login_data();
497 redirect_to_g();
 
498 }
 
 
499 if( g.perm.Password && zPasswd
500 && (zNew1 = P("n1"))!=0 && (zNew2 = P("n2"))!=0
501 ){
502 /* The user requests a password change */
503 zSha1Pw = sha1_shared_secret(zPasswd, g.zLogin, 0);
@@ -577,19 +597,40 @@
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 if( zGoto ){
587 @ <input type="hidden" name="g" value="%h(zGoto)" />
588 }else if( zReferer && strncmp(g.zBaseURL, zReferer, strlen(g.zBaseURL))==0 ){
589 @ <input type="hidden" name="g" value="%h(zReferer)" />
590 }
 
 
 
 
 
 
 
 
 
591 @ <table class="login_out">
592 @ <tr>
593 @ <td class="login_out_label">User ID:</td>
594 if( anonFlag ){
595 @ <td><input type="text" id="u" name="u" value="anonymous" size="30" /></td>
@@ -599,11 +640,11 @@
599 @ </tr>
600 @ <tr>
601 @ <td class="login_out_label">Password:</td>
602 @ <td><input type="password" id="p" name="p" value="" size="30" /></td>
603 @ </tr>
604 if( g.zLogin==0 ){
605 zAnonPw = db_text(0, "SELECT pw FROM user"
606 " WHERE login='anonymous'"
607 " AND cap!=''");
608 }
609 @ <tr>
@@ -624,20 +665,11 @@
624 @ form.action = "%h(zSSL)/login";
625 @ }
626 }
627 @ }
628 @ </script>
629 if( g.zLogin==0 ){
630 @ <p>Enter
631 }else{
632 @ <p>You are currently logged in as <b>%h(g.zLogin)</b></p>
633 @ <p>To change your login to a different user, enter
634 }
635 @ your user-id and password at the left and press the
636 @ "Login" button. Your user name will be stored in a browser cookie.
637 @ You must configure your web browser to accept cookies in order for
638 @ the login to take.</p>
639 if( db_get_boolean("self-register", 0) ){
640 @ <p>If you do not have an account, you can
641 @ <a href="%R/register?g=%T(P("G"))">create one</a>.
642 }
643 if( zAnonPw ){
@@ -657,22 +689,14 @@
657 @ onclick="gebi('u').value='anonymous'; gebi('p').value='%s(zDecoded)';" />
658 }
659 @ </div>
660 free(zCaptcha);
661 }
662 if( g.zLogin ){
663 @ <hr />
664 @ <p>To log off the system (and delete your login cookie)
665 @ press the following button:<br />
666 @ <input type="submit" name="out" value="Logout" /></p>
667 }
668 @ </form>
669 if( g.perm.Password ){
670 @ <hr />
671 @ <p>To change your password, enter your old password and your
672 @ new password twice below then press the "Change Password"
673 @ button.</p>
674 form_begin(0, "%R/login");
675 @ <table>
676 @ <tr><td class="login_out_label">Old Password:</td>
677 @ <td><input type="password" name="p" size="30" /></td></tr>
678 @ <tr><td class="login_out_label">New Password:</td>
@@ -811,10 +835,11 @@
811 ** variables appropriately.
812 **
813 ** g.userUid Database USER.UID value. Might be -1 for "nobody"
814 ** g.zLogin Database USER.LOGIN value. NULL for user "nobody"
815 ** g.perm Permissions granted to this user
 
816 ** g.isHuman True if the user is human, not a spider or robot
817 **
818 */
819 void login_check_credentials(void){
820 int uid = 0; /* User id */
@@ -1002,23 +1027,32 @@
1002 ** Memory of settings
1003 */
1004 static int login_anon_once = 1;
1005
1006 /*
1007 ** Add the default privileges of users "nobody" and "anonymous" as appropriate
1008 ** for the user g.zLogin.
 
 
 
 
1009 */
1010 void login_set_anon_nobody_capabilities(void){
1011 if( g.zLogin && login_anon_once ){
1012 const char *zCap;
1013 /* All logged-in users inherit privileges from "nobody" */
1014 zCap = db_text("", "SELECT cap FROM user WHERE login = 'nobody'");
1015 login_set_capabilities(zCap, 0);
1016 if( fossil_strcmp(g.zLogin, "nobody")!=0 ){
 
1017 /* All logged-in users inherit privileges from "anonymous" */
1018 zCap = db_text("", "SELECT cap FROM user WHERE login = 'anonymous'");
1019 login_set_capabilities(zCap, 0);
 
 
 
 
 
1020 }
1021 login_anon_once = 0;
1022 }
1023 }
1024
@@ -1025,55 +1059,57 @@
1025 /*
1026 ** Flags passed into the 2nd argument of login_set/replace_capabilities().
1027 */
1028 #if INTERFACE
1029 #define LOGIN_IGNORE_UV 0x01 /* Ignore "u" and "v" */
 
1030 #endif
1031
1032 /*
1033 ** Adds all capability flags in zCap to g.perm.
1034 */
1035 void login_set_capabilities(const char *zCap, unsigned flags){
1036 int i;
 
1037 if(NULL==zCap){
1038 return;
1039 }
1040 for(i=0; zCap[i]; i++){
1041 switch( zCap[i] ){
1042 case 's': g.perm.Setup = 1; /* Fall thru into Admin */
1043 case 'a': g.perm.Admin = g.perm.RdTkt = g.perm.WrTkt = g.perm.Zip =
1044 g.perm.RdWiki = g.perm.WrWiki = g.perm.NewWiki =
1045 g.perm.ApndWiki = g.perm.Hyperlink = g.perm.Clone =
1046 g.perm.NewTkt = g.perm.Password = g.perm.RdAddr =
1047 g.perm.TktFmt = g.perm.Attach = g.perm.ApndTkt =
1048 g.perm.ModWiki = g.perm.ModTkt = 1;
1049 /* Fall thru into Read/Write */
1050 case 'i': g.perm.Read = g.perm.Write = 1; break;
1051 case 'o': g.perm.Read = 1; break;
1052 case 'z': g.perm.Zip = 1; break;
1053
1054 case 'd': g.perm.Delete = 1; break;
1055 case 'h': g.perm.Hyperlink = 1; break;
1056 case 'g': g.perm.Clone = 1; break;
1057 case 'p': g.perm.Password = 1; break;
1058
1059 case 'j': g.perm.RdWiki = 1; break;
1060 case 'k': g.perm.WrWiki = g.perm.RdWiki = g.perm.ApndWiki =1; break;
1061 case 'm': g.perm.ApndWiki = 1; break;
1062 case 'f': g.perm.NewWiki = 1; break;
1063 case 'l': g.perm.ModWiki = 1; break;
1064
1065 case 'e': g.perm.RdAddr = 1; break;
1066 case 'r': g.perm.RdTkt = 1; break;
1067 case 'n': g.perm.NewTkt = 1; break;
1068 case 'w': g.perm.WrTkt = g.perm.RdTkt = g.perm.NewTkt =
1069 g.perm.ApndTkt = 1; break;
1070 case 'c': g.perm.ApndTkt = 1; break;
1071 case 'q': g.perm.ModTkt = 1; break;
1072 case 't': g.perm.TktFmt = 1; break;
1073 case 'b': g.perm.Attach = 1; break;
1074 case 'x': g.perm.Private = 1; break;
1075
1076 /* The "u" privileges is a little different. It recursively
1077 ** inherits all privileges of the user named "reader" */
1078 case 'u': {
1079 if( (flags & LOGIN_IGNORE_UV)==0 ){
@@ -1110,42 +1146,43 @@
1110 /*
1111 ** If the current login lacks any of the capabilities listed in
1112 ** the input, then return 0. If all capabilities are present, then
1113 ** return 1.
1114 */
1115 int login_has_capability(const char *zCap, int nCap){
1116 int i;
1117 int rc = 1;
 
1118 if( nCap<0 ) nCap = strlen(zCap);
1119 for(i=0; i<nCap && rc && zCap[i]; i++){
1120 switch( zCap[i] ){
1121 case 'a': rc = g.perm.Admin; break;
1122 case 'b': rc = g.perm.Attach; break;
1123 case 'c': rc = g.perm.ApndTkt; break;
1124 case 'd': rc = g.perm.Delete; break;
1125 case 'e': rc = g.perm.RdAddr; break;
1126 case 'f': rc = g.perm.NewWiki; break;
1127 case 'g': rc = g.perm.Clone; break;
1128 case 'h': rc = g.perm.Hyperlink; break;
1129 case 'i': rc = g.perm.Write; break;
1130 case 'j': rc = g.perm.RdWiki; break;
1131 case 'k': rc = g.perm.WrWiki; break;
1132 case 'l': rc = g.perm.ModWiki; break;
1133 case 'm': rc = g.perm.ApndWiki; break;
1134 case 'n': rc = g.perm.NewTkt; break;
1135 case 'o': rc = g.perm.Read; break;
1136 case 'p': rc = g.perm.Password; break;
1137 case 'q': rc = g.perm.ModTkt; break;
1138 case 'r': rc = g.perm.RdTkt; break;
1139 case 's': rc = g.perm.Setup; break;
1140 case 't': rc = g.perm.TktFmt; break;
1141 /* case 'u': READER */
1142 /* case 'v': DEVELOPER */
1143 case 'w': rc = g.perm.WrTkt; break;
1144 case 'x': rc = g.perm.Private; break;
1145 /* case 'y': */
1146 case 'z': rc = g.perm.Zip; break;
1147 default: rc = 0; break;
1148 }
1149 }
1150 return rc;
1151 }
@@ -1195,11 +1232,11 @@
1195
1196 /*
1197 ** Call this routine when the credential check fails. It causes
1198 ** a redirect to the "login" page.
1199 */
1200 void login_needed(void){
1201 #ifdef FOSSIL_ENABLE_JSON
1202 if(g.json.isJsonMode){
1203 json_err( FSL_JSON_E_DENIED, NULL, 1 );
1204 fossil_exit(0);
1205 /* NOTREACHED */
@@ -1206,11 +1243,23 @@
1206 assert(0);
1207 }else
1208 #endif /* FOSSIL_ENABLE_JSON */
1209 {
1210 const char *zUrl = PD("REQUEST_URI", "index");
1211 cgi_redirect(mprintf("login?g=%T", zUrl));
 
 
 
 
 
 
 
 
 
 
 
 
1212 /* NOTREACHED */
1213 assert(0);
1214 }
1215 }
1216
@@ -1219,14 +1268,11 @@
1219 ** the anonymous user has Hyperlink permission, then paint a mesage
1220 ** to inform the user that much more information is available by
1221 ** logging in as anonymous.
1222 */
1223 void login_anonymous_available(void){
1224 if( !g.perm.Hyperlink &&
1225 db_exists("SELECT 1 FROM user"
1226 " WHERE login='anonymous'"
1227 " AND cap LIKE '%%h%%'") ){
1228 const char *zUrl = PD("REQUEST_URI", "index");
1229 @ <p>Many <span class="disabled">hyperlinks are disabled.</span><br />
1230 @ Use <a href="%R/login?anon=1&amp;g=%T(zUrl)">anonymous login</a>
1231 @ to enable hyperlinks.</p>
1232 }
1233
--- src/login.c
+++ src/login.c
@@ -352,16 +352,12 @@
352 login_cookie_path(), -86400);
353 db_multi_exec("UPDATE user SET cookie=NULL, ipaddr=NULL, "
354 " cexpire=0 WHERE uid=%d"
355 " AND login NOT IN ('anonymous','nobody',"
356 " 'developer','reader')", g.userUid);
357 cgi_replace_parameter(cookie, NULL);
358 cgi_replace_parameter("anon", NULL);
 
 
 
 
359 }
360 }
361
362 /*
363 ** Return true if the prefix of zStr matches zPattern. Return false if
@@ -451,27 +447,46 @@
447 }
448 sqlite3_result_int(context, rc);
449 }
450
451 /*
452 ** Return true if the current page was reached by a redirect from the /login
453 ** page.
454 */
455 int referred_from_login(void){
456 const char *zReferer = P("HTTP_REFERER");
457 char *zPattern;
458 int rc;
459 if( zReferer==0 ) return 0;
460 zPattern = mprintf("%s/login*", g.zBaseURL);
461 rc = sqlite3_strglob(zPattern, zReferer)==0;
462 fossil_free(zPattern);
463 return rc;
464 }
465
466 /*
467 ** There used to be a page named "my" that was designed to show information
468 ** about a specific user. The "my" page was linked from the "Logged in as USER"
469 ** line on the title bar. The "my" page was never completed so it is now
470 ** removed. Use this page as a placeholder in older installations.
471 **
472 ** WEBPAGE: login
473 ** WEBPAGE: logout
474 ** WEBPAGE: my
475 **
476 ** The login/logout page. Parameters:
477 **
478 ** g=URL Jump back to this URL after login completes
479 ** anon The g=URL is not accessible by "nobody" but is
480 ** accessible by "anonymous"
481 */
482 void login_page(void){
483 const char *zUsername, *zPasswd;
484 const char *zNew1, *zNew2;
485 const char *zAnonPw = 0;
486 const char *zGoto = P("g");
487 int anonFlag; /* Login as "anonymous" would be useful */
488 char *zErrMsg = "";
489 int uid; /* User id logged in user */
490 char *zSha1Pw;
491 const char *zIpAddr; /* IP address of requestor */
492 const char *zReferer;
@@ -489,15 +504,20 @@
504 }
505 sqlite3_create_function(g.db, "constant_time_cmp", 2, SQLITE_UTF8, 0,
506 constant_time_cmp_function, 0, 0);
507 zUsername = P("u");
508 zPasswd = P("p");
509 anonFlag = g.zLogin==0 && PB("anon");
510
511 /* Handle log-out requests */
512 if( P("out") ){
513 login_clear_login_data();
514 redirect_to_g();
515 return;
516 }
517
518 /* Deal with password-change requests */
519 if( g.perm.Password && zPasswd
520 && (zNew1 = P("n1"))!=0 && (zNew2 = P("n2"))!=0
521 ){
522 /* The user requests a password change */
523 zSha1Pw = sha1_shared_secret(zPasswd, g.zLogin, 0);
@@ -577,19 +597,40 @@
597 }
598 }
599 style_header("Login/Logout");
600 style_adunit_config(ADUNIT_OFF);
601 @ %s(zErrMsg)
602 if( zGoto ){
603 char *zAbbrev = fossil_strdup(zGoto);
604 int i;
605 for(i=0; zAbbrev[i] && zAbbrev[i]!='?'; i++){}
606 zAbbrev[i] = 0;
607 if( g.zLogin ){
608 @ <p>Use a different login with greater privilege that <b>%h(g.zLogin)</b>
609 @ to access <b>%h(zAbbrev)</b>.
610 }else if( anonFlag ){
611 @ <p>Login as <b>anonymous</b> or any named user
612 @ to access page <b>%h(zAbbrev)</b>.
613 }else{
614 @ <p>Login as a named user to access page <b>%h(zAbbrev)</b>.
615 }
616 }
617 form_begin(0, "%R/login");
618 if( zGoto ){
619 @ <input type="hidden" name="g" value="%h(zGoto)" />
620 }else if( zReferer && strncmp(g.zBaseURL, zReferer, strlen(g.zBaseURL))==0 ){
621 @ <input type="hidden" name="g" value="%h(zReferer)" />
622 }
623 if( anonFlag ){
624 @ <input type="hidden" name="anon" value="1" />
625 }
626 if( g.zLogin ){
627 @ <p>Currently logged in as <b>%h(g.zLogin)</b>.
628 @ <input type="submit" name="out" value="Logout"></p>
629 @ <hr />
630 @ <p>Change user:
631 }
632 @ <table class="login_out">
633 @ <tr>
634 @ <td class="login_out_label">User ID:</td>
635 if( anonFlag ){
636 @ <td><input type="text" id="u" name="u" value="anonymous" size="30" /></td>
@@ -599,11 +640,11 @@
640 @ </tr>
641 @ <tr>
642 @ <td class="login_out_label">Password:</td>
643 @ <td><input type="password" id="p" name="p" value="" size="30" /></td>
644 @ </tr>
645 if( g.zLogin==0 && (anonFlag || zGoto==0) ){
646 zAnonPw = db_text(0, "SELECT pw FROM user"
647 " WHERE login='anonymous'"
648 " AND cap!=''");
649 }
650 @ <tr>
@@ -624,20 +665,11 @@
665 @ form.action = "%h(zSSL)/login";
666 @ }
667 }
668 @ }
669 @ </script>
670 @ <p>Pressing the Login button grants permission to store a cookie.</p>
 
 
 
 
 
 
 
 
 
671 if( db_get_boolean("self-register", 0) ){
672 @ <p>If you do not have an account, you can
673 @ <a href="%R/register?g=%T(P("G"))">create one</a>.
674 }
675 if( zAnonPw ){
@@ -657,22 +689,14 @@
689 @ onclick="gebi('u').value='anonymous'; gebi('p').value='%s(zDecoded)';" />
690 }
691 @ </div>
692 free(zCaptcha);
693 }
 
 
 
 
 
 
694 @ </form>
695 if( g.perm.Password ){
696 @ <hr />
697 @ <p>Change Password for user <b>%h(g.zLogin)</b>:</p>
 
 
698 form_begin(0, "%R/login");
699 @ <table>
700 @ <tr><td class="login_out_label">Old Password:</td>
701 @ <td><input type="password" name="p" size="30" /></td></tr>
702 @ <tr><td class="login_out_label">New Password:</td>
@@ -811,10 +835,11 @@
835 ** variables appropriately.
836 **
837 ** g.userUid Database USER.UID value. Might be -1 for "nobody"
838 ** g.zLogin Database USER.LOGIN value. NULL for user "nobody"
839 ** g.perm Permissions granted to this user
840 ** g.anon Permissions that would be available to anonymous
841 ** g.isHuman True if the user is human, not a spider or robot
842 **
843 */
844 void login_check_credentials(void){
845 int uid = 0; /* User id */
@@ -1002,23 +1027,32 @@
1027 ** Memory of settings
1028 */
1029 static int login_anon_once = 1;
1030
1031 /*
1032 ** Add to g.perm the default privileges of users "nobody" and/or "anonymous"
1033 ** as appropriate for the user g.zLogin.
1034 **
1035 ** This routine also sets up g.anon to be either a copy of g.perm for
1036 ** all logged in uses, or the privileges that would be available to "anonymous"
1037 ** if g.zLogin==0 (meaning that the user is "nobody").
1038 */
1039 void login_set_anon_nobody_capabilities(void){
1040 if( login_anon_once ){
1041 const char *zCap;
1042 /* All users get privileges from "nobody" */
1043 zCap = db_text("", "SELECT cap FROM user WHERE login = 'nobody'");
1044 login_set_capabilities(zCap, 0);
1045 zCap = db_text("", "SELECT cap FROM user WHERE login = 'anonymous'");
1046 if( g.zLogin && fossil_strcmp(g.zLogin, "nobody")!=0 ){
1047 /* All logged-in users inherit privileges from "anonymous" */
 
1048 login_set_capabilities(zCap, 0);
1049 g.anon = g.perm;
1050 }else{
1051 /* Record the privileges of anonymous in g.anon */
1052 g.anon = g.perm;
1053 login_set_capabilities(zCap, LOGIN_ANON);
1054 }
1055 login_anon_once = 0;
1056 }
1057 }
1058
@@ -1025,55 +1059,57 @@
1059 /*
1060 ** Flags passed into the 2nd argument of login_set/replace_capabilities().
1061 */
1062 #if INTERFACE
1063 #define LOGIN_IGNORE_UV 0x01 /* Ignore "u" and "v" */
1064 #define LOGIN_ANON 0x02 /* Use g.anon instead of g.perm */
1065 #endif
1066
1067 /*
1068 ** Adds all capability flags in zCap to g.perm or g.anon.
1069 */
1070 void login_set_capabilities(const char *zCap, unsigned flags){
1071 int i;
1072 FossilUserPerms *p = (flags & LOGIN_ANON) ? &g.anon : &g.perm;
1073 if(NULL==zCap){
1074 return;
1075 }
1076 for(i=0; zCap[i]; i++){
1077 switch( zCap[i] ){
1078 case 's': p->Setup = 1; /* Fall thru into Admin */
1079 case 'a': p->Admin = p->RdTkt = p->WrTkt = p->Zip =
1080 p->RdWiki = p->WrWiki = p->NewWiki =
1081 p->ApndWiki = p->Hyperlink = p->Clone =
1082 p->NewTkt = p->Password = p->RdAddr =
1083 p->TktFmt = p->Attach = p->ApndTkt =
1084 p->ModWiki = p->ModTkt = 1;
1085 /* Fall thru into Read/Write */
1086 case 'i': p->Read = p->Write = 1; break;
1087 case 'o': p->Read = 1; break;
1088 case 'z': p->Zip = 1; break;
1089
1090 case 'd': p->Delete = 1; break;
1091 case 'h': p->Hyperlink = 1; break;
1092 case 'g': p->Clone = 1; break;
1093 case 'p': p->Password = 1; break;
1094
1095 case 'j': p->RdWiki = 1; break;
1096 case 'k': p->WrWiki = p->RdWiki = p->ApndWiki =1; break;
1097 case 'm': p->ApndWiki = 1; break;
1098 case 'f': p->NewWiki = 1; break;
1099 case 'l': p->ModWiki = 1; break;
1100
1101 case 'e': p->RdAddr = 1; break;
1102 case 'r': p->RdTkt = 1; break;
1103 case 'n': p->NewTkt = 1; break;
1104 case 'w': p->WrTkt = p->RdTkt = p->NewTkt =
1105 p->ApndTkt = 1; break;
1106 case 'c': p->ApndTkt = 1; break;
1107 case 'q': p->ModTkt = 1; break;
1108 case 't': p->TktFmt = 1; break;
1109 case 'b': p->Attach = 1; break;
1110 case 'x': p->Private = 1; break;
1111
1112 /* The "u" privileges is a little different. It recursively
1113 ** inherits all privileges of the user named "reader" */
1114 case 'u': {
1115 if( (flags & LOGIN_IGNORE_UV)==0 ){
@@ -1110,42 +1146,43 @@
1146 /*
1147 ** If the current login lacks any of the capabilities listed in
1148 ** the input, then return 0. If all capabilities are present, then
1149 ** return 1.
1150 */
1151 int login_has_capability(const char *zCap, int nCap, u32 flgs){
1152 int i;
1153 int rc = 1;
1154 FossilUserPerms *p = (flgs & LOGIN_ANON) ? &g.anon : &g.perm;
1155 if( nCap<0 ) nCap = strlen(zCap);
1156 for(i=0; i<nCap && rc && zCap[i]; i++){
1157 switch( zCap[i] ){
1158 case 'a': rc = p->Admin; break;
1159 case 'b': rc = p->Attach; break;
1160 case 'c': rc = p->ApndTkt; break;
1161 case 'd': rc = p->Delete; break;
1162 case 'e': rc = p->RdAddr; break;
1163 case 'f': rc = p->NewWiki; break;
1164 case 'g': rc = p->Clone; break;
1165 case 'h': rc = p->Hyperlink; break;
1166 case 'i': rc = p->Write; break;
1167 case 'j': rc = p->RdWiki; break;
1168 case 'k': rc = p->WrWiki; break;
1169 case 'l': rc = p->ModWiki; break;
1170 case 'm': rc = p->ApndWiki; break;
1171 case 'n': rc = p->NewTkt; break;
1172 case 'o': rc = p->Read; break;
1173 case 'p': rc = p->Password; break;
1174 case 'q': rc = p->ModTkt; break;
1175 case 'r': rc = p->RdTkt; break;
1176 case 's': rc = p->Setup; break;
1177 case 't': rc = p->TktFmt; break;
1178 /* case 'u': READER */
1179 /* case 'v': DEVELOPER */
1180 case 'w': rc = p->WrTkt; break;
1181 case 'x': rc = p->Private; break;
1182 /* case 'y': */
1183 case 'z': rc = p->Zip; break;
1184 default: rc = 0; break;
1185 }
1186 }
1187 return rc;
1188 }
@@ -1195,11 +1232,11 @@
1232
1233 /*
1234 ** Call this routine when the credential check fails. It causes
1235 ** a redirect to the "login" page.
1236 */
1237 void login_needed(int anonOk){
1238 #ifdef FOSSIL_ENABLE_JSON
1239 if(g.json.isJsonMode){
1240 json_err( FSL_JSON_E_DENIED, NULL, 1 );
1241 fossil_exit(0);
1242 /* NOTREACHED */
@@ -1206,11 +1243,23 @@
1243 assert(0);
1244 }else
1245 #endif /* FOSSIL_ENABLE_JSON */
1246 {
1247 const char *zUrl = PD("REQUEST_URI", "index");
1248 const char *zQS = P("QUERY_STRING");
1249 Blob redir;
1250 blob_init(&redir, 0, 0);
1251 if( login_wants_https_redirect() ){
1252 blob_appendf(&redir, "%s/login?g=%T", g.zHttpsURL, zUrl);
1253 }else{
1254 blob_appendf(&redir, "%R/login?g=%T", zUrl);
1255 }
1256 if( anonOk ) blob_append(&redir, "&anon", 5);
1257 if( zQS && zQS[0] ){
1258 blob_appendf(&redir, "&%s", zQS);
1259 }
1260 cgi_redirect(blob_str(&redir));
1261 /* NOTREACHED */
1262 assert(0);
1263 }
1264 }
1265
@@ -1219,14 +1268,11 @@
1268 ** the anonymous user has Hyperlink permission, then paint a mesage
1269 ** to inform the user that much more information is available by
1270 ** logging in as anonymous.
1271 */
1272 void login_anonymous_available(void){
1273 if( !g.perm.Hyperlink && g.anon.Hyperlink ){
 
 
 
1274 const char *zUrl = PD("REQUEST_URI", "index");
1275 @ <p>Many <span class="disabled">hyperlinks are disabled.</span><br />
1276 @ Use <a href="%R/login?anon=1&amp;g=%T(zUrl)">anonymous login</a>
1277 @ to enable hyperlinks.</p>
1278 }
1279
+6 -1
--- src/main.c
+++ src/main.c
@@ -193,12 +193,17 @@
193193
/* Information used to populate the RCVFROM table */
194194
int rcvid; /* The rcvid. 0 if not yet defined. */
195195
char *zIpAddr; /* The remote IP address */
196196
char *zNonce; /* The nonce used for login */
197197
198
- /* permissions used by the server */
198
+ /* permissions available to current user */
199199
struct FossilUserPerms perm;
200
+
201
+ /* permissions available to current user or to "anonymous".
202
+ ** This is the logical union of perm permissions above with
203
+ ** the value that perm would take if g.zLogin were "anonymous". */
204
+ struct FossilUserPerms anon;
200205
201206
#ifdef FOSSIL_ENABLE_TCL
202207
/* all Tcl related context necessary for integration */
203208
struct TclContext tcl;
204209
#endif
205210
--- src/main.c
+++ src/main.c
@@ -193,12 +193,17 @@
193 /* Information used to populate the RCVFROM table */
194 int rcvid; /* The rcvid. 0 if not yet defined. */
195 char *zIpAddr; /* The remote IP address */
196 char *zNonce; /* The nonce used for login */
197
198 /* permissions used by the server */
199 struct FossilUserPerms perm;
 
 
 
 
 
200
201 #ifdef FOSSIL_ENABLE_TCL
202 /* all Tcl related context necessary for integration */
203 struct TclContext tcl;
204 #endif
205
--- src/main.c
+++ src/main.c
@@ -193,12 +193,17 @@
193 /* Information used to populate the RCVFROM table */
194 int rcvid; /* The rcvid. 0 if not yet defined. */
195 char *zIpAddr; /* The remote IP address */
196 char *zNonce; /* The nonce used for login */
197
198 /* permissions available to current user */
199 struct FossilUserPerms perm;
200
201 /* permissions available to current user or to "anonymous".
202 ** This is the logical union of perm permissions above with
203 ** the value that perm would take if g.zLogin were "anonymous". */
204 struct FossilUserPerms anon;
205
206 #ifdef FOSSIL_ENABLE_TCL
207 /* all Tcl related context necessary for integration */
208 struct TclContext tcl;
209 #endif
210
+4 -1
--- src/moderate.c
+++ src/moderate.c
@@ -144,11 +144,14 @@
144144
void modreq_page(void){
145145
Blob sql;
146146
Stmt q;
147147
148148
login_check_credentials();
149
- if( !g.perm.RdWiki && !g.perm.RdTkt ){ login_needed(); return; }
149
+ if( !g.perm.RdWiki && !g.perm.RdTkt ){
150
+ login_needed(g.anon.RdWiki && g.anon.RdTkt);
151
+ return;
152
+ }
150153
style_header("Pending Moderation Requests");
151154
@ <h2>All Pending Moderation Requests</h2>
152155
if( moderation_table_exists() ){
153156
blob_init(&sql, timeline_query_for_www(), -1);
154157
blob_append_sql(&sql,
155158
--- src/moderate.c
+++ src/moderate.c
@@ -144,11 +144,14 @@
144 void modreq_page(void){
145 Blob sql;
146 Stmt q;
147
148 login_check_credentials();
149 if( !g.perm.RdWiki && !g.perm.RdTkt ){ login_needed(); return; }
 
 
 
150 style_header("Pending Moderation Requests");
151 @ <h2>All Pending Moderation Requests</h2>
152 if( moderation_table_exists() ){
153 blob_init(&sql, timeline_query_for_www(), -1);
154 blob_append_sql(&sql,
155
--- src/moderate.c
+++ src/moderate.c
@@ -144,11 +144,14 @@
144 void modreq_page(void){
145 Blob sql;
146 Stmt q;
147
148 login_check_credentials();
149 if( !g.perm.RdWiki && !g.perm.RdTkt ){
150 login_needed(g.anon.RdWiki && g.anon.RdTkt);
151 return;
152 }
153 style_header("Pending Moderation Requests");
154 @ <h2>All Pending Moderation Requests</h2>
155 if( moderation_table_exists() ){
156 blob_init(&sql, timeline_query_for_www(), -1);
157 blob_append_sql(&sql,
158
+2 -2
--- src/name.c
+++ src/name.c
@@ -987,11 +987,11 @@
987987
int n = atoi(PD("n","5000"));
988988
int mx = db_int(0, "SELECT max(rid) FROM blob");
989989
char *zRange;
990990
991991
login_check_credentials();
992
- if( !g.perm.Read ){ login_needed(); return; }
992
+ if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
993993
style_header("List Of Artifacts");
994994
if( mx>n && P("s")==0 ){
995995
int i;
996996
@ <p>Select a range of artifacts to view:</p>
997997
@ <ul>
@@ -1083,11 +1083,11 @@
10831083
int cnt;
10841084
char *azHit[MAX_COLLIDE];
10851085
char z[UUID_SIZE+1];
10861086
} aCollide[UUID_SIZE+1];
10871087
login_check_credentials();
1088
- if( !g.perm.Read ){ login_needed(); return; }
1088
+ if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
10891089
memset(aCollide, 0, sizeof(aCollide));
10901090
memset(zPrev, 0, sizeof(zPrev));
10911091
db_prepare(&q,"SELECT uuid FROM blob ORDER BY 1");
10921092
while( db_step(&q)==SQLITE_ROW ){
10931093
const char *zUuid = db_column_text(&q,0);
10941094
--- src/name.c
+++ src/name.c
@@ -987,11 +987,11 @@
987 int n = atoi(PD("n","5000"));
988 int mx = db_int(0, "SELECT max(rid) FROM blob");
989 char *zRange;
990
991 login_check_credentials();
992 if( !g.perm.Read ){ login_needed(); return; }
993 style_header("List Of Artifacts");
994 if( mx>n && P("s")==0 ){
995 int i;
996 @ <p>Select a range of artifacts to view:</p>
997 @ <ul>
@@ -1083,11 +1083,11 @@
1083 int cnt;
1084 char *azHit[MAX_COLLIDE];
1085 char z[UUID_SIZE+1];
1086 } aCollide[UUID_SIZE+1];
1087 login_check_credentials();
1088 if( !g.perm.Read ){ login_needed(); return; }
1089 memset(aCollide, 0, sizeof(aCollide));
1090 memset(zPrev, 0, sizeof(zPrev));
1091 db_prepare(&q,"SELECT uuid FROM blob ORDER BY 1");
1092 while( db_step(&q)==SQLITE_ROW ){
1093 const char *zUuid = db_column_text(&q,0);
1094
--- src/name.c
+++ src/name.c
@@ -987,11 +987,11 @@
987 int n = atoi(PD("n","5000"));
988 int mx = db_int(0, "SELECT max(rid) FROM blob");
989 char *zRange;
990
991 login_check_credentials();
992 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
993 style_header("List Of Artifacts");
994 if( mx>n && P("s")==0 ){
995 int i;
996 @ <p>Select a range of artifacts to view:</p>
997 @ <ul>
@@ -1083,11 +1083,11 @@
1083 int cnt;
1084 char *azHit[MAX_COLLIDE];
1085 char z[UUID_SIZE+1];
1086 } aCollide[UUID_SIZE+1];
1087 login_check_credentials();
1088 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1089 memset(aCollide, 0, sizeof(aCollide));
1090 memset(zPrev, 0, sizeof(zPrev));
1091 db_prepare(&q,"SELECT uuid FROM blob ORDER BY 1");
1092 while( db_step(&q)==SQLITE_ROW ){
1093 const char *zUuid = db_column_text(&q,0);
1094
+1 -1
--- src/path.c
+++ src/path.c
@@ -543,11 +543,11 @@
543543
*/
544544
void test_rename_list_page(void){
545545
Stmt q;
546546
547547
login_check_credentials();
548
- if( !g.perm.Read ){ login_needed(); return; }
548
+ if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
549549
style_header("List Of File Name Changes");
550550
@ <h3>NB: Experimental Page</h3>
551551
@ <table border="1" width="100%%">
552552
@ <tr><th>Date &amp; Time</th>
553553
@ <th>Old Name</th>
554554
--- src/path.c
+++ src/path.c
@@ -543,11 +543,11 @@
543 */
544 void test_rename_list_page(void){
545 Stmt q;
546
547 login_check_credentials();
548 if( !g.perm.Read ){ login_needed(); return; }
549 style_header("List Of File Name Changes");
550 @ <h3>NB: Experimental Page</h3>
551 @ <table border="1" width="100%%">
552 @ <tr><th>Date &amp; Time</th>
553 @ <th>Old Name</th>
554
--- src/path.c
+++ src/path.c
@@ -543,11 +543,11 @@
543 */
544 void test_rename_list_page(void){
545 Stmt q;
546
547 login_check_credentials();
548 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
549 style_header("List Of File Name Changes");
550 @ <h3>NB: Experimental Page</h3>
551 @ <table border="1" width="100%%">
552 @ <tr><th>Date &amp; Time</th>
553 @ <th>Old Name</th>
554
+7 -4
--- src/report.c
+++ src/report.c
@@ -40,11 +40,14 @@
4040
Stmt q;
4141
int rn = 0;
4242
int cnt = 0;
4343
4444
login_check_credentials();
45
- if( !g.perm.RdTkt && !g.perm.NewTkt ){ login_needed(); return; }
45
+ if( !g.perm.RdTkt && !g.perm.NewTkt ){
46
+ login_needed(g.anon.RdTkt || g.anon.NewTkt);
47
+ return;
48
+ }
4649
style_header("Ticket Main Menu");
4750
ticket_standard_submenu(T_ALL_BUT(T_REPLIST));
4851
if( g.thTrace ) Th_Trace("BEGIN_REPORTLIST<br />\n", -1);
4952
zScript = ticket_reportlist_code();
5053
if( g.thTrace ) Th_Trace("BEGIN_REPORTLIST_SCRIPT<br />\n", -1);
@@ -293,11 +296,11 @@
293296
const char *zClrKey;
294297
Stmt q;
295298
296299
login_check_credentials();
297300
if( !g.perm.TktFmt ){
298
- login_needed();
301
+ login_needed(g.anon.TktFmt);
299302
return;
300303
}
301304
rn = atoi(PD("rn","0"));
302305
db_prepare(&q, "SELECT title, sqlcode, owner, cols "
303306
"FROM reportfmt WHERE rn=%d",rn);
@@ -343,11 +346,11 @@
343346
char *zSQL;
344347
char *zErr = 0;
345348
346349
login_check_credentials();
347350
if( !g.perm.TktFmt ){
348
- login_needed();
351
+ login_needed(g.anon.TktFmt);
349352
return;
350353
}
351354
/*view_add_functions(0);*/
352355
rn = atoi(PD("rn","0"));
353356
zTitle = P("t");
@@ -1078,11 +1081,11 @@
10781081
Stmt q;
10791082
char *zErr1 = 0;
10801083
char *zErr2 = 0;
10811084
10821085
login_check_credentials();
1083
- if( !g.perm.RdTkt ){ login_needed(); return; }
1086
+ if( !g.perm.RdTkt ){ login_needed(g.anon.RdTkt); return; }
10841087
rn = atoi(PD("rn","0"));
10851088
if( rn==0 ){
10861089
cgi_redirect("reportlist");
10871090
return;
10881091
}
10891092
--- src/report.c
+++ src/report.c
@@ -40,11 +40,14 @@
40 Stmt q;
41 int rn = 0;
42 int cnt = 0;
43
44 login_check_credentials();
45 if( !g.perm.RdTkt && !g.perm.NewTkt ){ login_needed(); return; }
 
 
 
46 style_header("Ticket Main Menu");
47 ticket_standard_submenu(T_ALL_BUT(T_REPLIST));
48 if( g.thTrace ) Th_Trace("BEGIN_REPORTLIST<br />\n", -1);
49 zScript = ticket_reportlist_code();
50 if( g.thTrace ) Th_Trace("BEGIN_REPORTLIST_SCRIPT<br />\n", -1);
@@ -293,11 +296,11 @@
293 const char *zClrKey;
294 Stmt q;
295
296 login_check_credentials();
297 if( !g.perm.TktFmt ){
298 login_needed();
299 return;
300 }
301 rn = atoi(PD("rn","0"));
302 db_prepare(&q, "SELECT title, sqlcode, owner, cols "
303 "FROM reportfmt WHERE rn=%d",rn);
@@ -343,11 +346,11 @@
343 char *zSQL;
344 char *zErr = 0;
345
346 login_check_credentials();
347 if( !g.perm.TktFmt ){
348 login_needed();
349 return;
350 }
351 /*view_add_functions(0);*/
352 rn = atoi(PD("rn","0"));
353 zTitle = P("t");
@@ -1078,11 +1081,11 @@
1078 Stmt q;
1079 char *zErr1 = 0;
1080 char *zErr2 = 0;
1081
1082 login_check_credentials();
1083 if( !g.perm.RdTkt ){ login_needed(); return; }
1084 rn = atoi(PD("rn","0"));
1085 if( rn==0 ){
1086 cgi_redirect("reportlist");
1087 return;
1088 }
1089
--- src/report.c
+++ src/report.c
@@ -40,11 +40,14 @@
40 Stmt q;
41 int rn = 0;
42 int cnt = 0;
43
44 login_check_credentials();
45 if( !g.perm.RdTkt && !g.perm.NewTkt ){
46 login_needed(g.anon.RdTkt || g.anon.NewTkt);
47 return;
48 }
49 style_header("Ticket Main Menu");
50 ticket_standard_submenu(T_ALL_BUT(T_REPLIST));
51 if( g.thTrace ) Th_Trace("BEGIN_REPORTLIST<br />\n", -1);
52 zScript = ticket_reportlist_code();
53 if( g.thTrace ) Th_Trace("BEGIN_REPORTLIST_SCRIPT<br />\n", -1);
@@ -293,11 +296,11 @@
296 const char *zClrKey;
297 Stmt q;
298
299 login_check_credentials();
300 if( !g.perm.TktFmt ){
301 login_needed(g.anon.TktFmt);
302 return;
303 }
304 rn = atoi(PD("rn","0"));
305 db_prepare(&q, "SELECT title, sqlcode, owner, cols "
306 "FROM reportfmt WHERE rn=%d",rn);
@@ -343,11 +346,11 @@
346 char *zSQL;
347 char *zErr = 0;
348
349 login_check_credentials();
350 if( !g.perm.TktFmt ){
351 login_needed(g.anon.TktFmt);
352 return;
353 }
354 /*view_add_functions(0);*/
355 rn = atoi(PD("rn","0"));
356 zTitle = P("t");
@@ -1078,11 +1081,11 @@
1081 Stmt q;
1082 char *zErr1 = 0;
1083 char *zErr2 = 0;
1084
1085 login_check_credentials();
1086 if( !g.perm.RdTkt ){ login_needed(g.anon.RdTkt); return; }
1087 rn = atoi(PD("rn","0"));
1088 if( rn==0 ){
1089 cgi_redirect("reportlist");
1090 return;
1091 }
1092
+33 -18
--- src/setup.c
+++ src/setup.c
@@ -59,11 +59,11 @@
5959
** WEBPAGE: /setup
6060
*/
6161
void setup_page(void){
6262
login_check_credentials();
6363
if( !g.perm.Setup ){
64
- login_needed();
64
+ login_needed(0);
6565
}
6666
6767
style_header("Server Administration");
6868
6969
/* Make sure the header contains <base href="...">. Issue a warning
@@ -152,11 +152,11 @@
152152
Stmt s;
153153
int prevLevel = 0;
154154
155155
login_check_credentials();
156156
if( !g.perm.Admin ){
157
- login_needed();
157
+ login_needed(0);
158158
return;
159159
}
160160
161161
style_submenu_element("Add", "Add User", "setup_uedit");
162162
style_header("User List");
@@ -336,11 +336,11 @@
336336
const char *oa[128];
337337
338338
/* Must have ADMIN privileges to access this page
339339
*/
340340
login_check_credentials();
341
- if( !g.perm.Admin ){ login_needed(); return; }
341
+ if( !g.perm.Admin ){ login_needed(0); return; }
342342
343343
/* Check to see if an ADMIN user is trying to edit a SETUP account.
344344
** Don't allow that.
345345
*/
346346
zId = PD("id", "0");
@@ -998,11 +998,12 @@
998998
** WEBPAGE: setup_access
999999
*/
10001000
void setup_access(void){
10011001
login_check_credentials();
10021002
if( !g.perm.Setup ){
1003
- login_needed();
1003
+ login_needed(0);
1004
+ return;
10041005
}
10051006
10061007
style_header("Access Control Settings");
10071008
db_begin_transaction();
10081009
@ <form action="%s(g.zTop)/setup_access" method="post"><div>
@@ -1203,11 +1204,12 @@
12031204
const char *zPw = PD("pw", "");
12041205
const char *zNewName = PD("newname", "New Login Group");
12051206
12061207
login_check_credentials();
12071208
if( !g.perm.Setup ){
1208
- login_needed();
1209
+ login_needed(0);
1210
+ return;
12091211
}
12101212
file_canonical_name(g.zRepositoryName, &fullName, 0);
12111213
zSelfRepo = fossil_strdup(blob_str(&fullName));
12121214
blob_reset(&fullName);
12131215
if( P("join")!=0 ){
@@ -1315,11 +1317,12 @@
13151317
"3", "YYMMDD HH:MM",
13161318
"4", "(off)"
13171319
};
13181320
login_check_credentials();
13191321
if( !g.perm.Setup ){
1320
- login_needed();
1322
+ login_needed(0);
1323
+ return;
13211324
}
13221325
13231326
style_header("Timeline Display Preferences");
13241327
db_begin_transaction();
13251328
@ <form action="%s(g.zTop)/setup_timeline" method="post"><div>
@@ -1393,11 +1396,12 @@
13931396
void setup_settings(void){
13941397
Setting const *pSet;
13951398
13961399
login_check_credentials();
13971400
if( !g.perm.Setup ){
1398
- login_needed();
1401
+ login_needed(0);
1402
+ return;
13991403
}
14001404
14011405
(void) aCmdHelp; /* NOTE: Silence compiler warning. */
14021406
style_header("Settings");
14031407
if(!g.repositoryOpen){
@@ -1473,11 +1477,12 @@
14731477
** WEBPAGE: setup_config
14741478
*/
14751479
void setup_config(void){
14761480
login_check_credentials();
14771481
if( !g.perm.Setup ){
1478
- login_needed();
1482
+ login_needed(0);
1483
+ return;
14791484
}
14801485
14811486
style_header("WWW Configuration");
14821487
db_begin_transaction();
14831488
@ <form action="%s(g.zTop)/setup_config" method="post"><div>
@@ -1551,11 +1556,12 @@
15511556
** WEBPAGE: setup_editcss
15521557
*/
15531558
void setup_editcss(void){
15541559
login_check_credentials();
15551560
if( !g.perm.Setup ){
1556
- login_needed();
1561
+ login_needed(0);
1562
+ return;
15571563
}
15581564
db_begin_transaction();
15591565
if( P("clear")!=0 ){
15601566
db_multi_exec("DELETE FROM config WHERE name='css'");
15611567
cgi_replace_parameter("css", builtin_text("skins/default/css.txt"));
@@ -1596,11 +1602,12 @@
15961602
** WEBPAGE: setup_header
15971603
*/
15981604
void setup_header(void){
15991605
login_check_credentials();
16001606
if( !g.perm.Setup ){
1601
- login_needed();
1607
+ login_needed(0);
1608
+ return;
16021609
}
16031610
db_begin_transaction();
16041611
if( P("clear")!=0 ){
16051612
db_multi_exec("DELETE FROM config WHERE name='header'");
16061613
cgi_replace_parameter("header", builtin_text("skins/default/header.txt"));
@@ -1660,11 +1667,12 @@
16601667
** WEBPAGE: setup_footer
16611668
*/
16621669
void setup_footer(void){
16631670
login_check_credentials();
16641671
if( !g.perm.Setup ){
1665
- login_needed();
1672
+ login_needed(0);
1673
+ return;
16661674
}
16671675
db_begin_transaction();
16681676
if( P("clear")!=0 ){
16691677
db_multi_exec("DELETE FROM config WHERE name='footer'");
16701678
cgi_replace_parameter("footer", builtin_text("skins/default/footer.txt"));
@@ -1697,11 +1705,12 @@
16971705
** WEBPAGE: setup_modreq
16981706
*/
16991707
void setup_modreq(void){
17001708
login_check_credentials();
17011709
if( !g.perm.Setup ){
1702
- login_needed();
1710
+ login_needed(0);
1711
+ return;
17031712
}
17041713
17051714
style_header("Moderator For Wiki And Tickets");
17061715
db_begin_transaction();
17071716
@ <form action="%R/setup_modreq" method="post"><div>
@@ -1741,11 +1750,12 @@
17411750
** WEBPAGE: setup_adunit
17421751
*/
17431752
void setup_adunit(void){
17441753
login_check_credentials();
17451754
if( !g.perm.Setup ){
1746
- login_needed();
1755
+ login_needed(0);
1756
+ return;
17471757
}
17481758
db_begin_transaction();
17491759
if( P("clear")!=0 ){
17501760
db_multi_exec("DELETE FROM config WHERE name GLOB 'adunit*'");
17511761
cgi_replace_parameter("adunit","");
@@ -1822,11 +1832,12 @@
18221832
if( szBgImg>0 ){
18231833
zBgMime = PD("bgim:mimetype","image/gif");
18241834
}
18251835
login_check_credentials();
18261836
if( !g.perm.Setup ){
1827
- login_needed();
1837
+ login_needed(0);
1838
+ return;
18281839
}
18291840
db_begin_transaction();
18301841
if( P("setlogo")!=0 && zLogoMime && zLogoMime[0] && szLogoImg>0 ){
18311842
Blob img;
18321843
Stmt ins;
@@ -1961,11 +1972,12 @@
19611972
void sql_page(void){
19621973
const char *zQ = P("q");
19631974
int go = P("go")!=0;
19641975
login_check_credentials();
19651976
if( !g.perm.Setup ){
1966
- login_needed();
1977
+ login_needed(0);
1978
+ return;
19671979
}
19681980
db_begin_transaction();
19691981
style_header("Raw SQL Commands");
19701982
@ <p><b>Caution:</b> There are no restrictions on the SQL that can be
19711983
@ run by this page. You can do serious and irrepairable damage to the
@@ -2082,11 +2094,12 @@
20822094
void th1_page(void){
20832095
const char *zQ = P("q");
20842096
int go = P("go")!=0;
20852097
login_check_credentials();
20862098
if( !g.perm.Setup ){
2087
- login_needed();
2099
+ login_needed(0);
2100
+ return;
20882101
}
20892102
db_begin_transaction();
20902103
style_header("Raw TH1 Commands");
20912104
@ <p><b>Caution:</b> There are no restrictions on the TH1 that can be
20922105
@ run by this page. If Tcl integration was enabled at compile-time and
@@ -2142,11 +2155,12 @@
21422155
int limit;
21432156
int fLogEnabled;
21442157
int counter = 0;
21452158
login_check_credentials();
21462159
if( !g.perm.Setup && !g.perm.Admin ){
2147
- login_needed();
2160
+ login_needed(0);
2161
+ return;
21482162
}
21492163
style_header("Admin Log");
21502164
create_admin_log_table();
21512165
limit = atoi(PD("n","20"));
21522166
fLogEnabled = db_get_boolean("admin-log", 0);
@@ -2199,11 +2213,12 @@
21992213
** Configure the search engine.
22002214
*/
22012215
void page_srchsetup(){
22022216
login_check_credentials();
22032217
if( !g.perm.Setup && !g.perm.Admin ){
2204
- login_needed();
2218
+ login_needed(0);
2219
+ return;
22052220
}
22062221
style_header("Search Configuration");
22072222
@ <form action="%s(g.zTop)/srchsetup" method="post"><div>
22082223
login_insert_csrf_secret();
22092224
@ <div style="text-align:center;font-weight:bold;">
22102225
--- src/setup.c
+++ src/setup.c
@@ -59,11 +59,11 @@
59 ** WEBPAGE: /setup
60 */
61 void setup_page(void){
62 login_check_credentials();
63 if( !g.perm.Setup ){
64 login_needed();
65 }
66
67 style_header("Server Administration");
68
69 /* Make sure the header contains <base href="...">. Issue a warning
@@ -152,11 +152,11 @@
152 Stmt s;
153 int prevLevel = 0;
154
155 login_check_credentials();
156 if( !g.perm.Admin ){
157 login_needed();
158 return;
159 }
160
161 style_submenu_element("Add", "Add User", "setup_uedit");
162 style_header("User List");
@@ -336,11 +336,11 @@
336 const char *oa[128];
337
338 /* Must have ADMIN privileges to access this page
339 */
340 login_check_credentials();
341 if( !g.perm.Admin ){ login_needed(); return; }
342
343 /* Check to see if an ADMIN user is trying to edit a SETUP account.
344 ** Don't allow that.
345 */
346 zId = PD("id", "0");
@@ -998,11 +998,12 @@
998 ** WEBPAGE: setup_access
999 */
1000 void setup_access(void){
1001 login_check_credentials();
1002 if( !g.perm.Setup ){
1003 login_needed();
 
1004 }
1005
1006 style_header("Access Control Settings");
1007 db_begin_transaction();
1008 @ <form action="%s(g.zTop)/setup_access" method="post"><div>
@@ -1203,11 +1204,12 @@
1203 const char *zPw = PD("pw", "");
1204 const char *zNewName = PD("newname", "New Login Group");
1205
1206 login_check_credentials();
1207 if( !g.perm.Setup ){
1208 login_needed();
 
1209 }
1210 file_canonical_name(g.zRepositoryName, &fullName, 0);
1211 zSelfRepo = fossil_strdup(blob_str(&fullName));
1212 blob_reset(&fullName);
1213 if( P("join")!=0 ){
@@ -1315,11 +1317,12 @@
1315 "3", "YYMMDD HH:MM",
1316 "4", "(off)"
1317 };
1318 login_check_credentials();
1319 if( !g.perm.Setup ){
1320 login_needed();
 
1321 }
1322
1323 style_header("Timeline Display Preferences");
1324 db_begin_transaction();
1325 @ <form action="%s(g.zTop)/setup_timeline" method="post"><div>
@@ -1393,11 +1396,12 @@
1393 void setup_settings(void){
1394 Setting const *pSet;
1395
1396 login_check_credentials();
1397 if( !g.perm.Setup ){
1398 login_needed();
 
1399 }
1400
1401 (void) aCmdHelp; /* NOTE: Silence compiler warning. */
1402 style_header("Settings");
1403 if(!g.repositoryOpen){
@@ -1473,11 +1477,12 @@
1473 ** WEBPAGE: setup_config
1474 */
1475 void setup_config(void){
1476 login_check_credentials();
1477 if( !g.perm.Setup ){
1478 login_needed();
 
1479 }
1480
1481 style_header("WWW Configuration");
1482 db_begin_transaction();
1483 @ <form action="%s(g.zTop)/setup_config" method="post"><div>
@@ -1551,11 +1556,12 @@
1551 ** WEBPAGE: setup_editcss
1552 */
1553 void setup_editcss(void){
1554 login_check_credentials();
1555 if( !g.perm.Setup ){
1556 login_needed();
 
1557 }
1558 db_begin_transaction();
1559 if( P("clear")!=0 ){
1560 db_multi_exec("DELETE FROM config WHERE name='css'");
1561 cgi_replace_parameter("css", builtin_text("skins/default/css.txt"));
@@ -1596,11 +1602,12 @@
1596 ** WEBPAGE: setup_header
1597 */
1598 void setup_header(void){
1599 login_check_credentials();
1600 if( !g.perm.Setup ){
1601 login_needed();
 
1602 }
1603 db_begin_transaction();
1604 if( P("clear")!=0 ){
1605 db_multi_exec("DELETE FROM config WHERE name='header'");
1606 cgi_replace_parameter("header", builtin_text("skins/default/header.txt"));
@@ -1660,11 +1667,12 @@
1660 ** WEBPAGE: setup_footer
1661 */
1662 void setup_footer(void){
1663 login_check_credentials();
1664 if( !g.perm.Setup ){
1665 login_needed();
 
1666 }
1667 db_begin_transaction();
1668 if( P("clear")!=0 ){
1669 db_multi_exec("DELETE FROM config WHERE name='footer'");
1670 cgi_replace_parameter("footer", builtin_text("skins/default/footer.txt"));
@@ -1697,11 +1705,12 @@
1697 ** WEBPAGE: setup_modreq
1698 */
1699 void setup_modreq(void){
1700 login_check_credentials();
1701 if( !g.perm.Setup ){
1702 login_needed();
 
1703 }
1704
1705 style_header("Moderator For Wiki And Tickets");
1706 db_begin_transaction();
1707 @ <form action="%R/setup_modreq" method="post"><div>
@@ -1741,11 +1750,12 @@
1741 ** WEBPAGE: setup_adunit
1742 */
1743 void setup_adunit(void){
1744 login_check_credentials();
1745 if( !g.perm.Setup ){
1746 login_needed();
 
1747 }
1748 db_begin_transaction();
1749 if( P("clear")!=0 ){
1750 db_multi_exec("DELETE FROM config WHERE name GLOB 'adunit*'");
1751 cgi_replace_parameter("adunit","");
@@ -1822,11 +1832,12 @@
1822 if( szBgImg>0 ){
1823 zBgMime = PD("bgim:mimetype","image/gif");
1824 }
1825 login_check_credentials();
1826 if( !g.perm.Setup ){
1827 login_needed();
 
1828 }
1829 db_begin_transaction();
1830 if( P("setlogo")!=0 && zLogoMime && zLogoMime[0] && szLogoImg>0 ){
1831 Blob img;
1832 Stmt ins;
@@ -1961,11 +1972,12 @@
1961 void sql_page(void){
1962 const char *zQ = P("q");
1963 int go = P("go")!=0;
1964 login_check_credentials();
1965 if( !g.perm.Setup ){
1966 login_needed();
 
1967 }
1968 db_begin_transaction();
1969 style_header("Raw SQL Commands");
1970 @ <p><b>Caution:</b> There are no restrictions on the SQL that can be
1971 @ run by this page. You can do serious and irrepairable damage to the
@@ -2082,11 +2094,12 @@
2082 void th1_page(void){
2083 const char *zQ = P("q");
2084 int go = P("go")!=0;
2085 login_check_credentials();
2086 if( !g.perm.Setup ){
2087 login_needed();
 
2088 }
2089 db_begin_transaction();
2090 style_header("Raw TH1 Commands");
2091 @ <p><b>Caution:</b> There are no restrictions on the TH1 that can be
2092 @ run by this page. If Tcl integration was enabled at compile-time and
@@ -2142,11 +2155,12 @@
2142 int limit;
2143 int fLogEnabled;
2144 int counter = 0;
2145 login_check_credentials();
2146 if( !g.perm.Setup && !g.perm.Admin ){
2147 login_needed();
 
2148 }
2149 style_header("Admin Log");
2150 create_admin_log_table();
2151 limit = atoi(PD("n","20"));
2152 fLogEnabled = db_get_boolean("admin-log", 0);
@@ -2199,11 +2213,12 @@
2199 ** Configure the search engine.
2200 */
2201 void page_srchsetup(){
2202 login_check_credentials();
2203 if( !g.perm.Setup && !g.perm.Admin ){
2204 login_needed();
 
2205 }
2206 style_header("Search Configuration");
2207 @ <form action="%s(g.zTop)/srchsetup" method="post"><div>
2208 login_insert_csrf_secret();
2209 @ <div style="text-align:center;font-weight:bold;">
2210
--- src/setup.c
+++ src/setup.c
@@ -59,11 +59,11 @@
59 ** WEBPAGE: /setup
60 */
61 void setup_page(void){
62 login_check_credentials();
63 if( !g.perm.Setup ){
64 login_needed(0);
65 }
66
67 style_header("Server Administration");
68
69 /* Make sure the header contains <base href="...">. Issue a warning
@@ -152,11 +152,11 @@
152 Stmt s;
153 int prevLevel = 0;
154
155 login_check_credentials();
156 if( !g.perm.Admin ){
157 login_needed(0);
158 return;
159 }
160
161 style_submenu_element("Add", "Add User", "setup_uedit");
162 style_header("User List");
@@ -336,11 +336,11 @@
336 const char *oa[128];
337
338 /* Must have ADMIN privileges to access this page
339 */
340 login_check_credentials();
341 if( !g.perm.Admin ){ login_needed(0); return; }
342
343 /* Check to see if an ADMIN user is trying to edit a SETUP account.
344 ** Don't allow that.
345 */
346 zId = PD("id", "0");
@@ -998,11 +998,12 @@
998 ** WEBPAGE: setup_access
999 */
1000 void setup_access(void){
1001 login_check_credentials();
1002 if( !g.perm.Setup ){
1003 login_needed(0);
1004 return;
1005 }
1006
1007 style_header("Access Control Settings");
1008 db_begin_transaction();
1009 @ <form action="%s(g.zTop)/setup_access" method="post"><div>
@@ -1203,11 +1204,12 @@
1204 const char *zPw = PD("pw", "");
1205 const char *zNewName = PD("newname", "New Login Group");
1206
1207 login_check_credentials();
1208 if( !g.perm.Setup ){
1209 login_needed(0);
1210 return;
1211 }
1212 file_canonical_name(g.zRepositoryName, &fullName, 0);
1213 zSelfRepo = fossil_strdup(blob_str(&fullName));
1214 blob_reset(&fullName);
1215 if( P("join")!=0 ){
@@ -1315,11 +1317,12 @@
1317 "3", "YYMMDD HH:MM",
1318 "4", "(off)"
1319 };
1320 login_check_credentials();
1321 if( !g.perm.Setup ){
1322 login_needed(0);
1323 return;
1324 }
1325
1326 style_header("Timeline Display Preferences");
1327 db_begin_transaction();
1328 @ <form action="%s(g.zTop)/setup_timeline" method="post"><div>
@@ -1393,11 +1396,12 @@
1396 void setup_settings(void){
1397 Setting const *pSet;
1398
1399 login_check_credentials();
1400 if( !g.perm.Setup ){
1401 login_needed(0);
1402 return;
1403 }
1404
1405 (void) aCmdHelp; /* NOTE: Silence compiler warning. */
1406 style_header("Settings");
1407 if(!g.repositoryOpen){
@@ -1473,11 +1477,12 @@
1477 ** WEBPAGE: setup_config
1478 */
1479 void setup_config(void){
1480 login_check_credentials();
1481 if( !g.perm.Setup ){
1482 login_needed(0);
1483 return;
1484 }
1485
1486 style_header("WWW Configuration");
1487 db_begin_transaction();
1488 @ <form action="%s(g.zTop)/setup_config" method="post"><div>
@@ -1551,11 +1556,12 @@
1556 ** WEBPAGE: setup_editcss
1557 */
1558 void setup_editcss(void){
1559 login_check_credentials();
1560 if( !g.perm.Setup ){
1561 login_needed(0);
1562 return;
1563 }
1564 db_begin_transaction();
1565 if( P("clear")!=0 ){
1566 db_multi_exec("DELETE FROM config WHERE name='css'");
1567 cgi_replace_parameter("css", builtin_text("skins/default/css.txt"));
@@ -1596,11 +1602,12 @@
1602 ** WEBPAGE: setup_header
1603 */
1604 void setup_header(void){
1605 login_check_credentials();
1606 if( !g.perm.Setup ){
1607 login_needed(0);
1608 return;
1609 }
1610 db_begin_transaction();
1611 if( P("clear")!=0 ){
1612 db_multi_exec("DELETE FROM config WHERE name='header'");
1613 cgi_replace_parameter("header", builtin_text("skins/default/header.txt"));
@@ -1660,11 +1667,12 @@
1667 ** WEBPAGE: setup_footer
1668 */
1669 void setup_footer(void){
1670 login_check_credentials();
1671 if( !g.perm.Setup ){
1672 login_needed(0);
1673 return;
1674 }
1675 db_begin_transaction();
1676 if( P("clear")!=0 ){
1677 db_multi_exec("DELETE FROM config WHERE name='footer'");
1678 cgi_replace_parameter("footer", builtin_text("skins/default/footer.txt"));
@@ -1697,11 +1705,12 @@
1705 ** WEBPAGE: setup_modreq
1706 */
1707 void setup_modreq(void){
1708 login_check_credentials();
1709 if( !g.perm.Setup ){
1710 login_needed(0);
1711 return;
1712 }
1713
1714 style_header("Moderator For Wiki And Tickets");
1715 db_begin_transaction();
1716 @ <form action="%R/setup_modreq" method="post"><div>
@@ -1741,11 +1750,12 @@
1750 ** WEBPAGE: setup_adunit
1751 */
1752 void setup_adunit(void){
1753 login_check_credentials();
1754 if( !g.perm.Setup ){
1755 login_needed(0);
1756 return;
1757 }
1758 db_begin_transaction();
1759 if( P("clear")!=0 ){
1760 db_multi_exec("DELETE FROM config WHERE name GLOB 'adunit*'");
1761 cgi_replace_parameter("adunit","");
@@ -1822,11 +1832,12 @@
1832 if( szBgImg>0 ){
1833 zBgMime = PD("bgim:mimetype","image/gif");
1834 }
1835 login_check_credentials();
1836 if( !g.perm.Setup ){
1837 login_needed(0);
1838 return;
1839 }
1840 db_begin_transaction();
1841 if( P("setlogo")!=0 && zLogoMime && zLogoMime[0] && szLogoImg>0 ){
1842 Blob img;
1843 Stmt ins;
@@ -1961,11 +1972,12 @@
1972 void sql_page(void){
1973 const char *zQ = P("q");
1974 int go = P("go")!=0;
1975 login_check_credentials();
1976 if( !g.perm.Setup ){
1977 login_needed(0);
1978 return;
1979 }
1980 db_begin_transaction();
1981 style_header("Raw SQL Commands");
1982 @ <p><b>Caution:</b> There are no restrictions on the SQL that can be
1983 @ run by this page. You can do serious and irrepairable damage to the
@@ -2082,11 +2094,12 @@
2094 void th1_page(void){
2095 const char *zQ = P("q");
2096 int go = P("go")!=0;
2097 login_check_credentials();
2098 if( !g.perm.Setup ){
2099 login_needed(0);
2100 return;
2101 }
2102 db_begin_transaction();
2103 style_header("Raw TH1 Commands");
2104 @ <p><b>Caution:</b> There are no restrictions on the TH1 that can be
2105 @ run by this page. If Tcl integration was enabled at compile-time and
@@ -2142,11 +2155,12 @@
2155 int limit;
2156 int fLogEnabled;
2157 int counter = 0;
2158 login_check_credentials();
2159 if( !g.perm.Setup && !g.perm.Admin ){
2160 login_needed(0);
2161 return;
2162 }
2163 style_header("Admin Log");
2164 create_admin_log_table();
2165 limit = atoi(PD("n","20"));
2166 fLogEnabled = db_get_boolean("admin-log", 0);
@@ -2199,11 +2213,12 @@
2213 ** Configure the search engine.
2214 */
2215 void page_srchsetup(){
2216 login_check_credentials();
2217 if( !g.perm.Setup && !g.perm.Admin ){
2218 login_needed(0);
2219 return;
2220 }
2221 style_header("Search Configuration");
2222 @ <form action="%s(g.zTop)/srchsetup" method="post"><div>
2223 login_insert_csrf_secret();
2224 @ <div style="text-align:center;font-weight:bold;">
2225
+6 -3
--- src/shun.c
+++ src/shun.c
@@ -49,11 +49,12 @@
4949
int numRows = 3;
5050
char *zCanonical = 0;
5151
5252
login_check_credentials();
5353
if( !g.perm.Admin ){
54
- login_needed();
54
+ login_needed(0);
55
+ return;
5556
}
5657
if( P("rebuild") ){
5758
db_close(1);
5859
db_open_repository(g.zRepositoryName);
5960
db_begin_transaction();
@@ -301,11 +302,12 @@
301302
int cnt;
302303
Stmt q;
303304
304305
login_check_credentials();
305306
if( !g.perm.Admin ){
306
- login_needed();
307
+ login_needed(0);
308
+ return;
307309
}
308310
style_header("Artifact Receipts");
309311
if( showAll ){
310312
ofst = 0;
311313
}else{
@@ -381,11 +383,12 @@
381383
int rcvid = atoi(PD("rcvid","0"));
382384
Stmt q;
383385
384386
login_check_credentials();
385387
if( !g.perm.Admin ){
386
- login_needed();
388
+ login_needed(0);
389
+ return;
387390
}
388391
style_header("Artifact Receipt %d", rcvid);
389392
if( db_exists(
390393
"SELECT 1 FROM blob WHERE rcvid=%d AND"
391394
" NOT EXISTS (SELECT 1 FROM shun WHERE shun.uuid=blob.uuid)", rcvid)
392395
--- src/shun.c
+++ src/shun.c
@@ -49,11 +49,12 @@
49 int numRows = 3;
50 char *zCanonical = 0;
51
52 login_check_credentials();
53 if( !g.perm.Admin ){
54 login_needed();
 
55 }
56 if( P("rebuild") ){
57 db_close(1);
58 db_open_repository(g.zRepositoryName);
59 db_begin_transaction();
@@ -301,11 +302,12 @@
301 int cnt;
302 Stmt q;
303
304 login_check_credentials();
305 if( !g.perm.Admin ){
306 login_needed();
 
307 }
308 style_header("Artifact Receipts");
309 if( showAll ){
310 ofst = 0;
311 }else{
@@ -381,11 +383,12 @@
381 int rcvid = atoi(PD("rcvid","0"));
382 Stmt q;
383
384 login_check_credentials();
385 if( !g.perm.Admin ){
386 login_needed();
 
387 }
388 style_header("Artifact Receipt %d", rcvid);
389 if( db_exists(
390 "SELECT 1 FROM blob WHERE rcvid=%d AND"
391 " NOT EXISTS (SELECT 1 FROM shun WHERE shun.uuid=blob.uuid)", rcvid)
392
--- src/shun.c
+++ src/shun.c
@@ -49,11 +49,12 @@
49 int numRows = 3;
50 char *zCanonical = 0;
51
52 login_check_credentials();
53 if( !g.perm.Admin ){
54 login_needed(0);
55 return;
56 }
57 if( P("rebuild") ){
58 db_close(1);
59 db_open_repository(g.zRepositoryName);
60 db_begin_transaction();
@@ -301,11 +302,12 @@
302 int cnt;
303 Stmt q;
304
305 login_check_credentials();
306 if( !g.perm.Admin ){
307 login_needed(0);
308 return;
309 }
310 style_header("Artifact Receipts");
311 if( showAll ){
312 ofst = 0;
313 }else{
@@ -381,11 +383,12 @@
383 int rcvid = atoi(PD("rcvid","0"));
384 Stmt q;
385
386 login_check_credentials();
387 if( !g.perm.Admin ){
388 login_needed(0);
389 return;
390 }
391 style_header("Artifact Receipt %d", rcvid);
392 if( db_exists(
393 "SELECT 1 FROM blob WHERE rcvid=%d AND"
394 " NOT EXISTS (SELECT 1 FROM shun WHERE shun.uuid=blob.uuid)", rcvid)
395
+2 -1
--- src/skins.c
+++ src/skins.c
@@ -289,11 +289,12 @@
289289
Stmt q;
290290
int seenCurrent = 0;
291291
292292
login_check_credentials();
293293
if( !g.perm.Setup ){
294
- login_needed();
294
+ login_needed(0);
295
+ return;
295296
}
296297
db_begin_transaction();
297298
zCurrent = getSkin(0);
298299
for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){
299300
aBuiltinSkin[i].zSQL = getSkin(aBuiltinSkin[i].zLabel);
300301
--- src/skins.c
+++ src/skins.c
@@ -289,11 +289,12 @@
289 Stmt q;
290 int seenCurrent = 0;
291
292 login_check_credentials();
293 if( !g.perm.Setup ){
294 login_needed();
 
295 }
296 db_begin_transaction();
297 zCurrent = getSkin(0);
298 for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){
299 aBuiltinSkin[i].zSQL = getSkin(aBuiltinSkin[i].zLabel);
300
--- src/skins.c
+++ src/skins.c
@@ -289,11 +289,12 @@
289 Stmt q;
290 int seenCurrent = 0;
291
292 login_check_credentials();
293 if( !g.perm.Setup ){
294 login_needed(0);
295 return;
296 }
297 db_begin_transaction();
298 zCurrent = getSkin(0);
299 for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){
300 aBuiltinSkin[i].zSQL = getSkin(aBuiltinSkin[i].zLabel);
301
+3 -3
--- src/stat.c
+++ src/stat.c
@@ -52,11 +52,11 @@
5252
int brief;
5353
char zBuf[100];
5454
const char *p;
5555
5656
login_check_credentials();
57
- if( !g.perm.Read ){ login_needed(); return; }
57
+ if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
5858
brief = P("brief")!=0;
5959
style_header("Repository Statistics");
6060
style_adunit_config(ADUNIT_RIGHT_OK);
6161
if( g.perm.Admin ){
6262
style_submenu_element("URLs", "URLs and Checkouts", "urllist");
@@ -292,11 +292,11 @@
292292
*/
293293
void urllist_page(void){
294294
Stmt q;
295295
int cnt;
296296
login_check_credentials();
297
- if( !g.perm.Admin ){ login_needed(); return; }
297
+ if( !g.perm.Admin ){ login_needed(0); return; }
298298
299299
style_header("URLs and Checkouts");
300300
style_adunit_config(ADUNIT_RIGHT_OK);
301301
style_submenu_element("Stat", "Repository Stats", "stat");
302302
style_submenu_element("Schema", "Repository Schema", "repo_schema");
@@ -339,11 +339,11 @@
339339
** Show the repository schema
340340
*/
341341
void repo_schema_page(void){
342342
Stmt q;
343343
login_check_credentials();
344
- if( !g.perm.Admin ){ login_needed(); return; }
344
+ if( !g.perm.Admin ){ login_needed(0); return; }
345345
346346
style_header("Repository Schema");
347347
style_adunit_config(ADUNIT_RIGHT_OK);
348348
style_submenu_element("Stat", "Repository Stats", "stat");
349349
style_submenu_element("URLs", "URLs and Checkouts", "urllist");
350350
--- src/stat.c
+++ src/stat.c
@@ -52,11 +52,11 @@
52 int brief;
53 char zBuf[100];
54 const char *p;
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");
@@ -292,11 +292,11 @@
292 */
293 void urllist_page(void){
294 Stmt q;
295 int cnt;
296 login_check_credentials();
297 if( !g.perm.Admin ){ login_needed(); return; }
298
299 style_header("URLs and Checkouts");
300 style_adunit_config(ADUNIT_RIGHT_OK);
301 style_submenu_element("Stat", "Repository Stats", "stat");
302 style_submenu_element("Schema", "Repository Schema", "repo_schema");
@@ -339,11 +339,11 @@
339 ** Show the repository schema
340 */
341 void repo_schema_page(void){
342 Stmt q;
343 login_check_credentials();
344 if( !g.perm.Admin ){ login_needed(); return; }
345
346 style_header("Repository Schema");
347 style_adunit_config(ADUNIT_RIGHT_OK);
348 style_submenu_element("Stat", "Repository Stats", "stat");
349 style_submenu_element("URLs", "URLs and Checkouts", "urllist");
350
--- src/stat.c
+++ src/stat.c
@@ -52,11 +52,11 @@
52 int brief;
53 char zBuf[100];
54 const char *p;
55
56 login_check_credentials();
57 if( !g.perm.Read ){ login_needed(g.anon.Read); 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");
@@ -292,11 +292,11 @@
292 */
293 void urllist_page(void){
294 Stmt q;
295 int cnt;
296 login_check_credentials();
297 if( !g.perm.Admin ){ login_needed(0); return; }
298
299 style_header("URLs and Checkouts");
300 style_adunit_config(ADUNIT_RIGHT_OK);
301 style_submenu_element("Stat", "Repository Stats", "stat");
302 style_submenu_element("Schema", "Repository Schema", "repo_schema");
@@ -339,11 +339,11 @@
339 ** Show the repository schema
340 */
341 void repo_schema_page(void){
342 Stmt q;
343 login_check_credentials();
344 if( !g.perm.Admin ){ login_needed(0); return; }
345
346 style_header("Repository Schema");
347 style_adunit_config(ADUNIT_RIGHT_OK);
348 style_submenu_element("Stat", "Repository Stats", "stat");
349 style_submenu_element("URLs", "URLs and Checkouts", "urllist");
350
+1 -1
--- src/statrep.c
+++ src/statrep.c
@@ -728,11 +728,11 @@
728728
HQuery url; /* URL for various branch links */
729729
const char *zView = P("view"); /* Which view/report to show. */
730730
const char *zUserName = P("user");
731731
732732
login_check_credentials();
733
- if( !g.perm.Read ){ login_needed(); return; }
733
+ if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
734734
if(!zUserName) zUserName = P("u");
735735
url_initialize(&url, "reports");
736736
if(zUserName && *zUserName){
737737
url_add_parameter(&url,"user", zUserName);
738738
statrep_submenu(&url, "(Remove User Flag)", "view", zView, "user");
739739
--- src/statrep.c
+++ src/statrep.c
@@ -728,11 +728,11 @@
728 HQuery url; /* URL for various branch links */
729 const char *zView = P("view"); /* Which view/report to show. */
730 const char *zUserName = P("user");
731
732 login_check_credentials();
733 if( !g.perm.Read ){ login_needed(); return; }
734 if(!zUserName) zUserName = P("u");
735 url_initialize(&url, "reports");
736 if(zUserName && *zUserName){
737 url_add_parameter(&url,"user", zUserName);
738 statrep_submenu(&url, "(Remove User Flag)", "view", zView, "user");
739
--- src/statrep.c
+++ src/statrep.c
@@ -728,11 +728,11 @@
728 HQuery url; /* URL for various branch links */
729 const char *zView = P("view"); /* Which view/report to show. */
730 const char *zUserName = P("user");
731
732 login_check_credentials();
733 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
734 if(!zUserName) zUserName = P("u");
735 url_initialize(&url, "reports");
736 if(zUserName && *zUserName){
737 url_add_parameter(&url,"user", zUserName);
738 statrep_submenu(&url, "(Remove User Flag)", "view", zView, "user");
739
+10 -2
--- src/style.c
+++ src/style.c
@@ -1411,11 +1411,11 @@
14111411
"REQUEST_URI", "SCRIPT_FILENAME", "SCRIPT_NAME", "SERVER_PROTOCOL",
14121412
};
14131413
14141414
login_check_credentials();
14151415
if( !g.perm.Admin && !g.perm.Setup && !db_get_boolean("test_env_enable",0) ){
1416
- login_needed();
1416
+ login_needed(0);
14171417
return;
14181418
}
14191419
for(i=0; i<count(azCgiVars); i++) (void)P(azCgiVars[i]);
14201420
style_header("Environment Test");
14211421
showAll = atoi(PD("showall","0"));
@@ -1430,17 +1430,25 @@
14301430
@ g.zBaseURL = %h(g.zBaseURL)<br />
14311431
@ g.zHttpsURL = %h(g.zHttpsURL)<br />
14321432
@ g.zTop = %h(g.zTop)<br />
14331433
@ g.zPath = %h(g.zPath)<br />
14341434
for(i=0, c='a'; c<='z'; c++){
1435
- if( login_has_capability(&c, 1) ) zCap[i++] = c;
1435
+ if( login_has_capability(&c, 1, 0) ) zCap[i++] = c;
14361436
}
14371437
zCap[i] = 0;
14381438
@ g.userUid = %d(g.userUid)<br />
14391439
@ g.zLogin = %h(g.zLogin)<br />
14401440
@ g.isHuman = %d(g.isHuman)<br />
14411441
@ capabilities = %s(zCap)<br />
1442
+ for(i=0, c='a'; c<='z'; c++){
1443
+ if( login_has_capability(&c, 1, LOGIN_ANON)
1444
+ && !login_has_capability(&c, 1, 0) ) zCap[i++] = c;
1445
+ }
1446
+ zCap[i] = 0;
1447
+ if( i>0 ){
1448
+ @ anonymous-adds = %s(zCap)<br />
1449
+ }
14421450
@ g.zRepositoryName = %h(g.zRepositoryName)<br />
14431451
@ load_average() = %f(load_average())<br />
14441452
@ <hr>
14451453
P("HTTP_USER_AGENT");
14461454
cgi_print_all(showAll);
14471455
--- src/style.c
+++ src/style.c
@@ -1411,11 +1411,11 @@
1411 "REQUEST_URI", "SCRIPT_FILENAME", "SCRIPT_NAME", "SERVER_PROTOCOL",
1412 };
1413
1414 login_check_credentials();
1415 if( !g.perm.Admin && !g.perm.Setup && !db_get_boolean("test_env_enable",0) ){
1416 login_needed();
1417 return;
1418 }
1419 for(i=0; i<count(azCgiVars); i++) (void)P(azCgiVars[i]);
1420 style_header("Environment Test");
1421 showAll = atoi(PD("showall","0"));
@@ -1430,17 +1430,25 @@
1430 @ g.zBaseURL = %h(g.zBaseURL)<br />
1431 @ g.zHttpsURL = %h(g.zHttpsURL)<br />
1432 @ g.zTop = %h(g.zTop)<br />
1433 @ g.zPath = %h(g.zPath)<br />
1434 for(i=0, c='a'; c<='z'; c++){
1435 if( login_has_capability(&c, 1) ) zCap[i++] = c;
1436 }
1437 zCap[i] = 0;
1438 @ g.userUid = %d(g.userUid)<br />
1439 @ g.zLogin = %h(g.zLogin)<br />
1440 @ g.isHuman = %d(g.isHuman)<br />
1441 @ capabilities = %s(zCap)<br />
 
 
 
 
 
 
 
 
1442 @ g.zRepositoryName = %h(g.zRepositoryName)<br />
1443 @ load_average() = %f(load_average())<br />
1444 @ <hr>
1445 P("HTTP_USER_AGENT");
1446 cgi_print_all(showAll);
1447
--- src/style.c
+++ src/style.c
@@ -1411,11 +1411,11 @@
1411 "REQUEST_URI", "SCRIPT_FILENAME", "SCRIPT_NAME", "SERVER_PROTOCOL",
1412 };
1413
1414 login_check_credentials();
1415 if( !g.perm.Admin && !g.perm.Setup && !db_get_boolean("test_env_enable",0) ){
1416 login_needed(0);
1417 return;
1418 }
1419 for(i=0; i<count(azCgiVars); i++) (void)P(azCgiVars[i]);
1420 style_header("Environment Test");
1421 showAll = atoi(PD("showall","0"));
@@ -1430,17 +1430,25 @@
1430 @ g.zBaseURL = %h(g.zBaseURL)<br />
1431 @ g.zHttpsURL = %h(g.zHttpsURL)<br />
1432 @ g.zTop = %h(g.zTop)<br />
1433 @ g.zPath = %h(g.zPath)<br />
1434 for(i=0, c='a'; c<='z'; c++){
1435 if( login_has_capability(&c, 1, 0) ) zCap[i++] = c;
1436 }
1437 zCap[i] = 0;
1438 @ g.userUid = %d(g.userUid)<br />
1439 @ g.zLogin = %h(g.zLogin)<br />
1440 @ g.isHuman = %d(g.isHuman)<br />
1441 @ capabilities = %s(zCap)<br />
1442 for(i=0, c='a'; c<='z'; c++){
1443 if( login_has_capability(&c, 1, LOGIN_ANON)
1444 && !login_has_capability(&c, 1, 0) ) zCap[i++] = c;
1445 }
1446 zCap[i] = 0;
1447 if( i>0 ){
1448 @ anonymous-adds = %s(zCap)<br />
1449 }
1450 @ g.zRepositoryName = %h(g.zRepositoryName)<br />
1451 @ load_average() = %f(load_average())<br />
1452 @ <hr>
1453 P("HTTP_USER_AGENT");
1454 cgi_print_all(showAll);
1455
+2 -2
--- src/tag.c
+++ src/tag.c
@@ -542,11 +542,11 @@
542542
void taglist_page(void){
543543
Stmt q;
544544
545545
login_check_credentials();
546546
if( !g.perm.Read ){
547
- login_needed();
547
+ login_needed(g.anon.Read);
548548
}
549549
login_anonymous_available();
550550
style_header("Tags");
551551
style_adunit_config(ADUNIT_RIGHT_OK);
552552
style_submenu_element("Timeline", "Timeline", "tagtimeline");
@@ -580,11 +580,11 @@
580580
*/
581581
void tagtimeline_page(void){
582582
Stmt q;
583583
584584
login_check_credentials();
585
- if( !g.perm.Read ){ login_needed(); return; }
585
+ if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
586586
587587
style_header("Tagged Check-ins");
588588
style_submenu_element("List", "List", "taglist");
589589
login_anonymous_available();
590590
@ <h2>Check-ins with non-propagating tags:</h2>
591591
--- src/tag.c
+++ src/tag.c
@@ -542,11 +542,11 @@
542 void taglist_page(void){
543 Stmt q;
544
545 login_check_credentials();
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");
@@ -580,11 +580,11 @@
580 */
581 void tagtimeline_page(void){
582 Stmt q;
583
584 login_check_credentials();
585 if( !g.perm.Read ){ login_needed(); return; }
586
587 style_header("Tagged Check-ins");
588 style_submenu_element("List", "List", "taglist");
589 login_anonymous_available();
590 @ <h2>Check-ins with non-propagating tags:</h2>
591
--- src/tag.c
+++ src/tag.c
@@ -542,11 +542,11 @@
542 void taglist_page(void){
543 Stmt q;
544
545 login_check_credentials();
546 if( !g.perm.Read ){
547 login_needed(g.anon.Read);
548 }
549 login_anonymous_available();
550 style_header("Tags");
551 style_adunit_config(ADUNIT_RIGHT_OK);
552 style_submenu_element("Timeline", "Timeline", "tagtimeline");
@@ -580,11 +580,11 @@
580 */
581 void tagtimeline_page(void){
582 Stmt q;
583
584 login_check_credentials();
585 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
586
587 style_header("Tagged Check-ins");
588 style_submenu_element("List", "List", "taglist");
589 login_anonymous_available();
590 @ <h2>Check-ins with non-propagating tags:</h2>
591
+12 -1
--- src/tar.c
+++ src/tar.c
@@ -603,11 +603,11 @@
603603
char *zName, *zRid, *zKey;
604604
int nName, nRid;
605605
Blob tarball;
606606
607607
login_check_credentials();
608
- if( !g.perm.Zip ){ login_needed(); return; }
608
+ if( !g.perm.Zip ){ login_needed(g.anon.Zip); return; }
609609
load_control();
610610
zName = mprintf("%s", PD("name",""));
611611
nName = strlen(zName);
612612
zRid = mprintf("%s", PD("uuid","trunk"));
613613
nRid = strlen(zRid);
@@ -638,10 +638,21 @@
638638
@ zName = "%h(zName)"<br>
639639
@ rid = %d(rid)<br>
640640
@ zKey = "%h(zKey)"
641641
style_footer();
642642
return;
643
+ }
644
+ if( referred_from_login() ){
645
+ style_header("Tarball Download");
646
+ @ <form action='%R/tarball'>
647
+ cgi_query_parameters_to_hidden();
648
+ @ <p>Tarball named <b>%h(zName).tar.gz</b> holding the content
649
+ @ of check-in <b>%h(zRid)</b>:
650
+ @ <input type="submit" value="Download" />
651
+ @ </form>
652
+ style_footer();
653
+ return;
643654
}
644655
blob_zero(&tarball);
645656
if( cache_read(&tarball, zKey)==0 ){
646657
tarball_of_checkin(rid, &tarball, zName);
647658
cache_write(&tarball, zKey);
648659
--- src/tar.c
+++ src/tar.c
@@ -603,11 +603,11 @@
603 char *zName, *zRid, *zKey;
604 int nName, nRid;
605 Blob tarball;
606
607 login_check_credentials();
608 if( !g.perm.Zip ){ login_needed(); return; }
609 load_control();
610 zName = mprintf("%s", PD("name",""));
611 nName = strlen(zName);
612 zRid = mprintf("%s", PD("uuid","trunk"));
613 nRid = strlen(zRid);
@@ -638,10 +638,21 @@
638 @ zName = "%h(zName)"<br>
639 @ rid = %d(rid)<br>
640 @ zKey = "%h(zKey)"
641 style_footer();
642 return;
 
 
 
 
 
 
 
 
 
 
 
643 }
644 blob_zero(&tarball);
645 if( cache_read(&tarball, zKey)==0 ){
646 tarball_of_checkin(rid, &tarball, zName);
647 cache_write(&tarball, zKey);
648
--- src/tar.c
+++ src/tar.c
@@ -603,11 +603,11 @@
603 char *zName, *zRid, *zKey;
604 int nName, nRid;
605 Blob tarball;
606
607 login_check_credentials();
608 if( !g.perm.Zip ){ login_needed(g.anon.Zip); return; }
609 load_control();
610 zName = mprintf("%s", PD("name",""));
611 nName = strlen(zName);
612 zRid = mprintf("%s", PD("uuid","trunk"));
613 nRid = strlen(zRid);
@@ -638,10 +638,21 @@
638 @ zName = "%h(zName)"<br>
639 @ rid = %d(rid)<br>
640 @ zKey = "%h(zKey)"
641 style_footer();
642 return;
643 }
644 if( referred_from_login() ){
645 style_header("Tarball Download");
646 @ <form action='%R/tarball'>
647 cgi_query_parameters_to_hidden();
648 @ <p>Tarball named <b>%h(zName).tar.gz</b> holding the content
649 @ of check-in <b>%h(zRid)</b>:
650 @ <input type="submit" value="Download" />
651 @ </form>
652 style_footer();
653 return;
654 }
655 blob_zero(&tarball);
656 if( cache_read(&tarball, zKey)==0 ){
657 tarball_of_checkin(rid, &tarball, zName);
658 cache_write(&tarball, zKey);
659
+11 -5
--- src/th_main.c
+++ src/th_main.c
@@ -342,12 +342,14 @@
342342
return TH_OK;
343343
}
344344
345345
/*
346346
** TH1 command: hascap STRING...
347
+** TH1 command: anoncap STRING...
347348
**
348
-** Return true if the user has all of the capabilities listed in STRING.
349
+** Return true if the current user (hascap) or if the anonymous user
350
+** (anoncap) has all of the capabilities listed in STRING.
349351
*/
350352
static int hascapCmd(
351353
Th_Interp *interp,
352354
void *p,
353355
int argc,
@@ -357,11 +359,11 @@
357359
int rc = 0, i;
358360
if( argc<2 ){
359361
return Th_WrongNumArgs(interp, "hascap STRING ...");
360362
}
361363
for(i=1; i<argc && rc==0; i++){
362
- rc = login_has_capability((char*)argv[i],argl[i]);
364
+ rc = login_has_capability((char*)argv[i],argl[i],*(int*)p);
363365
}
364366
if( g.thTrace ){
365367
Th_Trace("[hascap %#h] => %d<br />\n", argl[1], argv[1], rc);
366368
}
367369
Th_SetResultInt(interp, rc);
@@ -543,11 +545,12 @@
543545
544546
545547
/*
546548
** TH1 command: anycap STRING
547549
**
548
-** Return true if the user has any one of the capabilities listed in STRING.
550
+** Return true if the current user user
551
+** has any one of the capabilities listed in STRING.
549552
*/
550553
static int anycapCmd(
551554
Th_Interp *interp,
552555
void *p,
553556
int argc,
@@ -558,11 +561,11 @@
558561
int i;
559562
if( argc!=2 ){
560563
return Th_WrongNumArgs(interp, "anycap STRING");
561564
}
562565
for(i=0; rc==0 && i<argl[1]; i++){
563
- rc = login_has_capability((char*)&argv[1][i],1);
566
+ rc = login_has_capability((char*)&argv[1][i],1,0);
564567
}
565568
if( g.thTrace ){
566569
Th_Trace("[hascap %#h] => %d<br />\n", argl[1], argv[1], rc);
567570
}
568571
Th_SetResultInt(interp, rc);
@@ -1450,15 +1453,18 @@
14501453
int needConfig = flags & TH_INIT_NEED_CONFIG;
14511454
int forceReset = flags & TH_INIT_FORCE_RESET;
14521455
int forceTcl = flags & TH_INIT_FORCE_TCL;
14531456
int forceSetup = flags & TH_INIT_FORCE_SETUP;
14541457
static unsigned int aFlags[] = { 0, 1, WIKI_LINKSONLY };
1458
+ static int anonFlag = LOGIN_ANON;
1459
+ static int zeroInt = 0;
14551460
static struct _Command {
14561461
const char *zName;
14571462
Th_CommandProc xProc;
14581463
void *pContext;
14591464
} aCommand[] = {
1465
+ {"anoncap", hascapCmd, (void*)&anonFlag},
14601466
{"anycap", anycapCmd, 0},
14611467
{"artifact", artifactCmd, 0},
14621468
{"checkout", checkoutCmd, 0},
14631469
{"combobox", comboboxCmd, 0},
14641470
{"date", dateCmd, 0},
@@ -1465,11 +1471,11 @@
14651471
{"decorate", wikiCmd, (void*)&aFlags[2]},
14661472
{"enable_output", enableOutputCmd, 0},
14671473
{"getParameter", getParameterCmd, 0},
14681474
{"globalState", globalStateCmd, 0},
14691475
{"httpize", httpizeCmd, 0},
1470
- {"hascap", hascapCmd, 0},
1476
+ {"hascap", hascapCmd, (void*)&zeroInt},
14711477
{"hasfeature", hasfeatureCmd, 0},
14721478
{"html", putsCmd, (void*)&aFlags[0]},
14731479
{"htmlize", htmlizeCmd, 0},
14741480
{"http", httpCmd, 0},
14751481
{"linecount", linecntCmd, 0},
14761482
--- src/th_main.c
+++ src/th_main.c
@@ -342,12 +342,14 @@
342 return TH_OK;
343 }
344
345 /*
346 ** TH1 command: hascap STRING...
 
347 **
348 ** Return true if the user has all of the capabilities listed in STRING.
 
349 */
350 static int hascapCmd(
351 Th_Interp *interp,
352 void *p,
353 int argc,
@@ -357,11 +359,11 @@
357 int rc = 0, i;
358 if( argc<2 ){
359 return Th_WrongNumArgs(interp, "hascap STRING ...");
360 }
361 for(i=1; i<argc && rc==0; i++){
362 rc = login_has_capability((char*)argv[i],argl[i]);
363 }
364 if( g.thTrace ){
365 Th_Trace("[hascap %#h] => %d<br />\n", argl[1], argv[1], rc);
366 }
367 Th_SetResultInt(interp, rc);
@@ -543,11 +545,12 @@
543
544
545 /*
546 ** TH1 command: anycap STRING
547 **
548 ** Return true if the user has any one of the capabilities listed in STRING.
 
549 */
550 static int anycapCmd(
551 Th_Interp *interp,
552 void *p,
553 int argc,
@@ -558,11 +561,11 @@
558 int i;
559 if( argc!=2 ){
560 return Th_WrongNumArgs(interp, "anycap STRING");
561 }
562 for(i=0; rc==0 && i<argl[1]; i++){
563 rc = login_has_capability((char*)&argv[1][i],1);
564 }
565 if( g.thTrace ){
566 Th_Trace("[hascap %#h] => %d<br />\n", argl[1], argv[1], rc);
567 }
568 Th_SetResultInt(interp, rc);
@@ -1450,15 +1453,18 @@
1450 int needConfig = flags & TH_INIT_NEED_CONFIG;
1451 int forceReset = flags & TH_INIT_FORCE_RESET;
1452 int forceTcl = flags & TH_INIT_FORCE_TCL;
1453 int forceSetup = flags & TH_INIT_FORCE_SETUP;
1454 static unsigned int aFlags[] = { 0, 1, WIKI_LINKSONLY };
 
 
1455 static struct _Command {
1456 const char *zName;
1457 Th_CommandProc xProc;
1458 void *pContext;
1459 } aCommand[] = {
 
1460 {"anycap", anycapCmd, 0},
1461 {"artifact", artifactCmd, 0},
1462 {"checkout", checkoutCmd, 0},
1463 {"combobox", comboboxCmd, 0},
1464 {"date", dateCmd, 0},
@@ -1465,11 +1471,11 @@
1465 {"decorate", wikiCmd, (void*)&aFlags[2]},
1466 {"enable_output", enableOutputCmd, 0},
1467 {"getParameter", getParameterCmd, 0},
1468 {"globalState", globalStateCmd, 0},
1469 {"httpize", httpizeCmd, 0},
1470 {"hascap", hascapCmd, 0},
1471 {"hasfeature", hasfeatureCmd, 0},
1472 {"html", putsCmd, (void*)&aFlags[0]},
1473 {"htmlize", htmlizeCmd, 0},
1474 {"http", httpCmd, 0},
1475 {"linecount", linecntCmd, 0},
1476
--- src/th_main.c
+++ src/th_main.c
@@ -342,12 +342,14 @@
342 return TH_OK;
343 }
344
345 /*
346 ** TH1 command: hascap STRING...
347 ** TH1 command: anoncap STRING...
348 **
349 ** Return true if the current user (hascap) or if the anonymous user
350 ** (anoncap) has all of the capabilities listed in STRING.
351 */
352 static int hascapCmd(
353 Th_Interp *interp,
354 void *p,
355 int argc,
@@ -357,11 +359,11 @@
359 int rc = 0, i;
360 if( argc<2 ){
361 return Th_WrongNumArgs(interp, "hascap STRING ...");
362 }
363 for(i=1; i<argc && rc==0; i++){
364 rc = login_has_capability((char*)argv[i],argl[i],*(int*)p);
365 }
366 if( g.thTrace ){
367 Th_Trace("[hascap %#h] => %d<br />\n", argl[1], argv[1], rc);
368 }
369 Th_SetResultInt(interp, rc);
@@ -543,11 +545,12 @@
545
546
547 /*
548 ** TH1 command: anycap STRING
549 **
550 ** Return true if the current user user
551 ** has any one of the capabilities listed in STRING.
552 */
553 static int anycapCmd(
554 Th_Interp *interp,
555 void *p,
556 int argc,
@@ -558,11 +561,11 @@
561 int i;
562 if( argc!=2 ){
563 return Th_WrongNumArgs(interp, "anycap STRING");
564 }
565 for(i=0; rc==0 && i<argl[1]; i++){
566 rc = login_has_capability((char*)&argv[1][i],1,0);
567 }
568 if( g.thTrace ){
569 Th_Trace("[hascap %#h] => %d<br />\n", argl[1], argv[1], rc);
570 }
571 Th_SetResultInt(interp, rc);
@@ -1450,15 +1453,18 @@
1453 int needConfig = flags & TH_INIT_NEED_CONFIG;
1454 int forceReset = flags & TH_INIT_FORCE_RESET;
1455 int forceTcl = flags & TH_INIT_FORCE_TCL;
1456 int forceSetup = flags & TH_INIT_FORCE_SETUP;
1457 static unsigned int aFlags[] = { 0, 1, WIKI_LINKSONLY };
1458 static int anonFlag = LOGIN_ANON;
1459 static int zeroInt = 0;
1460 static struct _Command {
1461 const char *zName;
1462 Th_CommandProc xProc;
1463 void *pContext;
1464 } aCommand[] = {
1465 {"anoncap", hascapCmd, (void*)&anonFlag},
1466 {"anycap", anycapCmd, 0},
1467 {"artifact", artifactCmd, 0},
1468 {"checkout", checkoutCmd, 0},
1469 {"combobox", comboboxCmd, 0},
1470 {"date", dateCmd, 0},
@@ -1465,11 +1471,11 @@
1471 {"decorate", wikiCmd, (void*)&aFlags[2]},
1472 {"enable_output", enableOutputCmd, 0},
1473 {"getParameter", getParameterCmd, 0},
1474 {"globalState", globalStateCmd, 0},
1475 {"httpize", httpizeCmd, 0},
1476 {"hascap", hascapCmd, (void*)&zeroInt},
1477 {"hasfeature", hasfeatureCmd, 0},
1478 {"html", putsCmd, (void*)&aFlags[0]},
1479 {"htmlize", htmlizeCmd, 0},
1480 {"http", httpCmd, 0},
1481 {"linecount", linecntCmd, 0},
1482
+6 -3
--- src/timeline.c
+++ src/timeline.c
@@ -163,11 +163,11 @@
163163
void test_hash_color_page(void){
164164
const char *zBr;
165165
char zNm[10];
166166
int i, cnt;
167167
login_check_credentials();
168
- if( !g.perm.Read ){ login_needed(); return; }
168
+ if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
169169
170170
style_header("Hash Color Test");
171171
for(i=cnt=0; i<10; i++){
172172
sqlite3_snprintf(sizeof(zNm),zNm,"b%d",i);
173173
zBr = P(zNm);
@@ -1175,11 +1175,11 @@
11751175
if( pd_rid ){
11761176
p_rid = d_rid = pd_rid;
11771177
}
11781178
login_check_credentials();
11791179
if( !g.perm.Read && !g.perm.RdTkt && !g.perm.RdWiki ){
1180
- login_needed();
1180
+ login_needed(g.anon.Read && g.anon.RdTkt && g.anon.RdWiki);
11811181
return;
11821182
}
11831183
url_initialize(&url, "timeline");
11841184
cgi_query_parameters_to_url(&url);
11851185
if( zTagName && g.perm.Read ){
@@ -2068,11 +2068,14 @@
20682068
*/
20692069
void test_timewarp_page(void){
20702070
Stmt q;
20712071
20722072
login_check_credentials();
2073
- if( !g.perm.Read || !g.perm.Hyperlink ){ login_needed(); return; }
2073
+ if( !g.perm.Read || !g.perm.Hyperlink ){
2074
+ login_needed(g.anon.Read && g.anon.Hyperlink);
2075
+ return;
2076
+ }
20742077
style_header("Instances of timewarp");
20752078
@ <ul>
20762079
db_prepare(&q,
20772080
"SELECT blob.uuid "
20782081
" FROM plink p, plink c, blob"
20792082
--- src/timeline.c
+++ src/timeline.c
@@ -163,11 +163,11 @@
163 void test_hash_color_page(void){
164 const char *zBr;
165 char zNm[10];
166 int i, cnt;
167 login_check_credentials();
168 if( !g.perm.Read ){ login_needed(); return; }
169
170 style_header("Hash Color Test");
171 for(i=cnt=0; i<10; i++){
172 sqlite3_snprintf(sizeof(zNm),zNm,"b%d",i);
173 zBr = P(zNm);
@@ -1175,11 +1175,11 @@
1175 if( pd_rid ){
1176 p_rid = d_rid = pd_rid;
1177 }
1178 login_check_credentials();
1179 if( !g.perm.Read && !g.perm.RdTkt && !g.perm.RdWiki ){
1180 login_needed();
1181 return;
1182 }
1183 url_initialize(&url, "timeline");
1184 cgi_query_parameters_to_url(&url);
1185 if( zTagName && g.perm.Read ){
@@ -2068,11 +2068,14 @@
2068 */
2069 void test_timewarp_page(void){
2070 Stmt q;
2071
2072 login_check_credentials();
2073 if( !g.perm.Read || !g.perm.Hyperlink ){ login_needed(); return; }
 
 
 
2074 style_header("Instances of timewarp");
2075 @ <ul>
2076 db_prepare(&q,
2077 "SELECT blob.uuid "
2078 " FROM plink p, plink c, blob"
2079
--- src/timeline.c
+++ src/timeline.c
@@ -163,11 +163,11 @@
163 void test_hash_color_page(void){
164 const char *zBr;
165 char zNm[10];
166 int i, cnt;
167 login_check_credentials();
168 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
169
170 style_header("Hash Color Test");
171 for(i=cnt=0; i<10; i++){
172 sqlite3_snprintf(sizeof(zNm),zNm,"b%d",i);
173 zBr = P(zNm);
@@ -1175,11 +1175,11 @@
1175 if( pd_rid ){
1176 p_rid = d_rid = pd_rid;
1177 }
1178 login_check_credentials();
1179 if( !g.perm.Read && !g.perm.RdTkt && !g.perm.RdWiki ){
1180 login_needed(g.anon.Read && g.anon.RdTkt && g.anon.RdWiki);
1181 return;
1182 }
1183 url_initialize(&url, "timeline");
1184 cgi_query_parameters_to_url(&url);
1185 if( zTagName && g.perm.Read ){
@@ -2068,11 +2068,14 @@
2068 */
2069 void test_timewarp_page(void){
2070 Stmt q;
2071
2072 login_check_credentials();
2073 if( !g.perm.Read || !g.perm.Hyperlink ){
2074 login_needed(g.anon.Read && g.anon.Hyperlink);
2075 return;
2076 }
2077 style_header("Instances of timewarp");
2078 @ <ul>
2079 db_prepare(&q,
2080 "SELECT blob.uuid "
2081 " FROM plink p, plink c, blob"
2082
+18 -9
--- src/tkt.c
+++ src/tkt.c
@@ -449,12 +449,12 @@
449449
const char *zScript;
450450
char *zFullName;
451451
const char *zUuid = PD("name","");
452452
453453
login_check_credentials();
454
- if( !g.perm.RdTkt ){ login_needed(); return; }
455
- if( g.perm.WrTkt || g.perm.ApndTkt ){
454
+ if( !g.perm.RdTkt ){ login_needed(g.anon.RdTkt); return; }
455
+ if( g.anon.WrTkt || g.anon.ApndTkt ){
456456
style_submenu_element("Edit", "Edit The Ticket", "%s/tktedit?name=%T",
457457
g.zTop, PD("name",""));
458458
}
459459
if( g.perm.Hyperlink ){
460460
style_submenu_element("History", "History Of This Ticket",
@@ -462,15 +462,15 @@
462462
style_submenu_element("Timeline", "Timeline Of This Ticket",
463463
"%s/tkttimeline/%T", g.zTop, zUuid);
464464
style_submenu_element("Check-ins", "Check-ins Of This Ticket",
465465
"%s/tkttimeline/%T?y=ci", g.zTop, zUuid);
466466
}
467
- if( g.perm.NewTkt ){
467
+ if( g.anon.NewTkt ){
468468
style_submenu_element("New Ticket", "Create a new ticket",
469469
"%s/tktnew", g.zTop);
470470
}
471
- if( g.perm.ApndTkt && g.perm.Attach ){
471
+ if( g.anon.ApndTkt && g.anon.Attach ){
472472
style_submenu_element("Attach", "Add An Attachment",
473473
"%s/attachadd?tkt=%T&from=%s/tktview/%t",
474474
g.zTop, zUuid, g.zTop, zUuid);
475475
}
476476
if( P("plaintext") ){
@@ -687,11 +687,11 @@
687687
void tktnew_page(void){
688688
const char *zScript;
689689
char *zNewUuid = 0;
690690
691691
login_check_credentials();
692
- if( !g.perm.NewTkt ){ login_needed(); return; }
692
+ if( !g.perm.NewTkt ){ login_needed(g.anon.NewTkt); return; }
693693
if( P("cancel") ){
694694
cgi_redirect("home");
695695
}
696696
style_header("New Ticket");
697697
ticket_standard_submenu(T_ALL_BUT(T_NEW));
@@ -738,11 +738,14 @@
738738
int nName;
739739
const char *zName;
740740
int nRec;
741741
742742
login_check_credentials();
743
- if( !g.perm.ApndTkt && !g.perm.WrTkt ){ login_needed(); return; }
743
+ if( !g.perm.ApndTkt && !g.perm.WrTkt ){
744
+ login_needed(g.anon.ApndTkt || g.anon.WrTkt);
745
+ return;
746
+ }
744747
zName = P("name");
745748
if( P("cancel") ){
746749
cgi_redirectf("tktview?name=%T", zName);
747750
}
748751
style_header("Edit Ticket");
@@ -839,11 +842,14 @@
839842
int tagid;
840843
char zGlobPattern[50];
841844
const char *zType;
842845
843846
login_check_credentials();
844
- if( !g.perm.Hyperlink || !g.perm.RdTkt ){ login_needed(); return; }
847
+ if( !g.perm.Hyperlink || !g.perm.RdTkt ){
848
+ login_needed(g.anon.Hyperlink && g.anon.RdTkt);
849
+ return;
850
+ }
845851
zUuid = PD("name","");
846852
zType = PD("y","a");
847853
if( zType[0]!='c' ){
848854
style_submenu_element("Check-ins", "Check-ins",
849855
"%s/tkttimeline?name=%T&y=ci", g.zTop, zUuid);
@@ -912,11 +918,14 @@
912918
const char *zUuid;
913919
int tagid;
914920
int nChng = 0;
915921
916922
login_check_credentials();
917
- if( !g.perm.Hyperlink || !g.perm.RdTkt ){ login_needed(); return; }
923
+ if( !g.perm.Hyperlink || !g.perm.RdTkt ){
924
+ login_needed(g.anon.Hyperlink && g.anon.RdTkt);
925
+ return;
926
+ }
918927
zUuid = PD("name","");
919928
zTitle = mprintf("History Of Ticket %h", zUuid);
920929
style_submenu_element("Status", "Status",
921930
"%s/info/%s", g.zTop, zUuid);
922931
style_submenu_element("Check-ins", "Check-ins",
@@ -1403,11 +1412,11 @@
14031412
style_submenu_element("Search","Search","%R/tktsrch");
14041413
}
14051414
if( (ok & T_REPLIST)!=0 ){
14061415
style_submenu_element("Reports","Reports","%R/reportlist");
14071416
}
1408
- if( (ok & T_NEW)!=0 && g.perm.NewTkt ){
1417
+ if( (ok & T_NEW)!=0 && g.anon.NewTkt ){
14091418
style_submenu_element("New","New","%R/tktnew");
14101419
}
14111420
}
14121421
14131422
/*
14141423
--- src/tkt.c
+++ src/tkt.c
@@ -449,12 +449,12 @@
449 const char *zScript;
450 char *zFullName;
451 const char *zUuid = PD("name","");
452
453 login_check_credentials();
454 if( !g.perm.RdTkt ){ login_needed(); return; }
455 if( g.perm.WrTkt || g.perm.ApndTkt ){
456 style_submenu_element("Edit", "Edit The Ticket", "%s/tktedit?name=%T",
457 g.zTop, PD("name",""));
458 }
459 if( g.perm.Hyperlink ){
460 style_submenu_element("History", "History Of This Ticket",
@@ -462,15 +462,15 @@
462 style_submenu_element("Timeline", "Timeline Of This Ticket",
463 "%s/tkttimeline/%T", g.zTop, zUuid);
464 style_submenu_element("Check-ins", "Check-ins Of This Ticket",
465 "%s/tkttimeline/%T?y=ci", g.zTop, zUuid);
466 }
467 if( g.perm.NewTkt ){
468 style_submenu_element("New Ticket", "Create a new ticket",
469 "%s/tktnew", g.zTop);
470 }
471 if( g.perm.ApndTkt && g.perm.Attach ){
472 style_submenu_element("Attach", "Add An Attachment",
473 "%s/attachadd?tkt=%T&from=%s/tktview/%t",
474 g.zTop, zUuid, g.zTop, zUuid);
475 }
476 if( P("plaintext") ){
@@ -687,11 +687,11 @@
687 void tktnew_page(void){
688 const char *zScript;
689 char *zNewUuid = 0;
690
691 login_check_credentials();
692 if( !g.perm.NewTkt ){ login_needed(); return; }
693 if( P("cancel") ){
694 cgi_redirect("home");
695 }
696 style_header("New Ticket");
697 ticket_standard_submenu(T_ALL_BUT(T_NEW));
@@ -738,11 +738,14 @@
738 int nName;
739 const char *zName;
740 int nRec;
741
742 login_check_credentials();
743 if( !g.perm.ApndTkt && !g.perm.WrTkt ){ login_needed(); return; }
 
 
 
744 zName = P("name");
745 if( P("cancel") ){
746 cgi_redirectf("tktview?name=%T", zName);
747 }
748 style_header("Edit Ticket");
@@ -839,11 +842,14 @@
839 int tagid;
840 char zGlobPattern[50];
841 const char *zType;
842
843 login_check_credentials();
844 if( !g.perm.Hyperlink || !g.perm.RdTkt ){ login_needed(); return; }
 
 
 
845 zUuid = PD("name","");
846 zType = PD("y","a");
847 if( zType[0]!='c' ){
848 style_submenu_element("Check-ins", "Check-ins",
849 "%s/tkttimeline?name=%T&y=ci", g.zTop, zUuid);
@@ -912,11 +918,14 @@
912 const char *zUuid;
913 int tagid;
914 int nChng = 0;
915
916 login_check_credentials();
917 if( !g.perm.Hyperlink || !g.perm.RdTkt ){ login_needed(); return; }
 
 
 
918 zUuid = PD("name","");
919 zTitle = mprintf("History Of Ticket %h", zUuid);
920 style_submenu_element("Status", "Status",
921 "%s/info/%s", g.zTop, zUuid);
922 style_submenu_element("Check-ins", "Check-ins",
@@ -1403,11 +1412,11 @@
1403 style_submenu_element("Search","Search","%R/tktsrch");
1404 }
1405 if( (ok & T_REPLIST)!=0 ){
1406 style_submenu_element("Reports","Reports","%R/reportlist");
1407 }
1408 if( (ok & T_NEW)!=0 && g.perm.NewTkt ){
1409 style_submenu_element("New","New","%R/tktnew");
1410 }
1411 }
1412
1413 /*
1414
--- src/tkt.c
+++ src/tkt.c
@@ -449,12 +449,12 @@
449 const char *zScript;
450 char *zFullName;
451 const char *zUuid = PD("name","");
452
453 login_check_credentials();
454 if( !g.perm.RdTkt ){ login_needed(g.anon.RdTkt); return; }
455 if( g.anon.WrTkt || g.anon.ApndTkt ){
456 style_submenu_element("Edit", "Edit The Ticket", "%s/tktedit?name=%T",
457 g.zTop, PD("name",""));
458 }
459 if( g.perm.Hyperlink ){
460 style_submenu_element("History", "History Of This Ticket",
@@ -462,15 +462,15 @@
462 style_submenu_element("Timeline", "Timeline Of This Ticket",
463 "%s/tkttimeline/%T", g.zTop, zUuid);
464 style_submenu_element("Check-ins", "Check-ins Of This Ticket",
465 "%s/tkttimeline/%T?y=ci", g.zTop, zUuid);
466 }
467 if( g.anon.NewTkt ){
468 style_submenu_element("New Ticket", "Create a new ticket",
469 "%s/tktnew", g.zTop);
470 }
471 if( g.anon.ApndTkt && g.anon.Attach ){
472 style_submenu_element("Attach", "Add An Attachment",
473 "%s/attachadd?tkt=%T&from=%s/tktview/%t",
474 g.zTop, zUuid, g.zTop, zUuid);
475 }
476 if( P("plaintext") ){
@@ -687,11 +687,11 @@
687 void tktnew_page(void){
688 const char *zScript;
689 char *zNewUuid = 0;
690
691 login_check_credentials();
692 if( !g.perm.NewTkt ){ login_needed(g.anon.NewTkt); return; }
693 if( P("cancel") ){
694 cgi_redirect("home");
695 }
696 style_header("New Ticket");
697 ticket_standard_submenu(T_ALL_BUT(T_NEW));
@@ -738,11 +738,14 @@
738 int nName;
739 const char *zName;
740 int nRec;
741
742 login_check_credentials();
743 if( !g.perm.ApndTkt && !g.perm.WrTkt ){
744 login_needed(g.anon.ApndTkt || g.anon.WrTkt);
745 return;
746 }
747 zName = P("name");
748 if( P("cancel") ){
749 cgi_redirectf("tktview?name=%T", zName);
750 }
751 style_header("Edit Ticket");
@@ -839,11 +842,14 @@
842 int tagid;
843 char zGlobPattern[50];
844 const char *zType;
845
846 login_check_credentials();
847 if( !g.perm.Hyperlink || !g.perm.RdTkt ){
848 login_needed(g.anon.Hyperlink && g.anon.RdTkt);
849 return;
850 }
851 zUuid = PD("name","");
852 zType = PD("y","a");
853 if( zType[0]!='c' ){
854 style_submenu_element("Check-ins", "Check-ins",
855 "%s/tkttimeline?name=%T&y=ci", g.zTop, zUuid);
@@ -912,11 +918,14 @@
918 const char *zUuid;
919 int tagid;
920 int nChng = 0;
921
922 login_check_credentials();
923 if( !g.perm.Hyperlink || !g.perm.RdTkt ){
924 login_needed(g.anon.Hyperlink && g.anon.RdTkt);
925 return;
926 }
927 zUuid = PD("name","");
928 zTitle = mprintf("History Of Ticket %h", zUuid);
929 style_submenu_element("Status", "Status",
930 "%s/info/%s", g.zTop, zUuid);
931 style_submenu_element("Check-ins", "Check-ins",
@@ -1403,11 +1412,11 @@
1412 style_submenu_element("Search","Search","%R/tktsrch");
1413 }
1414 if( (ok & T_REPLIST)!=0 ){
1415 style_submenu_element("Reports","Reports","%R/reportlist");
1416 }
1417 if( (ok & T_NEW)!=0 && g.anon.NewTkt ){
1418 style_submenu_element("New","New","%R/tktnew");
1419 }
1420 }
1421
1422 /*
1423
+11 -8
--- src/tktsetup.c
+++ src/tktsetup.c
@@ -27,11 +27,12 @@
2727
** WEBPAGE: tktsetup
2828
*/
2929
void tktsetup_page(void){
3030
login_check_credentials();
3131
if( !g.perm.Setup ){
32
- login_needed();
32
+ login_needed(0);
33
+ return;
3334
}
3435
3536
style_header("Ticket Setup");
3637
@ <table border="0" cellspacing="20">
3738
setup_menu_entry("Table", "tktsetup_tab",
@@ -118,13 +119,14 @@
118119
const char *z;
119120
int isSubmit;
120121
121122
login_check_credentials();
122123
if( !g.perm.Setup ){
123
- login_needed();
124
+ login_needed(0);
125
+ return;
124126
}
125
- if( P("setup") ){
127
+ if( PB("setup") ){
126128
cgi_redirect("tktsetup");
127129
}
128130
isSubmit = P("submit")!=0;
129131
z = P("x");
130132
if( z==0 ){
@@ -713,11 +715,11 @@
713715
/*
714716
** The default report list page
715717
*/
716718
static const char zDefaultReportList[] =
717719
@ <th1>
718
-@ if {[hascap n]} {
720
+@ if {[anoncap n]} {
719721
@ html "<p>Enter a new ticket:</p>"
720722
@ html "<ul><li><a href='tktnew'>New ticket</a></li></ul>"
721723
@ }
722724
@ </th1>
723725
@
@@ -725,16 +727,16 @@
725727
@ <ol>
726728
@ <th1>html $report_items</th1>
727729
@ </ol>
728730
@
729731
@ <th1>
730
-@ if {[hascap t q]} {
732
+@ if {[anoncap t q]} {
731733
@ html "<p>Other options:</p>\n<ul>\n"
732
-@ if {[hascap t]} {
734
+@ if {[anoncap t]} {
733735
@ html "<li><a href='rptnew'>New report format</a></li>\n"
734736
@ }
735
-@ if {[hascap q]} {
737
+@ if {[anoncap q]} {
736738
@ html "<li><a href='modreq'>Tend to pending moderation requests</a></li>\n"
737739
@ }
738740
@ }
739741
@ </th1>
740742
;
@@ -858,11 +860,12 @@
858860
** WEBPAGE: tktsetup_timeline
859861
*/
860862
void tktsetup_timeline_page(void){
861863
login_check_credentials();
862864
if( !g.perm.Setup ){
863
- login_needed();
865
+ login_needed(0);
866
+ return;
864867
}
865868
866869
if( P("setup") ){
867870
cgi_redirect("tktsetup");
868871
}
869872
--- src/tktsetup.c
+++ src/tktsetup.c
@@ -27,11 +27,12 @@
27 ** WEBPAGE: tktsetup
28 */
29 void tktsetup_page(void){
30 login_check_credentials();
31 if( !g.perm.Setup ){
32 login_needed();
 
33 }
34
35 style_header("Ticket Setup");
36 @ <table border="0" cellspacing="20">
37 setup_menu_entry("Table", "tktsetup_tab",
@@ -118,13 +119,14 @@
118 const char *z;
119 int isSubmit;
120
121 login_check_credentials();
122 if( !g.perm.Setup ){
123 login_needed();
 
124 }
125 if( P("setup") ){
126 cgi_redirect("tktsetup");
127 }
128 isSubmit = P("submit")!=0;
129 z = P("x");
130 if( z==0 ){
@@ -713,11 +715,11 @@
713 /*
714 ** The default report list page
715 */
716 static const char zDefaultReportList[] =
717 @ <th1>
718 @ if {[hascap n]} {
719 @ html "<p>Enter a new ticket:</p>"
720 @ html "<ul><li><a href='tktnew'>New ticket</a></li></ul>"
721 @ }
722 @ </th1>
723 @
@@ -725,16 +727,16 @@
725 @ <ol>
726 @ <th1>html $report_items</th1>
727 @ </ol>
728 @
729 @ <th1>
730 @ if {[hascap t q]} {
731 @ html "<p>Other options:</p>\n<ul>\n"
732 @ if {[hascap t]} {
733 @ html "<li><a href='rptnew'>New report format</a></li>\n"
734 @ }
735 @ if {[hascap q]} {
736 @ html "<li><a href='modreq'>Tend to pending moderation requests</a></li>\n"
737 @ }
738 @ }
739 @ </th1>
740 ;
@@ -858,11 +860,12 @@
858 ** WEBPAGE: tktsetup_timeline
859 */
860 void tktsetup_timeline_page(void){
861 login_check_credentials();
862 if( !g.perm.Setup ){
863 login_needed();
 
864 }
865
866 if( P("setup") ){
867 cgi_redirect("tktsetup");
868 }
869
--- src/tktsetup.c
+++ src/tktsetup.c
@@ -27,11 +27,12 @@
27 ** WEBPAGE: tktsetup
28 */
29 void tktsetup_page(void){
30 login_check_credentials();
31 if( !g.perm.Setup ){
32 login_needed(0);
33 return;
34 }
35
36 style_header("Ticket Setup");
37 @ <table border="0" cellspacing="20">
38 setup_menu_entry("Table", "tktsetup_tab",
@@ -118,13 +119,14 @@
119 const char *z;
120 int isSubmit;
121
122 login_check_credentials();
123 if( !g.perm.Setup ){
124 login_needed(0);
125 return;
126 }
127 if( PB("setup") ){
128 cgi_redirect("tktsetup");
129 }
130 isSubmit = P("submit")!=0;
131 z = P("x");
132 if( z==0 ){
@@ -713,11 +715,11 @@
715 /*
716 ** The default report list page
717 */
718 static const char zDefaultReportList[] =
719 @ <th1>
720 @ if {[anoncap n]} {
721 @ html "<p>Enter a new ticket:</p>"
722 @ html "<ul><li><a href='tktnew'>New ticket</a></li></ul>"
723 @ }
724 @ </th1>
725 @
@@ -725,16 +727,16 @@
727 @ <ol>
728 @ <th1>html $report_items</th1>
729 @ </ol>
730 @
731 @ <th1>
732 @ if {[anoncap t q]} {
733 @ html "<p>Other options:</p>\n<ul>\n"
734 @ if {[anoncap t]} {
735 @ html "<li><a href='rptnew'>New report format</a></li>\n"
736 @ }
737 @ if {[anoncap q]} {
738 @ html "<li><a href='modreq'>Tend to pending moderation requests</a></li>\n"
739 @ }
740 @ }
741 @ </th1>
742 ;
@@ -858,11 +860,12 @@
860 ** WEBPAGE: tktsetup_timeline
861 */
862 void tktsetup_timeline_page(void){
863 login_check_credentials();
864 if( !g.perm.Setup ){
865 login_needed(0);
866 return;
867 }
868
869 if( P("setup") ){
870 cgi_redirect("tktsetup");
871 }
872
+1 -1
--- src/user.c
+++ src/user.c
@@ -424,11 +424,11 @@
424424
Stmt q;
425425
int cnt = 0;
426426
int rc;
427427
428428
login_check_credentials();
429
- if( !g.perm.Admin ){ login_needed(); return; }
429
+ if( !g.perm.Admin ){ login_needed(0); return; }
430430
create_accesslog_table();
431431
432432
if( P("delall") && P("delallbtn") ){
433433
db_multi_exec("DELETE FROM accesslog");
434434
cgi_redirectf("%s/access_log?y=%d&n=%d&o=%o", g.zTop, y, n, skip);
435435
--- src/user.c
+++ src/user.c
@@ -424,11 +424,11 @@
424 Stmt q;
425 int cnt = 0;
426 int rc;
427
428 login_check_credentials();
429 if( !g.perm.Admin ){ login_needed(); return; }
430 create_accesslog_table();
431
432 if( P("delall") && P("delallbtn") ){
433 db_multi_exec("DELETE FROM accesslog");
434 cgi_redirectf("%s/access_log?y=%d&n=%d&o=%o", g.zTop, y, n, skip);
435
--- src/user.c
+++ src/user.c
@@ -424,11 +424,11 @@
424 Stmt q;
425 int cnt = 0;
426 int rc;
427
428 login_check_credentials();
429 if( !g.perm.Admin ){ login_needed(0); return; }
430 create_accesslog_table();
431
432 if( P("delall") && P("delallbtn") ){
433 db_multi_exec("DELETE FROM accesslog");
434 cgi_redirectf("%s/access_log?y=%d&n=%d&o=%o", g.zTop, y, n, skip);
435
+18 -18
--- src/wiki.c
+++ src/wiki.c
@@ -222,11 +222,11 @@
222222
style_submenu_element("List","List","%R/wcontent");
223223
}
224224
if( (ok & W_HELP)!=0 ){
225225
style_submenu_element("Help","Help","%R/wikihelp");
226226
}
227
- if( (ok & W_NEW)!=0 && g.perm.NewWiki ){
227
+ if( (ok & W_NEW)!=0 && g.anon.NewWiki ){
228228
style_submenu_element("New","New","%R/wikinew");
229229
}
230230
#if 0
231231
if( (ok & W_BLOG)!=0
232232
#endif
@@ -239,11 +239,11 @@
239239
** WEBPAGE: wikihelp
240240
** A generic landing page for wiki.
241241
*/
242242
void wiki_helppage(void){
243243
login_check_credentials();
244
- if( !g.perm.RdWiki ){ login_needed(); return; }
244
+ if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; }
245245
style_header("Wiki Help");
246246
wiki_standard_submenu(W_ALL_BUT(W_HELP));
247247
@ <h2>Wiki Links</h2>
248248
@ <ul>
249249
{ char *zWikiHomePageName = db_get("index-page",0);
@@ -261,19 +261,19 @@
261261
@ <li> %z(href("%R/timeline?y=w"))Recent changes</a> to wiki pages.</li>
262262
@ <li> Formatting rules for %z(href("%R/wiki_rules"))Fossil Wiki</a> and for
263263
@ %z(href("%R/md_rules"))Markdown Wiki</a>.</li>
264264
@ <li> Use the %z(href("%R/wiki?name=Sandbox"))Sandbox</a>
265265
@ to experiment.</li>
266
- if( g.perm.NewWiki ){
266
+ if( g.anon.NewWiki ){
267267
@ <li> Create a %z(href("%R/wikinew"))new wiki page</a>.</li>
268
- if( g.perm.Write ){
269
- @ <li> Create a %z(href("%R/eventedit"))new blog entry</a>.</li>
268
+ if( g.anon.Write ){
269
+ @ <li> Create a %z(href("%R/eventedit"))new tech-note</a>.</li>
270270
}
271271
}
272272
@ <li> %z(href("%R/wcontent"))List of All Wiki Pages</a>
273273
@ available on this server.</li>
274
- if( g.perm.ModWiki ){
274
+ if( g.anon.ModWiki ){
275275
@ <li> %z(href("%R/modreq"))Tend to pending moderation requests</a></li>
276276
}
277277
if( search_restrict(SRCH_WIKI)!=0 ){
278278
@ <li> %z(href("%R/wikisrch"))Search</a> for wiki pages containing key
279279
@ words</li>
@@ -312,11 +312,11 @@
312312
const char *zPageName;
313313
const char *zMimetype = 0;
314314
char *zBody = mprintf("%s","<i>Empty Page</i>");
315315
316316
login_check_credentials();
317
- if( !g.perm.RdWiki ){ login_needed(); return; }
317
+ if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; }
318318
zPageName = P("name");
319319
if( zPageName==0 ){
320320
if( search_restrict(SRCH_WIKI)!=0 ){
321321
wiki_srchpage();
322322
}else{
@@ -355,11 +355,11 @@
355355
"%R/wdiff?name=%T&a=%d", zPageName, rid);
356356
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
357357
style_submenu_element("Details", "Details",
358358
"%R/info/%s", zUuid);
359359
}
360
- if( (rid && g.perm.WrWiki) || (!rid && g.perm.NewWiki) ){
360
+ if( (rid && g.anon.WrWiki) || (!rid && g.anon.NewWiki) ){
361361
if( db_get_boolean("wysiwyg-wiki", 0) ){
362362
style_submenu_element("Edit", "Edit Wiki Page",
363363
"%s/wikiedit?name=%T&wysiwyg=1",
364364
g.zTop, zPageName);
365365
}else{
@@ -366,16 +366,16 @@
366366
style_submenu_element("Edit", "Edit Wiki Page",
367367
"%s/wikiedit?name=%T",
368368
g.zTop, zPageName);
369369
}
370370
}
371
- if( rid && g.perm.ApndWiki && g.perm.Attach ){
371
+ if( rid && g.anon.ApndWiki && g.anon.Attach ){
372372
style_submenu_element("Attach", "Add An Attachment",
373373
"%s/attachadd?page=%T&from=%s/wiki%%3fname=%T",
374374
g.zTop, zPageName, g.zTop, zPageName);
375375
}
376
- if( rid && g.perm.ApndWiki ){
376
+ if( rid && g.anon.ApndWiki ){
377377
style_submenu_element("Append", "Add A Comment",
378378
"%s/wikiappend?name=%T&mimetype=%s",
379379
g.zTop, zPageName, zMimetype);
380380
}
381381
if( g.perm.Hyperlink ){
@@ -485,11 +485,11 @@
485485
zPageName = PD("name","");
486486
if( check_name(zPageName) ) return;
487487
isSandbox = is_sandbox(zPageName);
488488
if( isSandbox ){
489489
if( !g.perm.WrWiki ){
490
- login_needed();
490
+ login_needed(g.anon.WrWiki);
491491
return;
492492
}
493493
if( zBody==0 ){
494494
zBody = db_get("sandbox","");
495495
zMimetype = db_get("sandbox-mimetype","text/x-fossil-wiki");
@@ -501,11 +501,11 @@
501501
" WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)"
502502
" ORDER BY mtime DESC", zTag
503503
);
504504
free(zTag);
505505
if( (rid && !g.perm.WrWiki) || (!rid && !g.perm.NewWiki) ){
506
- login_needed();
506
+ login_needed(rid ? g.anon.WrWiki : g.anon.NewWiki);
507507
return;
508508
}
509509
if( zBody==0 && (pWiki = manifest_get(rid, CFTYPE_WIKI, 0))!=0 ){
510510
zBody = pWiki->zWiki;
511511
zMimetype = pWiki->zMimetype;
@@ -625,11 +625,11 @@
625625
void wikinew_page(void){
626626
const char *zName;
627627
const char *zMimetype;
628628
login_check_credentials();
629629
if( !g.perm.NewWiki ){
630
- login_needed();
630
+ login_needed(g.anon.NewWiki);
631631
return;
632632
}
633633
zName = PD("name","");
634634
zMimetype = wiki_filter_mimetypes(P("mimetype"));
635635
if( zName[0] && wiki_name_is_wellformed((const unsigned char *)zName) ){
@@ -727,11 +727,11 @@
727727
fossil_redirect_home();
728728
return;
729729
}
730730
}
731731
if( !g.perm.ApndWiki ){
732
- login_needed();
732
+ login_needed(g.anon.ApndWiki);
733733
return;
734734
}
735735
if( P("submit")!=0 && P("r")!=0 && P("u")!=0
736736
&& (goodCaptcha = captcha_is_correct())
737737
){
@@ -840,11 +840,11 @@
840840
*/
841841
void whistory_page(void){
842842
Stmt q;
843843
const char *zPageName;
844844
login_check_credentials();
845
- if( !g.perm.Hyperlink ){ login_needed(); return; }
845
+ if( !g.perm.Hyperlink ){ login_needed(g.anon.Hyperlink); return; }
846846
zPageName = PD("name","");
847847
style_header("History Of %s", zPageName);
848848
849849
db_prepare(&q, "%s AND event.objid IN "
850850
" (SELECT rid FROM tagxref WHERE tagid="
@@ -872,11 +872,11 @@
872872
Blob w1, w2, d;
873873
u64 diffFlags;
874874
875875
login_check_credentials();
876876
rid1 = atoi(PD("a","0"));
877
- if( !g.perm.Hyperlink ){ login_needed(); return; }
877
+ if( !g.perm.Hyperlink ){ login_needed(g.anon.Hyperlink); return; }
878878
if( rid1==0 ) fossil_redirect_home();
879879
rid2 = atoi(PD("b","0"));
880880
zPageName = PD("name","");
881881
style_header("Changes To %s", zPageName);
882882
@@ -935,11 +935,11 @@
935935
void wcontent_page(void){
936936
Stmt q;
937937
int showAll = P("all")!=0;
938938
939939
login_check_credentials();
940
- if( !g.perm.RdWiki ){ login_needed(); return; }
940
+ if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; }
941941
style_header("Available Wiki Pages");
942942
if( showAll ){
943943
style_submenu_element("Active", "Only Active Pages", "%s/wcontent", g.zTop);
944944
}else{
945945
style_submenu_element("All", "All", "%s/wcontent?all=1", g.zTop);
@@ -969,11 +969,11 @@
969969
*/
970970
void wfind_page(void){
971971
Stmt q;
972972
const char *zTitle;
973973
login_check_credentials();
974
- if( !g.perm.RdWiki ){ login_needed(); return; }
974
+ if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; }
975975
zTitle = PD("title","*");
976976
style_header("Wiki Pages Found");
977977
@ <ul>
978978
db_prepare(&q,
979979
"SELECT substr(tagname, 6, 1000) FROM tag WHERE tagname like 'wiki-%%%q%%'"
980980
--- src/wiki.c
+++ src/wiki.c
@@ -222,11 +222,11 @@
222 style_submenu_element("List","List","%R/wcontent");
223 }
224 if( (ok & W_HELP)!=0 ){
225 style_submenu_element("Help","Help","%R/wikihelp");
226 }
227 if( (ok & W_NEW)!=0 && g.perm.NewWiki ){
228 style_submenu_element("New","New","%R/wikinew");
229 }
230 #if 0
231 if( (ok & W_BLOG)!=0
232 #endif
@@ -239,11 +239,11 @@
239 ** WEBPAGE: wikihelp
240 ** A generic landing page for wiki.
241 */
242 void wiki_helppage(void){
243 login_check_credentials();
244 if( !g.perm.RdWiki ){ login_needed(); return; }
245 style_header("Wiki Help");
246 wiki_standard_submenu(W_ALL_BUT(W_HELP));
247 @ <h2>Wiki Links</h2>
248 @ <ul>
249 { char *zWikiHomePageName = db_get("index-page",0);
@@ -261,19 +261,19 @@
261 @ <li> %z(href("%R/timeline?y=w"))Recent changes</a> to wiki pages.</li>
262 @ <li> Formatting rules for %z(href("%R/wiki_rules"))Fossil Wiki</a> and for
263 @ %z(href("%R/md_rules"))Markdown Wiki</a>.</li>
264 @ <li> Use the %z(href("%R/wiki?name=Sandbox"))Sandbox</a>
265 @ to experiment.</li>
266 if( g.perm.NewWiki ){
267 @ <li> Create a %z(href("%R/wikinew"))new wiki page</a>.</li>
268 if( g.perm.Write ){
269 @ <li> Create a %z(href("%R/eventedit"))new blog entry</a>.</li>
270 }
271 }
272 @ <li> %z(href("%R/wcontent"))List of All Wiki Pages</a>
273 @ available on this server.</li>
274 if( g.perm.ModWiki ){
275 @ <li> %z(href("%R/modreq"))Tend to pending moderation requests</a></li>
276 }
277 if( search_restrict(SRCH_WIKI)!=0 ){
278 @ <li> %z(href("%R/wikisrch"))Search</a> for wiki pages containing key
279 @ words</li>
@@ -312,11 +312,11 @@
312 const char *zPageName;
313 const char *zMimetype = 0;
314 char *zBody = mprintf("%s","<i>Empty Page</i>");
315
316 login_check_credentials();
317 if( !g.perm.RdWiki ){ login_needed(); return; }
318 zPageName = P("name");
319 if( zPageName==0 ){
320 if( search_restrict(SRCH_WIKI)!=0 ){
321 wiki_srchpage();
322 }else{
@@ -355,11 +355,11 @@
355 "%R/wdiff?name=%T&a=%d", zPageName, rid);
356 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
357 style_submenu_element("Details", "Details",
358 "%R/info/%s", zUuid);
359 }
360 if( (rid && g.perm.WrWiki) || (!rid && g.perm.NewWiki) ){
361 if( db_get_boolean("wysiwyg-wiki", 0) ){
362 style_submenu_element("Edit", "Edit Wiki Page",
363 "%s/wikiedit?name=%T&wysiwyg=1",
364 g.zTop, zPageName);
365 }else{
@@ -366,16 +366,16 @@
366 style_submenu_element("Edit", "Edit Wiki Page",
367 "%s/wikiedit?name=%T",
368 g.zTop, zPageName);
369 }
370 }
371 if( rid && g.perm.ApndWiki && g.perm.Attach ){
372 style_submenu_element("Attach", "Add An Attachment",
373 "%s/attachadd?page=%T&from=%s/wiki%%3fname=%T",
374 g.zTop, zPageName, g.zTop, zPageName);
375 }
376 if( rid && g.perm.ApndWiki ){
377 style_submenu_element("Append", "Add A Comment",
378 "%s/wikiappend?name=%T&mimetype=%s",
379 g.zTop, zPageName, zMimetype);
380 }
381 if( g.perm.Hyperlink ){
@@ -485,11 +485,11 @@
485 zPageName = PD("name","");
486 if( check_name(zPageName) ) return;
487 isSandbox = is_sandbox(zPageName);
488 if( isSandbox ){
489 if( !g.perm.WrWiki ){
490 login_needed();
491 return;
492 }
493 if( zBody==0 ){
494 zBody = db_get("sandbox","");
495 zMimetype = db_get("sandbox-mimetype","text/x-fossil-wiki");
@@ -501,11 +501,11 @@
501 " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)"
502 " ORDER BY mtime DESC", zTag
503 );
504 free(zTag);
505 if( (rid && !g.perm.WrWiki) || (!rid && !g.perm.NewWiki) ){
506 login_needed();
507 return;
508 }
509 if( zBody==0 && (pWiki = manifest_get(rid, CFTYPE_WIKI, 0))!=0 ){
510 zBody = pWiki->zWiki;
511 zMimetype = pWiki->zMimetype;
@@ -625,11 +625,11 @@
625 void wikinew_page(void){
626 const char *zName;
627 const char *zMimetype;
628 login_check_credentials();
629 if( !g.perm.NewWiki ){
630 login_needed();
631 return;
632 }
633 zName = PD("name","");
634 zMimetype = wiki_filter_mimetypes(P("mimetype"));
635 if( zName[0] && wiki_name_is_wellformed((const unsigned char *)zName) ){
@@ -727,11 +727,11 @@
727 fossil_redirect_home();
728 return;
729 }
730 }
731 if( !g.perm.ApndWiki ){
732 login_needed();
733 return;
734 }
735 if( P("submit")!=0 && P("r")!=0 && P("u")!=0
736 && (goodCaptcha = captcha_is_correct())
737 ){
@@ -840,11 +840,11 @@
840 */
841 void whistory_page(void){
842 Stmt q;
843 const char *zPageName;
844 login_check_credentials();
845 if( !g.perm.Hyperlink ){ login_needed(); return; }
846 zPageName = PD("name","");
847 style_header("History Of %s", zPageName);
848
849 db_prepare(&q, "%s AND event.objid IN "
850 " (SELECT rid FROM tagxref WHERE tagid="
@@ -872,11 +872,11 @@
872 Blob w1, w2, d;
873 u64 diffFlags;
874
875 login_check_credentials();
876 rid1 = atoi(PD("a","0"));
877 if( !g.perm.Hyperlink ){ login_needed(); return; }
878 if( rid1==0 ) fossil_redirect_home();
879 rid2 = atoi(PD("b","0"));
880 zPageName = PD("name","");
881 style_header("Changes To %s", zPageName);
882
@@ -935,11 +935,11 @@
935 void wcontent_page(void){
936 Stmt q;
937 int showAll = P("all")!=0;
938
939 login_check_credentials();
940 if( !g.perm.RdWiki ){ login_needed(); return; }
941 style_header("Available Wiki Pages");
942 if( showAll ){
943 style_submenu_element("Active", "Only Active Pages", "%s/wcontent", g.zTop);
944 }else{
945 style_submenu_element("All", "All", "%s/wcontent?all=1", g.zTop);
@@ -969,11 +969,11 @@
969 */
970 void wfind_page(void){
971 Stmt q;
972 const char *zTitle;
973 login_check_credentials();
974 if( !g.perm.RdWiki ){ login_needed(); return; }
975 zTitle = PD("title","*");
976 style_header("Wiki Pages Found");
977 @ <ul>
978 db_prepare(&q,
979 "SELECT substr(tagname, 6, 1000) FROM tag WHERE tagname like 'wiki-%%%q%%'"
980
--- src/wiki.c
+++ src/wiki.c
@@ -222,11 +222,11 @@
222 style_submenu_element("List","List","%R/wcontent");
223 }
224 if( (ok & W_HELP)!=0 ){
225 style_submenu_element("Help","Help","%R/wikihelp");
226 }
227 if( (ok & W_NEW)!=0 && g.anon.NewWiki ){
228 style_submenu_element("New","New","%R/wikinew");
229 }
230 #if 0
231 if( (ok & W_BLOG)!=0
232 #endif
@@ -239,11 +239,11 @@
239 ** WEBPAGE: wikihelp
240 ** A generic landing page for wiki.
241 */
242 void wiki_helppage(void){
243 login_check_credentials();
244 if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; }
245 style_header("Wiki Help");
246 wiki_standard_submenu(W_ALL_BUT(W_HELP));
247 @ <h2>Wiki Links</h2>
248 @ <ul>
249 { char *zWikiHomePageName = db_get("index-page",0);
@@ -261,19 +261,19 @@
261 @ <li> %z(href("%R/timeline?y=w"))Recent changes</a> to wiki pages.</li>
262 @ <li> Formatting rules for %z(href("%R/wiki_rules"))Fossil Wiki</a> and for
263 @ %z(href("%R/md_rules"))Markdown Wiki</a>.</li>
264 @ <li> Use the %z(href("%R/wiki?name=Sandbox"))Sandbox</a>
265 @ to experiment.</li>
266 if( g.anon.NewWiki ){
267 @ <li> Create a %z(href("%R/wikinew"))new wiki page</a>.</li>
268 if( g.anon.Write ){
269 @ <li> Create a %z(href("%R/eventedit"))new tech-note</a>.</li>
270 }
271 }
272 @ <li> %z(href("%R/wcontent"))List of All Wiki Pages</a>
273 @ available on this server.</li>
274 if( g.anon.ModWiki ){
275 @ <li> %z(href("%R/modreq"))Tend to pending moderation requests</a></li>
276 }
277 if( search_restrict(SRCH_WIKI)!=0 ){
278 @ <li> %z(href("%R/wikisrch"))Search</a> for wiki pages containing key
279 @ words</li>
@@ -312,11 +312,11 @@
312 const char *zPageName;
313 const char *zMimetype = 0;
314 char *zBody = mprintf("%s","<i>Empty Page</i>");
315
316 login_check_credentials();
317 if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; }
318 zPageName = P("name");
319 if( zPageName==0 ){
320 if( search_restrict(SRCH_WIKI)!=0 ){
321 wiki_srchpage();
322 }else{
@@ -355,11 +355,11 @@
355 "%R/wdiff?name=%T&a=%d", zPageName, rid);
356 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
357 style_submenu_element("Details", "Details",
358 "%R/info/%s", zUuid);
359 }
360 if( (rid && g.anon.WrWiki) || (!rid && g.anon.NewWiki) ){
361 if( db_get_boolean("wysiwyg-wiki", 0) ){
362 style_submenu_element("Edit", "Edit Wiki Page",
363 "%s/wikiedit?name=%T&wysiwyg=1",
364 g.zTop, zPageName);
365 }else{
@@ -366,16 +366,16 @@
366 style_submenu_element("Edit", "Edit Wiki Page",
367 "%s/wikiedit?name=%T",
368 g.zTop, zPageName);
369 }
370 }
371 if( rid && g.anon.ApndWiki && g.anon.Attach ){
372 style_submenu_element("Attach", "Add An Attachment",
373 "%s/attachadd?page=%T&from=%s/wiki%%3fname=%T",
374 g.zTop, zPageName, g.zTop, zPageName);
375 }
376 if( rid && g.anon.ApndWiki ){
377 style_submenu_element("Append", "Add A Comment",
378 "%s/wikiappend?name=%T&mimetype=%s",
379 g.zTop, zPageName, zMimetype);
380 }
381 if( g.perm.Hyperlink ){
@@ -485,11 +485,11 @@
485 zPageName = PD("name","");
486 if( check_name(zPageName) ) return;
487 isSandbox = is_sandbox(zPageName);
488 if( isSandbox ){
489 if( !g.perm.WrWiki ){
490 login_needed(g.anon.WrWiki);
491 return;
492 }
493 if( zBody==0 ){
494 zBody = db_get("sandbox","");
495 zMimetype = db_get("sandbox-mimetype","text/x-fossil-wiki");
@@ -501,11 +501,11 @@
501 " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)"
502 " ORDER BY mtime DESC", zTag
503 );
504 free(zTag);
505 if( (rid && !g.perm.WrWiki) || (!rid && !g.perm.NewWiki) ){
506 login_needed(rid ? g.anon.WrWiki : g.anon.NewWiki);
507 return;
508 }
509 if( zBody==0 && (pWiki = manifest_get(rid, CFTYPE_WIKI, 0))!=0 ){
510 zBody = pWiki->zWiki;
511 zMimetype = pWiki->zMimetype;
@@ -625,11 +625,11 @@
625 void wikinew_page(void){
626 const char *zName;
627 const char *zMimetype;
628 login_check_credentials();
629 if( !g.perm.NewWiki ){
630 login_needed(g.anon.NewWiki);
631 return;
632 }
633 zName = PD("name","");
634 zMimetype = wiki_filter_mimetypes(P("mimetype"));
635 if( zName[0] && wiki_name_is_wellformed((const unsigned char *)zName) ){
@@ -727,11 +727,11 @@
727 fossil_redirect_home();
728 return;
729 }
730 }
731 if( !g.perm.ApndWiki ){
732 login_needed(g.anon.ApndWiki);
733 return;
734 }
735 if( P("submit")!=0 && P("r")!=0 && P("u")!=0
736 && (goodCaptcha = captcha_is_correct())
737 ){
@@ -840,11 +840,11 @@
840 */
841 void whistory_page(void){
842 Stmt q;
843 const char *zPageName;
844 login_check_credentials();
845 if( !g.perm.Hyperlink ){ login_needed(g.anon.Hyperlink); return; }
846 zPageName = PD("name","");
847 style_header("History Of %s", zPageName);
848
849 db_prepare(&q, "%s AND event.objid IN "
850 " (SELECT rid FROM tagxref WHERE tagid="
@@ -872,11 +872,11 @@
872 Blob w1, w2, d;
873 u64 diffFlags;
874
875 login_check_credentials();
876 rid1 = atoi(PD("a","0"));
877 if( !g.perm.Hyperlink ){ login_needed(g.anon.Hyperlink); return; }
878 if( rid1==0 ) fossil_redirect_home();
879 rid2 = atoi(PD("b","0"));
880 zPageName = PD("name","");
881 style_header("Changes To %s", zPageName);
882
@@ -935,11 +935,11 @@
935 void wcontent_page(void){
936 Stmt q;
937 int showAll = P("all")!=0;
938
939 login_check_credentials();
940 if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; }
941 style_header("Available Wiki Pages");
942 if( showAll ){
943 style_submenu_element("Active", "Only Active Pages", "%s/wcontent", g.zTop);
944 }else{
945 style_submenu_element("All", "All", "%s/wcontent?all=1", g.zTop);
@@ -969,11 +969,11 @@
969 */
970 void wfind_page(void){
971 Stmt q;
972 const char *zTitle;
973 login_check_credentials();
974 if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; }
975 zTitle = PD("title","*");
976 style_header("Wiki Pages Found");
977 @ <ul>
978 db_prepare(&q,
979 "SELECT substr(tagname, 6, 1000) FROM tag WHERE tagname like 'wiki-%%%q%%'"
980
+4 -2
--- src/xfersetup.c
+++ src/xfersetup.c
@@ -27,11 +27,12 @@
2727
** WEBPAGE: xfersetup
2828
*/
2929
void xfersetup_page(void){
3030
login_check_credentials();
3131
if( !g.perm.Setup ){
32
- login_needed();
32
+ login_needed(0);
33
+ return;
3334
}
3435
3536
style_header("Transfer Setup");
3637
3738
@ <table border="0" cellspacing="20">
@@ -104,11 +105,12 @@
104105
const char *z;
105106
int isSubmit;
106107
107108
login_check_credentials();
108109
if( !g.perm.Setup ){
109
- login_needed();
110
+ login_needed(0);
111
+ return;
110112
}
111113
if( P("setup") ){
112114
cgi_redirect("xfersetup");
113115
}
114116
isSubmit = P("submit")!=0;
115117
--- src/xfersetup.c
+++ src/xfersetup.c
@@ -27,11 +27,12 @@
27 ** WEBPAGE: xfersetup
28 */
29 void xfersetup_page(void){
30 login_check_credentials();
31 if( !g.perm.Setup ){
32 login_needed();
 
33 }
34
35 style_header("Transfer Setup");
36
37 @ <table border="0" cellspacing="20">
@@ -104,11 +105,12 @@
104 const char *z;
105 int isSubmit;
106
107 login_check_credentials();
108 if( !g.perm.Setup ){
109 login_needed();
 
110 }
111 if( P("setup") ){
112 cgi_redirect("xfersetup");
113 }
114 isSubmit = P("submit")!=0;
115
--- src/xfersetup.c
+++ src/xfersetup.c
@@ -27,11 +27,12 @@
27 ** WEBPAGE: xfersetup
28 */
29 void xfersetup_page(void){
30 login_check_credentials();
31 if( !g.perm.Setup ){
32 login_needed(0);
33 return;
34 }
35
36 style_header("Transfer Setup");
37
38 @ <table border="0" cellspacing="20">
@@ -104,11 +105,12 @@
105 const char *z;
106 int isSubmit;
107
108 login_check_credentials();
109 if( !g.perm.Setup ){
110 login_needed(0);
111 return;
112 }
113 if( P("setup") ){
114 cgi_redirect("xfersetup");
115 }
116 isSubmit = P("submit")!=0;
117
+12 -1
--- src/zip.c
+++ src/zip.c
@@ -448,11 +448,11 @@
448448
int nName, nRid;
449449
Blob zip;
450450
char *zKey;
451451
452452
login_check_credentials();
453
- if( !g.perm.Zip ){ login_needed(); return; }
453
+ if( !g.perm.Zip ){ login_needed(g.anon.Zip); return; }
454454
load_control();
455455
zName = mprintf("%s", PD("name",""));
456456
nName = strlen(zName);
457457
zRid = mprintf("%s", PD("uuid","trunk"));
458458
nRid = strlen(zRid);
@@ -472,10 +472,21 @@
472472
}
473473
rid = name_to_typed_rid(nRid?zRid:zName,"ci");
474474
if( rid==0 ){
475475
@ Not found
476476
return;
477
+ }
478
+ if( referred_from_login() ){
479
+ style_header("ZIP Archive Download");
480
+ @ <form action='%R/zip'>
481
+ cgi_query_parameters_to_hidden();
482
+ @ <p>ZIP Archive named <b>%h(zName).zip</b> holding the content
483
+ @ of check-in <b>%h(zRid)</b>:
484
+ @ <input type="submit" value="Download" />
485
+ @ </form>
486
+ style_footer();
487
+ return;
477488
}
478489
if( nRid==0 && nName>10 ) zName[10] = 0;
479490
zKey = db_text(0, "SELECT '/zip/'||uuid||'/%q' FROM blob WHERE rid=%d",zName,rid);
480491
blob_zero(&zip);
481492
if( cache_read(&zip, zKey)==0 ){
482493
--- src/zip.c
+++ src/zip.c
@@ -448,11 +448,11 @@
448 int nName, nRid;
449 Blob zip;
450 char *zKey;
451
452 login_check_credentials();
453 if( !g.perm.Zip ){ login_needed(); return; }
454 load_control();
455 zName = mprintf("%s", PD("name",""));
456 nName = strlen(zName);
457 zRid = mprintf("%s", PD("uuid","trunk"));
458 nRid = strlen(zRid);
@@ -472,10 +472,21 @@
472 }
473 rid = name_to_typed_rid(nRid?zRid:zName,"ci");
474 if( rid==0 ){
475 @ Not found
476 return;
 
 
 
 
 
 
 
 
 
 
 
477 }
478 if( nRid==0 && nName>10 ) zName[10] = 0;
479 zKey = db_text(0, "SELECT '/zip/'||uuid||'/%q' FROM blob WHERE rid=%d",zName,rid);
480 blob_zero(&zip);
481 if( cache_read(&zip, zKey)==0 ){
482
--- src/zip.c
+++ src/zip.c
@@ -448,11 +448,11 @@
448 int nName, nRid;
449 Blob zip;
450 char *zKey;
451
452 login_check_credentials();
453 if( !g.perm.Zip ){ login_needed(g.anon.Zip); return; }
454 load_control();
455 zName = mprintf("%s", PD("name",""));
456 nName = strlen(zName);
457 zRid = mprintf("%s", PD("uuid","trunk"));
458 nRid = strlen(zRid);
@@ -472,10 +472,21 @@
472 }
473 rid = name_to_typed_rid(nRid?zRid:zName,"ci");
474 if( rid==0 ){
475 @ Not found
476 return;
477 }
478 if( referred_from_login() ){
479 style_header("ZIP Archive Download");
480 @ <form action='%R/zip'>
481 cgi_query_parameters_to_hidden();
482 @ <p>ZIP Archive named <b>%h(zName).zip</b> holding the content
483 @ of check-in <b>%h(zRid)</b>:
484 @ <input type="submit" value="Download" />
485 @ </form>
486 style_footer();
487 return;
488 }
489 if( nRid==0 && nName>10 ) zName[10] = 0;
490 zKey = db_text(0, "SELECT '/zip/'||uuid||'/%q' FROM blob WHERE rid=%d",zName,rid);
491 blob_zero(&zip);
492 if( cache_read(&zip, zKey)==0 ){
493

Keyboard Shortcuts

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