Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Implemented /json/wiki/save. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | json |
Files: | files | file ages | folders |
SHA1: |
2162c86d9ec34458dd5db2a5a3f93b00 |
User & Date: | stephan 2011-09-22 17:56:37.939 |
Context
2011-09-22
| ||
19:14 | Implemented /json/wiki/create. ... (check-in: 1df648ab user: stephan tags: json) | |
17:56 | Implemented /json/wiki/save. ... (check-in: 2162c86d user: stephan tags: json) | |
17:18 | added src/Makefile so that (ctrl-x m) will DTRT. ... (check-in: ce4f3103 user: stephan tags: json) | |
Changes
Changes to ajax/wiki-editor.html.
︙ | ︙ | |||
184 185 186 187 188 189 190 191 192 193 194 195 196 197 | TheApp.cgi.onLogout = function(){ TheApp.jqe.taResponse.val( "Logged out!" ); TheApp.jqe.currentAuthToken.text(""); }; TheApp.showPage = function(name){ function doShow(page){ TheApp.jqe.spanPageName.text('('+page.name+')'); TheApp.jqe.taPageContent.val(page.content); } var p = ('object' === typeof name) ? name : TheApp.pages[name]; if('object' === typeof p) { doShow(p); return; | > | 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 | TheApp.cgi.onLogout = function(){ TheApp.jqe.taResponse.val( "Logged out!" ); TheApp.jqe.currentAuthToken.text(""); }; TheApp.showPage = function(name){ function doShow(page){ TheApp.currentPage = page; TheApp.jqe.spanPageName.text('('+page.name+')'); TheApp.jqe.taPageContent.val(page.content); } var p = ('object' === typeof name) ? name : TheApp.pages[name]; if('object' === typeof p) { doShow(p); return; |
︙ | ︙ | |||
233 234 235 236 237 238 239 240 241 242 243 244 245 246 | if(resp.resultCode) return; else TheApp.updatePageList(resp.payload); } }); return false /*for click handlers*/; } }); </script> </head> <body> | > > > > > > > > > > > > > > > > > > | 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 | if(resp.resultCode) return; else TheApp.updatePageList(resp.payload); } }); return false /*for click handlers*/; } TheApp.savePage = function(p){ p = p || TheApp.currentPage || TheApp.pages[TheApp.currentPage]; if( 'object' !== typeof p ){ p = TheApp.pages[p]; } if('object' !== typeof p){ alert("savePage() argument is not a page object or known page name."); } TheApp.pages[p.name] = p; p.content = TheApp.jqe.taPageContent.val(); var req = { name:p.name, content:p.content }; if(! confirm("Really save wiki page ["+p.name+"]?") ) return; TheApp.cgi.sendCommand('/json/wiki/save',req); }; }); </script> </head> <body> |
︙ | ︙ | |||
263 264 265 266 267 268 269 270 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 | <strong>Quick-posts:</strong><br/> <input type='button' value='HAI' onclick='TheApp.cgi.HAI()' /> <input type='button' value='version' onclick='TheApp.cgi.sendCommand("/json/version")' /> <input type='button' value='stat' onclick='TheApp.cgi.sendCommand("/json/stat")' /> <input type='button' value='whoami' onclick='TheApp.cgi.sendCommand("/json/whoami")' /> <input type='button' value='cap' onclick='TheApp.cgi.sendCommand("/json/cap")' /> <input type='button' value='wiki/list' onclick='TheApp.loadPageList()' /> <!-- <input type='button' value='get whiki' onclick='TheApp.cgi.getPages("whiki")' /> <input type='button' value='get more' onclick='TheApp.cgi.getPages("HelloWorld/WhikiNews")' /> <input type='button' value='get client data' onclick='TheApp.cgi.getPageClientData("HelloWorld/whiki/WhikiCommands")' /> <input type='button' value='save client data' onclick='TheApp.cgi.savePageClientData({"HelloWorld":[1,3,5]})' /> --> <hr/> <table> <tr> <th>Page List</th> <th>Content <span id='spanPageName'></span></th> </tr> <tr> <td width='25%' valign='top'> <div id='pageListArea'></div> </td> <td width='75%' valign='top'> <textarea id='taPageContent' rows='20' cols='60'></textarea> </td> </tr> <tr> <th colspan='2'>Response <span id='timer'></span></th> </tr> <tr> | > > > > | 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 308 309 310 311 312 313 314 315 316 317 318 | <strong>Quick-posts:</strong><br/> <input type='button' value='HAI' onclick='TheApp.cgi.HAI()' /> <input type='button' value='version' onclick='TheApp.cgi.sendCommand("/json/version")' /> <input type='button' value='stat' onclick='TheApp.cgi.sendCommand("/json/stat")' /> <input type='button' value='whoami' onclick='TheApp.cgi.sendCommand("/json/whoami")' /> <input type='button' value='cap' onclick='TheApp.cgi.sendCommand("/json/cap")' /> <input type='button' value='wiki/list' onclick='TheApp.loadPageList()' /> <!-- <input type='button' value='timeline/ci' onclick='TheApp.cgi.sendCommand("/json/timeline/ci")' /> --> <!-- <input type='button' value='get whiki' onclick='TheApp.cgi.getPages("whiki")' /> <input type='button' value='get more' onclick='TheApp.cgi.getPages("HelloWorld/WhikiNews")' /> <input type='button' value='get client data' onclick='TheApp.cgi.getPageClientData("HelloWorld/whiki/WhikiCommands")' /> <input type='button' value='save client data' onclick='TheApp.cgi.savePageClientData({"HelloWorld":[1,3,5]})' /> --> <hr/> <table> <tr> <th>Page List</th> <th>Content <span id='spanPageName'></span></th> </tr> <tr> <td width='25%' valign='top'> <div id='pageListArea'></div> </td> <td width='75%' valign='top'> <input type='button' value='Save' onclick='TheApp.savePage()' /><br/> <textarea id='taPageContent' rows='20' cols='60'></textarea> </td> </tr> <tr> <th colspan='2'>Response <span id='timer'></span></th> </tr> <tr> |
︙ | ︙ |
Changes to src/json.c.
︙ | ︙ | |||
479 480 481 482 483 484 485 486 487 488 489 490 491 492 | g.json.authToken = v; } } } } return g.json.authToken; } /* ** Initializes some JSON bits which need to be initialized relatively ** early on. It should only be called from cgi_init() or ** json_cmd_top() (early on in those functions). ** ** Initializes g.json.gc and g.json.param. This code does not (and | > > > > > > > > > > > > | 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 | g.json.authToken = v; } } } } return g.json.authToken; } /* ** IFF json.reqPayload.o is not NULL then this returns ** cson_object_get(json.reqPayload.o,pKey), else it returns NULL. ** ** The returned value is owned by (or shared with) json.reqPayload.v. */ cson_value * json_req_payload_get(char const *pKey){ return g.json.reqPayload.o ? cson_object_get(g.json.reqPayload.o,pKey) : NULL; } /* ** Initializes some JSON bits which need to be initialized relatively ** early on. It should only be called from cgi_init() or ** json_cmd_top() (early on in those functions). ** ** Initializes g.json.gc and g.json.param. This code does not (and |
︙ | ︙ | |||
940 941 942 943 944 945 946 947 948 949 950 951 952 953 | ** repo is opened (will trigger a fatal error in db_xxx()). */ static cson_value * json_julian_to_timestamp(double j){ return cson_value_new_integer((cson_int_t) db_int64(0,"SELECT strftime('%%s',%lf)",j) ); } /* ** Creates a new Fossil/JSON response envelope skeleton. It is owned ** by the caller, who must eventually free it using cson_value_free(), ** or add it to a cson container to transfer ownership. Returns NULL ** on error. ** | > > > > > > > > > > > > > > | 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 | ** repo is opened (will trigger a fatal error in db_xxx()). */ static cson_value * json_julian_to_timestamp(double j){ return cson_value_new_integer((cson_int_t) db_int64(0,"SELECT strftime('%%s',%lf)",j) ); } /* ** Returns a timestamp value. */ static cson_int_t json_timestamp(){ return (cson_int_t)time(0); } /* ** Returns a new JSON value (owned by the caller) representing ** a timestamp. If timeVal is < 0 then time(0) is used to fetch ** the time, else timeVal is used as-is */ static cson_value * json_new_timestamp(cson_int_t timeVal){ return cson_value_new_integer((timeVal<0) ? (cson_int_t)time(0) : timeVal); } /* ** Creates a new Fossil/JSON response envelope skeleton. It is owned ** by the caller, who must eventually free it using cson_value_free(), ** or add it to a cson container to transfer ownership. Returns NULL ** on error. ** |
︙ | ︙ | |||
984 985 986 987 988 989 990 | goto cleanup; \ }while(0) tmp = cson_value_new_string(MANIFEST_UUID,strlen(MANIFEST_UUID)); SET("fossil"); {/* timestamp */ | < < < < < < | < < < < < < < < < < < < < < < < < < | 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 | goto cleanup; \ }while(0) tmp = cson_value_new_string(MANIFEST_UUID,strlen(MANIFEST_UUID)); SET("fossil"); {/* timestamp */ tmp = json_new_timestamp(-1); SET(FossilJsonKeys.timestamp); } if( 0 != resultCode ){ if( ! pMsg ) pMsg = json_err_str(resultCode); tmp = json_rc_string(resultCode); SET(FossilJsonKeys.resultCode); } |
︙ | ︙ | |||
1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 | return jv; #undef SETBUF } static cson_value * json_wiki_list(unsigned int depth); static cson_value * json_wiki_get(unsigned int depth); /* ** Mapping of /json/wiki/XXX commands/paths to callbacks. */ static const JsonPageDef JsonPageDefs_Wiki[] = { {"get", json_wiki_get, 0}, {"list", json_wiki_list, 0}, | > | | 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 | return jv; #undef SETBUF } static cson_value * json_wiki_list(unsigned int depth); static cson_value * json_wiki_get(unsigned int depth); static cson_value * json_wiki_save(unsigned int depth); /* ** Mapping of /json/wiki/XXX commands/paths to callbacks. */ static const JsonPageDef JsonPageDefs_Wiki[] = { {"get", json_wiki_get, 0}, {"list", json_wiki_list, 0}, {"save", json_wiki_save, 1}, /* Last entry MUST have a NULL name. */ {NULL,NULL,0} }; /* ** A page/command dispatch helper for fossil_json_f() implementations. ** depth should be the depth parameter passed to the fossil_json_f(). |
︙ | ︙ | |||
1576 1577 1578 1579 1580 1581 1582 | cson_object * pay = cson_value_get_object(payV); cson_object_set(pay,"name",json_new_string(zPageName)); cson_object_set(pay,"version",json_new_string(pWiki->zBaseline)) /*FIXME: pWiki->zBaseline is NULL. How to get the version number?*/ ; cson_object_set(pay,"rid",cson_value_new_integer((cson_int_t)rid)); cson_object_set(pay,"lastSavedBy",json_new_string(pWiki->zUser)); | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 | cson_object * pay = cson_value_get_object(payV); cson_object_set(pay,"name",json_new_string(zPageName)); cson_object_set(pay,"version",json_new_string(pWiki->zBaseline)) /*FIXME: pWiki->zBaseline is NULL. How to get the version number?*/ ; cson_object_set(pay,"rid",cson_value_new_integer((cson_int_t)rid)); cson_object_set(pay,"lastSavedBy",json_new_string(pWiki->zUser)); cson_object_set(pay,FossilJsonKeys.timestamp, json_julian_to_timestamp(pWiki->rDate)); cson_object_set(pay,"contentLength",cson_value_new_integer((cson_int_t)len)); cson_object_set(pay,"contentFormat",json_new_string(doParse?"html":"raw")); cson_object_set(pay,"content",cson_value_new_string(zBody,len)); /*TODO: add 'T' (tag) fields*/ /*TODO: add the 'A' card (file attachment) entries?*/ manifest_destroy(pWiki); return payV; } } /* ** Implementation of /json/wiki/save. */ static cson_value * json_wiki_save(unsigned int depth){ Blob content = empty_blob; cson_value * nameV; cson_value * contentV; cson_value * payV = NULL; cson_object * pay = NULL; cson_string const * jstr = NULL; char const * zContent; char const * zBody = NULL; char const * zPageName; if( !g.perm.WrWiki ){ g.json.resultCode = FSL_JSON_E_DENIED; return NULL; } nameV = json_req_payload_get("name"); contentV = nameV ? json_req_payload_get("content") : NULL; if(!nameV || !contentV){ g.json.resultCode = FSL_JSON_E_MISSING_ARGS; return NULL; } if( !cson_value_is_string(nameV) || !cson_value_is_string(contentV)){ g.json.resultCode = FSL_JSON_E_INVALID_ARGS; return NULL; } zPageName = cson_string_cstr(cson_value_get_string(nameV)); jstr = cson_value_get_string(contentV); blob_append(&content, cson_string_cstr(jstr),(int)cson_string_length_bytes(jstr)); wiki_cmd_commit(zPageName, 0, &content); blob_reset(&content); payV = cson_value_new_object(); pay = cson_value_get_object(payV); cson_object_set( pay, "name", nameV ); cson_object_set( pay, FossilJsonKeys.timestamp, json_new_timestamp(-1) ); return payV; } /* ** Implementation of /json/wiki/list. */ static cson_value * json_wiki_list(unsigned int depth){ cson_value * listV = NULL; cson_array * list = NULL; |
︙ | ︙ | |||
1985 1986 1987 1988 1989 1990 1991 | {"logout",json_page_logout,1}, {"stat",json_page_stat,0}, {"tag", json_page_nyi,0}, {"ticket", json_page_nyi,0}, {"timeline", json_page_timeline,0}, {"user", json_page_nyi,0}, {"version",json_page_version,0}, | | | 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 | {"logout",json_page_logout,1}, {"stat",json_page_stat,0}, {"tag", json_page_nyi,0}, {"ticket", json_page_nyi,0}, {"timeline", json_page_timeline,0}, {"user", json_page_nyi,0}, {"version",json_page_version,0}, {"whoami",json_page_whoami,1/*FIXME: work in CLI mode*/}, {"wiki",json_page_wiki,0}, /* Last entry MUST have a NULL name. */ {NULL,NULL,0} }; /* |
︙ | ︙ |
Changes to src/wiki.c.
︙ | ︙ | |||
799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 | rid = db_int(0, "SELECT x.rid FROM tag t, tagxref x" " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'" " ORDER BY x.mtime DESC LIMIT 1", zPageName ); if( rid==0 && !isNew ){ fossil_fatal("no such wiki page: %s", zPageName); } if( rid!=0 && isNew ){ fossil_fatal("wiki page %s already exists", zPageName); } blob_zero(&wiki); zDate = date_in_standard_format("now"); blob_appendf(&wiki, "D %s\n", zDate); free(zDate); | > > | 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 | rid = db_int(0, "SELECT x.rid FROM tag t, tagxref x" " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'" " ORDER BY x.mtime DESC LIMIT 1", zPageName ); if( rid==0 && !isNew ){ g.json.resultCode = FSL_JSON_E_RESOURCE_NOT_FOUND; fossil_fatal("no such wiki page: %s", zPageName); } if( rid!=0 && isNew ){ g.json.resultCode = FSL_JSON_E_DENIED/*need a better code for this*/; fossil_fatal("wiki page %s already exists", zPageName); } blob_zero(&wiki); zDate = date_in_standard_format("now"); blob_appendf(&wiki, "D %s\n", zDate); free(zDate); |
︙ | ︙ |