From b56673c56e803a1d0593265b083abaf564e6b9ca Mon Sep 17 00:00:00 2001 From: gnosygnu Date: Sat, 28 Mar 2020 10:33:04 -0400 Subject: [PATCH] HTTP Server: Url-encode urls in portal div [#572] --- .../gplx/xowa/htmls/hrefs/Xoh_href_wtr.java | 20 +++++++++++ .../xowa/htmls/portal/Xow_portal_mgr.java | 30 ++++++++++++----- .../xowa/htmls/portal/Xow_portal_mgr_tst.java | 33 +++++++++++++++---- .../src/gplx/xowa/wikis/metas/Xow_user.java | 1 + 4 files changed, 69 insertions(+), 15 deletions(-) diff --git a/400_xowa/src/gplx/xowa/htmls/hrefs/Xoh_href_wtr.java b/400_xowa/src/gplx/xowa/htmls/hrefs/Xoh_href_wtr.java index 7651f8f96..95acb0901 100644 --- a/400_xowa/src/gplx/xowa/htmls/hrefs/Xoh_href_wtr.java +++ b/400_xowa/src/gplx/xowa/htmls/hrefs/Xoh_href_wtr.java @@ -20,10 +20,30 @@ import gplx.xowa.wikis.xwikis.*; public class Xoh_href_wtr { // TS:do not move to app-level private final Gfo_url_encoder encoder = Gfo_url_encoder_.New__html_href_mw(Bool_.Y).Make(); private final Bry_bfr encoder_bfr = Bry_bfr_.Reset(255), tmp_bfr = Bry_bfr_.Reset(255); + public byte[] Build_to_bry(Xow_wiki wiki, byte[] ttl_bry) { + Xoa_ttl ttl = wiki.Ttl_parse(ttl_bry); + Build_to_bfr(tmp_bfr, wiki.App(), Xoh_wtr_ctx.Basic, wiki.Domain_bry(), ttl); + return tmp_bfr.To_bry_and_clear(); + } public byte[] Build_to_bry(Xow_wiki wiki, Xoa_ttl ttl) { Build_to_bfr(tmp_bfr, wiki.App(), Xoh_wtr_ctx.Basic, wiki.Domain_bry(), ttl); return tmp_bfr.To_bry_and_clear(); } + public byte[] Build_to_bry(Bry_bfr tmp, Xow_wiki wiki, Xoa_ttl ttl) { + this.Build_to_bfr(tmp, wiki.App(), wiki.Domain_bry(), ttl); + return tmp.To_bry_and_clear(); + } + public byte[] Build_to_bry_w_qargs(Bry_bfr tmp, Xow_wiki wiki, Xoa_ttl ttl, byte[]... qargs_ary) { + this.Build_to_bfr(tmp, wiki.App(), wiki.Domain_bry(), ttl); + int qargs_len = qargs_ary.length / 2; + for (int i = 0; i < qargs_len; i++) { + tmp.Add_byte(i == 0 ? Byte_ascii.Question : Byte_ascii.Eq); + tmp.Add(qargs_ary[i]); + tmp.Add_byte(Byte_ascii.Eq); + tmp.Add(qargs_ary[i + 1]); + } + return tmp.To_bry_and_clear(); + } public void Build_to_bfr(Bry_bfr bfr, Xoa_app app, byte[] domain_bry, Xoa_ttl ttl) {Build_to_bfr(bfr, app, Xoh_wtr_ctx.Basic, domain_bry, ttl);} public void Build_to_bfr(Bry_bfr bfr, Xoa_app app, Xoh_wtr_ctx hctx, byte[] domain_bry, Xoa_ttl ttl) { // given ttl, write href; EX: A -> '/wiki/A' int hctx_mode = hctx.Mode(); diff --git a/400_xowa/src/gplx/xowa/htmls/portal/Xow_portal_mgr.java b/400_xowa/src/gplx/xowa/htmls/portal/Xow_portal_mgr.java index ed4709789..79fadc76d 100644 --- a/400_xowa/src/gplx/xowa/htmls/portal/Xow_portal_mgr.java +++ b/400_xowa/src/gplx/xowa/htmls/portal/Xow_portal_mgr.java @@ -107,12 +107,16 @@ public class Xow_portal_mgr implements Gfo_invk { public byte[] Div_personal_bry(boolean from_hdump) { Bry_bfr tmp_bfr = wiki.Utl__bfr_mkr().Get_b512(); + Xoh_href_wtr href_wtr = wiki.Html__href_wtr(); byte[] wiki_user_name = wiki.User().Name(); + byte[] user_href = href_wtr.Build_to_bry(wiki, Bry_.Add(wiki.Ns_mgr().Ids_get_or_null(Xow_ns_.Tid__user).Name_db_w_colon(), wiki_user_name)); + byte[] talk_href = href_wtr.Build_to_bry(wiki, Bry_.Add(wiki.Ns_mgr().Ids_get_or_null(Xow_ns_.Tid__user_talk).Name_db_w_colon(), wiki_user_name)); + byte[] rv = Init_fmtr(tmp_bfr, wiki.Eval_mgr(), div_personal_fmtr - , Bry_.Add(Xoh_href_.Bry__wiki, wiki.Ns_mgr().Ids_get_or_null(Xow_ns_.Tid__user).Name_db_w_colon(), wiki_user_name) + , user_href , wiki_user_name , Ns_cls_by_id(wiki.Ns_mgr(), Xow_ns_.Tid__user) - , Bry_.Add(Xoh_href_.Bry__wiki, wiki.Ns_mgr().Ids_get_or_null(Xow_ns_.Tid__user_talk).Name_db_w_colon(), wiki_user_name) + , talk_href , Ns_cls_by_id(wiki.Ns_mgr(), Xow_ns_.Tid__user_talk) , indicators_pagesource_enabled ? (from_hdump ? indicators_pagesource_html : indicators_pagesource_wtxt) @@ -136,9 +140,10 @@ public class Xow_portal_mgr implements Gfo_invk { } // NOTE: need to escape args href for Search page b/c user can enter in quotes and apos; EX:localhost:8080/en.wikipedia.org/wiki/Special:XowaSearch?search=title:(%2Breturn%20%2B"abc") ; DATE:2017-07-16 + Xoh_href_wtr href_wtr = wiki.Html__href_wtr(); Bry_bfr tmp_bfr = bfr_mkr.Get_k004(); - byte[] subj_href = Xoh_html_wtr_escaper.Escape(Xop_amp_mgr.Instance, tmp_bfr, Bry_.Add(Xoh_href_.Bry__wiki, ttl.Subj_url())); - byte[] talk_href = Xoh_html_wtr_escaper.Escape(Xop_amp_mgr.Instance, tmp_bfr, Bry_.Add(Xoh_href_.Bry__wiki, ttl.Talk_url())); + byte[] subj_href = href_wtr.Build_to_bry(wiki, ttl.Subj_txt()); + byte[] talk_href = href_wtr.Build_to_bry(wiki, ttl.Talk_txt()); div_ns_fmtr.Bld_bfr_many(tmp_bfr, subj_href, subj_cls, talk_href, talk_cls, vnt_menu); return tmp_bfr.To_bry_and_rls(); @@ -152,7 +157,13 @@ public class Xow_portal_mgr implements Gfo_invk { return ns == null || ns.Exists() ? Bry_.Empty : missing_ns_cls; } public byte[] Div_view_bry(Bry_bfr_mkr bfr_mkr, byte output_tid, byte[] search_text, Xoa_ttl ttl) { + // generate url-encoded ttls for view / edit / html; ISSUE#:572 PAGE:en.w:.07%; DATE:2020-03-28 Bry_bfr tmp_bfr = bfr_mkr.Get_k004(); + Xoh_href_wtr href_wtr = wiki.Html__href_wtr(); + byte[] view_ttl = href_wtr.Build_to_bry(tmp_bfr, wiki, ttl); + byte[] edit_ttl = href_wtr.Build_to_bry_w_qargs(tmp_bfr, wiki, ttl, Xoa_url_.Qarg__action, Xoa_url_.Qarg__action__edit); + byte[] html_ttl = href_wtr.Build_to_bry_w_qargs(tmp_bfr, wiki, ttl, Xoa_url_.Qarg__action, Xoa_url_.Qarg__action__html); + byte[] read_cls = Bry_.Empty, edit_cls = Bry_.Empty, html_cls = Bry_.Empty; switch (output_tid) { case Xopg_view_mode_.Tid__read: read_cls = Cls_selected_y; break; @@ -160,12 +171,10 @@ public class Xow_portal_mgr implements Gfo_invk { case Xopg_view_mode_.Tid__html: html_cls = Cls_selected_y; break; } - // build url_fragment with action query argument; EX: "/wiki/Page_name?action=" - byte[] url_frag_w_action_qarg = Bry_.Add(Xoh_href_.Bry__wiki, ttl.Full_db(), Byte_ascii.Question_bry, Xoa_url_.Qarg__action, Byte_ascii.Eq_bry); div_view_fmtr.Bld_bfr_many(tmp_bfr, read_cls, edit_cls, html_cls, search_text - , Bry_.Add(Xoh_href_.Bry__wiki, ttl.Full_db()) - , Bry_.Add(url_frag_w_action_qarg, Xoa_url_.Qarg__action__edit) - , Bry_.Add(url_frag_w_action_qarg, Xoa_url_.Qarg__action__html) + , view_ttl + , edit_ttl + , html_ttl , wiki.Props().Site_name() ); @@ -198,6 +207,9 @@ public class Xow_portal_mgr implements Gfo_invk { , div_wikis_fmtr = Bry_fmtr.new_("", "toggle_btn", "toggle_hdr") ; public Bry_fmtr Div_logo_fmtr() {return div_logo_fmtr;} // TEST: + public Bry_fmtr Div_view_fmtr() {return div_view_fmtr;} // TEST: + public Bry_fmtr Div_ns_fmtr() {return div_ns_fmtr;} // TEST: + public Bry_fmtr Div_personal_fmtr() {return div_personal_fmtr;} // TEST: private byte[] Reverse_li(byte[] bry) { return lang_is_rtl ? Xoh_rtl_utl.Reverse_li(bry) : bry; } diff --git a/400_xowa/src/gplx/xowa/htmls/portal/Xow_portal_mgr_tst.java b/400_xowa/src/gplx/xowa/htmls/portal/Xow_portal_mgr_tst.java index 162dab39d..bc1d8e381 100644 --- a/400_xowa/src/gplx/xowa/htmls/portal/Xow_portal_mgr_tst.java +++ b/400_xowa/src/gplx/xowa/htmls/portal/Xow_portal_mgr_tst.java @@ -15,15 +15,13 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt */ package gplx.xowa.htmls.portal; import gplx.*; import gplx.xowa.*; import gplx.xowa.htmls.*; import org.junit.*; import gplx.core.tests.*; +import gplx.xowa.wikis.pages.*; public class Xow_portal_mgr_tst { @Before public void init() {fxt.Init();} private Xowh_portal_mgr_fxt fxt = new Xowh_portal_mgr_fxt(); @Test public void Div_ns_bry() { fxt.Test_div_ns_bry("A" , "/wiki/A;selected;/wiki/Talk:A;xowa_display_none;"); fxt.Test_div_ns_bry("Talk:A" , "/wiki/A;;/wiki/Talk:A;selected;"); } - @Test public void Div_personal_bry() { - fxt.Test_div_personal_bry("/wiki/User:anonymous;anonymous;xowa_display_none;/wiki/User_talk:anonymous;xowa_display_none;"); - } @Test public void Missing_ns_cls() { fxt.Test_missing_ns_cls("xowa_display_none"); } @@ -55,6 +53,21 @@ public class Xow_portal_mgr_tst { , " " ), fxt.Portal_mgr().Div_jump_to()); } + @Test public void Div_personal() { + fxt.Wiki().User().Name_(Bry_.new_a7("anonymous")); + fxt.Test__div_personal("/wiki/User:Anonymous;anonymous;xowa_display_none;/wiki/User_talk:Anonymous;xowa_display_none;"); + } + @Test public void Div_personal__url() { + fxt.Wiki().User().Name_(Bry_.new_a7("A%")); + fxt.Test__div_personal("/wiki/User:A%25;A%;xowa_display_none;/wiki/User_talk:A%25;xowa_display_none;"); + } + @Test public void Div_ns() { + fxt.Test__div_ns("A%", "/wiki/A%25;selected;/wiki/Talk:A%25;xowa_display_none;"); + } + @Test public void Div_view() { // PURPOSE: ensure that ttl is url-encoded; ISSUE#:572 PAGE:en.w:.07%; DATE:2020-03-28 + fxt.Wiki().Html_mgr().Portal_mgr().Div_view_fmtr().Fmt_("~{portal_view_read_href};~{portal_view_edit_href};~{portal_view_html_href}"); + fxt.Test__div_view(Xopg_view_mode_.Tid__read, "A%", "/wiki/A%25;/wiki/A%25?action=edit;/wiki/A%25?action=html"); + } } class Xowh_portal_mgr_fxt { private Xow_portal_mgr portal_mgr; @@ -72,9 +85,6 @@ class Xowh_portal_mgr_fxt { public void Test_div_ns_bry(String ttl, String expd) { Tfds.Eq(expd, String_.new_a7(wiki.Html_mgr().Portal_mgr().Div_ns_bry(wiki.Utl__bfr_mkr(), Xoa_ttl.Parse(wiki, Bry_.new_a7(ttl)), wiki.Ns_mgr()))); } - public void Test_div_personal_bry(String expd) { - Tfds.Eq(expd, String_.new_a7(wiki.Html_mgr().Portal_mgr().Div_personal_bry(false))); - } public void Test_missing_ns_cls(String expd) { Tfds.Eq(expd, String_.new_a7(wiki.Html_mgr().Portal_mgr().Missing_ns_cls())); } @@ -83,4 +93,15 @@ class Xowh_portal_mgr_fxt { String actl = String_.new_a7(wiki.Html_mgr().Portal_mgr().Div_logo_bry(nightmode)); Gftest.Eq__str(expd, actl); } + public void Test__div_personal(String expd) { + Tfds.Eq(expd, String_.new_a7(wiki.Html_mgr().Portal_mgr().Div_personal_bry(false))); + } + public void Test__div_view(byte output_tid, String ttl_str, String expd) { + Xoa_ttl ttl = wiki.Ttl_parse(Bry_.new_u8(ttl_str)); + Gftest.Eq__ary__lines(expd, String_.new_u8(wiki.Html_mgr().Portal_mgr().Div_view_bry(app.Utl__bfr_mkr(), output_tid, Bry_.Empty, ttl))); + } + public void Test__div_ns(String ttl_str, String expd) { + Xoa_ttl ttl = wiki.Ttl_parse(Bry_.new_u8(ttl_str)); + Gftest.Eq__ary__lines(expd, String_.new_u8(wiki.Html_mgr().Portal_mgr().Div_ns_bry(app.Utl__bfr_mkr(), ttl, wiki.Ns_mgr()))); + } } diff --git a/400_xowa/src/gplx/xowa/wikis/metas/Xow_user.java b/400_xowa/src/gplx/xowa/wikis/metas/Xow_user.java index a6aa2f63e..28aa6e979 100644 --- a/400_xowa/src/gplx/xowa/wikis/metas/Xow_user.java +++ b/400_xowa/src/gplx/xowa/wikis/metas/Xow_user.java @@ -16,6 +16,7 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt package gplx.xowa.wikis.metas; import gplx.*; import gplx.xowa.*; import gplx.xowa.wikis.*; public class Xow_user implements Gfo_invk { public byte[] Name() {return name;} private byte[] name = Bry_.new_a7("anonymous"); + public void Name_(byte[] v) {this.name = v;} public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) { if (ctx.Match(k, Invk_name_)) name = m.ReadBry("v"); else return Gfo_invk_.Rv_unhandled;