1
0
mirror of https://github.com/gnosygnu/xowa.git synced 2026-03-02 03:49:30 +00:00

Embeddable: Create core dbs in proper subdirectory

This commit is contained in:
gnosygnu
2017-10-23 20:50:50 -04:00
parent 1336d44f34
commit 66877212bf
4537 changed files with 311750 additions and 0 deletions

View File

@@ -13,3 +13,22 @@ 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.*;
class File_retrieve_mode {
public static String Xto_str(byte v) {
switch (v) {
case Mode_skip: return "skip";
case Mode_wait: return "wait";
case Mode_async_server: return "async_server";
default: throw Err_.new_unimplemented();
}
}
public static byte Xto_byte(String s) {
if (String_.Eq(s, "skip")) return Mode_skip;
else if (String_.Eq(s, "wait")) return Mode_wait;
else if (String_.Eq(s, "async_server")) return Mode_async_server;
else throw Err_.new_unimplemented();
}
public static final byte Mode_skip = 1, Mode_wait = 2, Mode_async_server = 3;
public static Keyval[] Options__list = Keyval_.Ary(Keyval_.new_("wait"), Keyval_.new_("skip"), Keyval_.new_("async_server", "async server"));
}

View File

@@ -13,3 +13,13 @@ 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.jsons.*;
public class Http_data__client {
public Http_data__client(byte[] server_host, String ip_address_str) {
this.server_host = server_host;
this.ip_address = Bry_.new_a7(ip_address_str);
}
public byte[] Server_host() {return server_host;} private final byte[] server_host;
public byte[] Ip_address() {return ip_address;} private final byte[] ip_address;
}

View File

@@ -13,3 +13,36 @@ 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.xowa.files.*;
class Http_file_utl {
public static byte[] To_mime_type_by_path_as_bry(byte[] path_bry) {
int dot_pos = Bry_find_.Find_bwd(path_bry, Byte_ascii.Dot);
return dot_pos == Bry_find_.Not_found ? Mime_octet_stream : To_mime_type_by_ext_as_bry(path_bry, dot_pos, path_bry.length);
}
public static byte[] To_mime_type_by_ext_as_bry(byte[] ext_bry, int bgn, int end) {
Object o = mime_hash.Get_by_mid(ext_bry, bgn, end);
return o == null ? Mime_octet_stream : (byte[])o;
}
private static final byte[]
Mime_octet_stream = Xof_ext_.Mime_type__ary[Xof_ext_.Id_unknown]
, Mime_html = Bry_.new_a7("text/html")
, Mime_css = Bry_.new_a7("text/css")
, Mime_js = Bry_.new_a7("application/javascript")
;
private static final Hash_adp_bry mime_hash = Mime_hash__new();
private static Hash_adp_bry Mime_hash__new() {
Hash_adp_bry rv = Hash_adp_bry.ci_a7();
int len = Xof_ext_.Id__max;
for (int i = 0; i < len; ++i) {
rv.Add_bry_obj
( Bry_.Add(Byte_ascii.Dot, Xof_ext_.Bry__ary[i])
, Xof_ext_.Mime_type__ary[i]);
}
rv.Add_str_obj(".htm" , Mime_html);
rv.Add_str_obj(".html" , Mime_html);
rv.Add_str_obj(".css" , Mime_css);
rv.Add_str_obj(".js" , Mime_js);
return rv;
}
}

View File

@@ -13,3 +13,144 @@ 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
*/
/*
This file is part of XOWA: the XOWA Offline Wiki Application
Copyright (C) 2013 matthiasjasny@gmail.com; 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 following files:
GPLv3 License: LICENSE-GPLv3.txt
Apache License: 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.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.*;
public class Http_server_mgr implements Gfo_invk {
private final Object thread_lock = new Object();
private final Gfo_usr_dlg usr_dlg;
private Http_server_socket wkr;
private byte retrieve_mode = File_retrieve_mode.Mode_wait;
private boolean running, init_gui_needed = true;
public Http_server_mgr(Xoae_app app) {
this.app = app;
this.usr_dlg = app.Usr_dlg();
this.request_parser = new Http_request_parser(server_wtr, false);
}
public Xoae_app App() {return app;} private final Xoae_app app;
public Http_server_wtr Server_wtr() {return server_wtr;} private final Http_server_wtr server_wtr = Http_server_wtr_.New__console();
public Http_request_parser Request_parser() {return request_parser;} private final Http_request_parser request_parser;
public Gfo_url_encoder Encoder() {return encoder;} private final Gfo_url_encoder encoder = Gfo_url_encoder_.New__http_url().Make();
public int Port() {return port;}
public Http_server_mgr Port_(int v, boolean caller_is_cfg) {
if ( caller_is_cfg
&& v == Port__default // new_val == 8080
&& port != Port__default) {// cur_val != 8080
return this; // exit; do not override command-line value with cfg_value
}
port = v;
return this;
} private int port = Port__default;
public Http_server_wkr_pool Wkr_pool() {return wkr_pool;} private final Http_server_wkr_pool wkr_pool = new Http_server_wkr_pool();
public Int_pool Uid_pool() {return uid_pool;} private final Int_pool uid_pool = new Int_pool();
public byte[] Home() {return home;} public void Home_(byte[] v) {home = Bry_.Add(Byte_ascii.Slash_bry, v);} private byte[] home = Bry_.new_a7("/home/wiki/Main_Page");
private void Running_(boolean val) {
if (val) {
if (running)
Note("HTTP Server already started");
else {
Run();
}
}
else {
if (running) {
wkr.Canceled_(true);
wkr = null;
Note("HTTP Server stopped");
}
else
Note("HTTP Server not started");
}
running = val;
}
public void Run() {
app.Cfg().Bind_many_app(this, Cfg__port, Cfg__file_retrieve_mode);
if (wkr == null) wkr = new Http_server_socket(this);
Thread_adp_.Start_by_key("thread:xowa.http_server.server", wkr, Http_server_socket.Invk_run);
Note("HTTP Server started: Navigate to http://localhost:" + Int_.To_str(port));
}
public void Run_xowa_cmd(Xoae_app app, String url_encoded_str) {
Gfo_url_encoder url_converter = Gfo_url_encoder_.New__http_url().Make(); // create instance for each call
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) {
synchronized (thread_lock) {
// create a shim gui to automatically handle default XOWA gui JS calls
if (init_gui_needed) {
init_gui_needed = false;
Gxw_html_server.Init_gui_for_server(app, null);
}
// 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);
Xoa_ttl ttl = Xoa_ttl.Parse(wiki, url.To_bry_page_w_anch()); // changed from ttl_bry to page_w_anch; DATE:2017-07-24
// get the page
gplx.xowa.guis.views.Xog_tab_itm tab = Gxw_html_server.Assert_tab2(app, wiki); // HACK: assert tab exists
Xoae_page page = wiki.Page_mgr().Load_page(url, ttl, tab);
app.Gui_mgr().Browser_win().Active_page_(page); // HACK: init gui_mgr's page for output (which server ordinarily doesn't need)
if (page.Db().Page().Exists_n()) { // if page does not exist, replace with message; else null_ref error; DATE:2014-03-08
page.Db().Text().Text_bry_(Bry_.new_a7("'''Page not found.'''"));
wiki.Parser_mgr().Parse(page, false);
}
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
boolean rebuild_html = false;
switch (retrieve_mode) {
case File_retrieve_mode.Mode_skip: // noop
break;
case File_retrieve_mode.Mode_async_server:
rebuild_html = true;
app.Gui_mgr().Browser_win().Page__async__bgn(tab);
break;
case File_retrieve_mode.Mode_wait:
rebuild_html = true;
gplx.xowa.guis.views.Xog_async_wkr.Async(page, tab.Html_itm());
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));
return rv;
}
}
private void Note(String s) {
// usr_dlg.Prog_many("", "", s); // messages should write to progress bar for gui
usr_dlg.Note_many("", "", s);
}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Cfg__port)) Port_(m.ReadInt("v"), true);
else if (ctx.Match(k, Cfg__file_retrieve_mode)) retrieve_mode = File_retrieve_mode.Xto_byte(m.ReadStr("v"));
else if (ctx.Match(k, Invk_running_)) Running_(m.ReadYn("v"));
else return Gfo_invk_.Rv_unhandled;
return this;
}
private static final String Invk_running_ = "running_";
private static final String
Cfg__port = "xowa.addon.http_server.port"
, Cfg__file_retrieve_mode = "xowa.addon.http_server.file_retrieve_mode";
private static final int Port__default = 8080;
}

View File

@@ -13,3 +13,50 @@ 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.core.net.*; import gplx.core.threads.*; import gplx.core.primitives.*;
class Http_server_socket implements Gfo_invk {
private final Http_server_mgr server_mgr;
private Server_socket_adp server_socket;
public Http_server_socket(Http_server_mgr server_mgr) {this.server_mgr = server_mgr;}
public boolean Canceled() {return canceled;}
public Http_server_socket Canceled_(boolean v) {
canceled = v;
if (canceled) {
server_socket.Rls();
server_socket = null;
}
return this;
} private boolean canceled;
public void Run() {
if (server_socket == null) server_socket = new Server_socket_adp__base().Ctor(server_mgr.Port());
while (true) { // listen for incoming requests
Socket_adp client_socket = server_socket.Accept(); // NOTE: blocking call
int wkr_uid = -1; // NOTE: default to -1 to handle cases when http_server.max_clients is not set; DATE:2015-10-11
Http_server_wkr_pool wkr_pool = server_mgr.Wkr_pool();
if (wkr_pool.Enabled()) {
Http_server_wtr server_wtr = server_mgr.Server_wtr();
int timeout = wkr_pool.Timeout();
boolean print_msg = true;
while (wkr_pool.Full()) {
if (print_msg) {
print_msg = false;
server_wtr.Write_str_w_nl("maximum # of concurrent connections reached; max=" + wkr_pool.Max() + " timeout=" + timeout);
}
Thread_adp_.Sleep(timeout);
}
wkr_uid = server_mgr.Uid_pool().Get_next();
wkr_pool.Add(wkr_uid);
// server_wtr.Write_str_w_nl("added new worker; uid=" + wkr_uid);
}
Http_server_wkr wkr = new Http_server_wkr(server_mgr, wkr_uid);
wkr.Init_by_thread(client_socket);
Thread_adp_.Start_by_key("thread:xowa.http_server.client", wkr, Http_server_wkr.Invk_run);
}
}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_run)) this.Run();
else return Gfo_invk_.Rv_unhandled;
return this;
} public static final String Invk_run = "run";
}

View File

@@ -13,3 +13,171 @@ 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.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.*;
class Http_server_wkr implements Gfo_invk {
private final int uid;
private final Http_server_mgr server_mgr;
private final Http_server_wtr server_wtr;
private final Http_client_wtr client_wtr = Http_client_wtr_.new_stream();
private final Http_client_rdr client_rdr = Http_client_rdr_.new_stream();
private final Http_request_parser request_parser;
private final Gfo_url_encoder url_encoder;
private final Xoae_app app;
private final String root_dir_http;
private final byte[] root_dir_fsys;
private final Bry_bfr tmp_bfr = Bry_bfr_.New_w_size(64);
private Socket_adp socket;
private Http_data__client data__client;
public Http_server_wkr(Http_server_mgr server_mgr, int uid){
this.server_mgr = server_mgr; this.uid = uid;
this.app = server_mgr.App(); this.server_wtr = server_mgr.Server_wtr(); this.url_encoder = server_mgr.Encoder();
this.root_dir_http = app.Fsys_mgr().Root_dir().To_http_file_str();
this.root_dir_fsys = Bry_.new_u8(app.Fsys_mgr().Root_dir().Raw());
this.request_parser = server_mgr.Request_parser();
}
public void Init_by_thread(Socket_adp socket) {
this.socket = socket;
}
public void Run(){
Http_request_itm request = null;
try {
client_rdr.Stream_(socket.Get_input_stream());
client_wtr.Stream_(socket.Get_output_stream());
request = request_parser.Parse(client_rdr);
this.data__client = new Http_data__client(request.Host(), socket.Ip_address());
byte[] url_bry = request.Url();
if (Bry_.Eq(url_bry, Url__home)) url_bry = server_mgr.Home(); // "localhost:8080" comes thru as url of "/"; transform to custom home page; DATE:2015-10-11
switch (request.Type()) {
case Http_request_itm.Type_get: Process_get(request, url_bry); break;
case Http_request_itm.Type_post: Process_post(request); break;
}
client_wtr.Rls(); // client_rdr.Rls(); socket.Rls();
}
catch (Exception e) {
String request_str = request == null ? "<<NULL>>" : request.To_str(tmp_bfr, Bool_.N);
server_wtr.Write_str_w_nl(String_.Format("failed to process request;\nrequest={0}\nerr_msg={1}", request_str, Err_.Message_gplx_full(e)));
}
finally {
if (uid != -1) { // only release if uid was acquired; DATE:2015-10-11
server_mgr.Wkr_pool().Del(uid);
server_mgr.Uid_pool().Del(uid);
}
}
}
private void Process_get(Http_request_itm request, byte[] url) {
server_wtr.Write_str_w_nl(String_.new_u8(request.Host()) + "|GET|" + String_.new_u8(request.Url())); // use request url
if (Bry_.Has_at_bgn(url, Url__fsys)) Serve_file(url);
else if (Bry_.Has_at_bgn(url, Url__exec)) Exec_exec(url, Url__exec);
else if (Bry_.Has_at_bgn(url, Url__exec_2)) Exec_exec(url, Url__exec_2);
else Write_wiki(url);
}
private void Serve_file(byte[] url) {
tmp_bfr.Clear().Add(root_dir_fsys); // add "C:\xowa\"
int question_pos = Bry_find_.Find_fwd(url, Byte_ascii.Question);
int url_bgn = Bry_.Has_at_bgn(url, Url__fsys) ? Url__fsys_len : 0; // most files will have "/fsys/" at start, but Mathjax will not
int url_end = question_pos == Bry_find_.Not_found ? url.length : question_pos; // ignore files with query params; EX: /file/A.png?key=val
url_encoder.Decode(tmp_bfr, Bool_.N, url, url_bgn, url_end); // decode url to actual chars; note that XOWA stores on fsys in UTF-8 chars; "<22>" not "%C3"
byte[] path = tmp_bfr.To_bry_and_clear();
if (gplx.core.envs.Op_sys.Cur().Tid_is_wnt()) path = Bry_.Replace(path, Byte_ascii.Backslash, Byte_ascii.Slash);
client_wtr.Write_bry(Xosrv_http_wkr_.Rsp__http_ok);
// client_wtr.Write_str("Expires: Sun, 17-Jan-2038 19:14:07 GMT\n");
String mime_type = String_.new_u8(Http_file_utl.To_mime_type_by_path_as_bry(path));
client_wtr.Write_str("Content-Type: " + mime_type + "\n\n");
Io_stream_rdr file_stream = Io_stream_rdr_.New_by_url(Io_url_.new_fil_(String_.new_u8(path))).Open();
client_wtr.Write_stream(file_stream);
file_stream.Rls(); client_rdr.Rls(); socket.Rls();
}
private void Exec_exec(byte[] url, byte[] tkn_bgn) {
byte[] cmd = Bry_.Mid(url, tkn_bgn.length);
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];
}
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);
}
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) {
byte[] msg = request.Post_data_hash().Get_by(Key__msg).Val();
byte[] app_mode = request.Post_data_hash().Get_by(Key__app_mode).Val();
Xoa_app_mode app_mode_itm = Xoa_app_mode.parse(String_.new_u8(app_mode));
server_wtr.Write_str_w_nl(String_.new_u8(request.Host()) + "|POST|" + String_.new_u8(msg));
Object url_tid_obj = post_url_hash.Get_by_bry(request.Url()); if (url_tid_obj == null) throw Err_.new_wo_type("unknown url", "url", request.Url(), "request", request.To_str(tmp_bfr, Bool_.N));
String rv = null;
switch (((Int_obj_val)url_tid_obj).Val()) {
case Tid_post_url_json:
rv = app.Html__bridge_mgr().Cmd_mgr().Exec(msg);
break;
case Tid_post_url_gfs:
rv = Object_.Xto_str_strict_or_null_mark(app.Gfs_mgr().Run_str(String_.new_u8(msg)));
break;
}
if (app_mode_itm.Tid_is_http())
rv = Convert_page(rv, root_dir_http , "<<MISSING_WIKI>>");
Xosrv_http_wkr_.Write_response_as_html(client_wtr, app_mode_itm.Tid() == Xoa_app_mode.Itm_file.Tid(), rv);
}
private static final byte[] Key__msg = Bry_.new_a7("msg"), Key__app_mode = Bry_.new_a7("app_mode");
private static final int Tid_post_url_json = 1, Tid_post_url_gfs = 2;
private static final Hash_adp_bry post_url_hash = Hash_adp_bry.ci_a7()
.Add_str_int("/exec/json" , Tid_post_url_json)
.Add_str_int("/exec/gfs" , Tid_post_url_gfs)
;
private static String Convert_page(String page_html, String root_dir_http, String wiki_domain) {
page_html = String_.Replace(page_html, root_dir_http , "/fsys/");
page_html = String_.Replace(page_html, "xowa-cmd:" , "/exec/");
page_html = String_.Replace(page_html, "<a href=\"/wiki/" , "<a href=\"/" + wiki_domain + "/wiki/");
page_html = String_.Replace(page_html, "<a href='/wiki/" , "<a href='/" + wiki_domain + "/wiki/");
page_html = String_.Replace(page_html, "action=\"/wiki/" , "action=\"/" + wiki_domain + "/wiki/");
page_html = String_.Replace(page_html, "/site" , "");
return page_html;
}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_run)) {this.Run();}
else return Gfo_invk_.Rv_unhandled;
return this;
} public static final String Invk_run = "run";
private static final byte[]
Url__home = Bry_.new_a7("/"), Url__fsys = Bry_.new_a7("/fsys/")
, Url__exec = Bry_.new_a7("/exec/"), Url__exec_2 = Bry_.new_a7("/xowa-cmd:")
;
private static final int Url__fsys_len = Url__fsys.length;
}
class Xosrv_http_wkr_ {
public static void Write_response_as_html(Http_client_wtr client_wtr, boolean cross_domain, String html) {Write_response_as_html(client_wtr, cross_domain, Bry_.new_u8(html));}
public static void Write_response_as_html(Http_client_wtr client_wtr, boolean cross_domain, byte[] html) {
try{
// TODO_OLD: add command-line argument to allow testing from local file
// if (cross_domain)
// client_wtr.Write_str("Access-Control-Allow-Origin: *\n"); // No 'Access-Control-Allow-Origin' header is present on the requested resource.
client_wtr.Write_bry
( Bry_.Add
( Rsp__http_ok
, Rsp__content_type_html
, Byte_ascii.Nl_bry
, html
));
} catch (Exception err) {
client_wtr.Write_str("Site not found. Check address please, or see console log.\n" + Err_.Message_lang(err));
client_wtr.Rls();
}
}
public static final byte[]
Rsp__http_ok = Bry_.new_a7("HTTP/1.1 200 OK:\n")
, Rsp__content_type_html = Bry_.new_a7("Content-Type: text/html; charset=utf-8\n")
;
}

View File

@@ -13,3 +13,25 @@ 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.xowa.wikis.domains.*; import gplx.xowa.langs.*;
class Http_server_wkr_ {
public static String Assert_main_page(Xoae_app app, String req) {
int mode = -1;
String[] req_array = String_.Split(req, "/");
if (String_.Has_at_end(req, "wiki/")) mode = 0;
else if (String_.Has_at_end(req, "wiki")) mode = 1;
else if (req_array.length == 3) mode = 2;
if (mode == -1) return req; // not a link to a Main Page; EX:localhost:8080/en.wikipedia.org/wiki/Earth
if (req_array.length < 3) return req; // shouldn't happen; EX: "localhost:8080wiki"
byte[] wiki_domain = Bry_.new_u8(req_array[1]);
Xow_domain_itm domain_itm = Xow_domain_itm_.parse(wiki_domain);
if (domain_itm.Domain_type_id() == Xow_domain_tid_.Tid__other && domain_itm.Lang_actl_itm().Id() == Xol_lang_stub_.Id__intl) return req;
Xowe_wiki wiki = app.Wiki_mgr().Get_by_or_make(wiki_domain);
wiki.Init_assert();
String main_page = String_.new_u8(wiki.Props().Main_page());
if (mode == 1) main_page = "/" + main_page;
else if (mode == 2) main_page = "wiki/" + main_page;
return req + main_page;
}
}

View File

@@ -13,3 +13,28 @@ 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.*;
public class Http_server_wkr__tst {
@Before public void init() {fxt.Clear();} private Http_server_wkr__fxt fxt = new Http_server_wkr__fxt();
@Test public void Assert_main_page() {
fxt.Init_wiki_main_page("fr.wikiversity.org", "Accueil");
fxt.Test_assert_main_page("/fr.wikiversity.org/" , "/fr.wikiversity.org/wiki/Accueil");
fxt.Test_assert_main_page("/fr.wikiversity.org/wiki" , "/fr.wikiversity.org/wiki/Accueil");
fxt.Test_assert_main_page("/fr.wikiversity.org/wiki/" , "/fr.wikiversity.org/wiki/Accueil");
fxt.Test_assert_main_page("/fr.wikiversity.org/wiki/A" , "/fr.wikiversity.org/wiki/A");
}
}
class Http_server_wkr__fxt {
private Xoae_app app;
public void Clear() {
this.app = Xoa_app_fxt.Make__app__edit();
}
public void Init_wiki_main_page(String domain, String main_page) {
Xowe_wiki wiki = app.Wiki_mgr().Get_by_or_make(Bry_.new_u8(domain));
wiki.Props().Main_page_(Bry_.new_u8(main_page));
}
public void Test_assert_main_page(String url, String expd) {
Tfds.Eq(expd, Http_server_wkr_.Assert_main_page(app, url));
}
}

View File

@@ -13,3 +13,29 @@ 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.core.primitives.*;
public class Http_server_wkr_pool {
private final Ordered_hash hash = Ordered_hash_.New(); private final Int_obj_ref hash_key = Int_obj_ref.New_neg1();
public boolean Enabled() {return max != 0;}
public int Max() {return max;} private int max;
public int Timeout() {return timeout;} private int timeout;
public int Len() {return len;} private int len;
public boolean Full() {return len >= max;}
public void Init(int max, int timeout) {this.max = max; this.timeout = timeout;}
public void Add(int uid) {
if (max == 0) return; // disabled
synchronized (hash) {
Int_obj_ref wkr_key = Int_obj_ref.New(uid);
hash.Add(wkr_key, wkr_key);
++len;
}
}
public void Del(int uid) {
if (max == 0) return; // disabled
synchronized (hash) {
hash.Del(hash_key.Val_(uid));
--len;
}
}
}