Fossil

Check-in [5fcf49f1]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Enhance the webpage_error() routine to show the complete calling environment to authorized users. Also, continuing work on forum.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | forum-v2
Files: files | file ages | folders
SHA3-256: 5fcf49f104496abf290eeaf14c58be6bd4569e25a03b99b2447e434cdc2cf67a
User & Date: drh 2018-07-25 11:25:46
Context
2018-07-25
13:09
Initial implementation of the forum reply screen. check-in: c35fe945 user: drh tags: forum-v2
11:25
Enhance the webpage_error() routine to show the complete calling environment to authorized users. Also, continuing work on forum. check-in: 5fcf49f1 user: drh tags: forum-v2
2018-07-24
23:37
Forum posts appear in the timeline. The /info command displays posts. check-in: 449f06c2 user: drh tags: forum-v2
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/forum.c.

45
46
47
48
49
50
51

52
53
54
55
56
57
58
59
..
61
62
63
64
65
66
67
68












69
70
71
72
73
74
75
...
258
259
260
261
262
263
264
265
266
























267


268
  while( db_step(&q)==SQLITE_ROW ){
    int fpid = db_column_int(&q, 0);
    int fprev = db_column_int(&q, 1);
    int firt = db_column_int(&q, 2);
    const char *zUuid = db_column_text(&q, 3);
    const char *zDate = db_column_text(&q, 4);
    Manifest *pPost = manifest_get(fpid, CFTYPE_FORUM, 0);

    if( i==0 ){
      @ <hr>
    }
    i++;
    @ <p>%d(fpid) %h(zUuid)<br>
    @ By %h(pPost->zUser) on %h(zDate)
    if( fprev ){
      @ edit of %d(fprev) %h(pPost->azParent[0])
................................................................................
    if( firt ){
      @ in reply to %d(firt) %h(pPost->zInReplyTo)
    }
    if( pPost->zThreadTitle ){
      @ <h1>%h(pPost->zThreadTitle)</h1>
    }
    forum_render(pPost->zMimetype, pPost->zWiki);
    if( pPost==0 ) continue;












    manifest_destroy(pPost);
  }
  db_finalize(&q);
}

/*
** WEBPAGE: forumthread
................................................................................
**
** Edit an existing forum message.
** Query parameters:
**
**   name=X        Hash of the post to be editted.  REQUIRED
*/
void forumedit_page(void){
  style_header("Pending");
  @ TBD...
























  style_footer();


}







>
|







 







|
>
>
>
>
>
>
>
>
>
>
>
>







 







|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>

45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
..
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
...
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
  while( db_step(&q)==SQLITE_ROW ){
    int fpid = db_column_int(&q, 0);
    int fprev = db_column_int(&q, 1);
    int firt = db_column_int(&q, 2);
    const char *zUuid = db_column_text(&q, 3);
    const char *zDate = db_column_text(&q, 4);
    Manifest *pPost = manifest_get(fpid, CFTYPE_FORUM, 0);
    if( pPost==0 ) continue;
    if( i>0 ){
      @ <hr>
    }
    i++;
    @ <p>%d(fpid) %h(zUuid)<br>
    @ By %h(pPost->zUser) on %h(zDate)
    if( fprev ){
      @ edit of %d(fprev) %h(pPost->azParent[0])
................................................................................
    if( firt ){
      @ in reply to %d(firt) %h(pPost->zInReplyTo)
    }
    if( pPost->zThreadTitle ){
      @ <h1>%h(pPost->zThreadTitle)</h1>
    }
    forum_render(pPost->zMimetype, pPost->zWiki);
    if( g.perm.WrForum ){
      @ <p><form action="%R/forumedit" method="POST">
      @ <input type="hidden" name="fpid" value="%s(zUuid)">
      @ <input type="submit" name="reply" value="Reply">
      if( g.perm.Admin || fossil_strcmp(pPost->zUser,g.zLogin)==0 ){
        @ <input type="submit" name="edit" value="Edit">
      }
      if( g.perm.ModForum && content_is_private(fpid) ){
        @ <input type="submit" name="approve" value="Approve">
        @ <input type="submit" name="reject" value="Reject">
      }
      @ </form></p>
    }
    manifest_destroy(pPost);
  }
  db_finalize(&q);
}

/*
** WEBPAGE: forumthread
................................................................................
**
** Edit an existing forum message.
** Query parameters:
**
**   name=X        Hash of the post to be editted.  REQUIRED
*/
void forumedit_page(void){
  int fpid;
  Manifest *pPost;

  fpid = symbolic_name_to_rid(PD("fpid",""), "f");
  login_check_credentials();
  if( !g.perm.WrForum ){
    login_needed(g.anon.WrForum);
    return;
  }
  if( fpid<=0 || (pPost = manifest_get(fpid, CFTYPE_FORUM, 0))==0 ){
    webpage_error("Missing or invalid fpid query parameter");
    return;
  }
#if 0
  if( g.perm.ModForum ){
    if( P("approve") ){
    }
    if( P("reject") ){
    }
  }
  if( P("submit") ){
  }
  if( P("edit") ){
  }
  if( P("reply") ){
  }
  style_footer();
#endif
  webpage_error("Not yet implemented");
}

Changes to src/info.c.

976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004


  @ <div class="section">Content</div>
  blob_init(&wiki, pWiki->zWiki, -1);
  wiki_render_by_mimetype(&wiki, pWiki->zMimetype);
  blob_reset(&wiki);
  manifest_destroy(pWiki);
  style_footer();
}

/*
** Show a webpage error message
*/
void webpage_error(const char *zFormat, ...){
  va_list ap;
  const char *z;
  va_start(ap, zFormat);
  z = vmprintf(zFormat, ap);
  va_end(ap);
  style_header("URL Error");
  @ <h1>Error</h1>
  @ <p>%h(z)</p>
  style_footer();
}

/*
** Find an check-in based on query parameter zParam and parse its
** manifest.  Return the number of errors.
*/







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







976
977
978
979
980
981
982















983
984
985
986
987
988
989


  @ <div class="section">Content</div>
  blob_init(&wiki, pWiki->zWiki, -1);
  wiki_render_by_mimetype(&wiki, pWiki->zMimetype);
  blob_reset(&wiki);
  manifest_destroy(pWiki);















  style_footer();
}

/*
** Find an check-in based on query parameter zParam and parse its
** manifest.  Return the number of errors.
*/

Changes to src/style.c.

862
863
864
865
866
867
868

































869
870
871
872
873
874
875
876
877























878
879


880
881
882
883
884
885
886
887
...
893
894
895
896
897
898
899
900
901
902
903
904

















905
906
907
908

909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
  }else{
    etag_check(0,0);
  }
  blob_init(&out, zTxt, -1);
  cgi_set_content(&out);
}



































/*
** WEBPAGE: test_env
**
** Display CGI-variables and other aspects of the run-time
** environment, for debugging and trouble-shooting purposes.
*/
void page_test_env(void){
  char c;























  int i;
  int showAll;


  char zCap[30];
  static const char *const azCgiVars[] = {
    "COMSPEC", "DOCUMENT_ROOT", "GATEWAY_INTERFACE",
    "HTTP_ACCEPT", "HTTP_ACCEPT_CHARSET", "HTTP_ACCEPT_ENCODING",
    "HTTP_ACCEPT_LANGUAGE", "HTTP_AUTHENICATION",
    "HTTP_CONNECTION", "HTTP_HOST",
    "HTTP_IF_NONE_MATCH", "HTTP_IF_MODIFIED_SINCE",
    "HTTP_USER_AGENT", "HTTP_REFERER", "PATH_INFO", "PATH_TRANSLATED",
................................................................................
    "TEMP", "TMP", "FOSSIL_VFS",
    "FOSSIL_FORCE_TICKET_MODERATION", "FOSSIL_FORCE_WIKI_MODERATION",
    "FOSSIL_TCL_PATH", "TH1_DELETE_INTERP", "TH1_ENABLE_DOCS",
    "TH1_ENABLE_HOOKS", "TH1_ENABLE_TCL", "REMOTE_HOST"
  };

  login_check_credentials();
  if( !g.perm.Admin && !g.perm.Setup && !db_get_boolean("test_env_enable",0) ){
    login_needed(0);
    return;
  }
  for(i=0; i<count(azCgiVars); i++) (void)P(azCgiVars[i]);

















  style_header("Environment Test");
  showAll = PB("showall");
  style_submenu_checkbox("showall", "Cookies", 0, 0);
  style_submenu_element("Stats", "%R/stat");


#if !defined(_WIN32)
  @ uid=%d(getuid()), gid=%d(getgid())<br />
#endif
  @ g.zBaseURL = %h(g.zBaseURL)<br />
  @ g.zHttpsURL = %h(g.zHttpsURL)<br />
  @ g.zTop = %h(g.zTop)<br />
  @ g.zPath = %h(g.zPath)<br />
  for(i=0, c='a'; c<='z'; c++){
    if( login_has_capability(&c, 1, 0) ) zCap[i++] = c;
  }
  zCap[i] = 0;
  @ g.userUid = %d(g.userUid)<br />
  @ g.zLogin = %h(g.zLogin)<br />
  @ g.isHuman = %d(g.isHuman)<br />
  if( g.nRequest ){
    @ g.nRequest = %d(g.nRequest)<br />
  }
  if( g.nPendingRequest>1 ){
    @ g.nPendingRequest = %d(g.nPendingRequest)<br />
  }
  @ capabilities = %s(zCap)<br />
  for(i=0, c='a'; c<='z'; c++){
    if( login_has_capability(&c, 1, LOGIN_ANON)
         && !login_has_capability(&c, 1, 0) ) zCap[i++] = c;
  }
  zCap[i] = 0;
  if( i>0 ){
    @ anonymous-adds = %s(zCap)<br />
  }
  @ g.zRepositoryName = %h(g.zRepositoryName)<br />
  @ load_average() = %f(load_average())<br />
  @ cgi_csrf_safe(0) = %d(cgi_csrf_safe(0))<br />
  @ <hr />
  P("HTTP_USER_AGENT");
  cgi_print_all(showAll, 0);
  if( showAll && blob_size(&g.httpHeader)>0 ){
    @ <hr />
    @ <pre>
    @ %h(blob_str(&g.httpHeader))
    @ </pre>
  }
  if( g.perm.Setup ){
    const char *zRedir = P("redirect");
    if( zRedir ) cgi_redirect(zRedir);
  }
  style_footer();
  if( g.perm.Admin && P("err") ) fossil_fatal("%s", P("err"));
}

/*
** WEBPAGE: honeypot
** This page is a honeypot for spiders and bots.
*/
void honeypot_page(void){
  cgi_set_status(403, "Forbidden");
  @ <p>Please enable javascript or log in to see this content</p>
}







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>








|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


>
>
|







 







|
|
<


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
>








<
<
<
<









|
<
<
<
<
|
<
|













<
<
<
<

<

<
<
<
<
<
<
<
<
<
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
...
951
952
953
954
955
956
957
958
959

960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991




992
993
994
995
996
997
998
999
1000
1001




1002

1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016




1017

1018









  }else{
    etag_check(0,0);
  }
  blob_init(&out, zTxt, -1);
  cgi_set_content(&out);
}

/*
** All possible capabilities
*/
static const char allCap[] = 
  "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKL";

/*
** Compute the current login capabilities
*/
static char *find_capabilities(char *zCap){
  int i, j;
  char c;
  for(i=j=0; (c = allCap[j])!=0; j++){
    if( login_has_capability(&c, 1, 0) ) zCap[i++] = c;
  }
  zCap[i] = 0;
  return zCap;
}

/*
** Compute the current login capabilities that were
** contributed by Anonymous
*/
static char *find_anon_capabilities(char *zCap){
  int i, j;
  char c;
  for(i=j=0; (c = allCap[j])!=0; j++){
    if( login_has_capability(&c, 1, LOGIN_ANON)
      && !login_has_capability(&c, 1, 0) ) zCap[i++] = c;
  }
  zCap[i] = 0;
  return zCap;
}

/*
** WEBPAGE: test_env
**
** Display CGI-variables and other aspects of the run-time
** environment, for debugging and trouble-shooting purposes.
*/
void page_test_env(void){
  webpage_error("");
}

/*
** WEBPAGE: honeypot
** This page is a honeypot for spiders and bots.
*/
void honeypot_page(void){
  cgi_set_status(403, "Forbidden");
  @ <p>Please enable javascript or log in to see this content</p>
}

/*
** Webpages that encounter an error due to missing or incorrect
** query parameters can jump to this routine to render an error
** message screen.
**
** For administators, or if the test_env_enable setting is true, then
** details of the request environment are displayed.  Otherwise, just
** the error message is shown.
**
** If zFormat is an empty string, then this is the /test_env page.
*/
void webpage_error(const char *zFormat, ...){
  int i;
  int showAll;
  char *zErr;
  int isAuth = 0;
  char zCap[100];
  static const char *const azCgiVars[] = {
    "COMSPEC", "DOCUMENT_ROOT", "GATEWAY_INTERFACE",
    "HTTP_ACCEPT", "HTTP_ACCEPT_CHARSET", "HTTP_ACCEPT_ENCODING",
    "HTTP_ACCEPT_LANGUAGE", "HTTP_AUTHENICATION",
    "HTTP_CONNECTION", "HTTP_HOST",
    "HTTP_IF_NONE_MATCH", "HTTP_IF_MODIFIED_SINCE",
    "HTTP_USER_AGENT", "HTTP_REFERER", "PATH_INFO", "PATH_TRANSLATED",
................................................................................
    "TEMP", "TMP", "FOSSIL_VFS",
    "FOSSIL_FORCE_TICKET_MODERATION", "FOSSIL_FORCE_WIKI_MODERATION",
    "FOSSIL_TCL_PATH", "TH1_DELETE_INTERP", "TH1_ENABLE_DOCS",
    "TH1_ENABLE_HOOKS", "TH1_ENABLE_TCL", "REMOTE_HOST"
  };

  login_check_credentials();
  if( g.perm.Admin || g.perm.Setup  || db_get_boolean("test_env_enable",0) ){
    isAuth = 1;

  }
  for(i=0; i<count(azCgiVars); i++) (void)P(azCgiVars[i]);
  if( zFormat[0] ){
    va_list ap;
    va_start(ap, zFormat);
    zErr = vmprintf(zFormat, ap);
    va_end(ap);
    style_header("Bad Request");
    @ <h1>/%h(g.zPath): %h(zErr)</h1>
    fossil_free(zErr);
    showAll = 0;
    if( !isAuth ){
      style_footer();
      return;
    }
  }else if( !isAuth ){
    login_needed(0);
    return;
  }else{
    style_header("Environment Test");
    showAll = PB("showall");
    style_submenu_checkbox("showall", "Cookies", 0, 0);
    style_submenu_element("Stats", "%R/stat");
  }

#if !defined(_WIN32)
  @ uid=%d(getuid()), gid=%d(getgid())<br />
#endif
  @ g.zBaseURL = %h(g.zBaseURL)<br />
  @ g.zHttpsURL = %h(g.zHttpsURL)<br />
  @ g.zTop = %h(g.zTop)<br />
  @ g.zPath = %h(g.zPath)<br />




  @ g.userUid = %d(g.userUid)<br />
  @ g.zLogin = %h(g.zLogin)<br />
  @ g.isHuman = %d(g.isHuman)<br />
  if( g.nRequest ){
    @ g.nRequest = %d(g.nRequest)<br />
  }
  if( g.nPendingRequest>1 ){
    @ g.nPendingRequest = %d(g.nPendingRequest)<br />
  }
  @ capabilities = %s(find_capabilities(zCap))<br />




  if( zCap[0] ){

    @ anonymous-adds = %s(find_anon_capabilities(zCap))<br />
  }
  @ g.zRepositoryName = %h(g.zRepositoryName)<br />
  @ load_average() = %f(load_average())<br />
  @ cgi_csrf_safe(0) = %d(cgi_csrf_safe(0))<br />
  @ <hr />
  P("HTTP_USER_AGENT");
  cgi_print_all(showAll, 0);
  if( showAll && blob_size(&g.httpHeader)>0 ){
    @ <hr />
    @ <pre>
    @ %h(blob_str(&g.httpHeader))
    @ </pre>
  }




  style_footer();

}