Index: src/report.c
==================================================================
--- src/report.c
+++ src/report.c
@@ -873,11 +873,11 @@
   Stmt q;
   char *zErr1 = 0;
   char *zErr2 = 0;
 
   login_check_credentials();
-  if( !g.okRead ){ login_needed(); return; }
+  if( !g.okRdTkt ){ login_needed(); return; }
   rn = atoi(PD("rn","0"));
   if( rn==0 ){
     cgi_redirect("reportlist");
     return;
   }

Index: src/search.c
==================================================================
--- src/search.c
+++ src/search.c
@@ -175,11 +175,11 @@
 ** Testing the search function.
 **
 ** COMMAND: search
 ** %fossil search pattern...
 **
-** Search for timeline entrys matching the pattern.
+** Search for timeline entries matching the pattern.
 */
 void search_cmd(void){
   Search *p;
   Blob pattern;
   int i;

Index: src/skins.c
==================================================================
--- src/skins.c
+++ src/skins.c
@@ -188,14 +188,16 @@
 @ if {[hascap h]} {
 @   html "<a href=''$baseurl/dir''>Files</a> "
 @ }
 @ if {[hascap o]} {
 @   html "<a href=''$baseurl/leaves''>Leaves</a> "
-@   html "<a href=''$baseurl/timeline''>Timeline</a> "
 @   html "<a href=''$baseurl/brlist''>Branches</a> "
 @   html "<a href=''$baseurl/taglist''>Tags</a> "
 @ }
+@ if {[hascap h]} {
+@   html "<a href=''$baseurl/timeline''>Timeline</a> "
+@ }
 @ if {[hascap r]} {
 @   html "<a href=''$baseurl/reportlist''>Tickets</a> "
 @ }
 @ if {[hascap j]} {
 @   html "<a href=''$baseurl/wiki''>Wiki</a> "
@@ -388,14 +390,16 @@
 @ if {[hascap h]} {
 @   html "<a href=''$baseurl/dir''>Files</a> "
 @ }
 @ if {[hascap o]} {
 @   html "<a href=''$baseurl/leaves''>Leaves</a> "
-@   html "<a href=''$baseurl/timeline''>Timeline</a> "
 @   html "<a href=''$baseurl/brlist''>Branches</a> "
 @   html "<a href=''$baseurl/taglist''>Tags</a> "
 @ }
+@ if {[hascap h]} {
+@   html "<a href=''$baseurl/timeline''>Timeline</a> "
+@ }
 @ if {[hascap r]} {
 @   html "<a href=''$baseurl/reportlist''>Tickets</a> "
 @ }
 @ if {[hascap j]} {
 @   html "<a href=''$baseurl/wiki''>Wiki</a> "
@@ -621,14 +625,16 @@
 @ if {[hascap h]} {
 @   html "<li><a href=''$baseurl/dir''>Files</a></li>"
 @ }
 @ if {[hascap o]} {
 @   html "<li><a href=''$baseurl/leaves''>Leaves</a></li>"
-@   html "<li><a href=''$baseurl/timeline''>Timeline</a></li>"
 @   html "<li><a href=''$baseurl/brlist''>Branches</a></li>"
 @   html "<li><a href=''$baseurl/taglist''>Tags</a></li>"
 @ }
+@ if {[hascap h]} {
+@   html "<li><a href=''$baseurl/timeline''>Timeline</a></li>"
+@ }
 @ if {[hascap r]} {
 @   html "<li><a href=''$baseurl/reportlist''>Tickets</a></li>"
 @ }
 @ if {[hascap j]} {
 @   html "<li><a href=''$baseurl/wiki''>Wiki</a></li>"

Index: src/style.c
==================================================================
--- src/style.c
+++ src/style.c
@@ -210,14 +210,16 @@
 @ if {[hascap h]} {
 @   html "<a href='$baseurl/dir'>Files</a> "
 @ }
 @ if {[hascap o]} {
 @   html "<a href='$baseurl/leaves'>Leaves</a> "
-@   html "<a href='$baseurl/timeline'>Timeline</a> "
 @   html "<a href='$baseurl/brlist'>Branches</a> "
 @   html "<a href='$baseurl/taglist'>Tags</a> "
 @ }
+@ if {[hascap h]} {
+@   html "<a href='$baseurl/timeline'>Timeline</a> "
+@ }
 @ if {[hascap r]} {
 @   html "<a href='$baseurl/reportlist'>Tickets</a> "
 @ }
 @ if {[hascap j]} {
 @   html "<a href='$baseurl/wiki'>Wiki</a> "

Index: src/timeline.c
==================================================================
--- src/timeline.c
+++ src/timeline.c
@@ -445,14 +445,20 @@
   const char *zString = P("s");      /* String text search of comment and brief */
   HQuery url;                        /* URL for various branch links */
   int tagid;                         /* Tag ID */
   int tmFlags;                       /* Timeline flags */
 
-  /* To view the timeline, must have permission to read project data.
-  */
+  /* To view the timeline, must have permission to project history.*/
   login_check_credentials();
-  if( !g.okRead ){ login_needed(); return; }
+  if( !g.okHistory ){ login_needed(); return; }
+  
+  /* Prevent them from getting an empty list due to security constraints */
+  if( (p_rid || d_rid) && !g.okRead ){ login_needed(); return; }
+  if( zType[0]=='c' && zType[1]=='i' && !g.okRead){ login_needed(); return; }
+  if( zType[0]=='t' && !g.okRdTkt){ login_needed(); return; }
+  if( zType[0]=='w' && !g.okRdWiki){ login_needed(); return; }
+  
   if( zTagName ){
     tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'", zTagName);
   }else{
     tagid = 0;
   }
@@ -467,10 +473,20 @@
   timeline_temp_table();
   blob_zero(&sql);
   blob_zero(&desc);
   blob_append(&sql, "INSERT OR IGNORE INTO timeline ", -1);
   blob_append(&sql, timeline_query_for_www(), -1);
+  /* limit the types of objects found in history */
+  if( !g.okRead ){
+    blob_appendf(&sql, " AND event.type<>'ci'");
+  }
+  if( !g.okRdTkt ){
+    blob_appendf(&sql, " AND event.type<>'t'");
+  }
+  if( !g.okRdWiki ){
+    blob_appendf(&sql, " AND event.type<>'w'");
+  }
   if( p_rid || d_rid ){
     /* If p= or d= is present, ignore all other parameters other than n= */
     char *zUuid;
     int np, nd;
 
@@ -636,17 +652,17 @@
         free(zDate);
       }else if( tagid==0 ){
         if( zType[0]!='a' ){
           timeline_submenu(&url, "All Types", "y", "all", 0);
         }
-        if( zType[0]!='w' ){
+        if( zType[0]!='w' && g.okRdWiki ){
           timeline_submenu(&url, "Wiki Only", "y", "w", 0);
         }
-        if( zType[0]!='c' ){
+        if( zType[0]!='c' && g.okRead ){
           timeline_submenu(&url, "Checkins Only", "y", "ci", 0);
         }
-        if( zType[0]!='t' ){
+        if( zType[0]!='t' && g.okRdTkt ){
           timeline_submenu(&url, "Tickets Only", "y", "t", 0);
         }
       }
       if( nEntry>20 ){
         timeline_submenu(&url, "20 Events", "n", "20", 0);