Fossil SCM

Alternative implementation of timeline security changes - this implementation always shows the timeline link if it is applicable, even if the history capability is disabled.

drh 2009-12-31 19:10 trunk
Commit 9b70675778479f712b0f084b0d9fad9888bf3367
+1 -1
--- src/search.c
+++ src/search.c
@@ -175,11 +175,11 @@
175175
** Testing the search function.
176176
**
177177
** COMMAND: search
178178
** %fossil search pattern...
179179
**
180
-** Search for timeline entrys matching the pattern.
180
+** Search for timeline entries matching the pattern.
181181
*/
182182
void search_cmd(void){
183183
Search *p;
184184
Blob pattern;
185185
int i;
186186
--- src/search.c
+++ src/search.c
@@ -175,11 +175,11 @@
175 ** Testing the search function.
176 **
177 ** COMMAND: search
178 ** %fossil search pattern...
179 **
180 ** Search for timeline entrys matching the pattern.
181 */
182 void search_cmd(void){
183 Search *p;
184 Blob pattern;
185 int i;
186
--- src/search.c
+++ src/search.c
@@ -175,11 +175,11 @@
175 ** Testing the search function.
176 **
177 ** COMMAND: search
178 ** %fossil search pattern...
179 **
180 ** Search for timeline entries matching the pattern.
181 */
182 void search_cmd(void){
183 Search *p;
184 Blob pattern;
185 int i;
186
+12 -6
--- src/skins.c
+++ src/skins.c
@@ -183,16 +183,18 @@
183183
@ }
184184
@ </th1></nobr></div>
185185
@ </div>
186186
@ <div class="mainmenu"><th1>
187187
@ html "<a href=''$baseurl$index_page''>Home</a> "
188
-@ if {[hascap h]} {
188
+@ if {[anycap jor]} {
189
+@ html "<a href='$baseurl/timeline'>Timeline</a> "
190
+@ }
191
+@ if {[hascap oh]} {
189192
@ html "<a href=''$baseurl/dir''>Files</a> "
190193
@ }
191194
@ if {[hascap o]} {
192195
@ html "<a href=''$baseurl/leaves''>Leaves</a> "
193
-@ html "<a href=''$baseurl/timeline''>Timeline</a> "
194196
@ html "<a href=''$baseurl/brlist''>Branches</a> "
195197
@ html "<a href=''$baseurl/taglist''>Tags</a> "
196198
@ }
197199
@ if {[hascap r]} {
198200
@ html "<a href=''$baseurl/reportlist''>Tickets</a> "
@@ -383,16 +385,18 @@
383385
@ }
384386
@ </th1></nobr></div>
385387
@ </div>
386388
@ <div class="mainmenu"><th1>
387389
@ html "<a href=''$baseurl$index_page''>Home</a> "
388
-@ if {[hascap h]} {
390
+@ if {[anycap jor]} {
391
+@ html "<a href='$baseurl/timeline'>Timeline</a> "
392
+@ }
393
+@ if {[hascap oh]} {
389394
@ html "<a href=''$baseurl/dir''>Files</a> "
390395
@ }
391396
@ if {[hascap o]} {
392397
@ html "<a href=''$baseurl/leaves''>Leaves</a> "
393
-@ html "<a href=''$baseurl/timeline''>Timeline</a> "
394398
@ html "<a href=''$baseurl/brlist''>Branches</a> "
395399
@ html "<a href=''$baseurl/taglist''>Tags</a> "
396400
@ }
397401
@ if {[hascap r]} {
398402
@ html "<a href=''$baseurl/reportlist''>Tickets</a> "
@@ -616,16 +620,18 @@
616620
@ }
617621
@ </th1></nobr></div>
618622
@ </div>
619623
@ <div class="mainmenu"><ul><th1>
620624
@ html "<li><a href=''$baseurl$index_page''>Home</a></li>"
621
-@ if {[hascap h]} {
625
+@ if {[anycap jor]} {
626
+@ html "<a href='$baseurl/timeline'>Timeline</a> "
627
+@ }
628
+@ if {[hascap oh]} {
622629
@ html "<li><a href=''$baseurl/dir''>Files</a></li>"
623630
@ }
624631
@ if {[hascap o]} {
625632
@ html "<li><a href=''$baseurl/leaves''>Leaves</a></li>"
626
-@ html "<li><a href=''$baseurl/timeline''>Timeline</a></li>"
627633
@ html "<li><a href=''$baseurl/brlist''>Branches</a></li>"
628634
@ html "<li><a href=''$baseurl/taglist''>Tags</a></li>"
629635
@ }
630636
@ if {[hascap r]} {
631637
@ html "<li><a href=''$baseurl/reportlist''>Tickets</a></li>"
632638
--- src/skins.c
+++ src/skins.c
@@ -183,16 +183,18 @@
183 @ }
184 @ </th1></nobr></div>
185 @ </div>
186 @ <div class="mainmenu"><th1>
187 @ html "<a href=''$baseurl$index_page''>Home</a> "
188 @ if {[hascap h]} {
 
 
 
189 @ html "<a href=''$baseurl/dir''>Files</a> "
190 @ }
191 @ if {[hascap o]} {
192 @ html "<a href=''$baseurl/leaves''>Leaves</a> "
193 @ html "<a href=''$baseurl/timeline''>Timeline</a> "
194 @ html "<a href=''$baseurl/brlist''>Branches</a> "
195 @ html "<a href=''$baseurl/taglist''>Tags</a> "
196 @ }
197 @ if {[hascap r]} {
198 @ html "<a href=''$baseurl/reportlist''>Tickets</a> "
@@ -383,16 +385,18 @@
383 @ }
384 @ </th1></nobr></div>
385 @ </div>
386 @ <div class="mainmenu"><th1>
387 @ html "<a href=''$baseurl$index_page''>Home</a> "
388 @ if {[hascap h]} {
 
 
 
389 @ html "<a href=''$baseurl/dir''>Files</a> "
390 @ }
391 @ if {[hascap o]} {
392 @ html "<a href=''$baseurl/leaves''>Leaves</a> "
393 @ html "<a href=''$baseurl/timeline''>Timeline</a> "
394 @ html "<a href=''$baseurl/brlist''>Branches</a> "
395 @ html "<a href=''$baseurl/taglist''>Tags</a> "
396 @ }
397 @ if {[hascap r]} {
398 @ html "<a href=''$baseurl/reportlist''>Tickets</a> "
@@ -616,16 +620,18 @@
616 @ }
617 @ </th1></nobr></div>
618 @ </div>
619 @ <div class="mainmenu"><ul><th1>
620 @ html "<li><a href=''$baseurl$index_page''>Home</a></li>"
621 @ if {[hascap h]} {
 
 
 
622 @ html "<li><a href=''$baseurl/dir''>Files</a></li>"
623 @ }
624 @ if {[hascap o]} {
625 @ html "<li><a href=''$baseurl/leaves''>Leaves</a></li>"
626 @ html "<li><a href=''$baseurl/timeline''>Timeline</a></li>"
627 @ html "<li><a href=''$baseurl/brlist''>Branches</a></li>"
628 @ html "<li><a href=''$baseurl/taglist''>Tags</a></li>"
629 @ }
630 @ if {[hascap r]} {
631 @ html "<li><a href=''$baseurl/reportlist''>Tickets</a></li>"
632
--- src/skins.c
+++ src/skins.c
@@ -183,16 +183,18 @@
183 @ }
184 @ </th1></nobr></div>
185 @ </div>
186 @ <div class="mainmenu"><th1>
187 @ html "<a href=''$baseurl$index_page''>Home</a> "
188 @ if {[anycap jor]} {
189 @ html "<a href='$baseurl/timeline'>Timeline</a> "
190 @ }
191 @ if {[hascap oh]} {
192 @ html "<a href=''$baseurl/dir''>Files</a> "
193 @ }
194 @ if {[hascap o]} {
195 @ html "<a href=''$baseurl/leaves''>Leaves</a> "
 
196 @ html "<a href=''$baseurl/brlist''>Branches</a> "
197 @ html "<a href=''$baseurl/taglist''>Tags</a> "
198 @ }
199 @ if {[hascap r]} {
200 @ html "<a href=''$baseurl/reportlist''>Tickets</a> "
@@ -383,16 +385,18 @@
385 @ }
386 @ </th1></nobr></div>
387 @ </div>
388 @ <div class="mainmenu"><th1>
389 @ html "<a href=''$baseurl$index_page''>Home</a> "
390 @ if {[anycap jor]} {
391 @ html "<a href='$baseurl/timeline'>Timeline</a> "
392 @ }
393 @ if {[hascap oh]} {
394 @ html "<a href=''$baseurl/dir''>Files</a> "
395 @ }
396 @ if {[hascap o]} {
397 @ html "<a href=''$baseurl/leaves''>Leaves</a> "
 
398 @ html "<a href=''$baseurl/brlist''>Branches</a> "
399 @ html "<a href=''$baseurl/taglist''>Tags</a> "
400 @ }
401 @ if {[hascap r]} {
402 @ html "<a href=''$baseurl/reportlist''>Tickets</a> "
@@ -616,16 +620,18 @@
620 @ }
621 @ </th1></nobr></div>
622 @ </div>
623 @ <div class="mainmenu"><ul><th1>
624 @ html "<li><a href=''$baseurl$index_page''>Home</a></li>"
625 @ if {[anycap jor]} {
626 @ html "<a href='$baseurl/timeline'>Timeline</a> "
627 @ }
628 @ if {[hascap oh]} {
629 @ html "<li><a href=''$baseurl/dir''>Files</a></li>"
630 @ }
631 @ if {[hascap o]} {
632 @ html "<li><a href=''$baseurl/leaves''>Leaves</a></li>"
 
633 @ html "<li><a href=''$baseurl/brlist''>Branches</a></li>"
634 @ html "<li><a href=''$baseurl/taglist''>Tags</a></li>"
635 @ }
636 @ if {[hascap r]} {
637 @ html "<li><a href=''$baseurl/reportlist''>Tickets</a></li>"
638
+4 -2
--- src/style.c
+++ src/style.c
@@ -205,16 +205,18 @@
205205
@ }
206206
@ </th1></nobr></div>
207207
@ </div>
208208
@ <div class="mainmenu"><th1>
209209
@ html "<a href='$baseurl$index_page'>Home</a> "
210
-@ if {[hascap h]} {
210
+@ if {[anycap jor]} {
211
+@ html "<a href='$baseurl/timeline'>Timeline</a> "
212
+@ }
213
+@ if {[hascap oh]} {
211214
@ html "<a href='$baseurl/dir'>Files</a> "
212215
@ }
213216
@ if {[hascap o]} {
214217
@ html "<a href='$baseurl/leaves'>Leaves</a> "
215
-@ html "<a href='$baseurl/timeline'>Timeline</a> "
216218
@ html "<a href='$baseurl/brlist'>Branches</a> "
217219
@ html "<a href='$baseurl/taglist'>Tags</a> "
218220
@ }
219221
@ if {[hascap r]} {
220222
@ html "<a href='$baseurl/reportlist'>Tickets</a> "
221223
--- src/style.c
+++ src/style.c
@@ -205,16 +205,18 @@
205 @ }
206 @ </th1></nobr></div>
207 @ </div>
208 @ <div class="mainmenu"><th1>
209 @ html "<a href='$baseurl$index_page'>Home</a> "
210 @ if {[hascap h]} {
 
 
 
211 @ html "<a href='$baseurl/dir'>Files</a> "
212 @ }
213 @ if {[hascap o]} {
214 @ html "<a href='$baseurl/leaves'>Leaves</a> "
215 @ html "<a href='$baseurl/timeline'>Timeline</a> "
216 @ html "<a href='$baseurl/brlist'>Branches</a> "
217 @ html "<a href='$baseurl/taglist'>Tags</a> "
218 @ }
219 @ if {[hascap r]} {
220 @ html "<a href='$baseurl/reportlist'>Tickets</a> "
221
--- src/style.c
+++ src/style.c
@@ -205,16 +205,18 @@
205 @ }
206 @ </th1></nobr></div>
207 @ </div>
208 @ <div class="mainmenu"><th1>
209 @ html "<a href='$baseurl$index_page'>Home</a> "
210 @ if {[anycap jor]} {
211 @ html "<a href='$baseurl/timeline'>Timeline</a> "
212 @ }
213 @ if {[hascap oh]} {
214 @ html "<a href='$baseurl/dir'>Files</a> "
215 @ }
216 @ if {[hascap o]} {
217 @ html "<a href='$baseurl/leaves'>Leaves</a> "
 
218 @ html "<a href='$baseurl/brlist'>Branches</a> "
219 @ html "<a href='$baseurl/taglist'>Tags</a> "
220 @ }
221 @ if {[hascap r]} {
222 @ html "<a href='$baseurl/reportlist'>Tickets</a> "
223
+29 -1
--- src/th_main.c
+++ src/th_main.c
@@ -209,11 +209,38 @@
209209
}
210210
rc = login_has_capability((char*)argv[1],argl[1]);
211211
if( g.thTrace ){
212212
Th_Trace("[hascap %.*h] => %d<br />\n", argl[1], argv[1], rc);
213213
}
214
- Th_SetResultInt(interp, login_has_capability((char*)argv[1],argl[1]));
214
+ Th_SetResultInt(interp, rc);
215
+ return TH_OK;
216
+}
217
+
218
+/*
219
+** TH command: anycap STRING
220
+**
221
+** Return true if the user has any one of the capabilities listed in STRING.
222
+*/
223
+static int anycapCmd(
224
+ Th_Interp *interp,
225
+ void *p,
226
+ int argc,
227
+ const char **argv,
228
+ int *argl
229
+){
230
+ int rc = 0;
231
+ int i;
232
+ if( argc!=2 ){
233
+ return Th_WrongNumArgs(interp, "anycap STRING");
234
+ }
235
+ for(i=0; rc==0 && i<argl[1]; i++){
236
+ rc = login_has_capability((char*)&argv[1][i],1);
237
+ }
238
+ if( g.thTrace ){
239
+ Th_Trace("[hascap %.*h] => %d<br />\n", argl[1], argv[1], rc);
240
+ }
241
+ Th_SetResultInt(interp, rc);
215242
return TH_OK;
216243
}
217244
218245
/*
219246
** TH1 command: combobox NAME TEXT-LIST NUMLINES
@@ -318,10 +345,11 @@
318345
static struct _Command {
319346
const char *zName;
320347
Th_CommandProc xProc;
321348
void *pContext;
322349
} aCommand[] = {
350
+ {"anycap", anycapCmd, 0},
323351
{"combobox", comboboxCmd, 0},
324352
{"enable_output", enableOutputCmd, 0},
325353
{"linecount", linecntCmd, 0},
326354
{"hascap", hascapCmd, 0},
327355
{"htmlize", htmlizeCmd, 0},
328356
--- src/th_main.c
+++ src/th_main.c
@@ -209,11 +209,38 @@
209 }
210 rc = login_has_capability((char*)argv[1],argl[1]);
211 if( g.thTrace ){
212 Th_Trace("[hascap %.*h] => %d<br />\n", argl[1], argv[1], rc);
213 }
214 Th_SetResultInt(interp, login_has_capability((char*)argv[1],argl[1]));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
215 return TH_OK;
216 }
217
218 /*
219 ** TH1 command: combobox NAME TEXT-LIST NUMLINES
@@ -318,10 +345,11 @@
318 static struct _Command {
319 const char *zName;
320 Th_CommandProc xProc;
321 void *pContext;
322 } aCommand[] = {
 
323 {"combobox", comboboxCmd, 0},
324 {"enable_output", enableOutputCmd, 0},
325 {"linecount", linecntCmd, 0},
326 {"hascap", hascapCmd, 0},
327 {"htmlize", htmlizeCmd, 0},
328
--- src/th_main.c
+++ src/th_main.c
@@ -209,11 +209,38 @@
209 }
210 rc = login_has_capability((char*)argv[1],argl[1]);
211 if( g.thTrace ){
212 Th_Trace("[hascap %.*h] => %d<br />\n", argl[1], argv[1], rc);
213 }
214 Th_SetResultInt(interp, rc);
215 return TH_OK;
216 }
217
218 /*
219 ** TH command: anycap STRING
220 **
221 ** Return true if the user has any one of the capabilities listed in STRING.
222 */
223 static int anycapCmd(
224 Th_Interp *interp,
225 void *p,
226 int argc,
227 const char **argv,
228 int *argl
229 ){
230 int rc = 0;
231 int i;
232 if( argc!=2 ){
233 return Th_WrongNumArgs(interp, "anycap STRING");
234 }
235 for(i=0; rc==0 && i<argl[1]; i++){
236 rc = login_has_capability((char*)&argv[1][i],1);
237 }
238 if( g.thTrace ){
239 Th_Trace("[hascap %.*h] => %d<br />\n", argl[1], argv[1], rc);
240 }
241 Th_SetResultInt(interp, rc);
242 return TH_OK;
243 }
244
245 /*
246 ** TH1 command: combobox NAME TEXT-LIST NUMLINES
@@ -318,10 +345,11 @@
345 static struct _Command {
346 const char *zName;
347 Th_CommandProc xProc;
348 void *pContext;
349 } aCommand[] = {
350 {"anycap", anycapCmd, 0},
351 {"combobox", comboboxCmd, 0},
352 {"enable_output", enableOutputCmd, 0},
353 {"linecount", linecntCmd, 0},
354 {"hascap", hascapCmd, 0},
355 {"htmlize", htmlizeCmd, 0},
356
+38 -13
--- src/timeline.c
+++ src/timeline.c
@@ -440,20 +440,20 @@
440440
const char *zType = PD("y","all"); /* Type of events. All if NULL */
441441
const char *zAfter = P("a"); /* Events after this time */
442442
const char *zBefore = P("b"); /* Events before this time */
443443
const char *zCirca = P("c"); /* Events near this time */
444444
const char *zTagName = P("t"); /* Show events with this tag */
445
- const char *zString = P("s"); /* String text search of comment and brief */
445
+ const char *zSearch = P("s"); /* Search string */
446446
HQuery url; /* URL for various branch links */
447447
int tagid; /* Tag ID */
448448
int tmFlags; /* Timeline flags */
449449
450450
/* To view the timeline, must have permission to read project data.
451451
*/
452452
login_check_credentials();
453
- if( !g.okRead ){ login_needed(); return; }
454
- if( zTagName ){
453
+ if( !g.okRead && !g.okRdTkt && !g.okRdWiki ){ login_needed(); return; }
454
+ if( zTagName && g.okRead ){
455455
tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'", zTagName);
456456
}else{
457457
tagid = 0;
458458
}
459459
if( zType[0]=='a' ){
@@ -467,11 +467,11 @@
467467
timeline_temp_table();
468468
blob_zero(&sql);
469469
blob_zero(&desc);
470470
blob_append(&sql, "INSERT OR IGNORE INTO timeline ", -1);
471471
blob_append(&sql, timeline_query_for_www(), -1);
472
- if( p_rid || d_rid ){
472
+ if( (p_rid || d_rid) && g.okRead ){
473473
/* If p= or d= is present, ignore all other parameters other than n= */
474474
char *zUuid;
475475
int np, nd;
476476
477477
if( p_rid && d_rid ){
@@ -530,12 +530,36 @@
530530
zType = "ci";
531531
url_add_parameter(&url, "t", zTagName);
532532
blob_appendf(&sql, " AND EXISTS (SELECT 1 FROM tagxref WHERE tagid=%d"
533533
" AND tagtype>0 AND rid=blob.rid)",
534534
tagid);
535
- }
536
- if( zType[0]!='a' ){
535
+ }
536
+ if( (zType[0]=='w' && !g.okRdWiki)
537
+ || (zType[0]=='t' && !g.okRdTkt)
538
+ || (zType[0]=='c' && !g.okRead)
539
+ ){
540
+ zType = "all";
541
+ }
542
+ if( zType[0]=='a' ){
543
+ if( !g.okRead || !g.okRdWiki || !g.okRdTkt ){
544
+ char cSep = '(';
545
+ blob_appendf(&sql, " AND event.type IN ");
546
+ if( g.okRead ){
547
+ blob_appendf(&sql, "%c'ci'", cSep);
548
+ cSep = ',';
549
+ }
550
+ if( g.okRdWiki ){
551
+ blob_appendf(&sql, "%c'w'", cSep);
552
+ cSep = ',';
553
+ }
554
+ if( g.okRdTkt ){
555
+ blob_appendf(&sql, "%c't'", cSep);
556
+ cSep = ',';
557
+ }
558
+ blob_appendf(&sql, ")");
559
+ }
560
+ }else{ /* zType!="all" */
537561
blob_appendf(&sql, " AND event.type=%Q", zType);
538562
url_add_parameter(&url, "y", zType);
539563
if( zType[0]=='c' ){
540564
zEType = "checkin";
541565
}else if( zType[0]=='w' ){
@@ -546,14 +570,15 @@
546570
}
547571
if( zUser ){
548572
blob_appendf(&sql, " AND event.user=%Q", zUser);
549573
url_add_parameter(&url, "u", zUser);
550574
}
551
- if ( zString ){
552
- blob_appendf(&sql, " AND (event.comment LIKE '%%%q%%' OR event.brief LIKE '%%%q%%')",
553
- zString, zString);
554
- url_add_parameter(&url, "s", zString);
575
+ if ( zSearch ){
576
+ blob_appendf(&sql,
577
+ " AND (event.comment LIKE '%%%q%%' OR event.brief LIKE '%%%q%%')",
578
+ zSearch, zSearch);
579
+ url_add_parameter(&url, "s", zSearch);
555580
}
556581
if( zAfter ){
557582
while( isspace(zAfter[0]) ){ zAfter++; }
558583
if( zAfter[0] ){
559584
blob_appendf(&sql,
@@ -636,17 +661,17 @@
636661
free(zDate);
637662
}else if( tagid==0 ){
638663
if( zType[0]!='a' ){
639664
timeline_submenu(&url, "All Types", "y", "all", 0);
640665
}
641
- if( zType[0]!='w' ){
666
+ if( zType[0]!='w' && g.okRdWiki ){
642667
timeline_submenu(&url, "Wiki Only", "y", "w", 0);
643668
}
644
- if( zType[0]!='c' ){
669
+ if( zType[0]!='c' && g.okRead ){
645670
timeline_submenu(&url, "Checkins Only", "y", "ci", 0);
646671
}
647
- if( zType[0]!='t' ){
672
+ if( zType[0]!='t' && g.okRdTkt ){
648673
timeline_submenu(&url, "Tickets Only", "y", "t", 0);
649674
}
650675
}
651676
if( nEntry>20 ){
652677
timeline_submenu(&url, "20 Events", "n", "20", 0);
653678
--- src/timeline.c
+++ src/timeline.c
@@ -440,20 +440,20 @@
440 const char *zType = PD("y","all"); /* Type of events. All if NULL */
441 const char *zAfter = P("a"); /* Events after this time */
442 const char *zBefore = P("b"); /* Events before this time */
443 const char *zCirca = P("c"); /* Events near this time */
444 const char *zTagName = P("t"); /* Show events with this tag */
445 const char *zString = P("s"); /* String text search of comment and brief */
446 HQuery url; /* URL for various branch links */
447 int tagid; /* Tag ID */
448 int tmFlags; /* Timeline flags */
449
450 /* To view the timeline, must have permission to read project data.
451 */
452 login_check_credentials();
453 if( !g.okRead ){ login_needed(); return; }
454 if( zTagName ){
455 tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'", zTagName);
456 }else{
457 tagid = 0;
458 }
459 if( zType[0]=='a' ){
@@ -467,11 +467,11 @@
467 timeline_temp_table();
468 blob_zero(&sql);
469 blob_zero(&desc);
470 blob_append(&sql, "INSERT OR IGNORE INTO timeline ", -1);
471 blob_append(&sql, timeline_query_for_www(), -1);
472 if( p_rid || d_rid ){
473 /* If p= or d= is present, ignore all other parameters other than n= */
474 char *zUuid;
475 int np, nd;
476
477 if( p_rid && d_rid ){
@@ -530,12 +530,36 @@
530 zType = "ci";
531 url_add_parameter(&url, "t", zTagName);
532 blob_appendf(&sql, " AND EXISTS (SELECT 1 FROM tagxref WHERE tagid=%d"
533 " AND tagtype>0 AND rid=blob.rid)",
534 tagid);
535 }
536 if( zType[0]!='a' ){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
537 blob_appendf(&sql, " AND event.type=%Q", zType);
538 url_add_parameter(&url, "y", zType);
539 if( zType[0]=='c' ){
540 zEType = "checkin";
541 }else if( zType[0]=='w' ){
@@ -546,14 +570,15 @@
546 }
547 if( zUser ){
548 blob_appendf(&sql, " AND event.user=%Q", zUser);
549 url_add_parameter(&url, "u", zUser);
550 }
551 if ( zString ){
552 blob_appendf(&sql, " AND (event.comment LIKE '%%%q%%' OR event.brief LIKE '%%%q%%')",
553 zString, zString);
554 url_add_parameter(&url, "s", zString);
 
555 }
556 if( zAfter ){
557 while( isspace(zAfter[0]) ){ zAfter++; }
558 if( zAfter[0] ){
559 blob_appendf(&sql,
@@ -636,17 +661,17 @@
636 free(zDate);
637 }else if( tagid==0 ){
638 if( zType[0]!='a' ){
639 timeline_submenu(&url, "All Types", "y", "all", 0);
640 }
641 if( zType[0]!='w' ){
642 timeline_submenu(&url, "Wiki Only", "y", "w", 0);
643 }
644 if( zType[0]!='c' ){
645 timeline_submenu(&url, "Checkins Only", "y", "ci", 0);
646 }
647 if( zType[0]!='t' ){
648 timeline_submenu(&url, "Tickets Only", "y", "t", 0);
649 }
650 }
651 if( nEntry>20 ){
652 timeline_submenu(&url, "20 Events", "n", "20", 0);
653
--- src/timeline.c
+++ src/timeline.c
@@ -440,20 +440,20 @@
440 const char *zType = PD("y","all"); /* Type of events. All if NULL */
441 const char *zAfter = P("a"); /* Events after this time */
442 const char *zBefore = P("b"); /* Events before this time */
443 const char *zCirca = P("c"); /* Events near this time */
444 const char *zTagName = P("t"); /* Show events with this tag */
445 const char *zSearch = P("s"); /* Search string */
446 HQuery url; /* URL for various branch links */
447 int tagid; /* Tag ID */
448 int tmFlags; /* Timeline flags */
449
450 /* To view the timeline, must have permission to read project data.
451 */
452 login_check_credentials();
453 if( !g.okRead && !g.okRdTkt && !g.okRdWiki ){ login_needed(); return; }
454 if( zTagName && g.okRead ){
455 tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'", zTagName);
456 }else{
457 tagid = 0;
458 }
459 if( zType[0]=='a' ){
@@ -467,11 +467,11 @@
467 timeline_temp_table();
468 blob_zero(&sql);
469 blob_zero(&desc);
470 blob_append(&sql, "INSERT OR IGNORE INTO timeline ", -1);
471 blob_append(&sql, timeline_query_for_www(), -1);
472 if( (p_rid || d_rid) && g.okRead ){
473 /* If p= or d= is present, ignore all other parameters other than n= */
474 char *zUuid;
475 int np, nd;
476
477 if( p_rid && d_rid ){
@@ -530,12 +530,36 @@
530 zType = "ci";
531 url_add_parameter(&url, "t", zTagName);
532 blob_appendf(&sql, " AND EXISTS (SELECT 1 FROM tagxref WHERE tagid=%d"
533 " AND tagtype>0 AND rid=blob.rid)",
534 tagid);
535 }
536 if( (zType[0]=='w' && !g.okRdWiki)
537 || (zType[0]=='t' && !g.okRdTkt)
538 || (zType[0]=='c' && !g.okRead)
539 ){
540 zType = "all";
541 }
542 if( zType[0]=='a' ){
543 if( !g.okRead || !g.okRdWiki || !g.okRdTkt ){
544 char cSep = '(';
545 blob_appendf(&sql, " AND event.type IN ");
546 if( g.okRead ){
547 blob_appendf(&sql, "%c'ci'", cSep);
548 cSep = ',';
549 }
550 if( g.okRdWiki ){
551 blob_appendf(&sql, "%c'w'", cSep);
552 cSep = ',';
553 }
554 if( g.okRdTkt ){
555 blob_appendf(&sql, "%c't'", cSep);
556 cSep = ',';
557 }
558 blob_appendf(&sql, ")");
559 }
560 }else{ /* zType!="all" */
561 blob_appendf(&sql, " AND event.type=%Q", zType);
562 url_add_parameter(&url, "y", zType);
563 if( zType[0]=='c' ){
564 zEType = "checkin";
565 }else if( zType[0]=='w' ){
@@ -546,14 +570,15 @@
570 }
571 if( zUser ){
572 blob_appendf(&sql, " AND event.user=%Q", zUser);
573 url_add_parameter(&url, "u", zUser);
574 }
575 if ( zSearch ){
576 blob_appendf(&sql,
577 " AND (event.comment LIKE '%%%q%%' OR event.brief LIKE '%%%q%%')",
578 zSearch, zSearch);
579 url_add_parameter(&url, "s", zSearch);
580 }
581 if( zAfter ){
582 while( isspace(zAfter[0]) ){ zAfter++; }
583 if( zAfter[0] ){
584 blob_appendf(&sql,
@@ -636,17 +661,17 @@
661 free(zDate);
662 }else if( tagid==0 ){
663 if( zType[0]!='a' ){
664 timeline_submenu(&url, "All Types", "y", "all", 0);
665 }
666 if( zType[0]!='w' && g.okRdWiki ){
667 timeline_submenu(&url, "Wiki Only", "y", "w", 0);
668 }
669 if( zType[0]!='c' && g.okRead ){
670 timeline_submenu(&url, "Checkins Only", "y", "ci", 0);
671 }
672 if( zType[0]!='t' && g.okRdTkt ){
673 timeline_submenu(&url, "Tickets Only", "y", "t", 0);
674 }
675 }
676 if( nEntry>20 ){
677 timeline_submenu(&url, "20 Events", "n", "20", 0);
678

Keyboard Shortcuts

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