Fossil SCM
(json wiki get) now supports returning the page metadata without the content. Fixed an arg-forwarding bug in json_find_option_cstr() which caused long-form args to be ignored.
Commit
913e0b6628bff13afd18fdc1a93f73c0139c9e01
Parent
8718b3c6ab2f3f8…
2 files changed
+4
-1
+46
-30
+4
-1
| --- src/json.c | ||
| +++ src/json.c | ||
| @@ -581,14 +581,17 @@ | ||
| 581 | 581 | rc = json_command_arg((unsigned char)argPos); |
| 582 | 582 | } |
| 583 | 583 | return rc; |
| 584 | 584 | } |
| 585 | 585 | |
| 586 | +/* | |
| 587 | +** Short-hand form of json_find_option_cstr(zKey,zCLILong,zCLIShort,-1). | |
| 588 | +*/ | |
| 586 | 589 | char const * json_find_option_cstr(char const * zKey, |
| 587 | 590 | char const * zCLILong, |
| 588 | 591 | char const * zCLIShort){ |
| 589 | - return json_find_option_cstr2(zKey, zCLIShort, zCLIShort, -1); | |
| 592 | + return json_find_option_cstr2(zKey, zCLILong, zCLIShort, -1); | |
| 590 | 593 | } |
| 591 | 594 | |
| 592 | 595 | /* |
| 593 | 596 | ** The boolean equivalent of json_find_option_cstr(). |
| 594 | 597 | ** If the option is not found, dftl is returned. |
| 595 | 598 |
| --- src/json.c | |
| +++ src/json.c | |
| @@ -581,14 +581,17 @@ | |
| 581 | rc = json_command_arg((unsigned char)argPos); |
| 582 | } |
| 583 | return rc; |
| 584 | } |
| 585 | |
| 586 | char const * json_find_option_cstr(char const * zKey, |
| 587 | char const * zCLILong, |
| 588 | char const * zCLIShort){ |
| 589 | return json_find_option_cstr2(zKey, zCLIShort, zCLIShort, -1); |
| 590 | } |
| 591 | |
| 592 | /* |
| 593 | ** The boolean equivalent of json_find_option_cstr(). |
| 594 | ** If the option is not found, dftl is returned. |
| 595 |
| --- src/json.c | |
| +++ src/json.c | |
| @@ -581,14 +581,17 @@ | |
| 581 | rc = json_command_arg((unsigned char)argPos); |
| 582 | } |
| 583 | return rc; |
| 584 | } |
| 585 | |
| 586 | /* |
| 587 | ** Short-hand form of json_find_option_cstr(zKey,zCLILong,zCLIShort,-1). |
| 588 | */ |
| 589 | char const * json_find_option_cstr(char const * zKey, |
| 590 | char const * zCLILong, |
| 591 | char const * zCLIShort){ |
| 592 | return json_find_option_cstr2(zKey, zCLILong, zCLIShort, -1); |
| 593 | } |
| 594 | |
| 595 | /* |
| 596 | ** The boolean equivalent of json_find_option_cstr(). |
| 597 | ** If the option is not found, dftl is returned. |
| 598 |
+46
-30
| --- src/json_wiki.c | ||
| +++ src/json_wiki.c | ||
| @@ -51,18 +51,21 @@ | ||
| 51 | 51 | } |
| 52 | 52 | |
| 53 | 53 | |
| 54 | 54 | /* |
| 55 | 55 | ** Loads the given wiki page and creates a JSON object representation |
| 56 | -** of it. If the page is not found then NULL is returned. If doParse | |
| 57 | -** is true then the page content is HTML-ized using fossil's | |
| 58 | -** conventional wiki format, else it is not parsed. | |
| 56 | +** of it. If the page is not found then NULL is returned. If | |
| 57 | +** contentFormat is positive true then the page content is HTML-ized | |
| 58 | +** using fossil's conventional wiki format, if it is negative then no | |
| 59 | +** parsing is performed, if it is 0 then the content is not returned | |
| 60 | +** in the response. If contentFormat is 0 then the contentSize reflects | |
| 61 | +** the number of bytes, not characters, stored in the page. | |
| 59 | 62 | ** |
| 60 | 63 | ** The returned value, if not NULL, is-a JSON Object owned by the |
| 61 | 64 | ** caller. |
| 62 | 65 | */ |
| 63 | -cson_value * json_get_wiki_page_by_name(char const * zPageName, char doParse){ | |
| 66 | +cson_value * json_get_wiki_page_by_name(char const * zPageName, char contentFormat){ | |
| 64 | 67 | int rid; |
| 65 | 68 | Manifest *pWiki = 0; |
| 66 | 69 | char const * zBody = NULL; |
| 67 | 70 | char const * zFormat = NULL; |
| 68 | 71 | char * zUuid = NULL; |
| @@ -92,43 +95,52 @@ | ||
| 92 | 95 | cson_object_set(pay,"uuid",json_new_string(zUuid)); |
| 93 | 96 | free(zUuid); |
| 94 | 97 | zUuid = NULL; |
| 95 | 98 | /*cson_object_set(pay,"rid",json_new_int((cson_int_t)rid));*/ |
| 96 | 99 | cson_object_set(pay,"lastSavedBy",json_new_string(pWiki->zUser)); |
| 97 | - cson_object_set(pay,FossilJsonKeys.timestamp, json_julian_to_timestamp(pWiki->rDate)); | |
| 98 | - cson_object_set(pay,"contentFormat",json_new_string(zFormat)); | |
| 99 | - if( doParse ){ | |
| 100 | - Blob content = empty_blob; | |
| 101 | - Blob raw = empty_blob; | |
| 102 | - blob_append(&raw,zBody,-1); | |
| 103 | - wiki_convert(&raw,&content,0); | |
| 104 | - len = strlen(zBody); | |
| 105 | - len = (unsigned int)blob_size(&content); | |
| 106 | - cson_object_set(pay,"contentLength",json_new_int((cson_int_t)len)); | |
| 107 | - cson_object_set(pay,"content", | |
| 108 | - cson_value_new_string(blob_buffer(&content),len)); | |
| 109 | - blob_reset(&content); | |
| 110 | - blob_reset(&raw); | |
| 100 | + cson_object_set(pay,FossilJsonKeys.timestamp, | |
| 101 | + json_julian_to_timestamp(pWiki->rDate)); | |
| 102 | + | |
| 103 | + | |
| 104 | + if(0 == contentFormat){ | |
| 105 | + cson_object_set(pay,"contentLength", | |
| 106 | + json_new_int((cson_int_t)(zBody?strlen(zBody):0))); | |
| 111 | 107 | }else{ |
| 112 | - len = zBody ? strlen(zBody) : 0; | |
| 113 | - cson_object_set(pay,"contentLength",json_new_int((cson_int_t)len)); | |
| 114 | - cson_object_set(pay,"content",cson_value_new_string(zBody,len)); | |
| 108 | + cson_object_set(pay,"contentFormat",json_new_string(zFormat)); | |
| 109 | + if( contentFormat>0 ){/*HTML-ize it*/ | |
| 110 | + Blob content = empty_blob; | |
| 111 | + Blob raw = empty_blob; | |
| 112 | + blob_append(&raw,zBody,-1); | |
| 113 | + wiki_convert(&raw,&content,0); | |
| 114 | + len = strlen(zBody); | |
| 115 | + len = (unsigned int)blob_size(&content); | |
| 116 | + cson_object_set(pay,"contentLength",json_new_int((cson_int_t)len)); | |
| 117 | + cson_object_set(pay,"content", | |
| 118 | + cson_value_new_string(blob_buffer(&content),len)); | |
| 119 | + blob_reset(&content); | |
| 120 | + blob_reset(&raw); | |
| 121 | + }else{/*raw format*/ | |
| 122 | + len = zBody ? strlen(zBody) : 0; | |
| 123 | + cson_object_set(pay,"contentLength",json_new_int((cson_int_t)len)); | |
| 124 | + cson_object_set(pay,"content",cson_value_new_string(zBody,len)); | |
| 125 | + } | |
| 115 | 126 | } |
| 116 | 127 | /*TODO: add 'T' (tag) fields*/ |
| 117 | 128 | /*TODO: add the 'A' card (file attachment) entries?*/ |
| 118 | 129 | manifest_destroy(pWiki); |
| 119 | 130 | return cson_object_value(pay); |
| 120 | - } | |
| 131 | + } | |
| 132 | + | |
| 121 | 133 | } |
| 122 | 134 | |
| 123 | 135 | |
| 124 | 136 | /* |
| 125 | 137 | ** Searches for a wiki page with the given rid. If found it behaves |
| 126 | -** like json_get_wiki_page_by_name(pageName, doParse), else it returns | |
| 138 | +** like json_get_wiki_page_by_name(pageName, contentFormat), else it returns | |
| 127 | 139 | ** NULL. |
| 128 | 140 | */ |
| 129 | -cson_value * json_get_wiki_page_by_rid(int rid, char doParse){ | |
| 141 | +cson_value * json_get_wiki_page_by_rid(int rid, char contentFormat){ | |
| 130 | 142 | char * zPageName = NULL; |
| 131 | 143 | cson_value * rc = NULL; |
| 132 | 144 | zPageName = db_text(NULL, |
| 133 | 145 | "SELECT substr(t.tagname,6) AS name " |
| 134 | 146 | " FROM tag t, tagxref x, blob b " |
| @@ -135,11 +147,11 @@ | ||
| 135 | 147 | " WHERE b.rid=%d " |
| 136 | 148 | " AND t.tagname GLOB 'wiki-*'" |
| 137 | 149 | " AND x.tagid=t.tagid AND b.rid=x.rid ", |
| 138 | 150 | rid); |
| 139 | 151 | if( zPageName ){ |
| 140 | - rc = json_get_wiki_page_by_name(zPageName, doParse); | |
| 152 | + rc = json_get_wiki_page_by_name(zPageName, contentFormat); | |
| 141 | 153 | free(zPageName); |
| 142 | 154 | } |
| 143 | 155 | return rc; |
| 144 | 156 | } |
| 145 | 157 | |
| @@ -152,10 +164,11 @@ | ||
| 152 | 164 | Manifest *pWiki = 0; |
| 153 | 165 | char const * zBody = NULL; |
| 154 | 166 | char const * zPageName; |
| 155 | 167 | char const * zFormat = NULL; |
| 156 | 168 | char * zUuid = NULL; |
| 169 | + char contentFormat = -1; | |
| 157 | 170 | Stmt q; |
| 158 | 171 | if( !g.perm.RdWiki && !g.perm.Read ){ |
| 159 | 172 | json_set_err(FSL_JSON_E_DENIED, |
| 160 | 173 | "Requires 'o' or 'j' access."); |
| 161 | 174 | return NULL; |
| @@ -180,17 +193,20 @@ | ||
| 180 | 193 | "'name' argument is missing."); |
| 181 | 194 | return NULL; |
| 182 | 195 | } |
| 183 | 196 | |
| 184 | 197 | zFormat = json_find_option_cstr("format",NULL,"f"); |
| 185 | - if(!zFormat || !*zFormat){ | |
| 186 | - zFormat = "raw"; | |
| 198 | + if(!zFormat || !*zFormat || ('r'==*zFormat)){ | |
| 199 | + contentFormat = -1; | |
| 200 | + } | |
| 201 | + else if('h'==*zFormat){ | |
| 202 | + contentFormat = 1; | |
| 187 | 203 | } |
| 188 | - if( 'r' != *zFormat ){ | |
| 189 | - zFormat = "html"; | |
| 204 | + else if('n'==*zFormat){ | |
| 205 | + contentFormat = 0; | |
| 190 | 206 | } |
| 191 | - return json_get_wiki_page_by_name(zPageName, 'h'==*zFormat); | |
| 207 | + return json_get_wiki_page_by_name(zPageName, contentFormat); | |
| 192 | 208 | } |
| 193 | 209 | |
| 194 | 210 | /* |
| 195 | 211 | ** Internal impl of /wiki/save and /wiki/create. If createMode is 0 |
| 196 | 212 | ** and the page already exists then a |
| 197 | 213 |
| --- src/json_wiki.c | |
| +++ src/json_wiki.c | |
| @@ -51,18 +51,21 @@ | |
| 51 | } |
| 52 | |
| 53 | |
| 54 | /* |
| 55 | ** Loads the given wiki page and creates a JSON object representation |
| 56 | ** of it. If the page is not found then NULL is returned. If doParse |
| 57 | ** is true then the page content is HTML-ized using fossil's |
| 58 | ** conventional wiki format, else it is not parsed. |
| 59 | ** |
| 60 | ** The returned value, if not NULL, is-a JSON Object owned by the |
| 61 | ** caller. |
| 62 | */ |
| 63 | cson_value * json_get_wiki_page_by_name(char const * zPageName, char doParse){ |
| 64 | int rid; |
| 65 | Manifest *pWiki = 0; |
| 66 | char const * zBody = NULL; |
| 67 | char const * zFormat = NULL; |
| 68 | char * zUuid = NULL; |
| @@ -92,43 +95,52 @@ | |
| 92 | cson_object_set(pay,"uuid",json_new_string(zUuid)); |
| 93 | free(zUuid); |
| 94 | zUuid = NULL; |
| 95 | /*cson_object_set(pay,"rid",json_new_int((cson_int_t)rid));*/ |
| 96 | cson_object_set(pay,"lastSavedBy",json_new_string(pWiki->zUser)); |
| 97 | cson_object_set(pay,FossilJsonKeys.timestamp, json_julian_to_timestamp(pWiki->rDate)); |
| 98 | cson_object_set(pay,"contentFormat",json_new_string(zFormat)); |
| 99 | if( doParse ){ |
| 100 | Blob content = empty_blob; |
| 101 | Blob raw = empty_blob; |
| 102 | blob_append(&raw,zBody,-1); |
| 103 | wiki_convert(&raw,&content,0); |
| 104 | len = strlen(zBody); |
| 105 | len = (unsigned int)blob_size(&content); |
| 106 | cson_object_set(pay,"contentLength",json_new_int((cson_int_t)len)); |
| 107 | cson_object_set(pay,"content", |
| 108 | cson_value_new_string(blob_buffer(&content),len)); |
| 109 | blob_reset(&content); |
| 110 | blob_reset(&raw); |
| 111 | }else{ |
| 112 | len = zBody ? strlen(zBody) : 0; |
| 113 | cson_object_set(pay,"contentLength",json_new_int((cson_int_t)len)); |
| 114 | cson_object_set(pay,"content",cson_value_new_string(zBody,len)); |
| 115 | } |
| 116 | /*TODO: add 'T' (tag) fields*/ |
| 117 | /*TODO: add the 'A' card (file attachment) entries?*/ |
| 118 | manifest_destroy(pWiki); |
| 119 | return cson_object_value(pay); |
| 120 | } |
| 121 | } |
| 122 | |
| 123 | |
| 124 | /* |
| 125 | ** Searches for a wiki page with the given rid. If found it behaves |
| 126 | ** like json_get_wiki_page_by_name(pageName, doParse), else it returns |
| 127 | ** NULL. |
| 128 | */ |
| 129 | cson_value * json_get_wiki_page_by_rid(int rid, char doParse){ |
| 130 | char * zPageName = NULL; |
| 131 | cson_value * rc = NULL; |
| 132 | zPageName = db_text(NULL, |
| 133 | "SELECT substr(t.tagname,6) AS name " |
| 134 | " FROM tag t, tagxref x, blob b " |
| @@ -135,11 +147,11 @@ | |
| 135 | " WHERE b.rid=%d " |
| 136 | " AND t.tagname GLOB 'wiki-*'" |
| 137 | " AND x.tagid=t.tagid AND b.rid=x.rid ", |
| 138 | rid); |
| 139 | if( zPageName ){ |
| 140 | rc = json_get_wiki_page_by_name(zPageName, doParse); |
| 141 | free(zPageName); |
| 142 | } |
| 143 | return rc; |
| 144 | } |
| 145 | |
| @@ -152,10 +164,11 @@ | |
| 152 | Manifest *pWiki = 0; |
| 153 | char const * zBody = NULL; |
| 154 | char const * zPageName; |
| 155 | char const * zFormat = NULL; |
| 156 | char * zUuid = NULL; |
| 157 | Stmt q; |
| 158 | if( !g.perm.RdWiki && !g.perm.Read ){ |
| 159 | json_set_err(FSL_JSON_E_DENIED, |
| 160 | "Requires 'o' or 'j' access."); |
| 161 | return NULL; |
| @@ -180,17 +193,20 @@ | |
| 180 | "'name' argument is missing."); |
| 181 | return NULL; |
| 182 | } |
| 183 | |
| 184 | zFormat = json_find_option_cstr("format",NULL,"f"); |
| 185 | if(!zFormat || !*zFormat){ |
| 186 | zFormat = "raw"; |
| 187 | } |
| 188 | if( 'r' != *zFormat ){ |
| 189 | zFormat = "html"; |
| 190 | } |
| 191 | return json_get_wiki_page_by_name(zPageName, 'h'==*zFormat); |
| 192 | } |
| 193 | |
| 194 | /* |
| 195 | ** Internal impl of /wiki/save and /wiki/create. If createMode is 0 |
| 196 | ** and the page already exists then a |
| 197 |
| --- src/json_wiki.c | |
| +++ src/json_wiki.c | |
| @@ -51,18 +51,21 @@ | |
| 51 | } |
| 52 | |
| 53 | |
| 54 | /* |
| 55 | ** Loads the given wiki page and creates a JSON object representation |
| 56 | ** of it. If the page is not found then NULL is returned. If |
| 57 | ** contentFormat is positive true then the page content is HTML-ized |
| 58 | ** using fossil's conventional wiki format, if it is negative then no |
| 59 | ** parsing is performed, if it is 0 then the content is not returned |
| 60 | ** in the response. If contentFormat is 0 then the contentSize reflects |
| 61 | ** the number of bytes, not characters, stored in the page. |
| 62 | ** |
| 63 | ** The returned value, if not NULL, is-a JSON Object owned by the |
| 64 | ** caller. |
| 65 | */ |
| 66 | cson_value * json_get_wiki_page_by_name(char const * zPageName, char contentFormat){ |
| 67 | int rid; |
| 68 | Manifest *pWiki = 0; |
| 69 | char const * zBody = NULL; |
| 70 | char const * zFormat = NULL; |
| 71 | char * zUuid = NULL; |
| @@ -92,43 +95,52 @@ | |
| 95 | cson_object_set(pay,"uuid",json_new_string(zUuid)); |
| 96 | free(zUuid); |
| 97 | zUuid = NULL; |
| 98 | /*cson_object_set(pay,"rid",json_new_int((cson_int_t)rid));*/ |
| 99 | cson_object_set(pay,"lastSavedBy",json_new_string(pWiki->zUser)); |
| 100 | cson_object_set(pay,FossilJsonKeys.timestamp, |
| 101 | json_julian_to_timestamp(pWiki->rDate)); |
| 102 | |
| 103 | |
| 104 | if(0 == contentFormat){ |
| 105 | cson_object_set(pay,"contentLength", |
| 106 | json_new_int((cson_int_t)(zBody?strlen(zBody):0))); |
| 107 | }else{ |
| 108 | cson_object_set(pay,"contentFormat",json_new_string(zFormat)); |
| 109 | if( contentFormat>0 ){/*HTML-ize it*/ |
| 110 | Blob content = empty_blob; |
| 111 | Blob raw = empty_blob; |
| 112 | blob_append(&raw,zBody,-1); |
| 113 | wiki_convert(&raw,&content,0); |
| 114 | len = strlen(zBody); |
| 115 | len = (unsigned int)blob_size(&content); |
| 116 | cson_object_set(pay,"contentLength",json_new_int((cson_int_t)len)); |
| 117 | cson_object_set(pay,"content", |
| 118 | cson_value_new_string(blob_buffer(&content),len)); |
| 119 | blob_reset(&content); |
| 120 | blob_reset(&raw); |
| 121 | }else{/*raw format*/ |
| 122 | len = zBody ? strlen(zBody) : 0; |
| 123 | cson_object_set(pay,"contentLength",json_new_int((cson_int_t)len)); |
| 124 | cson_object_set(pay,"content",cson_value_new_string(zBody,len)); |
| 125 | } |
| 126 | } |
| 127 | /*TODO: add 'T' (tag) fields*/ |
| 128 | /*TODO: add the 'A' card (file attachment) entries?*/ |
| 129 | manifest_destroy(pWiki); |
| 130 | return cson_object_value(pay); |
| 131 | } |
| 132 | |
| 133 | } |
| 134 | |
| 135 | |
| 136 | /* |
| 137 | ** Searches for a wiki page with the given rid. If found it behaves |
| 138 | ** like json_get_wiki_page_by_name(pageName, contentFormat), else it returns |
| 139 | ** NULL. |
| 140 | */ |
| 141 | cson_value * json_get_wiki_page_by_rid(int rid, char contentFormat){ |
| 142 | char * zPageName = NULL; |
| 143 | cson_value * rc = NULL; |
| 144 | zPageName = db_text(NULL, |
| 145 | "SELECT substr(t.tagname,6) AS name " |
| 146 | " FROM tag t, tagxref x, blob b " |
| @@ -135,11 +147,11 @@ | |
| 147 | " WHERE b.rid=%d " |
| 148 | " AND t.tagname GLOB 'wiki-*'" |
| 149 | " AND x.tagid=t.tagid AND b.rid=x.rid ", |
| 150 | rid); |
| 151 | if( zPageName ){ |
| 152 | rc = json_get_wiki_page_by_name(zPageName, contentFormat); |
| 153 | free(zPageName); |
| 154 | } |
| 155 | return rc; |
| 156 | } |
| 157 | |
| @@ -152,10 +164,11 @@ | |
| 164 | Manifest *pWiki = 0; |
| 165 | char const * zBody = NULL; |
| 166 | char const * zPageName; |
| 167 | char const * zFormat = NULL; |
| 168 | char * zUuid = NULL; |
| 169 | char contentFormat = -1; |
| 170 | Stmt q; |
| 171 | if( !g.perm.RdWiki && !g.perm.Read ){ |
| 172 | json_set_err(FSL_JSON_E_DENIED, |
| 173 | "Requires 'o' or 'j' access."); |
| 174 | return NULL; |
| @@ -180,17 +193,20 @@ | |
| 193 | "'name' argument is missing."); |
| 194 | return NULL; |
| 195 | } |
| 196 | |
| 197 | zFormat = json_find_option_cstr("format",NULL,"f"); |
| 198 | if(!zFormat || !*zFormat || ('r'==*zFormat)){ |
| 199 | contentFormat = -1; |
| 200 | } |
| 201 | else if('h'==*zFormat){ |
| 202 | contentFormat = 1; |
| 203 | } |
| 204 | else if('n'==*zFormat){ |
| 205 | contentFormat = 0; |
| 206 | } |
| 207 | return json_get_wiki_page_by_name(zPageName, contentFormat); |
| 208 | } |
| 209 | |
| 210 | /* |
| 211 | ** Internal impl of /wiki/save and /wiki/create. If createMode is 0 |
| 212 | ** and the page already exists then a |
| 213 |