1
0
mirror of https://github.com/gnosygnu/xowa.git synced 2024-09-29 06:50:50 +00:00

Image: Handle image paths with spaces and other URL-encoding

This commit is contained in:
gnosygnu 2016-11-14 15:25:31 -05:00
parent 419367ad9f
commit bca989898e
7 changed files with 196 additions and 66 deletions

View File

@ -35,5 +35,6 @@ public class Xof_orig_wkr_ {
, Tid_wmf_api = 2 , Tid_wmf_api = 2
, Tid_xowa_meta = 3 , Tid_xowa_meta = 3
, Tid_xowa_img_links = 4 , Tid_xowa_img_links = 4
, Tid_mock = 5
; ;
} }

View File

@ -0,0 +1,36 @@
/*
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.files.origs; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.core.flds.*;
import gplx.dbs.*; import gplx.xowa.files.fsdb.*;
import gplx.xowa.wikis.tdbs.metas.*;
public class Xof_orig_wkr__mock implements Xof_orig_wkr {
private final Ordered_hash hash = Ordered_hash_.New_bry();
public byte Tid() {return Xof_orig_wkr_.Tid_mock;}
public void Find_by_list(Ordered_hash rv, List_adp itms) {Xof_orig_wkr_.Find_by_list(this, rv, itms);}
public Xof_orig_itm Find_as_itm(byte[] ttl, int list_idx, int list_len) {
return (Xof_orig_itm)hash.Get_by(ttl); // new Xof_orig_itm((byte)meta_itm.Vrtl_repo(), ttl, Xof_ext_.new_by_ttl_(ttl).Id(), meta_itm.Orig_w(), meta_itm.Orig_h(), meta_itm.Ptr_ttl());
}
public boolean Add_orig(byte repo, byte[] page, int ext_id, int w, int h, byte[] redirect) {
Xof_orig_itm itm = new Xof_orig_itm(repo, page, ext_id, w, h, redirect);
hash.Add(page, itm);
return false;
}
public void Db_txn_save() {}
public void Db_rls() {}
}

View File

@ -1,34 +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.guis.urls; import gplx.*; import gplx.xowa.*; import gplx.xowa.guis.*;
import gplx.xowa.files.*; import gplx.xowa.files.repos.*; import gplx.xowa.files.origs.*;
import gplx.xowa.parsers.lnkis.*;
public class Xof_orig_file_downloader {
public static Xof_fsdb_itm Make_fsdb(Xowe_wiki wiki, byte[] lnki_ttl, Xof_img_size img_size, Xof_url_bldr url_bldr) {
Xof_fsdb_itm fsdb = new Xof_fsdb_itm();
lnki_ttl = Xoa_ttl.Replace_spaces(gplx.langs.htmls.encoders.Gfo_url_encoder_.Http_url.Decode(lnki_ttl));
fsdb.Init_at_lnki(Xof_exec_tid.Tid_viewer_app, wiki.Domain_itm().Abrv_xo(), lnki_ttl, Xop_lnki_type.Id_none, Xop_lnki_tkn.Upright_null, Xof_img_size.Size__neg1, Xof_img_size.Size__neg1, Xof_lnki_time.Null, Xof_lnki_page.Null, Xof_patch_upright_tid_.Tid_all);
fsdb.Init_at_hdoc(Int_.Max_value, Xof_html_elem.Tid_img);// NOTE: set elem_id to "impossible" number, otherwise it will auto-update an image on the page with a super-large size; [[File:Alfred Sisley 062.jpg]]
Xof_orig_itm orig = wiki.File__orig_mgr().Find_by_ttl_or_null(lnki_ttl); if (orig == Xof_orig_itm.Null) return null; // orig not found; need orig in order to get repo
Xof_repo_itm repo = wiki.File__repo_mgr().Get_trg_by_id_or_null(orig.Repo(), lnki_ttl, Bry_.Empty); if (repo == null) return null; // repo not found
fsdb.Init_at_orig(orig.Repo(), repo.Wiki_domain(), orig.Ttl(), orig.Ext(), orig.W(), orig.H(), orig.Redirect());
fsdb.Init_at_html(Xof_exec_tid.Tid_viewer_app, img_size, repo, url_bldr);
fsdb.File_is_orig_(true);
return fsdb;
}
}

View File

@ -24,8 +24,6 @@ import gplx.xowa.guis.views.*;
public class Xog_url_wkr { public class Xog_url_wkr {
private final Xoa_url tmp_url = Xoa_url.blank(); private final Xoa_url tmp_url = Xoa_url.blank();
private Xoae_app app; private Xog_win_itm win; private Xowe_wiki wiki; private Xoae_page page; private Xoae_app app; private Xog_win_itm win; private Xowe_wiki wiki; private Xoae_page page;
private final Xof_img_size img_size = new Xof_img_size(); private final Xof_url_bldr url_bldr = Xof_url_bldr.new_v2();
private final Gfo_url_encoder fsys_lnx_encoder = Gfo_url_encoder_.New__fsys_lnx().Make();
public Xoa_url Parse(Xog_win_itm win, String href_str) { public Xoa_url Parse(Xog_win_itm win, String href_str) {
if (href_str == null) return tmp_url; // text is not link; return; if (href_str == null) return tmp_url; // text is not link; return;
byte[] href_bry = Bry_.new_u8(href_str); byte[] href_bry = Bry_.new_u8(href_str);
@ -38,7 +36,7 @@ public class Xog_url_wkr {
public void Init(Xowe_wiki wiki) { // TEST: public void Init(Xowe_wiki wiki) { // TEST:
this.wiki = wiki; this.wiki = wiki;
} }
public Xoa_url Exec(Xoa_url url) { public Xoa_url Exec_url(Xoa_url url) {
switch (url.Tid()) { switch (url.Tid()) {
case Xoa_url_.Tid_unknown: return Xoa_url.Null; // unknown; return null which will become a noop case Xoa_url_.Tid_unknown: return Xoa_url.Null; // unknown; return null which will become a noop
case Xoa_url_.Tid_inet: return Exec_url_http(app); // http://site.org case Xoa_url_.Tid_inet: return Exec_url_http(app); // http://site.org
@ -64,33 +62,9 @@ public class Xog_url_wkr {
return Rslt_handled; return Rslt_handled;
} }
private Xoa_url Exec_url_file(Xoae_app app, Xowe_wiki cur_wiki, Xoae_page page, Xog_win_itm win, byte[] href_bry) { // EX: file:///xowa/A.png private Xoa_url Exec_url_file(Xoae_app app, Xowe_wiki cur_wiki, Xoae_page page, Xog_win_itm win, byte[] href_bry) { // EX: file:///xowa/A.png
Xowe_wiki wiki = (Xowe_wiki)page.Commons_mgr().Source_wiki_or(cur_wiki); Xog_url_wkr__file wkr = new Xog_url_wkr__file(app, cur_wiki, page);
Io_url href_url = Io_url_.New__http_or_fail(String_.new_u8(Gfo_url_encoder_.Http_url.Decode(href_bry))); wkr.Extract_data(win.Active_html_box().Html_js_eval_proc_as_str(Xog_js_procs.Doc__root_html_get), href_bry);
Gfui_html html_box = win.Active_html_box(); wkr.Download_and_run();
byte[] href_bry_encoded = fsys_lnx_encoder.Encode(href_bry); // encode to href_bry; note must encode to same href_bry as Xof_url_bldr, which uses Gfo_url_encoder_.Fsys_lnx; PAGE:en.w:File:Volc<EFBFBD>n_Chimborazo,_"El_Taita_Chimborazo".jpg DATE:2015-12-06
String xowa_ttl = wiki.Gui_mgr().Cfg_browser().Content_editable()
? html_box.Html_js_eval_proc_as_str(Xog_js_procs.Selection__get_active_for_editable_mode, gplx.xowa.htmls.Xoh_consts.Atr_xowa_title_str, null)
: Xoh_dom_.Title_by_href(href_bry_encoded, Bry_.new_u8(html_box.Html_js_eval_proc_as_str(Xog_js_procs.Doc__root_html_get)));
if (xowa_ttl == null) {
app.Gui_mgr().Kit().Ask_ok("", "", "could not find anchor with href in html: href=~{0}", href_bry);
return Rslt_handled;
}
byte[] lnki_ttl = gplx.langs.htmls.encoders.Gfo_url_encoder_.Http_url.Decode(Xoa_ttl.Replace_spaces(Bry_.new_u8(xowa_ttl)));
Xof_fsdb_itm fsdb = Xof_orig_file_downloader.Make_fsdb(wiki, lnki_ttl, img_size, url_bldr);
if (!Io_mgr.Instance.ExistsFil(href_url)) {
// if (!Xof_orig_file_downloader.Get_to_url(fsdb, href_url, wiki, lnki_ttl, url_bldr))
if (!Xof_file_wkr.Show_img(fsdb, Xoa_app_.Usr_dlg(), wiki.File__bin_mgr(), wiki.File__mnt_mgr(), wiki.App().User().User_db_mgr().Cache_mgr(), wiki.File__repo_mgr(), gplx.xowa.guis.cbks.js.Xog_js_wkr_.Noop, img_size, url_bldr, page))
return Rslt_handled;
}
gplx.core.ios.IoItmFil fil = Io_mgr.Instance.QueryFil(href_url);
if (fil.Exists()) {
Process_adp media_player = app.Prog_mgr().App_by_ext(href_url.Ext());
media_player.Run(href_url);
fsdb.File_size_(fil.Size());
gplx.xowa.files.caches.Xou_cache_mgr cache_mgr = wiki.Appe().User().User_db_mgr().Cache_mgr();
cache_mgr.Update(fsdb);
cache_mgr.Db_save();
}
return Rslt_handled; return Rslt_handled;
} }
private Xoa_url Exec_url_page(Xowe_wiki wiki, byte[] href_bry) { // EX: "Page"; "/wiki/Page"; // rewritten; DATE:2014-01-19 private Xoa_url Exec_url_page(Xowe_wiki wiki, byte[] href_bry) { // EX: "Page"; "/wiki/Page"; // rewritten; DATE:2014-01-19
@ -100,6 +74,8 @@ public class Xog_url_wkr {
public static Xoa_url Exec_url(Xog_win_itm win, String href_str) { public static Xoa_url Exec_url(Xog_win_itm win, String href_str) {
Xog_url_wkr url_wkr = new Xog_url_wkr(); Xog_url_wkr url_wkr = new Xog_url_wkr();
Xoa_url url = url_wkr.Parse(win, href_str); Xoa_url url = url_wkr.Parse(win, href_str);
return url_wkr.Exec(url); return url_wkr.Exec_url(url);
}
public static void Get_href_url() {
} }
} }

View File

@ -0,0 +1,83 @@
/*
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.guis.urls; import gplx.*; import gplx.xowa.*; import gplx.xowa.guis.*;
import gplx.xowa.files.*; import gplx.xowa.files.origs.*; import gplx.xowa.files.repos.*;
import gplx.xowa.htmls.doms.*;
import gplx.xowa.parsers.lnkis.*;
class Xog_url_wkr__file {
private final Xoae_app app;
private final Xowe_wiki page_wiki;
private final Xoae_page page;
private final Xof_img_size img_size = new Xof_img_size();
private final Xof_url_bldr url_bldr = Xof_url_bldr.new_v2();
public Xog_url_wkr__file(Xoae_app app, Xowe_wiki page_wiki, Xoae_page page) {
this.app = app;
this.page_wiki = page_wiki;
this.page = page;
}
public byte[] File_page_db() {return file_page_db;} private byte[] file_page_db;
public Io_url File_url() {return file_url;} private Io_url file_url;
public Xof_fsdb_itm Fsdb() {return fsdb;} private Xof_fsdb_itm fsdb;
public Xowe_wiki File_wiki() {return file_wiki;} private Xowe_wiki file_wiki;
public void Extract_data(String html_doc, byte[] href_bry) { // EX: file:///xowa/A.png
// find xowa_ttl from html_doc for given file; EX: file:///xowa/A.png -> xowa_ttl = "A.png"
String xowa_ttl = Xoh_dom_.Title_by_href(href_bry, Bry_.new_u8(html_doc));
if (xowa_ttl == null) {
app.Gui_mgr().Kit().Ask_ok("", "", "could not find anchor with href in html: href=~{0}", href_bry);
return;
}
// get fsdb itm
this.file_page_db = gplx.langs.htmls.encoders.Gfo_url_encoder_.Http_url.Decode(Xoa_ttl.Replace_spaces(Bry_.new_u8(xowa_ttl)));
this.file_wiki = (Xowe_wiki)page.Commons_mgr().Source_wiki_or(page_wiki);
this.fsdb = Xog_url_wkr__file.Make_fsdb(file_wiki, file_page_db, img_size, url_bldr);
this.file_url = Io_url_.New__http_or_fail(String_.new_u8(gplx.langs.htmls.encoders.Gfo_url_encoder_.Http_url.Decode(href_bry)));
}
public void Download_and_run() {
// download file if it doesn't exist
if (!Io_mgr.Instance.ExistsFil(file_url)) {
if (!Xof_file_wkr.Show_img(fsdb, Xoa_app_.Usr_dlg(), file_wiki.File__bin_mgr(), file_wiki.File__mnt_mgr(), file_wiki.App().User().User_db_mgr().Cache_mgr(), file_wiki.File__repo_mgr(), gplx.xowa.guis.cbks.js.Xog_js_wkr_.Noop, img_size, url_bldr, page))
return;
}
// try to launch file
gplx.core.ios.IoItmFil fil = Io_mgr.Instance.QueryFil(file_url);
if (fil.Exists()) {
gplx.core.envs.Process_adp media_player = app.Prog_mgr().App_by_ext(file_url.Ext());
media_player.Run(file_url);
fsdb.File_size_(fil.Size());
gplx.xowa.files.caches.Xou_cache_mgr cache_mgr = file_wiki.Appe().User().User_db_mgr().Cache_mgr();
cache_mgr.Update(fsdb);
cache_mgr.Db_save();
}
}
public static Xof_fsdb_itm Make_fsdb(Xowe_wiki wiki, byte[] lnki_ttl, Xof_img_size img_size, Xof_url_bldr url_bldr) {
Xof_fsdb_itm fsdb = new Xof_fsdb_itm();
lnki_ttl = Xoa_ttl.Replace_spaces(gplx.langs.htmls.encoders.Gfo_url_encoder_.Http_url.Decode(lnki_ttl));
fsdb.Init_at_lnki(Xof_exec_tid.Tid_viewer_app, wiki.Domain_itm().Abrv_xo(), lnki_ttl, Xop_lnki_type.Id_none, Xop_lnki_tkn.Upright_null, Xof_img_size.Size__neg1, Xof_img_size.Size__neg1, Xof_lnki_time.Null, Xof_lnki_page.Null, Xof_patch_upright_tid_.Tid_all);
fsdb.Init_at_hdoc(Int_.Max_value, Xof_html_elem.Tid_img);// NOTE: set elem_id to "impossible" number, otherwise it will auto-update an image on the page with a super-large size; [[File:Alfred Sisley 062.jpg]]
Xof_orig_itm orig = wiki.File__orig_mgr().Find_by_ttl_or_null(lnki_ttl); if (orig == Xof_orig_itm.Null) return null; // orig not found; need orig in order to get repo
Xof_repo_itm repo = wiki.File__repo_mgr().Get_trg_by_id_or_null(orig.Repo(), lnki_ttl, Bry_.Empty); if (repo == null) return null; // repo not found
fsdb.Init_at_orig(orig.Repo(), repo.Wiki_domain(), orig.Ttl(), orig.Ext(), orig.W(), orig.H(), orig.Redirect());
fsdb.Init_at_html(Xof_exec_tid.Tid_viewer_app, img_size, repo, url_bldr);
fsdb.File_is_orig_(true);
return fsdb;
}
}

View File

@ -0,0 +1,68 @@
/*
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.guis.urls; import gplx.*; import gplx.xowa.*; import gplx.xowa.guis.*;
import org.junit.*; import gplx.core.tests.*;
import gplx.xowa.files.origs.*;
public class Xog_url_wkr__file__tst {
private final Xog_url_wkr__file__fxt fxt = new Xog_url_wkr__file__fxt();
@Test public void Basic() {
fxt.Test__extract("A.png", "file:///mem/xowa/file/commons.wikimedia.org/orig/7/0/A.png", 300, 200);
}
@Test public void Url_encoded() {
fxt.Test__extract("A,b.png", "file:///mem/xowa/file/commons.wikimedia.org/orig/d/6/A%2Cb.png", 300, 200);
}
@Test public void Utf8() {
fxt.Test__extract("Volcán_Chimborazo,_\"El_Taita_Chimborazo\".jpg", "file:///mem/xowa/file/commons.wikimedia.org/orig/3/c/Volc%C3%A1n_Chimborazo%2C_%22El_Taita_Chimborazo%22.jpg", 300, 200);
}
}
class Xog_url_wkr__file__fxt {
private final Xowe_wiki wiki;
private final Bry_bfr bfr = Bry_bfr_.New();
private final Xog_url_wkr__file wkr;
private final Xof_orig_wkr__mock orig_wkr = new Xof_orig_wkr__mock();
public Xog_url_wkr__file__fxt() {
Xoae_app app = Xoa_app_fxt.Make__app__edit();
wiki = Xoa_app_fxt.Make__wiki__edit(app);
Xoa_app_fxt.repo2_(app, wiki);
wiki.File__orig_mgr().Wkrs__add(orig_wkr);
this.wkr = new Xog_url_wkr__file(app, wiki, Xoae_page.New_edit(wiki, wiki.Ttl_parse(Bry_.new_a7("Test_page"))));
}
public String Make__html(byte[] href_bry, byte[] xowa_ttl) {
bfr.Add_str_u8_fmt("<a href=\"{0}\" class=\"@gplx.Internal protected\" title=\"test_title\" xowa_title=\"{1}\">Full resolution</a>", href_bry, xowa_ttl);
return bfr.To_str_and_clear();
}
public void Make__orig(byte repo, byte[] page, int w, int h, byte[] redirect) {
orig_wkr.Add_orig(repo, page, gplx.xowa.files.Xof_ext_.new_by_ttl_(page).Id(), w, h, redirect);
}
public void Exec__extract_data(byte[] href_bry, String html_doc) {
wkr.Extract_data(html_doc, href_bry);
}
public void Test__extract(String file_page_db, String a_href_str, int orig_w, int orig_h) {
byte[] a_href = Bry_.new_u8(a_href_str);
this.Make__orig(Xof_orig_itm.Repo_wiki, Bry_.new_u8(file_page_db), orig_w, orig_h, Bry_.Empty);
byte[] xowa_title_bry = gplx.xowa.htmls.core.wkrs.lnkis.htmls.Xoh_file_fmtr__basic.Escape_xowa_title(Bry_.new_u8(file_page_db));
this.Exec__extract_data(a_href, this.Make__html(a_href, xowa_title_bry));
Gftest.Eq__str(file_page_db , wkr.File_page_db() , "file_page_db");
Gftest.Eq__bry(a_href , wkr.File_url().To_http_file_bry() , "file_url");
Gftest.Eq__bry(a_href , wkr.Fsdb().Html_view_url().To_http_file_bry() , "fsdb.view_url");
Gftest.Eq__int(orig_w , wkr.Fsdb().Orig_w() , "fsdb.orig_w");
Gftest.Eq__int(orig_h , wkr.Fsdb().Orig_h() , "fsdb.orig_h");
}
}

View File

@ -40,7 +40,7 @@ class Xog_url_wkr__fxt {
} }
public void Exec__parse(String href) { public void Exec__parse(String href) {
this.url = wiki.Utl__url_parser().Parse(Bry_.new_u8(href)); this.url = wiki.Utl__url_parser().Parse(Bry_.new_u8(href));
this.url = wkr.Exec(url); this.url = wkr.Exec_url(url);
} }
public void Test__raw(String expd) {Gftest.Eq__str(expd, String_.new_u8(url.Raw()));} public void Test__raw(String expd) {Gftest.Eq__str(expd, String_.new_u8(url.Raw()));}
public void Test__qarg(String expd) {Gftest.Eq__str(expd, String_.new_u8(url.Qargs_mgr().To_bry()));} public void Test__qarg(String expd) {Gftest.Eq__str(expd, String_.new_u8(url.Qargs_mgr().To_bry()));}