mirror of
https://github.com/gnosygnu/xowa.git
synced 2026-03-02 03:49:30 +00:00
HTTP Server: Support 'action=edit' / 'action=html' [#264]
Also: * Change XOWA GUI to use 'action' query args, instead of xowa-cmd * Remove nginx http_variables due to compiler warnings
This commit is contained in:
@@ -32,6 +32,7 @@ package gplx.xowa.apps.servers.http; import gplx.*; import gplx.xowa.*; import g
|
||||
import gplx.core.threads.*; import gplx.core.net.*; import gplx.core.primitives.*; import gplx.core.envs.*;
|
||||
import gplx.langs.jsons.*; import gplx.langs.htmls.encoders.*;
|
||||
import gplx.xowa.wikis.pages.*;
|
||||
import gplx.xowa.addons.wikis.searchs.gui.htmlbars.*;
|
||||
public class Http_server_mgr implements Gfo_invk {
|
||||
private final Object thread_lock = new Object();
|
||||
private final Gfo_usr_dlg usr_dlg;
|
||||
@@ -76,7 +77,7 @@ public class Http_server_mgr implements Gfo_invk {
|
||||
}
|
||||
else
|
||||
Note("HTTP Server not started");
|
||||
}
|
||||
}
|
||||
running = val;
|
||||
}
|
||||
public void Run() {
|
||||
@@ -90,7 +91,7 @@ public class Http_server_mgr implements Gfo_invk {
|
||||
String cmd = url_converter.Decode_str(url_encoded_str);
|
||||
app.Gfs_mgr().Run_str(cmd);
|
||||
}
|
||||
public String Parse_page_to_html(Http_data__client data__client, byte[] wiki_domain, byte[] ttl_bry) {
|
||||
public String Parse_page_to_html(Http_data__client data__client, byte[] wiki_domain, byte[] ttl_bry, byte mode) {
|
||||
synchronized (thread_lock) {
|
||||
// create a shim gui to automatically handle default XOWA gui JS calls
|
||||
if (init_gui_needed) {
|
||||
@@ -101,7 +102,7 @@ public class Http_server_mgr implements Gfo_invk {
|
||||
// get the wiki
|
||||
Xowe_wiki wiki = (Xowe_wiki)app.Wiki_mgr().Get_by_or_make_init_y(wiki_domain); // assert init for Main_Page; EX:click zh.w on wiki sidebar; DATE:2015-07-19
|
||||
if (Runtime_.Memory_total() > Io_mgr.Len_gb) Xowe_wiki_.Rls_mem(wiki, true); // release memory at 1 GB; DATE:2015-09-11
|
||||
|
||||
|
||||
// get the url / ttl
|
||||
if (Bry_.Len_eq_0(ttl_bry)) ttl_bry = wiki.Props().Main_page();
|
||||
Xoa_url url = wiki.Utl__url_parser().Parse(ttl_bry);
|
||||
@@ -118,7 +119,7 @@ public class Http_server_mgr implements Gfo_invk {
|
||||
page.Html_data().Head_mgr().Itm__server().Init_by_http(data__client).Enabled_y_();
|
||||
|
||||
// generate html
|
||||
String rv = String_.new_u8(wiki.Html_mgr().Page_wtr_mgr().Gen(page, Xopg_page_.Tid_read)); // NOTE: must generate HTML now in order for "wait" and "async_server" to work with text_dbs; DATE:2016-07-10
|
||||
String rv = String_.new_u8(wiki.Html_mgr().Page_wtr_mgr().Gen(page, mode)); // NOTE: must generate HTML now in order for "wait" and "async_server" to work with text_dbs; DATE:2016-07-10
|
||||
boolean rebuild_html = false;
|
||||
switch (retrieve_mode) {
|
||||
case File_retrieve_mode.Mode_skip: // noop
|
||||
@@ -133,7 +134,7 @@ public class Http_server_mgr implements Gfo_invk {
|
||||
page = wiki.Page_mgr().Load_page(url, ttl, tab); // HACK: fetch page again so that HTML will now include img data
|
||||
break;
|
||||
}
|
||||
if (rebuild_html) rv = String_.new_u8(wiki.Html_mgr().Page_wtr_mgr().Gen(page, Xopg_page_.Tid_read));
|
||||
if (rebuild_html) rv = String_.new_u8(wiki.Html_mgr().Page_wtr_mgr().Gen(page, mode));
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import gplx.core.ios.*; import gplx.core.ios.streams.*;
|
||||
import gplx.core.primitives.*; import gplx.core.net.*; import gplx.langs.htmls.encoders.*;
|
||||
import gplx.xowa.apps.*;
|
||||
import gplx.xowa.htmls.js.*;
|
||||
import gplx.xowa.wikis.pages.*;
|
||||
class Http_server_wkr implements Gfo_invk {
|
||||
private final int uid;
|
||||
private final Http_server_mgr server_mgr;
|
||||
@@ -98,20 +99,15 @@ class Http_server_wkr implements Gfo_invk {
|
||||
app.Http_server().Run_xowa_cmd(app, String_.new_u8(cmd));
|
||||
}
|
||||
private void Write_wiki(byte[] req) {
|
||||
String wiki_domain = ""; String page_name = "";
|
||||
String[] req_split = String_.Split(String_.new_u8(req), "/");
|
||||
if(req_split.length >= 1){
|
||||
wiki_domain = req_split[1];
|
||||
Http_url_parser url_parser = new Http_url_parser(url_encoder);
|
||||
String page_html = "";
|
||||
if (!url_parser.Parse(req)) {
|
||||
page_html = url_parser.Err_msg();
|
||||
}
|
||||
if(req_split.length >= 4){
|
||||
page_name = req_split[3];
|
||||
for(int i = 4; i <= req_split.length-1; i++){
|
||||
page_name += "/" + req_split[i];
|
||||
}
|
||||
page_name = url_encoder.Decode_str(page_name);
|
||||
else {
|
||||
page_html = app.Http_server().Parse_page_to_html(data__client, url_parser.Wiki(), url_parser.Page(), url_parser.Action());
|
||||
page_html = Convert_page(page_html, root_dir_http, String_.new_u8(url_parser.Wiki()));
|
||||
}
|
||||
String page_html = app.Http_server().Parse_page_to_html(data__client, Bry_.new_u8(wiki_domain), Bry_.new_u8(page_name));
|
||||
page_html = Convert_page(page_html, root_dir_http, wiki_domain);
|
||||
Xosrv_http_wkr_.Write_response_as_html(client_wtr, Bool_.N, page_html);
|
||||
}
|
||||
private void Process_post(Http_request_itm request) {
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.xowa.apps.servers.http; import gplx.*; import gplx.xowa.*; import gplx.xowa.apps.*; import gplx.xowa.apps.servers.*;
|
||||
import gplx.langs.htmls.encoders.*;
|
||||
import gplx.xowa.htmls.hrefs.*;
|
||||
import gplx.xowa.wikis.pages.*;
|
||||
class Http_url_parser {
|
||||
private final Gfo_url_encoder url_encoder;
|
||||
public Http_url_parser(Gfo_url_encoder url_encoder) {
|
||||
this.url_encoder = url_encoder;
|
||||
}
|
||||
public byte[] Wiki() {return wiki;} public Http_url_parser Wiki_(String v) {this.wiki = Bry_.new_u8(v); return this;} private byte[] wiki;
|
||||
public byte[] Page() {return page;} public Http_url_parser Page_(String v) {this.page = Bry_.new_u8(v); return this;} private byte[] page;
|
||||
public byte Action() {return action;} public Http_url_parser Action_(byte v) {this.action = v; return this;} private byte action;
|
||||
public String Err_msg() {return err_msg;} public Http_url_parser Err_msg_(String v) {this.err_msg = v; return this;} private String err_msg;
|
||||
|
||||
public String To_str() {
|
||||
Bry_bfr bfr = Bry_bfr_.New();
|
||||
bfr.Add_str_a7("wiki=").Add_safe(wiki).Add_byte_nl();
|
||||
bfr.Add_str_a7("page=").Add_safe(page).Add_byte_nl();
|
||||
bfr.Add_str_a7("action=").Add_byte(action).Add_byte_nl();
|
||||
bfr.Add_str_a7("err_msg=").Add_str_u8_null(err_msg).Add_byte_nl();
|
||||
return bfr.To_str_and_clear();
|
||||
}
|
||||
|
||||
// Parse urls of form "/wiki_name/wiki/Page_name?action=val"
|
||||
public boolean Parse(byte[] url) {
|
||||
try {
|
||||
// initial validations
|
||||
if (url == null) return Fail(url, "invalid url; url is null");
|
||||
int url_len = url.length;
|
||||
if (url_len == 0) return Fail(url, "invalid url; url is empty");
|
||||
if (url[0] != Byte_ascii.Slash) return Fail(url, "invalid url; must start with '/'");
|
||||
|
||||
// get wiki
|
||||
int wiki_bgn = 1; // skip initial "/"
|
||||
int wiki_end = Bry_find_.Find_fwd_or(url, Byte_ascii.Slash, wiki_bgn, url_len, url_len);
|
||||
this.wiki = Bry_.Mid(url, wiki_bgn, wiki_end);
|
||||
if (wiki_end == url_len) {// no slash found; url is wiki-only; EX: "/en.wikipedia.org"
|
||||
return true;
|
||||
}
|
||||
|
||||
// get page after "/wiki/"
|
||||
byte[] wiki_separator = Xoh_href_.Bry__wiki;
|
||||
int page_bgn = wiki_end + wiki_separator.length;
|
||||
if (!Bry_.Eq(url, wiki_end, wiki_end + wiki_separator.length, Xoh_href_.Bry__wiki))
|
||||
return Fail(url, "invalid url; must have '/wiki/' after wiki_domain");
|
||||
int page_end = url_len;
|
||||
|
||||
// search for action arg
|
||||
this.action = Xopg_page_.Tid_read;
|
||||
int action_key_bgn = Bry_find_.Find_bwd(url, Qarg__action__frag, url_len);
|
||||
if (action_key_bgn != Bry_find_.Not_found) {
|
||||
int action_val_bgn = action_key_bgn + Qarg__action__frag.length;
|
||||
int action_val_end = url_len;
|
||||
boolean trim_page = true;
|
||||
if (Bry_.Eq(url, action_val_bgn, action_val_end, Xoa_url_.Qarg__action__read))
|
||||
this.action = Xopg_page_.Tid_read;
|
||||
else if (Bry_.Eq(url, action_val_bgn, action_val_end, Xoa_url_.Qarg__action__edit))
|
||||
this.action = Xopg_page_.Tid_edit;
|
||||
else if (Bry_.Eq(url, action_val_bgn, action_val_end, Xoa_url_.Qarg__action__html))
|
||||
this.action = Xopg_page_.Tid_html;
|
||||
else
|
||||
trim_page = false;
|
||||
if (trim_page)
|
||||
page_end = action_key_bgn;
|
||||
}
|
||||
|
||||
this.page = url_encoder.Decode(Bry_.Mid(url, page_bgn, page_end));
|
||||
return true;
|
||||
}
|
||||
catch (Exception e) {
|
||||
this.err_msg = Err_.Message_gplx_log(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
private boolean Fail(byte[] url, String err_msg) {
|
||||
this.wiki = null;
|
||||
this.page = null;
|
||||
this.err_msg = err_msg + "; url=" + String_.new_u8(url);
|
||||
return false;
|
||||
}
|
||||
private static final byte[]
|
||||
Qarg__action__frag = Bry_.Add(Byte_ascii.Question_bry, Xoa_url_.Qarg__action, Byte_ascii.Eq_bry) // "?action="
|
||||
;
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.xowa.apps.servers.http; import gplx.*; import gplx.xowa.*; import gplx.xowa.apps.*; import gplx.xowa.apps.servers.*;
|
||||
import org.junit.*; import gplx.core.tests.*;
|
||||
import gplx.langs.htmls.encoders.*;
|
||||
import gplx.xowa.wikis.pages.*;
|
||||
public class Http_url_parser_tst {
|
||||
private final Http_url_parser_fxt fxt = new Http_url_parser_fxt();
|
||||
@Test public void Parse() {
|
||||
// wiki-only
|
||||
fxt.Test__parse("/en.wikipedia.org", fxt.Make().Wiki_("en.wikipedia.org"));
|
||||
|
||||
// wiki + page
|
||||
fxt.Test__parse("/en.wikipedia.org/wiki/Page_1", fxt.Make().Wiki_("en.wikipedia.org").Page_("Page_1"));
|
||||
|
||||
// url-decoded; "%20" -> " "
|
||||
fxt.Test__parse("/en.wikipedia.org/wiki/Page%201", fxt.Make().Wiki_("en.wikipedia.org").Page_("Page 1"));
|
||||
|
||||
// page with multiple slashes
|
||||
fxt.Test__parse("/en.wikipedia.org/wiki/Page_1/A/B/C", fxt.Make().Wiki_("en.wikipedia.org").Page_("Page_1/A/B/C"));
|
||||
|
||||
// action=edit
|
||||
fxt.Test__parse("/en.wikipedia.org/wiki/Page_1?action=edit", fxt.Make().Wiki_("en.wikipedia.org").Page_("Page_1").Action_(Xopg_page_.Tid_edit));
|
||||
|
||||
// action=html
|
||||
fxt.Test__parse("/en.wikipedia.org/wiki/Page_1?action=html", fxt.Make().Wiki_("en.wikipedia.org").Page_("Page_1").Action_(Xopg_page_.Tid_html));
|
||||
|
||||
// action=N/A
|
||||
fxt.Test__parse("/en.wikipedia.org/wiki/Page_1?action=a", fxt.Make().Wiki_("en.wikipedia.org").Page_("Page_1?action=a"));
|
||||
|
||||
// fail: null
|
||||
fxt.Test__parse(null, fxt.Make().Err_msg_("invalid url; url is null; url="));
|
||||
|
||||
// fail: empty
|
||||
fxt.Test__parse("", fxt.Make().Err_msg_("invalid url; url is empty; url="));
|
||||
|
||||
// fail: missing '/' at start
|
||||
fxt.Test__parse("en.wikipedia.org", fxt.Make().Err_msg_("invalid url; must start with '/'; url=en.wikipedia.org"));
|
||||
|
||||
// fail: missing '/wiki/'
|
||||
fxt.Test__parse("/en.wikipedia.org/Page_1", fxt.Make().Err_msg_("invalid url; must have '/wiki/' after wiki_domain; url=/en.wikipedia.org/Page_1"));
|
||||
}
|
||||
}
|
||||
class Http_url_parser_fxt {
|
||||
private final Gfo_url_encoder url_encoder = Gfo_url_encoder_.New__http_url().Make();
|
||||
public Http_url_parser Make() {return new Http_url_parser(url_encoder);}
|
||||
public void Test__parse(String url, Http_url_parser expd) {
|
||||
Http_url_parser actl = new Http_url_parser(url_encoder);
|
||||
actl.Parse(url == null ? null : Bry_.new_u8(url));
|
||||
Gftest.Eq__ary__lines(expd.To_str(), actl.To_str());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user