1
0
mirror of https://github.com/gnosygnu/xowa.git synced 2026-03-02 03:49:30 +00:00
This commit is contained in:
gnosygnu
2015-07-12 21:10:02 -04:00
commit 794b5a232f
3099 changed files with 238212 additions and 0 deletions

View File

@@ -0,0 +1,95 @@
/*
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; import gplx.*;
import gplx.xowa.html.hrefs.*;
public class Xoa_url {
public byte[] Raw() {return raw;} public Xoa_url Raw_(byte[] v) {raw = v; return this;} private byte[] raw = Bry_.Empty;
public byte[] Wiki_bry() {return wiki_bry;} public Xoa_url Wiki_bry_(byte[] v) {wiki_bry = v; return this;} private byte[] wiki_bry;
public byte[] Page_bry() {return page_bry;} public Xoa_url Page_bry_(byte[] v) {page_bry = v; return this;} private byte[] page_bry;
public byte[] Anchor_bry() {return anchor_bry;} public Xoa_url Anchor_bry_(byte[] v) {anchor_bry = v; return this;} private byte[] anchor_bry = null;
public String Anchor_str() {return anchor_bry == null ? null : String_.new_u8(anchor_bry);}
public Gfo_url_arg[] Args() {return args;} public Xoa_url Args_(Gfo_url_arg[] v) {args = v; return this;} private Gfo_url_arg[] args = Gfo_url_arg.Ary_empty;
public Xoa_url_arg_hash Args_hash() {if (args_hash == null) args_hash = new Xoa_url_arg_hash().Load(this); return args_hash;} private Xoa_url_arg_hash args_hash;
public byte Protocol_tid() {return protocol_tid;} public Xoa_url Protocol_tid_(byte v) {protocol_tid = v; return this;} private byte protocol_tid;
public byte[] Protocol_bry() {return protocol_bry;} public Xoa_url Protocol_bry_(byte[] v) {protocol_bry = v; return this;} private byte[] protocol_bry;
public boolean Protocol_is_relative() {return protocol_is_relative;} public Xoa_url Protocol_is_relative_(boolean v) {protocol_is_relative = v; return this;} private boolean protocol_is_relative;
public byte[] Use_lang() {return use_lang;} public Xoa_url Use_lang_(byte[] v) {use_lang = v; return this;} private byte[] use_lang;
public byte[] Lang_bry() {return lang_bry;} public Xoa_url Lang_bry_(byte[] v) {lang_bry = v; return this;} private byte[] lang_bry;
public byte[] Xowa_vnt() {return xowa_vnt;} public void Xowa_vnt_(byte[] v) {xowa_vnt = v;} private byte[] xowa_vnt;
public boolean Redirect_force() {return redirect_force;} public Xoa_url Redirect_force_(boolean v) {redirect_force = v; return this;} private boolean redirect_force;
public boolean Search_fulltext() {return search_fulltext;} public Xoa_url Search_fulltext_(boolean v) {search_fulltext = v; return this;} private boolean search_fulltext;
public boolean Action_is_edit() {return action_is_edit;} public Xoa_url Action_is_edit_(boolean v) {action_is_edit = v; return this;} private boolean action_is_edit;
public byte Err() {return err;} public Xoa_url Err_(byte v) {err = v; return this;} private byte err;
public byte[][] Segs_ary() {return segs_ary;} public Xoa_url Segs_ary_(byte[][] v) {segs_ary = v; return this;} private byte[][] segs_ary;
public byte[] Page_for_lnki() {
int raw_len = raw.length;
int page_bgn = Page_bgn(raw_len);
if (page_bgn == Bry_.NotFound) // no /wiki/ found; return page
return page_bry == null ? Bry_.Empty : page_bry; // guard against null ref
else
return Bry_.Mid(raw, page_bgn, raw_len);// else take everything after "/wiki/";
}
public void Init(byte[] raw) {
this.raw = raw;
segs_ary = null;
lang_bry = wiki_bry = page_bry = anchor_bry = use_lang = xowa_vnt = null;
err = 0;
protocol_is_relative = false;
redirect_force = false;
action_is_edit = false;
}
public boolean Args_exists(byte[] key, byte[] val) {
int args_len = args.length;
for (int i = 0; i < args_len; i++) {
Gfo_url_arg arg = args[i];
if ( Bry_.Eq(arg.Key_bry(), key)
&& Bry_.Eq(arg.Val_bry(), val))
return true;
}
return false;
}
public byte[] Args_all_as_bry() {
int args_len = args.length;
if (args_len == 0) return Bry_.Empty;
Bry_bfr bfr = Bry_bfr.new_();
for (int i = 0; i < args_len; i++) {
Gfo_url_arg arg = args[i];
bfr.Add_byte(i == 0 ? Byte_ascii.Question : Byte_ascii.Amp);
bfr.Add(arg.Key_bry());
bfr.Add_byte(Byte_ascii.Eq);
bfr.Add(arg.Val_bry());
}
return bfr.Xto_bry_and_clear();
}
private int Page_bgn(int raw_len) {
int wiki_pos = Bry_finder.Find_fwd(raw, Xoh_href_parser.Href_wiki_bry, 0, raw_len); // look for /wiki/
return wiki_pos == Bry_.NotFound ? Bry_.NotFound : wiki_pos + Xoh_href_parser.Href_wiki_bry.length;
}
public boolean Eq_page(Xoa_url comp) {return Bry_.Eq(wiki_bry, comp.wiki_bry) && Bry_.Eq(page_bry, comp.page_bry) && redirect_force == comp.Redirect_force();}
public byte[] Xto_full_bry() {return wiki_bry == null ? page_bry : Bry_.Add(wiki_bry, Xoa_consts.Url_wiki_intermediary, page_bry);}
public String Xto_full_str() {return String_.new_u8(this.Xto_full_bry());}
public String Xto_full_str_safe() {try {return Xto_full_str();} catch (Exception e) {return gplx.Err_.Message_gplx_brief(e);}}
public static final Xoa_url Null = null;
public static Xoa_url blank_() {return new Xoa_url();}
public static Xoa_url new_(byte[] wiki, byte[] page) {
Xoa_url rv = new Xoa_url();
rv.Wiki_bry_(wiki);
rv.Page_bry_(page);
return rv;
} Xoa_url() {}
}

View File

@@ -0,0 +1,76 @@
/*
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; import gplx.*;
public class Xoa_url_arg_hash {
private Ordered_hash hash = Ordered_hash_.new_bry_();
public Gfo_url_arg Get_arg(byte[] key) {return (Gfo_url_arg)hash.Get_by(key);}
public int Get_val_int_or(byte[] key, int or) {
byte[] val_bry = Get_val_bry_or(key, null); if (val_bry == null) return or;
return Bry_.Xto_int_or(val_bry, or);
}
public byte[] Get_val_bry_or(byte[] key, byte[] or) {
Gfo_url_arg arg = (Gfo_url_arg)hash.Get_by(key);
return arg == null ? or : arg.Val_bry();
}
public String Get_val_str_or(byte[] key, String or) {
Gfo_url_arg arg = (Gfo_url_arg)hash.Get_by(key);
return arg == null ? or : String_.new_u8(arg.Val_bry());
}
public void Set_val_by_int(byte[] key, int val) {Set_val_by_bry(key, Bry_.new_a7(Int_.Xto_str(val)));}
public void Set_val_by_bry(byte[] key, byte[] val) {
Gfo_url_arg arg = (Gfo_url_arg)hash.Get_by(key);
if (arg == null) {
arg = new Gfo_url_arg(key, Bry_.Empty);
hash.Add(key, arg);
}
arg.Val_bry_(val);
}
public byte[] Concat(Bry_bfr bfr, byte[]... ary) {
int ary_len = ary.length;
for (int i = 0; i < ary_len; i++) {
byte[] key = ary[i];
Gfo_url_arg itm = Get_arg(key); if (itm == null) continue;
bfr.Add_byte(Byte_ascii.Amp).Add(itm.Key_bry()).Add_byte(Byte_ascii.Eq).Add(itm.Val_bry());
}
return bfr.Xto_bry_and_clear();
}
public Xoa_url_arg_hash Load(Xoa_url url) {
hash.Clear();
Gfo_url_arg[] ary = url.Args();
int ary_len = ary.length;
for (int i = 0; i < ary_len; i++) {
Gfo_url_arg itm = ary[i];
hash.Add(itm.Key_bry(), itm);
}
return this;
}
public void Save(Xoa_url url) {
Gfo_url_arg[] ary = (Gfo_url_arg[])hash.To_ary(Gfo_url_arg.class);
url.Args_(ary);
}
public static void Concat_bfr(Bry_bfr bfr, Url_encoder href_encoder, Gfo_url_arg[] ary) {
int ary_len = ary.length;
for (int i = 0; i < ary_len; i++) {
Gfo_url_arg itm = ary[i];
bfr.Add_byte(i == 0 ? Byte_ascii.Question : Byte_ascii.Amp);
href_encoder.Encode(bfr, itm.Key_bry());
bfr.Add_byte(Byte_ascii.Eq);
href_encoder.Encode(bfr, itm.Val_bry());
}
}
}

View File

@@ -0,0 +1,307 @@
/*
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; import gplx.*;
import gplx.core.primitives.*;
import gplx.xowa.langs.*; import gplx.xowa.wikis.*; import gplx.xowa.wikis.xwikis.*; import gplx.xowa.net.*; import gplx.xowa.files.*;
import gplx.xowa.html.hrefs.*;
public class Xoa_url_parser {
private final Url_encoder encoder = Url_encoder.new_html_href_mw_().Itms_raw_same_many(Byte_ascii.Underline); private final Bry_bfr tmp_bfr = Bry_bfr.reset_(255);
public Gfo_url_parser Url_parser() {return url_parser;} private Gfo_url_parser url_parser = new Gfo_url_parser(); private Gfo_url gfo_url = new Gfo_url();
public String Build_str(Xoa_url url) { // transform to "canonical" form that fits url box for both XOWA and Mozilla Firefox
tmp_bfr.Add(url.Wiki_bry()); // add wiki; EX: "en.wikipedia.org"
tmp_bfr.Add(Xoh_href_parser.Href_wiki_bry); // add "/wiki/" EX: "/wiki/"
tmp_bfr.Add(encoder.Decode(url.Page_bry())); // add page; EX: "A"
int args_len = url.Args().length;
if (args_len > 0) {
for (int i = 0; i < args_len; i++) {
byte dlm = i == 0 ? Byte_ascii.Question : Byte_ascii.Amp;
tmp_bfr.Add_byte(dlm);
Gfo_url_arg arg = url.Args()[i];
tmp_bfr.Add(arg.Key_bry()).Add_byte(Byte_ascii.Eq).Add(arg.Val_bry());
}
}
if (url.Anchor_bry() != null)
tmp_bfr.Add_byte(Byte_ascii.Hash).Add(url.Anchor_bry()); // add anchor; EX: "#B"
return tmp_bfr.Xto_str_and_clear();
}
public Xoa_url Parse(byte[] src) {
Xoa_url rv = Xoa_url.blank_();
Parse(rv, src);
return rv;
}
private boolean Parse(Xoa_url url, byte[] src, int bgn, int end) {return Parse(url, Bry_.Mid(src, bgn, end));}
public boolean Parse(Xoa_url url, byte[] src) {
url.Init(src); // NOTE: need to call init to clear state; Xoa_url is often reused
src = encoder.Decode(src); // decode any url-encoded parameters
int src_len = src.length;
url_parser.Parse(gfo_url, src, 0, src_len); // parse protocol
byte protocol_tid = gfo_url.Protocol_tid();
url.Protocol_tid_(gfo_url.Protocol_tid()); // NOTE: set protocol early b/c file may exit below; DATE:2014-04-25
url.Protocol_bry_(gfo_url.Protocol_bry());
if (protocol_tid == Xoo_protocol_itm.Tid_file && src_len > 5 && src[5] != Byte_ascii.Slash) { // file ns; EX: "File:A.png"; NOTE: for file:A.png, assume "file" refers to wiki_ns (File:), not protocol; hackish as it relies on looking for / after "file:" to distinguish between MW "File:A.png" and file system "file:///C/A.png"
url.Raw_(src);
url.Wiki_bry_(gfo_url.Raw());
return false;
}
url.Protocol_is_relative_(gfo_url.Protocol_is_relative());
url.Err_(gfo_url.Err());
url.Raw_(src);
if (gfo_url.Site() != null && Bry_.Eq(gfo_url.Site(), Bry_upload_wikimedia_org)) { // handle urls like "http://upload.wikimedia.org/wikipedia/commons/a/ab/C.svg"
byte[][] segs_ary = gfo_url.Segs();
byte[] domain_bry = segs_ary[0]; // type seems to be the 1st seg ; EX: "/wikipedia/"
byte[] sub_bry = segs_ary[1]; // lang/type seems to be 2nd seg; EX: "en", "fr"; "commons"
byte[] lang_bry = sub_bry;
if (upload_segs_hash.Has(sub_bry)) { // wikimedia links will have fmt of "/wikipedia/commons"; must change to wikimedia
domain_bry = Xow_domain_type_.Key_bry_wikimedia;
lang_bry = Xol_lang_itm_.Key__unknown;
}
tmp_bfr.Clear().Add(sub_bry).Add_byte(Byte_ascii.Dot) // add lang/type + .; EX: "en."; "fr."; "commons."
.Add(domain_bry).Add(Bry_dot_org); // add type + .org; EX: "wikipedia.org"; "wikimedia.org";
url.Segs_ary_(Xoa_url_parser.Bry_wiki_name_bry); // NOTE: add "wiki" as seg else will have "/site/commons.wikimedia.org/File:A" which will be invalid (needs to be "/site/commons.wikimedia.org/wiki/File:A")
url.Lang_bry_(lang_bry);
url.Wiki_bry_(tmp_bfr.Xto_bry_and_clear());
byte[][] segs = gfo_url.Segs();
byte[] page_bry = segs.length > 5 && Bry_.Eq(segs[2], Xof_url_bldr.Bry_thumb) ? segs[5] : gfo_url.Page();
url.Page_bry_(tmp_bfr.Add(Bry_file).Add(page_bry).Xto_bry_and_clear());
url.Anchor_bry_(Bry_.Empty);
}
else {
url.Segs_ary_(gfo_url.Segs());
url.Lang_bry_(gfo_url.Site_sub());
url.Wiki_bry_(gfo_url.Site());
url.Page_bry_(gfo_url.Page());
url.Anchor_bry_(gfo_url.Anchor());
}
Gfo_url_arg[] args = gfo_url.Args(); // parse args
int args_len = args.length;
boolean args_is_invalid = false;
for (int i = 0; i < args_len; i++) {
Gfo_url_arg arg = args[i];
byte[] key = arg.Key_bry();
if (Bry_.Len_eq_0(key)) {
args_is_invalid = true;
break;
}
Object o = qry_args_hash.Get_by_bry(key);
if (o != null) {
Byte_obj_val id = (Byte_obj_val)o;
switch (id.Val()) {
case Id_arg_redirect: url.Redirect_force_(true); break;
case Id_arg_uselang: url.Use_lang_(arg.Val_bry()); break;
case Id_arg_action: if (Bry_.Eq(arg.Val_bry(), Bry_arg_action_edit)) url.Action_is_edit_(true); break;
case Id_arg_title: url.Page_bry_(arg.Val_bry()); url.Segs_ary_(Segs_ary_remove_w(url.Segs_ary())); break; // handle /w/index.php?title=Earth
case Id_arg_fulltext: url.Search_fulltext_(true); break;
case Id_arg_xowa_vnt: url.Xowa_vnt_(arg.Val_bry()); ; break;
}
}
}
if (args_is_invalid) {
byte[] raw_bry = gfo_url.Raw();
byte[] args_bry = Bry_.Mid(raw_bry, gfo_url.Args_bgn(), raw_bry.length);
byte[] anchor_bry = url.Anchor_bry();
if (anchor_bry == null) // no anchor; set page to rest of url
url.Page_bry_(Bry_.Add(url.Page_bry(), args_bry));
else
url.Anchor_bry_(Bry_.Add(url.Anchor_bry(), args_bry));
}
else
url.Args_(args);
return url.Err() == Gfo_url.Err_none;
}
private static byte[][] Segs_ary_remove_w(byte[][] ary) {
int len = ary.length;
if (len != 1) return ary; // expecting only "w"
byte[] last = ary[0];
return last.length == 1 && last[0] == Byte_ascii.Ltr_w // last is not "w"
? Bry_.Ary_empty
: ary
;
}
public static Xoa_url Parse_url(Xoa_app app, Xow_wiki cur_wiki, String raw) {
byte[] raw_bry = Bry_.new_u8(raw);
return Parse_url(Xoa_url.blank_(), app, cur_wiki, raw_bry, 0, raw_bry.length, false);
}
public static Xoa_url Parse_url(Xoa_app app, Xow_wiki cur_wiki, byte[] raw, int bgn, int end, boolean from_url_bar) {return Parse_url(Xoa_url.blank_(), app, cur_wiki, raw, bgn, end, from_url_bar);}
public static Xoa_url Parse_url(Xoa_url rv, Xoa_app app, Xow_wiki cur_wiki, byte[] raw, int bgn, int end, boolean from_url_bar) {
Xow_wiki wiki = null; Bry_bfr_mkr bfr_mkr = app.Utl__bfr_mkr();
byte[] cur_wiki_key = cur_wiki.Domain_bry();
byte[] page_bry = Bry_.Empty;
boolean page_is_main_page = false;
if (app.Utl__url_parser().Parse(rv, raw, bgn, end)) { // parse passed; url has protocol; take Page; EX: "http://en.wikipedia.org/wiki/Earth"
wiki = Parse_url__wiki(app, rv.Wiki_bry());
if (rv.Segs_ary().length == 0 && rv.Page_bry() != null && Bry_.Eq(rv.Page_bry(), Xoa_url_parser.Bry_wiki_name)) // wiki, but directly after site; EX:en.wikipedia.org/wiki
page_is_main_page = true;
else
page_bry = Parse_url__combine(bfr_mkr, null, rv.Segs_ary(), rv.Page_bry()); // NOTE: pass null in for wiki b/c wiki has value, but should not be used for Page
}
else { // parse failed; url doesn't have protocol
byte[] wiki_bry = rv.Wiki_bry();
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().Wikii().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
&& Bry_.Eq(xwiki_itm.Domain_bry(), 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_mgri().Get_by_key_or_make_init_n(xwiki_itm.Domain_bry());
}
if (rv.Page_bry() == null) { // 1 seg; EX: "Earth"; "fr.wikipedia.org"
if (wiki != null) { // wiki_bry is known wiki; EX: "fr.wikipedia.org"
wiki = app.Wiki_mgri().Get_by_key_or_make_init_n(wiki_bry); // call get again, but this time "make" it
page_is_main_page = true;
}
else { // otherwise, assume page name
wiki = Parse_url__wiki(app, cur_wiki_key);
page_bry = wiki_bry;
}
}
else { // 2+ segs
if (wiki != null) { // valid wiki; handle en.wikisource.org/Hamlet and en.wikisource.org/Hamlet/Act I
if (rv.Segs_ary().length == 0 && Bry_.Eq(rv.Page_bry(), Xoa_url_parser.Bry_wiki_name))
page_is_main_page = true;
else
page_bry = Parse_url__combine(bfr_mkr, Xoa_page_.Main_page_bry_empty, rv.Segs_ary(), rv.Page_bry());
}
else { // invalid wiki; assume cur_wiki; EX: Hamlet/Act I
page_bry = rv.Page_bry();
byte[][] segs_ary = rv.Segs_ary();
if (segs_ary.length > 0)
page_bry = segs_ary[0];
int colon_pos = Bry_finder.Find_fwd(page_bry, Byte_ascii.Colon); // check for alias; EX: w:Earth
boolean xwiki_set = false;
if (colon_pos != Bry_.NotFound) { // alias found
Xow_xwiki_itm xwiki = cur_wiki.Xwiki_mgr().Get_by_mid(page_bry, 0, colon_pos);
if (xwiki != null) {
wiki = app.Wiki_mgri().Get_by_key_or_make_init_n(xwiki.Domain_bry());
page_bry = Bry_.Mid(page_bry, colon_pos + 1, page_bry.length);
if (rv.Segs_ary().length == 0) // handle xwiki without segs; EX: commons:Commons:Media_of_the_day; DATE:2014-02-19
rv.Segs_ary_(new byte[][] {Bry_wiki_name, page_bry}); // create segs of "/wiki/Page"
else {
rv.Segs_ary()[0] = page_bry;
page_bry = Parse_url__combine(bfr_mkr, rv.Wiki_bry(), rv.Segs_ary(), rv.Page_bry());
}
xwiki_set = true;
}
}
if (!xwiki_set) {
wiki = Parse_url__wiki(app, cur_wiki_key);
page_bry = Parse_url__combine(bfr_mkr, rv.Wiki_bry(), rv.Segs_ary(), rv.Page_bry());
}
}
}
}
if (page_is_main_page) { // Main_Page requested; EX: "zh.wikipedia.org"; "zh.wikipedia.org/wiki/"; DATE:2014-02-16
if (from_url_bar) {
wiki.Init_by_wiki(); // NOTE: must call Init_assert to load Main_Page; only call if from url_bar, else all sister wikis will be loaded when parsing Sister_wikis panel
page_bry = wiki.Props().Main_page();
}
else
page_bry = Xoa_page_.Main_page_bry_empty;
}
if (rv.Anchor_bry() != null) {
byte[] anchor_bry = Xoa_app_.Utl__encoder_mgr().Id().Encode(rv.Anchor_bry()); // reencode for anchors (which use . encoding, not % encoding); PAGE:en.w:Enlightenment_Spain#Enlightened_despotism_.281759%E2%80%931788.29
rv.Anchor_bry_(anchor_bry);
}
Xoa_ttl ttl = wiki.Ttl_parse(page_bry);
if (ttl != null) { // can still be empty; EX: "en.wikipedia.org"
Xow_xwiki_itm lang_xwiki = ttl.Wik_itm();
if (lang_xwiki != null && lang_xwiki.Type_is_xwiki_lang(wiki.Lang().Lang_id())) { // format of http://en.wikipedia.org/wiki/fr:A
wiki = app.Wiki_mgri().Get_by_key_or_make_init_n(lang_xwiki.Domain_bry());
page_bry = ttl.Page_txt();
}
}
rv.Wiki_bry_(wiki.Domain_bry());
rv.Page_bry_(page_bry);
return rv;
}
private static Xow_wiki Parse_url__wiki(Xoa_app app, byte[] key) {
Xow_wiki rv = null;
Xow_xwiki_itm xwiki = app.User().Wikii().Xwiki_mgr().Get_by_key(key);
if (xwiki == null)
rv = app.User().Wikii();
else
rv = app.Wiki_mgri().Get_by_key_or_make_init_n(xwiki.Domain_bry());
return rv;
}
private static byte[] Parse_url__combine(Bry_bfr_mkr bry_bfr_mkr, byte[] wiki, byte[][] segs, byte[] page) {
Bry_bfr bfr = bry_bfr_mkr.Get_b512();
if (wiki != null) bfr.Add(wiki);
if (segs != null) {
int segs_len = segs.length;
for (int i = 0; i < segs_len; i++) {
byte[] seg = segs[i];
if (i == 0 && Bry_.Eq(seg, Xoa_url_parser.Bry_wiki_name)) continue;
if (bfr.Len() > 0) bfr.Add_byte(Byte_ascii.Slash);
bfr.Add(seg);
}
}
if (page != null) {
if (bfr.Len() > 0) bfr.Add_byte(Byte_ascii.Slash);
bfr.Add(page);
}
return bfr.To_bry_and_rls();
}
public static Xoa_url Parse_from_url_bar(Xoae_app app, Xowe_wiki wiki, String s) {
byte[] bry = Bry_.new_u8(s);
bry = Parse_from_url_bar__strip_mobile(bry);
byte[] fmt = app.Gui_mgr().Url_macro_mgr().Fmt_or_null(bry);
if (fmt != null) bry = fmt;
Xoa_url rv = Xoa_url_parser.Parse_url(app, wiki, bry, 0, bry.length, true);
if (app.Wiki_mgr().Wiki_regy().Url_is_invalid_domain(rv)) { // handle lang_code entered; EX: "war" should redirect to "war" article in current wiki, not war.wikipedia.org; DATE:2014-02-07
rv.Page_bry_(rv.Wiki_bry());
rv.Wiki_bry_(wiki.Domain_bry());
}
return rv;
}
private static byte[] Parse_from_url_bar__strip_mobile(byte[] v) {// DATE:2014-05-03
int pos = Bry_finder.Find_fwd(v, Byte_ascii.Dot);
if ( pos == Bry_finder.Not_found // no dot; EX: "A"
|| pos + 2 >= v.length // not enough space for .m.; EX: "A.b"
)
return v;
switch (v[pos + 1]) { // check for m
case Byte_ascii.Ltr_M:
case Byte_ascii.Ltr_m:
break;
default:
return v;
}
if (v[pos + 2] != Byte_ascii.Dot) return v;
return Bry_.Add(Bry_.Mid(v, 0, pos), Bry_.Mid(v, pos + 2)); // skip ".m"
}
// private static final byte Tid_xowa = (byte)Gfo_url_parser.Protocol_file_tid + 1;
private static final byte Id_arg_redirect = 0, Id_arg_uselang = 1, Id_arg_title = 2, Id_arg_action = 3, Id_arg_fulltext = 4, Id_arg_xowa_vnt = 5;
private static final byte[] Bry_arg_redirect = Bry_.new_a7("redirect"), Bry_arg_uselang = Bry_.new_a7("uselang"), Bry_arg_title = Bry_.new_a7("title"), Bry_arg_fulltext = Bry_.new_a7("fulltext");
private static final byte[] Bry_upload_wikimedia_org = Bry_.new_a7("upload.wikimedia.org"), Bry_dot_org = Bry_.new_a7(".org")
, Bry_file = Bry_.new_a7("File:"); // NOTE: File does not need i18n; is a canonical namespace
public static final byte[] Bry_wiki_name = Bry_.new_a7("wiki");
private static final byte[][] Bry_wiki_name_bry = new byte[][] {Bry_wiki_name};
public static final byte[] Bry_arg_action_eq_edit = Bry_.new_a7("action=edit")
, Bry_arg_action = Bry_.new_a7("action")
, Bry_arg_action_edit = Bry_.new_a7("edit")
, Bry_arg_xowa_vnt = Bry_.new_a7("xowa_vnt")
;
private static final Hash_adp_bry qry_args_hash = Hash_adp_bry.ci_ascii_()
.Add_bry_byte(Bry_arg_redirect, Id_arg_redirect)
.Add_bry_byte(Bry_arg_uselang, Id_arg_uselang)
.Add_bry_byte(Bry_arg_title, Id_arg_title)
.Add_bry_byte(Bry_arg_action, Id_arg_action)
.Add_bry_byte(Bry_arg_fulltext, Id_arg_fulltext)
.Add_bry_byte(Bry_arg_xowa_vnt, Id_arg_xowa_vnt)
;
private static final Hash_adp_bry upload_segs_hash = Hash_adp_bry.ci_ascii_()
.Add_bry_bry(Xow_domain_type_.Key_bry_commons);//.Add_bry_bry(Xow_domain_type_.Key_bry_species_bry).Add_bry_bry(Xow_domain_type_.Key_bry_meta_bry);
}

View File

@@ -0,0 +1,172 @@
/*
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; import gplx.*;
import org.junit.*; import gplx.xowa.wikis.xwikis.*;
public class Xoa_url_parser_basic_tst {
@Before public void init() {fxt.Reset();} private Xoa_url_parser_chkr fxt = new Xoa_url_parser_chkr();
@Test public void Basic() {
fxt.Expd_wiki("en.wikipedia.org").Expd_page("A").Test_parse_w_wiki("en.wikipedia.org/wiki/A");
}
@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");
}
@Test public void Relative() {
fxt.Expd_wiki("en.wikipedia.org").Expd_page("A").Test_parse_w_wiki("//en.wikipedia.org/wiki/A");
}
@Test public void Name() {
fxt.Expd_wiki("en.wikipedia.org").Expd_page("A").Test_parse_w_wiki("A");
}
@Test public void Sub_1() {
fxt.Expd_wiki("en.wikipedia.org").Expd_page("A/b").Test_parse_w_wiki("A/b");
}
@Test public void Sub_2() {
fxt.Expd_wiki("en.wikipedia.org").Expd_page("A/b/c").Test_parse_w_wiki("A/b/c");
}
@Test public void Sub_3() {
fxt.Expd_wiki("en.wikipedia.org").Expd_page("A/b").Test_parse_w_wiki("en.wikipedia.org/wiki/A/b");
}
@Test public void Ns_category() {
fxt.Expd_wiki("en.wikipedia.org").Expd_page("Category:A").Test_parse_w_wiki("Category:A");
}
@Test public void Ns_file() {
fxt.Expd_wiki("en.wikipedia.org").Expd_page("File:A").Test_parse_w_wiki("File:A");
}
@Test public void Anchor() {
fxt.Expd_wiki("en.wikipedia.org").Expd_page("A").Expd_anchor("b").Test_parse_w_wiki("A#b");
}
@Test public void Upload() {
fxt.App().Usere().Wiki().Xwiki_mgr().Add_full("commons.wikimedia.org", "commons.wikimedia.org");
fxt.Reset().Expd_wiki("commons.wikimedia.org").Expd_page("File:C.svg").Test_parse_w_wiki("http://upload.wikimedia.org/wikipedia/commons/a/ab/C.svg");
fxt.Reset().Expd_wiki("commons.wikimedia.org").Expd_page("File:A.png").Test_parse_w_wiki("http://upload.wikimedia.org/wikipedia/commons/thumb/7/70/A.png/220px-A.png");
}
@Test public void Parse_lang() {
Xow_xwiki_mgr xwiki_mgr = fxt.Wiki_en_w().Xwiki_mgr();
xwiki_mgr.Add_full(Bry_.new_a7("fr"), Bry_.new_a7("fr.wikipedia.org"), Bry_.new_a7("http://fr.wikipedia.org/~{0}"));
fxt.Expd_wiki("fr.wikipedia.org").Expd_page("A").Test_parse_w_wiki("http://en.wikipedia.org/wiki/fr:A");
}
@Test public void Alias_wiki() {
Xow_xwiki_mgr xwiki_mgr = fxt.Wiki_en_w().Xwiki_mgr();
xwiki_mgr.Add_full(Bry_.new_a7("s"), Bry_.new_a7("en.wikisource.org"));
fxt.Expd_wiki("en.wikisource.org").Expd_page("A/b/c").Test_parse_w_wiki("s:A/b/c");
}
@Test public void Xwiki_no_segs() { // PURPOSE: handle xwiki without full url; EX: "commons:Commons:Media_of_the_day"; DATE:2014-02-19
Xow_xwiki_mgr xwiki_mgr = fxt.Wiki_en_w().Xwiki_mgr();
xwiki_mgr.Add_full(Bry_.new_a7("s"), Bry_.new_a7("en.wikisource.org"));
fxt.Expd_wiki("en.wikisource.org").Expd_page("Project:A").Test_parse_w_wiki("s:Project:A");
}
@Test public void Domain_only() {
fxt.App().Usere().Wiki().Xwiki_mgr().Add_full("fr.wikipedia.org", "fr.wikipedia.org");
fxt.Expd_wiki("fr.wikipedia.org").Expd_page("").Test_parse_w_wiki("fr.wikipedia.org");
}
@Test public void Domain_and_wiki() {
fxt.App().Usere().Wiki().Xwiki_mgr().Add_full("fr.wikipedia.org", "fr.wikipedia.org");
fxt.Expd_wiki("fr.wikipedia.org").Expd_page("").Test_parse_w_wiki("fr.wikipedia.org/wiki");
}
@Test public void Domain_and_wiki_w_http() {
fxt.App().Usere().Wiki().Xwiki_mgr().Add_full("fr.wikipedia.org", "fr.wikipedia.org");
fxt.Expd_wiki("fr.wikipedia.org").Expd_page("").Test_parse_w_wiki("http://fr.wikipedia.org/wiki");
}
@Test public void Redirect() {
fxt.Expd_wiki("en.wikipedia.org").Expd_page("A").Test_parse_w_wiki("A?redirect=no");
}
@Test public void Namespace_in_different_wiki() { // PURPOSE.fix: namespaced titles would default to default_wiki instead of current_wiki
fxt.Expd_wiki("en.wikisource.org").Expd_page("Category:A").Test_parse_w_wiki(fxt.Wiki_en_s(), "Category:A");
}
@Test public void Action_is_edit() {
fxt.Expd_wiki("en.wikipedia.org").Expd_page("A").Expd_action_is_edit_y().Test_parse_w_wiki("A?action=edit");
}
@Test public void Assert_state_cleared() { // PURPOSE.fix: action_is_edit (et. al.) was not being cleared on parse even though Xoa_url reused; DATE:20121231
byte[] raw = Bry_.new_a7("A?action=edit");
Xoa_url url = Xoa_url_parser.Parse_url(fxt.App(), fxt.Wiki_en_w(), raw, 0, raw.length, false);
Tfds.Eq(true, url.Action_is_edit());
raw = Bry_.new_a7("B");
Xoa_url_parser.Parse_url(url, fxt.App(), fxt.Wiki_en_w(), raw, 0, raw.length, false);
Tfds.Eq(false, url.Action_is_edit());
}
@Test public void Query_arg() { // PURPOSE.fix: query args were not printing out
byte[] raw = Bry_.new_a7("en.wikipedia.org/wiki/Special:Search/Earth?fulltext=yes");
Xoa_url url = Xoa_url_parser.Parse_url(fxt.App(), fxt.Wiki_en_w(), raw, 0, raw.length, false);
Xoa_url_parser parser = new Xoa_url_parser();
Tfds.Eq("en.wikipedia.org/wiki/Special:Search/Earth?fulltext=yes", parser.Build_str(url));
}
@Test public void Anchor_with_slash() { // PURPOSE: A/b#c/d was not parsing correctly
fxt.Expd_page("A/b").Expd_anchor("c.2Fd").Test_parse_w_wiki("A/b#c/d");
}
@Test public void Slash() {
fxt.Reset().Expd_wiki("en.wikipedia.org").Expd_page("/A").Test_parse_w_wiki("en.wikipedia.org/wiki//A");
fxt.Reset().Expd_wiki("en.wikipedia.org").Expd_page("A//b").Test_parse_w_wiki("en.wikipedia.org/wiki/A//b");
fxt.Reset().Expd_wiki("en.wikipedia.org").Expd_page("//A").Test_parse_w_wiki("en.wikipedia.org/wiki///A");
}
@Test public void Question_is_page() {
fxt.Expd_wiki("en.wikipedia.org").Expd_page("A?B").Expd_anchor(null).Test_parse_w_wiki("A?B");
}
@Test public void Question_is_anchor() {
fxt.Expd_wiki("en.wikipedia.org").Expd_page("A").Expd_anchor("b.3Fc").Test_parse_w_wiki("A#b?c");
}
}
class Xoa_url_parser_chkr implements Tst_chkr {
public Xoa_url_parser_chkr Reset() {
if (app == null) {
app = Xoa_app_fxt.app_();
wiki_en_w = Xoa_app_fxt.wiki_(app, "en.wikipedia.org");
wiki_en_s = Xoa_app_fxt.wiki_(app, "en.wikisource.org");
app.Usere().Wiki().Xwiki_mgr().Add_full("en.wikipedia.org", "en.wikipedia.org");
app.Usere().Wiki().Xwiki_mgr().Add_full("en.wikisource.org", "en.wikisource.org");
}
expd_wiki_str = expd_page = expd_anchor = null;
expd_anchor_is_edit = Bool_.__byte;
return this;
}
public Xoae_app App() {return app;} private Xoae_app app;
public Xowe_wiki Wiki_en_w() {return wiki_en_w;} private Xowe_wiki wiki_en_w;
public Xowe_wiki Wiki_en_s() {return wiki_en_s;} private Xowe_wiki wiki_en_s;
public Class<?> TypeOf() {return Xoa_url.class;}
public Xoa_url_parser_chkr Expd_wiki(String v) {this.expd_wiki_str = v; return this;} private String expd_wiki_str;
public Xoa_url_parser_chkr Expd_page(String v) {this.expd_page = v; return this;} private String expd_page;
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.Usere().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;
rv += mgr.Tst_val(expd_wiki_str == null, path, "wiki", expd_wiki_str, String_.new_u8(actl.Wiki_bry()));
rv += mgr.Tst_val(expd_page == null, path, "page", expd_page, String_.new_u8(actl.Page_bry()));
rv += mgr.Tst_val(expd_anchor == null, path, "anchor", expd_anchor, String_.new_u8(actl.Anchor_bry()));
rv += mgr.Tst_val(expd_anchor_is_edit == Bool_.__byte, path, "anchor_is_edit", expd_anchor_is_edit == Bool_.Y_byte, actl.Action_is_edit());
return rv;
}
public Xoa_url_parser_chkr Test_parse_from_url_bar(String raw, String expd) {
Xoa_url actl_url = Xoa_url_parser.Parse_from_url_bar(app, wiki_en_w, raw);
Tfds.Eq(expd, actl_url.Xto_full_str());
return this;
}
public void Test_parse_w_wiki(String raw) {Test_parse_w_wiki(wiki_en_w, raw);}
public void Test_parse_w_wiki(Xowe_wiki w, String raw) {
Xoa_url url = Xoa_url_parser.Parse_url(app, w, raw);
Tst_mgr tst_mgr = new Tst_mgr();
tst_mgr.Tst_obj(this, url);
}
}

View File

@@ -0,0 +1,25 @@
/*
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; import gplx.*;
import org.junit.*;
public class Xoa_url_parser_mw_links_tst {
@Before public void init() {fxt.Reset();} private Xoa_url_parser_chkr fxt = new Xoa_url_parser_chkr();
@Test public void Title_remove_w() { // PURPOSE: fix /w/ showing up as seg; DATE:2014-05-30
fxt.Expd_page("A").Expd_wiki("en.wikipedia.org").Test_parse_w_wiki("http://en.wikipedia.org/w/index.php?title=A");
}
}

View File

@@ -0,0 +1,69 @@
/*
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; import gplx.*;
import org.junit.*;
public class Xoa_url_parser_url_bar_tst {
@Before public void init() {fxt.Reset();} private Xoa_url_parser_chkr fxt = new Xoa_url_parser_chkr();
@Test public void Basic() {
fxt.Test_parse_from_url_bar("Page_1" , "en.wikipedia.org/wiki/Page_1"); // basic
}
@Test public void Lang() {
fxt.App().Usere().Wiki().Xwiki_mgr().Add_full("uk", "uk.wikipedia.org");
fxt.Test_parse_from_url_bar("uk" , "en.wikipedia.org/wiki/uk"); // lang-like page (uk=Ukraine) should not try to open wiki; DATE:2014-02-07
}
@Test public void Lang_like() {
fxt.App().Usere().Wiki().Xwiki_mgr().Add_full(Bry_.new_a7("uk"), Bry_.new_a7("uk.wikipedia.org"), Bry_.new_a7("http://~{1}.wikipedia.org")); // NOTE: fmt needed for Type_is_lang
fxt.Test_parse_from_url_bar("uk/A" , "en.wikipedia.org/wiki/uk/A"); // uk/A should not try be interpreted as wiki="uk" page="A"; DATE:2014-04-26
}
@Test public void Macro() {
fxt.App().Usere().Wiki().Xwiki_mgr().Add_full("fr.wikisource.org", "fr.wikisource.org");
fxt.Test_parse_from_url_bar("fr.s:Auteur:Shakespeare" , "fr.wikisource.org/wiki/Auteur:Shakespeare"); // url_macros
}
@Test public void Home() {
Init_db(fxt.App().Usere().Wiki());
fxt.Test_parse_from_url_bar("home" , "en.wikipedia.org/wiki/home"); // home should go to current wiki's home; DATE:2014-02-09
fxt.Test_parse_from_url_bar("home/wiki/Main_Page" , "home/wiki/Main_Page"); // home Main_Page should go to home; DATE:2014-02-09
}
@Test public void Custom() {
// fxt.App().Usere().Wiki().Xwiki_mgr().Add_full("zh.wikipedia.org", "zh.wikipedia.org");
// gplx.xowa.wikis.Xoa_wiki_regy.Make_wiki_dir(fxt.App(), "zh.wikipedia.org");
// fxt.App().Wiki_mgr().Get_by_key_or_make(Bry_.new_a7("zh.wikipedia.org")).Props().Main_page_(Bry_.new_a7("Zh_Main_Page"));
fxt.App().Usere().Wiki().Xwiki_mgr().Add_full("zh.wikipedia.org", "zh.wikipedia.org");
Xowe_wiki zh_wiki = fxt.App().Wiki_mgr().Get_by_key_or_make(Bry_.new_a7("zh.wikipedia.org"));
Init_db(zh_wiki);
gplx.xowa.wikis.Xoa_wiki_regy.Make_wiki_dir(fxt.App(), "zh.wikipedia.org");
zh_wiki.Props().Main_page_(Bry_.new_a7("Zh_Main_Page"));
fxt.Test_parse_from_url_bar("zh.w:" , "zh.wikipedia.org/wiki/Zh_Main_Page");
fxt.Test_parse_from_url_bar("zh.w:Main_Page" , "zh.wikipedia.org/wiki/Main_Page");
}
@Test public void Mobile() { // PURPOSE: handle mobile links; DATE:2014-05-03
fxt.Test_parse_from_url_bar("en.m.wikipedia.org/wiki/A" , "en.wikipedia.org/wiki/A"); // basic
fxt.Test_parse_from_url_bar("en.M.wikipedia.org/wiki/A" , "en.wikipedia.org/wiki/A"); // upper
fxt.Test_parse_from_url_bar("A" , "en.wikipedia.org/wiki/A"); // bounds-check: 0
fxt.Test_parse_from_url_bar("A." , "en.wikipedia.org/wiki/A."); // bounds-check: 1
fxt.Test_parse_from_url_bar("A.b" , "en.wikipedia.org/wiki/A.b"); // bounds-check: 2
fxt.Test_parse_from_url_bar("A.b.m." , "en.wikipedia.org/wiki/A.b.m."); // false-match
fxt.Test_parse_from_url_bar("en.x.wikipedia.org/wiki/A" , "en.wikipedia.org/wiki/en.x.wikipedia.org/A"); // fail
}
public static void Init_db(Xowe_wiki wiki) {
Xoa_test_.Db_init(true, Xoa_test_.Url_root());
wiki.Ns_mgr().Init_w_defaults();
Xowe_wiki_bldr.Create(wiki, 1, "dump.xml");
wiki.Data__core_mgr().Db__core().Tbl__ns().Insert(wiki.Ns_mgr());
}
}

View File

@@ -0,0 +1,32 @@
/*
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; import gplx.*;
import org.junit.*;
public class Xoa_url_tst {
Xoa_url_fxt fxt = new Xoa_url_fxt();
@Before public void init() {fxt.Clear();}
@Test public void Eq_page() {
fxt.Eq_page_tst(fxt.url_("en.wikipedia.org", "Earth", false), fxt.url_("en.wikipedia.org", "Earth", false), true);
fxt.Eq_page_tst(fxt.url_("en.wikipedia.org", "Earth", false), fxt.url_("en.wikipedia.org", "Earth", true ), false);
}
}
class Xoa_url_fxt {
public void Clear() {}
public Xoa_url url_(String wiki_str, String page_str, boolean redirect_force) {return Xoa_url.blank_().Wiki_bry_(Bry_.new_u8(wiki_str)).Page_bry_(Bry_.new_u8(page_str)).Redirect_force_(redirect_force);}
public void Eq_page_tst(Xoa_url lhs, Xoa_url rhs, boolean expd) {Tfds.Eq(expd, lhs.Eq_page(rhs));}
}