1
0
mirror of https://github.com/gnosygnu/xowa.git synced 2024-10-27 20:34:16 +00:00

v1.10.3.1

This commit is contained in:
gnosygnu 2014-10-20 00:38:50 -04:00
parent d6561b3c1f
commit 7d8984f6a8
58 changed files with 654 additions and 441 deletions

View File

@ -30,6 +30,6 @@ public class Html_entity_ {
, Pipe_bry = Bry_.new_ascii_("|")
, Colon_bry = Bry_.new_ascii_(":"), Underline_bry = Bry_.new_ascii_("_"), Asterisk_bry = Bry_.new_ascii_("*")
, Brack_bgn_bry = Bry_.new_ascii_("["), Brack_end_bry = Bry_.new_ascii_("]")
, Nbsp_bry = Bry_.new_ascii_(" ")
, Nbsp_num_bry = Bry_.new_ascii_(" ")
;
}

View File

@ -41,6 +41,7 @@ public class Html_tag_ {
, Script_lhs = Bry_.new_ascii_("<script>")
, Script_lhs_w_type = Bry_.new_ascii_("<script type='text/javascript'>")
, Script_rhs = Bry_.new_ascii_("</script>")
, Span_rhs = Bry_.new_ascii_("</span>")
;
public static final String

View File

@ -24,7 +24,7 @@ public class Xoa_app_ {
boot_mgr.Run(args);
}
public static final String Name = "xowa";
public static final String Version = "1.10.2.1";
public static final String Version = "1.10.3.1";
public static String Build_date = "2012-12-30 00:00:00";
public static String Op_sys;
public static String User_agent = "";

View File

@ -21,7 +21,7 @@ public class Xoapi_net implements GfoInvkAble, GfoEvObj {
public GfoEvMgr EvMgr() {return ev_mgr;} private GfoEvMgr ev_mgr;
public void Init_by_kit(Xoa_app app) {
}
public boolean Enabled() {return enabled;} private boolean enabled;
public boolean Enabled() {return enabled;} private boolean enabled = true;
public void Enabled_(boolean v) {
this.enabled = v;
gplx.ios.IoEngine_system.Web_access_enabled = v;

View File

@ -60,7 +60,7 @@ public class Xob_cmd_mgr implements GfoInvkAble {
else if (String_.Eq(cmd_key, Xob_page_regy_cmd.KEY_oimg)) return Add(new Xob_page_regy_cmd(bldr, wiki));
else if (String_.Eq(cmd_key, Xob_cmd_exec_sql.KEY)) return Add(new Xob_cmd_exec_sql(bldr, wiki));
else if (String_.Eq(cmd_key, Xob_wiki_redirect_cmd.KEY_redirect)) return Add(new Xob_wiki_redirect_cmd(bldr, wiki));
else if (String_.Eq(cmd_key, Xob_redirect_cmd.KEY_redirect)) return Add(new Xob_redirect_cmd(bldr, wiki));
else if (String_.Eq(cmd_key, Xob_wiki_image_sql.KEY)) return Add(new Xob_wiki_image_sql(bldr, wiki));
else if (String_.Eq(cmd_key, Xob_fsdb_make.KEY_oimg)) return Add(new Xob_fsdb_make(bldr, wiki));

View File

@ -30,7 +30,7 @@ public class Xob_lnki_temp_wkr extends Xob_dump_mgr_base implements Xop_lnki_log
private Xob_hdump_bldr hdump_bldr; private long hdump_max = Io_mgr.Len_gb;
public Xob_lnki_temp_wkr(Xob_bldr bldr, Xow_wiki wiki) {this.Cmd_ctor(bldr, wiki);}
@Override public String Cmd_key() {return KEY_oimg;} public static final String KEY_oimg = "file.lnki_temp";
@Override public byte Init_redirect() {return Bool_.N_byte;} // lnki will never be found in a redirect
@Override public byte Init_redirect() {return Bool_.N_byte;}
@Override public int[] Init_ns_ary() {return ns_ids;}
@Override protected void Init_reset(Db_provider p) {
p.Exec_sql("DELETE FROM " + Xodb_xowa_cfg_tbl.Tbl_name);
@ -40,8 +40,8 @@ public class Xob_lnki_temp_wkr extends Xob_dump_mgr_base implements Xop_lnki_log
}
@Override protected Db_provider Init_db_file() {
ctx.Lnki().File_wkr_(this);
Xodb_db_file db_file = Xodb_db_file.init__file_make(wiki.Fsys_mgr().Root_dir());
provider = db_file.Provider();
Xodb_db_file make_db_file = Xodb_db_file.init__file_make(wiki.Fsys_mgr().Root_dir());
provider = make_db_file.Provider();
Xob_lnki_temp_tbl.Create_table(provider);
stmt = Xob_lnki_temp_tbl.Insert_stmt(provider);
return provider;
@ -68,7 +68,9 @@ public class Xob_lnki_temp_wkr extends Xob_dump_mgr_base implements Xop_lnki_log
Fsdb_mnt_mgr trg_mnt_mgr = trg_fsdb_mgr.Mnt_mgr();
trg_mnt_mgr.Insert_to_mnt_(Fsdb_mnt_mgr.Mnt_idx_main);
Fsdb_mnt_mgr.Patch(trg_mnt_mgr); // NOTE: see fsdb_make; DATE:2014-04-26
if (gen_hdump) hdump_bldr = new Xob_hdump_bldr(wiki, provider, hdump_max);
if (gen_hdump) {
hdump_bldr = new Xob_hdump_bldr(wiki, provider, hdump_max);
}
provider.Txn_mgr().Txn_bgn_if_none();
log_mgr.Txn_bgn();
}
@ -88,6 +90,7 @@ public class Xob_lnki_temp_wkr extends Xob_dump_mgr_base implements Xop_lnki_log
parser.Parse_page_all_clear(root, ctx, ctx.Tkn_mkr(), page_src);
if (gen_html) {
page.Root_(root);
if (!page.Redirected())
wiki.Html_mgr().Page_wtr_mgr().Gen(ctx.Cur_page(), Xopg_view_mode.Tid_read);
}
if (gen_hdump) {

View File

@ -25,14 +25,8 @@ public class Xob_import_marker {
if (!Io_mgr._.ExistsFil(url)) return true;
Xoa_app app = wiki.App();
app.Usr_dlg().Log_many("", "", "import.marker: marker found: url=~{0}", url.Raw());
int rslt = app.Gui_mgr().Kit().Ask_yes_no_cancel("", "", String_.Concat_lines_nl
( "~{0} was not completely imported."
, "Please choose one of the following:"
, ""
, "* Yes\t: Delete the wiki. You will need to reimport again."
, "* No\t: Delete the warning. XOWA will continue, but may run into unexpected issues."
, "* Cancel\t: Do nothing and continue. This message will show whenever you restart the app and reopen this wiki."
), wiki.Domain_str());
byte[] incompete_msg_bry = app.User().Msg_mgr().Val_by_key_args(Bry_.new_ascii_("api-xowa.import.core.incomplete"), wiki.Domain_str());
int rslt = app.Gui_mgr().Kit().Ask_yes_no_cancel("", "", String_.new_utf8_(incompete_msg_bry));
switch (rslt) {
case Gfui_dlg_msg_.Btn_yes: Xobc_core_cleanup.Delete_wiki_sql(wiki); Import_end(wiki); return false; // delete wiki
case Gfui_dlg_msg_.Btn_no: Import_end(wiki); return true; // delete marker

View File

@ -16,13 +16,14 @@ You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.bldrs.imports; import gplx.*; import gplx.xowa.*; import gplx.xowa.bldrs.*;
import gplx.dbs.*; import gplx.xowa.dbs.*; import gplx.xowa.dbs.tbls.*; import gplx.ios.*;
import gplx.dbs.*; import gplx.xowa.dbs.*; import gplx.xowa.dbs.tbls.*; import gplx.ios.*; import gplx.xowa.bldrs.wikis.redirects.*;
public class Xob_page_sql extends Xob_itm_basic_base implements Xobd_wkr, GfoInvkAble {
private Db_idx_mode idx_mode = Db_idx_mode.Itm_end;
private Xop_redirect_mgr redirect_mgr; private Io_stream_zip_mgr zip_mgr; private byte data_storage_format;
private Io_stream_zip_mgr zip_mgr; private byte data_storage_format; private boolean redirect_id_enabled;
private Xodb_mgr_sql db_mgr; private Xodb_fsys_mgr fsys_mgr; private Db_provider page_provider; private Db_stmt page_stmt; private Xob_text_stmts_mgr text_stmts_mgr;
private int page_count_all, page_count_main = 0; private int txn_commit_interval = 100000; // 100 k
private DateAdp modified_latest = DateAdp_.MinValue;
private Xop_redirect_mgr redirect_mgr; private Xob_redirect_tbl redirect_tbl;
public Xob_page_sql(Xob_bldr bldr, Xow_wiki wiki) {this.Cmd_ctor(bldr, wiki);}
public String Wkr_key() {return KEY;} public static final String KEY = "import.sql.page";
public void Wkr_bgn(Xob_bldr bldr) {
@ -42,6 +43,11 @@ public class Xob_page_sql extends Xob_itm_basic_base implements Xobd_wkr, GfoInv
page_provider.Txn_mgr().Txn_bgn_if_none();
text_stmts_mgr = new Xob_text_stmts_mgr(db_mgr, fsys_mgr);
if (idx_mode.Tid_is_bgn()) Idx_create();
if (redirect_id_enabled) {
redirect_tbl = new Xob_redirect_tbl(wiki.Fsys_mgr().Root_dir(), app.Encoder_mgr().Url_ttl()).Create_table();
redirect_tbl.Provider().Txn_mgr().Txn_bgn_if_none();
}
}
public void Wkr_run(Xodb_page page) {
int page_id = page.Id();
@ -66,6 +72,9 @@ public class Xob_page_sql extends Xob_itm_basic_base implements Xobd_wkr, GfoInv
page_stmt.New(); // must new stmt variable, else java.sql.SQLException: "statement is not executing"
text_stmt.New(); // must new stmt variable, else java.sql.SQLException: "statement is not executing"
}
if (redirect && redirect_id_enabled) {
redirect_tbl.Insert(page_id, page.Ttl_wo_ns(), redirect_ttl);
}
++page_count_all;
if (ns.Id_main() && !page.Type_redirect()) ++page_count_main;
if (page_count_all % txn_commit_interval == 0) text_stmt.Provider().Txn_mgr().Txn_end_all_bgn_if_none();
@ -82,6 +91,12 @@ public class Xob_page_sql extends Xob_itm_basic_base implements Xobd_wkr, GfoInv
db_mgr.Tbl_xowa_db().Commit_all(page_provider, db_mgr.Fsys_mgr().Files_ary()); // save dbs; note that dbs can be saved again later
db_mgr.Tbl_xowa_cfg().Insert_str(Xodb_mgr_sql.Grp_wiki_init, "props.modified_latest", modified_latest.XtoStr_fmt(DateAdp_.Fmt_iso8561_date_time));
if (idx_mode.Tid_is_end()) Idx_create();
if (redirect_id_enabled) {
redirect_tbl.Provider().Txn_mgr().Txn_end_all();
Xodb_file core_file = fsys_mgr.Get_tid_root(Xodb_file_tid.Tid_core);
redirect_tbl.Update_trg_redirect_id(core_file.Url(), 1);
redirect_tbl.Update_src_redirect_id(core_file.Url(), page_provider);
}
}
private void Idx_create() {
fsys_mgr.Index_create(usr_dlg, Byte_.Ary(Xodb_file_tid.Tid_core, Xodb_file_tid.Tid_text), Idx_page_title, Idx_page_random);
@ -89,10 +104,11 @@ public class Xob_page_sql extends Xob_itm_basic_base implements Xobd_wkr, GfoInv
@Override public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_txn_commit_interval_)) txn_commit_interval = m.ReadInt("v");
else if (ctx.Match(k, Invk_idx_mode_)) idx_mode = Db_idx_mode.Xto_itm(m.ReadStr("v"));
else if (ctx.Match(k, Invk_redirect_id_enabled_)) redirect_id_enabled = m.ReadYn("v");
else return super.Invk(ctx, ikey, k, m);
return this;
}
private static final String Invk_txn_commit_interval_ = "txn_commit_interval_", Invk_idx_mode_ = "idx_mode_";
private static final String Invk_txn_commit_interval_ = "txn_commit_interval_", Invk_idx_mode_ = "idx_mode_", Invk_redirect_id_enabled_ = "redirect_id_enabled_";
public void Wkr_ini(Xob_bldr bldr) {}
public void Wkr_print() {}
private static final Db_idx_itm
@ -155,5 +171,5 @@ class Xob_text_stmts_mgr {
}
text_stmts[stmt_idx] = stmt;
text_stmts_len = new_len;
} Db_stmt[] text_stmts = new Db_stmt[0]; int text_stmts_len, text_stmts_max = 0;
} private Db_stmt[] text_stmts = new Db_stmt[0]; int text_stmts_len, text_stmts_max = 0;
}

View File

@ -24,6 +24,7 @@ public class Xob_category_registry_sql implements Xob_cmd {
public void Cmd_bgn(Xob_bldr bldr) {}
public void Cmd_run() {}
public void Cmd_end() { // NOTE: placing in end, b/c must run *after* page_sql
wiki.Html_mgr().Importing_ctgs_(Bool_.Y);
Io_url rslt_dir = Xob_category_registry_sql.Get_dir_output(wiki);
Io_mgr._.DeleteDirDeep(rslt_dir);
Xob_tmp_wtr rslt_wtr = Xob_tmp_wtr.new_wo_ns_(Io_url_gen_.dir_(rslt_dir), Io_mgr.Len_mb);
@ -47,6 +48,7 @@ public class Xob_category_registry_sql implements Xob_cmd {
}
} finally {rdr.Rls();}
rslt_wtr.Flush(usr_dlg);
wiki.Html_mgr().Importing_ctgs_(Bool_.N);
}
public void Cmd_print() {}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {

View File

@ -22,6 +22,7 @@ public abstract class Xob_categorylinks_base extends Xob_sql_dump_base implement
@Override public String Sql_file_name() {return "categorylinks";}
@Override public void Cmd_bgn_hook(Xob_bldr bldr, Sql_file_parser parser) {
this.sql_parser = parser;
wiki.Html_mgr().Importing_ctgs_(Bool_.Y);
parser.Fld_cmd_(this).Flds_req_(Fld_cl_from, Fld_cl_to, Fld_cl_timestamp, Fld_cl_collation, Fld_cl_sortkey, Fld_cl_type);
} static final byte[] Fld_cl_from = Bry_.new_ascii_("cl_from"), Fld_cl_to = Bry_.new_ascii_("cl_to"), Fld_cl_timestamp = Bry_.new_ascii_("cl_timestamp"), Fld_cl_collation = Bry_.new_ascii_("cl_collation"), Fld_cl_sortkey = Bry_.new_ascii_("cl_sortkey"), Fld_cl_type = Bry_.new_ascii_("cl_type");
public void Exec(byte[] src, byte[] fld_key, int fld_idx, int fld_bgn, int fld_end, Bry_bfr file_bfr, Sql_file_parser_data data) {
@ -65,6 +66,7 @@ public abstract class Xob_categorylinks_base extends Xob_sql_dump_base implement
} int cur_id = -1, cur_date = -1; byte[] cur_ctg = null, cur_sortkey = null; byte cur_tid = Byte_.MaxValue_127; boolean cur_collation_is_uca; int[] cur_modified_on = new int[7];
@Override public void Cmd_end() {
Xobdc_merger.Basic(bldr.Usr_dlg(), dump_url_gen, temp_dir.GenSubDir("sort"), sort_mem_len, Xoctg_link_sql_sorter._, Io_line_rdr_key_gen_.noop, Make_sort_cmd(sql_parser));
wiki.Html_mgr().Importing_ctgs_(Bool_.N);
}
DateAdp_parser date_parser = DateAdp_parser.new_(); Sql_file_parser sql_parser; Uca_trie trie; Bry_bfr uca_bfr = Bry_bfr.reset_(255);
private static final byte[] Collation_uca = Bry_.new_utf8_("uca"), Sortkey_space = new byte[] {Byte_ascii.Space};

View File

@ -17,47 +17,41 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.bldrs.wikis.redirects; import gplx.*; import gplx.xowa.*; import gplx.xowa.bldrs.*; import gplx.xowa.bldrs.wikis.*;
import gplx.dbs.*; import gplx.xowa.dbs.*; import gplx.xowa.dbs.tbls.*; import gplx.xowa.bldrs.oimgs.*;
public class Xob_wiki_redirect_cmd extends Xob_dump_mgr_base {
private Db_provider provider; private Db_stmt stmt;
private Xob_wiki_redirect_tbl tbl_redirect;
public class Xob_redirect_cmd extends Xob_dump_mgr_base {
private Db_provider provider; private Xob_redirect_tbl redirect_tbl;
private Xodb_mgr_sql db_mgr; private Xop_redirect_mgr redirect_mgr; private Url_encoder encoder;
public Xob_wiki_redirect_cmd(Xob_bldr bldr, Xow_wiki wiki) {this.Cmd_ctor(bldr, wiki);}
public Xob_redirect_cmd(Xob_bldr bldr, Xow_wiki wiki) {this.Cmd_ctor(bldr, wiki);}
@Override public String Cmd_key() {return KEY_redirect;} public static final String KEY_redirect = "wiki.redirect";
@Override public int[] Init_ns_ary() {return Int_.Ary(Xow_ns_.Id_file);} // restrict to file ns
@Override public byte Init_redirect() {return Bool_.Y_byte;} // restrict to redirects
@Override protected void Init_reset(Db_provider p) {
p.Exec_sql("DELETE FROM " + Xodb_xowa_cfg_tbl.Tbl_name);
p.Exec_sql("DELETE FROM " + Xob_wiki_redirect_tbl.Tbl_name);
p.Exec_sql("DELETE FROM " + Xob_redirect_tbl.Tbl_name);
}
@Override protected Db_provider Init_db_file() {
this.db_mgr = wiki.Db_mgr_as_sql();
Xoa_app app = bldr.App();
redirect_mgr = wiki.Redirect_mgr();
encoder = app.Encoder_mgr().Url_ttl();
// app.Usr_dlg().Prog_none("", "", "dropping index: page__title");
// db_mgr.Fsys_mgr().Core_provider().Exec_sql("DROP INDEX IF EXISTS page__title");
// Sqlite_engine_.Idx_create(app.Usr_dlg(), db_mgr.Fsys_mgr().Core_provider(), "page", Idx_page_title);
Xodb_db_file db_file = Xodb_db_file.init__wiki_redirect(wiki.Fsys_mgr().Root_dir());
provider = db_file.Provider();
tbl_redirect = new Xob_wiki_redirect_tbl().Create_table(provider);
stmt = tbl_redirect.Insert_stmt(provider);
redirect_tbl = new Xob_redirect_tbl(wiki.Fsys_mgr().Root_dir(), app.Encoder_mgr().Url_ttl()).Create_table();
provider = redirect_tbl.Provider();
provider.Txn_mgr().Txn_bgn_if_none();
return provider;
}
@Override protected void Cmd_bgn_end() {}
@Override public void Exec_pg_itm_hook(Xow_ns ns, Xodb_page page, byte[] page_src) {
Xoa_ttl redirect_ttl = redirect_mgr.Extract_redirect(page_src, page_src.length);
byte[] redirect_ttl_bry = Xoa_ttl.Replace_spaces(redirect_ttl.Page_db()); // NOTE: spaces can still exist b/c redirect is scraped from #REDIRECT which sometimes has a mix; EX: "A_b c"
redirect_ttl_bry = encoder.Decode(redirect_ttl_bry);
tbl_redirect.Insert(stmt, page.Id(), Xoa_ttl.Replace_spaces(page.Ttl_wo_ns()), -1, redirect_ttl.Ns().Id(), redirect_ttl_bry, redirect_ttl.Anch_txt(), 1);
redirect_tbl.Insert(page.Id(), Xoa_ttl.Replace_spaces(page.Ttl_wo_ns()), -1, redirect_ttl.Ns().Id(), redirect_ttl_bry, redirect_ttl.Anch_txt(), 1);
}
@Override public void Exec_commit_hook() {
provider.Txn_mgr().Txn_end_all_bgn_if_none();
}
@Override public void Exec_end_hook() {
provider.Txn_mgr().Txn_end_all();
tbl_redirect.Create_indexes(usr_dlg, provider);
tbl_redirect.Update_redirects(provider, db_mgr.Fsys_mgr().Get_url(Xodb_file_tid.Tid_core), 4);
redirect_tbl.Create_indexes(usr_dlg);
redirect_tbl.Update_trg_redirect_id(db_mgr.Fsys_mgr().Get_url(Xodb_file_tid.Tid_core), 4);
}
// private static final Db_idx_itm Idx_page_title = Db_idx_itm.sql_("CREATE UNIQUE INDEX IF NOT EXISTS page__title ON page (page_namespace, page_title, page_id, page_len, page_is_redirect, page_file_idx);"); // PERF:page_id for general queries; PERF: page_len for search_suggest
}

View File

@ -0,0 +1,164 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.bldrs.wikis.redirects; import gplx.*; import gplx.xowa.*; import gplx.xowa.bldrs.*; import gplx.xowa.bldrs.wikis.*;
import gplx.dbs.*; import gplx.xowa.dbs.*; import gplx.xowa.bldrs.oimgs.*;
public class Xob_redirect_tbl {
private Url_encoder encoder; private Db_stmt insert_stmt;
public Xob_redirect_tbl(Io_url root_dir, Url_encoder encoder) {
this.db_file = Xodb_db_file.init__wiki_redirect(root_dir);
this.provider = db_file.Provider();
this.encoder = encoder;
}
public Xodb_db_file Db_file() {return db_file;} private Xodb_db_file db_file;
public Db_provider Provider() {return provider;} private Db_provider provider;
public Xob_redirect_tbl Create_table() {Sqlite_engine_.Tbl_create(provider, Tbl_name, Tbl_sql); return this;}
public void Create_indexes(Gfo_usr_dlg usr_dlg) {
Sqlite_engine_.Idx_create(usr_dlg, provider, Xodb_db_file.Name__wiki_redirect, Idx_trg_id, Idx_trg_ttl);
}
public void Update_trg_redirect_id(Io_url core_url, int max_redirected_depth) {
Sqlite_engine_.Db_attach(provider, "page_db", core_url.Raw()); // link database with page table
provider.Exec_sql(Sql_get_page_data); // fill in page_id, page_ns, page_is_redirect for trg_ttl; EX: Page_A has "#REDIRECT Page_B"; Page_B is in redirect tbl; find its id, ttl, redirect status
for (int i = 0; i < max_redirected_depth; i++) { // loop to find redirected redirects; note that it is bounded by depth (to guard against circular redirects)
int affected = provider.Exec_sql(Sql_get_redirect_redirects); // find redirects that are also redirects
if (affected == 0) break; // no more redirected redirects; stop
provider.Exec_sql(Sql_get_redirect_page_data); // get page data for redirects
}
Sqlite_engine_.Db_detach(provider, "page_db");
}
public void Update_src_redirect_id(Io_url core_url, Db_provider core_provider) {
core_provider.Exec_sql(Sql_ddl__page_redirect_id); // create page.page_redirect_id
Sqlite_engine_.Idx_create(provider, Idx_trg_src);
Sqlite_engine_.Db_attach(provider, "page_db", core_url.Raw()); // link database with page table
provider.Exec_sql(Sql_update_redirect_id); // update page_redirect_id
Sqlite_engine_.Db_detach(provider, "page_db");
}
public void Insert(int src_id, byte[] src_bry, Xoa_ttl trg_ttl) {
byte[] redirect_ttl_bry = Xoa_ttl.Replace_spaces(trg_ttl.Page_db()); // NOTE: spaces can still exist b/c redirect is scraped from #REDIRECT which sometimes has a mix; EX: "A_b c"
redirect_ttl_bry = encoder.Decode(redirect_ttl_bry);
this.Insert(src_id, Xoa_ttl.Replace_spaces(src_bry), -1, trg_ttl.Ns().Id(), redirect_ttl_bry, trg_ttl.Anch_txt(), 1);
}
public void Insert(int src_id, byte[] src_ttl, int trg_id, int trg_ns, byte[] trg_ttl, byte[] trg_anchor, int count) {
if (insert_stmt == null) insert_stmt = Db_stmt_.new_insert_(provider, Tbl_name, Fld_src_id, Fld_src_ttl, Fld_trg_id, Fld_trg_ns, Fld_trg_ttl, Fld_trg_anchor, Fld_trg_is_redirect, Fld_redirect_count);
insert_stmt.Clear()
.Val_int_(src_id)
.Val_str_by_bry_(src_ttl)
.Val_int_(trg_id)
.Val_int_(trg_ns)
.Val_str_by_bry_(trg_ttl)
.Val_str_by_bry_(trg_anchor)
.Val_byte_((byte)1)
.Val_int_(count)
.Exec_insert();
}
public void Rls_all() {
insert_stmt.Rls();
provider.Conn_term();
}
public static final String Tbl_name = "redirect";
private static final String
Fld_src_id = "src_id", Fld_src_ttl = "src_ttl", Fld_trg_id = "trg_id", Fld_trg_ns = "trg_ns", Fld_trg_ttl = "trg_ttl", Fld_trg_anchor = "trg_anchor"
, Fld_trg_is_redirect = "trg_is_redirect", Fld_redirect_count = "redirect_count";
private static final String Tbl_sql = String_.Concat_lines_nl
( "CREATE TABLE IF NOT EXISTS redirect"
, "( src_id integer NOT NULL PRIMARY KEY"
, ", src_ttl varchar(255) NOT NULL"
, ", trg_id integer NOT NULL"
, ", trg_ns integer NOT NULL"
, ", trg_ttl varchar(255) NOT NULL"
, ", trg_anchor varchar(255) NOT NULL"
, ", trg_is_redirect tinyint NOT NULL"
, ", redirect_count integer NOT NULL"
, ");"
);
private static final Db_idx_itm
Idx_trg_ttl = Db_idx_itm.sql_("CREATE INDEX IF NOT EXISTS redirect__trg_ttl ON redirect (trg_ttl);")
, Idx_trg_id = Db_idx_itm.sql_("CREATE INDEX IF NOT EXISTS redirect__trg_id ON redirect (trg_id);")
, Idx_trg_src = Db_idx_itm.sql_("CREATE INDEX IF NOT EXISTS redirect__trg_src ON redirect (src_id, trg_id);")
;
public static final String
Sql_ddl__page_redirect_id = "ALTER TABLE page ADD COLUMN page_redirect_id integer NOT NULL DEFAULT '-1'"
;
private static final String
Sql_get_page_data = String_.Concat_lines_nl // get data from page table for initial redirect dump
( "REPLACE INTO redirect "
, "SELECT t.src_id"
, ", t.src_ttl"
, ", j.page_id"
, ", t.trg_ns"
, ", t.trg_ttl"
, ", t.trg_anchor"
, ", j.page_is_redirect"
, ", t.redirect_count"
, "FROM redirect t"
, " JOIN page_db.page j "
, " ON t.trg_ns = j.page_namespace"
, " AND t.trg_ttl = j.page_title"
, " AND t.trg_is_redirect = 1 -- limit to redirects"
, ";"
)
, Sql_get_redirect_redirects = String_.Concat_lines_nl // find redirects that are redirected
( "REPLACE INTO redirect"
, "SELECT t.src_id"
, ", t.src_ttl"
, ", j.trg_id"
, ", -1"
, ", ''"
, ", ''"
, ", 1"
, ", t.redirect_count + 1"
, "FROM redirect t"
, " JOIN redirect j "
, " ON t.trg_id = j.src_id"
, " AND t.trg_is_redirect = 1"
, ";"
, ""
)
, Sql_get_redirect_page_data = String_.Concat_lines_nl // get data from page table for redirected redirects
( "REPLACE INTO redirect"
, "SELECT t.src_id"
, ", t.src_ttl"
, ", t.trg_id"
, ", j.page_namespace"
, ", j.page_title"
, ", t.trg_anchor"
, ", j.page_is_redirect"
, ", t.redirect_count"
, "FROM redirect t"
, " JOIN page_db.page j "
, " ON t.trg_id = j.page_id "
, " AND t.trg_is_redirect = 1 -- limit to redirects"
, ";"
)
, Sql_update_redirect_id = String_.Concat_lines_nl_skip_last
( "REPLACE INTO"
, " page_db.page"
, "SELECT p.page_id"
, ", p.page_namespace"
, ", p.page_title"
, ", p.page_is_redirect"
, ", p.page_touched"
, ", p.page_len"
, ", p.page_random_int"
, ", p.page_file_idx"
// , ", p.page_html_db_id"
, ", r.trg_id"
, "FROM redirect r"
, " JOIN page_db.page p ON r.src_id = p.page_id"
)
;
}

View File

@ -1,118 +0,0 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.bldrs.wikis.redirects; import gplx.*; import gplx.xowa.*; import gplx.xowa.bldrs.*; import gplx.xowa.bldrs.wikis.*;
import gplx.dbs.*; import gplx.xowa.dbs.*; import gplx.xowa.bldrs.oimgs.*;
class Xob_wiki_redirect_tbl {
public Xob_wiki_redirect_tbl Create_table(Db_provider p) {Sqlite_engine_.Tbl_create(p, Tbl_name, Tbl_sql); return this;}
public void Create_indexes(Gfo_usr_dlg usr_dlg, Db_provider p) {
Sqlite_engine_.Idx_create(usr_dlg, p, Xodb_db_file.Name__wiki_redirect, Idx_trg_id, Idx_trg_ttl);
}
public void Update_redirects(Db_provider p, Io_url core_url, int max_redirected_depth) {
Sqlite_engine_.Db_attach(p, "join_db", core_url.Raw()); // link database with page table
p.Exec_sql(Sql_get_page_data); // fill in page_id, page_ns, page_is_redirect for trg_ttl; EX: Page_A has "#REDIRECT Page_B"; Page_B is in redirect tbl; find its id, ttl, redirect status
for (int i = 0; i < max_redirected_depth; i++) { // loop to find redirected redirects; note that it is bounded by depth (to guard against circular redirects)
int affected = p.Exec_sql(Sql_get_redirect_redirects); // find redirects that are also redirects
if (affected == 0) break; // no more redirected redirects; stop
p.Exec_sql(Sql_get_redirect_page_data); // get page data for redirects
}
Sqlite_engine_.Db_detach(p, "join_db");
}
public Db_stmt Insert_stmt(Db_provider p) {return Db_stmt_.new_insert_(p, Tbl_name, Fld_src_id, Fld_src_ttl, Fld_trg_id, Fld_trg_ns, Fld_trg_ttl, Fld_trg_anchor, Fld_trg_is_redirect, Fld_redirect_count);}
public void Insert(Db_stmt stmt, int src_id, byte[] src_ttl, int trg_id, int trg_ns, byte[] trg_ttl, byte[] trg_anchor, int count) {
stmt.Clear()
.Val_int_(src_id)
.Val_str_by_bry_(src_ttl)
.Val_int_(trg_id)
.Val_int_(trg_ns)
.Val_str_by_bry_(trg_ttl)
.Val_str_by_bry_(trg_anchor)
.Val_byte_((byte)1)
.Val_int_(count)
.Exec_insert();
}
public static final String Tbl_name = "redirect"
, Fld_src_id = "src_id", Fld_src_ttl = "src_ttl", Fld_trg_id = "trg_id", Fld_trg_ns = "trg_ns", Fld_trg_ttl = "trg_ttl", Fld_trg_anchor = "trg_anchor"
, Fld_trg_is_redirect = "trg_is_redirect", Fld_redirect_count = "redirect_count";
private static final String Tbl_sql = String_.Concat_lines_nl
( "CREATE TABLE IF NOT EXISTS redirect"
, "( src_id integer NOT NULL PRIMARY KEY"
, ", src_ttl varchar(255) NOT NULL"
, ", trg_id integer NOT NULL"
, ", trg_ns integer NOT NULL"
, ", trg_ttl varchar(255) NOT NULL"
, ", trg_anchor varchar(255) NOT NULL"
, ", trg_is_redirect tinyint NOT NULL"
, ", redirect_count integer NOT NULL"
, ");"
);
private static final Db_idx_itm
Idx_trg_ttl = Db_idx_itm.sql_("CREATE INDEX IF NOT EXISTS redirect__trg_ttl ON redirect (trg_ttl);")
, Idx_trg_id = Db_idx_itm.sql_("CREATE INDEX IF NOT EXISTS redirect__trg_id ON redirect (trg_id);")
;
private static final String
Sql_get_page_data = String_.Concat_lines_nl // get data from page table for initial redirect dump
( "REPLACE INTO redirect "
, "SELECT t.src_id"
, ", t.src_ttl"
, ", j.page_id"
, ", t.trg_ns"
, ", t.trg_ttl"
, ", t.trg_anchor"
, ", j.page_is_redirect"
, ", t.redirect_count"
, "FROM redirect t"
, " JOIN join_db.page j "
, " ON t.trg_ns = j.page_namespace"
, " AND t.trg_ttl = j.page_title"
, " AND t.trg_is_redirect = 1 -- limit to redirects"
, ";"
)
, Sql_get_redirect_redirects = String_.Concat_lines_nl // find redirects that are redirected
( "REPLACE INTO redirect"
, "SELECT t.src_id"
, ", t.src_ttl"
, ", j.trg_id"
, ", -1"
, ", ''"
, ", ''"
, ", 1"
, ", t.redirect_count + 1"
, "FROM redirect t"
, " JOIN redirect j "
, " ON t.trg_id = j.src_id"
, " AND t.trg_is_redirect = 1"
, ";"
, ""
)
, Sql_get_redirect_page_data = String_.Concat_lines_nl // get data from page table for redirected redirects
( "REPLACE INTO redirect"
, "SELECT t.src_id"
, ", t.src_ttl"
, ", t.trg_id"
, ", j.page_namespace"
, ", j.page_title"
, ", t.trg_anchor"
, ", j.page_is_redirect"
, ", t.redirect_count"
, "FROM redirect t"
, " JOIN join_db.page j "
, " ON t.trg_id = j.page_id "
, " AND t.trg_is_redirect = 1 -- limit to redirects"
, ";"
);
}

View File

@ -19,14 +19,14 @@ package gplx.xowa.ctgs; import gplx.*; import gplx.xowa.*;
import gplx.xowa.dbs.*;
public class Xoctg_html_mgr implements GfoInvkAble {
@gplx.Internal protected Xoctg_fmtr_grp Fmtr_grp() {return fmtr_grp;} private Xoctg_fmtr_grp fmtr_grp = new Xoctg_fmtr_grp();
Xoctg_fmtr_all mgr_subcs = new Xoctg_fmtr_all(Xoa_ctg_mgr.Tid_subc);
Xoctg_fmtr_all mgr_pages = new Xoctg_fmtr_all(Xoa_ctg_mgr.Tid_page);
Xoctg_fmtr_all mgr_files = new Xoctg_fmtr_all(Xoa_ctg_mgr.Tid_file);
private final Xoctg_fmtr_all mgr_subcs = new Xoctg_fmtr_all(Xoa_ctg_mgr.Tid_subc);
private final Xoctg_fmtr_all mgr_pages = new Xoctg_fmtr_all(Xoa_ctg_mgr.Tid_page);
private final Xoctg_fmtr_all mgr_files = new Xoctg_fmtr_all(Xoa_ctg_mgr.Tid_file);
public Xoctg_data_cache Data_cache() {return data_cache;} private Xoctg_data_cache data_cache = new Xoctg_data_cache();
public void Bld_html(Xoa_page page, Bry_bfr bfr) {
Bry_bfr tmp_bfr = page.Wiki().Utl_bry_bfr_mkr().Get_m001();
try {
Xow_wiki wiki = page.Wiki();
Bry_bfr tmp_bfr = wiki.Utl_bry_bfr_mkr().Get_m001();
try {
if (wiki.Db_mgr().Category_version() == Xoa_ctg_mgr.Version_2)
Bld_html_v2(wiki, page, tmp_bfr);
else

View File

@ -87,6 +87,7 @@ public class Xodb_fsys_mgr {
int file_idx = files_ary_len;
Io_url url = Create_sqlite3(src_dir, trg_dir, wiki_name, file_idx);
Xodb_file rv = Xodb_file.make_(file_idx, file_tid, url.NameAndExt()).Connect_(Db_conn_info_.sqlite_(url));
rv.Url_(url);
Xodb_xowa_cfg_tbl.Insert_str(rv.Provider(), Cfg_grp_db_meta, "type_name", Xodb_file_tid.Xto_key(file_tid));
files_ary = (Xodb_file[])Array_.Resize(files_ary, files_ary_len + 1);
files_ary[files_ary_len++] = rv;

View File

@ -17,36 +17,26 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.gui.history; import gplx.*; import gplx.xowa.*; import gplx.xowa.gui.*;
public class Xog_history_itm {
public Xog_history_itm(Xoa_page page) {
this.wiki_key = page.Wiki().Domain_bry();
this.page_key = page.Ttl().Full_url(); // get page_name only (no anchor; no query args)
this.anch_key = page.Url().Anchor_bry();
this.qarg_key = page.Url().Args_all_as_bry();
this.redirect_force = page.Url().Redirect_force() ? Bool_.Y_bry : Bool_.N_bry;
this.key = Xog_history_itm.Build_key(wiki_key, page_key, anch_key, qarg_key, redirect_force);
this.html_doc_pos = page.Html_data().Bmk_pos();
if (this.html_doc_pos == null)
this.html_doc_pos = Html_doc_pos_toc; // never allow null doc_pos; set to top
private final boolean redirect_force;
public Xog_history_itm(byte[] wiki, byte[] page, byte[] anch, byte[] qarg, boolean redirect_force, String bmk_pos) {
this.key = Bry_.Add_w_dlm(Byte_ascii.Pipe, wiki, page, anch, qarg, redirect_force ? Bool_.Y_bry : Bool_.N_bry);
this.wiki = wiki; this.page = page; this.anch = anch; this.qarg = qarg;
this.redirect_force = redirect_force; this.bmk_pos = bmk_pos;
}
public byte[] Key() {return key;} private byte[] key;
public byte[] Wiki_key() {return wiki_key;} private byte[] wiki_key;
public byte[] Page_key() {return page_key;} private byte[] page_key;
public byte[] Anch_key() {return anch_key;} private byte[] anch_key;
public byte[] Qarg_key() {return qarg_key;} private byte[] qarg_key;
public byte[] Redirect_force() {return redirect_force;} private byte[] redirect_force;
public String Html_doc_pos() {return html_doc_pos;} private String html_doc_pos;
public void Html_doc_pos_(String v) {html_doc_pos = v;}
public boolean Eq_except_bmk(Xog_history_itm comp) {
return Bry_.Eq(wiki_key, comp.Wiki_key())
&& Bry_.Eq(page_key, comp.Page_key())
&& Bry_.Eq(anch_key, comp.Anch_key())
&& Bry_.Eq(qarg_key, comp.Qarg_key())
&& Bry_.Eq(redirect_force, comp.Redirect_force())
public byte[] Key() {return key;} private final byte[] key;
public byte[] Wiki() {return wiki;} private final byte[] wiki;
public byte[] Page() {return page;} private final byte[] page;
public byte[] Anch() {return anch;} private final byte[] anch;
public byte[] Qarg() {return qarg;} private final byte[] qarg;
public String Bmk_pos() {return bmk_pos;} public void Bmk_pos_(String v) {bmk_pos = v;} private String bmk_pos;
public boolean Eq_wo_bmk_pos(Xog_history_itm comp) {
return Bry_.Eq(wiki, comp.wiki)
&& Bry_.Eq(page, comp.page)
&& Bry_.Eq(anch, comp.anch)
&& Bry_.Eq(qarg, comp.qarg)
&& redirect_force == comp.redirect_force
;
}
public static byte[] Build_key(byte[] wiki_key, byte[] page_key, byte[] anch_key, byte[] qarg_key, byte[] redirect_force) {
return Bry_.Add_w_dlm(Byte_ascii.Pipe, wiki_key, page_key, anch_key, qarg_key, redirect_force);
}
public static final String Html_doc_pos_toc = "top";
public static final Xog_history_itm Null = new Xog_history_itm(); private Xog_history_itm() {}
public static final Xog_history_itm Null = new Xog_history_itm(null, null, null, null, false, null);
}

View File

@ -17,37 +17,61 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.gui.history; import gplx.*; import gplx.xowa.*; import gplx.xowa.gui.*;
public class Xog_history_mgr {
private OrderedHash hash = OrderedHash_.new_bry_();
private Xog_history_stack itm_stack = new Xog_history_stack();
private final OrderedHash hash = OrderedHash_.new_bry_(); private final Xog_history_stack stack = new Xog_history_stack();
public int Count() {return hash.Count();}
public Xoa_page Cur_page(Xow_wiki wiki) {return Get_or_fetch(wiki, stack.Cur_itm());}
public Xoa_page Go_bwd(Xow_wiki wiki) {return Go_by_dir(wiki, Bool_.N);}
public Xoa_page Go_fwd(Xow_wiki wiki) {return Go_by_dir(wiki, Bool_.Y);}
public Xoa_page Go_by_dir(Xow_wiki wiki, boolean fwd) {
Xog_history_itm itm = fwd ? stack.Go_fwd() : stack.Go_bwd();
if (itm == Xog_history_itm.Null) return Xoa_page.Empty;
Xoa_page rv = Get_or_fetch(wiki, itm);
byte[] anch_key = itm.Anch();
rv.Url().Anchor_bry_(anch_key); // must override anchor as it may be different for cached page
rv.Html_data().Bmk_pos_(itm.Bmk_pos());
return rv;
}
public void Add(Xoa_page page) {
itm_stack.Add(page);
Xog_history_itm new_itm = Xog_history_mgr.new_(page);
stack.Add(new_itm);
byte[] page_key = Build_page_key(page);
if (!hash.Has(page_key))
hash.Add(page_key, page);
}
public void Update_html_doc_pos(Xoa_page page, byte history_nav_type) {
itm_stack.Update_html_doc_pos(page, history_nav_type);
Xog_history_itm itm = Get_recent(page, history_nav_type);
if (itm != null) itm.Bmk_pos_(page.Html_data().Bmk_pos());
}
public Xoa_page Cur_page(Xow_wiki wiki) {return Get_or_fetch(wiki, itm_stack.Cur_itm());}
public Xoa_page Go_bwd(Xow_wiki wiki) {return Go_by_dir(wiki, Bool_.N);}
public Xoa_page Go_fwd(Xow_wiki wiki) {return Go_by_dir(wiki, Bool_.Y);}
public Xoa_page Go_by_dir(Xow_wiki wiki, boolean fwd) {
Xog_history_itm itm = fwd ? itm_stack.Go_fwd() : itm_stack.Go_bwd();
if (itm == Xog_history_itm.Null) return Xoa_page.Empty;
Xoa_page rv = Get_or_fetch(wiki, itm);
byte[] anch_key = itm.Anch_key();
rv.Url().Anchor_bry_(anch_key); // must override anchor as it may be different for cached page
rv.Html_data().Bmk_pos_(itm.Html_doc_pos());
return rv;
private Xog_history_itm Get_recent(Xoa_page page, byte history_nav_type) {
int pos = -1;
int list_pos = stack.Cur_pos();
switch (history_nav_type) {
case Xog_history_stack.Nav_fwd: pos = list_pos - 1; break;
case Xog_history_stack.Nav_bwd: pos = list_pos + 1; break;
case Xog_history_stack.Nav_by_anchor: pos = list_pos; break;
}
if (pos < 0 || pos >= stack.Len()) return null;
Xog_history_itm recent = stack.Get_at(pos);
Xog_history_itm page_itm = Xog_history_mgr.new_(page);
return page_itm.Eq_wo_bmk_pos(recent) ? recent : null; // check that recent page actually matches current; DATE:2014-05-10
}
private Xoa_page Get_or_fetch(Xow_wiki wiki, Xog_history_itm itm) {
byte[] page_key = Build_page_key(itm.Wiki_key(), itm.Page_key(), itm.Qarg_key());
byte[] page_key = Build_page_key(itm.Wiki(), itm.Page(), itm.Qarg());
Xoa_page rv = (Xoa_page)hash.Fetch(page_key);
if (rv != null) return rv;
Xoa_ttl ttl = Xoa_ttl.parse_(wiki, itm.Page_key());
Xoa_ttl ttl = Xoa_ttl.parse_(wiki, itm.Page());
return wiki.Data_mgr().Get_page(ttl, false);
}
private static byte[] Build_page_key(Xoa_page page) {return Build_page_key(page.Wiki().Domain_bry(), page.Ttl().Full_url(), page.Url().Args_all_as_bry());}
private static byte[] Build_page_key(byte[] wiki_key, byte[] page_key, byte[] args_key) {return Bry_.Add_w_dlm(Byte_ascii.Pipe, wiki_key, page_key, args_key);}
public static Xog_history_itm new_(Xoa_page pg) {
byte[] wiki = pg.Wiki().Domain_bry();
byte[] page = pg.Ttl().Full_url(); // get page_name only (no anchor; no query args)
byte[] anch = pg.Url().Anchor_bry();
byte[] qarg = pg.Url().Args_all_as_bry();
boolean redirect_force = pg.Url().Redirect_force();
String bmk_pos = pg.Html_data().Bmk_pos();
if (bmk_pos == null) bmk_pos = Xog_history_itm.Html_doc_pos_toc; // never allow null doc_pos; set to top
return new Xog_history_itm(wiki, page, anch, qarg, redirect_force, bmk_pos);
}
}

View File

@ -17,56 +17,36 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.gui.history; import gplx.*; import gplx.xowa.*; import gplx.xowa.gui.*;
public class Xog_history_stack {
private ListAdp list = ListAdp_.new_();
public int Stack_pos() {return list_pos;} private int list_pos = 0;
public int Count() {return list.Count();}
public void Clear() {list.Clear(); list_pos = 0;}
public Xog_history_itm Cur_itm() {return list.Count() == 0 ? Xog_history_itm.Null : (Xog_history_itm)list.FetchAt(list_pos);}
public Xog_history_itm Add(Xoa_page page) {
Xog_history_itm new_itm = new Xog_history_itm(page);
private final ListAdp list = ListAdp_.new_();
public int Len() {return list.Count();}
public void Clear() {list.Clear(); cur_pos = 0;}
public Xog_history_itm Get_at(int i) {return (Xog_history_itm)list.FetchAt(i);}
public int Cur_pos() {return cur_pos;} private int cur_pos = 0;
public Xog_history_itm Cur_itm() {return list.Count() == 0 ? Xog_history_itm.Null : (Xog_history_itm)list.FetchAt(cur_pos);}
public void Add(Xog_history_itm new_itm) {
Xog_history_itm cur_itm = this.Cur_itm();
if ( cur_itm != Xog_history_itm.Null
&& cur_itm.Eq_except_bmk(new_itm)
)
return Xog_history_itm.Null; // do not add if last itm is same;
Del_all_from(list_pos + 1);
if (cur_itm != Xog_history_itm.Null && cur_itm.Eq_wo_bmk_pos(new_itm)) return; // do not add if last itm is same;
this.Del_from(cur_pos + 1);
list.Add(new_itm);
list_pos = list.Count() - 1;
return new_itm;
}
public void Update_html_doc_pos(Xoa_page page, byte history_nav_type) {
Xog_history_itm itm = Get_recent(page, history_nav_type);
if (itm != null) itm.Html_doc_pos_(page.Html_data().Bmk_pos());
}
private Xog_history_itm Get_recent(Xoa_page page, byte history_nav_type) {
int pos = -1;
switch (history_nav_type) {
case Xog_history_stack.Nav_fwd: pos = list_pos - 1; break;
case Xog_history_stack.Nav_bwd: pos = list_pos + 1; break;
case Xog_history_stack.Nav_by_anchor: pos = list_pos; break;
}
if (pos < 0 || pos >= list.Count()) return null;
Xog_history_itm recent = (Xog_history_itm)list.FetchAt(pos);
Xog_history_itm page_itm = new Xog_history_itm(page);
return page_itm.Eq_except_bmk(recent) ? recent : null; // check that recent page actually matches current; DATE:2014-05-10
cur_pos = list.Count() - 1;
}
public Xog_history_itm Go_bwd() {
if (list.Count() == 0) return Xog_history_itm.Null;
--list_pos;
if (list_pos < 0) list_pos = 0;
--cur_pos;
if (cur_pos < 0) cur_pos = 0;
return this.Cur_itm();
}
public Xog_history_itm Go_fwd() {
int list_count = list.Count();
if (list_count == 0) return Xog_history_itm.Null;
++list_pos;
if (list_pos == list_count) list_pos = list_count - 1;
++cur_pos;
if (cur_pos == list_count) cur_pos = list_count - 1;
return this.Cur_itm();
}
private void Del_all_from(int from) {
int list_count = list.Count();
if (from <= list_count - 1)
list.Del_range(from, list_count - 1);
private void Del_from(int from) {
int len = list.Count();
if (from <= len - 1)
list.Del_range(from, len - 1);
}
public static final byte Nav_fwd = 1, Nav_bwd = 2, Nav_by_anchor = 3;
}

View File

@ -50,13 +50,13 @@ class Xog_history_stack_fxt {
} private Xoa_app app; private Xow_wiki wiki; private Xog_history_stack stack = new Xog_history_stack(); private Xoa_url_parser url_parser;
public Xog_history_stack_fxt Test_cur(String expd) {
Xog_history_itm page = stack.Cur_itm();
String actl = page == null ? null : String_.new_utf8_(page.Page_key());
String actl = page == null ? null : String_.new_utf8_(page.Page());
Tfds.Eq(expd, actl, "cur");
return this;
}
public Xog_history_stack_fxt Test_cur_qargs(String expd) {
Xog_history_itm page = stack.Cur_itm();
String actl = page == null ? null : String_.new_utf8_(page.Qarg_key());
String actl = page == null ? null : String_.new_utf8_(page.Qarg());
Tfds.Eq(expd, actl, "cur_qargs");
return this;
}
@ -78,9 +78,9 @@ class Xog_history_stack_fxt {
if (arg_str != null) url_bry = Bry_.Add(url_bry, Bry_.new_utf8_(arg_str));
Xoa_url url = url_parser.Parse(url_bry);
page.Url_(url); // set url b/c history_mgr.Add uses url
stack.Add(page);
stack.Add(Xog_history_mgr.new_(page));
return this;
}
public Xog_history_stack_fxt Test_pos(int expd) {Tfds.Eq(expd, stack.Stack_pos(), "pos"); return this;}
public Xog_history_stack_fxt Test_len(int expd) {Tfds.Eq(expd, stack.Count(), "len"); return this;}
public Xog_history_stack_fxt Test_pos(int expd) {Tfds.Eq(expd, stack.Cur_pos(), "pos"); return this;}
public Xog_history_stack_fxt Test_len(int expd) {Tfds.Eq(expd, stack.Len(), "len"); return this;}
}

View File

@ -67,16 +67,17 @@ public class Xob_hdump_bldr {
}
private static void Db_init(Db_provider p) {p.Exec_sql(Hdump_text_tbl.Tbl_sql);}
private static void Db_term(Xodb_file core_db_file, Db_provider hdump_db_provider, int hdump_db_id) {
hdump_db_provider.Txn_mgr().Txn_end();
hdump_db_provider.Txn_mgr().Txn_end_all();
Sqlite_engine_.Idx_create(hdump_db_provider, Hdump_text_tbl.Idx_core);
Sqlite_engine_.Db_attach(hdump_db_provider, "page_db", core_db_file.Url().Raw());
hdump_db_provider.Txn_mgr().Txn_bgn();
hdump_db_provider.Exec_sql(String_.Format(Sql_update_page, hdump_db_id)); // update all page_html_db_id entries in page_db
hdump_db_provider.Txn_mgr().Txn_end();
Sqlite_engine_.Db_detach(hdump_db_provider, "page_db");
hdump_db_provider.Txn_mgr().Txn_end_all();
}
private static final String Cfg_grp_hdump_make = "hdump.make", Cfg_itm_hdump_size = "hdump.size";
private static final String Sql_update_page = String_.Concat_lines_nl_skip_last
( "REPLACE INTO page_db.page"
( "REPLACE INTO page_db.page (page_id, page_namespace, page_title, page_is_redirect, page_touched, page_len, page_random_int, page_file_idx, page_redirect_id, page_html_db_id)"
, "SELECT p.page_id"
, ", p.page_namespace"
, ", p.page_title"
@ -85,6 +86,7 @@ public class Xob_hdump_bldr {
, ", p.page_len"
, ", p.page_random_int"
, ", p.page_file_idx"
, ", p.page_redirect_id"
, ", {0}"
, "FROM page_db.page p"
, " JOIN html_text h ON p.page_id = h.page_id"

View File

@ -61,8 +61,8 @@ public class Xodb_hdump_mgr {
public void Load(Xow_wiki wiki, Xoa_page page, int html_db_id) {
if (!Enabled_chk()) return;
page.Root_(new Xop_root_tkn());
Hdump_page hpg = new Hdump_page().Init(page.Revision_data().Id(), page.Url());
load_mgr.Load(hpg, wiki.Db_mgr_as_sql().Fsys_mgr(), html_db_id, page.Revision_data().Id());
Hdump_page hpg = new Hdump_page().Init(page.Revision_data().Id(), page.Url(), page.Ttl());
load_mgr.Load(hpg, wiki.Db_mgr_as_sql().Fsys_mgr(), html_db_id, page.Revision_data().Id(), page.Ttl());
Load_page(wiki, page, hpg);
}
private void Load_page(Xow_wiki wiki, Xoa_page page, Hdump_page hpg) {

View File

@ -38,7 +38,6 @@ public class Xodb_hdump_mgr_setup {
if (String_.Eq(val, "y")) return;
try {
core_provider.Exec_sql(Sql_ddl__page_html_db_id);
core_provider.Exec_sql(Sql_ddl__page_redirect_id);
cfg_tbl.Insert_str(Xodb_fsys_mgr.Cfg_grp_db_meta, Cfg_itm_html_db_exists, "y");
} catch (Exception e) {Gfo_usr_dlg_._.Warn_many("", "", "failed to update core: db=~{0} err=~{1}", core_provider.Conn_info().Str_raw(), Err_.Message_gplx(e));}
}
@ -52,8 +51,7 @@ public class Xodb_hdump_mgr_setup {
Sqlite_engine_.Idx_create(html_db_file.Provider(), Hdump_text_tbl.Idx_core);
}
private static final String Cfg_itm_html_db_exists = "html_db.exists";
private static final String
public static final String
Sql_ddl__page_html_db_id = "ALTER TABLE page ADD COLUMN page_html_db_id integer NOT NULL DEFAULT '-1'"
, Sql_ddl__page_redirect_id = "ALTER TABLE page ADD COLUMN page_redirect_id integer NOT NULL DEFAULT '-1'"
;
}

View File

@ -0,0 +1,52 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.hdumps; import gplx.*; import gplx.xowa.*;
import gplx.xowa.hdumps.core.*; import gplx.xowa.gui.history.*;
public abstract class Xogv_tab_base {
private Xog_history_stack history_stack = new Xog_history_stack();
private Xoav_wiki_mgr wiki_mgr;
public void Ctor(Xoav_wiki_mgr wiki_mgr) {this.wiki_mgr = wiki_mgr;}
public Xog_history_itm Cur_itm() {return history_stack.Cur_itm();}
public Hdump_page Go_to(byte[] page) {return Go_to(history_stack.Cur_itm().Wiki(), page, Bry_.Empty, Bry_.Empty, false, "");}
public Hdump_page Go_to(byte[] wiki, byte[] page) {return Go_to(wiki, page, Bry_.Empty, Bry_.Empty, false, "");}
public Hdump_page Go_to(byte[] wiki, byte[] page, byte[] anch, byte[] qarg, boolean redirect_force, String bmk_pos) {
Xog_history_itm old_itm = this.Cur_itm();
Xog_history_itm new_itm = new Xog_history_itm(wiki, page, anch, qarg, redirect_force, bmk_pos);
history_stack.Add(new_itm);
return Fetch_page_and_show(old_itm, new_itm);
}
public Hdump_page Go_bwd() {return Go_by_dir(Bool_.Y);}
public Hdump_page Go_fwd() {return Go_by_dir(Bool_.N);}
private Hdump_page Go_by_dir(boolean bwd) {
Xog_history_itm old_itm = this.Cur_itm();
Xog_history_itm new_itm = bwd ? history_stack.Go_bwd() : history_stack.Go_fwd();
return Fetch_page_and_show(old_itm, new_itm);
}
private Hdump_page Fetch_page_and_show(Xog_history_itm old_itm, Xog_history_itm new_itm) {
Hdump_page new_hpg = Fetch_page(new_itm.Wiki(), new_itm.Page());
Show_page(old_itm, new_itm, new_hpg);
return new_hpg;
}
private Hdump_page Fetch_page(byte[] wiki_domain, byte[] page_ttl) {
Xowv_wiki wiki = wiki_mgr.Get_by_domain(wiki_domain);
Hdump_page rv = new Hdump_page();
wiki.Hdump_mgr().Load(rv, page_ttl);
return rv;
}
protected abstract void Show_page(Xog_history_itm old_itm, Xog_history_itm new_itm, Hdump_page new_hpg);
}

View File

@ -20,7 +20,7 @@ import gplx.intl.*; import gplx.dbs.*;
import gplx.xowa.hdumps.core.*; import gplx.xowa.hdumps.loads.*; import gplx.xowa.hdumps.htmls.*; import gplx.xowa.apps.fsys.*;
public class Xowd_hdump_mgr {
private final Xoav_app app; private final Xowv_wiki wiki; private final Xowv_db_mgr wiki_db_mgr;
private Xodb_page dbpg = new Xodb_page(); private Hdump_page hpg = new Hdump_page();
private Xodb_page dbpg = new Xodb_page();
private Hdump_load_mgr load_mgr = new Hdump_load_mgr();
private Hdump_html_body html_body = new Hdump_html_body();
public Xowd_hdump_mgr(Xoav_app app, Xowv_wiki wiki) {
@ -31,9 +31,9 @@ public class Xowd_hdump_mgr {
Xoa_ttl ttl = wiki.Ttl_parse(ttl_bry);
wiki_db_mgr.Tbl_mgr().Tbl__page().Select_by_ttl(dbpg, app.Db_mgr().Get(wiki_db_mgr.Key__core()), ttl.Ns(), ttl.Page_db());
if (dbpg.Html_db_id() == -1) return; // should return "not found" message
load_mgr.Load2(hpg, app.Db_mgr().Get(wiki_db_mgr.Key_by_idx(dbpg.Html_db_id())), dbpg.Id());
load_mgr.Load2(rv, app.Db_mgr().Get(wiki_db_mgr.Key_by_idx(dbpg.Html_db_id())), dbpg.Id(), ttl);
Bry_bfr bfr = app.Utl_bfr_mkr().Get_m001();
html_body.Init_by_page(wiki.Domain_bry(), hpg).Write(bfr);
html_body.Init_by_page(wiki.Domain_bry(), rv).Write(bfr);
rv.Page_body_(bfr.Mkr_rls().Xto_bry_and_clear());
}
}

View File

@ -19,6 +19,7 @@ package gplx.xowa.hdumps.core; import gplx.*; import gplx.xowa.*; import gplx.xo
public class Hdump_page {
public int Page_id() {return page_id;} private int page_id;
public Xoa_url Page_url() {return page_url;} private Xoa_url page_url;
public Xoa_ttl Page_ttl() {return page_ttl;} private Xoa_ttl page_ttl;
public int Version_id() {return version_id;} public void Version_id_(int v) {version_id = v;} private int version_id;
public int Img_count() {return img_count;} public void Img_count_(int v) {img_count = v;} private int img_count;
public Hdump_module_mgr Module_mgr() {return module_mgr;} private Hdump_module_mgr module_mgr = new Hdump_module_mgr();
@ -29,9 +30,8 @@ public class Hdump_page {
public int[] Redlink_uids() {return redlink_uids;} public void Redlink_uids_(int[] v) {redlink_uids = v;} private int[] redlink_uids;
public Hdump_data_img__base[] Img_itms() {return img_itms;} public void Img_itms_(Hdump_data_img__base[] v) {this.img_itms = v;} private Hdump_data_img__base[] img_itms;
public OrderedHash Gly_itms() {return gly_itms;} private OrderedHash gly_itms = OrderedHash_.new_();
public Hdump_page Init(int page_id, Xoa_url page_url) {
this.page_id = page_id;
this.page_url = page_url;
public Hdump_page Init(int page_id, Xoa_url page_url, Xoa_ttl page_ttl) {
this.page_id = page_id; this.page_url = page_url; this.page_ttl = page_ttl;
content_sub = sidebar_div = Bry_.Empty;
display_ttl = null;
img_itms = Hdump_data_img__base.Ary_empty;

View File

@ -28,10 +28,13 @@ public class Hdump_text_tbl {
try {stmt_delete.Clear().Val_int_(page_id).Exec_delete();}
catch (Exception exc) {stmt_delete = null; throw Err_.err_(exc, "stmt failed");} // must reset stmt, else next call will fail
}
@gplx.Virtual public void Insert(int page_id, int tid, byte[] data) {
@gplx.Virtual public int Insert(int page_id, int tid, byte[] data) {
if (stmt_insert == null) stmt_insert = Db_stmt_.new_insert_(provider, Tbl_name, Flds_all);
if (zip_mgr != null) data = zip_mgr.Zip(db_mgr.Data_storage_format(), data);
try {stmt_insert.Clear().Val_int_(page_id).Val_int_(tid).Val_str_by_bry_(data).Exec_insert();}
try {
stmt_insert.Clear().Val_int_(page_id).Val_int_(tid).Val_str_by_bry_(data).Exec_insert();
return data.length;
}
catch (Exception exc) {stmt_insert = null; throw Err_.err_(exc, "stmt failed");} // must reset stmt, else next call will fail
}
private static final String[] Select_by_page_flds = new String[] {Fld_page_id, Fld_text_tid, Fld_text_data};

View File

@ -18,10 +18,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
package gplx.xowa.hdumps.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.hdumps.*;
import gplx.dbs.*;
public class Hdump_text_tbl_mem extends Hdump_text_tbl { private HashAdp pages = HashAdp_.new_();
@Override public void Insert(int page_id, int tid, byte[] data) {
@Override public int Insert(int page_id, int tid, byte[] data) {
Hdump_text_row row = new Hdump_text_row(page_id, tid, data);
ListAdp rows = Get_or_new(pages, page_id);
rows.Add(row);
return data.length;
}
@Override public void Select_by_page(ListAdp rv, int page_id) {
ListAdp rows = Get_or_new(pages, page_id);

View File

@ -23,17 +23,17 @@ public class Hdump_load_mgr {
private ListAdp tmp_rows = ListAdp_.new_(), img_itms = ListAdp_.new_();
public Hdump_load_mgr() {}
public byte Zip_tid() {return zip_tid;} public void Zip_tid_(byte v) {zip_tid = v;} private byte zip_tid = gplx.ios.Io_stream_.Tid_file;
public void Load2(Hdump_page hpg, Db_provider provider, int page_id) {
public void Load2(Hdump_page hpg, Db_provider provider, int page_id, Xoa_ttl page_ttl) {
text_tbl.Provider_(provider).Select_by_page(tmp_rows, page_id);
Load_rows(hpg, page_id, Xoa_url.blank_(), tmp_rows);
Load_rows(hpg, page_id, Xoa_url.blank_(), page_ttl, tmp_rows);
}
public void Load(Hdump_page hpg, Xodb_fsys_mgr db_fsys_mgr, int html_db_id, int page_id) {
public void Load(Hdump_page hpg, Xodb_fsys_mgr db_fsys_mgr, int html_db_id, int page_id, Xoa_ttl page_ttl) {
Db_provider provider = db_fsys_mgr.Get_by_idx(html_db_id).Provider();
text_tbl.Provider_(provider).Select_by_page(tmp_rows, page_id);
Load_rows(hpg, page_id, hpg.Page_url(), tmp_rows);
Load_rows(hpg, page_id, hpg.Page_url(), page_ttl, tmp_rows);
}
public void Load_rows(Hdump_page hpg, int page_id, Xoa_url page_url, ListAdp rows) {
hpg.Init(page_id, page_url);
public void Load_rows(Hdump_page hpg, int page_id, Xoa_url page_url, Xoa_ttl page_ttl, ListAdp rows) {
hpg.Init(page_id, page_url, page_ttl);
img_itms.Clear();
int len = rows.Count();
for (int i = 0; i < len; ++i) {

View File

@ -87,7 +87,7 @@ class Hdump_load_mgr_fxt {
public Hdump_load_mgr_fxt Expd_sidebar_div(String v) {this.expd_sidebar_div = v; return this;}
public Hdump_load_mgr_fxt Expd_img(Hdump_data_img__base img) {expd_imgs.Add(img); return this;}
public Hdump_load_mgr_fxt Test_load(int page_id) {
load_mgr.Load_rows(hpg, page_id, page_url, init_rows);
load_mgr.Load_rows(hpg, page_id, page_url, Xoa_ttl.Null, init_rows);
if (expd_body != null) Tfds.Eq(expd_body, String_.new_utf8_(hpg.Page_body()));
if (expd_display_ttl != null) Tfds.Eq(expd_display_ttl, String_.new_utf8_(hpg.Display_ttl()));
if (expd_content_sub != null) Tfds.Eq(expd_content_sub, String_.new_utf8_(hpg.Content_sub()));

View File

@ -37,8 +37,7 @@ public class Hdump_save_mgr {
public int Insert_body(Xoa_page page, int page_id) {
Hdump_page_body_srl.Save(tmp_bfr, page);
byte[] body_bry = tmp_bfr.Xto_bry_and_clear();
text_tbl.Insert(page_id, Hdump_text_row_tid.Tid_body, body_bry);
return body_bry.length;
return text_tbl.Insert(page_id, Hdump_text_row_tid.Tid_body, body_bry);
}
public static byte[] Write_imgs(Bry_bfr bfr, ListAdp imgs) {
int len = imgs.Count(); if (len == 0) return null; // no images; exit early, else will write blank String

View File

@ -129,7 +129,11 @@ public class Xoh_page_wtr_wkr implements Bry_fmtr_arg {
if (ns_id == Xow_ns_.Id_category) // if Category, render rest of html (Subcategories; Pages; Files); note that a category may have other html which requires wikitext processing
wiki.Html_mgr().Ns_ctg().Bld_html(page, bfr);
int ctgs_len = page.Category_list().length; // add Categories
if (ctgs_enabled && ctgs_len > 0) {
if ( ctgs_enabled
&& ctgs_len > 0
&& !wiki.Html_mgr().Importing_ctgs() // do not show categories if importing categories, page will wait for category import to be done; DATE:2014-10-15
) {
app.Usr_dlg().Prog_many("", "", "loading categories: count=~{0}", ctgs_len);
if (app.Ctg_mgr().Pagecats_grouping_enabled())
app.Ctg_mgr().Pagectgs_wtr().Write(bfr, wiki, page);

View File

@ -46,6 +46,7 @@ public class Xow_html_mgr implements GfoInvkAble {
public Xow_portal_mgr Portal_mgr() {return portal_mgr;} private Xow_portal_mgr portal_mgr;
public Xow_toc_mgr Toc_mgr() {return toc_mgr;} private Xow_toc_mgr toc_mgr = new Xow_toc_mgr();
public Xow_module_mgr Module_mgr() {return module_mgr;} private Xow_module_mgr module_mgr;
public boolean Importing_ctgs() {return importing_ctgs;} public void Importing_ctgs_(boolean v) {importing_ctgs = v;} private boolean importing_ctgs;
public int Img_thumb_width() {return img_thumb_width;} private int img_thumb_width = 220;
public byte[] Img_media_play_btn() {return img_media_play_btn;} private byte[] img_media_play_btn;
public byte[] Img_media_info_btn() {return img_media_info_btn;} private byte[] img_media_info_btn;

View File

@ -88,7 +88,7 @@ class Xop_vnt_lxr_end implements Xop_lxr {
catch (Exception e) {
ctx.App().Usr_dlg().Warn_many("", "", "vnt.parse failed: page=~{0} src=~{1} err=~{2}", String_.new_utf8_(ctx.Cur_page().Ttl().Raw()), String_.new_utf8_(src, bgn_pos, cur_pos), Err_.Message_gplx_brief(e));
if (vnt_tkn != null)
root.Subs_add(tkn_mkr.Bry(src, vnt_tkn.Src_bgn(), cur_pos));
root.Subs_add(tkn_mkr.Bry_mid(src, vnt_tkn.Src_bgn(), cur_pos));
}
return cur_pos;
}

View File

@ -155,7 +155,7 @@ class Xop_vnt_rules_parser {
case Xop_vnt_rule_trie_itm.Tid_semic:
switch (mode) {
case Mode_text:
text_tkns_list.Add(tkn_mkr.Bry(src_bgn, pos, Bry_.Trim(Bry_.Mid(src, src_bgn, pos))));
text_tkns_list.Add(tkn_mkr.Bry_raw(src_bgn, pos, Bry_.Trim(Bry_.Mid(src, src_bgn, pos))));
Make_rule();
cur_lang_bry = null;
mode = Mode_key;

View File

@ -105,7 +105,7 @@ public class Xop_para_wkr implements Xop_ctx_wkr {
if ( next_char_pos < src.length // bounds check
&& src[next_char_pos] == Byte_ascii.NewLine // is "\n\s\n"; i.e.: "\n" only
) {
ctx.Subs_add(root, ctx.Tkn_mkr().Bry(bgn_pos, bgn_pos, Byte_ascii.NewLine_bry)); // add a "\n" tkn; note that adding a NewLine tkn doesn't work, b/c Xoh_html_wtr has code to remove consecutive \n; PAGE:en.w:Preferred_numbers DATE:2014-06-24
ctx.Subs_add(root, ctx.Tkn_mkr().Bry_raw(bgn_pos, bgn_pos, Byte_ascii.NewLine_bry)); // add a "\n" tkn; note that adding a NewLine tkn doesn't work, b/c Xoh_html_wtr has code to remove consecutive \n; PAGE:en.w:Preferred_numbers DATE:2014-06-24
prv_nl_pos = bgn_pos;
}
}

View File

@ -53,6 +53,20 @@ public class Xop_tblw_lxr implements Xop_lxr {
return ctx.Lxr_make_txt_(cur_pos);
}
}
if (wlxr_type == Xop_tblw_wkr.Tblw_type_th2) { // !!; extra check to make sure \n! exists; DATE:2014-10-19
int prv_th_pos = Bry_finder.Find_bwd(src, Byte_ascii.NewLine, bgn_pos); // search for previous \n
boolean invalid = prv_th_pos == Bry_finder.Not_found; // no \n; invalid
if (!invalid) {
++prv_th_pos; // skip \n
prv_th_pos = Bry_finder.Find_fwd_while_space_or_tab(src, prv_th_pos, src_len); // skip \s; needed for "\n\s!" which is still a tblw
if (prv_th_pos == bgn_pos) // invalid: "\n" is directly in front of "!!"
invalid = true;
else
invalid = src[prv_th_pos] != Byte_ascii.Bang; // invalid if not "\n!"
}
if (invalid)
return Xop_tblw_wkr.Handle_false_tblw_match(ctx, root, src, bgn_pos, cur_pos, tkn_mkr.Txt(bgn_pos, cur_pos), false);
}
break;
}
return Continue;

View File

@ -27,7 +27,7 @@ public class Xop_tblw_wkr__double_pipe_tst {
, ""
));
}
@Test public void Tblw_lnki_nth() { // PURPOSE: if || is nth pipe, then treat as lnki; PAGE:en.w:Main_Page;de.w:Main_Page; DATE:2014-05-06
@Test public void Lnki_nth() { // PURPOSE: if || is nth pipe, then treat as lnki; PAGE:en.w:Main_Page;de.w:Main_Page; DATE:2014-05-06
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "{|"
, "|[[File:A.png|b||c]]"
@ -43,7 +43,7 @@ public class Xop_tblw_wkr__double_pipe_tst {
)
);
}
@Test public void Tblw_lnki_list_1st() { // PURPOSE: if || is 1st pipe, but inside list, then treat as lnki; EX:w:Second_Boer_War; DATE:2014-05-05
@Test public void Lnki_list_1st() { // PURPOSE: if || is 1st pipe, but inside list, then treat as lnki; EX:w:Second_Boer_War; DATE:2014-05-05
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "{|"
, "|"
@ -65,7 +65,7 @@ public class Xop_tblw_wkr__double_pipe_tst {
)
);
}
@Test public void Tblw_lnki_double_bang() { // PURPOSE: do not treat !! as tblw; PAGE:en.w:Pink_(singer); DATE:2014-06-25
@Test public void Double_bang_lnki() { // PURPOSE: do not treat !! as tblw; PAGE:en.w:Pink_(singer); DATE:2014-06-25
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "{|"
, "|"
@ -85,4 +85,24 @@ public class Xop_tblw_wkr__double_pipe_tst {
)
);
}
@Test public void Double_bang_list() { // PURPOSE: do not treat !! as tblw; PAGE:en.w:Wikipedia:Featured_picture_candidates; DATE:2014-10-19
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "{|"
, "* a !! b"
, "|}"
) , String_.Concat_lines_nl_skip_last
( "<table>"
, " <ul>"
, " <li> a !! b"
, " </li>"
, " </ul>"
, " <tr>"
, " <td>"
, " </td>"
, " </tr>"
, "</table>"
, "</p>" // NOTE: </p> is incorrect, but benign
)
);
}
}

View File

@ -47,7 +47,7 @@ public class Xou_history_mgr implements GfoInvkAble {
byte[] page_ttl = null;
ListAdp redirect_list = page.Redirected_ttls();
if (redirect_list.Count() > 0) // page was redirected; add src ttl to history, not trg; EX: UK -> United Kingdom; add "UK"; DATE:2014-02-28
page_ttl = (byte[])page.Redirected_ttls().FetchAt(0);
page_ttl = page.Redirected_ttls__itm_0();
else {
page_ttl = Bry_.Add(ttl.Ns().Name_db_w_colon(), ttl.Page_txt()); // use ttl.Page_txt() b/c it normalizes space/casing (url.Page_txt does not)
if (url.Args().length > 0)

View File

@ -1,31 +0,0 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.poems; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.core.btries.*; import gplx.xowa.parsers.paras.*;
public class Poem_lxr_nl implements Xop_lxr {
public byte Lxr_tid() {return Xop_lxr_.Tid_nl_poem;}
public void Init_by_wiki(Xow_wiki wiki, Btrie_fast_mgr core_trie) {core_trie.Add(Byte_ascii.NewLine, this);}
public void Init_by_lang(Xol_lang lang, Btrie_fast_mgr core_trie) {}
public int Make_tkn(Xop_ctx ctx, Xop_tkn_mkr tkn_mkr, Xop_root_tkn root, byte[] src, int src_len, int bgn_pos, int cur_pos) {
if (bgn_pos == Xop_parser_.Doc_bgn_bos) return ctx.Lxr_make_txt_(cur_pos); // simulated nl at beginning of every parse
ctx.Subs_add(root, tkn_mkr.Xnde(bgn_pos, cur_pos).Tag_(Xop_xnde_tag_.Tag_br)); // add <br/>
ctx.Subs_add(root, tkn_mkr.NewLine(cur_pos, cur_pos, Xop_nl_tkn.Tid_char, 1)); // add \n; for pretty-printing
return cur_pos;
}
public static final Poem_lxr_nl _ = new Poem_lxr_nl(); Poem_lxr_nl() {}
}

View File

@ -1,46 +0,0 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.poems; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.core.btries.*; import gplx.xowa.parsers.paras.*;
public class Poem_lxr_pre implements Xop_lxr {
public byte Lxr_tid() {return Xop_lxr_.Tid_poem;}
public void Init_by_wiki(Xow_wiki wiki, Btrie_fast_mgr core_trie) {core_trie.Add(Hook_ary, this);}
public void Init_by_lang(Xol_lang lang, Btrie_fast_mgr core_trie) {}
public int Make_tkn(Xop_ctx ctx, Xop_tkn_mkr tkn_mkr, Xop_root_tkn root, byte[] src, int src_len, int bgn_pos, int cur_pos) {
int space_count = 1;
while (cur_pos < src_len) {
if (src[cur_pos++] == Byte_ascii.Space) {
++space_count;
}
else {
--cur_pos;
break;
}
}
if (bgn_pos != Xop_parser_.Doc_bgn_bos) { // do not add xnde/nl if \n is BOS \n; PAGE:en.w:Teresa of Ávila; "<poem>\n\s\s"
ctx.Subs_add(root, tkn_mkr.Xnde(cur_pos, cur_pos).Tag_(Xop_xnde_tag_.Tag_br));
ctx.Subs_add(root, tkn_mkr.NewLine(cur_pos, cur_pos, Xop_nl_tkn.Tid_char, 1));
}
for (int i = 0; i < space_count; i++)
ctx.Subs_add(root, tkn_mkr.Amp_num(bgn_pos + 1, cur_pos, 160, Nbsp_bry));
return cur_pos;
}
private static final byte[] Nbsp_bry = gplx.intl.Utf16_.Encode_int_to_bry(160);
private static final byte[] Hook_ary = new byte[] {Byte_ascii.NewLine, Byte_ascii.Space};
public static final Poem_lxr_pre _ = new Poem_lxr_pre(); Poem_lxr_pre() {}
}

View File

@ -16,7 +16,7 @@ You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.poems; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.xowa.html.*;
import gplx.html.*; import gplx.xowa.html.*;
public class Poem_nde implements Xox_xnde {
private Xop_root_tkn xtn_root;
public void Xtn_parse(Xow_wiki wiki, Xop_ctx ctx, Xop_root_tkn root, byte[] src, Xop_xnde_tkn xnde) {// REF.MW: Poem.php|wfRenderPoemTag
@ -27,15 +27,57 @@ public class Poem_nde implements Xox_xnde {
if (src[itm_end - 1] == Byte_ascii.NewLine // ignore last \n;
&& itm_end != itm_bgn) --itm_end; // ...if not same as 1st \n; EX: <poem>\n</poem>
Poem_xtn_mgr xtn_mgr = (Poem_xtn_mgr)wiki.Xtn_mgr().Get_or_fail(Poem_xtn_mgr.XTN_KEY);
xtn_root = xtn_mgr.Parser().Parse_text_to_wdom_old_ctx(ctx, Bry_.Mid(src, itm_bgn, itm_end), true); // NOTE: ignoring paragraph mode; technically MW enables para mode, but by replacing "\n" with "<br/>\n" all the logic with para/pre mode is skipped
byte[] poem_bry = Parse_lines(wiki.Utl_bry_bfr_mkr(), src, itm_bgn, itm_end);
xtn_root = xtn_mgr.Parser().Parse_text_to_wdom_old_ctx(ctx, poem_bry, true); // NOTE: ignoring paragraph mode; technically MW enables para mode, but by replacing "\n" with "<br/>\n" all the logic with para/pre mode is skipped
}
public void Xtn_write(Bry_bfr bfr, Xoa_app app, Xop_ctx ctx, Xoh_html_wtr html_wtr, Xoh_wtr_ctx hctx, Xop_xnde_tkn xnde, byte[] src) {
if (xtn_root == null) return; // inline poem; write nothing; EX: <poem/>
bfr.Add(Bry_poem_bgn);
bfr.Add(Div_poem_bgn);
html_wtr.Write_tkn(bfr, ctx, hctx, xtn_root.Root_src(), xnde, Xoh_html_wtr.Sub_idx_null, xtn_root);
bfr.Add(Bry_poem_end);
bfr.Add(Div_poem_end);
}
private static byte[] Parse_lines(Bry_bfr_mkr bfr_mkr, byte[] src, int src_bgn, int src_end) {
Bry_bfr bfr = bfr_mkr.Get_k004().Mkr_rls();
int line_bgn = src_bgn; boolean line_is_1st = true;
while (line_bgn < src_end) { // iterate over each \n
boolean indent_enabled = false;
if (line_is_1st) line_is_1st = false;
else {
if (Bry_.Match(src, line_bgn, line_bgn + Comment_marker.length, Comment_marker))
bfr.Add_byte_nl();
else
bfr.Add(Html_tag_.Br_inl).Add_byte_nl().Add(Comment_marker); // add "<br/>\n" unless 1st line; EX: "<poem>\n\s" should not add leading "<br/>\n"
}
switch (src[line_bgn]) {
case Byte_ascii.Space: // "\n\s" -> "\n&#160;"
int space_end = Bry_finder.Find_fwd_while(src, line_bgn, src_end, Byte_ascii.Space);
int space_count = space_end - line_bgn;
line_bgn = space_end;
for (int i = 0; i < space_count; ++i)
bfr.Add(Html_entity_.Nbsp_num_bry);
break;
case Byte_ascii.Colon: { // "\n:" -> <span class='mw-poem-indented' style='display: inline-block; margin-left: #em;'>
int colon_end = Bry_finder.Find_fwd_while(src, line_bgn, src_end, Byte_ascii.Colon);
int colon_count = colon_end - line_bgn;
line_bgn = colon_end;
bfr.Add(Indent_bgn).Add_int_variable(colon_count).Add(Indent_end); // add <span class='mw-poem-indented' style='display: inline-block; margin-left: #em;'>
indent_enabled = true;
break;
}
}
int line_end = Bry_finder.Find_fwd(src, Byte_ascii.NewLine, line_bgn, src_end); // find end "\n"
if (line_end == Bry_finder.Not_found) line_end = src_end; // no "\n"; use eos;
bfr.Add_mid(src, line_bgn, line_end); // add everything from line_bgn to line_end
if (indent_enabled) bfr.Add(Html_tag_.Span_rhs); // if "\n:", add </span>
line_bgn = line_end + 1; // +1 to skip over end "\n"
}
return bfr.Xto_bry_and_clear();
}
private static byte[]
Bry_poem_bgn = Bry_.new_ascii_("<div class=\"poem\">\n<p>\n") // NOTE: always enclose in <p>; MW does this implicitly in its modified parse; DATE:2014-04-27
, Bry_poem_end = Bry_.new_ascii_("\n</p>\n</div>");
Div_poem_bgn = Bry_.new_ascii_("<div class=\"poem\">\n<p>\n") // NOTE: always enclose in <p>; MW does this implicitly in its modified parse; DATE:2014-04-27
, Div_poem_end = Bry_.new_ascii_("\n</p>\n</div>")
, Indent_bgn = Bry_.new_ascii_("\n<span class='mw-poem-indented' style='display: inline-block; margin-left: ")
, Indent_end = Bry_.new_ascii_("em;'>")
, Comment_marker = Bry_.new_ascii_("<!--xowa-->")
;
}

View File

@ -38,7 +38,7 @@ public class Poem_nde_tst {
, "</div>"
));
}
@Test public void Indent() {
@Test public void Nbsp_basic() {
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "<poem>"
, "a 1"
@ -57,7 +57,7 @@ public class Poem_nde_tst {
, "</div>"
));
}
@Test public void Indent_2() { // PURPOSE: indent on 1st line caused page_break
@Test public void Nbsp_line_0() {// PURPOSE: indent on 1st line caused page_break
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "<poem>"
, " a"
@ -76,22 +76,30 @@ public class Poem_nde_tst {
, "</div>"
));
}
@Test public void List() {
@Test public void Nbsp_blank_lines() {// PURPOSE: check blank lines; PAGE:none
fxt.Test_parse_page_wiki_str(String_.Concat_lines_nl_skip_last
( "<poem>"
, ":a"
, ":b"
, " a"
, " "
, " "
, " b"
, "</poem>"
), String_.Concat_lines_nl_skip_last
( "<div class=\"poem\">"
, "<p>"
, ""
, "<dl>"
, " <dd>a"
, " </dd>"
, " <dd>b"
, " </dd>"
, "</dl>"
, "&#160;&#160;a<br/>"
, "&#160;&#160;<br/>"
, "&#160;&#160;<br/>"
, "&#160;&#160;b"
, "</p>"
, "</div>"
));
}
@Test public void Comment() {
fxt.Test_parse_page_wiki_str("<poem>a<!-- b --> c</poem>", String_.Concat_lines_nl_skip_last
( "<div class=\"poem\">"
, "<p>"
, "a c"
, "</p>"
, "</div>"
));
@ -104,7 +112,6 @@ public class Poem_nde_tst {
));
fxt.Test_parse_page_all_str(String_.Concat_lines_nl_skip_last
( "{{test_outer}}"
// ( "{{test_print|a <poem>b}}c</poem>}}"
), String_.Concat_lines_nl_skip_last
( "a <div class=\"poem\">"
, "<p>"
@ -114,16 +121,7 @@ public class Poem_nde_tst {
));
fxt.Init_defn_clear();
}
@Test public void Comment() {
fxt.Test_parse_page_wiki_str("<poem>a<!-- b --> c</poem>", String_.Concat_lines_nl_skip_last
( "<div class=\"poem\">"
, "<p>"
, "a c"
, "</p>"
, "</div>"
));
}
@Test public void Err_empty_line() {
@Test public void Err_empty_line() {// PURPOSE: one \n caused poem to fail
fxt.Test_parse_page_wiki_str("<poem>\n</poem>", String_.Concat_lines_nl_skip_last
( "<div class=\"poem\">"
, "<p>"
@ -133,8 +131,7 @@ public class Poem_nde_tst {
));
}
@Test public void Ref() { // PURPOSE: <ref> inside poem was not showing up; DATE:2014-01-17
fxt.Test_parse_page_all_str
( String_.Concat_lines_nl_skip_last
fxt.Test_parse_page_all_str(String_.Concat_lines_nl_skip_last
( "<poem>a<ref>b</ref></poem>"
, "<references/>"), String_.Concat_lines_nl_skip_last
( "<div class=\"poem\">"
@ -178,4 +175,99 @@ public class Poem_nde_tst {
, "</div>de"
));
}
@Test public void Indent_line_0() { // PURPOSE: handle colon on 1st line; PAGE:en.w:Mary_Wollstonecraft DATE:2014-10-19
fxt.Test_parse_page_all_str(String_.Concat_lines_nl_skip_last
( "<poem>"
, ":a"
, ":b"
, "</poem>"
), String_.Concat_lines_nl_skip_last
( "<div class=\"poem\">"
, "<p>"
, "<span class='mw-poem-indented' style='display: inline-block; margin-left: 1em;'>a</span><br/>"
, "<span class='mw-poem-indented' style='display: inline-block; margin-left: 1em;'>b</span>"
, "</p>"
, "</div>"
));
}
@Test public void Indent_many() { // PURPOSE: handle colon on 2nd line; PAGE:vi.s:Văn_Côi_thánh_nguyệt_tán_tụng_thi_ca DATE:2014-10-15
fxt.Test_parse_page_all_str(String_.Concat_lines_nl_skip_last
( "<poem>"
, "a"
, ":b"
, "::c"
, "</poem>"
), String_.Concat_lines_nl_skip_last
( "<div class=\"poem\">"
, "<p>"
, "a<br/>"
, "<span class='mw-poem-indented' style='display: inline-block; margin-left: 1em;'>b</span><br/>"
, "<span class='mw-poem-indented' style='display: inline-block; margin-left: 2em;'>c</span>"
, "</p>"
, "</div>"
));
}
@Test public void Indent_blank() { // PURPOSE: check blank lines; PAGE:none DATE:2014-10-19
fxt.Test_parse_page_all_str(String_.Concat_lines_nl_skip_last
( "<poem>"
, ":a"
, ":"
, ":b"
, "</poem>"
), String_.Concat_lines_nl_skip_last
( "<div class=\"poem\">"
, "<p>"
, "<span class='mw-poem-indented' style='display: inline-block; margin-left: 1em;'>a</span><br/>"
, "<span class='mw-poem-indented' style='display: inline-block; margin-left: 1em;'></span><br/>"
, "<span class='mw-poem-indented' style='display: inline-block; margin-left: 1em;'>b</span>"
, "</p>"
, "</div>"
));
}
@Test public void List_does_not_end() {// PURPOSE: list does not end with "\ntext"; PAGE:vi.s:Dương_Từ_Hà_Mậu_(dị_bản_mới); li.s:Sint_Servaes_legende/Nuuj_fergmènter DATE:2014-10-19
fxt.Test_parse_page_all_str(String_.Concat_lines_nl_skip_last
( "<poem>"
, "a"
, "*b"
, "**c"
, "d"
, "</poem>"
), String_.Concat_lines_nl_skip_last
( "<div class=\"poem\">"
, "<p>"
, "a<br/>"
, "<ul>"
, " <li>b<br/>"
, " <ul>"
, " <li>c<br/>"
, " </li>"
, " </ul>"
, " </li>"
, "</ul>"
, "d" // was being embedded directly after <li>c
, "</p>"
, "</div>"
));
}
@Test public void Page() { // PURPOSE: handled dangling poems across pages; PAGE:ca.s:Llibre_de_Disputació_de_l'Ase DATE:2014-10-19
fxt.Init_xtn_pages();
fxt.Init_page_create("Page:A/1", "<poem>a\nb\n");
fxt.Init_page_create("Page:A/2", "<poem>c\nd\n");
fxt.Test_parse_page_wiki_str("<pages index=\"A\" from=1 to=2 />", String_.Concat_lines_nl_skip_last
( "<p><div class=\"poem\">"
, "<p>"
, "a<br/>"
, "b<br/>"
, " <div class=\"poem\">"
, "<p>"
, "c<br/>" // NOTE: 1 <br/> not 2
, "d<br/>"
, " "
, "</p>"
, "</div>"
, "</p>"
, "</div>"
, "</p>"
));
}
}

View File

@ -21,7 +21,7 @@ public class Poem_xtn_mgr extends Xox_mgr_base {
@Override public Xox_mgr Clone_new() {return new Poem_xtn_mgr();}
public Xop_parser Parser() {return parser;} private Xop_parser parser;
@Override public void Xtn_init_by_wiki(Xow_wiki wiki) {
parser = new Xop_parser(wiki, wiki.Parser().Tmpl_lxr_mgr(), Xop_lxr_mgr.Poem_lxr_mgr);
parser = new Xop_parser(wiki, wiki.Parser().Tmpl_lxr_mgr(), wiki.Parser().Wtxt_lxr_mgr());
parser.Init_by_wiki(wiki);
parser.Init_by_lang(wiki.Lang());
}

View File

@ -19,12 +19,7 @@ package gplx.xowa.xtns.proofreadPage; import gplx.*; import gplx.xowa.*; import
import org.junit.*;
public class Pp_pages_nde_recursion_tst {
private Xop_fxt fxt = new Xop_fxt();
@Before public void Init() {
Io_mgr._.InitEngine_mem();
fxt.Wiki().Xtn_mgr().Xtn_proofread().Enabled_y_();
fxt.Wiki().Db_mgr().Load_mgr().Clear(); // must clear; otherwise fails b/c files get deleted, but wiki.data_mgr caches the Xowd_regy_mgr (the .reg file) in memory;
fxt.Wiki().Ns_mgr().Add_new(Xowc_xtn_pages.Ns_page_id_default, "Page").Add_new(Xowc_xtn_pages.Ns_index_id_default, "Index").Init();
}
@Before public void Init() {fxt.Init_xtn_pages();}
@After public void term() {
fxt.Wiki().Cache_mgr().Free_mem_all();
}

View File

@ -20,6 +20,7 @@ public class Int_2_val {
public Int_2_val(int v0, int v1) {val_0 = v0; val_1 = v1;}
public int Val_0() {return val_0;} final int val_0;
public int Val_1() {return val_1;} final int val_1;
public String Xto_str(Bry_bfr bfr) {return Xto_str(bfr, val_0, val_1);}
public static final Int_2_val Null_ptr = null;
public static Int_2_val parse_(String raw) {
String[] itms = String_.Split(raw, ',');
@ -28,4 +29,5 @@ public class Int_2_val {
int v1 = Int_.parse_or_(itms[1], Int_.MinValue); if (v1 == Int_.MinValue) return Null_ptr;
return new Int_2_val(v0, v1);
}
public static String Xto_str(Bry_bfr bfr, int x, int y) {return bfr.Add_int_variable(x).Add_byte_comma().Add_int_variable(y).Xto_str_and_clear();}
}

View File

@ -66,9 +66,9 @@ public class Xoa_css_extractor {
this.lang_is_ltr = wiki.Lang().Dir_ltr();
this.wiki_code = wiki.Domain_abrv();
mainpage_html = Mainpage_download_html();
Logo_setup();
Css_common_setup();
Css_wiki_setup();
Logo_setup();
}
public void Css_common_setup() {
if (opt_download_css_common)
@ -95,14 +95,6 @@ public class Xoa_css_extractor {
if (Io_mgr._.ExistsFil(css_commons_url)) return css_commons_url; // specific css exists for wiki; use it; EX: xowa_common_wiki_mediawikiwiki.css
return failover_dir.GenSubFil(lang_is_ltr ? Css_common_name_ltr : Css_common_name_rtl);
}
// private boolean Css_common_download(Io_url trg_fil) { // DELETE: replaced with Css_scrape; DATE:2014-02-11
// String src_fil = String_.Format(css_stylesheet_common_src_fmt, String_.new_utf8_(wiki_domain));
// String log_msg = usr_dlg.Prog_many("", "", "downloading css common: '~{0}'", src_fil);
// boolean rv = download_xrg.Prog_fmt_hdr_(log_msg).Src_(src_fil).Trg_(trg_fil).Exec();
// if (!rv)
// usr_dlg.Warn_many("", "", "failed to download css_common: src_url=~{0};", src_fil);
// return rv;
// }
public void Css_wiki_setup() {
boolean css_stylesheet_wiki_missing = true;
Io_url trg_fil = wiki_html_dir.GenSubFil(Css_wiki_name);
@ -141,6 +133,7 @@ public class Xoa_css_extractor {
private boolean Logo_download(Io_url trg_fil) {
String src_fil = Logo_find_src();
if (src_fil == null) {
if (Logo_copy_from_css(trg_fil)) return true;
usr_dlg.Warn_many("", "", "failed to extract logo: trg_fil=~{0};", trg_fil.Raw());
return false;
}
@ -150,6 +143,19 @@ public class Xoa_css_extractor {
usr_dlg.Warn_many("", "", "failed to download logo: src_url=~{0};", src_fil);
return rv;
}
private boolean Logo_copy_from_css(Io_url trg_fil) {
Io_url commons_file = wiki_html_dir.GenSubFil(Css_common_name);
byte[] commons_src = Io_mgr._.LoadFilBry(commons_file);
int bgn_pos = Bry_finder.Find_fwd(commons_src, Bry_mw_wiki_logo); if (bgn_pos == Bry_finder.Not_found) return false;
bgn_pos += Bry_mw_wiki_logo.length;
int end_pos = Bry_finder.Find_fwd(commons_src, Byte_ascii.Quote, bgn_pos + 1); if (end_pos == Bry_finder.Not_found) return false;
byte[] src_bry = Bry_.Mid(commons_src, bgn_pos, end_pos);
if (Op_sys.Cur().Tid_is_wnt())
src_bry = Bry_.Replace(src_bry, Byte_ascii.Slash, Byte_ascii.Backslash);
Io_url src_fil = wiki_html_dir.GenSubFil(String_.new_utf8_(src_bry));
Io_mgr._.CopyFil(src_fil, trg_fil, true);
return true;
} private static final byte[] Bry_mw_wiki_logo = Bry_.new_ascii_(".mw-wiki-logo{background-image:url(\"");
private String Logo_find_src() {
if (mainpage_html == null) return null;
int main_page_html_len = mainpage_html.length;

View File

@ -25,6 +25,13 @@ public class Xoa_css_extractor_basic_tst {
fxt.Exec_logo_setup();
fxt.Test_fil("mem/xowa/user/anonymous/wiki/en.wikipedia.org/html/logo.png", "download");
}
@Test public void Logo_download_mw_wiki_logo() {
fxt.Init_fil("mem/http/en.wikipedia.org" , "");
fxt.Init_fil("mem/xowa/user/anonymous/wiki/en.wikipedia.org/html/wiki.png" , "download");
fxt.Init_fil("mem/xowa/user/anonymous/wiki/en.wikipedia.org/html/xowa_common.css" , ".mw-wiki-logo{background-image:url(\"wiki.png\");");
fxt.Exec_logo_setup();
fxt.Test_fil("mem/xowa/user/anonymous/wiki/en.wikipedia.org/html/logo.png" , "download");
}
@Test public void Logo_failover() {
fxt.Init_fil("mem/xowa/bin/any/html/xowa/import/logo.png" , "failover");
fxt.Exec_logo_setup();

View File

@ -27,7 +27,7 @@ public class Xoi_dump_mgr implements GfoInvkAble {
public boolean Wiki_storage_type_is_sql() {return wiki_storage_type == Wiki_storage_type_sqlite;}
public String Db_ns_map() {return db_ns_map;} private String db_ns_map = "Template~Module";
public boolean Css_wiki_update() {return css_wiki_update;} private boolean css_wiki_update = true;
public boolean Css_commons_download() {return css_commons_download;} private boolean css_commons_download = false;
public boolean Css_commons_download() {return css_commons_download;} private boolean css_commons_download = true; // changed from false to true; DATE:2014-10-19
public boolean Delete_xml_file() {return delete_xml_file;} private boolean delete_xml_file = true;
public byte Search_version() {return search_version;} private byte search_version = gplx.xowa.specials.search.Xosrh_core.Version_2;
public boolean Import_bz2_by_stdout() {return import_bz2_by_stdout;} private boolean import_bz2_by_stdout = true;

View File

@ -41,6 +41,7 @@ public class Xoa_page {
public boolean Missing() {return missing;} public Xoa_page Missing_() {return Missing_(true);} public Xoa_page Missing_(boolean v) {missing = v; return this;} private boolean missing;
public boolean Redirected() {return redirected;} public Xoa_page Redirected_(boolean v) {redirected = v; return this;} private boolean redirected;
public ListAdp Redirected_ttls() {return redirected_ttls;} private ListAdp redirected_ttls = ListAdp_.new_();
public byte[] Redirected_ttls__itm_0() {return (byte[])redirected_ttls.FetchAt(0);}
public byte[] Redirected_src() {return redirected_src;} public void Redirected_src_(byte[] v) {this.redirected_src = v;} private byte[] redirected_src;
public byte Edit_mode() {return edit_mode;} private byte edit_mode; public void Edit_mode_update_() {edit_mode = Xoa_page_.Edit_mode_update;}
public Xop_root_tkn Root() {return root;} public Xoa_page Root_(Xop_root_tkn v) {root = v; return this;} private Xop_root_tkn root;

View File

@ -148,10 +148,11 @@ public class Xoa_url_parser {
}
else { // parse failed; url doesn't have protocol
byte[] wiki_bry = rv.Wiki_bry();
if (Bry_.Len_gt_0(wiki_bry)) { // NOTE: wiki_bry null when passing in Category:A from home_wiki
Xow_xwiki_itm xwiki_itm = app.User().Wiki().Xwiki_mgr().Get_by_key(wiki_bry); // see if url.Wiki_bry is actually wiki;
if (Bry_.Len_gt_0(wiki_bry)) { // NOTE: wiki_bry is null when passing in Category:A from home_wiki
Xow_xwiki_itm xwiki_itm = app.User().Wiki().Xwiki_mgr().Get_by_key(wiki_bry); // check if url.Wiki_bry is actually wiki; note that checking User().Wiki().Xwiki_mgr() to find "offline" wikis
if ( xwiki_itm != null // null-check
&& !xwiki_itm.Type_is_xwiki_lang(cur_wiki.Lang().Lang_id())) // in xwiki, but not lang; EX: "fr.wikipedia.org" vs "fr"; ca.s:So/Natura_del_so; DATE:2014-04-26
&& Bry_.Eq(xwiki_itm.Domain(), wiki_bry) // check that xwiki.domain == wiki; avoids false lang matches like "so/page" or "C/page"; EX: "fr.wikipedia.org" vs "fr"; ca.s:So/Natura_del_so; DATE:2014-04-26; PAGE:no.b:C/Variabler; DATE:2014-10-14
)
wiki = app.Wiki_mgr().Get_by_key_or_make(xwiki_itm.Domain());
}
if (rv.Page_bry() == null) { // 1 seg; EX: "Earth"; "fr.wikipedia.org"

View File

@ -25,6 +25,10 @@ public class Xoa_url_parser_basic_tst {
@Test public void Abrv() { // deprecate; no longer needed with shortcuts
fxt.Expd_wiki("en.wikipedia.org").Expd_page("A").Test_parse_w_wiki("en.wikipedia.org/A");
}
@Test public void Commons() { // PURPOSE: "C" was being picked up as an xwiki to commons; PAGE:no.b:C/Variabler; DATE:2014-10-14
fxt.Init_xwiki("c", "commons.wikimedia.org"); // add alias of "C"
fxt.Expd_wiki("en.wikipedia.org").Expd_page("C/D").Test_parse_w_wiki("C/D"); // should use default wiki of enwiki, not commons; also, page should be "C/D", not "D"
}
@Test public void Http_basic() {
fxt.Expd_wiki("en.wikipedia.org").Expd_page("A").Test_parse_w_wiki("http://en.wikipedia.org/wiki/A");
}
@ -144,6 +148,7 @@ class Xoa_url_parser_chkr implements Tst_chkr {
public Xoa_url_parser_chkr Expd_anchor(String v) {this.expd_anchor = v; return this;} private String expd_anchor;
public Xoa_url_parser_chkr Expd_action_is_edit_y() {this.expd_anchor_is_edit = Bool_.Y_byte; return this;} private byte expd_anchor_is_edit = Bool_.__byte;
public Xoa_url_parser_chkr Expd_action_is_edit_n() {this.expd_anchor_is_edit = Bool_.N_byte; return this;}
public void Init_xwiki(String alias, String domain) {app.User().Wiki().Xwiki_mgr().Add_full(alias, domain);}
public int Chk(Tst_mgr mgr, String path, Object actl_obj) {
Xoa_url actl = (Xoa_url)actl_obj;
int rv = 0;

View File

@ -400,5 +400,11 @@ public class Xop_fxt {
Xol_kwd_grp kwd_grp = kwd_mgr.Get_or_new(kwd_id);
kwd_grp.Srl_load(case_match, Bry_.Ary(kwds));
}
public void Init_xtn_pages() {
Io_mgr._.InitEngine_mem();
wiki.Xtn_mgr().Xtn_proofread().Enabled_y_();
wiki.Db_mgr().Load_mgr().Clear(); // must clear; otherwise fails b/c files get deleted, but wiki.data_mgr caches the Xowd_regy_mgr (the .reg file) in memory;
wiki.Ns_mgr().Add_new(Xowc_xtn_pages.Ns_page_id_default, "Page").Add_new(Xowc_xtn_pages.Ns_index_id_default, "Index").Init();
}
public void Clear_ref_mgr() {this.Page().Ref_mgr().Grps_clear();} // clear to reset count
}

View File

@ -64,20 +64,6 @@ public class Xop_lxr_mgr {
, Xop_under_lxr._
});
}
public static final Xop_lxr_mgr Poem_lxr_mgr // NOTE: can't go into gplx.xowa.xtn.poems b/c lxrs below are not public
= new Xop_lxr_mgr(new Xop_lxr[]
{ Xop_pipe_lxr._, new Xop_eq_lxr(false), Xop_space_lxr._, Xop_tab_lxr._
, Xop_amp_lxr._, Xop_apos_lxr._, Xop_colon_lxr._
, Xop_lnki_lxr_bgn._, Xop_lnki_lxr_end._
, Xop_list_lxr._
, Xop_hdr_lxr._
, Xop_hr_lxr._
, Xop_xnde_lxr._
, Xop_lnke_lxr._, Xop_lnke_end_lxr._
, Xop_tblw_lxr._
, gplx.xowa.xtns.poems.Poem_lxr_nl._
, gplx.xowa.xtns.poems.Poem_lxr_pre._
});
public static final Xop_lxr_mgr Popup_lxr_mgr // same as orig_page, except apos_lxr added
= new Xop_lxr_mgr(new Xop_lxr[]
{ Xop_pipe_lxr._, new Xop_eq_lxr(true), Xop_colon_lxr._, Xop_space_lxr._, Xop_tab_lxr._, Xop_nl_lxr._

View File

@ -60,8 +60,8 @@ public class Xop_tkn_mkr {
public Xop_pre_tkn Para_pre_bgn(int pos) {return new Xop_pre_tkn(pos, pos, Xop_pre_tkn.Pre_tid_bgn, null);}
public Xop_pre_tkn Para_pre_end(int pos, Xop_tkn_itm bgn) {return new Xop_pre_tkn(pos, pos, Xop_pre_tkn.Pre_tid_end, bgn);}
public Xop_ignore_tkn Ignore(int bgn, int end, byte ignore_type) {return new Xop_ignore_tkn(bgn, end, ignore_type);}
public Xop_bry_tkn Bry(int bgn, int end, byte[] bry) {return new Xop_bry_tkn(bgn, end, bry);}
public Xop_bry_tkn Bry(byte[] src, int bgn, int end) {return new Xop_bry_tkn(bgn, end, Bry_.Mid(src, bgn, end));}
public Xop_bry_tkn Bry_raw(int bgn, int end, byte[] bry) {return new Xop_bry_tkn(bgn, end, bry);}
public Xop_bry_tkn Bry_mid(byte[] src, int bgn, int end) {return new Xop_bry_tkn(bgn, end, Bry_.Mid(src, bgn, end));}
public Xop_under_tkn Under(int bgn, int end, int v) {return new Xop_under_tkn(bgn, end, v);}
public gplx.xowa.xtns.xowa_cmds.Xop_xowa_cmd Xnde_xowa_cmd() {return new gplx.xowa.xtns.xowa_cmds.Xop_xowa_cmd();}
public gplx.xowa.xtns.poems.Poem_nde Xnde_poem() {return new gplx.xowa.xtns.poems.Poem_nde();}

View File

@ -140,7 +140,7 @@ public class Xop_lnki_wkr implements Xop_ctx_wkr, Xop_arg_wkr {
int subs_len = val_tkn.Subs_len();
Xop_tkn_itm caption_val_tkn = ((Arg_nde_tkn)cur_caption_tkn).Val_tkn();
int pipe_bgn = caption_val_tkn.Src_bgn(); // for bookeeping purposes, assign | pos to same pos as val_tkn; note that pos really shouldn't be used; DATE:2014-05-05
caption_val_tkn.Subs_add(ctx.Tkn_mkr().Bry(pipe_bgn, pipe_bgn + 1, Const_pipe)); // NOTE: add pipe once for entire caption tkn; used to add for every val tkn; DATE:2014-06-08
caption_val_tkn.Subs_add(ctx.Tkn_mkr().Bry_raw(pipe_bgn, pipe_bgn + 1, Const_pipe)); // NOTE: add pipe once for entire caption tkn; used to add for every val tkn; DATE:2014-06-08
for (int i = 0 ; i < subs_len; i++) {
Xop_tkn_itm sub_itm = val_tkn.Subs_get(i);
caption_val_tkn.Subs_add(sub_itm);

View File

@ -127,7 +127,7 @@ public class Xop_lnki_wkr_ {
&& lnki.Ttl() != null // only change "]]]" to "]" + "]]" if lnki is not title; otherwise [[A]]] -> "A]" which will be invalid; PAGE:en.w:Tall_poppy_syndrome DATE:2014-07-23
) {
Xop_tkn_itm caption_val_tkn = lnki.Caption_val_tkn();
caption_val_tkn.Subs_add(tkn_mkr.Bry(cur_pos, cur_pos + 1, Byte_ascii.Brack_end_bry)); // add "]" as bry
caption_val_tkn.Subs_add(tkn_mkr.Bry_raw(cur_pos, cur_pos + 1, Byte_ascii.Brack_end_bry)); // add "]" as bry
caption_val_tkn.Src_end_(caption_val_tkn.Src_end() + 1);
return true;
}

View File

@ -222,7 +222,7 @@ public class Xop_xnde_wkr implements Xop_ctx_wkr {
else if (len == 2 && src[cur_pos] == Byte_ascii.Lt
&& src[cur_pos + 1] == Byte_ascii.Slash) bry = Bry_escape_lt_slash;
else bry = Bry_.Add(Html_entity_.Lt_bry, Bry_.Mid(src, bgn_pos + 1, cur_pos)); // +1 to skip <
return tkn_mkr.Bry(bgn_pos, cur_pos, bry);
return tkn_mkr.Bry_raw(bgn_pos, cur_pos, bry);
}
private int Make_noinclude(Xop_ctx ctx, Xop_tkn_mkr tkn_mkr, Xop_root_tkn root, byte[] src, int src_len, int bgn_pos, int gtPos, Xop_xnde_tag tag, int tag_end_pos, boolean tag_is_closing) {
tag_end_pos = Bry_finder.Find_fwd_while(src, tag_end_pos, src_len, Byte_ascii.Space);// NOTE: must skip spaces else "<noinclude />" will not work with safesubst; PAGE:en.w:Wikipedia:Featured_picture_candidates; DATE:2014-06-24
@ -312,7 +312,7 @@ public class Xop_xnde_wkr implements Xop_ctx_wkr {
if ( page.Html_data().Html_restricted()
&& page.Wiki().Domain_tid() != Xow_wiki_domain_.Tid_home) {
int end_pos = gtPos + 1;
ctx.Subs_add(root, tkn_mkr.Bry(bgn_pos, end_pos, Bry_.Add(gplx.html.Html_entity_.Lt_bry, Bry_.Mid(src, bgn_pos + 1, end_pos)))); // +1 to skip <
ctx.Subs_add(root, tkn_mkr.Bry_raw(bgn_pos, end_pos, Bry_.Add(gplx.html.Html_entity_.Lt_bry, Bry_.Mid(src, bgn_pos + 1, end_pos)))); // +1 to skip <
return end_pos;
}
}
@ -472,7 +472,7 @@ public class Xop_xnde_wkr implements Xop_ctx_wkr {
}
}
if (end_tag.Restricted()) // restricted tags (like <script>) are not placed on stack; for now, just write it out
ctx.Subs_add(root, tkn_mkr.Bry(bgn_pos, cur_pos, Bry_.Add(gplx.html.Html_entity_.Lt_bry, Bry_.Mid(src, bgn_pos + 1, cur_pos)))); // +1 to skip <
ctx.Subs_add(root, tkn_mkr.Bry_raw(bgn_pos, cur_pos, Bry_.Add(gplx.html.Html_entity_.Lt_bry, Bry_.Mid(src, bgn_pos + 1, cur_pos)))); // +1 to skip <
else {
if (pre2_pending) {
pre2_pending = false;
@ -482,7 +482,7 @@ public class Xop_xnde_wkr implements Xop_ctx_wkr {
if (end_tag.Xtn()) // if xtn end tag, ignore it; tidy / browser doesn't know about xtn_tags like "</poem>" so these need to be hidden, else they will show; DATE:2014-07-22
ctx.Subs_add(root, tkn_mkr.Ignore(bgn_pos, cur_pos, Xop_ignore_tkn.Ignore_tid_xnde_dangling));
else // regular tag; show it; depend on tidy to clean up; DATE:2014-07-22
ctx.Subs_add(root, tkn_mkr.Bry(src, bgn_pos, cur_pos));
ctx.Subs_add(root, tkn_mkr.Bry_mid(src, bgn_pos, cur_pos));
}
}
ctx.Para().Process_block__xnde(end_tag, end_tag.Block_close());