Fossil SCM

Allow /wikiedit's page-list-fetch operation to silently skip over mysteriously missing (shunned but not yet rebuilt?) wiki pages, to resolve an issue on the core fossil site where such a missing/invisible page named 'Security Desk Technician' is causing /wikiedit to fail to load.

stephan 2020-08-20 20:05 trunk
Commit 37409e7dbeddf00cca9ba8c1640b635c4d01d549df95ddae7ccf66237aee71a7
1 file changed +34 -11
+34 -11
--- src/wiki.c
+++ src/wiki.c
@@ -725,12 +725,24 @@
725725
** Loads the given wiki page, sets the response type to
726726
** application/json, and emits it as a JSON object. If zPageName is a
727727
** sandbox page then a "fake" object is emitted, as the wikiajax API
728728
** does not permit saving the sandbox.
729729
**
730
-** Returns true on success, false on error, and on error it
731
-** queues up a JSON-format error response.
730
+** If includeLeadingComma is true then a comma will be emitted
731
+** preceeding the object. This parameter is a bit of a hack to allow
732
+** wiki page list generation to recover from an unusual (so far unique
733
+** to one repo) error mode.
734
+**
735
+** Returns true on success, false on error. Its behaviour on error
736
+** depends on the 4th argument: if it's true, this function simply
737
+** returns false, else it queues up a JSON response and returns false.
738
+** The intention of this flag is to avoid a weird corner case seen, so
739
+** far, only on the main fossil repo (not clones of it) in which
740
+** loading fails for a page named "Security Desk Technician". The
741
+** hypothesis is that that page was once shunned on the core repo, but
742
+** a reference to it still exists in the tables from which we pull the
743
+** wiki list.
732744
**
733745
** Output JSON format:
734746
**
735747
** { name: "page name",
736748
** type: "normal" | "tag" | "checkin" | "branch" | "sandbox",
@@ -743,18 +755,23 @@
743755
** }
744756
**
745757
** If includeContent is false then the content member is elided.
746758
*/
747759
static int wiki_ajax_emit_page_object(const char *zPageName,
748
- int includeContent){
760
+ int includeContent,
761
+ int includeLeadingComma,
762
+ int ignoreLoadError){
749763
Manifest * pWiki = 0;
750764
char * zUuid;
751765
752766
if( is_sandbox(zPageName) ){
753767
char * zMimetype =
754768
db_get("sandbox-mimetype","text/x-fossil-wiki");
755769
char * zBody = db_get("sandbox","");
770
+ if(includeLeadingComma){
771
+ CX(",");
772
+ }
756773
CX("{\"name\": %!j, \"type\": \"sandbox\", "
757774
"\"mimetype\": %!j, \"version\": null, \"parent\": null",
758775
zPageName, zMimetype);
759776
if(includeContent){
760777
CX(", \"content\": %!j",
@@ -763,14 +780,19 @@
763780
CX("}");
764781
fossil_free(zMimetype);
765782
fossil_free(zBody);
766783
return 1;
767784
}else if( !wiki_fetch_by_name(zPageName, 0, 0, &pWiki) ){
768
- ajax_route_error(404, "Wiki page could not be loaded: %s",
769
- zPageName);
785
+ if(ignoreLoadError!=0){
786
+ ajax_route_error(404, "Wiki page could not be loaded: %s",
787
+ zPageName);
788
+ }
770789
return 0;
771790
}else{
791
+ if(includeLeadingComma){
792
+ CX(",");
793
+ }
772794
zUuid = rid_to_uuid(pWiki->rid);
773795
CX("{\"name\": %!j, \"type\": %!j, "
774796
"\"version\": %!j, "
775797
"\"mimetype\": %!j, ",
776798
pWiki->zWikiTitle,
@@ -853,11 +875,11 @@
853875
}
854876
blob_init(&content, zContent ? zContent : "", -1);
855877
cgi_set_content_type("application/json");
856878
db_begin_transaction();
857879
wiki_cmd_commit(zPageName, parentRid, &content, zMimetype, 0);
858
- rollback = wiki_ajax_emit_page_object(zPageName, 1) ? 0 : 1;
880
+ rollback = wiki_ajax_emit_page_object(zPageName, 1, 0, 0) ? 0 : 1;
859881
db_end_transaction(rollback);
860882
}
861883
862884
/*
863885
** Ajax route handler for /wikiajax/fetch.
@@ -876,11 +898,11 @@
876898
if( zPageName==0 || zPageName[0]==0 ){
877899
ajax_route_error(400,"Missing page name.");
878900
return;
879901
}
880902
cgi_set_content_type("application/json");
881
- wiki_ajax_emit_page_object(zPageName, 1);
903
+ wiki_ajax_emit_page_object(zPageName, 1, 0, 0);
882904
}
883905
884906
/*
885907
** Ajax route handler for /wikiajax/diff.
886908
**
@@ -984,17 +1006,18 @@
9841006
" UNION SELECT 'Sandbox' AS name"
9851007
" ORDER BY name COLLATE NOCASE");
9861008
CX("[");
9871009
while( SQLITE_ROW==db_step(&q) ){
9881010
char const * zName = db_column_text(&q,0);
989
- if(n++){
990
- CX(",");
991
- }
9921011
if(verbose==0){
1012
+ if(n++){
1013
+ CX(",");
1014
+ }
9931015
CX("%!j", zName);
9941016
}else{
995
- wiki_ajax_emit_page_object(zName, includeContent);
1017
+ wiki_ajax_emit_page_object(zName, includeContent,
1018
+ n++>0, 1);
9961019
}
9971020
}
9981021
CX("]");
9991022
db_finalize(&q);
10001023
db_end_transaction(0);
10011024
--- src/wiki.c
+++ src/wiki.c
@@ -725,12 +725,24 @@
725 ** Loads the given wiki page, sets the response type to
726 ** application/json, and emits it as a JSON object. If zPageName is a
727 ** sandbox page then a "fake" object is emitted, as the wikiajax API
728 ** does not permit saving the sandbox.
729 **
730 ** Returns true on success, false on error, and on error it
731 ** queues up a JSON-format error response.
 
 
 
 
 
 
 
 
 
 
 
 
732 **
733 ** Output JSON format:
734 **
735 ** { name: "page name",
736 ** type: "normal" | "tag" | "checkin" | "branch" | "sandbox",
@@ -743,18 +755,23 @@
743 ** }
744 **
745 ** If includeContent is false then the content member is elided.
746 */
747 static int wiki_ajax_emit_page_object(const char *zPageName,
748 int includeContent){
 
 
749 Manifest * pWiki = 0;
750 char * zUuid;
751
752 if( is_sandbox(zPageName) ){
753 char * zMimetype =
754 db_get("sandbox-mimetype","text/x-fossil-wiki");
755 char * zBody = db_get("sandbox","");
 
 
 
756 CX("{\"name\": %!j, \"type\": \"sandbox\", "
757 "\"mimetype\": %!j, \"version\": null, \"parent\": null",
758 zPageName, zMimetype);
759 if(includeContent){
760 CX(", \"content\": %!j",
@@ -763,14 +780,19 @@
763 CX("}");
764 fossil_free(zMimetype);
765 fossil_free(zBody);
766 return 1;
767 }else if( !wiki_fetch_by_name(zPageName, 0, 0, &pWiki) ){
768 ajax_route_error(404, "Wiki page could not be loaded: %s",
769 zPageName);
 
 
770 return 0;
771 }else{
 
 
 
772 zUuid = rid_to_uuid(pWiki->rid);
773 CX("{\"name\": %!j, \"type\": %!j, "
774 "\"version\": %!j, "
775 "\"mimetype\": %!j, ",
776 pWiki->zWikiTitle,
@@ -853,11 +875,11 @@
853 }
854 blob_init(&content, zContent ? zContent : "", -1);
855 cgi_set_content_type("application/json");
856 db_begin_transaction();
857 wiki_cmd_commit(zPageName, parentRid, &content, zMimetype, 0);
858 rollback = wiki_ajax_emit_page_object(zPageName, 1) ? 0 : 1;
859 db_end_transaction(rollback);
860 }
861
862 /*
863 ** Ajax route handler for /wikiajax/fetch.
@@ -876,11 +898,11 @@
876 if( zPageName==0 || zPageName[0]==0 ){
877 ajax_route_error(400,"Missing page name.");
878 return;
879 }
880 cgi_set_content_type("application/json");
881 wiki_ajax_emit_page_object(zPageName, 1);
882 }
883
884 /*
885 ** Ajax route handler for /wikiajax/diff.
886 **
@@ -984,17 +1006,18 @@
984 " UNION SELECT 'Sandbox' AS name"
985 " ORDER BY name COLLATE NOCASE");
986 CX("[");
987 while( SQLITE_ROW==db_step(&q) ){
988 char const * zName = db_column_text(&q,0);
989 if(n++){
990 CX(",");
991 }
992 if(verbose==0){
 
 
 
993 CX("%!j", zName);
994 }else{
995 wiki_ajax_emit_page_object(zName, includeContent);
 
996 }
997 }
998 CX("]");
999 db_finalize(&q);
1000 db_end_transaction(0);
1001
--- src/wiki.c
+++ src/wiki.c
@@ -725,12 +725,24 @@
725 ** Loads the given wiki page, sets the response type to
726 ** application/json, and emits it as a JSON object. If zPageName is a
727 ** sandbox page then a "fake" object is emitted, as the wikiajax API
728 ** does not permit saving the sandbox.
729 **
730 ** If includeLeadingComma is true then a comma will be emitted
731 ** preceeding the object. This parameter is a bit of a hack to allow
732 ** wiki page list generation to recover from an unusual (so far unique
733 ** to one repo) error mode.
734 **
735 ** Returns true on success, false on error. Its behaviour on error
736 ** depends on the 4th argument: if it's true, this function simply
737 ** returns false, else it queues up a JSON response and returns false.
738 ** The intention of this flag is to avoid a weird corner case seen, so
739 ** far, only on the main fossil repo (not clones of it) in which
740 ** loading fails for a page named "Security Desk Technician". The
741 ** hypothesis is that that page was once shunned on the core repo, but
742 ** a reference to it still exists in the tables from which we pull the
743 ** wiki list.
744 **
745 ** Output JSON format:
746 **
747 ** { name: "page name",
748 ** type: "normal" | "tag" | "checkin" | "branch" | "sandbox",
@@ -743,18 +755,23 @@
755 ** }
756 **
757 ** If includeContent is false then the content member is elided.
758 */
759 static int wiki_ajax_emit_page_object(const char *zPageName,
760 int includeContent,
761 int includeLeadingComma,
762 int ignoreLoadError){
763 Manifest * pWiki = 0;
764 char * zUuid;
765
766 if( is_sandbox(zPageName) ){
767 char * zMimetype =
768 db_get("sandbox-mimetype","text/x-fossil-wiki");
769 char * zBody = db_get("sandbox","");
770 if(includeLeadingComma){
771 CX(",");
772 }
773 CX("{\"name\": %!j, \"type\": \"sandbox\", "
774 "\"mimetype\": %!j, \"version\": null, \"parent\": null",
775 zPageName, zMimetype);
776 if(includeContent){
777 CX(", \"content\": %!j",
@@ -763,14 +780,19 @@
780 CX("}");
781 fossil_free(zMimetype);
782 fossil_free(zBody);
783 return 1;
784 }else if( !wiki_fetch_by_name(zPageName, 0, 0, &pWiki) ){
785 if(ignoreLoadError!=0){
786 ajax_route_error(404, "Wiki page could not be loaded: %s",
787 zPageName);
788 }
789 return 0;
790 }else{
791 if(includeLeadingComma){
792 CX(",");
793 }
794 zUuid = rid_to_uuid(pWiki->rid);
795 CX("{\"name\": %!j, \"type\": %!j, "
796 "\"version\": %!j, "
797 "\"mimetype\": %!j, ",
798 pWiki->zWikiTitle,
@@ -853,11 +875,11 @@
875 }
876 blob_init(&content, zContent ? zContent : "", -1);
877 cgi_set_content_type("application/json");
878 db_begin_transaction();
879 wiki_cmd_commit(zPageName, parentRid, &content, zMimetype, 0);
880 rollback = wiki_ajax_emit_page_object(zPageName, 1, 0, 0) ? 0 : 1;
881 db_end_transaction(rollback);
882 }
883
884 /*
885 ** Ajax route handler for /wikiajax/fetch.
@@ -876,11 +898,11 @@
898 if( zPageName==0 || zPageName[0]==0 ){
899 ajax_route_error(400,"Missing page name.");
900 return;
901 }
902 cgi_set_content_type("application/json");
903 wiki_ajax_emit_page_object(zPageName, 1, 0, 0);
904 }
905
906 /*
907 ** Ajax route handler for /wikiajax/diff.
908 **
@@ -984,17 +1006,18 @@
1006 " UNION SELECT 'Sandbox' AS name"
1007 " ORDER BY name COLLATE NOCASE");
1008 CX("[");
1009 while( SQLITE_ROW==db_step(&q) ){
1010 char const * zName = db_column_text(&q,0);
 
 
 
1011 if(verbose==0){
1012 if(n++){
1013 CX(",");
1014 }
1015 CX("%!j", zName);
1016 }else{
1017 wiki_ajax_emit_page_object(zName, includeContent,
1018 n++>0, 1);
1019 }
1020 }
1021 CX("]");
1022 db_finalize(&q);
1023 db_end_transaction(0);
1024

Keyboard Shortcuts

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