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

Source: Restore broken commit

This commit is contained in:
gnosygnu
2017-02-06 22:14:55 -05:00
parent 938beac9f9
commit 3bfeb94b43
4380 changed files with 328018 additions and 0 deletions

View File

@@ -0,0 +1,38 @@
/*
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/>.
*/
//namespace gplx.xowa.files {
// using gplx.xowa.files.caches;
// public class Xoa_file_mgr {
// private final List_adp list = List_adp_.New();
// public void Clear() {list.Clear();}
// public boolean Check_cache(Xow_wiki wiki, byte[] page_url, Xof_fsdb_itm fsdb_itm) {
// fsdb_itm.Init_at_cache(0, 0, null);
//// Xou_cache_mgr cache_mgr = new Xou_cache_mgr(null, null, null);
//// Xou_cache_itm cache_itm = cache_mgr.Get_or_null(fsdb_itm);
//// if (cache_itm == null) {
//// fsdb_itm.Init_at_cache(Bool_.N_byte, 0, 0, null);
//// return false;
//// }
//// else {
//// fsdb_itm.Init_at_cache(Bool_.Y_byte, cache_itm.Html_w(), cache_itm.Html_h(), cache_itm.File_url());
//// return true;
//// }
// return true;
// }
// }
//}

View File

@@ -0,0 +1,67 @@
/*
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; import gplx.*; import gplx.xowa.*;
import gplx.xowa.apps.fsys.*; import gplx.xowa.files.exts.*; import gplx.xowa.files.repos.*;
public class Xoa_repo_mgr implements Gfo_invk {
private final Xoa_fsys_mgr app_fsys; private final Xof_rule_mgr ext_rule_mgr;
public Xoa_repo_mgr(Xoa_fsys_mgr app_fsys, Xof_rule_mgr ext_rule_mgr) {this.app_fsys = app_fsys; this.ext_rule_mgr = ext_rule_mgr;}
public int Count() {return hash.Count();}
public Xof_repo_itm Get_at(int i) {return (Xof_repo_itm)hash.Get_at(i);}
public Xof_repo_itm Get_by(byte[] key) {return (Xof_repo_itm)hash.Get_by(key);}
public Xof_repo_itm Get_by_primary(byte[] key) {
int len = hash.Count();
for (int i = 0; i < len; i++) {
Xof_repo_itm repo = (Xof_repo_itm)hash.Get_at(i);
if (Bry_.Eq(key, repo.Wiki_domain()) && repo.Primary()) return repo;
}
return null;
}
public Xof_repo_itm Get_by_wmf_fsys(byte[] key) {
int len = hash.Count();
for (int i = 0; i < len; i++) {
Xof_repo_itm repo = (Xof_repo_itm)hash.Get_at(i);
if (Bry_.Eq(key, repo.Wiki_domain()) && repo.Wmf_fsys()) return repo;
}
return null;
}
public Xof_repo_itm Get_by_wiki_key(byte[] key) {
int len = hash.Count();
for (int i = 0; i < len; i++) {
Xof_repo_itm repo = (Xof_repo_itm)hash.Get_at(i);
if (Bry_.Eq(key, repo.Wiki_domain())) return repo;
}
return null;
}
public Xof_repo_itm Add(Xof_repo_itm itm) {hash.Add(itm.Key(), itm); return itm;} private Ordered_hash hash = Ordered_hash_.New_bry();
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_set)) return Set(m.ReadStr("key"), m.ReadStr("url"), m.ReadStr("wiki"));
else return Gfo_invk_.Rv_unhandled;
} private static final String Invk_set = "set";
public Xof_repo_itm Set(String key, String url_str, String wiki) {
byte[] key_bry = Bry_.new_u8(key);
Xof_repo_itm itm = (Xof_repo_itm)hash.Get_by(key_bry);
byte[] wiki_domain = Bry_.new_u8(wiki);
if (itm == null) {
itm = new Xof_repo_itm(key_bry, app_fsys, ext_rule_mgr, wiki_domain);
this.Add(itm);
}
itm.Root_str_(url_str);
itm.Wiki_domain_(wiki_domain);
return itm;
}
}

View File

@@ -0,0 +1,43 @@
/*
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; import gplx.*; import gplx.xowa.*;
import gplx.core.ios.*; import gplx.core.ios.streams.*;
import gplx.fsdb.data.*; import gplx.fsdb.meta.*; import gplx.xowa.files.fsdb.*;
public class Xof_bin_updater {
private final Fsd_thm_itm tmp_thm_itm = Fsd_thm_itm.new_();
public int Save_bin(Fsm_mnt_itm mnt, Fsm_atr_fil atr_fil, Fsm_bin_fil bin_fil, Xof_fsdb_itm fsdb, Io_stream_rdr rdr, long rdr_len) {
int db_uid = -1;
int orig_ext_id = fsdb.Orig_ext().Id();
if (fsdb.File_is_orig()) {
if (fsdb.Orig_ext().Id_is_image()) {
Fsd_img_itm img = mnt.Insert_img(atr_fil, bin_fil, fsdb.Orig_repo_name(), fsdb.Orig_ttl(), orig_ext_id, fsdb.Orig_w(), fsdb.Orig_h(), rdr_len, rdr);
db_uid = img.Fil_id();
}
else { // adds .pdf and .djvu b/c latter does not have w,h for fsdb_img
Fsd_fil_itm fil = mnt.Insert_fil(atr_fil, bin_fil, fsdb.Orig_repo_name(), fsdb.Orig_ttl(), orig_ext_id, rdr_len, rdr);
db_uid = fil.Fil_id();
}
}
else {
mnt.Insert_thm(tmp_thm_itm, atr_fil, bin_fil, fsdb.Orig_repo_name(), fsdb.Orig_ttl(), orig_ext_id, fsdb.Html_w(), fsdb.Html_h(), fsdb.Lnki_time(), fsdb.Lnki_page(), rdr_len, rdr);
db_uid = tmp_thm_itm.Thm_id();
}
mnt.Cfg_mgr().Next_id_commit();
return db_uid;
}
}

View File

@@ -0,0 +1,55 @@
/*
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; import gplx.*; import gplx.xowa.*;
public class Xof_cfg_download implements Gfo_invk {
public Xof_cfg_download() {
this.enabled = true; // changed to true; DATE:2016-12-19; OLD: CFG: set to false b/c some tests only do parsing [[File:A.png]] and repos are not set up
this.redownload = Redownload_none; // CFG: set to none to be as conservative as possible
}
public boolean Enabled() {return enabled;} public Xof_cfg_download Enabled_(boolean v) {enabled = v; return this;} private boolean enabled;
public byte Redownload() {return redownload;} public Xof_cfg_download Redownload_(byte v) {redownload = v; return this;} private byte redownload;
public void Init_by_wiki(Xow_wiki wiki) {
wiki.App().Cfg().Bind_many_app(this, Cfg__retrieval_enabled);
}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Cfg__retrieval_enabled)) enabled = m.ReadYn("v");
else if (ctx.Match(k, Invk_redownload)) return Redownload_to_str_(redownload);
else if (ctx.Match(k, Invk_redownload_)) redownload = Redownload_parse_(m.ReadStr("v"));
else if (ctx.Match(k, Invk_redownload_toggle)) redownload = redownload == Redownload_none ? Redownload_missing : Redownload_none;
else return Gfo_invk_.Rv_unhandled;
return this;
} private static final String Invk_redownload = "redownload", Invk_redownload_ = "redownload_", Invk_redownload_toggle = "redownload_toggle";
byte Redownload_parse_(String s) {
if (String_.Eq(s, "none")) return Redownload_none;
else if (String_.Eq(s, "missing")) return Redownload_missing;
else if (String_.Eq(s, "all")) return Redownload_all;
else throw Err_.new_unhandled(s);
}
public static final byte Redownload_none = 0, Redownload_missing = 1, Redownload_all = 2;
String Redownload_to_str_(byte v) {
switch (v) {
case Redownload_none: return "none";
case Redownload_missing: return "missing";
case Redownload_all: return "all";
default: throw Err_.new_unhandled(v);
}
}
private static final String Cfg__retrieval_enabled = "xowa.files.retrieval_enabled";
}

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.files; import gplx.*; import gplx.xowa.*;
public class Xof_exec_tid {
public static final int
Tid_wiki_page = 1 // regular page; EX: en.w:Earth
, Tid_wiki_file = 2 // "File:" ns; EX: en.w:File:A.png
, Tid_viewer_app = 3 // called by viewer_app
;
}

View File

@@ -0,0 +1,47 @@
/*
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; import gplx.*; import gplx.xowa.*;
public class Xof_ext {
public Xof_ext(int id, byte[] ext) {this.id = id; this.ext = ext;}
public int Id() {return id;} private int id;
public byte[] Ext() {return ext;} private byte[] ext;
public byte[] Ext_view() {return Xof_ext_.Bry__ary[Id_view()];}
public byte[] Mime_type() {return Xof_ext_.Mime_type__ary[id];}
public boolean Id_is_unknown() {return id == Xof_ext_.Id_unknown;}
public boolean Id_is_svg() {return id == Xof_ext_.Id_svg;}
public boolean Id_is_ogg() {return id == Xof_ext_.Id_ogg;}
public boolean Id_is_oga() {return id == Xof_ext_.Id_oga;}
public boolean Id_is_ogv() {return id == Xof_ext_.Id_ogv;}
public boolean Id_is_djvu() {return id == Xof_ext_.Id_djvu;}
public boolean Id_is_pdf() {return id == Xof_ext_.Id_pdf;}
public boolean Id_is_image() {return Xof_ext_.Id_is_image(id);}
public boolean Id_is_media() {return Xof_ext_.Id_is_media(id);}
public boolean Id_is_audio() {return Xof_ext_.Id_is_audio(id);}
public boolean Id_is_audio_strict() {return Xof_ext_.Id_is_audio_strict(id);}
public boolean Id_is_video() {return Xof_ext_.Id_is_video(id);}
public boolean Id_is_thumbable_img() {return Xof_ext_.Id_is_thumbable_img(id);}
public boolean Id_supports_page() {return Xof_ext_.Id_supports_page(id);}
public boolean Id_needs_convert() {return Xof_ext_.Id_needs_convert(id);}
public int Id_view() {return Xof_ext_.Id_view(id);}
public boolean Is_not_viewable(int exec_tid) {
return exec_tid != Xof_exec_tid.Tid_viewer_app // only apply logic if !Tid_viewer_app; note that if Tid_viewer_app, then user clicked on file, so return true;
&& ( this.Id_is_audio() // NOTE: was audio_strict, but v2 always redefines .ogg as .ogv; DATE:2014-02-02
|| id == Xof_ext_.Id_unknown // ignore unknown exts, else will download needlessly when viewing page; EX: .wav before .wav was registered; PAGE:pl.s:Spiaca_kr<6B>lewna_(Oppman); DATE:2014-08-17
);
}
}

View File

@@ -0,0 +1,192 @@
/*
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; import gplx.*; import gplx.xowa.*;
import gplx.core.primitives.*;
public class Xof_ext_ {
public static final int Id_unknown = 0 // SERIALIZED; ids are saved to fsdb;
, Id_png = 1, Id_jpg = 2, Id_jpeg = 3, Id_gif = 4, Id_tif = 5, Id_tiff = 6
, Id_svg = 7, Id_djvu = 8, Id_pdf = 9
, Id_mid = 10, Id_ogg = 11, Id_oga = 12, Id_ogv = 13, Id_webm = 14
, Id_flac = 15, Id_bmp = 16, Id_xcf = 17, Id_wav = 18;
public static final int Id__max = 19;
public static final byte[]
Bry_png = Bry_.new_a7("png"), Bry_jpg = Bry_.new_a7("jpg"), Bry_jpeg = Bry_.new_a7("jpeg")
, Bry_gif = Bry_.new_a7("gif"), Bry_tif = Bry_.new_a7("tif"), Bry_tiff = Bry_.new_a7("tiff")
, Bry_svg = Bry_.new_a7("svg"), Bry_djvu = Bry_.new_a7("djvu"), Bry_pdf = Bry_.new_a7("pdf")
, Bry_mid = Bry_.new_a7("mid"), Bry_ogg = Bry_.new_a7("ogg"), Bry_oga = Bry_.new_a7("oga")
, Bry_ogv = Bry_.new_a7("ogv"), Bry_webm = Bry_.new_a7("webm"), Bry_flac = Bry_.new_a7("flac")
, Bry_bmp = Bry_.new_a7("bmp"), Bry_xcf = Bry_.new_a7("xcf"), Bry_wav = Bry_.new_a7("wav")
;
public static final byte[][] Bry__ary = new byte[][]
{ Bry_.Empty, Bry_png, Bry_jpg, Bry_jpeg
, Bry_gif, Bry_tif, Bry_tiff
, Bry_svg, Bry_djvu, Bry_pdf
, Bry_mid, Bry_ogg, Bry_oga
, Bry_ogv, Bry_webm, Bry_flac
, Bry_bmp, Bry_xcf, Bry_wav
};
public static final byte[][] Mime_type__ary = new byte[][]
{ Bry_.new_a7("application/octet-stream"), Bry_.new_a7("image/png"), Bry_.new_a7("image/jpg"), Bry_.new_a7("image/jpeg")
, Bry_.new_a7("image/gif"), Bry_.new_a7("image/tiff"), Bry_.new_a7("image/tiff")
, Bry_.new_a7("image/svg+xml"), Bry_.new_a7("image/x.djvu"), Bry_.new_a7("application/pdf")
, Bry_.new_a7("application/x-midi"), Bry_.new_a7("video/ogg"), Bry_.new_a7("audio/oga")
, Bry_.new_a7("video/ogg"), Bry_.new_a7("video/webm"), Bry_.new_a7("audio/flac")
, Bry_.new_a7("image/bmp"), Bry_.new_a7("image/xcf"), Bry_.new_a7("audio/x-wav")
};
private static final Hash_adp id_hash = id_hash_new_();
private static Hash_adp id_hash_new_() {
Hash_adp rv = Hash_adp_bry.cs();
id_hash_new_(rv, Bry_png, Id_png); id_hash_new_(rv, Bry_jpg, Id_jpg); id_hash_new_(rv, Bry_jpeg, Id_jpeg);
id_hash_new_(rv, Bry_gif, Id_gif); id_hash_new_(rv, Bry_tif, Id_tif); id_hash_new_(rv, Bry_tiff, Id_tiff);
id_hash_new_(rv, Bry_svg, Id_svg); id_hash_new_(rv, Bry_djvu, Id_djvu); id_hash_new_(rv, Bry_pdf, Id_pdf);
id_hash_new_(rv, Bry_mid, Id_mid); id_hash_new_(rv, Bry_ogg, Id_ogg); id_hash_new_(rv, Bry_oga, Id_oga);
id_hash_new_(rv, Bry_ogv, Id_ogv); id_hash_new_(rv, Bry_webm, Id_webm); id_hash_new_(rv, Bry_flac, Id_flac);
id_hash_new_(rv, Bry_bmp, Id_bmp); id_hash_new_(rv, Bry_xcf, Id_xcf); id_hash_new_(rv, Bry_wav, Id_wav);
return rv;
}
private static void id_hash_new_(Hash_adp hash, byte[] key, int val) {hash.Add(key, new Int_obj_val(val));}
private static final Hash_adp_bry ext_hash = Hash_adp_bry.ci_a7()
.Add_bry_bry(Bry_png).Add_bry_bry(Bry_jpg).Add_bry_bry(Bry_jpeg)
.Add_bry_bry(Bry_gif).Add_bry_bry(Bry_tif).Add_bry_bry(Bry_tiff)
.Add_bry_bry(Bry_svg).Add_bry_bry(Bry_djvu).Add_bry_bry(Bry_pdf)
.Add_bry_bry(Bry_mid).Add_bry_bry(Bry_ogg).Add_bry_bry(Bry_oga)
.Add_bry_bry(Bry_ogv).Add_bry_bry(Bry_webm).Add_bry_bry(Bry_flac)
.Add_bry_bry(Bry_bmp).Add_bry_bry(Bry_xcf).Add_bry_bry(Bry_wav)
;
private static final Xof_ext[] Ary = new Xof_ext[Id__max];
public static byte[] Get_ext_by_id_(int id) {
if (id < 0 || id >= Id__max) throw Err_.new_wo_type("index out of bounds", "id", id);
return Bry__ary[id];
}
public static int Get_id_by_ext_(byte[] ext_bry) {
Object o = id_hash.Get_by(ext_bry);
return o == null ? Id_unknown : ((Int_obj_val)o).Val();
}
public static Xof_ext new_by_ttl_(byte[] ttl) {
int ttl_len = ttl.length;
int dot_pos = Bry_find_.Find_bwd(ttl, Byte_ascii.Dot);
byte[] ext = (dot_pos == Bry_find_.Not_found || dot_pos == ttl_len) ? Bry_.Empty : Bry_.Lcase__all(ttl, dot_pos + 1, ttl_len); // +1 to bgn after .
return new_(Get_id_by_ext_(ext), ext);
}
public static Xof_ext new_by_ext_(byte[] ext) {return new_(Get_id_by_ext_(ext), ext);}
public static Xof_ext new_by_id_(int id) {return new_(id, Get_ext_by_id_(id));}
public static Xof_ext new_(int id, byte[] ext) {
Xof_ext rv = Ary[id];
if (rv == null) {
rv = new Xof_ext(id, ext);
Ary[id] = rv;
}
return rv;
}
public static byte[] Lower_ext(byte[] ttl) {
int dot_pos = Bry_find_.Find_bwd(ttl, Byte_ascii.Dot);
int ttl_len = ttl.length;
if (dot_pos == Bry_find_.Not_found || dot_pos == ttl_len - 1) return ttl;
Object o = ext_hash.Get_by_mid(ttl, dot_pos + 1, ttl_len);
if (o == null) return ttl;
byte[] ext = (byte[])o;
boolean match = Bry_.Match(ttl, dot_pos, ttl_len, ext);
if (match) return ttl;
int ext_len = ext.length;
for (int i = 0; i < ext_len; i++)
ttl[i + dot_pos + 1] = ext[i];
return ttl;
}
public static boolean Orig_file_is_img(int v) { // identifies if orig_file can be used for <img src>; EX: png is valid, but svg, ogv, pdf is not
switch (v) {
case Id_png: case Id_jpg: case Id_jpeg:
case Id_gif: case Id_tif: case Id_tiff: return true;
default: return false;
}
}
public static boolean Id_supports_page(int v) { // identifies if tid supports page in lnki; EX: [[File:A.pdf|page=1]]; REF: https://en.wikipedia.org/wiki/Wikipedia:Picture_tutorial; DATE:2014-01-18
switch (v) {
case Id_pdf: case Id_djvu: return true;
default: return false;
}
}
public static boolean Id_supports_time(int v) { // identifies if tid supports thumbtime in lnki; EX: [[File:A.ogv|thumbtime=1]];
switch (v) {
case Id_ogg: case Id_ogv: case Id_webm: return true;
default: return false;
}
}
public static boolean Id_is_image(int id) {
switch (id) {
case Xof_ext_.Id_png: case Xof_ext_.Id_jpg: case Xof_ext_.Id_jpeg:
case Xof_ext_.Id_gif: case Xof_ext_.Id_tif: case Xof_ext_.Id_tiff:
case Xof_ext_.Id_svg:
case Xof_ext_.Id_bmp: case Xof_ext_.Id_xcf:
return true;
default:
return false;
}
}
public static boolean Id_is_image_wo_svg(int id) { // same as Id_is_image, but ignore svg
switch (id) {
case Xof_ext_.Id_png: case Xof_ext_.Id_jpg: case Xof_ext_.Id_jpeg:
case Xof_ext_.Id_gif: case Xof_ext_.Id_tif: case Xof_ext_.Id_tiff:
case Xof_ext_.Id_bmp: case Xof_ext_.Id_xcf:
return true;
default:
return false;
}
}
public static boolean Id_is_thumbable_img(int id) {
switch (id) {
case Xof_ext_.Id_png: case Xof_ext_.Id_jpg: case Xof_ext_.Id_jpeg:
case Xof_ext_.Id_gif: case Xof_ext_.Id_tif: case Xof_ext_.Id_tiff:
case Xof_ext_.Id_svg: case Xof_ext_.Id_djvu: case Xof_ext_.Id_pdf:
case Xof_ext_.Id_bmp: case Xof_ext_.Id_xcf:
return true;
default:
return false;
}
}
public static boolean Id_is_audio(int id) {
switch (id) {
case Xof_ext_.Id_mid: case Xof_ext_.Id_oga: case Xof_ext_.Id_flac: case Xof_ext_.Id_ogg: case Xof_ext_.Id_wav: return true;
default: return false;
}
}
public static boolean Id_is_video(int id) {return id == Xof_ext_.Id_ogv || id == Xof_ext_.Id_ogg || id == Xof_ext_.Id_webm;} // NOTE: ogg can be vid; PAGE:en.w:Comet; Encke_tail_rip_off.ogg
public static boolean Id_is_video_strict(int id) {return id == Xof_ext_.Id_ogv || id == Xof_ext_.Id_webm;} // NOTE: ogg can be aud / vid; PAGE:en.w:Comet; Encke_tail_rip_off.ogg
public static boolean Id_is_audio_strict(int id) { // same as above, but deliberately exclude ambiguous ogg
switch (id) {
case Xof_ext_.Id_mid: case Xof_ext_.Id_oga: case Xof_ext_.Id_flac: case Xof_ext_.Id_wav: return true;
default: return false;
}
}
public static boolean Id_is_media(int id) {return Id_is_audio(id) || Id_is_video(id);}
public static boolean Id_needs_convert(int id) {
switch (id) {
case Xof_ext_.Id_svg: case Xof_ext_.Id_djvu: case Xof_ext_.Id_pdf: return true;
default: return false;
}
}
public static int Id_view(int id) {
switch (id) {
case Xof_ext_.Id_svg: case Xof_ext_.Id_bmp: case Xof_ext_.Id_xcf: return Xof_ext_.Id_png;
case Xof_ext_.Id_tif: case Xof_ext_.Id_tiff: case Xof_ext_.Id_djvu: case Xof_ext_.Id_pdf:
case Xof_ext_.Id_ogg: case Xof_ext_.Id_ogv: case Xof_ext_.Id_webm: return Xof_ext_.Id_jpg;
default: return id;
}
}
}

View File

@@ -0,0 +1,50 @@
/*
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; import gplx.*; import gplx.xowa.*;
import gplx.dbs.*;
import gplx.xowa.files.origs.*; import gplx.xowa.files.repos.*;
public class Xof_file_fxt {
private final Xowe_wiki wiki;
Xof_file_fxt(Xowe_wiki wiki) {
this.wiki = wiki;
Io_mgr.Instance.InitEngine_mem();
Db_conn_bldr.Instance.Reg_default_mem();
wiki.File_mgr().Version_2_y_();
}
public static Xof_file_fxt new_(Xowe_wiki wiki) {return new Xof_file_fxt(wiki);}
public static Xof_file_fxt new_all(Xowe_wiki wiki) {return new Xof_file_fxt(wiki).Init_repos().Init_cache().Init_orig();}
public Xof_file_fxt Init_repos() {
Xow_repo_mgr_.Assert_repos(wiki.Appe(), wiki);
return this;
}
public Xof_file_fxt Init_cache() {
wiki.App().User().User_db_mgr().Init_by_app(Bool_.N, wiki.App().Fsys_mgr().Root_dir().GenSubFil_nest("user", "xowa.user.anonymous.sqlite3"));
return this;
}
public Xof_file_fxt Init_orig() {
Db_conn conn = Db_conn_bldr.Instance.Get_or_new(Io_url_.mem_fil_("mem/xowa/wiki/" + wiki.Domain_str() + "/orig.xowa")).Conn();
Xof_orig_tbl orig_tbl = new Xof_orig_tbl(conn, Bool_.Y);
orig_tbl.Create_tbl();
wiki.File_mgr().Orig_mgr().Init_by_wiki(wiki, Xof_fsdb_mode.New__v2__gui(), new Xof_orig_tbl[] {orig_tbl}, Xof_url_bldr.new_v2());
return this;
}
public void Exec_orig_add(boolean repo_is_commons, String orig_ttl, int orig_ext_id, int orig_w, int orig_h, String orig_redirect) {
byte repo_tid = repo_is_commons ? Xof_repo_tid_.Tid__remote : Xof_repo_tid_.Tid__local;
wiki.File_mgr().Orig_mgr().Insert(repo_tid, Bry_.new_u8(orig_ttl), orig_ext_id, orig_w, orig_h, Bry_.new_u8(orig_redirect));
}
}

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.files; import gplx.*; import gplx.xowa.*;
import gplx.xowa.guis.cbks.js.*; import gplx.xowa.files.repos.*;
public interface Xof_file_itm {
int Lnki_exec_tid();
byte[] Lnki_wiki_abrv();
byte[] Lnki_ttl();
byte Lnki_type();
double Lnki_upright();
int Lnki_w();
int Lnki_h();
double Lnki_time();
int Lnki_page();
boolean Orig_exists();
byte Orig_repo_id();
byte[] Orig_repo_name();
byte[] Orig_ttl();
byte[] Orig_ttl_md5();
Xof_ext Orig_ext();
int Orig_w();
int Orig_h();
byte[] Orig_redirect();
boolean File_is_orig();
int File_w();
boolean File_exists();
boolean File_exists_in_cache();
int Html_uid();
byte Html_elem_tid();
int Html_w();
int Html_h();
Io_url Html_view_url();
Io_url Html_orig_url();
int Html_gallery_mgr_h();
Js_img_wkr Html_img_wkr();
int Hdump_mode();
void File_exists_(boolean v);
void Html_orig_url_(Io_url v);
void Html_img_wkr_(Js_img_wkr v);
void Html_elem_tid_(byte v);
void Html_size_(int w, int h);
void Html_gallery_mgr_h_(int h);
void Init_at_lnki(int exec_tid, byte[] wiki_abrv, byte[] ttl, byte lnki_type, double upright, int w, int h, double time, int page, int lnki_upright_patch);
void Init_at_orig(byte orig_repo_id, byte[] orig_repo_name, byte[] orig_ttl, Xof_ext orig_ext, int orig_w, int orig_h, byte[] orig_redirect);
void Init_at_html(int exec_tid, Xof_img_size img_size, Xof_repo_itm repo, Xof_url_bldr url_bldr);
void Init_at_hdoc(int html_uid, byte html_elem_tid);
void Init_at_gallery_bgn(int html_w, int html_h, int file_w);
void Init_at_gallery_end(int html_w, int html_h, Io_url html_view_url, Io_url html_orig_url);
boolean Dbmeta_is_new();
}

View File

@@ -0,0 +1,41 @@
/*
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; import gplx.*; import gplx.xowa.*;
import gplx.dbs.*;
import gplx.xowa.files.commons.*; import gplx.xowa.files.exts.*; import gplx.xowa.files.caches.*; import gplx.xowa.files.imgs.*;
import gplx.xowa.bldrs.wms.*;
import gplx.xowa.xtns.math.*;
public class Xof_file_mgr implements Gfo_invk {
public Xoa_repo_mgr Repo_mgr() {return repo_mgr;} private Xoa_repo_mgr repo_mgr;
public Xof_img_mgr Img_mgr() {return img_mgr;} private final Xof_img_mgr img_mgr = new Xof_img_mgr();
public Xof_cache_mgr Cache_mgr() {return cache_mgr;} private Xof_cache_mgr cache_mgr;
public Xof_rule_mgr Ext_rules() {return ext_rules;} private final Xof_rule_mgr ext_rules = new Xof_rule_mgr();
public void Ctor_by_app(Xoae_app app) {
Gfo_usr_dlg usr_dlg = app.Usr_dlg();
this.cache_mgr = new Xof_cache_mgr(usr_dlg, app.Wiki_mgr(), repo_mgr);
this.repo_mgr = new Xoa_repo_mgr(app.Fsys_mgr(), ext_rules);
img_mgr.Init_by_app(app.Wmf_mgr(), app.Prog_mgr());
}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_repos)) return repo_mgr;
else if (ctx.Match(k, Invk_img_mgr)) return img_mgr;
else if (ctx.Match(k, Invk_ext_rules)) return ext_rules;
else if (ctx.Match(k, Invk_cache_mgr)) return cache_mgr;
else return Gfo_invk_.Rv_unhandled;
} private static final String Invk_repos = "repos", Invk_img_mgr= "img_mgr", Invk_ext_rules = "ext_rules", Invk_cache_mgr = "cache_mgr";
}

View File

@@ -0,0 +1,137 @@
/*
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; import gplx.*; import gplx.xowa.*;
import gplx.core.threads.*; import gplx.core.ios.*; import gplx.core.ios.streams.*;
import gplx.fsdb.*; import gplx.fsdb.meta.*; import gplx.fsdb.data.*; import gplx.xowa.files.fsdb.*; import gplx.xowa.files.imgs.*;
import gplx.xowa.files.repos.*; import gplx.xowa.files.origs.*; import gplx.xowa.files.bins.*; import gplx.xowa.files.caches.*; import gplx.xowa.guis.cbks.js.*;
public class Xof_file_wkr implements Gfo_thread_wkr {
private final Xof_orig_mgr orig_mgr; private final Xof_bin_mgr bin_mgr; private final Fsm_mnt_mgr mnt_mgr; private final Xou_cache_mgr cache_mgr;
private final Gfo_usr_dlg usr_dlg; private final Xow_repo_mgr repo_mgr; private final Xog_js_wkr js_wkr;
private final Xof_url_bldr url_bldr = Xof_url_bldr.new_v2(); private final Xof_img_size img_size = new Xof_img_size();
private final Xoa_page hpg; private final List_adp imgs;
public Xof_file_wkr(Xof_orig_mgr orig_mgr, Xof_bin_mgr bin_mgr, Fsm_mnt_mgr mnt_mgr, Xou_cache_mgr cache_mgr, Xow_repo_mgr repo_mgr, Xog_js_wkr js_wkr, Xoa_page hpg, List_adp imgs) {
this.orig_mgr = orig_mgr; this.bin_mgr = bin_mgr; this.mnt_mgr = mnt_mgr; this.cache_mgr = cache_mgr;
this.usr_dlg = Gfo_usr_dlg_.Instance; this.repo_mgr = repo_mgr; this.js_wkr = js_wkr;
this.hpg = hpg; this.imgs = imgs;
}
public String Thread__name() {return "xowa.load_imgs";}
public boolean Thread__resume() {return true;}
public void Thread__exec() {
int len = imgs.Count();
for (int i = 0; i < len; ++i)
Exec_by_fsdb((Xof_fsdb_itm)imgs.Get_at(i));
Xoa_app_.Usr_dlg().Prog_none("", "", "");
}
private void Exec_by_fsdb(Xof_fsdb_itm fsdb) {
try {
if (fsdb.File_exists_in_cache()) return;
fsdb.Orig_exists_n_();
Xof_orig_itm orig = orig_mgr.Find_by_ttl_or_null(fsdb.Lnki_ttl()); if (orig == Xof_orig_itm.Null) return;
Eval_orig(orig, fsdb, url_bldr, repo_mgr, img_size);
Show_img(fsdb, usr_dlg, bin_mgr, mnt_mgr, cache_mgr, repo_mgr, js_wkr, img_size, url_bldr, hpg);
} catch (Exception e) {
usr_dlg.Warn_many("", "", "file.unknown: err=~{0}", Err_.Message_gplx_full(e));
}
}
public static boolean Show_img(Xof_fsdb_itm fsdb, Gfo_usr_dlg usr_dlg, Xof_bin_mgr bin_mgr, Fsm_mnt_mgr mnt_mgr, Xou_cache_mgr cache_mgr, Xow_repo_mgr repo_mgr, Xog_js_wkr js_wkr, Xof_img_size img_size, Xof_url_bldr url_bldr, Xoa_page page) {
try {
usr_dlg.Log_many("", "", "file.get: file=~{0} width=~{1} page=~{2}", fsdb.Orig_ttl(), fsdb.Lnki_w(), page.Ttl().Full_db());
if (fsdb.Orig_ext() == null) {
usr_dlg.Warn_many("", "", "file.missing.ext: file=~{0} width=~{1} page=~{2}", fsdb.Orig_ttl(), fsdb.Lnki_w(), page.Ttl().Full_db());
return false;
}
Xof_repo_itm repo = repo_mgr.Get_trg_by_id_or_null(fsdb.Orig_repo_id(), fsdb.Orig_ttl(), page.Url_bry_safe());
if (repo == null) return false;
if (fsdb.Hdump_mode() == Xof_fsdb_itm.Hdump_mode__null)
fsdb.Init_at_html(fsdb.Lnki_exec_tid(), img_size, repo, url_bldr);
if (fsdb.Orig_ext().Is_not_viewable(fsdb.Lnki_exec_tid())) return false; // file not viewable; exit; EX: exec_tid = page and fsdb is audio
IoItmFil file = Io_mgr.Instance.QueryFil(fsdb.Html_view_url());
if (!file.Exists()) {
if (bin_mgr.Find_to_url_as_bool(fsdb.Lnki_exec_tid(), fsdb)) {
if (fsdb.Fsdb_insert()) Save_bin(fsdb, mnt_mgr, fsdb.Html_view_url());
}
else {
boolean pass = false;
if (fsdb.Lnki_exec_tid() == Xof_exec_tid.Tid_wiki_file) {
pass = Show_img_near(fsdb, bin_mgr, repo_mgr, page, img_size, url_bldr, js_wkr);
}
if (!pass) {
usr_dlg.Warn_many("", "", "file.missing.bin: file=~{0} width=~{1} page=~{2}", fsdb.Orig_ttl(), fsdb.Lnki_w(), page.Ttl().Full_db());
fsdb.File_exists_n_();
// gplx.xowa.files.gui.Js_img_mgr.Update_img_missing(usr_dlg, fsdb.Html_uid()); // TODO_OLD: update caption with "" if image is missing
return false;
}
}
}
else {
fsdb.File_exists_y_();
fsdb.File_size_(file.Size());
}
Js_img_mgr.Update_img(page, js_wkr, fsdb);
if (cache_mgr != null) cache_mgr.Update(fsdb); // cache_mgr null during tests;
return true;
} catch (Exception e) {
usr_dlg.Warn_many("", "", "file.unknown: err=~{0}", Err_.Message_gplx_full(e));
return false;
}
}
private static boolean Show_img_near(Xof_fsdb_itm fsdb, Xof_bin_mgr bin_mgr, Xow_repo_mgr repo_mgr, Xoa_page page, Xof_img_size img_size, Xof_url_bldr url_bldr, Xog_js_wkr js_wkr) {
Xof_bin_wkr__fsdb_sql fsdb_sql_wkr = (Xof_bin_wkr__fsdb_sql)bin_mgr.Wkrs__get_or_null(Xof_bin_wkr_.Key_fsdb_wiki);
if (fsdb_sql_wkr != null) {
Io_stream_rdr file_rdr = fsdb_sql_wkr.Get_to_fsys_near(fsdb, fsdb.Orig_repo_name(), fsdb.Orig_ttl(), fsdb.Orig_ext(), fsdb.Lnki_time(), fsdb.Lnki_page());
try {
if (file_rdr != Io_stream_rdr_.Noop) {
Xof_repo_itm repo = repo_mgr.Get_trg_by_id_or_null(fsdb.Orig_repo_id(), fsdb.Lnki_ttl(), page.Url_bry_safe());
Io_url file_url = url_bldr.Init_for_trg_file(repo, Xof_img_mode_.By_bool(!fsdb.File_is_orig()), fsdb.Orig_ttl(), fsdb.Orig_ttl_md5(), fsdb.Orig_ext(), fsdb.File_w(), fsdb.Lnki_time(), fsdb.Lnki_page()).Xto_url();
Io_stream_wtr_.Save_rdr(file_url, file_rdr, Io_download_fmt.Null);
fsdb.File_size_(file_rdr.Len()); // must update file size for cache
fsdb.Init_at_lnki_by_near(fsdb.File_w()); // change lnki to be file_w,-1
fsdb.Init_at_html(fsdb.Lnki_exec_tid(), img_size, repo, url_bldr);
return true;
}
} finally {
file_rdr.Rls();
}
}
return false;
}
public static void Eval_orig(Xof_orig_itm orig, Xof_fsdb_itm fsdb, Xof_url_bldr url_bldr, Xow_repo_mgr repo_mgr, Xof_img_size img_size) {
fsdb.Orig_exists_y_();
byte repo_id = orig.Repo();
Xof_repo_itm repo_itm = repo_mgr.Get_trg_by_id_or_null(repo_id, fsdb.Lnki_ttl(), Bry_.Empty);
if (repo_itm == null) return;
fsdb.Init_at_orig(repo_id, repo_itm.Wiki_domain(), orig.Ttl(), orig.Ext(), orig.W(), orig.H(), orig.Redirect());
fsdb.Init_at_html(fsdb.Lnki_exec_tid(), img_size, repo_itm, url_bldr);
}
public static void Save_bin(Xof_fsdb_itm itm, Fsm_mnt_mgr mnt_mgr, Io_url html_url) {
long rdr_len = Io_mgr.Instance.QueryFil(html_url).Size();
Io_stream_rdr rdr = gplx.core.ios.streams.Io_stream_rdr_.New__raw(html_url);
try {
rdr.Open();
Fsm_mnt_itm mnt_itm = mnt_mgr.Mnts__get_insert();
Fsm_atr_fil atr_fil = mnt_itm.Atr_mgr().Db__core();
Fsm_bin_fil bin_fil = mnt_itm.Bin_mgr().Dbs__get_nth();
Xof_bin_updater bin_updater = new Xof_bin_updater();
bin_updater.Save_bin(mnt_itm, atr_fil, bin_fil, itm, rdr, rdr_len);
}
catch (Exception e) {
Xoa_app_.Usr_dlg().Warn_many("", "", "failed to save file: ttl=~{0} url=~{1} err=~{2}", itm.Orig_ttl(), html_url.Raw(), Err_.Message_gplx_full(e));
}
finally {rdr.Rls();}
}
}

View File

@@ -0,0 +1,60 @@
/*
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; import gplx.*; import gplx.xowa.*;
import gplx.core.consoles.*; import gplx.langs.htmls.encoders.*;
public class Xof_file_wkr_ {
private static final gplx.core.security.Hash_algo md5_hash = gplx.core.security.Hash_algo_.New__md5();
public static final Gfo_url_encoder Md5_decoder = Gfo_url_encoder_.New__http_url().Init__same__many(Byte_ascii.Plus).Make();
public static byte[] Md5_fast(byte[] v) {
synchronized (md5_hash) {
return md5_hash.Hash_bry_as_bry(v);
}
}
public static byte[] Md5(byte[] ttl) {
synchronized (md5_hash) {
ttl = Md5_decoder.Decode(Ttl_standardize(ttl));
return Xof_file_wkr_.Md5_fast(ttl); // NOTE: md5 is calculated off of url_decoded ttl; EX: A%2Cb is converted to A,b and then md5'd. note that A%2Cb still remains the title
}
}
public static byte[] Ttl_standardize(byte[] src) {
int len = src.length; if (len == 0) return src;
byte[] rv = null;
boolean dirty = false;
byte b = src[0];
if (b > 96 && b < 123) {
dirty = true;
rv = new byte[len];
rv[0] = (byte)(b - 32); // NOTE: [[File:]] automatically uppercases 1st letter for md5; EX:en.d:File:wikiquote-logo.png has md5 of "32" (W...) not "82" (w...); PAGE:en.d:freedom_of_speech DATE:2016-01-21
}
for (int i = 1; i < len; ++i) {
b = src[i];
if (b == Byte_ascii.Space) {
if (!dirty) {
dirty = true;
rv = new byte[len]; Bry_.Copy_by_pos(src, 0, i, rv, 0);
}
rv[i] = Byte_ascii.Underline;
}
else {
if (dirty)
rv[i] = b;
}
}
return dirty ? rv : src;
}
}

View File

@@ -0,0 +1,33 @@
/*
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; import gplx.*; import gplx.xowa.*;
import org.junit.*;
public class Xof_file_wkr__tst {
private final Xof_file_wkr___fxt fxt = new Xof_file_wkr___fxt();
@Test public void Ttl_standardize() {
fxt.Test__ttl_standardize("Abc.png" , "Abc.png"); // basic
fxt.Test__ttl_standardize("A b.png" , "A_b.png"); // spaces -> unders
fxt.Test__ttl_standardize("A b c.png" , "A_b_c.png"); // spaces -> unders; multiple
fxt.Test__ttl_standardize("abc.png" , "Abc.png"); // ucase 1st
}
}
class Xof_file_wkr___fxt {
public void Test__ttl_standardize(String src_str, String expd) {
Tfds.Eq_bry(Bry_.new_u8(expd), Xof_file_wkr_.Ttl_standardize(Bry_.new_u8(src_str)));
}
}

View File

@@ -0,0 +1,195 @@
/*
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; import gplx.*; import gplx.xowa.*;
import gplx.core.ios.*;
import gplx.xowa.guis.cbks.js.*; import gplx.xowa.files.repos.*;
import gplx.xowa.parsers.lnkis.*;
public class Xof_fsdb_itm implements Xof_file_itm {
private int lnki_upright_patch;
public byte[] Lnki_wiki_abrv() {return lnki_wiki_abrv;} private byte[] lnki_wiki_abrv;
public int Lnki_exec_tid() {return lnki_exec_tid;} private int lnki_exec_tid;
public byte[] Lnki_ttl() {return lnki_ttl;} private byte[] lnki_ttl;
public byte Lnki_type() {return lnki_type;} private byte lnki_type;
public double Lnki_upright() {return lnki_upright;} private double lnki_upright;
public int Lnki_w() {return lnki_w;} private int lnki_w;
public int Lnki_h() {return lnki_h;} private int lnki_h;
public double Lnki_time() {return lnki_time;} private double lnki_time = Xof_lnki_time.Null;
public int Lnki_page() {return lnki_page;} private int lnki_page = Xof_lnki_page.Null;
public int User_thumb_w() {return user_thumb_w;} private int user_thumb_w = Xof_img_size.Thumb_width_img;
public byte Orig_repo_id() {return orig_repo_id;} private byte orig_repo_id = Xof_repo_tid_.Tid__null;
public byte[] Orig_repo_name() {return orig_repo_name;} private byte[] orig_repo_name;
public byte[] Orig_ttl() {return orig_ttl;} private byte[] orig_ttl;
public byte[] Orig_ttl_md5() {return orig_ttl_md5;} private byte[] orig_ttl_md5;
public Xof_ext Orig_ext() {return orig_ext;} private Xof_ext orig_ext;
public byte[] Orig_redirect() {return orig_redirect;} private byte[] orig_redirect;
public int Orig_w() {return orig_w;} private int orig_w = Xop_lnki_tkn.Width_null;
public int Orig_h() {return orig_h;} private int orig_h = Xop_lnki_tkn.Height_null;
public int Html_uid() {return html_uid;} private int html_uid;
public byte Html_elem_tid() {return html_elem_tid;} private byte html_elem_tid;
public int Html_w() {return html_w;} private int html_w;
public int Html_h() {return html_h;} private int html_h;
public Io_url Html_view_url() {return html_view_url;} private Io_url html_view_url;
public Io_url Html_orig_url() {return html_orig_url;} private Io_url html_orig_url = Io_url_.Empty;
public int Html_gallery_mgr_h() {return html_gallery_mgr_h;} private int html_gallery_mgr_h = Int_.Neg1;
public Js_img_wkr Html_img_wkr() {return html_img_wkr;} private Js_img_wkr html_img_wkr;
public boolean File_is_orig() {return file_is_orig;} private boolean file_is_orig;
public int File_w() {return file_w;} private int file_w;
public long File_size() {return file_size;} private long file_size;
public boolean Dbmeta_is_new() {return false;}
public boolean Orig_exists() {return orig_exists;} public void Orig_exists_y_() {orig_exists = Bool_.Y;} public void Orig_exists_n_() {orig_exists = Bool_.N;} private boolean orig_exists;
public boolean File_exists() {return file_exists;} public void File_exists_y_() {file_exists = Bool_.Y;} public void File_exists_n_() {file_exists = Bool_.N;} public void File_exists_(boolean v) {file_exists = v;} private boolean file_exists;
public boolean File_exists_in_cache() {return file_exists_in_cache;} private boolean file_exists_in_cache;
public boolean File_resized() {return file_resized;} public void File_resized_y_() {file_resized = Bool_.Y;} private boolean file_resized;
public boolean Fsdb_insert() {return fsdb_insert;} public void Fsdb_insert_y_() {fsdb_insert = true;} private boolean fsdb_insert;
public int Hdump_mode() {return hdump_mode;} private int hdump_mode = Hdump_mode__null;
public int Xfer_idx() {return xfer_idx;} private int xfer_idx;
public int Xfer_len() {return xfer_len;} private int xfer_len;
public void Init_at_lnki(int exec_tid, byte[] wiki_abrv, byte[] lnki_ttl, byte lnki_type, double lnki_upright, int lnki_w, int lnki_h, double lnki_time, int lnki_page, int lnki_upright_patch) {
this.lnki_exec_tid = exec_tid; this.lnki_wiki_abrv = wiki_abrv;
this.lnki_type = lnki_type; this.lnki_upright = lnki_upright; this.lnki_upright_patch = lnki_upright_patch;
this.lnki_w = lnki_w; this.lnki_h = lnki_h; this.lnki_time = lnki_time; this.lnki_page = lnki_page;
this.lnki_ttl = lnki_ttl;
this.Orig_ttl_(lnki_ttl); // default orig_ttl to lnki_ttl, since there are some classes that don't call Ctor_by_orig
this.orig_ext = Xof_ext_.new_by_ttl_(lnki_ttl);
}
public void Init_at_orig(byte orig_repo_id, byte[] orig_repo_name, byte[] orig_ttl, Xof_ext orig_ext, int orig_w, int orig_h, byte[] orig_redirect) {
this.orig_repo_id = orig_repo_id; this.orig_repo_name = orig_repo_name; this.orig_redirect = orig_redirect;
this.orig_w = orig_w; this.orig_h = orig_h;
if (Bry_.Len_gt_0(orig_redirect)) // redirect exists; EX: A.png redirected to B.png
this.Orig_ttl_(orig_redirect); // update fsdb with atrs of B.png
else if (!Bry_.Eq(lnki_ttl, orig_ttl)) // ttls differ; EX: "A_.png" vs "A.png"
this.Orig_ttl_(orig_ttl);
else
this.Orig_ttl_(orig_ttl);
this.orig_ext = orig_ext; // NOTE: always use orig_ext since this comes directly from wmf_api; DATE:2015-05-17
}
public void Init_at_lnki_by_near(int file_w) {
this.lnki_w = file_w; this.lnki_h = Xof_img_size.Size__neg1;
}
public void Init_at_html(int exec_tid, Xof_img_size img_size, Xof_repo_itm repo, Xof_url_bldr url_bldr) {
Calc_html_size(exec_tid, img_size);
this.html_view_url = url_bldr.To_url_trg(repo, this, file_is_orig);
this.html_orig_url = url_bldr.To_url_trg(repo, this, Bool_.Y);
}
public void Init_at_gallery_bgn(int html_w, int html_h, int file_w) {
this.html_w = html_w; this.html_h = html_h;
this.file_w = file_w;
}
public void Init_at_gallery_end(int html_w, int html_h, Io_url html_view_url, Io_url html_orig_url) {
this.html_w = html_w; this.html_h = html_h;
this.html_view_url = html_view_url;
this.html_orig_url = html_orig_url;
this.file_exists = true;
}
public void Init_at_hdoc(int html_uid, byte html_elem_tid) {
this.html_uid = html_uid; this.html_elem_tid = html_elem_tid;
}
public void Init_at_fsdb_make
( byte[] orig_ttl, int orig_ext_id // NOTE:fsdb_make uses fields named lnki_ttl and lnki_ext_id, but really is orig_ttl and orig_ext_id
, int lnki_w, int lnki_h, double lnki_time, int lnki_page
, byte orig_repo_id, int orig_w, int orig_h, byte[] orig_redirect
, boolean file_is_orig
) {
this.lnki_w = lnki_w; this.lnki_h = lnki_h; this.lnki_time = lnki_time; this.lnki_page = lnki_page;
this.orig_repo_id = orig_repo_id; this.orig_w = orig_w; this.orig_h = orig_h;
this.file_is_orig = file_is_orig;
this.file_w = lnki_w; // must set file_w, else fsdb_make will always download origs; DATE:2016-08-25
this.html_w = lnki_w; this.html_h = lnki_h; // set html_size as file_size (may try to optimize later by removing similar thumbs (EX: 220,221 -> 220))
this.Orig_ttl_(orig_ttl);
this.orig_ext = Xof_ext_.new_by_id_(orig_ext_id); // NOTE: data in fsdb_make may override lnki_ext; EX: ttl=A.png; but ext=".jpg"
}
public void Init_by_fsdb_near(boolean file_is_orig, int file_w) {
this.file_is_orig = file_is_orig; this.file_w = file_w;
}
public void Init_at_xfer(int idx, int len) {
this.xfer_idx = idx; this.xfer_len = len;
}
public void Init_at_cache(boolean file_exists_in_cache, int w, int h, Io_url view_url) {
this.file_exists_in_cache = file_exists_in_cache;
this.html_w = w; this.html_h = h; this.html_view_url = view_url;
}
public void Init_by_wm_parse(byte[] lnki_wiki_abrv, boolean repo_is_commons, boolean file_is_orig, byte[] file_ttl_bry, Xof_ext orig_ext, int file_w, double file_time, int file_page) {
this.hdump_mode = Hdump_mode__v2;
// lnki
this.lnki_ttl = file_ttl_bry;
this.lnki_w = file_w;
this.lnki_h = -1;
this.lnki_type = file_is_orig ? Xop_lnki_type.Id_none : Xop_lnki_type.Id_thumb;
this.lnki_wiki_abrv = lnki_wiki_abrv;
this.lnki_time = file_time;
this.lnki_page = file_page;
this.lnki_exec_tid = Xof_exec_tid.Tid_wiki_page;
// orig
this.orig_repo_id = repo_is_commons ? Xof_repo_tid_.Tid__remote : Xof_repo_tid_.Tid__local;
this.file_is_orig = file_is_orig;
this.Orig_ttl_(file_ttl_bry);
this.orig_ext = orig_ext;
// html
this.file_w = this.html_w = file_w;
}
public void Change_repo(byte orig_repo_id, byte[] orig_repo_name) {
this.orig_repo_id = orig_repo_id; this.orig_repo_name = orig_repo_name;
}
public void File_is_orig_(boolean v) {this.file_is_orig = v;}
public void Orig_repo_name_(byte[] v) {orig_repo_name = v;}
public void Html_elem_tid_(byte v) {this.html_elem_tid = v;}
public void Html_size_(int w, int h) {html_w = w; html_h = h;}
public void Html_view_url_(Io_url v) {html_view_url = v;}
public void Html_orig_url_(Io_url v) {html_orig_url = v;}
public void Html_img_wkr_(Js_img_wkr v) {html_img_wkr = v;}
public void Html_gallery_mgr_h_(int v) {html_gallery_mgr_h = v;}
public void File_size_(long v) {this.file_size = v;}
private void Orig_ttl_(byte[] v) {
this.orig_ttl = v;
this.orig_ttl_md5 = Xof_file_wkr_.Md5_fast(v);
}
private void Lnki_time_validate() {
if (!orig_ext.Id_is_media() && lnki_time != Xof_lnki_time.Null) // file is not media, but has thumbtime; this check can't be moved to Lnki_time_() b/c it needs ext
lnki_time = Xof_lnki_time.Null; // set time to null; needed else url will reference thumbtime; PAGE:en.w:Moon; EX:[[File:Lunar libration with phase Oct 2007 450px.gif|thumbtime=0:02]]; DATE:2014-07-20
}
private void Calc_html_size(int exec_tid, Xof_img_size img_size) {
this.Lnki_time_validate();
if (orig_ext.Id_is_audio_strict()) // audio does not have html size calculated; everything else does
file_is_orig = Bool_.Y;
else {
img_size.Html_size_calc(exec_tid, lnki_w, lnki_h, lnki_type, lnki_upright_patch, lnki_upright, orig_ext.Id(), orig_w, orig_h, Xof_img_size.Thumb_width_img);
if (lnki_type != Xop_lnki_type.Tid_orig_known) { // NOTE: hdump sets html_w / html_h; don't override; needed for packed-gallery; PAGE:en.w:Mexico; DATE:2016-08-10
html_w = img_size.Html_w(); html_h = img_size.Html_h();
}
file_w = img_size.File_w();
file_is_orig = img_size.File_is_orig();
}
}
public void To_bfr(Bry_bfr bfr) {
bfr .Add_int_variable(html_uid);
bfr.Add_byte_pipe().Add_int_variable(lnki_exec_tid);
bfr.Add_byte_pipe().Add(lnki_wiki_abrv);
bfr.Add_byte_pipe().Add_int_variable(lnki_type);
bfr.Add_byte_pipe().Add_double(lnki_upright);
bfr.Add_byte_pipe().Add_int_variable(lnki_upright_patch);
bfr.Add_byte_pipe().Add_int_variable(lnki_w);
bfr.Add_byte_pipe().Add_int_variable(lnki_h);
bfr.Add_byte_pipe().Add_double(lnki_time);
bfr.Add_byte_pipe().Add_int_variable(lnki_page);
bfr.Add_byte_nl();
}
public static final int Hdump_mode__null = 0, Hdump_mode__v2 = 2;
}

View File

@@ -0,0 +1,81 @@
/*
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; import gplx.*; import gplx.xowa.*;
import gplx.xowa.wikis.domains.*;
import gplx.xowa.files.repos.*;
import gplx.xowa.parsers.lnkis.*;
public class Xof_fsdb_itm_fxt {
private byte[] wiki_abrv;
private byte[] lnki_ttl;
private byte lnki_type;
private double lnki_upright;
private int lnki_w;
private int lnki_h;
private double lnki_time;
private int lnki_page;
private byte orig_repo_id;
private byte[] orig_repo_name;
private byte[] orig_ttl;
private Xof_ext orig_ext;
private int orig_w;
private int orig_h;
private byte[] orig_redirect;
public Xof_fsdb_itm_fxt() {this.Clear();}
public void Clear() {
this.wiki_abrv = lnki_ttl = null;
this.lnki_type = Xop_lnki_type.Id_null;
this.lnki_upright = Xof_img_size.Upright_null;
this.lnki_w = this.lnki_h = this.orig_w = this.orig_h = Xof_img_size.Size__neg1;
this.lnki_h = Xof_img_size.Size__neg1;
this.lnki_time = Xof_lnki_time.Null;
this.lnki_page = Xof_lnki_page.Null;
this.orig_repo_id = Xof_repo_tid_.Tid__null;
this.orig_repo_name = orig_ttl = orig_redirect = null;
this.orig_ext = null;
}
public Xof_fsdb_itm_fxt Lnki__en_w(String lnki_ttl_str) {
this.wiki_abrv = Abrv__en_w;
this.lnki_ttl = Bry_.new_u8(lnki_ttl_str);
return this;
}
public Xof_fsdb_itm_fxt Orig__commons__lnki() {
this.orig_repo_name = Xow_domain_itm_.Bry__commons;
this.orig_repo_id = Xof_repo_tid_.Tid__remote;
this.orig_ttl = lnki_ttl;
this.orig_ext = Xof_ext_.new_by_ttl_(orig_ttl);
this.orig_w = 880;
this.orig_w = 440;
return this;
}
public Xof_fsdb_itm_fxt Orig__enwiki__lnki() {
this.orig_repo_name = Xow_domain_itm_.Bry__enwiki;
this.orig_repo_id = Xof_repo_tid_.Tid__local;
this.orig_ttl = lnki_ttl;
this.orig_ext = Xof_ext_.new_by_ttl_(orig_ttl);
this.orig_w = 880;
this.orig_w = 440;
return this;
}
public Xof_fsdb_itm Make() {
Xof_fsdb_itm rv = new Xof_fsdb_itm();
rv.Init_at_lnki(Xof_exec_tid.Tid_wiki_page, wiki_abrv, lnki_ttl, lnki_type, lnki_upright, lnki_w, lnki_h, lnki_time, lnki_page, Xof_patch_upright_tid_.Tid_all);
rv.Init_at_orig(orig_repo_id, orig_repo_name, orig_ttl, orig_ext, orig_w, orig_h, orig_redirect);
return rv;
}
private final static byte[] Abrv__en_w = Bry_.new_a7("en.w");
}

View File

@@ -0,0 +1,34 @@
/*
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; import gplx.*; import gplx.xowa.*;
public class Xof_fsdb_mode {
private int tid;
Xof_fsdb_mode(int tid) {this.tid = tid;}
public boolean Tid__v2__bld() {return tid == TID__v2__bld;}
public void Tid__v2__bld__y_() {tid = TID__v2__bld;}
public void Tid__v2__mp__y_() {tid = TID__v2__mp;}
public boolean Tid__bld() {return tid > TID__v2__gui;}
private static final int
TID__v0 = 1
, TID__v2__gui = 2
, TID__v2__bld = 3
, TID__v2__mp = 4
;
public static Xof_fsdb_mode New__v0() {return new Xof_fsdb_mode(TID__v0);}
public static Xof_fsdb_mode New__v2__gui() {return new Xof_fsdb_mode(TID__v2__gui);}
}

View File

@@ -0,0 +1,27 @@
/*
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; import gplx.*; import gplx.xowa.*;
public class Xof_html_elem {
public static final byte Tid_none = 0, Tid_img = 1, Tid_vid = 2, Tid_gallery = 3, Tid_gallery_v2 = 4, Tid_imap = 5, Tid_aud = 6;
public static boolean Tid_is_file(byte tid) {
switch (tid) {
case Tid_img: case Tid_vid: return true;
default: return false;
}
}
}

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.files; import gplx.*; import gplx.xowa.*;
import gplx.core.bits.*;
import gplx.xowa.parsers.lnkis.*;
public class Xof_img_size {
public int Html_w() {return html_w;} private int html_w;
public int Html_h() {return html_h;} private int html_h;
public int File_w() {return file_w;} private int file_w; // NOTE: file_w will always equal html_w, unless rounding is implemented; EX: html_w=150,151,152 -> file_w=150
public int File_h() {return file_h;} private int file_h;
public boolean File_is_orig() {return file_is_orig;} private boolean file_is_orig;
private void Clear() {
html_w = html_h = file_w = file_h = 0;
file_is_orig = false;
}
public void Html_size_calc(int exec_tid, int lnki_w, int lnki_h, byte lnki_type, int upright_patch, double lnki_upright, int orig_ext, int orig_w, int orig_h, int thm_dflt_w) {
synchronized (this) {
this.Clear(); // always clear before calc; caller should be responsible, but just to be safe.
if ( Xof_ext_.Id_supports_time(orig_ext) // ext is video
&& lnki_w == Xof_img_size.Null // no size specified
&& !Xop_lnki_type.Id_is_thumbable(lnki_type) // not thumb which is implicitly 220; PAGE:en.w:Edward_Snowden; DATE:2015-08-17
)
lnki_w = orig_w; // use original size; EX:[[File:A.ogv]] -> [[File:A.ogv|550px]] where 550px is orig_w; DATE:2015-08-07
if (Bitmask_.Has_int(lnki_type, Xop_lnki_type.Id_frame) // frame: always return orig size; Linker.php!makeThumbLink2; // Use image dimensions, don't scale
&& lnki_h == Null) { // unless lnki_h specified; DATE:2013-12-22
html_w = file_w = orig_w;
html_h = file_h = orig_h;
file_is_orig = Xof_ext_.Orig_file_is_img(orig_ext); // file_is_orig = true, unless svg, ogv, pdf
if (file_is_orig)
file_w = file_h = Size__same_as_orig;
return;
}
html_w = lnki_w; html_h = lnki_h; // set html vals to lnki vals
file_is_orig = false;
if (html_w == Null && html_h == Null) { // no size set; NOTE: do not default to thumb if only height is set; EX: x900px should have w=0 h=900
if (Xop_lnki_type.Id_defaults_to_thumb(lnki_type))
html_w = thm_dflt_w;
else if ( orig_ext == Xof_ext_.Id_pdf // pdf and viewing on page; default to 220
&& exec_tid == Xof_exec_tid.Tid_wiki_page)
html_w = thm_dflt_w;
else
html_w = orig_w;
}
html_w = Upright_calc(upright_patch, lnki_upright, html_w, lnki_w, lnki_h, lnki_type);
if (orig_w == Null) return; // no orig_w; just use html_w and html_h (html_h will likely be -1 and wrong)
boolean ext_is_svg = orig_ext == Xof_ext_.Id_svg;
if (html_w == Xof_img_size.Null) {
if ( ext_is_svg // following strange MW logic; REF.MW:Linker.php|makeImageLink|If its a vector image, and user only specifies height, we don't want it to be limited by its "normal" width; DATE: 2013-11-26
&& html_h != Xof_img_size.Null)
html_w = Svg_max_width;
else
html_w = orig_w; // html_w missing >>> use orig_w; REF.MW:Linker.php|makeImageLink2|$hp['width'] = $file->getWidth( $page );
}
if (html_h != Xof_img_size.Null) { // html_h exists; REF.MW:ImageHandler.php|normaliseParams|if ( isset( $params['height'] ) && $params['height'] != -1 ) {
if ( (long)html_w * (long)orig_h
> (long)html_h * (long)orig_w) // html ratio > orig ratio; recalc html_w; SEE:NOTE_2; NOTE: casting to long to prevent int overflow; [[File:A.png|9999999999x90px]]; DATE:2014-04-26
html_w = Calc_w(orig_w, orig_h, html_h);
}
html_h = Scale_h(orig_w, orig_h, html_w); // calc html_h
if ( html_w >= orig_w // html >= orig
&& ( Xof_ext_.Orig_file_is_img(orig_ext) // orig is img (ignore for svg, ogv, pdf, etc)
|| ext_is_svg && exec_tid == Xof_exec_tid.Tid_wiki_file // limit to size if svg and [[File]] page
)
) {
file_is_orig = true; // use orig img (don't create thumb)
file_w = file_h = Size__same_as_orig;
if (Xop_lnki_type.Id_limits_large_size(lnki_type)) {// do not allow html_w > orig_w; REF.MW:Generic.php|normaliseParams
html_w = orig_w;
html_h = orig_h;
}
}
else { // html < orig
file_w = html_w;
file_h = html_h;
}
}
}
public static int Calc_w(int file_w, int file_h, int lnki_h) { // REF.MW:media/MediaHandler.php|fitBoxWidth
double ideal_w = (double)file_w * (double)lnki_h / (double)file_h;
double ideal_w_ceil = Math_.Ceil(ideal_w);
return Math_.Round(ideal_w_ceil * file_h / file_w, 0) > lnki_h
? (int)Math_.Floor(ideal_w)
: (int)ideal_w_ceil;
}
public static int Scale_h(int file_w, int file_h, int lnki_w) {
return file_w == 0 // REF.MW:File.php|scaleHeight
? 0
: (int)Math_.Round(((double)lnki_w * file_h) / file_w, 0); // NOTE: (double) needed else result will be int and fraction will be truncated
}
public static int Upright_calc(int upright_patch_tid, double upright, int cur_w, int lnki_w, int lnki_h, byte lnki_type) {
boolean upright_patch_use_thumb_w = Xof_patch_upright_tid_.Split_use_thumb_w(upright_patch_tid);
boolean upright_patch_fix_default = Xof_patch_upright_tid_.Split_fix_default(upright_patch_tid);
double upright_default_val = upright_patch_fix_default ? .75f : 1f;
if (upright_patch_use_thumb_w) {
if (upright != Upright_null // upright set
&& lnki_w == Null // w is null; EX: ( -1, 220); must exit early or will become 0; DATE:2013-11-23
&& lnki_h == Null // h is null; EX: (220, -1); REF:Linker.php|makeImageLink|"if (... !$hp['width'] );
&& Xop_lnki_type.Id_supports_upright(lnki_type)
) {
if (upright == Upright_default_marker) upright = upright_default_val; // upright is default; set val to .75; EX: [[File:A.png|upright]]
int rv = (int)(Thumb_width_img * upright);
return Round_10p2(rv);
}
else
return cur_w; // upright doesn't apply; return self;
}
else { // support old broken calc
if (upright == Upright_null) return cur_w; // upright is null; return width
else if (upright == Upright_default_marker)upright = upright_default_val; // upright is default; set val to .75; NOTE: wrong b/c [[File:A.png|upright=1]] -> .75
if (cur_w == Null) return Null; // width is null (-1); must exit early or will become 0; DATE:2013-11-23
int rv = (int)(cur_w * upright); // NOTE: wrong b/c should be Thumb_width_img, not cur_w
return Round_10p2(rv);
}
}
private static int Round_10p2(int v) {
int mod = v % 10;
if (mod > 4) v += 10 - mod;
else v -= mod;
return v;
}
public static final int Null = -1;
public static final int Thumb_width_img = 220, Thumb_width_ogv = 220;
public static final double Upright_null = -1, Upright_default_marker = 0; // REF:MW: if ( isset( $fp['upright'] ) && $fp['upright'] == 0 )
public static final int Size__neg1 = -1, Size_null = 0; // Size_null = 0, b/c either imageMagick / inkscape fails when -1 is passed
public static final int Size__same_as_orig = -1;
private static final int Svg_max_width = 2048;
}
/*
NOTE_1:proc source/layout
MW calls the falling procs
. Linker.php|makeImageLink2
. Linker.php|makeThumbLink2
. File.php|transform
. Bitmap.php|normaliseParams
. media/MediaHandler.php|fitBoxWidth
. File.php|scaleHeight
Note that this proc is a selective culling of the w,h setting code in the above (the procs do a lot of other checks/building)
also, MW's if branching can be combined. for now, emulating MW and not enforcing matching if/else
NOTE_2: lnki_ratio > orig_ratio
REF.MW:media/MediaHandler.php|fitBoxWidth
COMMENT:"Height is the relative smaller dimension, so scale width accordingly"
consider file of 200,100 (2:1)
EX_1: view is 120,40 (3:1)
- dimensions are either (a) 120,80 or (b) 80,40
- use (b) 80,40
EX_2: view is 120,80 (1.5:1)
- dimensions are either (a) 120,60 or (b) 160,80
- use (a) 120,60
*/

View File

@@ -0,0 +1,107 @@
/*
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; import gplx.*; import gplx.xowa.*;
import org.junit.*; import gplx.core.bits.*; import gplx.xowa.files.*; import gplx.xowa.parsers.lnkis.*;
public class Xof_img_size_tst {
private final Xof_img_size_fxt fxt = new Xof_img_size_fxt();
@Before public void init() {
fxt.Reset();
fxt.Orig_(400, 200);
}
@Test public void Lnki_lt_orig_null() {fxt.Lnki_type_(Xop_lnki_type.Id_null) .Lnki_(200, 100).Test_html(200, 100, Bool_.N);} // [[File:A.png|200px]] -> 200,100; File_is_orig = n
@Test public void Lnki_lt_orig_thumb() {fxt.Lnki_type_(Xop_lnki_type.Id_thumb) .Lnki_(200, 100).Test_html(200, 100, Bool_.N);} // [[File:A.png|thumb|200px]] -> 200,100; File_is_orig = n
@Test public void Lnki_lt_orig_frameless() {fxt.Lnki_type_(Xop_lnki_type.Id_frameless) .Lnki_(200, 100).Test_html(200, 100, Bool_.N);} // [[File:A.png|frameless|200px]] -> 200,100; File_is_orig = n
@Test public void Lnki_lt_orig_frame() {fxt.Lnki_type_(Xop_lnki_type.Id_frame) .Lnki_(200, -1).Test_html(400, 200, Bool_.Y);} // [[File:A.png|frame|200px]] -> 400,200; File_is_orig = y; frame always ignores parameters and returns orig
@Test public void Lnki_gt_orig_null() {fxt.Lnki_type_(Xop_lnki_type.Id_null) .Lnki_(800, 400).Test_html(800, 400, Bool_.Y);} // [[File:A.png|800px]] -> 800,400; File_is_orig = n
@Test public void Lnki_gt_orig_thumb() {fxt.Lnki_type_(Xop_lnki_type.Id_thumb) .Lnki_(800, 400).Test_html(400, 200, Bool_.Y);} // [[File:A.png|thumb|800px]] -> 400,200; File_is_orig = n
@Test public void Lnki_gt_orig_frameless() {fxt.Lnki_type_(Xop_lnki_type.Id_frameless) .Lnki_(800, 400).Test_html(400, 200, Bool_.Y);} // [[File:A.png|frameless|800px]] -> 400,200; File_is_orig = n
@Test public void Lnki_gt_orig_frame() {fxt.Lnki_type_(Xop_lnki_type.Id_frame) .Lnki_(800, -1).Test_html(400, 200, Bool_.Y);} // [[File:A.png|frame|800px]] -> 400,200; File_is_orig = y; frame always ignores parameters and returns orig
@Test public void Lnki_eq_orig_null() {fxt.Lnki_type_(Xop_lnki_type.Id_null) .Lnki_(400, 200).Test_html(400, 200, Bool_.Y);} // make sure File_is_orig = y
@Test public void Lnki_gt_orig_null_svg() {fxt.Lnki_ext_(Xof_ext_.Id_svg).Lnki_type_(Xop_lnki_type.Id_null) .Lnki_(800, 400).Test_html(800, 400, Bool_.N);} // [[File:A.svg|800px]] -> 800,400; File_is_orig = n
@Test public void Lnki_gt_orig_thumb_svg() {fxt.Lnki_ext_(Xof_ext_.Id_svg).Lnki_type_(Xop_lnki_type.Id_thumb) .Lnki_(800, 400).Test_html(800, 400, Bool_.N);} // [[File:A.svg|thumb|800px]] -> 800,400; File_is_orig = n
@Test public void Lnki_gt_orig_frameless_svg(){fxt.Lnki_ext_(Xof_ext_.Id_svg).Lnki_type_(Xop_lnki_type.Id_frameless) .Lnki_(800, 400).Test_html(800, 400, Bool_.N);} // [[File:A.svg|frameless|800px]] -> 800,400; File_is_orig = n
@Test public void Lnki_gt_orig_frame_svg() {fxt.Lnki_ext_(Xof_ext_.Id_svg).Lnki_type_(Xop_lnki_type.Id_frame) .Lnki_(800, -1).Test_html(400, 200, Bool_.N);} // [[File:A.svg|frame|800px]] -> 400,200; File_is_orig = n; frame always ignores parameters and returns orig
@Test public void Width_missing() {fxt.Lnki_( -1, 100).Test_html(200, 100);} // calc width based on height and orig
@Test public void Height_missing() {fxt.Lnki_(200, -1).Test_html(200, 100);}
@Test public void Orig_missing() {fxt.Lnki_(400, 200).Orig_( -1, -1).Test_html(400, 200);} // no orig_size; use lnki_w and lnki_h
@Test public void Lnki_missing() {fxt.Lnki_( -1, -1).Test_html(220, 110);} // w=thumbnail default; h=calc from orig
@Test public void Lnki_missing_frameless() {fxt.Lnki_( -1, -1).Lnki_type_(Xop_lnki_type.Id_frameless) .Test_html(220, 110, Bool_.N);} // default to thumb width
@Test public void Lnki_missing_null() {fxt.Lnki_( -1, -1).Lnki_type_(Xop_lnki_type.Id_null) .Test_html(400, 200, Bool_.Y);} // default to orig width
@Test public void Lnki_missing__orig_missing(){fxt.Lnki_( -1, -1).Orig_( -1, -1).Test_html(220, -1);} // no lnki or orig size; default to 220 with unknown height
@Test public void Prefer_height_over_width() {fxt.Lnki_(200, 100).Test_html(200, 100);} // prefer height; if width were preferred, size would be 200,134
@Test public void Upright() {fxt.Lnki_upright_(1).Lnki_(-1, -1).Orig_(440, 400).Test_html(220, 200);}
@Test public void Upright_w_thumb() {fxt.Lnki_type_(Xop_lnki_type.Id_thumb).Lnki_upright_(2).Lnki_(-1, -1).Orig_(1500, 1125).Test_html(440, 330);}
@Test public void Upright_ignored_by_w() {fxt.Lnki_type_(Xop_lnki_type.Id_thumb).Lnki_upright_(3.2).Lnki_(900, -1).Orig_(4653, 854).Test_html(900, 165);}// PAGE: fr.w:Bogota; DATE:2014-05-22
@Test public void Explicit_ratio_large() {fxt.Lnki_(120, 40).Test_html( 80, 40);} // see NOTE_2: lnki_ratio > orig_ratio
@Test public void Explicit_ratio_small() {fxt.Lnki_(120, 80).Test_html(120, 60);} // see NOTE_2: lnki_ratio > orig_ratio
@Test public void Lnki_gt_orig_null_svg_example() { // EX:[[File:Crystal Clear app kedit.svg|50x40px]]
fxt.Lnki_ext_(Xof_ext_.Id_svg).Lnki_type_(Xop_lnki_type.Id_null).Lnki_( 50, 40).Orig_( 40, 40).Test_html( 40, 40);
}
@Test public void Prefer_height_over_width_example() {// EX:[[File:Firma B.Ohiggins.svg|128x80px|alt=|Bernardo O'Higgins's signature]]
fxt.Lnki_ext_(Xof_ext_.Id_svg).Lnki_type_(Xop_lnki_type.Id_null).Lnki_(128, 80).Orig_(720, 194).Test_html(128, 34);
}
@Test public void Lnki_gt_orig_thumb_example() {// EX:[[File:Adhanema Lasva.jpg|thumb|300px|The Firman given to the Bosnian Franciscans]]
fxt.Lnki_type_(Xop_lnki_type.Id_thumb).Lnki_(300, -1).Orig_(149, 408).Test_html(149, 408, Bool_.Y);
}
@Test public void Upright_and_null_width_fails() {// PURPOSE: if width = -1, but upright is specified, ignore upright (was calculating 0 for width); DATE:2013-11-23
fxt.Lnki_type_(Xop_lnki_type.Id_null).Lnki_(-1, 110).Orig_(440, 220).Lnki_upright_(.50f).Test_html(220, 110, Bool_.N);
}
@Test public void Svg_null_width() { // PURPOSE: if svg and only height is specified, default width to 2048 (and recalc); DATE: 2013-11-26
fxt.Lnki_ext_(Xof_ext_.Id_svg).Lnki_(-1, 40).Orig_(1, 1).Test_html(40, 40, Bool_.N); // NOTE: used to be 1,1
}
@Test public void Svg_max_width() { // PURPOSE: large width causes int overflow; vi.w:Danh_sách_quốc_kỳ DATE:2014-04-26
fxt.Lnki_ext_(Xof_ext_.Id_svg).Lnki_(Int_.Max_value, 90).Orig_(900, 600).Test_html(135, 90, Bool_.N); // NOTE: used to be Int_.Max_value,90
}
@Test public void Pdf_none_defaults_to_thumb() { // PURPOSE: if no width is specified, pdf uses thumb width default, not orig width); DATE: 2013-11-27
fxt.Lnki_type_(Xop_lnki_type.Id_none).Lnki_ext_(Xof_ext_.Id_pdf).Lnki_(-1, -1).Orig_(440, 220).Test_html(220, 110, Bool_.N); // NOTE: used to be 1,1
}
@Test public void Frame() { // PURPOSE: frame incorrectly defaulted to file_is_orig; [[File:MESSENGER.jpg|200x200px|framed]]; DATE:2013-12-22
fxt.Lnki_type_(Xop_lnki_type.Id_frame).Lnki_ext_(Xof_ext_.Id_png).Lnki_(200, 200).Orig_(2038, 1529).Test_html(200, 150, Bool_.N);
}
@Test public void Frame_and_thumb(){ // PURPOSE: frame and thumb should be treated as frame; Enm.Has(val, Id_frame) vs val == Id_frame; PAGE:en.w:History_of_Western_Civilization; DATE:2015-04-16
fxt.Lnki_type_(Bitmask_.Add_byte(Xop_lnki_type.Id_frame, Xop_lnki_type.Id_thumb)).Lnki_(200, -1).Test_html(400, 200, Bool_.Y); // mut return same as Lnki_lt_orig_frame above
}
@Test public void Video__use_orig_w(){ // PURPOSE: video should use orig_w; DATE:2015-08-07
fxt.Lnki_type_(Xop_lnki_type.Id_none).Lnki_ext_(Xof_ext_.Id_ogv).Lnki_(-1, -1).Orig_(500, 250).Test_html(500, 250, Bool_.N);
}
@Test public void Video__use_thumb(){ // PURPOSE: video should use thumb_w, not orig_w; PAGE:en.w:Edward_Snowden DATE:2015-08-17
fxt.Lnki_type_(Xop_lnki_type.Id_thumb).Lnki_ext_(Xof_ext_.Id_ogv).Lnki_(-1, -1).Orig_(440, 220).Test_html(220, 110, Bool_.N);
}
}
class Xof_img_size_fxt {
private Xof_img_size img_size = new Xof_img_size();
public Xof_img_size_fxt Reset() {
lnki_type = Xop_lnki_type.Id_thumb;
lnki_ext = Xof_ext_.Id_jpg;
lnki_upright = Xof_img_size.Upright_null;
orig_w = orig_h = lnki_w = lnki_h = Xof_img_size.Null;
return this;
}
public Xof_img_size_fxt Lnki_type_(byte v) {lnki_type = v; return this;} private byte lnki_type;
public Xof_img_size_fxt Lnki_ext_(int v) {lnki_ext = v; return this;} private int lnki_ext;
public Xof_img_size_fxt Lnki_upright_(double v) {lnki_upright = v; return this;} private double lnki_upright;
public Xof_img_size_fxt Orig_(int w, int h) {orig_w = w; orig_h = h; return this;} private int orig_w, orig_h;
public Xof_img_size_fxt Lnki_(int w, int h) {lnki_w = w; lnki_h = h; return this;} private int lnki_w, lnki_h;
public void Test_html(int expd_w, int expd_h) {Test_html(expd_w, expd_h, false);}
public void Test_html(int expd_html_w, int expd_html_h, boolean expd_file_is_orig) {
img_size.Html_size_calc(Xof_exec_tid.Tid_wiki_page, lnki_w, lnki_h, lnki_type, Xof_patch_upright_tid_.Tid_all, lnki_upright, lnki_ext, orig_w, orig_h, Xof_img_size.Thumb_width_img);
Tfds.Eq(expd_html_w, img_size.Html_w(), "html_w");
Tfds.Eq(expd_html_h, img_size.Html_h(), "html_h");
Tfds.Eq(expd_file_is_orig, img_size.File_is_orig(), "file_is_orig");
}
}

View File

@@ -0,0 +1,28 @@
/*
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; import gplx.*; import gplx.xowa.*;
import gplx.core.stores.*;
import gplx.dbs.*;
public class Xof_lnki_page {
public static final int Null = -1;
public static boolean Null_y(int v) {return v == Null;}
public static boolean Null_n(int v) {return v != Null;}
public static int Db_load_int(DataRdr rdr, String fld) {return rdr.ReadInt(fld);}
public static int Db_load_int(Db_rdr rdr, String fld) {return rdr.Read_int(fld);}
public static int Db_save_int(int v) {return v;}
}

View File

@@ -0,0 +1,44 @@
/*
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; import gplx.*; import gplx.xowa.*;
import gplx.core.stores.*;
import gplx.dbs.*;
public class Xof_lnki_time {
public static double Db_save_double(double v) {return v;}
public static double Db_load_double(DataRdr rdr, String fld) {return rdr.ReadDouble(fld);}
public static double Db_load_double(Db_rdr rdr, String fld) {return rdr.Read_double(fld);}
public static int Db_save_int(double v) {return (int)v;}
public static double Db_load_int(DataRdr rdr, String fld) {return rdr.ReadInt(fld);}
public static double Db_load_int(Db_rdr rdr, String fld) {return rdr.Read_int(fld);}
public static int X_int(double v) {return (int)v;}
public static String X_str(double v) {return Double_.To_str(v);}
public static final double Null = -1;
public static boolean Null_y(double v) {return v == Null;}
public static boolean Null_n(double v) {return v != Null;}
public static final int Null_as_int = -1;
public static double Convert_to_xowa_thumbtime (int ext, double val) {return Xof_ext_.Id_supports_time(ext) ? val : Null;}
public static int Convert_to_xowa_page (int ext, double val) {return Xof_ext_.Id_supports_page(ext) ? (int)val : Xof_lnki_page.Null;}
public static double Convert_to_fsdb_thumbtime (int ext, double thumbtime, int page) {
return page != Xof_lnki_page.Null
&& Xof_ext_.Id_supports_page(ext) // redefine thumbtime to page if pdf
? page
: thumbtime
;
}
}

View File

@@ -0,0 +1,30 @@
/*
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; import gplx.*; import gplx.xowa.*;
public class Xof_media_type {
public static final byte Tid_null = 0, Tid_audio = 1, Tid_bitmap = 2, Tid_drawing = 2, Tid_office = 3, Tid_video = 4;
public static final String Name_null = "", Name_audio = "AUDIO", Name_bitmap = "BITMAP", Name_drawing = "DRAWING", Name_office = "OFFICE", Name_video = "VIDEO";
public static byte Xto_byte(String v) {
if (String_.Eq(v, Name_audio)) return Tid_audio;
else if (String_.Eq(v, Name_bitmap)) return Tid_bitmap;
else if (String_.Eq(v, Name_drawing)) return Tid_drawing;
else if (String_.Eq(v, Name_office)) return Tid_office;
else if (String_.Eq(v, Name_video)) return Tid_video;
else return Tid_null;
}
}

View File

@@ -0,0 +1,55 @@
/*
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; import gplx.*; import gplx.xowa.*;
import gplx.core.primitives.*;
public class Xof_mime_minor_ {
public static Xof_ext ext_(byte[] minor_mime) {
Int_obj_val id_obj = (Int_obj_val)mime_hash.Get_by(minor_mime);
int id = id_obj == null ? Xof_ext_.Id_unknown : id_obj.Val();
return Xof_ext_.new_by_id_(id);
}
private static final byte[]
Mime_svg = Bry_.new_a7("svg+xml"), Mime_djvu = Bry_.new_a7("vnd.djvu"), Mime_midi = Bry_.new_a7("midi")
, Mime_xcf = Bry_.new_a7("x-xcf"), Mime_flac = Bry_.new_a7("x-flac")
, Mime_bmp = Bry_.new_a7("x-bmp"), Mime_bmp_2 = Bry_.new_a7("x-ms-bmp");
private static final Hash_adp mime_hash = mime_hash_();
private static Hash_adp mime_hash_() {
Hash_adp rv = Hash_adp_bry.cs();
mime_hash_itm_(rv, Xof_ext_.Bry_png , Xof_ext_.Id_png);
mime_hash_itm_(rv, Xof_ext_.Bry_jpg , Xof_ext_.Id_jpg);
mime_hash_itm_(rv, Xof_ext_.Bry_jpeg , Xof_ext_.Id_jpeg);
mime_hash_itm_(rv, Xof_ext_.Bry_gif , Xof_ext_.Id_gif);
mime_hash_itm_(rv, Xof_ext_.Bry_tif , Xof_ext_.Id_tif);
mime_hash_itm_(rv, Xof_ext_.Bry_tiff , Xof_ext_.Id_tiff);
mime_hash_itm_(rv, Mime_svg , Xof_ext_.Id_svg);
mime_hash_itm_(rv, Mime_djvu , Xof_ext_.Id_djvu);
mime_hash_itm_(rv, Xof_ext_.Bry_pdf , Xof_ext_.Id_pdf);
mime_hash_itm_(rv, Mime_midi , Xof_ext_.Id_mid);
mime_hash_itm_(rv, Xof_ext_.Bry_ogg , Xof_ext_.Id_ogg);
mime_hash_itm_(rv, Xof_ext_.Bry_oga , Xof_ext_.Id_oga);
mime_hash_itm_(rv, Xof_ext_.Bry_ogv , Xof_ext_.Id_ogv);
mime_hash_itm_(rv, Xof_ext_.Bry_webm , Xof_ext_.Id_webm);
mime_hash_itm_(rv, Mime_flac , Xof_ext_.Id_flac);
mime_hash_itm_(rv, Mime_bmp , Xof_ext_.Id_bmp);
mime_hash_itm_(rv, Mime_bmp_2 , Xof_ext_.Id_bmp);
mime_hash_itm_(rv, Mime_xcf , Xof_ext_.Id_xcf);
mime_hash_itm_(rv, Xof_ext_.Bry_wav , Xof_ext_.Id_wav);
return rv;
}
private static void mime_hash_itm_(Hash_adp hash, byte[] key, int val) {hash.Add(key, new Int_obj_val(val));}
}

View File

@@ -0,0 +1,31 @@
/*
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; import gplx.*; import gplx.xowa.*;
import gplx.core.bits.*;
public class Xof_patch_upright_tid_ {
public static final int Tid_unpatched = 0, Tid_use_thumb_w = 1, Tid_fix_default = 2;
public static final int Tid_all = Tid_use_thumb_w | Tid_fix_default;
public static int Merge(boolean use_thumb_w, boolean fix_default) {
if (use_thumb_w && fix_default) return Bitmask_.Add_int(Tid_use_thumb_w, Tid_fix_default);
else if (use_thumb_w) return Tid_use_thumb_w;
else if (fix_default) return Tid_fix_default;
else return Tid_unpatched;
}
public static boolean Split_use_thumb_w(int tid) {return Bitmask_.Has_int(tid, Tid_use_thumb_w);}
public static boolean Split_fix_default(int tid) {return Bitmask_.Has_int(tid, Tid_fix_default);}
}

View File

@@ -0,0 +1,231 @@
/*
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; import gplx.*; import gplx.xowa.*;
import gplx.core.envs.*;
import gplx.langs.htmls.encoders.*;
import gplx.xowa.files.repos.*; import gplx.xowa.files.fsdb.*; import gplx.xowa.files.imgs.*;
public class Xof_url_bldr {
private final Bry_bfr tmp_bfr = Bry_bfr_.Reset(400);
private final Gfo_url_encoder encoder_src_http = Gfo_url_encoder_.New__http_url().Make(); // NOTE: changed from new_html_href_mw_ to new_url_ on 2012-11-19; issues with A%2Cb becoming A%252Cb
private byte[] ttl; private byte[] md5; private Xof_ext ext; private boolean file_is_thumb; private int file_w;
private double time = Xof_lnki_time.Null; private int page = Xof_lnki_page.Null; private byte time_dlm = Byte_ascii.At;
private byte repo_tid;
private byte[] root; private byte dir_spr; private boolean fsys_is_wnt; private boolean wmf_dir_hive; private boolean wmf_protocol_is_file; private int md5_dir_depth; private byte[] area;
public Xof_url_bldr Root_(byte[] v) {root = v; return this;}
public Xof_url_bldr Init_by_repo(byte repo_tid, byte[] root, boolean fsys_is_wnt, byte dir_spr, boolean wmf_dir_hive, boolean wmf_protocol_is_file, int md5_dir_depth) {
this.repo_tid = repo_tid;
this.root = root; this.dir_spr = dir_spr; this.wmf_dir_hive = wmf_dir_hive; this.wmf_protocol_is_file = wmf_protocol_is_file; this.md5_dir_depth = md5_dir_depth;
this.fsys_is_wnt = fsys_is_wnt;
return this;
}
public Xof_url_bldr Init_by_itm(byte mode, byte[] ttl, byte[] md5, Xof_ext ext, int file_w, double time, int page) {
this.ttl = ttl; this.md5 = md5; this.ext = ext; this.file_w = file_w; this.time = time; this.page = page;
if (wmf_protocol_is_file && fsys_is_wnt) this.ttl = Xof_itm_ttl_.Remove_invalid(tmp_bfr, ttl); // NOTE: changed ttl does not change md5
this.file_is_thumb = mode == Xof_img_mode_.Tid__thumb;
this.area = Xof_img_mode_.Names_ary[mode];
return this;
}
public Xof_url_bldr Init_for_src_file(Xof_repo_itm repo, byte mode, byte[] ttl, byte[] md5, Xof_ext ext, int file_w, double time, int page) {
this.repo_tid = repo.Tid();
this.wmf_dir_hive = Bool_.Y; this.wmf_protocol_is_file = repo.Tarball();
this.dir_spr = repo.Dir_spr(); this.root = repo.Root_bry(); this.area = repo.Mode_names()[mode];
this.ttl = repo.Gen_name_src(tmp_bfr, ttl); this.md5 = md5; this.ext = ext;
this.file_is_thumb = mode == Xof_img_mode_.Tid__thumb; this.file_w = file_w; this.time = time; this.page = page;
return this;
}
public Xof_url_bldr Init_for_trg_file(Xof_repo_itm repo, byte mode, byte[] ttl, byte[] md5, Xof_ext ext, int file_w, double time, int page) {
return Init(repo.Tid(), Bool_.N, Bool_.N, repo.Dir_spr(), repo.Root_bry()
, repo.Mode_names()[mode], repo.Dir_depth(), repo.Gen_name_trg(tmp_bfr, ttl, md5, ext), md5, ext, mode, file_w, time, page);
}
public Xof_url_bldr Init_for_trg_html(Xof_repo_itm repo, byte mode, byte[] ttl, byte[] md5, Xof_ext ext, int file_w, double time, int page) {
return Init(repo.Tid(), Bool_.N, Bool_.N, Byte_ascii.Slash, repo.Root_http()
, repo.Mode_names()[mode], repo.Dir_depth(), repo.Gen_name_trg(tmp_bfr, ttl, md5, ext), md5, ext, mode, file_w, time, page);
}
private Xof_url_bldr Init(byte repo_tid, boolean wmf_dir_hive, boolean wmf_protocol_is_file, byte dir_spr
, byte[] root, byte[] area, int md5_dir_depth
, byte[] ttl, byte[] md5, Xof_ext ext
, byte file_mode, int file_w, double time, int page
) {
this.repo_tid = repo_tid;
this.wmf_dir_hive = wmf_dir_hive; this.wmf_protocol_is_file = wmf_protocol_is_file; this.dir_spr = dir_spr;
this.root = root; this.area = area; this.md5_dir_depth = md5_dir_depth;
this.ttl = ttl; this.md5 = md5; this.ext = ext;
this.file_is_thumb = file_mode == Xof_img_mode_.Tid__thumb; this.file_w = file_w; this.time = time; this.page = page;
return this;
}
public byte[] Xto_bry() {Bld(); byte[] rv = tmp_bfr.To_bry_and_clear(); Clear(); return rv;}
public String Xto_str() {Bld(); String rv = tmp_bfr.To_str(); Clear(); return rv;}
public Io_url Xto_url() {Bld(); Io_url rv = Io_url_.new_fil_(tmp_bfr.To_str()); Clear(); return rv;}
public Io_url Xto_url_by_http() {Bld(); Io_url rv = Io_url_.New__http_or_fail(tmp_bfr.To_str()); Clear(); return rv;}
public Io_url To_url_trg(Xof_repo_itm repo_itm, Xof_fsdb_itm itm, boolean orig) {
byte mode = orig ? Xof_img_mode_.Tid__orig : Xof_img_mode_.Tid__thumb;
return this.Init_for_trg_file(repo_itm, mode, itm.Orig_ttl(), itm.Orig_ttl_md5(), itm.Orig_ext(), itm.File_w(), itm.Lnki_time(), itm.Lnki_page()).Xto_url();
}
public Io_url To_url_trg(Xof_repo_itm repo_itm, Xof_file_itm itm, boolean orig) {
byte mode = orig ? Xof_img_mode_.Tid__orig : Xof_img_mode_.Tid__thumb;
return this.Init_for_trg_file(repo_itm, mode, itm.Orig_ttl(), itm.Orig_ttl_md5(), itm.Orig_ext(), itm.File_w(), itm.Lnki_time(), itm.Lnki_page()).Xto_url();
}
public Io_url To_url_trg(Xof_repo_itm repo_itm, gplx.xowa.files.caches.Xou_cache_itm itm, boolean orig) {
byte mode = orig ? Xof_img_mode_.Tid__orig : Xof_img_mode_.Tid__thumb;
return this.Init_for_trg_file(repo_itm, mode, itm.Orig_ttl(), itm.Orig_ttl_md5(), itm.Orig_ext_itm(), itm.File_w(), itm.Lnki_time(), itm.Lnki_page()).Xto_url();
}
private static final byte[] Bry__http = Bry_.new_a7("http");
private void Bld() {
if (repo_tid == Xof_repo_tid_.Tid__math) {
tmp_bfr.Add(root); // add root; EX: "C:\xowa\file\"; assume trailing dir_spr
boolean root_is_http = Bry_.Has_at_bgn(root, Bry__http);
if (root_is_http)
tmp_bfr.Add_mid(ttl, 0, ttl.length - 4); // -4 to remove ".svg". note that XO stores ".svg", but WM doesn't; EX: "596f8baf206a81478afd4194b44138715dc1a05c.svg"
else
tmp_bfr.Add(ttl);
}
else {
Add_core();
if (file_is_thumb) {
if (wmf_dir_hive) Add_thumb_wmf();
else Add_thumb_xowa();
}
}
}
private Xof_url_bldr Add_core() {
tmp_bfr.Add(root); // add root; EX: "C:\xowa\file\"; assume trailing dir_spr
if (area != null && !(wmf_dir_hive && !file_is_thumb)) // !(wmf_dir_hive && !thumb) means never add if wmf_dir_hive and orig
tmp_bfr.Add(area).Add_byte(dir_spr); // add area; EX: "thumb\"
byte b0 = md5[0];
if (wmf_dir_hive) {
tmp_bfr.Add_byte(b0).Add_byte(dir_spr); // add md5_0 EX: "0/"
tmp_bfr.Add_byte(b0).Add_byte(md5[1]).Add_byte(dir_spr); // add md5_01 EX: "01/"
}
else {
for (int i = 0; i < md5_dir_depth; i++)
tmp_bfr.Add_byte(md5[i]).Add_byte(dir_spr); // add md5_0123 EX: "0/1/2/3"
}
if (wmf_dir_hive) {
if (wmf_protocol_is_file) // sitting on local file system (as opposed to http)
tmp_bfr.Add(ttl); // NOTE: file_names are not url-encoded; this includes symbols (') and foreign characters (ö)
else // wmf_http
tmp_bfr.Add(encoder_src_http.Encode(ttl)); // NOTE: file_names must be url-encoded; JAVA will default to native charset which on Windows will be 1252; foreign character urls will fail due to conversion mismatch (1252 on windows; UTF-8 on WMF); PAGE:en.w:Möbius strip
}
else
tmp_bfr.Add(ttl); // add title; EX: "A.png"
return this;
}
private Xof_url_bldr Add_thumb_xowa() {
tmp_bfr.Add_byte(dir_spr); // add dir_spr; EX: "\"
tmp_bfr.Add_int_variable(file_w).Add(Bry_px); // add file_w; EX: "220px"
if (Xof_lnki_time.Null_n(time))
tmp_bfr.Add_byte(time_dlm).Add_str_a7(Xof_lnki_time.X_str(time)); // add time EX: "@5"
else if (page != Xof_lnki_page.Null)
tmp_bfr.Add_byte(Byte_ascii.Dash).Add_int_variable(page); // add page EX: "-5"
tmp_bfr.Add_byte(Byte_ascii.Dot); // add . EX: "."
if (file_is_thumb)
tmp_bfr.Add(ext.Ext_view()); // add view_ext EX: ".png"
else
tmp_bfr.Add(ext.Ext()); // add orig_ext EX: ".svg"
return this;
}
private Xof_url_bldr Add_thumb_wmf() {
tmp_bfr.Add_byte(dir_spr); // add dir_spr; EX: "\"
int file_ext_id = ext.Id();
switch (file_ext_id) {
case Xof_ext_.Id_ogg:
case Xof_ext_.Id_ogv:
case Xof_ext_.Id_webm:
tmp_bfr.Add_int_variable(file_w); // add file_w; EX: "220"; PAGE:en.w:Alice_Brady; DATE:2015-08-06
tmp_bfr.Add(Bry_px_dash); // add px; EX: "px-"
if (Xof_lnki_time.Null_n(time))
tmp_bfr.Add(Bry_seek).Add_str_a7(Xof_lnki_time.X_str(time)).Add_byte(Byte_ascii.Dash);// add seek; EX: "seek%3D5-"
else
tmp_bfr.Add_byte(Byte_ascii.Dash); // add mid; EX: "-"; NOTE: was "mid-"; DATE:2015-08-06
break;
case Xof_ext_.Id_tif:
case Xof_ext_.Id_tiff:
Add_thumb_wmf_page(Bry_lossy_page1, Bry_lossy_page);
tmp_bfr.Add_int_variable(file_w); // add file_w; EX: "220"
tmp_bfr.Add(Bry_px_dash); // add px; EX: "px-"
break;
case Xof_ext_.Id_pdf:
case Xof_ext_.Id_djvu:
Add_thumb_wmf_page(Bry_page1, Bry_page);
tmp_bfr.Add_int_variable(file_w); // add file_w; EX: "220"
tmp_bfr.Add(Bry_px_dash); // add px; EX: "px-"
break;
default:
tmp_bfr.Add_int_variable(file_w); // add file_w; EX: "220"
tmp_bfr.Add(Bry_px_dash); // add px; EX: "px-"
break;
}
int ttl_len = ttl.length;
if (ttl_len > 160) { // long file name
tmp_bfr.Add(Bry_thumnbail_w_dot);
tmp_bfr.Add(ext.Ext());
}
else
tmp_bfr.Add(encoder_src_http.Encode(ttl)); // add ttl again; EX: "A.png"
switch (file_ext_id) {
case Xof_ext_.Id_svg:
case Xof_ext_.Id_bmp:
case Xof_ext_.Id_xcf:
tmp_bfr.Add_byte(Byte_ascii.Dot).Add(Xof_ext_.Bry_png); // add .png; EX: "A.svg" -> "A.svg.png" NOTE: MediaWiki always adds as lowercase
break;
case Xof_ext_.Id_pdf:
case Xof_ext_.Id_tif: // add .jpg EX: "A.tif" -> "A.tif.jpg" NOTE: MediaWiki always adds as lowercase
case Xof_ext_.Id_tiff:
case Xof_ext_.Id_ogg:
case Xof_ext_.Id_ogv:
case Xof_ext_.Id_djvu:
case Xof_ext_.Id_webm:
tmp_bfr.Add_byte(Byte_ascii.Dot).Add(Xof_ext_.Bry_jpg);
break;
}
return this;
}
private void Add_thumb_wmf_page(byte[] bry_page_1, byte[] bry_page) {
if (Xof_lnki_time.Null_y(page))
tmp_bfr.Add(bry_page_1); // add "lossy-page1-" EX: "lossy-page1-"
else {
tmp_bfr.Add(bry_page); // add "lossy-page" EX: "lossy-page"
tmp_bfr.Add_int_variable(page); // add page EX: 123
tmp_bfr.Add_byte(Byte_ascii.Dash); // add - EX: "-"
}
}
private Xof_url_bldr Clear() {
root = area = ttl = md5 = null;
file_w = Xof_img_size.Null;
time = Xof_lnki_time.Null;
ext = null;
tmp_bfr.Clear();
repo_tid = Xof_repo_tid_.Tid__null;
return this;
}
public static final byte[]
Bry_reg = Bry_.new_a7("reg.csv")
, Bry_px = Bry_.new_a7("px"), Bry_px_dash = Bry_.new_a7("px-")
, Bry_thumb = Bry_.new_a7("thumb")
, Bry_thumnbail_w_dot = Bry_.new_a7("thumbnail.")
;
private static final byte[]
Bry_lossy_page = Bry_.new_a7("lossy-page"), Bry_page = Bry_.new_a7("page")
, Bry_lossy_page1 = Bry_.new_a7("lossy-page1-"), Bry_page1 = Bry_.new_a7("page1-"), Bry_seek = Bry_.new_a7("seek%3D");
public static Xof_url_bldr new_v2() {
Xof_url_bldr rv = new Xof_url_bldr();
rv.time_dlm = Byte_ascii.Dash;
return rv;
}
public static final int Md5_dir_depth_2 = 2;
}

View File

@@ -0,0 +1,67 @@
/*
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; import gplx.*; import gplx.xowa.*;
import org.junit.*; import gplx.xowa.files.repos.*; import gplx.xowa.files.imgs.*;
public class Xof_url_bldr__tst {
private Xof_url_bldr__fxt fxt = new Xof_url_bldr__fxt();
@Before public void init() {fxt.Clear().Dir_spr_http_();}
@Test public void Ogv() {fxt.Root_("http://test/").Md5_("d0").Ttl_("A.ogv").W_(220).Expd_src_("http://test/thumb/d/d0/A.ogv/220px--A.ogv.jpg").Test();}
@Test public void Ogv__seek() {fxt.Root_("http://test/").Md5_("d0").Ttl_("A.ogv").W_(220).Expd_src_("http://test/thumb/d/d0/A.ogv/220px-seek%3D5-A.ogv.jpg").Seek_(5).Test();}
@Test public void Ogv__no_w() {fxt.Root_("http://test/").Md5_("d0").Ttl_("A.ogv").W_( -1).Expd_src_("http://test/thumb/d/d0/A.ogv/-1px--A.ogv.jpg").Test();} // TODO_OLD: use orig_w, not -1
@Test public void Xcf() {fxt.Root_("http://test/").Md5_("44").Ttl_("A.xcf").W_(220).Expd_src_("http://test/thumb/4/44/A.xcf/220px-A.xcf.png").Test();}
@Test public void Bmp() {fxt.Root_("http://test/").Md5_("70").Ttl_("A.bmp").W_(220).Expd_src_("http://test/thumb/7/70/A.bmp/220px-A.bmp.png").Test();}
@Test public void Pdf() {fxt.Root_("http://test/").Md5_("ef").Ttl_("A.pdf").W_(220).Expd_src_("http://test/thumb/e/ef/A.pdf/page1-220px-A.pdf.jpg").Test();}
@Test public void Pdf__page_2() {fxt.Root_("http://test/").Md5_("ef").Ttl_("A.pdf").W_(220).Expd_src_("http://test/thumb/e/ef/A.pdf/page2-220px-A.pdf.jpg").Page_(2).Test();}
@Test public void Long() {
String filename = String_.Repeat("A", 200) + ".png";
fxt.Root_("http://test/").Md5_("14").Ttl_(filename).W_(220)
.Expd_src_("http://test/thumb/1/14/" + filename + "/220px-thumbnail.png")
.Test()
;
}
@Test public void Math__http() {fxt.Repo_tid_(Xof_repo_tid_.Tid__math).Fsys_is_wnt_(Bool_.N).Root_("http://test/").Ttl_("random_md5.svg").Expd_src_("http://test/random_md5").Test();} // NOTE: strip ".svg" if online
@Test public void Math__file() {fxt.Repo_tid_(Xof_repo_tid_.Tid__math).Fsys_is_wnt_(Bool_.Y).Root_("file://xowa/").Ttl_("random_md5.svg").Expd_src_("file://xowa/random_md5.svg").Test();} // NOTE: keep ".svg" if online
}
class Xof_url_bldr__fxt {
private final Xof_url_bldr url_bldr = new Xof_url_bldr();
public Xof_url_bldr__fxt Clear() {
dir_spr = Byte_.Zero; ext = null; root = md5 = ttl = expd_src = null;
seek = Xof_lnki_time.Null;
page = Xof_lnki_page.Null;
w = Xof_img_size.Null;
return this;
}
public Xof_url_bldr__fxt Dir_spr_http_() {return Dir_spr_(Byte_ascii.Slash);}
public Xof_url_bldr__fxt Dir_spr_fsys_wnt_() {return Dir_spr_(Byte_ascii.Backslash);}
public Xof_url_bldr__fxt Dir_spr_(byte v) {dir_spr = v; return this;} private byte dir_spr;
public Xof_url_bldr__fxt Root_(String v) {root = v; return this;} private String root;
public Xof_url_bldr__fxt Md5_(String v) {md5 = v; return this;} private String md5;
public Xof_url_bldr__fxt Ttl_(String v) {ttl = v; ext = Xof_ext_.new_by_ttl_(Bry_.new_u8(v)); return this;} private String ttl; Xof_ext ext;
public Xof_url_bldr__fxt W_(int v) {this.w = v; return this;} private int w;
public Xof_url_bldr__fxt Page_(int v) {page = v; return this;} private int page = Xof_lnki_page.Null;
public Xof_url_bldr__fxt Seek_(int v) {seek = v; return this;} private double seek = Xof_lnki_time.Null;
public Xof_url_bldr__fxt Repo_tid_(byte v) {repo_tid = v; return this;} private byte repo_tid = Xof_repo_tid_.Tid__null;
public Xof_url_bldr__fxt Fsys_is_wnt_(boolean v) {fsys_is_wnt = v; return this;} private boolean fsys_is_wnt;
public Xof_url_bldr__fxt Expd_src_(String v) {expd_src = v; return this;} private String expd_src;
public Xof_url_bldr__fxt Test() {
url_bldr.Init_by_repo(repo_tid, Bry_.new_u8(root), fsys_is_wnt, dir_spr, Bool_.Y, Bool_.N, 2);
url_bldr.Init_by_itm (Xof_img_mode_.Tid__thumb, Bry_.new_u8(ttl), Bry_.new_u8_safe(md5), ext, w, seek, page);
Tfds.Eq(expd_src, url_bldr.Xto_str());
return this;
}
}

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; import gplx.*; import gplx.xowa.*;
import gplx.xowa.files.fsdb.*;
import gplx.xowa.files.fsdb.fs_roots.*;
class Xof_wkr_mgr implements Gfo_invk {
private Xow_file_mgr file_mgr;
public Xof_wkr_mgr(Xow_file_mgr file_mgr) {this.file_mgr = file_mgr;}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_get)) return Get_or_new(m.ReadStr("v"));
else return Gfo_invk_.Rv_unhandled;
}
private static final String Invk_get = "get";
private Xof_fsdb_mgr Get_or_new(String key) {
if (String_.Eq(key, "fs.dir")) {
return Fs_root_core.Set_fsdb_mgr(file_mgr, file_mgr.Wiki());
}
else
throw Err_.new_unhandled(key);
}
}

View File

@@ -0,0 +1,313 @@
/*
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; import gplx.*; import gplx.xowa.*;
import gplx.core.primitives.*;
import gplx.xowa.guis.cbks.js.*; import gplx.xowa.files.repos.*; import gplx.xowa.files.imgs.*;
import gplx.xowa.wikis.tdbs.metas.*;
import gplx.xowa.parsers.utils.*;
public class Xof_xfer_itm implements Xof_file_itm {
private Xof_url_bldr tmp_url_bldr = dflt_url_bldr;
public Xof_xfer_itm() {
lnki_type = orig_repo_id = Byte_.Max_value_127;
lnki_w = lnki_h = file_w = orig_w = orig_h = html_w = html_h = html_gallery_mgr_h = Int_.Neg1;
orig_ext = null;
lnki_upright = Int_.Neg1; lnki_time = Xof_lnki_time.Null; lnki_page = Xof_lnki_page.Null;
file_exists = false; file_is_orig = true;
orig_file_len = 0; // NOTE: cannot be -1, or else will always download orig; see ext rule chk and (orig_file_len < 0)
orig_repo_name = orig_ttl = orig_redirect = null; lnki_ttl = null; orig_ttl_md5 = null;
html_orig_url = html_view_url = Io_url_.Empty;
meta_itm = null;
html_uid = Int_.Neg1; html_elem_tid = Xof_html_elem.Tid_none;
}
public int Lnki_exec_tid() {return lnki_exec_tid;} private int lnki_exec_tid;
public byte[] Lnki_wiki_abrv() {return lnki_wiki_abrv;} private byte[] lnki_wiki_abrv;
public byte[] Lnki_ttl() {return lnki_ttl;} private byte[] lnki_ttl;
public byte Lnki_type() {return lnki_type;} private byte lnki_type;
public double Lnki_upright() {return lnki_upright;} private double lnki_upright;
public int Lnki_w() {return lnki_w;} private int lnki_w;
public int Lnki_h() {return lnki_h;} private int lnki_h;
public double Lnki_time() {return lnki_time;} private double lnki_time;
public int Lnki_page() {return lnki_page;} private int lnki_page;
public boolean Orig_exists() {return orig_exists;} private boolean orig_exists;
public byte Orig_repo_id() {return orig_repo_id;} private byte orig_repo_id;
public byte[] Orig_repo_name() {return orig_repo_name;} private byte[] orig_repo_name;
public byte[] Orig_ttl() {return orig_ttl;} private byte[] orig_ttl;
public byte[] Orig_ttl_md5() {return orig_ttl_md5;} private byte[] orig_ttl_md5;
public Xof_ext Orig_ext() {return orig_ext;} private Xof_ext orig_ext;
public int Orig_w() {return orig_w;} private int orig_w;
public int Orig_h() {return orig_h;} private int orig_h;
public byte[] Orig_redirect() {return orig_redirect;} private byte[] orig_redirect;
public long Orig_file_len() {return orig_file_len;} private long orig_file_len; // used for filtering downloads by file_max
public boolean File_is_orig() {return file_is_orig;} private boolean file_is_orig; // SEE:NOTE_1:Lnki_thumbable
public int File_w() {return file_w == -1 ? html_w : file_w;} private int file_w = -1; // NOTE: for itm_meta, file_w == html_w
public int Html_uid() {return html_uid;} private int html_uid;
public byte Html_elem_tid() {return html_elem_tid;} private byte html_elem_tid;
public int Html_w() {return html_w;} private int html_w;
public int Html_h() {return html_h;} private int html_h;
public Io_url Html_view_url() {return html_view_url;} private Io_url html_view_url = Io_url_.Empty; // needed else null_err
public Io_url Html_orig_url() {return html_orig_url;} private Io_url html_orig_url = Io_url_.Empty; // needed else null_err
public int Html_gallery_mgr_h() {return html_gallery_mgr_h;} private int html_gallery_mgr_h;
public Js_img_wkr Html_img_wkr() {return html_img_wkr;} private Js_img_wkr html_img_wkr;
public boolean File_exists() {return file_exists;} private boolean file_exists;
public boolean File_exists_in_cache() {return false;}
public boolean Dbmeta_is_new() {return meta_itm.State_new();}
public void Html_elem_tid_(byte v) {html_elem_tid = v;}
public void Html_size_(int w, int h) {this.html_w = w; this.html_h = h;}
public void Html_gallery_mgr_h_(int v) {html_gallery_mgr_h = v;}
public void Html_img_wkr_(Js_img_wkr v) {html_img_wkr = v;}
public int Hdump_mode() {return hdump_mode;} private int hdump_mode = Xof_fsdb_itm.Hdump_mode__null;
public void File_exists_y_() {file_exists = Bool_.Y;} public void File_exists_n_() {file_exists = Bool_.N;} public void File_exists_(boolean v) {file_exists = v;}
public void Html_orig_url_(Io_url v) {html_orig_url = v;}
public void Init_at_lnki(int exec_tid, byte[] wiki_abrv, byte[] ttl, byte lnki_type, double upright, int w, int h, double time, int page, int lnki_upright_patch) {
this.lnki_exec_tid = exec_tid; this.lnki_wiki_abrv = wiki_abrv;
this.lnki_type = lnki_type; this.lnki_upright = upright; this.lnki_w = w; this.lnki_h = h; this.lnki_time = time; this.lnki_page = page;
this.file_is_orig = !Xof_xfer_itm_.Lnki_thumbable_calc(lnki_type, lnki_w, lnki_h);
this.lnki_ttl = Xof_file_wkr_.Md5_decoder.Decode(Xof_file_wkr_.Ttl_standardize(ttl));
this.Orig_ttl_(ttl);
this.orig_ext = Xof_ext_.new_by_ttl_(ttl);
if (lnki_time != Xof_lnki_time.Null && !orig_ext.Id_is_media()) // thumbtime is set, but ext is not media; PAGE:en.w:Moon; EX:[[File:A.png|thumbtime=0:02]] DATE:2014-07-22
lnki_time = Xof_lnki_time.Null; // disable thumbtime
}
public void Init_at_orig(byte orig_repo_id, byte[] orig_repo_name, byte[] orig_ttl, Xof_ext orig_ext, int orig_w, int orig_h, byte[] orig_redirect) {
this.orig_repo_id = orig_repo_id; this.orig_repo_name = orig_repo_name;
this.orig_ttl = orig_ttl; this.orig_ttl_md5 = Xof_file_wkr_.Md5(orig_ttl);
this.orig_w = orig_w; this.orig_h = orig_h; this.orig_redirect = orig_redirect;
if (Bry_.Len_gt_0(orig_redirect)) // redirect exists; EX: A.png redirected to B.png
this.Orig_ttl_(orig_redirect); // update fsdb with atrs of B.png
else if (!Bry_.Eq(lnki_ttl, orig_ttl)) // ttls differ; EX: "A_.png" vs "A.png"
this.Orig_ttl_(orig_ttl);
else
this.Orig_ttl_(orig_ttl);
this.orig_ext = orig_ext; // overwrite ext with whatever's in file_orig; needed for ogg -> oga / ogv
this.orig_exists = true;
}
public void Init_at_gallery_bgn(int html_w, int html_h, int file_w) {
this.html_w = html_w; this.html_h = html_h;
this.file_w = file_w;
}
public void Init_at_gallery_end(int html_w, int html_h, Io_url html_view_url, Io_url html_orig_url) {
this.html_w = html_w; this.html_h = html_h;
this.html_view_url = html_view_url;
this.html_orig_url = html_orig_url;
this.file_exists = true;
}
public void Calc_by_fsdb(int html_w, int html_h, Io_url view_url, Io_url orig_url) {
this.html_w = html_w;
this.html_h = html_h;
this.html_orig_url = orig_url;
this.html_view_url = view_url;
}
public void Orig_ttl_and_redirect_(byte[] ttl, byte[] redirect) {
this.orig_redirect = redirect;
this.lnki_ttl = orig_redirect == Xop_redirect_mgr.Redirect_null_bry ? Bry_.Copy(ttl) : orig_redirect;
this.lnki_ttl = Xof_file_wkr_.Md5_decoder.Decode(Xof_file_wkr_.Ttl_standardize(lnki_ttl)); // NOTE: this line is repeated in static method below
this.orig_ttl = lnki_ttl;
this.orig_ttl_md5 = Xof_file_wkr_.Md5_fast(lnki_ttl); // NOTE: md5 is calculated off of url_decoded ttl; EX: A%2Cb is converted to A,b and then md5'd. note that A%2Cb still remains the title
this.orig_ext = Xof_ext_.new_by_ttl_(lnki_ttl);
}
private void Orig_ttl_(byte[] v) {
this.orig_ttl = Xof_file_wkr_.Ttl_standardize(v);
this.orig_ttl_md5 = Xof_file_wkr_.Md5_fast(v);
}
public Xof_meta_itm Dbmeta_itm() {return meta_itm;} private Xof_meta_itm meta_itm;
public void Trg_repo_itm_(Xof_repo_itm v) {
trg_repo_itm = v;
trg_repo_root = trg_repo_itm == null ? Bry_.Empty : trg_repo_itm.Root_http();
} private Xof_repo_itm trg_repo_itm;
public byte[] Trg_repo_root() {return trg_repo_root;} private byte[] trg_repo_root = Bry_.Empty; // HACK: needed for hdump
public void Ctor_for_html(int exec_tid, int lnki_upright_patch, Xof_img_size img_size, Xof_repo_itm repo, Xof_url_bldr url_bldr) {
Calc_html_size(exec_tid, lnki_upright_patch, img_size);
this.html_view_url = url_bldr.To_url_trg(repo, this, file_is_orig);
this.html_orig_url = url_bldr.To_url_trg(repo, this, Bool_.Y);
}
private void Calc_html_size(int exec_tid, int lnki_upright_patch, Xof_img_size img_size) {
if (!orig_ext.Id_is_media() && lnki_time != Xof_lnki_time.Null) // file is not media, but has thumbtime; this check can't be moved to Lnki_time_() b/c it needs ext
lnki_time = Xof_lnki_time.Null; // set time to null; needed else url will reference thumbtime; PAGE:en.w:Moon; EX:[[File:Lunar libration with phase Oct 2007 450px.gif|thumbtime=0:02]]; DATE:2014-07-20
if (orig_ext.Id_is_audio_strict()) // audio does not have html size calculated; everything else does
this.file_is_orig = Bool_.Y;
else {
img_size.Html_size_calc(exec_tid, lnki_w, lnki_h, lnki_type, lnki_upright_patch, lnki_upright, orig_ext.Id(), orig_w, orig_h, Xof_img_size.Thumb_width_img);
html_w = img_size.Html_w(); html_h = img_size.Html_h(); file_w = img_size.File_w();
this.file_is_orig = img_size.File_is_orig();
}
}
public void Init_by_orig_old(int w, int h, int orig_file_len) {
this.orig_w = w; this.orig_h = h; this.orig_file_len = orig_file_len;
}
public void Orig_repo_id_(int v) {this.orig_repo_id = (byte)v;}
public void File_w_(int v) {file_w = v;}
public void Init_for_test__img(int html_w, int html_h, Io_url html_view_url, Io_url html_orig_url) {
this.html_w = html_w; this.html_h = html_h; this.html_view_url = html_view_url; this.html_orig_url = html_orig_url;
}
public void Init_at_hdoc(int html_uid, byte html_elem_tid) {
this.html_uid = html_uid; this.html_elem_tid = html_elem_tid;
}
public void Set__meta(Xof_meta_itm meta_itm, Xof_repo_itm trg_repo_itm, int thumb_w_img) {
this.meta_itm = meta_itm; Trg_repo_itm_(trg_repo_itm); this.thumb_w_img = thumb_w_img;
this.orig_w = meta_itm.Orig_w(); this.orig_h = meta_itm.Orig_h(); // orig_w / orig_h needed for imap; DATE:2014-08-08
} private int thumb_w_img;
public void Set__meta_only(Xof_meta_itm meta_itm) {this.meta_itm = meta_itm; Orig_ttl_and_redirect_(meta_itm.Ttl(), meta_itm.Ptr_ttl());}
public void Init_at_html(int exec_tid, Xof_img_size img_size, Xof_repo_itm repo, Xof_url_bldr url_bldr) {
Calc_html_size(exec_tid, img_size);
this.html_view_url = url_bldr.To_url_trg(repo, this, file_is_orig);
this.html_orig_url = url_bldr.To_url_trg(repo, this, Bool_.Y);
}
private void Calc_html_size(int exec_tid, Xof_img_size img_size) {
if (!orig_ext.Id_is_media() && lnki_time != Xof_lnki_time.Null) // file is not media, but has thumbtime; this check can't be moved to Lnki_time_() b/c it needs ext
lnki_time = Xof_lnki_time.Null; // set time to null; needed else url will reference thumbtime; PAGE:en.w:Moon; EX:[[File:Lunar libration with phase Oct 2007 450px.gif|thumbtime=0:02]]; DATE:2014-07-20
if (orig_ext.Id_is_audio_strict()) // audio does not have html size calculated; everything else does
file_is_orig = Bool_.Y;
else {
img_size.Html_size_calc(exec_tid, lnki_w, lnki_h, lnki_type, Xof_patch_upright_tid_.Tid_all, lnki_upright, orig_ext.Id(), orig_w, orig_h, Xof_img_size.Thumb_width_img);
html_w = img_size.Html_w(); html_h = img_size.Html_h();
file_w = img_size.File_w();
file_is_orig = img_size.File_is_orig();
}
}
private Io_url Trg_view_url(byte mode_id, int width) {return tmp_url_bldr.Init_for_trg_file(trg_repo_itm, mode_id, lnki_ttl, orig_ttl_md5, orig_ext, width, lnki_time, lnki_page).Xto_url();}
public Io_url Trg_orig_url(byte mode_id, int width) {return tmp_url_bldr.Init_for_trg_file(trg_repo_itm, mode_id, lnki_ttl, orig_ttl_md5, orig_ext, width, lnki_time, lnki_page).Xto_url();}
public boolean Calc_by_meta() {return Calc_by_meta(false);}
public boolean Calc_by_meta(boolean caller_is_file_page) {
file_exists = false;
html_orig_url = html_view_url = Io_url_.Empty;
html_w = lnki_w; html_h = lnki_h;
if (meta_itm == null || trg_repo_itm == null) return false;
if (meta_itm.Ptr_ttl_exists()) {
lnki_ttl = meta_itm.Ptr_ttl();
orig_ttl_md5 = Xof_file_wkr_.Md5(lnki_ttl);
}
boolean limit_size = !orig_ext.Id_is_svg() || (orig_ext.Id_is_svg() && caller_is_file_page);
if (orig_ext.Id_is_media() && html_w < 1) // if media and no width, set to default; NOTE: must be set or else dynamic download will resize play button to small size; DATE:20121227
html_w = Xof_img_size.Thumb_width_ogv;
if (!file_is_orig) { // file is thumb
if (orig_ext.Id_is_video()) { // video is a special case; src is thumb_w but html_w / html_h is based on calc
html_orig_url = Trg_view_url(Xof_img_mode_.Tid__orig, Xof_img_size.Size__neg1);
if (meta_itm.Thumbs_indicates_oga() && orig_ext.Id_is_ogv()) {orig_ext = Xof_ext_.new_by_ext_(Xof_ext_.Bry_oga); return true;} // if audio, do not thumb; NOTE: must happen after html_orig_bry, b/c html must still be generated to auto-download files; NOTE: must change ext to oga b/c ogg may trigger video code elsewhere
Xof_meta_thumb thumb = meta_itm.Thumbs_get_vid(Xof_lnki_time.X_int(lnki_time));
if (thumb != null) {
Xof_xfer_itm_.Calc_xfer_size(calc_size, lnki_type, thumb_w_img, thumb.Width(), thumb.Height(), html_w, html_h, !file_is_orig, lnki_upright);
html_w = calc_size.Val_0(); html_h = calc_size.Val_1();
html_view_url = Trg_view_url(Xof_img_mode_.Tid__thumb, thumb.Width()); // NOTE: must pass thumb.Width() not html_w b/c only one thumb generated for a video file
file_exists = true;
return true;
}
}
else { // regular thumb
html_orig_url = Trg_view_url(Xof_img_mode_.Tid__orig, Xof_img_size.Size__neg1);
if (orig_ext.Id_is_audio()) return true; // if audio, do not thumb; even if user requests thumb;
Xof_meta_thumb[] thumbs = meta_itm.Thumbs(); int thumbs_len = thumbs.length; Xof_meta_thumb thumb = null;
if (lnki_h > 0 && orig_w < 1 && thumbs_len > 0) { // if height is specified and no orig, then iterate over thumbs to find similar height; NOTE: this is a fallback case; orig_w/h is optimal; EX: c:Jacques-Louis David and <gallery>
Xof_meta_thumb largest = meta_itm.Thumbs_get_largest(thumbs_len); // get largest thumb
Xof_xfer_itm_.Calc_xfer_size(calc_size, lnki_type, thumb_w_img, largest.Width(), largest.Height(), html_w, html_h, !file_is_orig, lnki_upright, false); // use largest to calc correct width/height; note that this is needed for gallery which passes in 120,120; EX:c:Yellowstone Park
int comp_height = calc_size.Val_1();
for (int i = 0; i < thumbs_len; i++) {
Xof_meta_thumb tmp_thumb = thumbs[i];
if (Int_.Between(tmp_thumb.Height(), comp_height - 1, comp_height + 1)) {
thumb = tmp_thumb;
break;
}
}
if (thumb != null) return Calc_by_meta_found(lnki_type, thumb.Width(), thumb.Height()); // thumb found
}
Xof_xfer_itm_.Calc_xfer_size(calc_size, lnki_type, thumb_w_img, meta_itm.Orig_w(), meta_itm.Orig_h(), html_w, html_h, !file_is_orig, lnki_upright, limit_size); // calc html_h and html_w; can differ from lnki_w, lnki_h; note that -1 width is handled by thumb_w_img
html_w = calc_size.Val_0();
if (html_h != -1) html_h = calc_size.Val_1(); // NOTE: if -1 (no height specified) do not set height; EX:Tokage_2011-07-15.jpg; DATE:2013-06-03
html_view_url = Trg_view_url(Xof_img_mode_.Tid__thumb, this.File_w());
thumb = meta_itm.Thumbs_get_img(html_w, 0);
if (thumb == null) { // exact thumb not found
if (html_w == meta_itm.Orig_w() // html_w matches orig_w; occurs when thumb,upright requested, but upright size is larger than orig; PAGE:en.w:St. Petersburg
&& !orig_ext.Id_needs_convert() // but ext cannot be something that needs conversion; EX: 120,90 svg may match thumb of 120,90, but .png still needs to be generated
&& meta_itm.Orig_exists() == Xof_meta_itm.Exists_y
) {
html_h = meta_itm.Orig_h();
html_view_url = Trg_view_url(Xof_img_mode_.Tid__orig, -1);
file_exists = true;
return true;
}
if (orig_ext.Id_is_djvu()) { // NOTE: exact djvu w thumbs are not on server; always seems to be 1 off; EX: 90 requested, but 90 doesn't exist; 89 does
thumb = meta_itm.Thumbs_get_img(html_w, 1);
if (thumb != null) return Calc_by_meta_found(lnki_type, thumb.Width(), thumb.Height()); // thumb found
}
}
else {
html_h = thumb.Height();
file_exists = true;
return true;
}
}
}
else { // file is orig
byte mode_id = orig_ext.Id_is_svg() ? Xof_img_mode_.Tid__thumb : Xof_img_mode_.Tid__orig; // svgs will always return thumb; EX:[[A.svg]] -> A.svg.png
html_view_url = html_orig_url = Trg_view_url(mode_id, this.File_w());
if (meta_itm.Thumbs_indicates_oga() && orig_ext.Id_is_ogv()) {orig_ext = Xof_ext_.new_by_ext_(Xof_ext_.Bry_oga); return true;} // if audio, do not thumb; NOTE: must happen after html_orig_bry, b/c html must still be generated to auto-download files; NOTE: must change ext to oga b/c ogg may trigger video code elsewhere
if (orig_ext.Id_is_audio()) return true; // if audio, return true; SEE:NOTE_2
else if (orig_ext.Id_is_video()) {
Xof_meta_thumb thumb = meta_itm.Thumbs_get_vid(Xof_lnki_time.X_int(lnki_time)); // get thumb at lnki_time; NOTE: in most cases this will just be the 1st thumb; note that orig video files don't have an official thumb
if (thumb != null) {
html_w = thumb.Width(); html_h = thumb.Height(); // NOTE: take thumb_size; do not rescale to html_w, html_h b/c html_w will default to 220; native width of thumbnail should be used; DATE:2013-04-11
html_view_url = Trg_view_url(Xof_img_mode_.Tid__thumb, thumb.Width()); // NOTE: must pass thumb.Width() not html_w b/c only one thumb generated for a video file
file_exists = true;
return true;
}
}
if (meta_itm.Orig_exists() == Xof_meta_itm.Exists_y) { // file found previously >>> gen html
html_w = meta_itm.Orig_w(); html_h = meta_itm.Orig_h();
html_view_url = Trg_view_url(mode_id, this.File_w());
file_exists = true;
return true;
}
}
// file not found >>> set size to 0 and byte[] to empty
html_w = lnki_w < 0 ? 0 : lnki_w;
html_h = lnki_h < 0 ? 0 : lnki_h;
return false;
} private Int_2_ref calc_size = new Int_2_ref();
private boolean Calc_by_meta_found(byte lnki_type, int model_w, int model_h) {
Xof_xfer_itm_.Calc_xfer_size(calc_size, lnki_type, thumb_w_img, model_w, model_h, html_w, html_h, !file_is_orig, lnki_upright, false); // recalc html_w, html_h; note that false passed b/c truncation is not needed
html_w = calc_size.Val_0(); html_h = calc_size.Val_1();
html_view_url = Trg_view_url(Xof_img_mode_.Tid__thumb, model_w); // note that thumb.Width is used (the actual file width), not html_w
file_exists = true;
return true;
}
private static final Xof_url_bldr dflt_url_bldr = new Xof_url_bldr(); // NOTE: only used by v1
}
/*
NOTE_1:Lnki_thumbable
. false only if following form
[[A.png]] -> must get orig
. true in almost all other cases, especially if (a) type is thumb; (b) size exists; (c) upright;
. basically, indicates that image will be stored on wmf server as "/thumb/" url
[[A.png|thumb]] -> default to 220 and check for 220px
[[A.png|40px]] -> check for 40px
[[A.png|x40px]] -> calc n width and check for npx
NOTE_2:return true if media
. this seems hackish, but if Atrs_calc_for_html returns false, then file is generally added to the queue
. the problem is that media/audio is usually not found
.. so, for example, when a wiki page does pronunciation [[File:A.oga]], A.oga will return false (since it's not there)
.. however, unlike images which xowa will try to fetch the thumb, xowa will never fetch audios (since audios are not "visible", most will not be played, and some audios are big)
... the corollary is that audios are only fetched when the play buton is clicked (and via code in Xog_win_itm)
.. so, if false is returned, then A.oga gets added to the queue, only to be ignored by queue rules later
... the problem here is that the status bar will flash "downloading: File:A.oga" which is misleading
. so, return true so that it is never added to the queue. this depends on the "click" of the play button code to actually download the file
. note that video doesn't suffer from this issue, b/c video has thumbs which can or can not be found
*/

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.files; import gplx.*; import gplx.xowa.*;
import gplx.core.primitives.*;
import gplx.gfui.*; import gplx.xowa.parsers.lnkis.*;
public class Xof_xfer_itm_ {
public static void Calc_xfer_size(Int_2_ref rv, byte lnki_type, int thumb_default_w, int file_w, int file_h, int lnki_w, int lnki_h, boolean lnki_thumb, double lnki_upright, Xof_ext ext, int exec_tid) {
boolean ext_is_svg = ext.Id_is_svg();
boolean limit_size = !ext_is_svg || (ext_is_svg && exec_tid == Xof_exec_tid.Tid_wiki_file);
Calc_xfer_size(rv, lnki_type, thumb_default_w, file_w, file_h, lnki_w, lnki_h, lnki_thumb, lnki_upright, limit_size);
}
public static void Calc_xfer_size(Int_2_ref rv, byte lnki_type, int thumb_default_w, int file_w, int file_h, int lnki_w, int lnki_h, boolean lnki_thumb, double lnki_upright) {Calc_xfer_size(rv, lnki_type, thumb_default_w, file_w, file_h, lnki_w, lnki_h, lnki_thumb, lnki_upright, true);}
public static void Calc_xfer_size(Int_2_ref rv, byte lnki_type, int thumb_default_w, int file_w, int file_h, int lnki_w, int lnki_h, boolean lnki_thumb, double lnki_upright, boolean thumb_width_must_be_lt_file_width) {
int rv_w = lnki_w, rv_h = lnki_h;
if (lnki_w < 1 && lnki_h < 1) {
if (lnki_thumb) rv_w = thumb_default_w; // do not default to thumb if only height is set; EX: x900px should have w=0 h=900
else rv_w = file_w;
}
rv_w = Xof_img_size.Upright_calc(Xof_patch_upright_tid_.Tid_all, lnki_upright, rv_w, lnki_w, lnki_h, lnki_type); // only v1 calls Calc_xfer_size
if (file_w < 1) rv.Val_all_(rv_w, rv_h);
else Xof_xfer_itm_.Calc_view(rv, lnki_type, rv_w, rv_h, file_w, file_h, thumb_width_must_be_lt_file_width);
}
public static void Calc_view(Int_2_ref rv, byte lnki_type, int lnki_w, int lnki_h, int file_w, int file_h, boolean thumb_width_must_be_lt_file_width) {// SEE:NOTE_1 for proc source/layout
if (lnki_w == -1) lnki_w = file_w; // lnki_w missing >>> use file_w; REF.MW:Linker.php|makeImageLink2|$hp['width'] = $file->getWidth( $page );
if (lnki_h != -1) { // height exists; REF.MW:Generic.php|normaliseParams|if ( isset( $params['height'] ) && $params['height'] != -1 ) {
if (lnki_w * file_h > lnki_h * file_w) { // lnki ratio > file ratio; SEE:NOTE_2;
lnki_w = Calc_w(file_w, file_h, lnki_h);
}
}
lnki_h = Scale_h(file_w, file_h, lnki_w);
if ( Xop_lnki_type.Id_limits_large_size(lnki_type) // added on DATE:2014-04-09
&& lnki_w > file_w && thumb_width_must_be_lt_file_width) { // do not allow lnki_w > file_w; REF.MW:Generic.php|normaliseParams
lnki_w = file_w; lnki_h = file_h;
}
rv.Val_all_(lnki_w, lnki_h);
}
public static int Calc_w(int file_w, int file_h, int lnki_h) {
double ideal_w = (double)file_w * (double)lnki_h / (double)file_h;
double ideal_w_ceil = Math_.Ceil(ideal_w);
return Math_.Round(ideal_w_ceil * file_h / file_w, 0) > lnki_h
? (int)Math_.Floor(ideal_w)
: (int)ideal_w_ceil;
}
public static int Scale_h(int file_w, int file_h, int lnki_w) {
return file_w == 0 // REF.MW:File.php|scaleHeight
? 0
: (int)Math_.Round(((double)lnki_w * file_h) / file_w, 0); // NOTE: (double) needed else result will be int and decimal will be automatically truncated
}
public static boolean Lnki_thumbable_calc(byte lnki_type, int lnki_w, int lnki_h) {
return
( lnki_type == Xop_lnki_type.Id_frame && lnki_w != -1 && lnki_h != -1)
|| (Xop_lnki_type.Id_defaults_to_thumb(lnki_type) || lnki_w != -1 || lnki_h != -1)
;
} // SEE:NOTE_3
}
/*
NOTE_1:proc source/layout
MW calls the falling procs
. Linker.php|makeImageLink2
. Linker.php|makeThumbLink2
. File.php|transform
. Bitmap.php|normaliseParams
. Generic.php|normaliseParams
. File.php|scaleHeight
Note that this proc is a selective culling of the w,h setting code in the above (the procs do a lot of other checks/building)
also, MW's if branching can be combined. for now, emulating MW and not enforcing matching if/else
NOTE_2: view ratio > file ratio
REF.MW:ImageFunctions.php|wfFitBoxWidth
don't know why this logic exists; for now, articulating example
consider file of 200,100 (2:1)
EX_1: view is 120,40 (3:1)
- (a) 120,80 or (b) 80,40
- (b) 80,40
EX_2: view is 120,80 (1.5:1)
- (a) 120,60 or (b) 160,80
- (a) 120,60
*/

View File

@@ -0,0 +1,65 @@
/*
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; import gplx.*; import gplx.xowa.*;
import org.junit.*; import gplx.core.primitives.*; import gplx.gfui.*; import gplx.xowa.files.*; import gplx.xowa.parsers.lnkis.*;
public class Xof_xfer_itm_tst {
@Before public void init() {fxt.ini();} Xof_xfer_itm_fxt fxt = new Xof_xfer_itm_fxt();
@Test public void Box() {tst_Calc_view("40,50" , "40,40" , "40,40");} // EX:[[File:Crystal Clear app kedit.svg|50x40px]]
@Test public void Long_w() {tst_Calc_view("128,80" , "720,194" , "128,34");} // EX:[[File:Firma B.Ohiggins.svg|128x80px|alt=|Bernardo O'Higgins's signature]]
@Test public void Long_h() {tst_Calc_view("300,-1" , "149,408" , "149,408");} // EX:[[File:Adhanema Lasva.jpg|thumb|300px|The Firman given to the Bosnian Franciscans]]
@Test public void Width_too_long() {tst_Calc_view("100,-1" , "40,40" , "40,40");} // limit to height;
@Test public void Width_missing() {tst_Calc_view("-1,20" , "80,40" , "40,20");} // calc width based on height and file_size
@Test public void Prefer_height_over_width() {tst_Calc_view("60,20" , "120,60" , "40,20");} // prefer height; if width was preferred, size would be 60,30
@Test public void Height_missing() {tst_Calc_view("50,-1" , "100,200" , "50,100");}
@Test public void Explicit_ratio_large() {tst_Calc_view("120,40" , "200,100" , "80,40");} // see NOTE_1:view ratio > file ratio
@Test public void Explicit_ratio_small() {tst_Calc_view("120,80" , "200,100" , "120,60");} // see NOTE_1:view ratio > file ratio
private void tst_Calc_view(String lnki_str, String file_str, String expd_str) {
Int_2_ref rv = new Int_2_ref();
Int_2_val lnki = Int_2_val.parse(lnki_str);
Int_2_val file = Int_2_val.parse(file_str);
Int_2_val expd = Int_2_val.parse(expd_str);
Xof_xfer_itm_.Calc_view(rv, Xop_lnki_type.Id_thumb, lnki.Val_0(), lnki.Val_1(), file.Val_0(), file.Val_1(), true);
Tfds.Eq(expd.Val_0(), rv.Val_0());
Tfds.Eq(expd.Val_1(), rv.Val_1());
}
@Test public void Thumb_lnkY() {fxt.Lnki_(300, 200).tst(300, 200);} // size provided; use
@Test public void Thumb_lnkN() {fxt.Lnki_( -1, -1).tst(220, -1);} // w=thumbnail default
@Test public void Thumb_lnkN_sqlY() {fxt.Lnki_( -1, -1).File_(220, 200).tst(220, 200);} // w=thumbnail default; h=calc from sql
@Test public void Thumb_lnkN_sqlY_adjH() {fxt.Lnki_( -1, -1).File_(440, 500).tst(220, 250);} // w=thumbnail default; h=calc from sql
@Test public void Thumb_lnkW_sqlY() {fxt.Lnki_(200, -1).File_(400, 500).tst(200, 250);} // w=lnki; h=calc from sql
@Test public void Thumb_lnkH_sqlY() {fxt.Lnki_( -1, 250).File_(400, 500).tst(200, 250);} // w=calc from sql
@Test public void Thumb_lnkW_sqlY_W_too_large() {fxt.Lnki_(600, 750).File_(400, 500).tst(400, 500);} // w/h: truncate to file
@Test public void Thumb_w_is_wrong() {fxt.Lnki_( 20, 20).File_( 80, 100).tst( 16, 20);}
@Test public void Thumb_w_is_wrong_2() {fxt.Lnki_( 65, 50).File_(160, 160).tst( 50, 50);}
@Test public void Thumb_size_is_wrong() {fxt.Lnki_(128, 80).File_(720, 194).tst(128, 34);}
}
class Xof_xfer_itm_fxt {
public Xof_xfer_itm_fxt ini() {lnki_img_type = Xop_lnki_type.Id_thumb; lnki_upright = -1; file_w = file_h = lnki_w = lnki_h = -1; return this;}
public Xof_xfer_itm_fxt Lnki_img_type_(byte v) {lnki_img_type = v; return this;} private byte lnki_img_type;
public Xof_xfer_itm_fxt Lnki_upright_(double v) {lnki_upright = v; return this;} double lnki_upright;
public Xof_xfer_itm_fxt File_(int w, int h) {file_w = w; file_h = h; return this;} private int file_w, file_h;
public Xof_xfer_itm_fxt Lnki_(int w, int h) {lnki_w = w; lnki_h = h; return this;} private int lnki_w, lnki_h;
public Xof_xfer_itm_fxt tst(int expd_w, int expd_h) {
boolean wmf_thumbable = Xof_xfer_itm_.Lnki_thumbable_calc(lnki_img_type, lnki_w, lnki_h);
Int_2_ref calc_size = new Int_2_ref();
Xof_xfer_itm_.Calc_xfer_size(calc_size, Xop_lnki_type.Id_thumb, Xof_img_size.Thumb_width_img, file_w, file_h, lnki_w, lnki_h, wmf_thumbable, lnki_upright);
Tfds.Eq(expd_w, calc_size.Val_0());
Tfds.Eq(expd_h, calc_size.Val_1());
return this;
}
}

View File

@@ -0,0 +1,186 @@
/*
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; import gplx.*; import gplx.xowa.*;
import org.junit.*; import gplx.core.primitives.*; import gplx.dbs.*;
import gplx.xowa.files.fsdb.*; import gplx.xowa.files.caches.*; import gplx.xowa.parsers.lnkis.*;
import gplx.xowa.apps.*; import gplx.xowa.wikis.*; import gplx.xowa.files.origs.*;
public class Xofv_file_mgr_tst {
// @Before public void init() {fxt.Clear();} private final Xofv_file_mgr_fxt fxt = new Xofv_file_mgr_fxt();
@After public void term() {Gfo_usr_dlg_.Instance = Gfo_usr_dlg_.Noop;}
@Test public void Stub() {}
// @Test public void Thumb() {
// fxt .Init_orig_add(fxt.Mkr_orig().Init_comm("A.png", 440, 400))
// .Init_fsdb_add(fxt.Mkr_fsdb().Init_comm_thum("A.png", 220, 200))
// .Init_xfer_add(fxt.Mkr_xfer().Init_thumb(0, "A.png", 220, 200))
// .Exec_process_lnki()
// .Test_html_get(fxt.Mkr_html().Init(0, "file:///mem/xowa/file/comm/thumb/7/0/A.png/220px.png", 220, 200))
// .Test_fsys_get("mem/xowa/file/comm/thumb/7/0/A.png/220px.png")
// .Test_fsdb_download(1);
// ;
// }
// @Test public void Orig() {
// fxt .Init_orig_add(fxt.Mkr_orig().Init_comm("A.png", 440, 400))
// .Init_fsdb_add(fxt.Mkr_fsdb().Init_comm_orig("A.png", 440, 400))
// .Init_xfer_add(fxt.Mkr_xfer().Init_none(0, "A.png"))
// .Exec_process_lnki()
// .Test_html_get(fxt.Mkr_html().Init(0, "file:///mem/xowa/file/comm/orig/7/0/A.png", 440, 400))
// .Test_fsys_get("mem/xowa/file/comm/orig/7/0/A.png")
// .Test_fsdb_download(1);
// ;
// }
// @Test public void Img_size() { // PURPOSE: test integration of Xof_img_size
// fxt .Init_orig_add(fxt.Mkr_orig().Init_comm("A.png", 440, 400))
// .Init_fsdb_add(fxt.Mkr_fsdb().Init_comm_thum("A.png", 110, 100))
// .Init_xfer_add(fxt.Mkr_xfer().Init_thumb(0, "A.png", Xof_img_size.Null, Xof_img_size.Null).Upright_(.5f))
// .Exec_process_lnki()
// .Test_html_get(fxt.Mkr_html().Init(0, "file:///mem/xowa/file/comm/thumb/7/0/A.png/110px.png", 110, 100))
// .Test_fsys_get("mem/xowa/file/comm/thumb/7/0/A.png/110px.png")
// .Test_fsdb_download(1);
// ;
// }
// @Test public void Orig_mgr() { // PURPOSE: test integration of Orig_mgr
// fxt .Init_orig_add(fxt.Mkr_orig().Init_comm_redirect("B.jpg", "A.png", 440, 400)) // B.jpg redirects to A.png
// .Init_fsdb_add(fxt.Mkr_fsdb().Init_comm_thum("A.png", 220, 200))
// .Init_xfer_add(fxt.Mkr_xfer().Init_thumb(0, "B.jpg", 220, 200))
// .Exec_process_lnki()
// .Test_html_get(fxt.Mkr_html().Init(0, "file:///mem/xowa/file/comm/thumb/7/0/A.png/220px.png", 220, 200))
// .Test_fsys_get("mem/xowa/file/comm/thumb/7/0/A.png/220px.png")
// .Test_fsdb_download(1);
// ;
// }
// @Test public void Cache_exists() {
// fxt .Init_orig_add(fxt.Mkr_orig().Init_comm("A.png", 440, 400))
// .Init_fsdb_add(fxt.Mkr_fsdb().Init_comm_thum("A.png", 220, 200))
// .Init_xfer_add(fxt.Mkr_xfer().Init_thumb(0, "A.png", 220, 200))
// .Init_cache_add(fxt.Mkr_cache().Init("comm", "A.png", Bool_.N, 220)) // add to cache
// .Init_fsys_add("mem/xowa/file/comm/thumb/7/0/A.png/220px.png") // copy file to fsys
// .Exec_process_lnki()
// .Test_fsdb_download(0) // skip download
// ;
// }
// @Test public void Cache_absent() {
// fxt .Init_orig_add(fxt.Mkr_orig().Init_comm("A.png", 440, 400))
// .Init_fsdb_add(fxt.Mkr_fsdb().Init_comm_thum("A.png", 220, 200))
// .Init_xfer_add(fxt.Mkr_xfer().Init_thumb(0, "A.png", 220, 200))
// .Init_cache_add(fxt.Mkr_cache().Init("commons", "A.png", Bool_.N, 220)) // add to cache
// .Exec_process_lnki()
// .Test_fsdb_download(1) // do download
// ;
// }
}
// class Xofv_file_mgr_fxt {
// private Xofv_file_mgr file_mgr;
// public Xof_xfer_mkr Mkr_xfer() {return mkr_xfer;} private final Xof_xfer_mkr mkr_xfer = new Xof_xfer_mkr();
// public Xof_orig_itm_mkr Mkr_orig() {return mkr_orig;} private final Xof_orig_itm_mkr mkr_orig = new Xof_orig_itm_mkr();
// public Xof_fsdb_mkr Mkr_fsdb() {return mkr_fsdb;} private final Xof_fsdb_mkr mkr_fsdb = new Xof_fsdb_mkr();
// public Xou_cache_itm_mkr Mkr_cache() {return mkr_cache;} private final Xou_cache_itm_mkr mkr_cache = new Xou_cache_itm_mkr();
// public void Clear() {
// file_mgr = new Xofv_file_mgr(Bry_.Empty);
// Clear_repos();
// }
// private void Clear_repos() {
// Xofv_repo_mgr repo_mgr = file_mgr.Repo_mgr();
// Io_url root_dir = Io_url_.mem_dir_("mem/xowa/file/");
// Xofv_repo_itm repo_comm = Xofv_repo_itm.new_trg_fsys(Xofv_repo_itm.Tid_val_comm, Bry_.new_a7("comm"), root_dir.GenSubDir("comm"));
// Xofv_repo_itm repo_wiki = Xofv_repo_itm.new_trg_fsys(Xofv_repo_itm.Tid_val_wiki, Bry_.new_a7("wiki"), root_dir.GenSubDir("wiki"));
// repo_mgr.Add(repo_comm).Add(repo_wiki);
// mkr_orig.Setup_repos(repo_comm, repo_wiki);
// mkr_fsdb.Setup_repos(Bry_.new_a7("comm"), Bry_.new_a7("wiki"));
// }
// public Xofv_file_mgr_fxt Init_xfer_add(Xof_xfer_mkr mkr) {file_mgr.Reg(mkr.Make()); return this;}
// public Xofv_file_mgr_fxt Init_cache_add(Xou_cache_itm_mkr mkr) {mkr.Make(file_mgr.Cache_mgr()); return this;}
// public Xofv_file_mgr_fxt Init_fsys_add(String s) {Io_mgr.Instance.SaveFilStr(s, ""); return this;}
// public Xofv_file_mgr_fxt Exec_process_lnki() {file_mgr.Process_lnki(); return this;}
// public Xofv_file_mgr_fxt Test_fsys_get(String path) {
// Tfds.Eq_true(Io_mgr.Instance.ExistsFil(Io_url_.mem_fil_(path)), "fsys: " + path);
// return this;
// }
// }
class Xof_orig_itm_mkr {
private byte[] ttl_bry; private int ext, orig_w, orig_h; private Xofv_repo_itm repo;
private byte[] redirect_bry;
private Xofv_repo_itm repo_comm, repo_wiki;
public Xof_orig_itm_mkr() {this.Reset();}
private void Reset() {
redirect_bry = Bry_.Empty;
}
public void Setup_repos(Xofv_repo_itm repo_comm, Xofv_repo_itm repo_wiki) {this.repo_comm = repo_comm; this.repo_wiki = repo_wiki;}
public Xof_orig_itm_mkr Init_comm_redirect(String src, String trg, int orig_w, int orig_h) {return Init(Bool_.Y, src, trg, orig_w, orig_h);}
public Xof_orig_itm_mkr Init_comm(String ttl_str, int orig_w, int orig_h) {return Init(Bool_.Y, ttl_str, null, orig_w, orig_h);}
public Xof_orig_itm_mkr Init_wiki(String ttl_str, int orig_w, int orig_h) {return Init(Bool_.N, ttl_str, null, orig_w, orig_h);}
private Xof_orig_itm_mkr Init(boolean repo_is_comm, String ttl_str, String redirect_str, int orig_w, int orig_h) {
repo = repo_is_comm ? repo_comm : repo_wiki;
this.ttl_bry = Bry_.new_u8(ttl_str); this.orig_w = orig_w; this.orig_h = orig_h;
this.redirect_bry = redirect_str == null ? Bry_.Empty : Bry_.new_u8(redirect_str);
this.ext = Xof_ext_.new_by_ttl_(ttl_bry).Id();
return this;
}
public void Make(Xof_orig_wkr wkr) {
wkr.Add_orig(repo.Tid(), ttl_bry, ext, orig_w, orig_h, redirect_bry);
this.Reset();
}
}
class Xof_fsdb_mkr {
private byte[] repo_comm, repo_wiki, repo;
private byte[] ttl_bry; private byte lnki_type; private int file_w, file_h;
private double upright, time; private int page;
public Xof_fsdb_mkr() {this.Reset();}
public void Setup_repos(byte[] repo_comm, byte[] repo_wiki) {this.repo_comm = repo_comm; this.repo_wiki = repo_wiki;}
private void Reset() {
upright = Xop_lnki_tkn.Upright_null;
time = Xof_lnki_time.Null;
page = Xof_lnki_page.Null;
}
public Xof_fsdb_mkr Init_comm_thum(String ttl_str, int file_w, int file_h) {return Init(Bool_.Y, Bool_.N, ttl_str, file_w, file_h);}
public Xof_fsdb_mkr Init_comm_orig(String ttl_str, int file_w, int file_h) {return Init(Bool_.Y, Bool_.Y, ttl_str, file_w, file_h);}
public Xof_fsdb_mkr Init(boolean repo_is_commons, boolean file_is_orig, String ttl_str, int file_w, int file_h) {
this.lnki_type = file_is_orig ? Xop_lnki_type.Id_none : Xop_lnki_type.Id_thumb;
this.repo = repo_is_commons ? repo_comm : repo_wiki;
this.ttl_bry = Bry_.new_u8(ttl_str);
this.file_w = file_w; this.file_h = file_h;
return this;
}
public Xof_fsdb_itm Make() {
Xof_fsdb_itm rv = new Xof_fsdb_itm();
rv.Init_at_lnki(Xof_exec_tid.Tid_wiki_page, Bry_.new_a7("en.w"), ttl_bry, lnki_type, upright, file_w, file_h, time, page, Xof_patch_upright_tid_.Tid_all);
rv.Orig_repo_name_(repo);
this.Reset();
return rv;
}
}
class Xou_cache_itm_mkr {
// private byte[] dir; private byte[] ttl; private boolean is_orig; private int w, h; private double time; private int page; private long size;
public Xou_cache_itm_mkr() {this.Reset();}
private void Reset() {
// this.time = Xof_lnki_time.Null;
// this.page = Xof_lnki_page.Null;
// this.h = 200;
// this.size = 1;
}
public Xou_cache_itm_mkr Init(String dir_str, String ttl_str, boolean is_orig, int w) {
// this.dir = Bry_.new_u8(dir_str);
// this.ttl = Bry_.new_u8(ttl_str);
// this.is_orig = is_orig;
// this.w = w;
return this;
}
public void Make(Xof_cache_mgr cache_mgr) {
// cache_mgr.Fil__make(dir, ttl, is_orig, w, h, time, page, size);
this.Reset();
}
}

View File

@@ -0,0 +1,35 @@
/*
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; import gplx.*; import gplx.xowa.*;
public class Xofv_repo_itm {
Xofv_repo_itm(byte tid, byte[] key, byte dir_spr, byte[] dir_root, byte[] dir_sub_orig, byte[] dir_sub_thumb) {
this.tid = tid; this.key = key; this.dir_spr = dir_spr; this.dir_root = dir_root; this.dir_sub_orig = dir_sub_orig; this.dir_sub_thumb = dir_sub_thumb;
}
public byte Tid() {return tid;} private final byte tid;
public byte[] Key() {return key;} private final byte[] key;
public byte Dir_spr() {return dir_spr;} private final byte dir_spr;
public byte[] Dir_root() {return dir_root;} private final byte[] dir_root;
public byte[] Dir_sub_orig() {return dir_sub_orig;} private final byte[] dir_sub_orig;
public byte[] Dir_sub_thumb() {return dir_sub_thumb;} private final byte[] dir_sub_thumb;
public static Xofv_repo_itm new_trg_fsys(byte tid, byte[] key, Io_url root) {
return new Xofv_repo_itm(tid, key, root.Info().DirSpr_byte(), Bry_.new_u8(root.Raw()), Dir_sub_orig_dflt, Dir_sub_thumb_dflt);
}
public static final byte Tid_val_comm = 0, Tid_val_wiki = 1;
private static final byte[] Dir_sub_orig_dflt = Bry_.new_a7("orig"), Dir_sub_thumb_dflt = Bry_.new_a7("thumb");
public static final int Id_temp = 0;
}

View File

@@ -0,0 +1,34 @@
/*
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; import gplx.*; import gplx.xowa.*;
import gplx.core.primitives.*;
public class Xofv_repo_mgr {
private final Hash_adp_bry key_regy = Hash_adp_bry.cs();
private final Hash_adp tid_regy = Hash_adp_.New(); private final Byte_obj_ref tid_key = Byte_obj_ref.zero_();
public Xofv_repo_mgr Add(Xofv_repo_itm itm) {
key_regy.Add(itm.Key(), itm);
tid_regy.Add(Byte_obj_ref.new_(itm.Tid()), itm);
return this;
}
public Xofv_repo_itm Get_by_key(byte[] key) {
return (Xofv_repo_itm)key_regy.Get_by(key);
}
public Xofv_repo_itm Get_by_tid(byte tid) {
return (Xofv_repo_itm)tid_regy.Get_by(tid_key.Val_(tid));
}
}

View File

@@ -0,0 +1,31 @@
/*
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; import gplx.*; import gplx.xowa.*;
import gplx.core.threads.*; import gplx.xowa.guis.cbks.js.*;
public class Xog_redlink_thread implements Gfo_thread_wkr {
private final int[] redlink_ary; private final Xog_js_wkr js_wkr;
public Xog_redlink_thread(int[] redlink_ary, Xog_js_wkr js_wkr) {this.redlink_ary = redlink_ary; this.js_wkr = js_wkr;}
public String Thread__name() {return "xowa.gui.html.redlinks.set";}
public boolean Thread__resume() {return true;}
public void Thread__exec() {
int len = redlink_ary.length;
for (int i = 0; i < len; ++i) {
js_wkr.Html_redlink(gplx.xowa.wikis.pages.lnkis.Xopg_lnki_list.Lnki_id_prefix + Int_.To_str(redlink_ary[i]));
}
}
}

View File

@@ -0,0 +1,160 @@
/*
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; import gplx.*; import gplx.xowa.*;
import gplx.dbs.*; import gplx.dbs.cfgs.*;
import gplx.xowa.files.repos.*; import gplx.xowa.files.origs.*;
import gplx.fsdb.*; import gplx.fsdb.meta.*; import gplx.xowa.files.fsdb.*;
import gplx.xowa.wikis.tdbs.metas.*;
public class Xow_file_mgr implements Gfo_invk {
private Xof_wkr_mgr wkr_mgr;
public Xow_file_mgr(Xowe_wiki wiki) {
this.wiki = wiki;
repo_mgr = new Xowe_repo_mgr(wiki);
meta_mgr = new Xof_meta_mgr(wiki);
wkr_mgr = new Xof_wkr_mgr(this);
}
public Fsdb_db_mgr Db_core() {return db_core;} private Fsdb_db_mgr db_core;
public Xof_orig_mgr Orig_mgr() {return orig_mgr;} private final Xof_orig_mgr orig_mgr = new Xof_orig_mgr();
public Xof_fsdb_mode Fsdb_mode() {
if (fsdb_mode == null) {
Version();
}
return fsdb_mode;
} private Xof_fsdb_mode fsdb_mode = null;
public Xowe_wiki Wiki() {return wiki;} private Xowe_wiki wiki;
public byte Version() {
if (version == Bool_.__byte) {
Io_url file_dir = wiki.Fsys_mgr().File_dir();
if (!Io_mgr.Instance.ExistsFil(file_dir.GenSubFil(Fsdb_db_mgr__v1.Mnt_name))) {
version = Version_1;
fsdb_mode = Xof_fsdb_mode.New__v0();
}
else {
version = Version_2;
fsdb_mode = Xof_fsdb_mode.New__v2__gui();
}
}
return version;
} private byte version = Version_null;
public boolean Version_1_y() {return this.Version() == Version_1;}
public boolean Version_2_y() {return this.Version() == Version_2;}
public void Version_1_y_() {version = Version_1;} // TEST:
public void Version_2_y_() {version = Version_2; fsdb_mode = Xof_fsdb_mode.New__v2__gui();} // TEST:
public void Fsdb_mgr_(Xof_fsdb_mgr fsdb_mgr) {
this.fsdb_mgr = fsdb_mgr;
version = Version_2;
}
public int Patch_upright() {
Fsm_mnt_mgr mnt_mgr = fsdb_mgr.Mnt_mgr();
return this.Version() == Version_1 || mnt_mgr == null
? Xof_patch_upright_tid_.Tid_all
: fsdb_mgr.Mnt_mgr().Patch_upright()
;
}
public static final byte Version_null = Byte_.Max_value_127, Version_1 = 1, Version_2 = 2;
public Xowe_repo_mgr Repo_mgr() {return repo_mgr;} private Xowe_repo_mgr repo_mgr;
public Xof_meta_mgr Dbmeta_mgr() {return meta_mgr;} private Xof_meta_mgr meta_mgr;
public Xof_cfg_download Cfg_download() {return cfg_download;} private Xof_cfg_download cfg_download = new Xof_cfg_download();
public void Init_by_wiki(Xow_wiki wiki) {
cfg_download.Init_by_wiki(wiki);
// if non-wmf, set fsdb_mgr to fs.dir; DATE:2017-02-01
if (wiki.Domain_tid() == gplx.xowa.wikis.domains.Xow_domain_tid_.Tid__other) {
String cfg_domain_str = wiki.Data__core_mgr().Db__core().Tbl__cfg().Select_str("xowa.bldr.session", "wiki_domain");
// FOLDER.RENAME: do not change to fs.dir if renamed; DATE:2017-02-06
if (String_.Eq(cfg_domain_str, wiki.Domain_str())) {
gplx.xowa.files.fsdb.fs_roots.Fs_root_core fsdir_core = gplx.xowa.files.fsdb.fs_roots.Fs_root_core.Set_fsdb_mgr(this, this.wiki);
fsdir_core.Orig_dir_(wiki.Fsys_mgr().Root_dir().GenSubDir_nest("file", "orig"));
}
}
}
public void Cfg_set(String grp, String key, String val) { // TEST: should only be called by tests
if (test_grps == null) test_grps = Hash_adp_.New();
Db_cfg_hash grp_itm = (Db_cfg_hash)test_grps.Get_by(grp);
if (grp_itm == null) {
grp_itm = new Db_cfg_hash(grp);
test_grps.Add(grp, grp_itm);
}
grp_itm.Set(key, val);
} private Hash_adp test_grps;
public Db_cfg_hash Cfg_get(String grp) {
if (test_grps != null) {
Db_cfg_hash rv = (Db_cfg_hash)test_grps.Get_by(grp);
return rv == null ? new Db_cfg_hash("") : rv;
}
if (this.Version() == Version_1) return new Db_cfg_hash("");
this.Init_file_mgr_by_load(wiki); // make sure fsdb is init'd
return fsdb_mgr.Mnt_mgr().Mnts__get_main().Cfg_mgr().Grps_get_or_load(grp);
}
public Xof_fsdb_mgr Fsdb_mgr() {return fsdb_mgr;} private Xof_fsdb_mgr fsdb_mgr = new Xof_fsdb_mgr__sql();
public void Clear_for_tests() { // NOTE: must clear else fsdb_mode will be cached for multiple runs; will generally be v1, but some tests will set to v2; DATE:2015-12-22
version = Bool_.__byte;
fsdb_mode = null;
}
public boolean Find_meta(Xof_xfer_itm xfer_itm) {
xfer_itm.Orig_repo_id_(Xof_meta_itm.Repo_unknown);
byte[] xfer_itm_ttl = xfer_itm.Lnki_ttl();
xfer_itm.Orig_ttl_and_redirect_(xfer_itm_ttl, Bry_.Empty);
Xof_meta_itm meta_itm = meta_mgr.Get_itm_or_new(xfer_itm_ttl, xfer_itm.Orig_ttl_md5());
xfer_itm.Set__meta_only(meta_itm);
if (meta_itm.State_new()) { // meta_itm is brand new
xfer_itm.Set__meta(meta_itm, repo_mgr.Repos_get_at(0).Trg(), wiki.Html_mgr().Img_thumb_width()); // default to 1st repo to prevent null_ref in xfer_mgr; questionable, but all wikis must have at least 1 repo
xfer_itm.Calc_by_meta();
return false;
}
else { // meta_itm exists
Xof_repo_itm cur_repo = null;
cur_repo = meta_itm.Repo_itm(wiki);
xfer_itm.Set__meta(meta_itm, cur_repo, wiki.Html_mgr().Img_thumb_width());
return xfer_itm.Calc_by_meta();
}
}
public boolean Exists(byte[] ttl_bry) {
if (this.Version_1_y()) {
Xof_meta_itm meta = meta_mgr.Get_itm_or_new(ttl_bry);
return meta.Orig_exists() == Bool_.Y_byte || meta.Thumbs().length != 0;
}
else
return orig_mgr.Find_by_ttl_or_null(ttl_bry) != Xof_orig_itm.Null;
}
public void Init_file_mgr_by_load(Xow_wiki wiki) {
if (db_core != null) return; // already init'd
this.db_core = Fsdb_db_mgr_.new_detect(wiki, wiki.Fsys_mgr().Root_dir(), wiki.Fsys_mgr().File_dir());
if ( db_core == null // "-file-core.xowa" not found
&& !wiki.Data__core_mgr().Props().Layout_file().Tid_is_all() // DATE:2015-08-10
)
db_core = Fsdb_db_mgr__v2_bldr.Get_or_make(wiki, false); // make it
this.version = Version_2;
this.fsdb_mode = Xof_fsdb_mode.New__v2__gui();
orig_mgr.Init_by_wiki(wiki, fsdb_mode, db_core.File__orig_tbl_ary(), Xof_url_bldr.new_v2());
fsdb_mgr.Init_by_wiki(wiki);
}
public void Rls() {
fsdb_mgr.Rls();
db_core = null;
}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_repos)) return repo_mgr;
else if (ctx.Match(k, Invk_metas)) return meta_mgr;
else if (ctx.Match(k, Invk_cfg_download)) return cfg_download; // NOTE: documented for Schnark; https://sourceforge.net/p/xowa/tickets/344/
else if (ctx.Match(k, Invk_fsdb)) return fsdb_mgr;
else if (ctx.Match(k, Invk_wkrs)) return wkr_mgr;
else return Gfo_invk_.Rv_unhandled;
} private static final String Invk_repos = "repos", Invk_metas = "metas", Invk_cfg_download = "cfg_download", Invk_fsdb = "fsdb", Invk_wkrs = "wkrs";
}

View File

@@ -0,0 +1,65 @@
/*
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.bins; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.core.primitives.*;
interface Bin_fetcher {
boolean Save_as_url(Io_url trg);
boolean Save_as_bry(Bry_obj_ref bry);
}
class Bin_fetcher_fsys implements Bin_fetcher {
public void Init_src_url(Io_url src) {this.src = src;} private Io_url src;
public boolean Save_as_url(Io_url trg) {
try {Io_mgr.Instance.CopyFil(src, trg, true); return true;}
catch (Exception exc) {Err_.Noop(exc); return false;}
}
public boolean Save_as_bry(Bry_obj_ref bry_ref) {
try {
byte[] bry = Io_mgr.Instance.LoadFilBry(src);
bry_ref.Val_(bry);
return true;
}
catch (Exception exc) {Err_.Noop(exc); return false;}
}
}
class Bin_fetcher_http implements Bin_fetcher {
private gplx.core.ios.IoEngine_xrg_downloadFil download = gplx.core.ios.IoEngine_xrg_downloadFil.new_("", Io_url_.Empty);
public void Init_src_str(String src) {this.src = src;} private String src;
public boolean Save_as_url(Io_url trg) {
return download.Src_(src).Trg_(trg).Exec();
}
public boolean Save_as_bry(Bry_obj_ref bry_ref) {
try {
byte[] rv = download.Exec_as_bry(src);
bry_ref.Val_(rv);
return true;
}
catch (Exception exc) {Err_.Noop(exc); return false;}
}
}
class Bin_fetcher_fsdb {
public void Init_id(int id) {}
public boolean Save_as_url(Io_url trg) {
// IoStream s = fsdb.Get_stream(id);
// s.Save(trg);
return true;
}
public byte[] Save_to_mem() {
// return db.Get_bry(id);
return null;
}
}

View File

@@ -0,0 +1,22 @@
/*
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.bins; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.core.ios.*; import gplx.core.ios.streams.*;
public interface Io_download_mgr {
Io_stream_rdr Download_as_rdr(String src);
}

View File

@@ -0,0 +1,31 @@
/*
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.bins; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.core.ios.*; import gplx.core.ios.streams.*;
public class Io_download_mgr_ {
public static Io_download_mgr new_system() {return new Io_download_mgr__system();}
public static Io_download_mgr__memory new_memory() {return new Io_download_mgr__memory();}
}
class Io_download_mgr__system implements Io_download_mgr {
private final IoEngine_xrg_downloadFil download_wkr = IoEngine_xrg_downloadFil.new_("", Io_url_.Empty);
public void Upload_data(String url, byte[] data) {throw Err_.new_unimplemented();}
public Io_stream_rdr Download_as_rdr(String url) {
download_wkr.Init(url, Io_url_.Empty);
return download_wkr.Exec_as_rdr();
}
}

View File

@@ -0,0 +1,28 @@
/*
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.bins; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.core.ios.*; import gplx.core.ios.streams.*;
public class Io_download_mgr__memory implements Io_download_mgr {
private final Ordered_hash hash = Ordered_hash_.New();
public void Clear() {hash.Clear();}
public void Upload_data(String url, byte[] data) {hash.Add(url, data);}
public Io_stream_rdr Download_as_rdr(String url) {
byte[] data = (byte[])hash.Get_by(url); if (data == null) return Io_stream_rdr_.Noop;
return Io_stream_rdr_.New__mem(data);
}
}

View File

@@ -0,0 +1,195 @@
/*
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.bins; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.core.primitives.*; import gplx.core.ios.*; import gplx.core.ios.streams.*;
import gplx.fsdb.meta.*;
import gplx.xowa.files.repos.*; import gplx.xowa.files.fsdb.*; import gplx.xowa.files.cnvs.*; import gplx.xowa.files.caches.*;
import gplx.xowa.bldrs.wms.*;
public class Xof_bin_mgr {
private final Fsm_mnt_mgr mnt_mgr;
private final Gfo_usr_dlg usr_dlg; private final Xow_repo_mgr repo_mgr; private final Xof_url_bldr url_bldr = Xof_url_bldr.new_v2();
private Xof_bin_wkr[] wkrs = Xof_bin_wkr_.Ary_empty; private int wkrs_len;
private final String_obj_ref resize_warning = String_obj_ref.null_(); private final Xof_img_size tmp_size = new Xof_img_size();
private final Io_download_fmt download_fmt;
private final Io_stream_rdr_wrapper rdr_wrapper = new Io_stream_rdr_wrapper();
public Xof_bin_mgr(Fsm_mnt_mgr mnt_mgr, Xow_repo_mgr repo_mgr, Xof_img_wkr_resize_img resize_wkr, Io_download_fmt download_fmt) {
this.mnt_mgr = mnt_mgr; this.repo_mgr = repo_mgr; this.download_fmt = download_fmt;
this.usr_dlg = Gfo_usr_dlg_.Instance;
this.Resizer_(resize_wkr);
}
public void Resizer_(Xof_img_wkr_resize_img v) {resizer = v;} private Xof_img_wkr_resize_img resizer;
public void Wkrs__del(String key) {
List_adp list = List_adp_.New();
for (Xof_bin_wkr wkr : wkrs) {
if (String_.Eq(key, wkr.Key())) continue;
list.Add(wkr);
}
this.wkrs = (Xof_bin_wkr[])list.To_ary(Xof_bin_wkr.class);
this.wkrs_len = wkrs.length;
}
public void Wkrs__add(Xof_bin_wkr v) {
this.wkrs = (Xof_bin_wkr[])Array_.Resize_add_one(wkrs, wkrs_len, v);
++this.wkrs_len;
}
public Xof_bin_wkr Wkrs__get_or_null(String key) {
byte tid = Xof_bin_wkr_.X_key_to_tid(key);
for (int i = 0; i < wkrs_len; ++i) {
Xof_bin_wkr wkr = wkrs[i];
if (wkr.Tid() == tid) return wkr;
}
return null;
}
public void Rls() {
mnt_mgr.Rls();
}
public boolean Find_to_url_as_bool(int exec_tid, Xof_fsdb_itm fsdb) {return Find_as(Bool_.Y, rdr_wrapper, exec_tid, fsdb);}
// public boolean Find_to_url_as_bool3(int exec_tid, Xof_fsdb_itm fsdb) {return Find_to_url(exec_tid, fsdb) != Io_url_.Empty;}
// private Io_url Find_to_url(int exec_tid, Xof_fsdb_itm fsdb) {
// Io_stream_rdr rdr = Find_as_rdr(exec_tid, fsdb);
// if (rdr == Io_stream_rdr_.Noop) return Io_url_.Empty;
// Io_url trg = fsdb.Html_view_url();
// fsdb.File_size_(rdr.Len());
// if (fsdb.File_resized()) return trg; // rdr is opened directly from trg; return its url; occurs when url goes through imageMagick / inkscape, or when thumb is already on disk;
// Io_stream_wtr_.Save_rdr(trg, rdr, download_fmt); // rdr is stream; either from http_wmf or fsdb; save to trg and return;
// return trg;
// }
public Io_stream_rdr Find_as_rdr(int exec_tid, Xof_fsdb_itm fsdb) {
rdr_wrapper.Rdr_(Io_stream_rdr_.Noop);
Find_as(Bool_.N, rdr_wrapper, exec_tid, fsdb);
return rdr_wrapper.Rdr();
}
public Io_stream_rdr Find_as_rdr3(int exec_tid, Xof_fsdb_itm fsdb) {
Io_stream_rdr rv = Io_stream_rdr_.Noop;
Xof_repo_itm repo = repo_mgr.Repos_get_by_wiki(fsdb.Orig_repo_name()).Trg();
boolean file_is_orig = fsdb.File_is_orig();
if (file_is_orig || exec_tid == Xof_exec_tid.Tid_viewer_app) { // orig or viewer_app; note that viewer_app always return orig
Io_url trg = url_bldr.To_url_trg(repo, fsdb, Bool_.Y);
fsdb.Html_view_url_(trg);
for (int i = 0; i < wkrs_len; i++) {
Xof_bin_wkr wkr = wkrs[i];
rv = wkr.Get_as_rdr(fsdb, Bool_.N, fsdb.Html_w());
if (rv == Io_stream_rdr_.Noop) continue; // orig not found; continue;
fsdb.File_exists_y_();
return rv;
}
}
else { // thumb
Io_url trg = url_bldr.To_url_trg(repo, fsdb, Bool_.N);
fsdb.Html_view_url_(trg);
for (int i = 0; i < wkrs_len; i++) {
Xof_bin_wkr wkr = wkrs[i];
rv = wkr.Get_as_rdr(fsdb, Bool_.Y, fsdb.Html_w()); // get thumb's bin
if (rv != Io_stream_rdr_.Noop) { // thumb's bin exists;
fsdb.File_exists_y_();
return rv;
}
if (fsdb.Orig_ext().Id_is_video()) continue; // item is video; don't download orig as imageMagick can't thumbnail it; DATE:2015-06-16
rv = wkr.Get_as_rdr(fsdb, Bool_.N, fsdb.Orig_w()); // thumb missing; get orig;
if (rv == Io_stream_rdr_.Noop) {
usr_dlg.Log_direct(String_.Format("bin_mgr:thumb not found; wkr={0} ttl={1} w={2}", wkr.Key(), fsdb.Orig_ttl(), fsdb.Lnki_w()));
continue; // nothing found; continue;
}
if (!wkr.Resize_allowed()) continue;
Io_url orig = url_bldr.To_url_trg(repo, fsdb, Bool_.Y); // get orig url
Io_stream_wtr_.Save_rdr(orig, rv, download_fmt);
boolean resized = Resize(exec_tid, fsdb, file_is_orig, orig, trg);
if (!resized) continue;
fsdb.File_exists_y_();
rv = Io_stream_rdr_.New__raw(trg); // return stream of resized url; (result of imageMagick / inkscape)
rv.Open();
return rv;
}
}
return Io_stream_rdr_.Noop;
}
private boolean Find_as(boolean save_to_fsys, Io_stream_rdr_wrapper rdr_wrapper, int exec_tid, Xof_fsdb_itm fsdb) {
Xof_repo_itm repo = repo_mgr.Repos_get_by_wiki(fsdb.Orig_repo_name()).Trg();
boolean file_is_orig = fsdb.File_is_orig();
if (file_is_orig || exec_tid == Xof_exec_tid.Tid_viewer_app) { // orig or viewer_app; note that viewer_app always return orig
Io_url trg = url_bldr.To_url_trg(repo, fsdb, Bool_.Y);
fsdb.Html_view_url_(trg);
for (int i = 0; i < wkrs_len; i++) {
Xof_bin_wkr wkr = wkrs[i];
boolean found = Get_bin(Bool_.N, fsdb.File_w(), trg, save_to_fsys, rdr_wrapper, fsdb, wkr); // NOTE: must use File_w, not Html_w; else missing images in packed gallery in hdump; PAGE:en.w:France; DATE:2016-08-22
if (found) // orig found; return it;
return Set_found(save_to_fsys, fsdb, trg, rdr_wrapper);
}
}
else { // thumb
Io_url trg = url_bldr.To_url_trg(repo, fsdb, Bool_.N);
fsdb.Html_view_url_(trg);
for (int i = 0; i < wkrs_len; i++) {
Xof_bin_wkr wkr = wkrs[i];
boolean found = Get_bin(Bool_.Y, fsdb.File_w(), trg, save_to_fsys, rdr_wrapper, fsdb, wkr); // NOTE: must use File_w, not Html_w; else missing images in packed gallery in hdump; PAGE:en.w:France; DATE:2016-08-22
if (found) // thumb found; return it;
return Set_found(save_to_fsys, fsdb, trg, rdr_wrapper);
if (fsdb.Orig_ext().Id_is_video()) continue; // item is video; don't download orig as imageMagick can't thumbnail it; DATE:2015-06-16
if (!wkr.Resize_allowed()) continue; // resize code below; exit early if wkr doesn't allow resize
Io_url orig = url_bldr.To_url_trg(repo, fsdb, Bool_.Y); // get orig url
found = Get_bin(Bool_.N, fsdb.Orig_w(), orig, Bool_.Y, rdr_wrapper, fsdb, wkr); // get orig; note: save_to_fsys set to true b/c imageMagick will need actual file to convert
if (!found) {
usr_dlg.Log_direct(String_.Format("bin_mgr:thumb not found; wkr={0} ttl={1} w={2}", wkr.Key(), fsdb.Orig_ttl(), fsdb.Lnki_w()));
continue; // orig not found; skip rest since resize can't happen;
}
boolean resized = Resize(exec_tid, fsdb, file_is_orig, orig, trg);
if (!resized) continue;
if (save_to_fsys) { // noop; already saved to trg
}
else {
Io_stream_rdr rdr = Io_stream_rdr_.New__raw(trg); // return stream of resized url; (result of imageMagick / inkscape)
rdr.Open();
rdr_wrapper.Rdr_(rdr);
}
return Set_found(save_to_fsys, fsdb, trg, rdr_wrapper);
}
}
return false;
}
private boolean Get_bin(boolean is_thumb, int w, Io_url trg_url, boolean save_to_fsys, Io_stream_rdr_wrapper rdr_wrapper, Xof_fsdb_itm fsdb, Xof_bin_wkr wkr) {
boolean found = false;
if (save_to_fsys)
found = wkr.Get_to_fsys(fsdb, is_thumb, w, trg_url);
else {
Io_stream_rdr rdr = wkr.Get_as_rdr(fsdb, is_thumb, w);
if (rdr != Io_stream_rdr_.Noop) {
found = true;
rdr_wrapper.Rdr_(rdr);
}
}
return found;
}
private boolean Set_found(boolean save_to_fsys, Xof_fsdb_itm fsdb, Io_url fsys_url, Io_stream_rdr_wrapper rdr_wrapper) {
long fsdb_len = -1;
if (save_to_fsys)
fsdb_len = Io_mgr.Instance.QueryFil(fsys_url).Size();
else
fsdb_len = rdr_wrapper.Rdr().Len();
fsdb.File_size_(fsdb_len);
fsdb.File_exists_y_();
return true;
}
private boolean Resize(int exec_tid, Xof_fsdb_itm itm, boolean file_is_orig, Io_url src, Io_url trg) {
tmp_size.Html_size_calc(exec_tid, itm.Lnki_w(), itm.Lnki_h(), itm.Lnki_type(), mnt_mgr.Patch_upright(), itm.Lnki_upright(), itm.Orig_ext().Id(), itm.Orig_w(), itm.Orig_h(), Xof_img_size.Thumb_width_img);
boolean rv = resizer.Resize_exec(src, trg, tmp_size.Html_w(), tmp_size.Html_h(), itm.Orig_ext().Id(), resize_warning);
itm.File_resized_y_();
return rv;
}
}
class Io_stream_rdr_wrapper {
public Io_stream_rdr Rdr() {return rdr;} public void Rdr_(Io_stream_rdr v) {rdr = v;} private Io_stream_rdr rdr;
}

View File

@@ -0,0 +1,89 @@
/*
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.bins; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.core.ios.*; import gplx.core.ios.streams.*;
import gplx.fsdb.meta.*; import gplx.xowa.files.fsdb.*;
public class Xof_bin_skip_mgr {
private Xof_bin_skip_wkr[] wkrs = new Xof_bin_skip_wkr[0]; private int wkrs_len;
public Xof_bin_skip_mgr(Fsm_cfg_mgr cfg_mgr, String[] wkr_keys) {
List_adp list = List_adp_.New();
for (int i = 0; i < wkrs_len; ++i) {
Xof_bin_skip_wkr wkr = New_wkr(cfg_mgr, wkr_keys[i]);
if (wkr != null) list.Add(wkr);
}
this.wkrs = (Xof_bin_skip_wkr[])list.To_ary_and_clear(Xof_bin_skip_wkr.class);
this.wkrs_len = wkrs.length;
}
public boolean Skip(Xof_fsdb_itm fsdb, Io_stream_rdr src_rdr) {
for (int i = 0; i < wkrs_len; ++i) {
if (wkrs[i].Skip_exec(fsdb, src_rdr)) return true;
}
return false;
}
private Xof_bin_skip_wkr New_wkr(Fsm_cfg_mgr cfg_mgr, String key) {
Xof_bin_skip_wkr rv = null;
if (String_.Eq(key, Xof_bin_skip_wkr_.Key__page_gt_1)) rv = Xof_bin_skip_wkr__page_gt_1.Instance;
else if (String_.Eq(key, Xof_bin_skip_wkr_.Key__small_size)) rv = Xof_bin_skip_wkr__small_size.Instance;
else throw Err_.new_unhandled(key);
if (!rv.Skip_init(cfg_mgr)) return null;
return rv;
}
public void Skip_term(Fsm_cfg_mgr cfg_mgr) {
for (int i = 0; i < wkrs_len; ++i)
wkrs[i].Skip_term(cfg_mgr);
}
}
interface Xof_bin_skip_wkr {
String Key();
boolean Skip_init(Fsm_cfg_mgr cfg_mgr);
boolean Skip_exec(Xof_fsdb_itm fsdb, Io_stream_rdr src_rdr);
void Skip_term(Fsm_cfg_mgr cfg_mgr);
}
class Xof_bin_skip_wkr_ {
public static final String Key__page_gt_1 = "page_gt_1", Key__small_size = "small_size";
}
class Xof_bin_skip_wkr__page_gt_1 implements Xof_bin_skip_wkr { // prior to v2.4.3; lnkis with page > 1 was mistakenly bringing down page 1; EX: [[A.pdf|page=5]] -> page1; DATE:2015-04-21
public String Key() {return Xof_bin_skip_wkr_.Key__page_gt_1;}
public boolean Skip_init(Fsm_cfg_mgr cfg_mgr) {return !cfg_mgr.Patch__page_gt_1();}
public boolean Skip_exec(Xof_fsdb_itm fsdb, Io_stream_rdr src_rdr) {
boolean rv = fsdb.Lnki_page() > 1;
if (rv)
Xoa_app_.Usr_dlg().Note_many("", "", "src_bin_mgr:skip page gt 1: file=~{0} width=~{1} page=~{2}", fsdb.Orig_ttl(), fsdb.Html_w(), fsdb.Lnki_page());
return rv;
}
public void Skip_term(Fsm_cfg_mgr cfg_mgr) {
cfg_mgr.Patch__save(Fsm_cfg_mgr.Key_patch__page_gt_1);
}
public static final Xof_bin_skip_wkr__page_gt_1 Instance = new Xof_bin_skip_wkr__page_gt_1(); Xof_bin_skip_wkr__page_gt_1() {}
}
class Xof_bin_skip_wkr__small_size implements Xof_bin_skip_wkr {// downloads can randomly be broken; assume that anything with a small size is broken and redownload again; DATE:2015-04-21
public String Key() {return Xof_bin_skip_wkr_.Key__small_size;}
public boolean Skip_init(Fsm_cfg_mgr cfg_mgr) {return true;}
public boolean Skip_exec(Xof_fsdb_itm fsdb, Io_stream_rdr src_rdr) {
boolean rv =
src_rdr.Len() < 500 // file is small (< 500 bytes)
&& fsdb.Html_w() > 50 // only apply to images larger than 50 px (arbitrarily chosen); needed to ignore 1x1 images as well as icon-sized images
&& Xof_ext_.Id_is_image_wo_svg(fsdb.Orig_ext().Id()) // only consider images; needed b/c of file_w check; note:ignore svg which can be small
;
if (rv)
Xoa_app_.Usr_dlg().Note_many("", "", "src_bin_mgr:skip small file: file=~{0} width=~{1} ext=~{2} len=~{3}", fsdb.Orig_ttl(), fsdb.Lnki_w(), fsdb.Orig_ext(), src_rdr.Len());
return rv;
}
public void Skip_term(Fsm_cfg_mgr cfg_mgr) {}
public static final Xof_bin_skip_wkr__small_size Instance = new Xof_bin_skip_wkr__small_size(); Xof_bin_skip_wkr__small_size() {}
}

View File

@@ -0,0 +1,27 @@
/*
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.bins; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.core.ios.*; import gplx.core.ios.streams.*;
import gplx.xowa.files.fsdb.*;
public interface Xof_bin_wkr {
byte Tid();
String Key();
boolean Resize_allowed(); void Resize_allowed_(boolean v);
Io_stream_rdr Get_as_rdr (Xof_fsdb_itm itm, boolean is_thumb, int w);
boolean Get_to_fsys (Xof_fsdb_itm itm, boolean is_thumb, int w, Io_url bin_url);
}

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.bins; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
public class Xof_bin_wkr_ {
public static final Xof_bin_wkr[] Ary_empty = new Xof_bin_wkr[0];
public static final byte Tid_null = Byte_.Max_value_127, Tid_noop = 1, Tid_not_found = 2
, Tid_fsdb_xowa = 3 , Tid_http_wmf = 5
, Tid_fsys_wmf = 6 , Tid_fsys_xowa = 7
;
public static final String
Key_fsdb_wiki = "xowa.fsdb.wiki" , Key_http_wmf = "xowa.http.wmf"
, Key_fsys_wmf = "xowa.fsys.wmf" , Key_fsys_xowa = "xowa.fsys.xowa"
;
public static byte X_key_to_tid(String key) {
if (String_.Eq(key, Key_fsdb_wiki)) return Tid_fsdb_xowa;
else if (String_.Eq(key, Key_http_wmf)) return Tid_http_wmf;
else if (String_.Eq(key, Key_fsys_wmf)) return Tid_fsys_wmf;
else if (String_.Eq(key, Key_fsys_xowa)) return Tid_fsys_xowa;
else return Tid_null;
}
}

View File

@@ -0,0 +1,130 @@
/*
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.bins; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.dbs.*; import gplx.core.ios.*; import gplx.core.ios.streams.*; import gplx.core.caches.*; import gplx.xowa.files.fsdb.*;
import gplx.fsdb.*; import gplx.fsdb.data.*; import gplx.fsdb.meta.*;
public class Xof_bin_wkr__fsdb_sql implements Xof_bin_wkr {
private final Xof_bin_wkr_ids tmp_ids = new Xof_bin_wkr_ids();
private Xof_bin_skip_mgr skip_mgr;
Xof_bin_wkr__fsdb_sql(Fsm_mnt_mgr mnt_mgr) {this.mnt_mgr = mnt_mgr;}
public byte Tid() {return Xof_bin_wkr_.Tid_fsdb_xowa;}
public String Key() {return Xof_bin_wkr_.Key_fsdb_wiki;}
public Fsm_mnt_mgr Mnt_mgr() {return mnt_mgr;} private final Fsm_mnt_mgr mnt_mgr;
public boolean Resize_allowed() {return bin_wkr_resize;} public void Resize_allowed_(boolean v) {bin_wkr_resize = v;} private boolean bin_wkr_resize = false;
public Xof_bin_skip_mgr Skip_mgr() {return skip_mgr;}
public void Skip_mgr_init(Fsm_cfg_mgr cfg_mgr, String[] wkrs) {this.skip_mgr = new Xof_bin_skip_mgr(cfg_mgr, wkrs);}
public Io_stream_rdr Get_as_rdr(Xof_fsdb_itm fsdb, boolean is_thumb, int w) {
Find_ids(fsdb, is_thumb, w);
int bin_db_id = tmp_ids.Bin_db_id(); if (bin_db_id == Fsd_bin_tbl.Bin_db_id_null) return Io_stream_rdr_.Noop;
Fsm_bin_fil bin_db = mnt_mgr.Bins__at(tmp_ids.Mnt_id(), bin_db_id);
Io_stream_rdr rdr = bin_db.Select_as_rdr(tmp_ids.Itm_id());
if (skip_mgr != null && skip_mgr.Skip(fsdb, rdr)) return Io_stream_rdr_.Noop;
return rdr;
}
public boolean Get_to_fsys(Xof_fsdb_itm itm, boolean is_thumb, int w, Io_url bin_url) {return Get_to_fsys(itm.Orig_repo_name(), itm.Orig_ttl(), itm.Orig_ext(), is_thumb, w, itm.Lnki_time(), itm.Lnki_page(), bin_url);}
private boolean Get_to_fsys(byte[] orig_repo, byte[] orig_ttl, Xof_ext orig_ext, boolean lnki_is_thumb, int file_w, double lnki_time, int lnki_page, Io_url file_url) {
Find_ids(orig_repo, orig_ttl, orig_ext.Id(), lnki_time, lnki_page, lnki_is_thumb, file_w);
int bin_db_id = tmp_ids.Bin_db_id(); if (bin_db_id == Fsd_bin_tbl.Bin_db_id_null) return false;
Fsm_bin_fil bin_db = mnt_mgr.Bins__at(tmp_ids.Mnt_id(), bin_db_id);
return bin_db.Select_to_url(tmp_ids.Itm_id(), file_url);
}
public Io_stream_rdr Get_to_fsys_near(Xof_fsdb_itm rv, byte[] orig_repo, byte[] orig_ttl, Xof_ext orig_ext, double lnki_time, int lnki_page) {
Fsd_thm_itm thm_itm = Fsd_thm_itm.new_();
thm_itm.Init_by_req(Int_.Max_value, lnki_time, lnki_page);
boolean found = Select_thm_bin(Bool_.N, thm_itm, orig_repo, orig_ttl);
if (found) {
tmp_ids.Init_by_thm(found, thm_itm);
rv.Init_by_fsdb_near(Bool_.N, thm_itm.W());
}
else {
Fsd_fil_itm fil_itm = Select_fil_bin(orig_repo, orig_ttl); // find orig
if (fil_itm == Fsd_fil_itm.Null) return Io_stream_rdr_.Noop;
tmp_ids.Init_by_fil(fil_itm);
rv.Init_by_fsdb_near(Bool_.Y, rv.Orig_w());
}
Fsm_bin_fil bin_db = mnt_mgr.Bins__at(tmp_ids.Mnt_id(), tmp_ids.Bin_db_id());
return bin_db.Select_as_rdr(tmp_ids.Itm_id());
}
private void Find_ids(Xof_fsdb_itm itm, boolean is_thumb, int w) {Find_ids(itm.Orig_repo_name(), itm.Orig_ttl(), itm.Orig_ext().Id(), itm.Lnki_time(), itm.Lnki_page(), is_thumb, w);}
private void Find_ids(byte[] orig_repo, byte[] orig_ttl, int orig_ext, double lnki_time, int lnki_page, boolean is_thumb, int w) {
synchronized (tmp_ids) {
byte[] dir = orig_repo, fil = orig_ttl;
if (is_thumb) {
Fsd_thm_itm thm_itm = Fsd_thm_itm.new_();
thm_itm.Init_by_req(w, lnki_time, lnki_page);
boolean found = Select_thm_bin(Bool_.Y, thm_itm, dir, fil);
tmp_ids.Init_by_thm(found, thm_itm);
}
else {
Fsd_fil_itm fil_itm = Select_fil_bin(dir, fil);
tmp_ids.Init_by_fil(fil_itm);
}
}
}
private Fsd_fil_itm Select_fil_bin(byte[] dir, byte[] fil) {
int len = mnt_mgr.Mnts__len();
for (int i = 0; i < len; i++) {
Fsd_fil_itm rv = mnt_mgr.Mnts__get_at(i).Select_fil_or_null(dir, fil);
if ( rv != Fsd_fil_itm.Null
&& rv.Bin_db_id() != Fsd_bin_tbl.Bin_db_id_null) { // NOTE: mnt_0 can have thumb, but mnt_1 can have itm; check for itm with Db_bin_id; DATE:2013-11-16
return rv;
}
}
return Fsd_fil_itm.Null;
}
private boolean Select_thm_bin(boolean exact, Fsd_thm_itm rv, byte[] dir, byte[] fil) {
int len = mnt_mgr.Mnts__len();
for (int i = 0; i < len; i++) {
boolean exists = mnt_mgr.Mnts__get_at(i).Select_thm(exact, rv, dir, fil);
if (exists) return true;
}
return false;
}
public void Txn_bgn() {mnt_mgr.Mnts__get_insert().Txn_bgn();}
public void Txn_end() {mnt_mgr.Mnts__get_insert().Txn_end();}
public static Xof_bin_wkr__fsdb_sql new_(Fsm_mnt_mgr mnt_mgr) {return new Xof_bin_wkr__fsdb_sql(mnt_mgr);}
}
class Xof_bin_wkr_ids {
public Xof_bin_wkr_ids() {this.Clear();}
public int Mnt_id() {return mnt_id;} private int mnt_id;
public int Bin_db_id() {return bin_db_id;} private int bin_db_id;
public int Itm_id() {return itm_id;} private int itm_id;
public void Init_by_thm(boolean found, Fsd_thm_itm thm) {
if (found) {
this.mnt_id = thm.Mnt_id();
this.bin_db_id = thm.Bin_db_id();
this.itm_id = thm.Thm_id();
}
else
this.Clear();
}
public void Init_by_fil(Fsd_fil_itm fil) {
if (fil == Fsd_fil_itm.Null)
this.Clear();
else {
this.mnt_id = fil.Mnt_id();
this.bin_db_id = fil.Bin_db_id();
this.itm_id = fil.Fil_id();
}
}
private void Clear() {
this.mnt_id = -1;
this.bin_db_id = Fsd_bin_tbl.Bin_db_id_null;
this.itm_id = -1;
}
}

View File

@@ -0,0 +1,70 @@
/*
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.bins; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.core.ios.*; import gplx.core.ios.streams.*; import gplx.core.envs.*;
import gplx.xowa.files.fsdb.*; import gplx.xowa.files.repos.*; import gplx.xowa.files.imgs.*;
public abstract class Xof_bin_wkr__fsys_base implements Xof_bin_wkr, Gfo_invk {
public Xof_bin_wkr__fsys_base() {}
public abstract byte Tid();
public abstract String Key();
public boolean Resize_allowed() {return resize_allowed;} public void Resize_allowed_(boolean v) {resize_allowed = v;} private boolean resize_allowed = false;
public Io_stream_rdr Get_as_rdr(Xof_fsdb_itm itm, boolean is_thumb, int w) {
Io_url src_url = this.Get_src_url(Xof_img_mode_.By_bool(is_thumb), String_.new_u8(itm.Orig_repo_name()), itm.Orig_ttl(), itm.Orig_ttl_md5(), itm.Orig_ext(), w, itm.Lnki_time(), itm.Lnki_page());
return (src_url == Io_url_.Empty) ? gplx.core.ios.streams.Io_stream_rdr_.Noop : gplx.core.ios.streams.Io_stream_rdr_.New__raw(src_url);
}
public boolean Get_to_fsys(Xof_fsdb_itm itm, boolean is_thumb, int w, Io_url bin_url) {
return Get_to_fsys(itm.Orig_repo_name(), itm.Orig_ttl(), itm.Orig_ttl_md5(), itm.Orig_ext(), is_thumb, w, itm.Lnki_time(), itm.Lnki_page(), bin_url);
}
private boolean Get_to_fsys(byte[] orig_repo, byte[] orig_ttl, byte[] orig_md5, Xof_ext orig_ext, boolean lnki_is_thumb, int file_w, double lnki_time, int lnki_page, Io_url file_url) {
Io_url src_url = this.Get_src_url(Xof_img_mode_.By_bool(lnki_is_thumb), String_.new_u8(orig_repo), orig_ttl, orig_md5, orig_ext, file_w, lnki_time, lnki_page);
if (src_url == Io_url_.Empty) return false;
byte[] bin = Io_mgr.Instance.LoadFilBry(src_url);
return bin != Io_mgr.LoadFilBry_fail;
}
protected abstract Io_url Get_src_url(byte mode, String wiki, byte[] ttl_wo_ns, byte[] md5, Xof_ext ext, int w, double time, int page);
public abstract void Url_(Io_url v);
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_url_)) this.Url_(m.ReadIoUrl("v"));
else return Gfo_invk_.Rv_unhandled;
return this;
} private static final String Invk_url_ = "url_";
}
abstract class Xof_bin_wkr__fsys_wmf_base extends Xof_bin_wkr__fsys_base {
public Xof_url_bldr Url_bldr() {return url_bldr;} private Xof_url_bldr url_bldr = new Xof_url_bldr();
public abstract void Init_by_root();
@Override public void Url_(Io_url v) {url_bldr.Root_(Bry_.new_u8(v.Raw()));}
@Override protected Io_url Get_src_url(byte mode, String wiki, byte[] ttl_wo_ns, byte[] md5, Xof_ext ext, int w, double time, int page) {
return this.Url_bldr().Init_by_itm(mode, ttl_wo_ns, md5, ext, w, time, page).Xto_url();
}
}
class Xof_bin_wkr__fsys_wmf extends Xof_bin_wkr__fsys_wmf_base {
@Override public byte Tid() {return Xof_bin_wkr_.Tid_fsys_wmf;}
@Override public String Key() {return Xof_bin_wkr_.Key_fsys_wmf;}
@Override public void Init_by_root() {
this.Url_bldr().Init_by_repo(Xof_repo_tid_.Tid__null, Bry_.Empty, Op_sys.Cur().Tid_is_wnt(), Op_sys.Cur().Fsys_dir_spr_byte(), Bool_.Y, Bool_.Y, Md5_dir_depth__wmf);
}
private static final int Md5_dir_depth__wmf = 2;
}
class Xof_bin_wkr__fsys_xowa extends Xof_bin_wkr__fsys_wmf_base {
@Override public byte Tid() {return Xof_bin_wkr_.Tid_fsys_xowa;}
@Override public String Key() {return Xof_bin_wkr_.Key_fsys_xowa;}
@Override public void Init_by_root() {
this.Url_bldr().Init_by_repo(Xof_repo_tid_.Tid__null, Bry_.Empty, Op_sys.Cur().Tid_is_wnt(), Op_sys.Cur().Fsys_dir_spr_byte(), Bool_.N, Bool_.N, Md5_dir_depth__xowa);
}
private static final int Md5_dir_depth__xowa = 4;
}

View File

@@ -0,0 +1,86 @@
/*
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.bins; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.core.ios.*; import gplx.core.ios.streams.*; import gplx.core.threads.*;
import gplx.xowa.apps.*;
import gplx.xowa.files.fsdb.*; import gplx.xowa.files.repos.*; import gplx.xowa.files.imgs.*;
import gplx.xowa.wikis.domains.*;
public class Xof_bin_wkr__http_wmf implements Xof_bin_wkr {
private final Xow_repo_mgr repo_mgr; private final IoEngine_xrg_downloadFil download_wkr;
private final Io_download_mgr download_mgr;
private final Xof_url_bldr url_bldr = new Xof_url_bldr();
public Xof_bin_wkr__http_wmf(Xow_repo_mgr repo_mgr, Io_download_mgr download_mgr, IoEngine_xrg_downloadFil download_wkr) {
this.repo_mgr = repo_mgr; this.download_mgr = download_mgr; this.download_wkr = download_wkr;
}
public byte Tid() {return Xof_bin_wkr_.Tid_http_wmf;}
public String Key() {return Xof_bin_wkr_.Key_http_wmf;}
public boolean Resize_allowed() {return bin_wkr_resize;} public void Resize_allowed_(boolean v) {bin_wkr_resize = v;} private boolean bin_wkr_resize = true;
public int Fail_timeout() {return fail_timeout;} public Xof_bin_wkr__http_wmf Fail_timeout_(int v) {fail_timeout = v; return this;} private int fail_timeout = 0; // NOTE: always default to 0; manually set to 1000 for fsdb_make only; DATE:2014-06-21
public Io_stream_rdr Get_as_rdr(Xof_fsdb_itm fsdb, boolean is_thumb, int w) {
String src = Make_src(fsdb.Orig_repo_name(), fsdb.Orig_ttl(), fsdb.Orig_ttl_md5(), fsdb.Orig_ext(), is_thumb, w, fsdb.Lnki_time(), fsdb.Lnki_page(), Io_url_.Empty);
Io_stream_rdr rdr = download_mgr.Download_as_rdr(src);
boolean rv = rdr.Exists(); // NOTE: use Exists which detects for response_code 200, not content length > 0; DATE:2015-05-20
if (!rv) {
Handle_error();
if (!rv && fsdb.Orig_repo_id() == Xof_repo_tid_.Tid__local) { // image is not found in local; check commons; occurs with bldr which relies on inaccurate data in image dumps; PAGE:en.w:Apollo_13; DATE:2015-08-05
src = Make_src(Xow_domain_itm_.Bry__commons, fsdb.Orig_ttl(), fsdb.Orig_ttl_md5(), fsdb.Orig_ext(), is_thumb, w, fsdb.Lnki_time(), fsdb.Lnki_page(), Io_url_.Empty);
rdr = download_mgr.Download_as_rdr(src);
rv = rdr.Exists();
if (rv)
fsdb.Change_repo(Xof_repo_tid_.Tid__remote, Xow_domain_itm_.Bry__commons); // set commons.wikimedia.org; DATE:2015-08-05
else
Handle_error();
}
}
if (rv) fsdb.Fsdb_insert_y_();
return rv ? rdr : Io_stream_rdr_.Noop;
}
public boolean Get_to_fsys(Xof_fsdb_itm fsdb, boolean is_thumb, int w, Io_url bin_url) {
boolean rv = Get_to_fsys(fsdb.Orig_repo_name(), fsdb.Orig_ttl(), fsdb.Orig_ttl_md5(), fsdb.Orig_ext(), is_thumb, w, fsdb.Lnki_time(), fsdb.Lnki_page(), bin_url);
if (rv) fsdb.Fsdb_insert_y_();
return rv;
}
private boolean Get_to_fsys(byte[] orig_repo, byte[] orig_ttl, byte[] orig_md5, Xof_ext orig_ext, boolean lnki_is_thumb, int file_w, double lnki_time, int lnki_page, Io_url file_url) {
Init_download(orig_repo, orig_ttl, orig_md5, orig_ext, lnki_is_thumb, file_w, lnki_time, lnki_page, file_url);
boolean rv = download_wkr.Exec();
if (!rv) Handle_error();
return rv;
}
private void Handle_error() {
if (fail_timeout > 0)
Thread_adp_.Sleep(fail_timeout); // as per WMF policy, pause 1 second for every cache miss; http://lists.wikimedia.org/pipermail/wikitech-l/2013-September/071948.html
}
private void Init_download(byte[] orig_repo, byte[] orig_ttl, byte[] orig_md5, Xof_ext orig_ext, boolean lnki_is_thumb, int file_w, double lnki_time, int lnki_page, Io_url file_url) {
byte mode = lnki_is_thumb ? Xof_img_mode_.Tid__thumb : Xof_img_mode_.Tid__orig;
Xof_repo_pair repo_itm = repo_mgr.Repos_get_by_wiki(orig_repo);
String src = url_bldr.Init_for_src_file(repo_itm.Src(), mode, orig_ttl, orig_md5, orig_ext, file_w, lnki_time, lnki_page).Xto_str();
download_wkr.Init(src, file_url);
}
private String Make_src(byte[] orig_repo, byte[] orig_ttl, byte[] orig_md5, Xof_ext orig_ext, boolean lnki_is_thumb, int file_w, double lnki_time, int lnki_page, Io_url file_url) {
byte mode = lnki_is_thumb ? Xof_img_mode_.Tid__thumb : Xof_img_mode_.Tid__orig;
Xof_repo_pair repo_itm = repo_mgr.Repos_get_by_wiki(orig_repo);
return url_bldr.Init_for_src_file(repo_itm.Src(), mode, orig_ttl, orig_md5, orig_ext, file_w, lnki_time, lnki_page).Xto_str();
}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_fail_timeout_)) fail_timeout = m.ReadInt("v");
else return Gfo_invk_.Rv_unhandled;
return this;
} private static final String Invk_fail_timeout_ = "fail_timeout_";
public static Xof_bin_wkr__http_wmf new_(Xow_wiki wiki) {return new_(wiki, Io_download_mgr_.new_system());}
public static Xof_bin_wkr__http_wmf new_(Xow_wiki wiki, Io_download_mgr download_mgr) {return new Xof_bin_wkr__http_wmf(wiki.File__repo_mgr(), download_mgr, wiki.App().Wmf_mgr().Download_wkr().Download_xrg());}
}

View File

@@ -0,0 +1,67 @@
/*
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.bins; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import org.junit.*; import gplx.core.ios.*; import gplx.core.ios.streams.*; import gplx.xowa.files.repos.*;
public class Xof_bin_wkr__http_wmf__tst {
private final Xof_bin_wkr__http_wmf__fxt fxt = new Xof_bin_wkr__http_wmf__fxt();
@Before public void init() {fxt.Clear();}
@Test public void Basic() {
fxt.Init__Http("mem/http/commons.wikimedia.org/thumb/7/70/A.png/220px-A.png", "test_data");
fxt.Exec__Get_as_rdr(fxt.Fsdb_itm_mkr().Lnki__en_w("A.png").Orig__commons__lnki(), Bool_.Y, 220);
fxt.Test__Get_as_rdr__rdr("test_data");
}
@Test public void Enwiki_fails__fallback_to_commons() {
fxt.Init__Http("mem/http/commons.wikimedia.org/thumb/7/70/A.png/220px-A.png", "test_data"); // put file in commons
Xof_fsdb_itm fsdb_itm = fxt.Fsdb_itm_mkr().Lnki__en_w("A.png").Orig__enwiki__lnki().Make();
fxt.Exec__Get_as_rdr(fsdb_itm, Bool_.Y, 220); // look in enwiki
fxt.Test__Get_as_rdr__rdr("test_data"); // test that enwiki tries commons again
Tfds.Eq_str("commons.wikimedia.org", fsdb_itm.Orig_repo_name(), "repo_name"); // test that it's now commons
Tfds.Eq_byte(Xof_repo_tid_.Tid__remote, fsdb_itm.Orig_repo_id(), "repo_tid"); // test that it's now commons
}
@Test public void Long_filename_becomes_thumbnail() {
String filename = String_.Repeat("A", 200) + ".png";
fxt.Init__Http("mem/http/commons.wikimedia.org/thumb/1/14/" + filename + "/220px-thumbnail.png", "test_data"); // add file as "thumbnail.png"
Xof_fsdb_itm fsdb_itm = fxt.Fsdb_itm_mkr().Lnki__en_w(filename).Orig__enwiki__lnki().Make();
fxt.Exec__Get_as_rdr(fsdb_itm, Bool_.Y, 220); // look in enwiki
fxt.Test__Get_as_rdr__rdr("test_data"); // test that file is there
}
}
class Xof_bin_wkr__http_wmf__fxt {
private final Xof_bin_wkr__http_wmf wkr;
private final Io_download_mgr__memory download_mgr;
private Io_stream_rdr get_as_rdr__rdr;
public Xof_fsdb_itm_fxt Fsdb_itm_mkr() {return fsdb_itm_mkr;} private final Xof_fsdb_itm_fxt fsdb_itm_mkr = new Xof_fsdb_itm_fxt();
public Xof_bin_wkr__http_wmf__fxt() {
Xoae_app app = Xoa_app_fxt.Make__app__edit();
Xowe_wiki wiki = Xoa_app_fxt.Make__wiki__edit(app);
Xoa_app_fxt.repo2_(app, wiki);
this.download_mgr = Io_download_mgr_.new_memory();
this.wkr = Xof_bin_wkr__http_wmf.new_(wiki, download_mgr);
}
public void Clear() {
download_mgr.Clear();
}
public void Init__Http(String url, String data) {download_mgr.Upload_data(url, Bry_.new_u8(data));}
public void Exec__Get_as_rdr(Xof_fsdb_itm_fxt fsdb_itm_mkr, boolean is_thumb, int w) {Exec__Get_as_rdr(fsdb_itm_mkr.Make(), is_thumb, w);}
public void Exec__Get_as_rdr(Xof_fsdb_itm fsdb_itm , boolean is_thumb, int w) {
this.get_as_rdr__rdr = wkr.Get_as_rdr(fsdb_itm, is_thumb, w);
}
public void Test__Get_as_rdr__rdr(String expd) {
Tfds.Eq_str(expd, Io_stream_rdr_.Load_all_as_str(get_as_rdr__rdr), "rdr_contents");
}
}

View File

@@ -0,0 +1,81 @@
/*
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.caches; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.core.primitives.*; import gplx.core.envs.*;
import gplx.dbs.*;
import gplx.xowa.files.fsdb.*; import gplx.xowa.wikis.*;
public class Xof_cache_mgr implements Gfo_invk {
private final Gfo_usr_dlg usr_dlg; private final Xoae_wiki_mgr wiki_mgr; private final Xoa_repo_mgr repo_mgr;
private final Xofc_cfg_mgr cfg_mgr = new Xofc_cfg_mgr(); private final Xofc_dir_mgr dir_mgr; private final Xofc_fil_mgr fil_mgr;
private final Bool_obj_ref fil_created = Bool_obj_ref.n_();
public Xof_cache_mgr(Gfo_usr_dlg usr_dlg, Xoae_wiki_mgr wiki_mgr, Xoa_repo_mgr repo_mgr) {
this.usr_dlg = usr_dlg; this.wiki_mgr = wiki_mgr; this.repo_mgr = repo_mgr;
this.dir_mgr = new Xofc_dir_mgr(this);
this.fil_mgr = new Xofc_fil_mgr(this);
}
public int Next_id() {return cfg_mgr.Next_id();} public void Next_id_(int v) {cfg_mgr.Next_id_(v);}
public void Init_for_db(Db_conn conn, boolean created, boolean schema_is_1) {
cfg_mgr.Conn_(conn, created, schema_is_1);
dir_mgr.Conn_(conn, created, schema_is_1);
fil_mgr.Conn_(conn, created, schema_is_1);
}
public void Db_save() {
try {
dir_mgr.Save_all();
fil_mgr.Save_all();
cfg_mgr.Save_all(); // always save cfg_mgr last; fil_mgr / dir_mgr may change next_id during failed saves; DATE:2014-03-07
} catch (Exception e) {usr_dlg.Warn_many("", "", "cache_mgr.save:fatal error: err=~{0}", Err_.Message_gplx_full(e));}
}
public void Db_term() {
try {
cfg_mgr.Cleanup();
dir_mgr.Cleanup();
fil_mgr.Cleanup();
} catch (Exception e) {usr_dlg.Warn_many("", "", "cache_mgr.term:fatal error: err=~{0}", Err_.Message_gplx_full(e));}
}
public Xofc_fil_itm Reg(Xof_fsdb_itm itm, long bin_len) {return this.Reg(itm.Orig_repo_name(), itm.Orig_ttl(), itm.File_is_orig(), itm.File_w(), itm.File_w(), itm.Lnki_time(), itm.Orig_ext(), bin_len, DateAdp_.MaxValue, "");}
private Xofc_fil_itm Reg(byte[] repo, byte[] ttl, boolean fil_is_orig, int fil_w, int fil_h, double fil_thumbtime, Xof_ext ext, long bin_len, DateAdp modified, String hash) {
int dir_id = dir_mgr.Get_by_name_or_make(repo).Id();
Xofc_fil_itm fil_itm = fil_mgr.Get_or_make(dir_id, ttl, fil_is_orig, fil_w, fil_h, fil_thumbtime, ext, bin_len, fil_created.Val_n_());
fil_itm.Cache_time_now_();
if (fil_created.Val()) // increase cache_size if item is new; (don't increase if update); NOTE: not same as Db_cmd_mode.Created, b/c itm could be created, but not saved to db yet; EX: Page_1 has A.png; A.png marked Created; Page_2 has A.png; A.png still Created, but should increase cache_size
cfg_mgr.Cache_len_add(bin_len);
return fil_itm;
}
public void Reg_and_check_for_size_0(Xof_fsdb_itm itm) {
if (Env_.Mode_testing()) return; // NOTE: needed else test breaks in sqlite mode; DATE:2015-02-21
Xofc_fil_itm cache_fil_itm = this.Reg(itm, 0); // get item
if (cache_fil_itm.Size() == 0) { // item does not exist; size will be 0, since 0 passed above
long fil_size = Io_mgr.Instance.QueryFil(itm.Html_view_url()).Size();
cache_fil_itm.Size_(fil_size);
}
}
public void Compress_check() {
if (cfg_mgr.Cache_len() > cfg_mgr.Cache_max())
fil_mgr.Compress(usr_dlg, wiki_mgr, repo_mgr, dir_mgr, cfg_mgr);
}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_cache_min)) return cfg_mgr.Cache_min() / Io_mgr.Len_mb;
else if (ctx.Match(k, Invk_cache_min_)) cfg_mgr.Cache_min_(m.ReadLong("v") * Io_mgr.Len_mb);
else if (ctx.Match(k, Invk_cache_max)) return cfg_mgr.Cache_max() / Io_mgr.Len_mb;
else if (ctx.Match(k, Invk_cache_max_)) cfg_mgr.Cache_max_(m.ReadLong("v") * Io_mgr.Len_mb);
else if (ctx.Match(k, Invk_cache_compress)) fil_mgr.Compress(usr_dlg, wiki_mgr, repo_mgr, dir_mgr, cfg_mgr);
else return Gfo_invk_.Rv_unhandled;
return this;
} private static final String Invk_cache_min = "cache_min", Invk_cache_min_ = "cache_min_", Invk_cache_max = "cache_max", Invk_cache_max_ = "cache_max_", Invk_cache_compress = "cache_compress";
}

View File

@@ -0,0 +1,72 @@
/*
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.caches; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import org.junit.*; import gplx.dbs.*;
public class Xof_cache_mgr_tst {
// @Before public void init() {fxt.Reset();} private Xof_cache_mgr_fxt fxt = new Xof_cache_mgr_fxt();
@Test public void Basic() {
// Xou_cache_itm itm = fxt.Bldr_itm("A.png").Make();
// fxt.Test_get_n(itm);
// fxt.Exec_update(itm);
// fxt.Test_get_y(itm);
// fxt.Test_viewed_data(1, 123);
// fxt.Exec_update(itm);
// fxt.Test_viewed_data(2, 124);
// fxt.Exec_db_save(itm);
// fxt.Test_db_itms(itm);
}
}
// class Xof_cache_mgr_fxt {
// public Xof_cache_mgr_fxt Reset() {
// return this;
// }
// }
// class Xof_cache_itm_mkr {
//// private byte[] dir; private byte[] ttl; private boolean is_orig; private int w, h; private double time; private int page; private long size;
// private byte db_state;
// private int lnki_site; private byte[] lnki_ttl; private int lnki_type; private double lnki_upright; private int lnki_w; private int lnki_h; private double lnki_time; private int lnki_page;
// private int orig_wiki; private byte[] orig_ttl; private int orig_ext; private int file_w; private int file_h; private double file_time; private int file_page;
// private long temp_file_size; private int temp_view_count; private long temp_view_date; private int temp_w;
// private Bry_bfr key_bfr = Bry_bfr_.New();
// public Xof_cache_itm_mkr() {this.Reset();}
// private void Reset() {
// db_state = Db_cmd_mode.Tid_ignore;
// lnki_site = orig_wiki = -1;
// lnki_ttl = orig_ttl = null;
// lnki_type = Byte_.Max_value_127;
// lnki_upright = Xof_img_size.Upright_null;
// lnki_w = lnki_h = file_w = file_h = temp_w = Xof_img_size.Size_null;
// lnki_time = file_time = Xof_lnki_time.Null;
// lnki_page = file_page = Xof_lnki_page.Null;
// orig_ext = Xof_ext_.Id_unknown;
// temp_file_size = -1;
// temp_view_count = -1;
// temp_view_date = -1;
// }
// public Xof_cache_itm_mkr Init(String dir_str, String ttl_str, boolean is_orig, int w) {
//// this.dir = Bry_.new_u8(dir_str);
//// this.ttl = Bry_.new_u8(ttl_str);
//// this.is_orig = is_orig;
//// this.w = w;
// return this;
// }
// public Xou_cache_itm Make() {
// return new Xou_cache_itm(key_bfr, db_state, lnki_site, lnki_ttl, lnki_type, lnki_upright, lnki_w, lnki_h, file_w, file_h, );
// this.Reset();
// }
// }

View File

@@ -0,0 +1,50 @@
/*
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.caches; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.dbs.*; import gplx.dbs.cfgs.*; import gplx.xowa.wikis.data.tbls.*;
class Xofc_cfg_mgr {
private Db_cfg_tbl tbl;
public int Next_id() {return next_id++;} public void Next_id_(int v) {next_id = v;} private int next_id;
public long Cache_len() {return cache_len;} public void Cache_len_(long v) {cache_len = v;} private long cache_len = 0;
public void Cache_len_add(long v) {cache_len += v;}
public long Cache_min() {return cache_min;} public void Cache_min_(long v) {cache_min = v;} private long cache_min = Io_mgr.Len_mb * 75;
public long Cache_max() {return cache_max;} public void Cache_max_(long v) {cache_max = v;} private long cache_max = Io_mgr.Len_mb * 100;
public void Conn_(Db_conn v, boolean created, boolean schema_is_1) {
tbl = new Db_cfg_tbl(v, schema_is_1 ? gplx.xowa.wikis.data.Xowd_cfg_tbl_.Tbl_name : "file_cache_cfg");
if (created) {
tbl.Create_tbl();
tbl.Insert_int(Cfg_grp, Cfg_key__next_id, 1);
tbl.Insert_int(Cfg_grp, Cfg_key__cache_len, 0);
tbl.Insert_long(Cfg_grp, Cfg_key__cache_min, cache_min);
tbl.Insert_long(Cfg_grp, Cfg_key__cache_max, cache_max);
}
else {
next_id = tbl.Select_int(Cfg_grp, Cfg_key__next_id);
cache_len = tbl.Select_int(Cfg_grp, Cfg_key__cache_len);
cache_max = tbl.Select_int(Cfg_grp, Cfg_key__cache_max);
}
}
public void Save_all() {
tbl.Update_int(Cfg_grp, Cfg_key__next_id, next_id);
tbl.Update_long(Cfg_grp, Cfg_key__cache_len, cache_len);
tbl.Update_long(Cfg_grp, Cfg_key__cache_min, cache_min);
tbl.Update_long(Cfg_grp, Cfg_key__cache_max, cache_max);
}
public void Cleanup() {}
private static final String Cfg_grp = "fsdb.cache", Cfg_key__next_id = "next_id", Cfg_key__cache_min = "cache_min", Cfg_key__cache_max = "cache_max", Cfg_key__cache_len = "cache_len";
}

View File

@@ -0,0 +1,30 @@
/*
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.caches; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.dbs.*;
public class Xofc_dir_itm {
public Xofc_dir_itm(int id, byte[] name, byte cmd_mode) {
this.id = id;
this.name = name;
this.cmd_mode = cmd_mode;
}
public int Id() {return id;} public void Id_(int v) {id = v;} private int id;
public byte[] Name() {return name;} private final byte[] name;
public byte Cmd_mode() {return cmd_mode;} public Xofc_dir_itm Cmd_mode_(byte v) {cmd_mode = v; return this;} private byte cmd_mode;
public static final Xofc_dir_itm Null = null;
}

View File

@@ -0,0 +1,92 @@
/*
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.caches; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.dbs.*;
class Xofc_dir_mgr {
private final Xofc_dir_tbl tbl = new Xofc_dir_tbl();
private final Ordered_hash hash_by_names = Ordered_hash_.New_bry(); private final Hash_adp hash_by_ids = Hash_adp_.New();
private Xof_cache_mgr cache_mgr;
public Xofc_dir_mgr(Xof_cache_mgr v) {this.cache_mgr = v;}
public void Conn_(Db_conn v, boolean created, boolean schema_is_1) {tbl.Conn_(v, created, schema_is_1);}
public Xofc_dir_itm Get_by_id(int id) {return (Xofc_dir_itm)hash_by_ids.Get_by(id);}
public Xofc_dir_itm Get_by_name_or_make(byte[] name) {
Xofc_dir_itm itm = Get_by_name_or_null(name);
if (itm == null) { // not in memory / db
int id = cache_mgr.Next_id(); // make it
itm = new Xofc_dir_itm(id, name, Db_cmd_mode.Tid_create);
Add(name, itm);
}
return itm;
}
public Xofc_dir_itm Get_by_name_or_null(byte[] name) {
Xofc_dir_itm itm = (Xofc_dir_itm)hash_by_names.Get_by(name);
if (itm == null) { // not in memory
itm = tbl.Select_one(name); // check db
if (itm == Xofc_dir_itm.Null) return null; // in db
Add(name, itm);
}
return itm;
}
private void Add(byte[] name, Xofc_dir_itm dir) {
hash_by_names.Add(name, dir); // put it in memory
hash_by_ids.Add(dir.Id(), dir);
}
public void Save_all() {
int len = hash_by_names.Count();
boolean err_seen = false;
for (int i = 0; i < len; i++) {
Xofc_dir_itm itm = (Xofc_dir_itm)hash_by_names.Get_at(i);
if (err_seen)
itm.Id_(cache_mgr.Next_id());
if (itm.Cmd_mode() == Db_cmd_mode.Tid_create) { // create; check if in db;
Xofc_dir_itm cur = tbl.Select_one(itm.Name());
if (cur != Xofc_dir_itm.Null) // cur found
itm.Cmd_mode_(Db_cmd_mode.Tid_update); // change itm to update
}
String err = tbl.Db_save(itm);
if (err != null) {
Db_recalc_next_id(itm, err);
err_seen = true;
}
}
}
public void Load_all() {
List_adp list = List_adp_.New();
tbl.Select_all(list);
int len = list.Count();
hash_by_ids.Clear();
hash_by_names.Clear();
for (int i = 0; i < len; ++i) {
Xofc_dir_itm itm = (Xofc_dir_itm)list.Get_at(i);
hash_by_names.Add(itm.Name(), itm);
hash_by_ids.Add(itm.Id(), itm);
}
}
public void Cleanup() {tbl.Cleanup();}
private void Db_recalc_next_id(Xofc_dir_itm itm, String err) {
if (String_.Has(err, "PRIMARY KEY must be unique")) { // primary key exception in strange situations (multiple xowas at same time)
int next_id = tbl.Select_max_uid() + 1;
Gfo_usr_dlg_.Instance.Warn_many("", "", "uid out of sync; incrementing; uid=~{0} name=~{1} err=~{2}", itm.Id(), String_.new_u8(itm.Name()), err);
itm.Id_(next_id);
cache_mgr.Next_id_(next_id + 1);
err = tbl.Db_save(itm);
if (err == null) return;
}
Gfo_usr_dlg_.Instance.Warn_many("", "", "failed to save uid; uid=~{0} name=~{1} err=~{2}", itm.Id(), String_.new_u8(itm.Name()), err);
}
}

View File

@@ -0,0 +1,87 @@
/*
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.caches; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.dbs.*; import gplx.dbs.engines.sqlite.*;
class Xofc_dir_tbl implements Rls_able {
private String tbl_name = "file_cache_dir"; private final Dbmeta_fld_list flds = new Dbmeta_fld_list();
private String fld_id, fld_name;
private Db_conn conn; private final Db_stmt_bldr stmt_bldr = new Db_stmt_bldr(); private Db_stmt select_stmt;
public void Conn_(Db_conn new_conn, boolean created, boolean schema_is_1) {
this.conn = new_conn; flds.Clear();
String fld_prefix = "";
if (schema_is_1) {
tbl_name = "cache_dir";
fld_prefix = "dir_";
}
fld_id = flds.Add_int_pkey(fld_prefix + "id");
fld_name = flds.Add_str(fld_prefix + "name", 255);
if (created) {
Dbmeta_tbl_itm meta = Dbmeta_tbl_itm.New(tbl_name, flds
, Dbmeta_idx_itm.new_normal_by_tbl(tbl_name, "name", fld_name)
);
conn.Meta_tbl_create(meta);
}
stmt_bldr.Conn_(conn, tbl_name, flds, fld_id);
conn.Rls_reg(this);
}
public void Rls() {
select_stmt = Db_stmt_.Rls(select_stmt);
}
public String Db_save(Xofc_dir_itm itm) {
try {
Db_stmt stmt = stmt_bldr.Get(itm.Cmd_mode());
switch (itm.Cmd_mode()) {
case Db_cmd_mode.Tid_create: stmt.Clear().Val_int(fld_id, itm.Id()) .Val_bry_as_str(fld_name, itm.Name()).Exec_insert(); break;
case Db_cmd_mode.Tid_update: stmt.Clear() .Val_bry_as_str(fld_name, itm.Name()).Crt_int(fld_id, itm.Id()).Exec_update(); break;
case Db_cmd_mode.Tid_delete: stmt.Clear().Crt_int(fld_id, itm.Id()).Exec_delete(); break;
case Db_cmd_mode.Tid_ignore: break;
default: throw Err_.new_unhandled(itm.Cmd_mode());
}
itm.Cmd_mode_(Db_cmd_mode.Tid_ignore);
return null;
} catch (Exception e) {
stmt_bldr.Rls(); // rls bldr, else bad stmt will lead to other failures
return Err_.Message_gplx_full(e);
}
}
public void Cleanup() {
select_stmt = Db_stmt_.Rls(select_stmt);
stmt_bldr.Rls();
}
public Xofc_dir_itm Select_one(byte[] name) {
if (select_stmt == null) select_stmt = conn.Stmt_select(tbl_name, flds, fld_name);
Db_rdr rdr = select_stmt.Clear().Crt_bry_as_str(fld_name, name).Exec_select__rls_manual();
try {
return rdr.Move_next() ? new_itm(rdr) : Xofc_dir_itm.Null;
}
finally {rdr.Rls();}
}
public void Select_all(List_adp list) {
list.Clear();
Db_rdr rdr = conn.Stmt_select(tbl_name, flds, Dbmeta_fld_itm.Str_ary_empty).Exec_select__rls_auto();
try {
while (rdr.Move_next())
list.Add(new_itm(rdr));
}
finally {rdr.Rls();}
}
public int Select_max_uid() {return conn.Exec_select_as_int("SELECT Max(uid) AS MaxId FROM cache_dir;", -1);}
private Xofc_dir_itm new_itm(Db_rdr rdr) {
return new Xofc_dir_itm(rdr.Read_int(fld_id), rdr.Read_bry_by_str(fld_name), Db_cmd_mode.Tid_ignore);
}
}

View File

@@ -0,0 +1,73 @@
/*
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.caches; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.dbs.*;
public class Xofc_fil_itm implements CompareAble {
public Xofc_fil_itm(int uid, int dir_id, byte[] name, boolean is_orig, int w, int h, double time, int page, Xof_ext ext, long size, long cache_time, byte cmd_mode) {
this.uid = uid; this.dir_id = dir_id;
this.name = name; this.is_orig = is_orig; this.w = w; this.h = h; this.time = time; this.page = page; this.ext = ext; this.size = size;
this.cache_time = cache_time; this.cmd_mode = cmd_mode;
}
public String Key;
public int Uid() {return uid;} public void Uid_(int v) {uid = v;} private int uid;
public int Dir_id() {return dir_id;} private final int dir_id;
public byte[] Name() {return name;} private final byte[] name;
public boolean Is_orig() {return is_orig;} private final boolean is_orig;
public int W() {return w;} private final int w;
public int H() {return h;} private final int h;
public double Time() {return time;} private final double time;
public int Page() {return page;} private final int page;
public Xof_ext Ext() {return ext;} private final Xof_ext ext;
public long Size() {return size;} private long size;
public void Size_(long v) {
this.size = v;
cmd_mode = Db_cmd_mode.To_update(cmd_mode);
}
public long Cache_time() {return cache_time;} private long cache_time;
public Xofc_fil_itm Cache_time_now_() {
this.cache_time = Datetime_now.Get().XtoUtc().Timestamp_unix();
cmd_mode = Db_cmd_mode.To_update(cmd_mode);
return this;
}
public byte Cmd_mode() {return cmd_mode;} public Xofc_fil_itm Cmd_mode_(byte v) {cmd_mode = v; return this;} private byte cmd_mode;
public void Cmd_mode_delete_() {cmd_mode = Db_cmd_mode.Tid_delete;}
public byte[] Gen_hash_key_v1(Bry_bfr bfr) {return Gen_hash_key_v1(bfr, dir_id, name, is_orig, w, h, time);}
public byte[] Gen_hash_key_v2(Bry_bfr bfr) {return Gen_hash_key_v2(bfr, dir_id, name, is_orig, w, time, page);}
public static byte[] Gen_hash_key_v1(Bry_bfr bfr, int dir_id, byte[] name, boolean is_orig, int w, int h, double time) {
bfr .Add_int_variable(dir_id).Add_byte_pipe()
.Add(name).Add_byte_pipe()
.Add_yn(is_orig).Add_byte_pipe()
.Add_int_variable(w).Add_byte_pipe()
.Add_int_variable(h).Add_byte_pipe()
.Add_int_variable(Xof_lnki_time.X_int(time))
;
return bfr.To_bry_and_clear();
}
public static byte[] Gen_hash_key_v2(Bry_bfr bfr, int dir_id, byte[] name, boolean is_orig, int w, double time, int page) {
bfr .Add_int_variable(dir_id).Add_byte_pipe()
.Add(name).Add_byte_pipe()
.Add_yn(is_orig).Add_byte_pipe()
.Add_int_variable(w).Add_byte_pipe()
.Add_double(Xof_lnki_time.Db_save_double(time)).Add_byte_pipe()
.Add_int_variable(page)
;
return bfr.To_bry_and_clear();
}
public int compareTo(Object obj) {Xofc_fil_itm comp = (Xofc_fil_itm)obj; return -Long_.Compare(cache_time, comp.cache_time);} // - for DESC sort
public static final Xofc_fil_itm Null = null;
}

View File

@@ -0,0 +1,150 @@
/*
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.caches; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.core.primitives.*;
import gplx.dbs.*; import gplx.fsdb.*; import gplx.xowa.wikis.*;
import gplx.xowa.files.repos.*; import gplx.xowa.files.imgs.*;
class Xofc_fil_mgr {
private Xof_cache_mgr cache_mgr;
private final Xofc_fil_tbl tbl = new Xofc_fil_tbl(); private final Ordered_hash hash = Ordered_hash_.New_bry(); private final Bry_bfr key_bldr = Bry_bfr_.Reset(255);
public Xofc_fil_mgr(Xof_cache_mgr v) {this.cache_mgr = v;}
public void Conn_(Db_conn v, boolean created, boolean schema_is_1) {tbl.Conn_(v, created, schema_is_1);}
public void Save_all() {
int len = hash.Count();
boolean err_seen = false;
for (int i = 0; i < len; i++) {
Xofc_fil_itm itm = (Xofc_fil_itm)hash.Get_at(i);
if (err_seen)
itm.Uid_(cache_mgr.Next_id());
if (itm.Cmd_mode() == Db_cmd_mode.Tid_create) { // create; check if in db;
Xofc_fil_itm cur = tbl.Select_one_v1(itm.Dir_id(), itm.Name(), itm.Is_orig(), itm.W(), itm.H(), itm.Time());
if (cur != Xofc_fil_itm.Null) // cur found
itm.Cmd_mode_(Db_cmd_mode.Tid_update); // change itm to update
}
String err_msg = tbl.Db_save(itm);
if (err_msg != null) {
Db_recalc_next_id(itm, err_msg);
err_seen = true;
}
}
}
public Xofc_fil_itm Get_or_make(int dir_id, byte[] name, boolean is_orig, int w, int h, double time, Xof_ext ext, long size, Bool_obj_ref created) {
byte[] key = Xofc_fil_itm.Gen_hash_key_v1(key_bldr, dir_id, name, is_orig, w, h, time);
Xofc_fil_itm itm = (Xofc_fil_itm)hash.Get_by(key);
if (itm == Xofc_fil_itm.Null) { // not in memory
itm = tbl.Select_one_v1(dir_id, name, is_orig, w, h, time);
if (itm == Xofc_fil_itm.Null) { // not in db
itm = Make_v1(dir_id, name, is_orig, w, h, time, Xof_lnki_page.Null, ext, size);
created.Val_(true);
}
else // NOTE: itm loaded from tbl; add to hash; do not add if created b/c Make adds to hash;
hash.Add(key, itm);
}
return itm;
}
public Xofc_fil_itm Get_or_null(int dir_id, byte[] name, boolean is_orig, int w, double time, int page) {
byte[] key = Xofc_fil_itm.Gen_hash_key_v2(key_bldr, dir_id, name, is_orig, w, time, page);
Xofc_fil_itm itm = (Xofc_fil_itm)hash.Get_by(key);
if (itm == null) { // not in memory
itm = tbl.Select_one_v2(dir_id, name, is_orig, w, time, page);
if (itm == Xofc_fil_itm.Null) return itm; // not in db
hash.Add(key, itm);
}
return itm;
}
private Xofc_fil_itm Make_v1(int dir_id, byte[] name, boolean is_orig, int w, int h, double time, int page, Xof_ext ext, long size) {return Make(Bool_.Y, dir_id, name, is_orig, w, h, time, page, ext, size);}
public Xofc_fil_itm Make_v2(int dir_id, byte[] name, boolean is_orig, int w, int h, double time, int page, Xof_ext ext, long size) {return Make(Bool_.N, dir_id, name, is_orig, w, h, time, page, ext, size);}
private Xofc_fil_itm Make(boolean schema_is_1, int dir_id, byte[] name, boolean is_orig, int w, int h, double time, int page, Xof_ext ext, long size) {
int id = cache_mgr.Next_id();
Xofc_fil_itm rv = new Xofc_fil_itm(id, dir_id, name, is_orig, w, h, time, page, ext, size, 0, Db_cmd_mode.Tid_create).Cache_time_now_();
byte[] key = schema_is_1 ? rv.Gen_hash_key_v1(key_bldr) : rv.Gen_hash_key_v2(key_bldr);
hash.Add(key, rv);
return rv;
}
public void Compress(Gfo_usr_dlg usr_dlg, Xoae_wiki_mgr wiki_mgr, Xoa_repo_mgr repo_mgr, Xofc_dir_mgr dir_mgr, Xofc_cfg_mgr cfg_mgr) {
try {
usr_dlg.Note_many("", "", "compressing cache");
dir_mgr.Save_all(); dir_mgr.Load_all(); // save and load all dirs
this.Save_all(); tbl.Select_all(key_bldr, hash); // save and load all fils
hash.Sort(); // sorts by cache_time desc
int len = hash.Count();
long cur_size = 0, actl_size = 0;
Xof_url_bldr url_bldr = new Xof_url_bldr();
List_adp deleted = List_adp_.New();
tbl.Conn().Txn_bgn("user__file_cache__compress");
long compress_to = cfg_mgr.Cache_min();
for (int i = 0; i < len; ++i) {
Xofc_fil_itm itm = (Xofc_fil_itm)hash.Get_at(i);
long itm_size = itm.Size();
long new_size = cur_size + itm_size;
if (new_size > compress_to) {
itm.Cmd_mode_(gplx.dbs.Db_cmd_mode.Tid_delete);
Fsys_delete(url_bldr, wiki_mgr, repo_mgr, dir_mgr, itm);
deleted.Add(itm);
}
else
actl_size += itm_size;
cur_size = new_size;
String err_msg = tbl.Db_save(itm); // save to db now, b/c fils will be deleted and want to keep db and fsys in sync
if (err_msg != null)
Db_recalc_next_id(itm, err_msg);
}
len = deleted.Count();
for (int i = 0; i < len; i++) {
Xofc_fil_itm itm = (Xofc_fil_itm)deleted.Get_at(i);
byte[] fil_key = itm.Gen_hash_key_v1(key_bldr);
hash.Del(fil_key);
}
cfg_mgr.Cache_len_(actl_size);
this.Save_all(); // save everything again
}
catch (Exception e) {
usr_dlg.Warn_many("", "", "failed to compress cache: err=~{0}", Err_.Message_gplx_full(e));
}
finally {tbl.Conn().Txn_end();}
}
private void Fsys_delete(Xof_url_bldr url_bldr, Xoae_wiki_mgr wiki_mgr, Xoa_repo_mgr repo_mgr, Xofc_dir_mgr dir_mgr, Xofc_fil_itm itm) {
byte mode_id = itm.Is_orig() ? Xof_img_mode_.Tid__orig : Xof_img_mode_.Tid__thumb;
byte[] wiki_domain = dir_mgr.Get_by_id(itm.Dir_id()).Name();
Xowe_wiki wiki = wiki_mgr.Get_by_or_make(wiki_domain);
wiki.Init_assert();
Xof_repo_itm trg_repo = repo_mgr.Get_by_primary(wiki_domain);
byte[] ttl = itm.Name();
byte[] md5 = Xof_file_wkr_.Md5(ttl);
int itm_ext_id = itm.Ext().Id();
Io_url fil_url = url_bldr.Init_for_trg_file(trg_repo, mode_id, ttl, md5, itm.Ext(), itm.W()
, Xof_lnki_time.Convert_to_xowa_thumbtime (itm_ext_id, itm.Time())
, Xof_lnki_time.Convert_to_xowa_page (itm_ext_id, itm.Time())
).Xto_url();
Io_mgr.Instance.DeleteFil_args(fil_url).MissingFails_off().Exec();
itm.Cmd_mode_delete_();
}
public void Cleanup() {tbl.Rls();}
private void Db_recalc_next_id(Xofc_fil_itm fil_itm, String err_msg) {
if (String_.Has(err_msg, "PRIMARY KEY must be unique")) { // primary key exception in strange situations (multiple xowas at same time)
int next_id = tbl.Select_max_uid() + 1;
Gfo_usr_dlg_.Instance.Warn_many("", "", "uid out of sync; incrementing; uid=~{0} name=~{1} err=~{2}", fil_itm.Uid(), String_.new_u8(fil_itm.Name()), err_msg);
fil_itm.Uid_(next_id);
cache_mgr.Next_id_(next_id + 1);
err_msg = tbl.Db_save(fil_itm);
if (err_msg == null)
return;
}
Gfo_usr_dlg_.Instance.Warn_many("", "", "failed to save uid; uid=~{0} name=~{1} err=~{2}", fil_itm.Uid(), String_.new_u8(fil_itm.Name()), err_msg);
}
}

View File

@@ -0,0 +1,155 @@
/*
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.caches; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.dbs.*; import gplx.dbs.engines.sqlite.*;
class Xofc_fil_tbl implements Rls_able {
private String tbl_name = "file_cache_fil"; private final Dbmeta_fld_list flds = new Dbmeta_fld_list();
private String fld_uid, fld_dir_id, fld_name, fld_is_orig, fld_w, fld_h, fld_time, fld_page, fld_ext, fld_size, fld_cache_time;
private Db_conn conn; private final Db_stmt_bldr stmt_bldr = new Db_stmt_bldr(); private Db_stmt select_itm_stmt, select_itm_v2_stmt;
public Db_conn Conn() {return conn;}
public void Conn_(Db_conn new_conn, boolean created, boolean schema_is_1) {
this.conn = new_conn; flds.Clear();
String fld_prefix = "";
if (schema_is_1) {
tbl_name = "cache_fil";
fld_prefix = "fil_";
}
fld_uid = flds.Add_int_pkey("uid");
fld_dir_id = flds.Add_int("dir_id");
fld_name = flds.Add_str(fld_prefix + "name", 255);
fld_is_orig = flds.Add_byte(fld_prefix + "is_orig");
fld_w = flds.Add_int(fld_prefix + "w");
fld_h = flds.Add_int(fld_prefix + "h");
fld_time = flds.Add_int(fld_prefix + "thumbtime");
if (schema_is_1) {
fld_page = Dbmeta_fld_itm.Key_null;
}
else {
fld_page = flds.Add_int(fld_prefix + "page");
}
fld_ext = flds.Add_int(fld_prefix + "ext");
fld_size = flds.Add_long(fld_prefix + "size");
fld_cache_time = flds.Add_long("cache_time");
if (created) {
Dbmeta_tbl_itm meta = Dbmeta_tbl_itm.New(tbl_name, flds
, Dbmeta_idx_itm.new_normal_by_tbl(tbl_name, "fil", fld_name, fld_is_orig, fld_w, fld_h, fld_time, fld_cache_time, fld_uid)
);
conn.Meta_tbl_create(meta);
}
select_itm_stmt = select_itm_v2_stmt = null;
stmt_bldr.Conn_(conn, tbl_name, flds, fld_uid);
conn.Rls_reg(this);
}
public void Rls() {
select_itm_stmt = Db_stmt_.Rls(select_itm_stmt);
select_itm_v2_stmt = Db_stmt_.Rls(select_itm_v2_stmt);
stmt_bldr.Rls();
}
public String Db_save(Xofc_fil_itm itm) {
try {
Db_stmt stmt = stmt_bldr.Get(itm.Cmd_mode());
switch (itm.Cmd_mode()) {
case Db_cmd_mode.Tid_create: stmt.Clear().Val_int(fld_uid, itm.Uid()); Db_save_modify(stmt, itm); stmt.Exec_insert(); break;
case Db_cmd_mode.Tid_update: stmt.Clear(); Db_save_modify(stmt, itm); stmt.Crt_int(fld_uid, itm.Uid()).Exec_update(); break;
case Db_cmd_mode.Tid_delete: stmt.Clear().Crt_int(fld_uid, itm.Uid()); stmt.Exec_delete(); break;
case Db_cmd_mode.Tid_ignore: break;
default: throw Err_.new_unhandled(itm.Cmd_mode());
}
itm.Cmd_mode_(Db_cmd_mode.Tid_ignore);
return null;
} catch (Exception e) {
stmt_bldr.Rls(); // null out bldr, else bad stmt will lead to other failures
return Err_.Message_gplx_full(e);
}
}
private void Db_save_modify(Db_stmt stmt, Xofc_fil_itm itm) {
stmt.Val_int(fld_dir_id, itm.Dir_id())
.Val_bry_as_str(fld_name, itm.Name())
.Val_bool_as_byte(fld_is_orig, itm.Is_orig())
.Val_int(fld_w, itm.W())
.Val_int(fld_h, itm.H())
.Val_int(fld_time, Xof_lnki_time.Db_save_int(itm.Time()))
.Val_int(fld_page, itm.Page())
.Val_int(fld_ext, itm.Ext().Id())
.Val_long(fld_size, itm.Size())
.Val_long(fld_cache_time, itm.Cache_time())
;
}
public Xofc_fil_itm Select_one_v1(int dir_id, byte[] fil_name, boolean fil_is_orig, int fil_w, int fil_h, double fil_thumbtime) {
if (select_itm_stmt == null) select_itm_stmt = conn.Stmt_select(tbl_name, flds, String_.Ary(fld_dir_id, fld_name, fld_is_orig, fld_w, fld_h, fld_time));
Db_rdr rdr = select_itm_stmt.Clear()
.Crt_int(fld_dir_id, dir_id)
.Crt_bry_as_str(fld_name, fil_name)
.Crt_bool_as_byte(fld_is_orig, fil_is_orig)
.Crt_int(fld_w, fil_w)
.Crt_int(fld_h, fil_h)
.Crt_int(fld_time, Xof_lnki_time.Db_save_int(fil_thumbtime))
.Exec_select__rls_manual();
try {
return rdr.Move_next() ? new_itm(rdr) : Xofc_fil_itm.Null;
}
finally {rdr.Rls();}
}
public Xofc_fil_itm Select_one_v2(int dir_id, byte[] name, boolean is_orig, int w, double time, int page) {
if (select_itm_v2_stmt == null) select_itm_v2_stmt = conn.Stmt_select(tbl_name, flds, String_.Ary(fld_dir_id, fld_name, fld_is_orig, fld_w, fld_time, fld_page));
Db_rdr rdr = select_itm_v2_stmt.Clear()
.Crt_int(fld_dir_id, dir_id)
.Crt_bry_as_str(fld_name, name)
.Crt_bool_as_byte(fld_is_orig, is_orig)
.Crt_int(fld_w, w)
.Crt_int(fld_time, Xof_lnki_time.Db_save_int(time))
.Crt_int(fld_page, page)
.Exec_select__rls_manual();
try {
return rdr.Move_next() ? new_itm(rdr) : Xofc_fil_itm.Null;
}
finally {rdr.Rls();}
}
public void Select_all(Bry_bfr fil_key_bldr, Ordered_hash hash) {
hash.Clear();
Db_rdr rdr = conn.Stmt_select(tbl_name, flds, Dbmeta_fld_itm.Str_ary_empty).Exec_select__rls_auto();
try {
while (rdr.Move_next()) {
Xofc_fil_itm fil_itm = new_itm(rdr);
byte[] key = fil_itm.Gen_hash_key_v1(fil_key_bldr);
if (hash.Has(key)) // NOTE: need to check for uniqueness else dupe file will cause select to fail; shouldn't happen, but somehow did; DATE:2013-12-28
Gfo_usr_dlg_.Instance.Warn_many("", "", "cache had duplicate itm: key=~{0}", String_.new_u8(key));
else
hash.Add(key, fil_itm);
}
}
finally {rdr.Rls();}
}
public int Select_max_uid() {return conn.Exec_select_as_int("SELECT Max(uid) AS MaxId FROM cache_fil;", -1);}
private Xofc_fil_itm new_itm(Db_rdr rdr) {
return new Xofc_fil_itm
( rdr.Read_int(fld_uid)
, rdr.Read_int(fld_dir_id)
, rdr.Read_bry_by_str(fld_name)
, rdr.Read_byte(fld_is_orig) != Byte_.Zero
, rdr.Read_int(fld_w)
, rdr.Read_int(fld_h)
, Xof_lnki_time.Db_load_int(rdr, fld_time)
, Xof_lnki_page.Null
, Xof_ext_.new_by_id_(rdr.Read_int(fld_ext))
, rdr.Read_long(fld_size)
, rdr.Read_long(fld_cache_time)
, Db_cmd_mode.Tid_ignore
);
}
}

View File

@@ -0,0 +1,23 @@
/*
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.caches; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
public interface Xou_cache_finder {
boolean Find(Xow_wiki wiki, byte[] page_url, Xof_fsdb_itm fsdb_itm);
void Clear();
void Add(Xof_fsdb_itm fsdb_itm);
}

View File

@@ -0,0 +1,56 @@
/*
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.caches; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.xowa.files.repos.*;
public class Xou_cache_finder_ {
public static final Xou_cache_finder Noop = new Xou_cache_finder_noop();
public static Xou_cache_finder_mem New_mem() {return new Xou_cache_finder_mem();}
public static Xou_cache_finder New_db(Xou_cache_mgr cache_mgr) {return new Xou_cache_finder_db(cache_mgr);}
}
class Xou_cache_finder_noop implements Xou_cache_finder {
public boolean Find(Xow_wiki wiki, byte[] page_url, Xof_fsdb_itm fsdb_itm) {
fsdb_itm.Init_at_cache(false, 0, 0, Io_url_.Empty);
return false;
}
public void Clear() {}
public void Add(Xof_fsdb_itm fsdb_itm) {}
}
class Xou_cache_finder_db implements Xou_cache_finder {
private final Xou_cache_mgr cache_mgr;
private final Xof_img_size img_size = new Xof_img_size(); private final Xof_url_bldr url_bldr = Xof_url_bldr.new_v2();
public Xou_cache_finder_db(Xou_cache_mgr cache_mgr) {this.cache_mgr = cache_mgr;}
public boolean Find(Xow_wiki wiki, byte[] page_url, Xof_fsdb_itm cur) {
Xou_cache_itm cache_itm = cache_mgr.Get_or_null(cur);
if (cache_itm != null) {
Xof_repo_itm repo = wiki.File__repo_mgr().Get_trg_by_id_or_null(cache_itm.Orig_repo_id(), cur.Lnki_ttl(), page_url);
if (repo != null) {// unknown repo; shouldn't happen, but exit, else null ref
cur.Init_at_orig((byte)cache_itm.Orig_repo_id(), repo.Wiki_domain(), cache_itm.Orig_ttl(), cache_itm.Orig_ext_itm(), cache_itm.Orig_w(), cache_itm.Orig_h(), Bry_.Empty);
cur.Init_at_html(Xof_exec_tid.Tid_wiki_page, img_size, repo, url_bldr);
if (Io_mgr.Instance.ExistsFil(cur.Html_view_url())) {
cache_itm.Update_view_stats();
cur.Init_at_cache(true, cur.Html_w(), cur.Html_h(), cur.Html_view_url());
return true;
}
}
}
cur.Init_at_cache(false, 0, 0, Io_url_.Empty);
return false;
}
public void Clear() {}
public void Add(Xof_fsdb_itm cur) {}
}

View File

@@ -0,0 +1,43 @@
/*
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.caches; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.xowa.files.repos.*;
public class Xou_cache_finder_mem implements Xou_cache_finder {
private final Ordered_hash hash = Ordered_hash_.New_bry();
private final Bry_bfr tmp_bfr = Bry_bfr_.New_w_size(255);
private final Xof_img_size img_size = new Xof_img_size();
private final Xof_url_bldr url_bldr = Xof_url_bldr.new_v2();
public boolean Find(Xow_wiki wiki, byte[] page_url, Xof_fsdb_itm cur) {
byte[] key = Xou_cache_itm.Key_gen(tmp_bfr, cur.Lnki_wiki_abrv(), cur.Lnki_ttl(), cur.Lnki_type(), cur.Lnki_upright(), cur.Lnki_w(), cur.Lnki_h(), cur.Lnki_time(), cur.Lnki_page(), cur.User_thumb_w());
Xof_fsdb_itm mem = (Xof_fsdb_itm)hash.Get_by(key);
if (mem == null) {
cur.Init_at_cache(false, 0, 0, Io_url_.Empty);
return false;
}
Xof_repo_itm repo = wiki.File__repo_mgr().Get_trg_by_id_or_null(mem.Orig_repo_id(), mem.Lnki_ttl(), page_url);
if (repo != null) // HACK: ignore null repo for tests that don't create repos; DATE:2016-06-18
mem.Init_at_html(Xof_exec_tid.Tid_wiki_page, img_size, repo, url_bldr);
cur.Init_at_cache(true, mem.Html_w(), mem.Html_h(), mem.Html_view_url());
return true;
}
public void Clear() {}
public void Add(Xof_fsdb_itm cur) {
byte[] key = Xou_cache_itm.Key_gen(tmp_bfr, cur.Lnki_wiki_abrv(), cur.Lnki_ttl(), cur.Lnki_type(), cur.Lnki_upright(), cur.Lnki_w(), cur.Lnki_h(), cur.Lnki_time(), cur.Lnki_page(), cur.User_thumb_w());
hash.Add(key, cur);
}
}

View File

@@ -0,0 +1,89 @@
/*
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.caches; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.dbs.*;
public class Xou_cache_itm {
public Xou_cache_itm
( Bry_bfr lnki_key_bfr, byte db_state
, byte[] lnki_wiki_abrv, byte[] lnki_ttl, int lnki_type, double lnki_upright, int lnki_w, int lnki_h, double lnki_time, int lnki_page, int user_thumb_w
, int orig_repo_id, byte[] orig_ttl, int orig_ext_id, int orig_w, int orig_h
, int html_w, int html_h, double html_time, int html_page
, boolean file_is_orig, int file_w, double file_time, int file_page, long file_size
, int view_count, long view_date
) {
this.db_state = db_state;
this.lnki_wiki_abrv = lnki_wiki_abrv; this.lnki_ttl = lnki_ttl; this.lnki_type = lnki_type; this.lnki_upright = lnki_upright; this.lnki_w = lnki_w; this.lnki_h = lnki_h; this.lnki_time = lnki_time; this.lnki_page = lnki_page; this.user_thumb_w = user_thumb_w;
this.orig_repo_id = orig_repo_id; this.orig_ttl = orig_ttl; this.orig_ext_id = orig_ext_id; this.orig_w = orig_w; this.orig_h = orig_h;
this.file_is_orig = file_is_orig; this.html_w = html_w; this.html_h = html_h; this.html_time = html_time; this.html_page = html_page;
this.file_w = file_w; this.file_time = file_time; this.file_page = file_page; this.file_size = file_size;
this.view_count = view_count; this.view_date = view_date;
this.lnki_key = Key_gen(lnki_key_bfr, lnki_wiki_abrv, lnki_ttl, lnki_type, lnki_upright, lnki_w, lnki_h, lnki_time, lnki_page, user_thumb_w);
}
public byte Db_state() {return db_state;} public void Db_state_(byte v) {db_state = v;} private byte db_state;
public byte[] Lnki_wiki_abrv() {return lnki_wiki_abrv;} private final byte[] lnki_wiki_abrv; // differentiate commonwiki rows inserted by one wiki vs another
public byte[] Lnki_key() {return lnki_key;} private final byte[] lnki_key; // unique key by lnki props
public byte[] Lnki_ttl() {return lnki_ttl;} private final byte[] lnki_ttl;
public int Lnki_type() {return lnki_type;} private final int lnki_type;
public double Lnki_upright() {return lnki_upright;} private final double lnki_upright;
public int Lnki_w() {return lnki_w;} private final int lnki_w;
public int Lnki_h() {return lnki_h;} private final int lnki_h;
public double Lnki_time() {return lnki_time;} private final double lnki_time;
public int Lnki_page() {return lnki_page;} private final int lnki_page;
public int User_thumb_w() {return user_thumb_w;} private final int user_thumb_w;
public int Orig_repo_id() {return orig_repo_id;} private final int orig_repo_id;
public byte[] Orig_ttl() {return orig_ttl;} private final byte[] orig_ttl;
public byte[] Orig_ttl_md5() {if (orig_ttl_md5 == null) orig_ttl_md5 = Xof_file_wkr_.Md5_fast(orig_ttl); return orig_ttl_md5;} private byte[] orig_ttl_md5;
public int Orig_ext_id() {return orig_ext_id;} private final int orig_ext_id;
public Xof_ext Orig_ext_itm() {if (orig_ext_itm == null) orig_ext_itm = Xof_ext_.new_by_id_(orig_ext_id); return orig_ext_itm;} private Xof_ext orig_ext_itm;
public int Orig_w() {return orig_w;} private final int orig_w;
public int Orig_h() {return orig_h;} private final int orig_h;
public int Html_w() {return html_w;} private final int html_w;
public int Html_h() {return html_h;} private final int html_h;
public double Html_time() {return html_time;} private final double html_time;
public int Html_page() {return html_page;} private final int html_page;
public boolean File_is_orig() {return file_is_orig;} private final boolean file_is_orig;
public int File_w() {return file_w;} private int file_w;
public double File_time() {return file_time;} private final double file_time;
public int File_page() {return file_page;} private final int file_page;
public long File_size() {return file_size;} private final long file_size;
public Io_url File_url() {return file_url;} public void File_url_(Io_url v) {file_url = v;} private Io_url file_url;
public int View_count() {return view_count;} private int view_count;
public long View_date() {return view_date;} private long view_date;
public void Update_view_stats() {
++view_count;
view_date = Datetime_now.Get().Timestamp_unix();
db_state = Db_cmd_mode.To_update(db_state);
}
public static final Xou_cache_itm Null = null;
public static byte[] Key_gen(Bry_bfr key_bfr, byte[] lnki_wiki_abrv, byte[] ttl, int type, double upright, int w, int h, double time, int page, int user_thumb_w) {
key_bfr.Add(lnki_wiki_abrv).Add_byte_pipe()
.Add(ttl).Add_byte_pipe().Add_int_variable(type).Add_byte_pipe().Add_double(upright).Add_byte_pipe()
.Add_int_variable(w).Add_byte_pipe().Add_int_variable(h).Add_byte_pipe().Add_double(time).Add_byte_pipe().Add_int_variable(page)
.Add_int_variable(user_thumb_w)
;
return key_bfr.To_bry_and_clear();
}
}
class Xof_cache_mgr_sorter implements gplx.core.lists.ComparerAble {
public int compare(Object lhsObj, Object rhsObj) {
Xou_cache_itm lhs = (Xou_cache_itm)lhsObj;
Xou_cache_itm rhs = (Xou_cache_itm)rhsObj;
return -Long_.Compare(lhs.View_date(), rhs.View_date()); // - for DESC sort
}
public static final Xof_cache_mgr_sorter Instance = new Xof_cache_mgr_sorter(); Xof_cache_mgr_sorter() {}
}

View File

@@ -0,0 +1,252 @@
/*
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.caches; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.core.primitives.*; import gplx.dbs.*; import gplx.dbs.cfgs.*;
import gplx.xowa.files.fsdb.*; import gplx.xowa.files.repos.*; import gplx.xowa.files.imgs.*;
import gplx.xowa.wikis.*; import gplx.xowa.wikis.domains.*; import gplx.xowa.users.data.*;
public class Xou_cache_mgr implements Gfo_invk {
private long fsys_size_cur = 0;
private long fsys_size_min = Io_mgr.Len_mb * 75;
private long fsys_size_max = Io_mgr.Len_mb * 100;
private final Xoa_wiki_mgr wiki_mgr; private final Xou_cache_tbl cache_tbl; private final Db_cfg_tbl cfg_tbl; private final Bry_bfr tmp_bfr = Bry_bfr_.Reset(512);
private final Ordered_hash hash = Ordered_hash_.New_bry(); private final Xof_url_bldr url_bldr = Xof_url_bldr.new_v2(); private final Object thread_lock = new Object();
private final Io_url cache_dir; private boolean db_load_needed = true;
public Xou_cache_mgr(Xoa_wiki_mgr wiki_mgr, Io_url cache_dir, Xou_db_file db_file) {
this.wiki_mgr = wiki_mgr; this.cache_dir = cache_dir;
this.cfg_tbl = db_file.Tbl__cfg();
this.cache_tbl = db_file.Tbl__cache();
}
public boolean Enabled() {return enabled;} private boolean enabled = true; public void Enabled_n_() {enabled = false;}
public void Init_by_app(Xoa_app app) {
app.Cfg().Bind_many_app(this, Cfg__fsys_size_min, Cfg__fsys_size_max);
app.Cfg().Sub_many_app(this, Run__fsys_reduce_to_min, Run__fsys_clear);
app.Cfg().Dflt_mgr().Add(this, Val__fsys_info);
}
public Xou_cache_itm Get_or_null(Xof_fsdb_itm fsdb) {return Get_or_null(fsdb.Lnki_wiki_abrv(), fsdb.Lnki_ttl(), fsdb.Lnki_type(), fsdb.Lnki_upright(), fsdb.Lnki_w(), fsdb.Lnki_h(), fsdb.Lnki_time(), fsdb.Lnki_page(), fsdb.User_thumb_w());}
public Xou_cache_itm Get_or_null(byte[] wiki, byte[] ttl, int type, double upright, int w, int h, double time, int page, int user_thumb_w) {
if (!enabled) return null;
synchronized (thread_lock) {
this.Page_bgn();
byte[] key = Xou_cache_itm.Key_gen(tmp_bfr, wiki, ttl, type, upright, w, h, time, page, user_thumb_w);
Xou_cache_itm rv = (Xou_cache_itm)hash.Get_by(key);
if (rv == Xou_cache_itm.Null) {
rv = cache_tbl.Select_one(wiki, ttl, type, upright, w, h, time, page, user_thumb_w);
if (rv == Xou_cache_itm.Null) return Xou_cache_itm.Null;
hash.Add(key, rv);
}
return rv;
}
}
public void Update(Xof_fsdb_itm fsdb) {
synchronized (thread_lock) {
Xou_cache_itm itm = Get_or_null(fsdb.Lnki_wiki_abrv(), fsdb.Lnki_ttl(), fsdb.Lnki_type(), fsdb.Lnki_upright(), fsdb.Lnki_w(), fsdb.Lnki_h(), fsdb.Lnki_time(), fsdb.Lnki_page(), fsdb.User_thumb_w());
if (itm == Xou_cache_itm.Null) {
itm = new Xou_cache_itm(tmp_bfr, Db_cmd_mode.Tid_create, fsdb.Lnki_wiki_abrv(), fsdb.Lnki_ttl(), fsdb.Lnki_type(), fsdb.Lnki_upright(), fsdb.Lnki_w(), fsdb.Lnki_h(), fsdb.Lnki_time(), fsdb.Lnki_page(), fsdb.User_thumb_w()
, fsdb.Orig_repo_id(), fsdb.Orig_ttl(), fsdb.Orig_ext().Id(), fsdb.Orig_w(), fsdb.Orig_h()
, fsdb.Html_w(), fsdb.Html_h(), fsdb.Lnki_time(), fsdb.Lnki_page()
, fsdb.File_is_orig(), fsdb.File_w(), fsdb.Lnki_time(), fsdb.Lnki_page(), fsdb.File_size()
, 1, Datetime_now.Get().Timestamp_unix())
;
hash.Add(itm.Lnki_key(), itm);
fsys_size_cur += itm.File_size();
}
else
itm.Update_view_stats();
}
}
public void Page_bgn() {
if (db_load_needed) {
db_load_needed = false;
fsys_size_cur = cfg_tbl.Assert_long("user.file_cache", "size_sum", 0);
cache_tbl.Select_all(tmp_bfr, hash);
}
}
public void Page_end(Xoa_wiki_mgr wiki_mgr) { // threaded
cfg_tbl.Update_long("user.file_cache", "size_sum", fsys_size_cur);
this.Db_save();
if (fsys_size_cur > fsys_size_max) this.Reduce(fsys_size_min);
}
@gplx.Internal protected void Clear() {
db_load_needed = true;
fsys_size_cur = 0;
hash.Clear();
}
public void Db_save() {
synchronized (thread_lock) {
Db_conn conn = cache_tbl.Conn();
try {
conn.Txn_bgn("user__file_cache__save");
int len = hash.Count();
for (int i = 0; i < len; ++i) {
Xou_cache_itm itm = (Xou_cache_itm)hash.Get_at(i);
cache_tbl.Db_save(itm);
}
conn.Txn_end();
}
catch (Exception e) {conn.Txn_cxl(); throw Err_.new_exc(e, "cache", "unknown error while saving cache; err=~{0}", Err_.Message_gplx_log(e));}
}
}
public void Reduce(long reduce_to) {
Xoa_app_.Usr_dlg().Note_many("", "", "cache compress started");
synchronized (thread_lock) {
try {
this.Db_save(); cache_tbl.Select_all(tmp_bfr, hash); // save and load
Ordered_hash grp_hash = Ordered_hash_.New(); // aggregate by file path; needed when same commons file used by two wikis
int len = hash.Count();
for (int i = 0; i < len; ++i) {
Xou_cache_itm itm = (Xou_cache_itm)hash.Get_at(i);
Io_url itm_url = Calc_url(itm);
itm.File_url_(itm_url);
Xou_cache_grp grp = (Xou_cache_grp)grp_hash.Get_by(itm_url.Raw());
if (grp == null) {
grp = new Xou_cache_grp(itm_url);
grp_hash.Add(itm_url.Raw(), grp);
}
grp.Add(itm);
}
grp_hash.Sort_by(Xou_cache_grp_sorter.Instance); // sorts by cache_time desc
len = grp_hash.Count();
long fsys_size_calc = 0, fsys_size_temp = 0;
List_adp deleted = List_adp_.New();
for (int i = 0; i < len; ++i) { // iterate and find items to delete
Xou_cache_grp grp = (Xou_cache_grp)grp_hash.Get_at(i);
fsys_size_temp = fsys_size_calc + grp.File_size();
if ( fsys_size_temp > reduce_to // fsys_size_cur exceeded; mark itm for deletion
|| fsys_size_temp == -1 // fsys_size sometimes -1; note -1 b/c file is missing; should fix, but for now, consider -1 size deleted; DATE:2015-08-05
)
deleted.Add(grp);
else
fsys_size_calc = fsys_size_temp;
}
len = deleted.Count();
Db_conn conn = cache_tbl.Conn();
conn.Txn_bgn("user__file_cache__delete");
for (int i = 0; i < len; i++) { // iterate and delete
Xou_cache_grp grp = (Xou_cache_grp)deleted.Get_at(i);
grp.Delete(hash, cache_tbl);
fsys_size_cur -= grp.File_size();
}
conn.Txn_end();
Io_mgr.Instance.Delete_dir_empty(cache_dir);
}
catch (Exception e) {Xoa_app_.Usr_dlg().Warn_many("", "", "failed to compress cache: err=~{0}", Err_.Message_gplx_full(e)); return;}
}
Xoa_app_.Usr_dlg().Note_many("", "", "cache compress done");
}
private Io_url Calc_url(Xou_cache_itm cache) {
byte[] wiki_domain = Xow_abrv_xo_.To_itm(cache.Lnki_wiki_abrv()).Domain_bry();
Xow_wiki wiki = wiki_mgr.Get_by_or_make_init_y(wiki_domain); if (wiki == null) return Io_url_.Empty; // wiki is not available; should only happen in read-only mode; DATE:2015-05-23
Xof_repo_itm trg_repo = wiki.File__repo_mgr().Get_trg_by_id_or_null(cache.Orig_repo_id(), cache.Lnki_ttl(), Bry_.Empty);
if (trg_repo == null) return Io_url_.Empty;
byte[] orig_ttl = cache.Orig_ttl();
byte[] orig_md5 = cache.Orig_ttl_md5();
Xof_ext orig_ext = cache.Orig_ext_itm();
orig_ttl = trg_repo.Gen_name_trg(tmp_bfr, orig_ttl, orig_md5, orig_ext);
byte mode_id = cache.File_is_orig() ? Xof_img_mode_.Tid__orig : Xof_img_mode_.Tid__thumb;
return url_bldr.Init_for_trg_file(trg_repo, mode_id, orig_ttl, orig_md5, orig_ext, cache.File_w()
, Xof_lnki_time.Convert_to_xowa_thumbtime (orig_ext.Id(), cache.File_time())
, Xof_lnki_time.Convert_to_xowa_page (orig_ext.Id(), cache.File_page())
).Xto_url();
}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Cfg__fsys_size_min)) this.fsys_size_min = m.ReadLong("v") * Io_mgr.Len_mb;
else if (ctx.Match(k, Cfg__fsys_size_max)) this.fsys_size_max = m.ReadLong("v") * Io_mgr.Len_mb;
else if (ctx.Match(k, Val__fsys_info)) return this.Info_str();
else if (ctx.Match(k, Run__fsys_reduce_to_min)) {this.Reduce(fsys_size_min);}
else if (ctx.Match(k, Run__fsys_clear)) {this.Reduce(0);}
else return Gfo_invk_.Rv_unhandled;
return this;
}
private static final String
Cfg__fsys_size_min = "xowa.files.cache.fsys_size_min"
, Cfg__fsys_size_max = "xowa.files.cache.fsys_size_max"
, Run__fsys_reduce_to_min = "xowa.files.cache.reduce_to_min"
, Run__fsys_clear = "xowa.files.cache.clear"
, Val__fsys_info = "xowa.files.cache.info"
;
public void Fsys_size_(long min, long max) {fsys_size_min = min; fsys_size_max = max;} // TEST:
private String Info_str() {
this.Page_bgn();
Bry_bfr bfr = Bry_bfr_.New_w_size(255);
Keyval[] ary = this.Info_kvs();
int len = ary.length;
for (int i = 0; i < len; ++i) {
Keyval kv = ary[i];
bfr.Add_str_a7(kv.Key()).Add_str_a7(": ").Add_str_u8(kv.Val_to_str_or_empty()).Add_byte_nl();
}
return bfr.To_str_and_clear();
}
private Keyval[] Info_kvs() {
long view_date = Long_.Max_value;
long fsys_size = 0;
int len = hash.Count();
for (int i = 0; i < len; ++i) {
Xou_cache_itm itm = (Xou_cache_itm)hash.Get_at(i);
fsys_size += itm.File_size();
if (itm.View_date() < view_date) view_date = itm.View_date();
}
return Keyval_.Ary
( Keyval_.new_("cache folder", cache_dir.Xto_api())
, Keyval_.new_("space used", gplx.core.ios.Io_size_.To_str(fsys_size))
, Keyval_.new_("file count", len)
, Keyval_.new_("oldest file", view_date == Long_.Max_value ? "" : DateAdp_.unixtime_utc_seconds_(view_date).XtoStr_fmt_iso_8561())
);
}
}
class Xou_cache_grp {
private final List_adp list = List_adp_.New();
public Xou_cache_grp(Io_url file_url) {this.file_url = file_url;}
public long View_date() {return view_date;} private long view_date;
public long File_size() {return file_size;} private long file_size;
public Io_url File_url() {return file_url;} private final Io_url file_url;
public int Len() {return list.Count();}
public void Add(Xou_cache_itm itm) {
if (itm.View_date() > view_date) view_date = itm.View_date();
file_size += itm.File_size();
list.Add(itm);
}
public void Delete(Ordered_hash cache_hash, Xou_cache_tbl cache_tbl) {
int len = list.Count();
boolean deleted = false;
for (int i = 0; i < len; ++i) {
Xou_cache_itm itm = (Xou_cache_itm)list.Get_at(i);
cache_hash.Del(itm.Lnki_key());
itm.Db_state_(Db_cmd_mode.Tid_delete);
cache_tbl.Db_save(itm);
gplx.core.ios.IoItmFil fil = Io_mgr.Instance.QueryFil(itm.File_url());
if (fil.Exists()) {
Io_mgr.Instance.DeleteFil(itm.File_url());
deleted = true;
}
else {
if (!deleted) // multiple itms in cache resolve to same path; 1st gets deleted, but 2nd won't; ignore warning; PAGE:s.w:File:William_Shakespeare_Chandos_Portrait.jpg; DATE:2015-05-23
Xoa_app_.Usr_dlg().Warn_many("", "", "cache:file not found; file=~{0}", itm.File_url().Raw());
}
}
}
public Xou_cache_itm Get_at(int i) {return (Xou_cache_itm)list.Get_at(i);}
}
class Xou_cache_grp_sorter implements gplx.core.lists.ComparerAble {
public int compare(Object lhsObj, Object rhsObj) {
Xou_cache_grp lhs = (Xou_cache_grp)lhsObj;
Xou_cache_grp rhs = (Xou_cache_grp)rhsObj;
return -Long_.Compare(lhs.View_date(), rhs.View_date()); // - for DESC sort
}
public static final Xou_cache_grp_sorter Instance = new Xou_cache_grp_sorter(); Xou_cache_grp_sorter() {}
}

View File

@@ -0,0 +1,114 @@
/*
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.caches; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import org.junit.*; import gplx.dbs.*; import gplx.xowa.files.fsdb.*; import gplx.xowa.files.repos.*;
public class Xou_cache_mgr_tst {
@Before public void init() {fxt.Clear();} private final Xou_cache_mgr_fxt fxt = new Xou_cache_mgr_fxt();
@Test public void Update() {
Xof_fsdb_itm itm_1 = fxt.Make_itm("en.w", "1.png", 2);
fxt.Exec_update(itm_1);
fxt.Test_get(itm_1, 1, 0);
}
@Test public void Update_mult() {
Xof_fsdb_itm itm_1 = fxt.Make_itm("en.w", "1.png", 2);
fxt.Exec_update(itm_1, itm_1, itm_1);
fxt.Test_get(itm_1, 3, 2);
}
@Test public void Reload() {
Xof_fsdb_itm itm_1 = fxt.Make_itm("en.w", "1.png", 2);
fxt.Exec_update(itm_1, itm_1, itm_1);
fxt.Test_get(itm_1, 3, 2);
fxt.Exec_save_and_clear();
fxt.Test_get(itm_1, 3, 2);
}
@Test public void Reduce() {
fxt.Init_delete(3, 5);
Xof_fsdb_itm itm_1 = fxt.Make_itm("en.w", "1.png", 2);
Xof_fsdb_itm itm_2 = fxt.Make_itm("en.w", "2.png", 2);
Xof_fsdb_itm itm_3 = fxt.Make_itm("en.w", "3.png", 2);
fxt.Exec_update(itm_1, itm_2, itm_3);
fxt.Exec_reduce();
fxt.Test_get_y(itm_3);
fxt.Test_get_n(itm_1, itm_2);
}
@Test public void Reduce_same() {
fxt.Init_delete(3, 5);
Xof_fsdb_itm itm_1 = fxt.Make_itm("en.w", "1.png", 2);
Xof_fsdb_itm itm_2 = fxt.Make_itm("fr.w", "1.png", 2);
Xof_fsdb_itm itm_3 = fxt.Make_itm("en.w", "2.png", 2);
fxt.Exec_update(itm_3, itm_2, itm_1);
fxt.Exec_reduce();
fxt.Test_get_y(itm_3);
fxt.Test_get_n(itm_1, itm_2);
}
}
class Xou_cache_mgr_fxt {
private Xou_cache_mgr mgr;
private long cache_min;
public void Clear() {
Datetime_now.Manual_(DateAdp_.new_(1970, 1, 1, 0, 0, 0, 0));
Io_mgr.Instance.InitEngine_mem();
Db_conn_bldr.Instance.Reg_default_mem();
Xoae_app app = Xoa_app_fxt.Make__app__edit();
app.User().User_db_mgr().Init_by_app(Bool_.N, app.Fsys_mgr().Root_dir().GenSubFil_nest("user", "xowa.user.anonymous.sqlite3"));
Xoa_app_fxt.repo_(app, Xoa_app_fxt.Make__wiki__edit(app, "en.wikipedia.org"));
Xoa_app_fxt.repo_(app, Xoa_app_fxt.Make__wiki__edit(app, "fr.wikipedia.org"));
this.mgr = new Xou_cache_mgr(app.Wiki_mgr(), app.Fsys_mgr().File_dir(), app.User().User_db_mgr().Db_file());
}
public void Init_delete(long min, long max) {
cache_min = min;
mgr.Fsys_size_(min, max);
}
public Xof_fsdb_itm Make_itm(String wiki, String file, int size) {
Xof_fsdb_itm rv = new Xof_fsdb_itm();
byte[] wiki_domain = Bry_.new_a7(wiki);
byte[] file_ttl = Bry_.new_a7(file);
rv.Init_at_lnki(Xof_exec_tid.Tid_wiki_page, wiki_domain, file_ttl, Byte_.Zero, 1, 1, 1 ,1, 1, 1);
rv.Init_at_orig(Xof_repo_tid_.Tid__local, wiki_domain, file_ttl, Xof_ext_.new_by_id_(Xof_ext_.Id_png), 120, 120, Bry_.Empty);
rv.File_size_(size);
return rv;
}
public void Exec_update(Xof_fsdb_itm... ary) {
for (Xof_fsdb_itm itm : ary)
mgr.Update(itm);
}
public void Exec_save_and_clear() {
mgr.Db_save();
mgr.Clear();
}
public void Exec_reduce() {
mgr.Reduce(cache_min);
}
public void Test_get(Xof_fsdb_itm fsdb, int expd_view_count, long expd_view_date) {
Xou_cache_itm cache = mgr.Get_or_null(fsdb);
Tfds.Eq(expd_view_count, cache.View_count());
Tfds.Eq(expd_view_date , cache.View_date() / 60); // Tfds.Now increments by 60 seconds
}
public void Test_get_n(Xof_fsdb_itm... ary) {
for (Xof_fsdb_itm itm : ary) {
Xou_cache_itm cache = mgr.Get_or_null(itm);
Tfds.Eq_null(cache, String_.new_u8(itm.Lnki_ttl()));
}
}
public void Test_get_y(Xof_fsdb_itm... ary) {
for (Xof_fsdb_itm itm : ary) {
Xou_cache_itm cache = mgr.Get_or_null(itm);
Tfds.Eq_nullNot(cache, String_.new_u8(itm.Lnki_ttl()));
}
}
}

View File

@@ -0,0 +1,197 @@
/*
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.caches; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.dbs.*;
public class Xou_cache_tbl implements Rls_able {
private String tbl_name = "file_cache"; private final Dbmeta_fld_list flds = new Dbmeta_fld_list();
private String
fld_lnki_wiki_abrv, fld_lnki_ttl, fld_lnki_type, fld_lnki_upright, fld_lnki_w, fld_lnki_h, fld_lnki_time, fld_lnki_page, fld_user_thumb_w
, fld_orig_repo, fld_orig_ttl, fld_orig_ext, fld_orig_w, fld_orig_h
, fld_html_w, fld_html_h, fld_html_time, fld_html_page
, fld_file_is_orig, fld_file_w, fld_file_time, fld_file_page
, fld_file_size, fld_view_count, fld_view_date
;
public String Tbl_name() {return tbl_name;}
public String Fld_orig_ttl() {return fld_orig_ttl;}
private final Db_conn conn; private final Db_stmt_bldr stmt_bldr = new Db_stmt_bldr(); private Db_stmt select_stmt;
private final Bry_bfr lnki_key_bfr = Bry_bfr_.Reset(255);
public Db_conn Conn() {return conn;}
public Xou_cache_tbl(Db_conn conn) {
this.conn = conn;
fld_lnki_wiki_abrv = flds.Add_str("lnki_wiki_abrv", 255);
fld_lnki_ttl = flds.Add_str("lnki_ttl", 255);
fld_lnki_type = flds.Add_int("lnki_type");
fld_lnki_upright = flds.Add_double("lnki_upright");
fld_lnki_w = flds.Add_int("lnki_w");
fld_lnki_h = flds.Add_int("lnki_h");
fld_lnki_time = flds.Add_double("lnki_time");
fld_lnki_page = flds.Add_int("lnki_page");
fld_user_thumb_w = flds.Add_int("user_thumb_w");
fld_orig_repo = flds.Add_int("orig_repo");
fld_orig_ttl = flds.Add_str("orig_ttl", 255);
fld_orig_ext = flds.Add_int("orig_ext");
fld_orig_w = flds.Add_int("orig_w");
fld_orig_h = flds.Add_int("orig_h");
fld_html_w = flds.Add_int("html_w");
fld_html_h = flds.Add_int("html_h");
fld_html_time = flds.Add_double("html_time");
fld_html_page = flds.Add_int("html_page");
fld_file_is_orig = flds.Add_bool("file_is_orig");
fld_file_w = flds.Add_int("file_w");
fld_file_time = flds.Add_double("file_time");
fld_file_page = flds.Add_int("file_page");
fld_file_size = flds.Add_long("file_size");
fld_view_count = flds.Add_int("view_count");
fld_view_date = flds.Add_long("view_date");
stmt_bldr.Conn_(conn, tbl_name, flds, fld_lnki_wiki_abrv, fld_lnki_ttl, fld_lnki_type, fld_lnki_upright, fld_lnki_w, fld_lnki_h, fld_lnki_time, fld_lnki_page, fld_user_thumb_w);
conn.Rls_reg(this);
}
public void Rls() {
select_stmt = Db_stmt_.Rls(select_stmt);
}
public void Create_tbl() {
Dbmeta_tbl_itm meta = Dbmeta_tbl_itm.New(tbl_name, flds
, Dbmeta_idx_itm.new_unique_by_tbl(tbl_name, "main", fld_lnki_wiki_abrv, fld_lnki_ttl, fld_lnki_type, fld_lnki_upright, fld_lnki_w, fld_lnki_h, fld_lnki_time, fld_lnki_page, fld_user_thumb_w)
, Dbmeta_idx_itm.new_normal_by_tbl(tbl_name, "size", fld_file_size)
, Dbmeta_idx_itm.new_normal_by_tbl(tbl_name, "date", fld_view_date)
);
conn.Meta_tbl_create(meta);
}
public Xou_cache_itm Select_one(byte[] lnki_wiki_abrv, byte[] lnki_ttl, int lnki_type, double lnki_upright, int lnki_w, int lnki_h, double lnki_time, int lnki_page, int user_thumb_w) {
if (select_stmt == null) select_stmt = conn.Stmt_select(tbl_name, flds, String_.Ary(fld_lnki_wiki_abrv, fld_lnki_ttl, fld_lnki_type, fld_lnki_upright, fld_lnki_w, fld_lnki_h, fld_lnki_time, fld_lnki_page, fld_user_thumb_w));
Db_rdr rdr = select_stmt.Clear()
.Crt_bry_as_str (fld_lnki_wiki_abrv , lnki_wiki_abrv)
.Crt_bry_as_str (fld_lnki_ttl , lnki_ttl)
.Crt_int (fld_lnki_type , lnki_type)
.Crt_double (fld_lnki_upright , lnki_upright)
.Crt_int (fld_lnki_w , lnki_w)
.Crt_int (fld_lnki_h , lnki_h)
.Crt_double (fld_lnki_time , lnki_time)
.Crt_int (fld_lnki_page , lnki_page)
.Crt_int (fld_user_thumb_w , user_thumb_w)
.Exec_select__rls_manual();
try {return rdr.Move_next() ? new_itm(rdr) : Xou_cache_itm.Null;}
finally {rdr.Rls();}
}
public void Select_all(Bry_bfr fil_key_bldr, Ordered_hash hash) {
hash.Clear();
Db_rdr rdr = conn.Stmt_select(tbl_name, flds, Dbmeta_fld_itm.Str_ary_empty).Exec_select__rls_auto();
try {
while (rdr.Move_next()) {
Xou_cache_itm itm = new_itm(rdr);
hash.Add(itm.Lnki_key(), itm);
}
}
finally {rdr.Rls();}
}
public void Db_save(Xou_cache_itm itm) {
try {
Db_stmt stmt = stmt_bldr.Get(itm.Db_state());
switch (itm.Db_state()) {
case Db_cmd_mode.Tid_create: stmt.Clear(); Db_save_crt(stmt, itm, Bool_.Y); Db_save_val(stmt, itm); stmt.Exec_insert(); break;
case Db_cmd_mode.Tid_update: stmt.Clear(); Db_save_val(stmt, itm); Db_save_crt(stmt, itm, Bool_.N); stmt.Exec_update(); break;
case Db_cmd_mode.Tid_delete: stmt.Clear(); Db_save_crt(stmt, itm, Bool_.N); stmt.Exec_delete(); break;
case Db_cmd_mode.Tid_ignore: break;
default: throw Err_.new_unhandled(itm.Db_state());
}
itm.Db_state_(Db_cmd_mode.Tid_ignore);
} catch (Exception e) {stmt_bldr.Rls(); throw Err_.new_exc(e, "xo", "db_save failed");}
}
@gplx.Internal protected Db_rdr Select_all_for_test() {return conn.Stmt_select(tbl_name, flds, Dbmeta_fld_itm.Str_ary_empty).Exec_select__rls_manual();}
private void Db_save_crt(Db_stmt stmt, Xou_cache_itm itm, boolean insert) {
if (insert) {
stmt.Val_bry_as_str (fld_lnki_wiki_abrv , itm.Lnki_wiki_abrv())
.Val_bry_as_str (fld_lnki_ttl , itm.Lnki_ttl())
.Val_int (fld_lnki_type , itm.Lnki_type())
.Val_double (fld_lnki_upright , itm.Lnki_upright())
.Val_int (fld_lnki_w , itm.Lnki_w())
.Val_int (fld_lnki_h , itm.Lnki_h())
.Val_double (fld_lnki_time , itm.Lnki_time())
.Val_int (fld_lnki_page , itm.Lnki_page())
.Val_int (fld_user_thumb_w , itm.User_thumb_w())
;
}
else {
stmt.Crt_bry_as_str (fld_lnki_wiki_abrv , itm.Lnki_wiki_abrv())
.Crt_bry_as_str (fld_lnki_ttl , itm.Lnki_ttl())
.Crt_int (fld_lnki_type , itm.Lnki_type())
.Crt_double (fld_lnki_upright , itm.Lnki_upright())
.Crt_int (fld_lnki_w , itm.Lnki_w())
.Crt_int (fld_lnki_h , itm.Lnki_h())
.Crt_double (fld_lnki_time , itm.Lnki_time())
.Crt_int (fld_lnki_page , itm.Lnki_page())
.Crt_int (fld_user_thumb_w , itm.User_thumb_w())
;
}
}
private void Db_save_val(Db_stmt stmt, Xou_cache_itm itm) {
byte[] orig_ttl = itm.Orig_ttl(), lnki_ttl = itm.Lnki_ttl();
if (Bry_.Eq(orig_ttl, lnki_ttl)) orig_ttl = Bry_.Empty; // PERF:only store redirects in orig_ttl; DATE:2015-05-14
stmt.Val_int (fld_orig_repo , itm.Orig_repo_id())
.Val_bry_as_str (fld_orig_ttl , orig_ttl)
.Val_int (fld_orig_ext , itm.Orig_ext_id())
.Val_int (fld_orig_w , itm.Orig_w())
.Val_int (fld_orig_h , itm.Orig_h())
.Val_int (fld_html_w , itm.Html_w())
.Val_int (fld_html_h , itm.Html_h())
.Val_double (fld_html_time , itm.Html_time())
.Val_int (fld_html_page , itm.Html_page())
.Val_bool_as_byte (fld_file_is_orig , itm.File_is_orig())
.Val_int (fld_file_w , itm.File_w())
.Val_double (fld_file_time , itm.File_time())
.Val_int (fld_file_page , itm.File_page())
.Val_long (fld_file_size , itm.File_size())
.Val_int (fld_view_count , itm.View_count())
.Val_long (fld_view_date , itm.View_date())
;
}
private Xou_cache_itm new_itm(Db_rdr rdr) {
byte[] lnki_ttl = rdr.Read_bry_by_str (fld_lnki_ttl);
byte[] orig_ttl = rdr.Read_bry_by_str (fld_orig_ttl);
if (orig_ttl.length == 0) orig_ttl = lnki_ttl; // PERF:only store redirects in orig_ttl; DATE:2015-05-14
return new Xou_cache_itm
( lnki_key_bfr
, Db_cmd_mode.Tid_ignore
, rdr.Read_bry_by_str (fld_lnki_wiki_abrv)
, lnki_ttl
, rdr.Read_int (fld_lnki_type)
, rdr.Read_double (fld_lnki_upright)
, rdr.Read_int (fld_lnki_w)
, rdr.Read_int (fld_lnki_h)
, Xof_lnki_time.Db_load_double (rdr, fld_lnki_time)
, Xof_lnki_page.Db_load_int (rdr, fld_lnki_page)
, rdr.Read_int (fld_user_thumb_w)
, rdr.Read_int (fld_orig_repo)
, orig_ttl
, rdr.Read_int (fld_orig_ext)
, rdr.Read_int (fld_orig_w)
, rdr.Read_int (fld_orig_h)
, rdr.Read_int (fld_html_w)
, rdr.Read_int (fld_html_h)
, Xof_lnki_time.Db_load_double (rdr, fld_html_time)
, Xof_lnki_page.Db_load_int (rdr, fld_html_page)
, rdr.Read_bool_by_byte (fld_file_is_orig)
, rdr.Read_int (fld_file_w)
, Xof_lnki_time.Db_load_double (rdr, fld_file_time)
, Xof_lnki_page.Db_load_int (rdr, fld_file_page)
, rdr.Read_long (fld_file_size)
, rdr.Read_int (fld_view_count)
, rdr.Read_long (fld_view_date)
);
}
}

View File

@@ -0,0 +1,61 @@
/*
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.caches; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import org.junit.*; import gplx.dbs.*;
public class Xou_cache_tbl_tst {
@Before public void init() {fxt.Clear();} private final Xou_cache_tbl_fxt fxt = new Xou_cache_tbl_fxt();
@Test public void Orig_ttl__same() {fxt.Test_save_orig_ttl("A.png", "A.png", "");}
@Test public void Orig_ttl__redirect() {fxt.Test_save_orig_ttl("A.png", "B.png", "B.png");}
}
class Xou_cache_tbl_fxt {
private final Bry_bfr lnki_key_bfr = Bry_bfr_.New_w_size(255);
private Xou_cache_tbl tbl;
public void Clear() {
Io_mgr.Instance.InitEngine_mem();
Db_conn_bldr.Instance.Reg_default_mem();
Db_conn_bldr_data conn_data = Db_conn_bldr.Instance.Get_or_new(Io_url_.mem_fil_("mem/test.xowa"));
this.tbl = new Xou_cache_tbl(conn_data.Conn());
tbl.Create_tbl();
}
public Xou_cache_itm Make_itm(String lnki_wiki_abrv_xo, String lnki_ttl, int lnki_type, double lnki_upright, int lnki_w, int lnki_h, double lnki_time, int lnki_page, int user_thumb_w
, int orig_repo_id, String orig_ttl, int orig_ext_id, int orig_w, int orig_h
, int html_w, int html_h, double html_time, int html_page
, boolean file_is_orig, int file_w, double file_time, int file_page, long file_size
, int view_count, long view_date) {
return new Xou_cache_itm(lnki_key_bfr, Db_cmd_mode.Tid_create
, Bry_.new_u8(lnki_wiki_abrv_xo), Bry_.new_u8(lnki_ttl), lnki_type, lnki_upright, lnki_w, lnki_h, lnki_time, lnki_page, user_thumb_w
, orig_repo_id, Bry_.new_u8(orig_ttl), orig_ext_id, orig_w, orig_h
, html_w, html_h, html_time, html_page
, file_is_orig, file_w, file_time, file_page, file_size
, view_count, view_date
);
}
public Xou_cache_itm Exec_select_one(String lnki_wiki_abrv_xo, String lnki_ttl, int lnki_type, double lnki_upright, int lnki_w, int lnki_h, double lnki_time, int lnki_page, int user_thumb_w) {
return tbl.Select_one(Bry_.new_u8(lnki_wiki_abrv_xo), Bry_.new_u8(lnki_ttl), 1, 1, 1, 1, 1, 1, 1);
}
public void Test_save_orig_ttl(String lnki_ttl, String orig_ttl, String expd_orig_ttl) {
Xou_cache_itm itm = Make_itm("en.w", lnki_ttl, 1, 1, 1, 1, 1, 1, 1, 1, orig_ttl, 1, 1, 1, 1, 1, 1, 1, Bool_.Y, 1, 1, 1, 1, 1, 1);
tbl.Db_save(itm);
Db_rdr rdr = tbl.Select_all_for_test();
try {
Tfds.Eq_true(rdr.Move_next());
Tfds.Eq(expd_orig_ttl, rdr.Read_str(tbl.Fld_orig_ttl()));
}
finally {rdr.Rls();}
}
}

View File

@@ -0,0 +1,63 @@
/*
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.caches; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.core.ios.*;
import gplx.xowa.files.origs.*; import gplx.xowa.files.repos.*; import gplx.xowa.files.fsdb.*; import gplx.xowa.files.bins.*; import gplx.xowa.guis.cbks.js.*;
public class Xou_file_itm_finder {
private final Xou_cache_mgr cache_mgr; private final Xof_img_size img_size = new Xof_img_size();
public Xou_file_itm_finder(Xou_cache_mgr cache_mgr) {this.cache_mgr = cache_mgr;}
public boolean Find(Xowe_wiki wiki, int exec_tid, Xof_file_itm xfer, byte[] page_url) {
byte[] lnki_ttl = xfer.Lnki_ttl();
Xof_url_bldr url_bldr = wiki.Parser_mgr().Url_bldr();
try {
if (wiki.File__fsdb_mode().Tid__bld()) return false; // disable during build
Xou_cache_itm cache_itm = cache_mgr.Get_or_null(wiki.Domain_itm().Abrv_xo(), lnki_ttl, xfer.Lnki_type(), xfer.Lnki_upright(), xfer.Lnki_w(), xfer.Lnki_h(), xfer.Lnki_time(), xfer.Lnki_page(), Xof_img_size.Thumb_width_img);
Xof_repo_itm repo = null;
if (cache_itm == null) {// itm not in cache;
Xof_ext lnki_ext = Xof_ext_.new_by_ttl_(lnki_ttl);
if (lnki_ext.Id_is_ogg()) { // look up orig; needed for identifying .ogg to vid for html_wtr to write; PAGE:en.w:WWI; DATE:2015-05-19
Xof_orig_itm orig = wiki.File__orig_mgr().Find_by_ttl_or_null(lnki_ttl);
if (orig != Xof_orig_itm.Null) { // orig found
repo = wiki.File__repo_mgr().Get_trg_by_id_or_null(orig.Repo(), lnki_ttl, page_url);
if (repo != null) {
xfer.Init_at_orig(orig.Repo(), repo.Wiki_domain(), orig.Ttl(), orig.Ext(), orig.W(), orig.H(), orig.Redirect());
img_size.Html_size_calc(exec_tid, xfer.Lnki_w(), xfer.Lnki_h(), (byte)xfer.Lnki_type(), Xof_patch_upright_tid_.Tid_all, xfer.Lnki_upright(), orig.Ext().Id(), orig.W(), orig.H(), Xof_img_size.Thumb_width_img); // calc size for html
xfer.Init_at_gallery_end(img_size.Html_w(), img_size.Html_h(), url_bldr.To_url_trg(repo, xfer, Bool_.N), url_bldr.To_url_trg(repo, xfer, Bool_.Y));
}
}
}
return false;
}
repo = wiki.File__repo_mgr().Get_trg_by_id_or_null(cache_itm.Orig_repo_id(), lnki_ttl, page_url);
if (repo == null) return false; // unknown repo; shouldn't happen, but exit, else null ref
xfer.Init_at_orig((byte)cache_itm.Orig_repo_id(), repo.Wiki_domain(), cache_itm.Orig_ttl(), cache_itm.Orig_ext_itm(), cache_itm.Orig_w(), cache_itm.Orig_h(), Bry_.Empty);
// img_size.Html_size_calc(exec_tid, xfer.Lnki_w(), xfer.Lnki_h(), (byte)xfer.Lnki_type(), Xof_patch_upright_tid_.Tid_all, xfer.Lnki_upright(), cache_itm.Orig_ext_id(), cache_itm.Orig_w(), cache_itm.Orig_h(), Xof_img_size.Thumb_width_img);
// xfer.Init_at_gallery_end(img_size.Html_w(), img_size.Html_h(), url_bldr.To_url_trg(repo, cache_itm, Bool_.N), url_bldr.To_url_trg(repo, cache_itm, Bool_.Y));
xfer.Init_at_html(exec_tid, img_size, repo, url_bldr);
if (Io_mgr.Instance.ExistsFil(xfer.Html_view_url())) {
cache_itm.Update_view_stats();
return true;
}
else
return false;
} catch (Exception e) {
Xoa_app_.Usr_dlg().Warn_many("", "", "failed to find img: img=~{0} err=~{1}", lnki_ttl, Err_.Message_gplx_log(e));
return false;
}
}
}

View File

@@ -0,0 +1,21 @@
/*
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.cnvs; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
public class Xof_cnv_wkr_ {
public static final byte Tid_null = Byte_.Max_value_127, Tid_n = 0, Tid_y = 1;
}

View File

@@ -0,0 +1,22 @@
/*
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.cnvs; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.core.primitives.*;
public interface Xof_img_wkr_resize_img {
boolean Resize_exec(Io_url src, Io_url trg, int trg_w, int trg_h, int ext_id, String_obj_ref rslt_val);
}

View File

@@ -0,0 +1,44 @@
/*
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.cnvs; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.core.primitives.*; import gplx.core.envs.*;
import gplx.xowa.bldrs.wms.*;
public class Xof_img_wkr_resize_img_imageMagick implements Xof_img_wkr_resize_img {
private final Xowmf_mgr wmf_mgr; private final Process_adp cmd_convert, cmd_convert_svg_to_png;
private boolean init_needed = true;
public Xof_img_wkr_resize_img_imageMagick(Xowmf_mgr wmf_mgr, Process_adp cmd_convert, Process_adp cmd_convert_svg_to_png) {
this.wmf_mgr = wmf_mgr; this.cmd_convert = cmd_convert; this.cmd_convert_svg_to_png = cmd_convert_svg_to_png;
}
public boolean Resize_exec(Io_url src, Io_url trg, int trg_w, int trg_h, int ext_id, String_obj_ref rslt_val) {
if (!Io_mgr.Instance.ExistsFil(src)) return false;
Io_mgr.Instance.CreateDirIfAbsent(trg.OwnerDir());
if (init_needed) {
init_needed = false;
Gfo_usr_dlg usr_dlg = Xoa_app_.Usr_dlg();
cmd_convert.Prog_dlg_(usr_dlg);
cmd_convert_svg_to_png.Prog_dlg_(usr_dlg);
}
Process_adp cmd = ext_id == Xof_ext_.Id_svg ? cmd_convert_svg_to_png : cmd_convert;
cmd.Prog_fmt_(String_.Replace(wmf_mgr.Download_wkr().Download_xrg().Prog_fmt_hdr(), "~", "~~") + " converting: ~{process_seconds} second(s); ~{process_exe_name} ~{process_exe_args}");
cmd.Run(src.Raw(), trg.Raw(), trg_w, trg_h);
rslt_val.Val_(cmd.Rslt_out());
boolean rv = cmd.Exit_code_pass();
if (!rv) Xoa_app_.Usr_dlg().Log_many("", "process_warning", "process completed with warnings: ~{0}", cmd.Rslt_out());
return rv; // NOTE: was true (?); DATE:2015-06-16
}
}

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.files.cnvs; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.core.primitives.*;
import gplx.gfui.*; import gplx.gfui.imgs.*;
import gplx.xowa.files.cnvs.*;
public class Xof_img_wkr_resize_img_mok implements Xof_img_wkr_resize_img {
public boolean Resize_exec(Io_url src, Io_url trg, int trg_w, int trg_h, int ext_id, String_obj_ref rslt_val) {
SizeAdp src_size = ImageAdp_.txt_fil_(src).Size();
int src_w = src_size.Width(), src_h = src_size.Height();
if (trg_w < 1) throw Err_.new_wo_type("trg_w must be > 0", "trg_w", trg_w);
if (trg_h < 1) trg_h = Xof_xfer_itm_.Scale_h(src_w, src_h, trg_w);
Io_mgr.Instance.SaveFilStr(trg, SizeAdp_.new_(trg_w, trg_h).To_str());
return true;
}
public static final Xof_img_wkr_resize_img_mok Instance = new Xof_img_wkr_resize_img_mok(); Xof_img_wkr_resize_img_mok() {}
}

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.files.commons; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
public class Xof_commons_image_itm {
public Xof_commons_image_itm(String name, String media_type, String minor_mime, int size, int width, int height, int bits, int ext_id, String timestamp) {
this.name = name; this.media_type = media_type; this.minor_mime = minor_mime; this.size = size; this.width = width; this.height = height; this.bits = bits; this.ext_id = ext_id; this.timestamp = timestamp;
}
public String Name() {return name;} private final String name;
public String Media_type() {return media_type;} private final String media_type;
public String Minor_mime() {return minor_mime;} private final String minor_mime;
public int Size() {return size;} private final int size;
public int Width() {return width;} private final int width;
public int Height() {return height;} private final int height;
public int Bits() {return bits;} private final int bits;
public int Ext_id() {return ext_id;} private final int ext_id;
public String Timestamp() {return timestamp;} private final String timestamp;
}

View File

@@ -0,0 +1,72 @@
/*
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.commons; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.dbs.*;
public class Xof_commons_image_tbl implements Rls_able {
private Db_stmt stmt_insert;
public Db_conn Conn() {return conn;}
public void Conn_(Db_conn v) {
conn = v;
stmt_insert = null;
conn.Rls_reg(this);
} private Db_conn conn;
public void Rls() {
stmt_insert = Db_stmt_.Rls(stmt_insert);
}
public void Insert(String ttl, String media_type, String minor_mime, int size, int w, int h, int bits, int ext_id, String img_timestamp) {
if (stmt_insert == null) stmt_insert = conn.Stmt_insert(tbl_name, flds);
stmt_insert.Clear()
.Val_str(ttl).Val_str(media_type).Val_str(minor_mime)
.Val_int(size).Val_int(w).Val_int(h).Val_int(bits).Val_int(ext_id).Val_str(img_timestamp)
.Exec_insert();
}
public Xof_commons_image_itm Select(byte[] ttl) {
Db_rdr rdr = conn.Stmt_select(tbl_name, flds, fld_img_name).Clear().Val_bry_as_str(ttl).Exec_select__rls_auto();
try {
if (!rdr.Move_next()) return null;
return new Xof_commons_image_itm
( rdr.Read_str(fld_img_name)
, rdr.Read_str(fld_img_media_type)
, rdr.Read_str(fld_img_minor_mime)
, rdr.Read_int(fld_img_size)
, rdr.Read_int(fld_img_width)
, rdr.Read_int(fld_img_height)
, rdr.Read_int(fld_img_bits)
, rdr.Read_int(fld_img_ext_id)
, rdr.Read_str(fld_img_timestamp)
);
} finally {rdr.Rls();}
}
private static final String tbl_name = "image"; private static final Dbmeta_fld_list flds = new Dbmeta_fld_list();
private static final String
fld_img_name = flds.Add_str("img_name", 255) // varbinary(255)
, fld_img_media_type = flds.Add_str("img_media_type", 255) // enum('UNKNOWN','BITMAP','DRAWING','AUDIO','VIDEO','MULTIMEDIA','OFFICE','TEXT','EXECUTABLE','ARCHIVE')"
, fld_img_minor_mime = flds.Add_str("img_minor_mime", 255) // DEFAULT 'unknown'"
, fld_img_size = flds.Add_int("img_size") // int(8) unsigned
, fld_img_width = flds.Add_int("img_width") // int(5)
, fld_img_height = flds.Add_int("img_height") // int(5)
, fld_img_bits = flds.Add_short("img_bits") // int(3)
, fld_img_ext_id = flds.Add_int("img_ext_id") // xowa
, fld_img_timestamp = flds.Add_str("img_timestamp", 255) // 20140101155749
;
public static Dbmeta_tbl_itm new_meta() {
return Dbmeta_tbl_itm.New(tbl_name, flds.To_fld_ary()
, Dbmeta_idx_itm.new_normal_by_tbl(tbl_name, "name", fld_img_name, fld_img_timestamp)
);
}
}

View File

@@ -0,0 +1,23 @@
/*
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.downloads; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.core.ios.*;
public interface Xof_download_wkr {
byte Download(boolean src_is_web, String src, Io_url trg, String prog_fmt_hdr);
IoEngine_xrg_downloadFil Download_xrg();
}

View File

@@ -0,0 +1,40 @@
/*
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.downloads; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.core.ios.*;
public class Xof_download_wkr_io implements Xof_download_wkr {
IoEngine_xrg_downloadFil xrg = Io_mgr.Instance.DownloadFil_args("", Io_url_.Empty);
public IoEngine_xrg_downloadFil Download_xrg() {return xrg;}
public String Download_err() {return download_err;} private String download_err = "";
public byte Download(boolean src_is_web, String src_str, Io_url trg_url, String prog_fmt_hdr) {
download_err = "";
if (src_is_web) {
xrg.Prog_fmt_hdr_(prog_fmt_hdr);
xrg.Init(src_str, trg_url);
xrg.Exec();
return xrg.Rslt();
}
else {
Io_url src_url = Io_url_.new_fil_(src_str);
if (!Io_mgr.Instance.ExistsFil(src_url)) return IoEngine_xrg_downloadFil.Rslt_fail_file_not_found;
try {Io_mgr.Instance.CopyFil(src_url, trg_url, true);}
catch (Exception exc) {Err_.Noop(exc); return IoEngine_xrg_downloadFil.Rslt_fail_unknown;}
return IoEngine_xrg_downloadFil.Rslt_pass;
}
}
}

View File

@@ -0,0 +1,30 @@
/*
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.downloads; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.core.ios.*;
public class Xof_download_wkr_test implements Xof_download_wkr {
public IoEngine_xrg_downloadFil Download_xrg() {return IoEngine_xrg_downloadFil.new_("", Io_url_.Empty).Trg_engine_key_(IoEngine_.MemKey);}
public byte Download(boolean src_is_web, String src_str, Io_url trg_url, String prog_fmt_hdr) {
Io_mgr.Instance.CreateDirIfAbsent(trg_url.OwnerDir());
Io_url src_url = Io_url_.new_fil_(src_str);
if (!Io_mgr.Instance.ExistsFil(src_url)) return IoEngine_xrg_downloadFil.Rslt_fail_file_not_found;
try {Io_mgr.Instance.CopyFil(src_url, trg_url, true);}
catch (Exception exc) {Err_.Noop(exc); return IoEngine_xrg_downloadFil.Rslt_fail_unknown;}
return IoEngine_xrg_downloadFil.Rslt_pass;
}
}

View File

@@ -0,0 +1,42 @@
/*
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.exts; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.core.primitives.*;
public class Xof_rule_grp implements Gfo_invk {
private final Hash_adp_bry hash = Hash_adp_bry.cs();
public Xof_rule_grp(Xof_rule_mgr owner, byte[] key) {this.owner = owner; this.key = key;}
public Xof_rule_mgr Owner() {return owner;} private final Xof_rule_mgr owner;
public byte[] Key() {return key;} private final byte[] key;
public Xof_rule_itm Get_or_null(byte[] ext_bry) {return (Xof_rule_itm)hash.Get_by_bry(ext_bry);}
public Xof_rule_itm Get_or_new(byte[] ext_bry) {
Xof_rule_itm rv = Get_or_null(ext_bry);
if (rv == null) {
Xof_ext ext = Xof_ext_.new_by_ext_(ext_bry);
rv = new Xof_rule_itm(this, ext);
hash.Add(ext_bry, rv);
}
return rv;
}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_owner)) return owner;
else if (ctx.Match(k, Invk_set)) return Get_or_new(Bry_.new_u8(m.ReadStr("v")));
else return Gfo_invk_.Rv_unhandled;
} private static final String Invk_owner = "owner", Invk_set = "set";
private static final String Grp_app_default_str = "app_default";
public static byte[] Grp_app_default = Bry_.new_u8(Grp_app_default_str);
}

View File

@@ -0,0 +1,33 @@
/*
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.exts; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.xowa.apps.*;
public class Xof_rule_itm implements Gfo_invk {
public Xof_rule_itm(Xof_rule_grp owner, Xof_ext ext) {this.owner = owner;} // NOTE: ext currently not used; may want to set as property in future; DATE:2015-02-14
public Xof_rule_grp Owner() {return owner;} private Xof_rule_grp owner;
public long Make_max() {return make_max;} public Xof_rule_itm Make_max_(long v) {make_max = v; return this;} long make_max = Max_wildcard;
public long View_max() {return view_max;} public Xof_rule_itm View_max_(long v) {view_max = v; return this;} long view_max = Max_wildcard;
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_owner)) return owner;
else if (ctx.Match(k, Invk_make_max_)) make_max = gplx.core.ios.Io_size_.Load_int_(m);
else if (ctx.Match(k, Invk_view_max_)) view_max = gplx.core.ios.Io_size_.Load_int_(m);
else return Gfo_invk_.Rv_unhandled;
return this;
} private static final String Invk_owner = "owner", Invk_make_max_ = "make_max_", Invk_view_max_ = "view_max_";
public static final long Max_wildcard = -1;
}

View File

@@ -0,0 +1,45 @@
/*
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.exts; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.xowa.apps.*;
public class Xof_rule_mgr implements Gfo_invk {
private final Hash_adp_bry hash = Hash_adp_bry.cs();
public Xof_rule_mgr() {
Xof_rule_grp app_default = new Xof_rule_grp(this, Xof_rule_grp.Grp_app_default);
Set_app_default(app_default, Io_mgr.Len_gb, Xof_ext_.Bry__ary);
hash.Add(Xof_rule_grp.Grp_app_default, app_default);
}
private Xof_rule_grp Get_or_null(byte[] key) {return (Xof_rule_grp)hash.Get_by_bry(key);}
public Xof_rule_grp Get_or_new(byte[] key) {
Xof_rule_grp rv = Get_or_null(key);
if (rv == null) {
rv = new Xof_rule_grp(this, key);
hash.Add(key, rv);
}
return rv;
}
private static void Set_app_default(Xof_rule_grp app_default, long make_max, byte[][] keys) {
int len = keys.length;
for (int i = 0; i < len; i++)
app_default.Get_or_new(keys[i]).Make_max_(make_max);
}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_set)) return Get_or_new(Bry_.new_u8(m.ReadStr("v")));
else return Gfo_invk_.Rv_unhandled;
} private static final String Invk_set = "set";
}

View File

@@ -0,0 +1,78 @@
/*
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.fsdb; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.core.stores.*;
import gplx.dbs.*;
class Fsdb_regy_fil_tbl {
public Fsdb_regy_fil_itm Select(String name, boolean is_orig, int w, int thumbtime) {
return null;
}
public static final String Tbl_sql = String_.Concat_lines_nl
( "CREATE TABLE regy_fil"
, "( regy_id integer NOT NULL PRIMARY KEY AUTOINCREMENT"
, ", wiki_type_id integer"
, ", wiki_date_id integer"
, ", fil_name varchar(255)"
, ", fil_is_orig tinyint"
, ", fil_w integer"
, ", fil_h integer"
, ", fil_thumbtime integer"
, ", fil_ext integer"
, ", fil_size bigint"
, ", bin_db_id integer"
, ", fil_id integer"
, ", bin_id integer"
, ");"
);
public static final String
Fld_wiki_type_id = "wiki_type_id", Fld_wiki_date_id = "wiki_date_id", Fld_fil_name = "fil_name", Fld_fil_is_orig = "fil_is_orig"
, Fld_fil_w = "fil_w", Fld_fil_h = "fil_h", Fld_fil_thumbtime = "fil_thumbtime", Fld_fil_ext = "fil_ext", Fld_fil_size = "fil_size"
, Fld_bin_db_id = "bin_db_id", Fld_fil_id = "fil_id", Fld_bin_id = "bin_id"
;
public static final Db_idx_itm
Idx_ttl = Db_idx_itm.sql_("CREATE INDEX IF NOT EXISTS fsdb_fil_regy__fil ON fsdb (fil_name, fil_is_orig, fil_w, fil_h, fil_thumbtime, bin_db_id, fil_id, bin_id);")
;
}
class Fsdb_regy_fil_itm {
public int Wiki_type_id() {return wiki_type_id;} private int wiki_type_id;
public int Wiki_date_id() {return wiki_date_id;} private int wiki_date_id;
public String Fil_name() {return fil_name;} private String fil_name;
public boolean Fil_is_orig() {return fil_is_orig;} private boolean fil_is_orig;
public int Fil_w() {return fil_w;} private int fil_w;
public int Fil_h() {return fil_h;} private int fil_h;
public int Fil_thumbtime() {return fil_thumbtime;} private int fil_thumbtime;
public int Fil_ext() {return fil_ext;} private int fil_ext;
public long Fil_size() {return fil_size;} private long fil_size;
public int Bin_db_id() {return bin_db_id;} private int bin_db_id;
public int Fil_id() {return fil_id;} private int fil_id;
public int Bin_id() {return bin_id;} private int bin_id;
public void Load(DataRdr rdr) {
wiki_date_id = rdr.ReadInt(Fsdb_regy_fil_tbl.Fld_wiki_date_id);
wiki_type_id = rdr.ReadInt(Fsdb_regy_fil_tbl.Fld_wiki_type_id);
fil_name = rdr.ReadStr(Fsdb_regy_fil_tbl.Fld_fil_name);
fil_is_orig = rdr.ReadByte(Fsdb_regy_fil_tbl.Fld_fil_is_orig) != Byte_.Zero;
fil_w = rdr.ReadInt(Fsdb_regy_fil_tbl.Fld_fil_w);
fil_h = rdr.ReadInt(Fsdb_regy_fil_tbl.Fld_fil_h);
fil_thumbtime = rdr.ReadInt(Fsdb_regy_fil_tbl.Fld_fil_thumbtime);
fil_ext = rdr.ReadInt(Fsdb_regy_fil_tbl.Fld_fil_ext);
fil_size = rdr.ReadLong(Fsdb_regy_fil_tbl.Fld_fil_size);
bin_db_id = rdr.ReadInt(Fsdb_regy_fil_tbl.Fld_bin_db_id);
fil_id = rdr.ReadInt(Fsdb_regy_fil_tbl.Fld_fil_id);
bin_id = rdr.ReadInt(Fsdb_regy_fil_tbl.Fld_bin_id);
}
}

View File

@@ -0,0 +1,26 @@
/*
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.fsdb; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
public interface Xof_fsdb_mgr {
String Key();
gplx.xowa.files.bins.Xof_bin_mgr Bin_mgr();
gplx.fsdb.meta.Fsm_mnt_mgr Mnt_mgr();
void Init_by_wiki(Xow_wiki wiki);
void Fsdb_search_by_list(List_adp itms, Xow_wiki wiki, Xoa_page page, gplx.xowa.guis.cbks.js.Xog_js_wkr js_wkr);
void Rls();
}

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.files.fsdb; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.core.primitives.*;
import gplx.core.ios.*;
import gplx.dbs.*; import gplx.xowa.wikis.data.*;
import gplx.fsdb.*; import gplx.fsdb.meta.*;
import gplx.xowa.files.*; import gplx.xowa.files.repos.*; import gplx.xowa.files.imgs.*; import gplx.xowa.files.origs.*; import gplx.xowa.files.bins.*; import gplx.xowa.files.caches.*; import gplx.xowa.guis.cbks.js.*;
public class Xof_fsdb_mgr__sql implements Xof_fsdb_mgr, Gfo_invk {
private boolean init = false; private boolean fsdb_enabled = false;
private Xow_repo_mgr repo_mgr; private Xof_url_bldr url_bldr; private final Xof_img_size img_size = new Xof_img_size();
public String Key() {return "fsdb.sql";}
public Xof_bin_mgr Bin_mgr() {return bin_mgr;} private Xof_bin_mgr bin_mgr;
public Fsm_mnt_mgr Mnt_mgr() {return mnt_mgr;} private Fsm_mnt_mgr mnt_mgr = new Fsm_mnt_mgr();
public void Init_by_wiki(Xow_wiki wiki) {
if (init) return;
try {
init = true;
// if (wiki.File__fsdb_mode().Tid_v0()) return;
this.url_bldr = Xof_url_bldr.new_v2();
this.repo_mgr = wiki.File__repo_mgr();
Fsdb_db_mgr fsdb_core = wiki.File__fsdb_core();
// Fsdb_db_mgr fsdb_core = Fsdb_db_mgr_.new_detect(wiki, wiki.Fsys_mgr().Root_dir(), wiki.Fsys_mgr().File_dir());
if (fsdb_core == null) return;
fsdb_enabled = true;
mnt_mgr.Ctor_by_load(fsdb_core);
this.bin_mgr = new Xof_bin_mgr(mnt_mgr, repo_mgr, wiki.App().File__img_mgr().Wkr_resize_img(), wiki.App().Wmf_mgr().Download_wkr().Download_xrg().Download_fmt());
bin_mgr.Wkrs__add(Xof_bin_wkr__fsdb_sql.new_(mnt_mgr));
bin_mgr.Wkrs__add(Xof_bin_wkr__http_wmf.new_(wiki));
} catch (Exception e) {throw Err_.new_exc(e, "xo", "failed to initialize fsdb_mgr}", "wiki", wiki.Domain_str());}
}
public void Fsdb_search_by_list(List_adp itms, Xow_wiki cur_wiki, Xoa_page page, Xog_js_wkr js_wkr) {
if (!fsdb_enabled) return;
int len = itms.Count();
Gfo_usr_dlg usr_dlg = Gfo_usr_dlg_.Instance;
Xow_wiki wiki = page.Commons_mgr().Source_wiki_or(cur_wiki);
Xou_cache_mgr cache_mgr = wiki.App().User().User_db_mgr().Cache_mgr();
for (int i = 0; i < len; i++) {
if (usr_dlg.Canceled()) return;
Xof_fsdb_itm fsdb = (Xof_fsdb_itm)itms.Get_at(i);
if (fsdb.Hdump_mode() == Xof_fsdb_itm.Hdump_mode__null) {
Xof_orig_itm orig = wiki.File__orig_mgr().Find_by_ttl_or_null(fsdb.Lnki_ttl(), i, len);
if (orig != Xof_orig_itm.Null) { // orig exists;
gplx.xowa.files.repos.Xof_repo_itm repo = wiki.File__repo_mgr().Get_trg_by_id_or_null(orig.Repo(), fsdb.Lnki_ttl(), Bry_.Empty);
if (repo == null) continue;
fsdb.Init_at_orig(orig.Repo(), repo.Wiki_domain(), orig.Ttl(), orig.Ext(), orig.W(), orig.H(), orig.Redirect());
}
}
fsdb.Init_at_xfer(i, len);
Xof_file_wkr.Show_img(fsdb, usr_dlg, wiki.File__bin_mgr(), wiki.File__mnt_mgr(), cache_mgr, wiki.File__repo_mgr(), js_wkr, img_size, url_bldr, page);
}
}
public void Rls() {
if (bin_mgr != null) bin_mgr.Rls();
init = false;
}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_mnt_mgr)) return mnt_mgr;
else return Gfo_invk_.Rv_unhandled;
} private static final String Invk_mnt_mgr = "mnt_mgr";
}

View File

@@ -0,0 +1,27 @@
/*
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.fsdb; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
public class Xof_fsdb_mgr_cfg {
public static final String
Grp_xowa = "xowa"
, Key_gallery_fix_defaults = "gallery.fix_defaults"
, Key_gallery_packed = "gallery.packed"
, Key_upright_use_thumb_w = "file.upright_ignores_lnki_w"
, Key_upright_fix_default = "file.upright_fix_default"
;
}

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.files.fsdb.fs_roots; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*; import gplx.xowa.files.fsdb.*;
import gplx.xowa.guis.cbks.js.*;
public class Fs_root_core implements Xof_fsdb_mgr, Gfo_invk { // reads images from file-system dir
private Xowe_wiki wiki;
private final Fs_root_mgr mgr;
public Fs_root_core(Xowe_wiki wiki) {
this.Init_by_wiki(wiki);
this.mgr = new Fs_root_mgr(wiki);
}
public String Key() {return Fsdb_mgr_key;}
public gplx.xowa.files.bins.Xof_bin_mgr Bin_mgr() {throw Err_.new_unimplemented();}
public gplx.fsdb.meta.Fsm_mnt_mgr Mnt_mgr() {return null;}
public void Init_by_wiki(Xow_wiki wiki) {
this.wiki = (Xowe_wiki)wiki;
}
public Io_url Get_orig_url_or_null(byte[] lnki_ttl) {
Orig_fil_row rv = mgr.Wkr().Get_by_ttl(lnki_ttl);
return rv == null ? null : rv.Url();
}
public void Orig_dir_(Io_url v) {mgr.Orig_dir_(v);}
public void Fsdb_search_by_list(List_adp itms, Xow_wiki wiki, Xoa_page page, Xog_js_wkr js_wkr) {
int itms_len = itms.Count();
// NOTE: do not cache in /xowa/file b/c files will already exist in /xowa/wiki/wiki_name/file/thumb
gplx.xowa.files.caches.Xou_cache_mgr cache_mgr = wiki.App().User().User_db_mgr().Cache_mgr();
for (int i = 0; i < itms_len; i++) {
Xof_fsdb_itm itm = (Xof_fsdb_itm)itms.Get_at(i);
if (mgr.Find_file(itm)) {
Js_img_mgr.Update_img(page, js_wkr, itm);
cache_mgr.Update(itm);
}
}
cache_mgr.Db_save();
}
public void Rls() {}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_root_dir_)) mgr.Root_dir_(To_url(m.ReadBry("v")));
else if (ctx.Match(k, Invk_orig_dir_)) mgr.Orig_dir_(To_url(m.ReadBry("v")));
else if (ctx.Match(k, Invk_thumb_dir_)) {}
else return Gfo_invk_.Rv_unhandled;
return this;
}
private static final String Invk_root_dir_ = "root_dir_", Invk_orig_dir_ = "orig_dir_", Invk_thumb_dir_ = "thumb_dir_";
private Io_url To_url(byte[] v) {
if (gplx.core.envs.Op_sys.Cur().Tid_is_wnt())
v = Bry_.Replace(v, Byte_ascii.Slash, Byte_ascii.Backslash);
return gplx.core.brys.fmtrs.Bry_fmtr_eval_mgr_.Eval_url(wiki.Appe().Url_cmd_eval(), v);
}
public static Fs_root_core Set_fsdb_mgr(Xow_file_mgr file_mgr, Xowe_wiki wiki) {
Fs_root_core rv = new Fs_root_core(wiki);
file_mgr.Fsdb_mgr_(rv);
file_mgr.Orig_mgr().Wkrs__del(gplx.xowa.files.origs.Xof_orig_wkr_.Tid_wmf_api);
file_mgr.Orig_mgr().Wkrs__set(new Xof_orig_wkr__fs_root(rv.mgr.Wkr()));
return rv;
}
public static final String Fsdb_mgr_key = "fs.dir";
}

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.files.fsdb.fs_roots; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*; import gplx.xowa.files.fsdb.*;
import gplx.core.primitives.*; import gplx.dbs.*; import gplx.dbs.cfgs.*;
import gplx.xowa.files.*; import gplx.xowa.files.repos.*; import gplx.fsdb.meta.*;
class Fs_root_mgr {
private final Xowe_wiki wiki;
private final Fs_root_wkr wkr = new Fs_root_wkr();
private final Xof_url_bldr url_bldr = Xof_url_bldr.new_v2();
private final Xof_img_size img_size = new Xof_img_size();
private final String_obj_ref tmp_resize_result = String_obj_ref.null_();
private Xof_repo_itm repo;
private Io_url orig_dir;
public Fs_root_mgr(Xowe_wiki wiki) {
this.wiki = wiki;
}
public Fs_root_wkr Wkr() {return wkr;}
public boolean Find_file(Xof_fsdb_itm fsdb_itm) {
// get orig; exit if not found in dir
byte[] orig_ttl = fsdb_itm.Orig_ttl();
Orig_fil_row orig_itm = wkr.Get_by_ttl(orig_ttl);
if (orig_itm == Orig_fil_row.Null) return false;
// update fsdb.orig metadata
Xof_ext orig_ext = Xof_ext_.new_by_id_(orig_itm.Ext_id());
fsdb_itm.Init_at_orig(Xof_repo_tid_.Tid__local, wiki.Domain_bry(), orig_ttl, orig_ext, orig_itm.W(), orig_itm.H(), null);
// gen cache_orig_url
if (repo == null) repo = wiki.File__repo_mgr().Repos_get_by_wiki(wiki.Domain_bry()).Trg(); // assert repo
Io_url cache_orig_url = url_bldr.To_url_trg(repo, fsdb_itm, Bool_.Y);
fsdb_itm.Html_orig_url_(cache_orig_url);
// update html_w, html_h, html_orig_url, html_view_url
Io_url actl_orig_url = orig_itm.Url();
fsdb_itm.Init_at_html(Xof_exec_tid.Tid_wiki_page, img_size, repo, url_bldr);
// if cache_file doesn't exist, either copy file
if (fsdb_itm.File_is_orig()) {
// copy orig to cache
if (!Io_mgr.Instance.ExistsFil(cache_orig_url)) {
Io_mgr.Instance.CopyFil(actl_orig_url, cache_orig_url, false);
fsdb_itm.File_size_(Io_mgr.Instance.QueryFil(actl_orig_url).Size()); // set size for file_cache, else clear_cache won't delete items with 0 size
}
}
else {
// make thumb by imagemagick
Io_url cache_thumb_url = url_bldr.To_url_trg(repo, fsdb_itm, Bool_.N);
if (!Io_mgr.Instance.ExistsFil(cache_thumb_url)) {
if (!wiki.Appe().File_mgr().Img_mgr().Wkr_resize_img().Resize_exec(actl_orig_url, cache_thumb_url, fsdb_itm.Html_w(), fsdb_itm.Html_h(), fsdb_itm.Orig_ext().Id(), tmp_resize_result))
return false;
fsdb_itm.File_size_(Io_mgr.Instance.QueryFil(cache_thumb_url).Size()); // set size for file_cache, else clear_cache won't delete items with 0 size
}
}
return true;
}
public void Root_dir_(Io_url v) {
Io_url root_dir = v;
orig_dir = root_dir.GenSubDir("orig");
orig_dir_mgr_init(orig_dir);
}
public void Orig_dir_(Io_url v) {
orig_dir = v;
orig_dir_mgr_init(orig_dir);
}
private void orig_dir_mgr_init(Io_url orig_dir) {
wkr.Init(wiki.Appe().File_mgr().Img_mgr().Wkr_query_img_size(), orig_dir);
}
}

View File

@@ -0,0 +1,139 @@
/*
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.fsdb.fs_roots; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*; import gplx.xowa.files.fsdb.*;
import gplx.core.primitives.*;
import gplx.dbs.*; import gplx.dbs.cfgs.*; import gplx.gfui.*;
import gplx.fsdb.meta.*; import gplx.xowa.files.imgs.*;
class Fs_root_wkr {
private Xof_img_wkr_query_img_size img_size_wkr;
private Io_url orig_dir; private boolean recurse = true;
private Orig_fil_mgr cache = new Orig_fil_mgr(), fs_fil_mgr;
private Db_conn conn; private Db_cfg_tbl cfg_tbl;
private Orig_fil_tbl orig_tbl;
private int fil_id_next = 0;
public Orig_fil_tbl Orig_tbl() {return orig_tbl;}
public void Init(Xof_img_wkr_query_img_size img_size_wkr, Io_url orig_dir) {
this.img_size_wkr = img_size_wkr;
this.orig_dir = orig_dir;
}
public Orig_fil_row Get_by_ttl(byte[] lnki_ttl) {
Orig_fil_row rv = (Orig_fil_row)cache.Get_by_ttl(lnki_ttl);
if (rv == null) {
// not in mem; get from db
rv = Get_from_db(lnki_ttl);
// not in db; get from fsys
if (rv == null) {
rv = Get_from_fs(lnki_ttl);
if (rv == null) return Orig_fil_row.Null;
}
cache.Add(rv);
}
return rv;
}
private Orig_fil_row Get_from_db(byte[] lnki_ttl) {
if (conn == null) conn = Init_orig_db();
return orig_tbl.Select_itm_or_null(orig_dir, lnki_ttl);
}
private Orig_fil_row Get_from_fs(byte[] lnki_ttl) {
if (fs_fil_mgr == null) fs_fil_mgr = Init_fs_fil_mgr();
Orig_fil_row rv = fs_fil_mgr.Get_by_ttl(lnki_ttl);
if (rv == null) return Orig_fil_row.Null; // not in fs
SizeAdp img_size = SizeAdp_.Zero;
if (Xof_ext_.Id_is_image(rv.Ext_id()))
img_size = img_size_wkr.Exec(rv.Url());
rv.Init_by_fs(++fil_id_next, img_size.Width(), img_size.Height());
cfg_tbl.Update_int(Cfg_grp_root_dir, Cfg_key_fil_id_next, fil_id_next);
String fil_orig_dir = "~{orig_dir}" + rv.Url().OwnerDir().GenRelUrl_orEmpty(orig_dir); // converts "/xowa/wiki/custom_wiki/file/orig/7/70/A.png" -> "~{orig_dir}7/70/"
orig_tbl.Insert(rv, fil_orig_dir);
return rv;
}
private Orig_fil_mgr Init_fs_fil_mgr() { // NOTE: need to read entire dir, b/c ttl may be "A.png", but won't know which subdir
Orig_fil_mgr rv = new Orig_fil_mgr();
Io_url orig_changes_log = orig_dir.GenSubFil("xowa.orig.changes.log");
// loop over all fils in orig_dir
Io_url[] fils = Io_mgr.Instance.QueryDir_args(orig_dir).Recur_(recurse).ExecAsUrlAry();
int fils_len = fils.length;
for (int i = 0; i < fils_len; i++) {
Io_url fil = fils[i];
byte[] fil_name_bry = Bry_.new_u8(fil.NameAndExt());
String orig_change_type = null;
// if url has space, replace it with underscore
if (Bry_.Has(fil_name_bry, Byte_ascii.Space)) {
fil_name_bry = Bry_.Replace(fil_name_bry, Byte_ascii.Space, Byte_ascii.Underline);
orig_change_type = "space_to_underscore";
}
// TOMBSTONE: code below had unit_test, but not sure if needed; file's title should be title-cased, but it's possible to be lower-case for "File:" namespaces with case_match; DATE:2017-02-01
// if url's first char is lowercase, uppercase it;
// byte b_0 = fil_name_bry[0];
// if (b_0 >= Byte_ascii.Ltr_a && b_0 <= Byte_ascii.Ltr_z) {
// fil_name_bry = Bry_.Ucase__1st(fil_name_bry);
// orig_change_type = "ucase_1st";
// }
// if changed above, rename it and log it
if (orig_change_type != null) {
Io_url new_url = fil.GenNewNameAndExt(String_.new_u8(fil_name_bry));
Io_mgr.Instance.MoveFil_args(fil, new_url, true).Exec();
Io_mgr.Instance.AppendFilStr(orig_changes_log, orig_change_type + "|" + fil.Raw() + "\n");
fil = new_url;
}
// if file already seen, ignore it
Orig_fil_row fil_itm = rv.Get_by_ttl(fil_name_bry);
if (fil_itm != Orig_fil_row.Null) {
Gfo_usr_dlg_.Instance.Warn_many("", "", "file already exists: cur=~{0} new=~{1}", fil_itm.Url().Raw(), fil.Raw());
continue;
}
// add it to cache
Xof_ext ext = Xof_ext_.new_by_ttl_(fil_name_bry);
fil_itm = Orig_fil_row.New_by_fs(fil, fil_name_bry, ext.Id());
rv.Add(fil_itm);
}
return rv;
}
private Db_conn Init_orig_db() {
Io_url orig_db = orig_dir.GenSubFil("^orig_regy.sqlite3");
boolean created = false; boolean schema_is_1 = Bool_.Y;
Db_conn conn = Db_conn_bldr.Instance.Get(orig_db);
if (conn == null) {
conn = Db_conn_bldr.Instance.New(orig_db);
created = true;
}
cfg_tbl = new Db_cfg_tbl(conn, schema_is_1 ? "fsdb_cfg" : gplx.xowa.wikis.data.Xowd_cfg_tbl_.Tbl_name);
orig_tbl = new Orig_fil_tbl(conn, schema_is_1);
if (created) {
cfg_tbl.Create_tbl();
cfg_tbl.Insert_int(Cfg_grp_root_dir, Cfg_key_fil_id_next, fil_id_next);
orig_tbl.Create_tbl();
}
else {
fil_id_next = cfg_tbl.Select_int(Cfg_grp_root_dir, Cfg_key_fil_id_next);
}
return conn;
}
public void Rls() {
cfg_tbl.Rls();
orig_tbl.Rls();
}
private static final String Cfg_grp_root_dir = "xowa.root_dir", Cfg_key_fil_id_next = "fil_id_next";
public static final String Url_orig_dir = "~{orig_dir}";
}

View File

@@ -0,0 +1,84 @@
/*
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.fsdb.fs_roots; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*; import gplx.xowa.files.fsdb.*;
import org.junit.*;
import gplx.dbs.*; import gplx.dbs.cfgs.*; import gplx.xowa.files.imgs.*;
import gplx.fsdb.meta.*;
public class Fs_root_wkr_tst {
@Before public void init() {fxt.Reset();} private Fs_root_wkr_fxt fxt = new Fs_root_wkr_fxt();
@Test public void Basic() {
fxt.Init_fs("mem/dir/7/70/A.png", 200, 100);
fxt.Test_get("A.png", fxt.itm_().Url_("mem/dir/7/70/A.png").Size_(200, 100));
fxt.Test_db("A.png", fxt.itm_().Init(1, "mem/dir/7/70/A.png", 200, 100));
}
@Test public void Recurse() {
fxt.Init_fs("mem/dir/A/A1.png", 200, 100);
fxt.Test_get("A1.png", fxt.itm_().Url_("mem/dir/A/A1.png").Size_(200, 100));
}
}
class Fs_root_wkr_fxt {
private Fs_root_wkr root_dir = new Fs_root_wkr();
private Io_url url;
public void Reset() {
Db_conn_bldr.Instance.Reg_default_mem();
Io_mgr.Instance.InitEngine_mem();
url = Io_url_.mem_dir_("mem/dir/");
root_dir = new Fs_root_wkr();
Xof_img_wkr_query_img_size img_size_wkr = new Xof_img_wkr_query_img_size_test();
root_dir.Init(img_size_wkr, url);
}
public Orig_fil_mok itm_() {return new Orig_fil_mok();}
public void Init_fs(String url, int w, int h) {Save_img(url, w, h);}
public void Test_get(String name, Orig_fil_mok expd) {
Orig_fil_row actl = root_dir.Get_by_ttl(Bry_.new_u8(name));
expd.Test(actl);
}
public void Test_db(String ttl, Orig_fil_mok expd) {
Orig_fil_row actl = root_dir.Orig_tbl().Select_itm_or_null(url, Bry_.new_u8(ttl));
expd.Test(actl);
}
public static void Save_img(String url, int w, int h) {
gplx.gfui.SizeAdp img_size = gplx.gfui.SizeAdp_.new_(w, h);
Io_mgr.Instance.SaveFilStr(url, img_size.To_str());
}
}
class Orig_fil_mok {
private int uid = -1;
private int ext_id = -1;
private String name = null;
private int w = -1;
private int h = -1;
public Orig_fil_mok Url_(String v) {url = v; return this;} private String url = null;
public Orig_fil_mok Size_(int w, int h) {this.w = w; this.h = h; return this;}
public Orig_fil_mok Init(int uid, String url, int w, int h) {
this.uid = uid;
this.url = url; this.w = w; this.h = h;
this.name = Io_url_.new_any_(url).NameAndExt();
this.ext_id = Xof_ext_.new_by_ttl_(Bry_.new_u8(name)).Id();
return this;
}
public void Test(Orig_fil_row actl) {
if (actl == null) Tfds.Fail("actl itm is null");
if (w != -1) Tfds.Eq(w, actl.W());
if (h != -1) Tfds.Eq(h, actl.H());
if (url != null) Tfds.Eq(url, actl.Url().Raw());
if (uid != -1) Tfds.Eq(uid, actl.Uid());
if (ext_id != -1) Tfds.Eq(uid, actl.Ext_id());
if (name != null) Tfds.Eq(name, String_.new_u8(actl.Name()));
}
}

View File

@@ -0,0 +1,24 @@
/*
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.fsdb.fs_roots; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*; import gplx.xowa.files.fsdb.*;
class Orig_fil_mgr {
private final Ordered_hash hash = Ordered_hash_.New_bry();
public boolean Has(byte[] lnki_ttl) {return hash.Has(lnki_ttl);}
public Orig_fil_row Get_by_ttl(byte[] lnki_ttl) {return (Orig_fil_row)hash.Get_by(lnki_ttl);}
public void Add(Orig_fil_row fil) {hash.Add(fil.Name(), fil);}
}

View File

@@ -0,0 +1,47 @@
/*
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.fsdb.fs_roots; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*; import gplx.xowa.files.fsdb.*;
class Orig_fil_row {
Orig_fil_row(int uid, byte[] name, int ext_id, int w, int h, Io_url url) {
this.uid = uid;
this.name = name;
this.ext_id = ext_id;
this.w = w;
this.h = h;
this.url = url;
}
public int Uid() {return uid;} private int uid;
public byte[] Name() {return name;} private final byte[] name;
public int Ext_id() {return ext_id;} private final int ext_id;
public int W() {return w;} private int w;
public int H() {return h;} private int h;
public Io_url Url() {return url;} private final Io_url url;
public Orig_fil_row Init_by_fs(int uid, int w, int h) {
this.uid = uid; this.w = w; this.h = h;
return this;
}
public static final Orig_fil_row Null = null;
public static Orig_fil_row New_by_db(int uid, byte[] name, int ext_id, int w, int h, Io_url dir) {
return new Orig_fil_row(uid, name, ext_id, w, h, dir.GenSubFil(String_.new_u8(name)));
}
public static Orig_fil_row New_by_fs(Io_url url, byte[] name, int ext_id) {
return new Orig_fil_row(0, name, ext_id, 0, 0, url);
}
}

View File

@@ -0,0 +1,79 @@
/*
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.fsdb.fs_roots; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*; import gplx.xowa.files.fsdb.*;
import gplx.dbs.*;
class Orig_fil_tbl implements Rls_able {
private final Db_conn conn;
private final Dbmeta_fld_list flds = new Dbmeta_fld_list();
private String tbl_name = "orig_fil";
private String fld_uid, fld_name, fld_ext_id, fld_w, fld_h, fld_dir_url;
private Db_stmt stmt_insert, stmt_select;
public Orig_fil_tbl(Db_conn conn, boolean schema_is_1) {
this.conn = conn; conn.Rls_reg(this);
String fld_prefix = schema_is_1 ? "fil_" : "";
fld_uid = flds.Add_int(fld_prefix + "uid");
fld_name = flds.Add_str(fld_prefix + "name", 1024);
fld_ext_id = flds.Add_int(fld_prefix + "ext_id");
fld_w = flds.Add_int(fld_prefix + "w");
fld_h = flds.Add_int(fld_prefix + "h");
fld_dir_url = flds.Add_str(fld_prefix + "dir_url", 1024); // NOTE: don't put dir in separate table; note that entire root_dir_wkr is not built to scale due to need for recursively loading all files
}
public void Create_tbl() {
conn.Meta_tbl_create(Dbmeta_tbl_itm.New(tbl_name, flds
, Dbmeta_idx_itm.new_unique_by_tbl(tbl_name, "main", fld_name)
));
}
public void Rls() {
stmt_insert = Db_stmt_.Rls(stmt_insert);
stmt_select = Db_stmt_.Rls(stmt_select);
}
public Orig_fil_row Select_itm_or_null(Io_url dir, byte[] ttl) {
if (stmt_select == null) stmt_select = conn.Stmt_select(tbl_name, flds, fld_name);
Db_rdr rdr = stmt_select.Clear().Crt_bry_as_str(fld_name, ttl).Exec_select__rls_manual();
try {return rdr.Move_next() ? Load_itm(rdr, dir) : Orig_fil_row.Null;}
finally {rdr.Rls();}
}
private Orig_fil_row Load_itm(Db_rdr rdr, Io_url orig_root) {
String name = rdr.Read_str(fld_name);
String fil_orig_dir = rdr.Read_str(fld_dir_url);
Io_url dir = String_.Has_at_bgn(fil_orig_dir, Fs_root_wkr.Url_orig_dir)
// swap out orig_dir; EX: "~{orig_dir}7/70/" -> "/xowa/wiki/custom_wiki/file/orig/7/70/"
? Io_url_.new_dir_(orig_root.Raw() + String_.Mid(fil_orig_dir, String_.Len(Fs_root_wkr.Url_orig_dir)))
// load literally; EX: "/xowa/wiki/custom_wiki/file/orig/7/70/"
: Io_url_.new_dir_(fil_orig_dir);
return Orig_fil_row.New_by_db
( rdr.Read_int(fld_uid)
, Bry_.new_u8(name)
, rdr.Read_int(fld_ext_id)
, rdr.Read_int(fld_w)
, rdr.Read_int(fld_h)
, dir
);
}
public void Insert(Orig_fil_row row, String dir) {
if (stmt_insert == null) stmt_insert = conn.Stmt_insert(tbl_name, flds);
stmt_insert.Clear()
.Val_int (fld_uid , row.Uid())
.Val_bry_as_str(fld_name , row.Name())
.Val_int (fld_ext_id , row.Ext_id())
.Val_int (fld_w , row.W())
.Val_int (fld_h , row.H())
.Val_str (fld_dir_url , dir)
.Exec_insert();
}
}

View File

@@ -0,0 +1,43 @@
/*
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.fsdb.fs_roots; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*; import gplx.xowa.files.fsdb.*;
import gplx.dbs.*;
import gplx.xowa.files.origs.*;
class Xof_orig_wkr__fs_root implements Xof_orig_wkr {
private final Fs_root_wkr wkr;
public Xof_orig_wkr__fs_root(Fs_root_wkr wkr) {this.wkr = wkr;}
public byte Tid() {return Xof_orig_wkr_.Tid_fs_root;}
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) {
Orig_fil_row orig_row = wkr.Get_by_ttl(ttl);
if (orig_row == Orig_fil_row.Null) return Xof_orig_itm.Null;
Xof_orig_itm rv = new Xof_orig_itm
( gplx.xowa.files.repos.Xof_repo_tid_.Tid__local
, ttl
, Xof_ext_.new_by_ttl_(ttl).Id()
, orig_row.W()
, orig_row.H()
, null
);
return rv;
}
public boolean Add_orig(byte repo, byte[] page, int ext_id, int w, int h, byte[] redirect) {return false;}
public void Db_txn_save() {}
public void Db_rls() {}
}

View File

@@ -0,0 +1,33 @@
/*
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.fsdb.tsts; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*; import gplx.xowa.files.fsdb.*;
import org.junit.*;
public class Xof_file_ext__bmp_tst {
@Before public void init() {fxt.Reset();} private final Xof_file_fxt fxt = new Xof_file_fxt();
@After public void term() {fxt.Rls();}
@Test public void Make_orig() {
fxt.Init__orig_w_fsdb__commons_orig("A.bmp", 440, 400);
fxt.Exec_get(Xof_exec_arg.new_orig("A.bmp").Rslt_orig_exists_y().Rslt_file_exists_y().Rslt_file_resized_y());
fxt.Test_fsys("mem/root/common/thumb/7/0/A.bmp/440px.png", "440,400");
}
@Test public void Make_thumb() {
fxt.Init__orig_w_fsdb__commons_orig("A.bmp", 440, 400);
fxt.Exec_get(Xof_exec_arg.new_thumb("A.bmp").Rslt_orig_exists_y().Rslt_file_exists_y().Rslt_file_resized_y());
fxt.Test_fsys("mem/root/common/thumb/7/0/A.bmp/220px.png", "220,200");
}
}

View File

@@ -0,0 +1,35 @@
/*
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.fsdb.tsts; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*; import gplx.xowa.files.fsdb.*;
import org.junit.*;
public class Xof_file_ext__flac_tst {
@Before public void init() {fxt.Reset();} private final Xof_file_fxt fxt = new Xof_file_fxt();
@After public void term() {fxt.Rls();}
@Test public void Orig_page() { // .flac is on page [[File:A.flac]]
fxt.Init_orig_db(Xof_orig_arg.new_comm_file("A.flac"));
fxt.Init_fsdb_db(Xof_fsdb_arg.new_comm_file("A.flac"));
fxt.Exec_get(Xof_exec_arg.new_orig("A.flac").Rslt_orig_exists_y().Rslt_file_exists_n()); // check orig (since orig may redirect) but do not get file; (since file is not "viewable" immediately); DATE:2015-02-15
fxt.Test_fsys_exists_n("mem/root/common/orig/8/b/A.flac");
}
@Test public void Orig_app() { // .flac is clicked; get file
fxt.Init_orig_db(Xof_orig_arg.new_comm_file("A.flac"));
fxt.Init_fsdb_db(Xof_fsdb_arg.new_comm_file("A.flac"));
fxt.Exec_get(Xof_exec_arg.new_orig("A.flac").Exec_tid_(Xof_exec_tid.Tid_viewer_app).Rslt_orig_exists_y().Rslt_file_exists_y());
fxt.Test_fsys_exists_y("mem/root/common/orig/8/b/A.flac");
}
}

View File

@@ -0,0 +1,35 @@
/*
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.fsdb.tsts; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*; import gplx.xowa.files.fsdb.*;
import org.junit.*;
public class Xof_file_ext__oga_tst {
@Before public void init() {fxt.Reset();} private final Xof_file_fxt fxt = new Xof_file_fxt();
@After public void term() {fxt.Rls();}
@Test public void Orig_page() { // .oga is on page [[File:A.oga]]; check orig (since orig may redirect) but do not get file; (since file is not "viewable" immediately)
fxt.Init_orig_db(Xof_orig_arg.new_comm_file("A.oga"));
fxt.Init_fsdb_db(Xof_fsdb_arg.new_comm_file("A.oga"));
fxt.Exec_get(Xof_exec_arg.new_orig("A.oga").Rslt_orig_exists_y().Rslt_file_exists_n());
fxt.Test_fsys_exists_n("mem/root/common/orig/4/f/A.oga");
}
@Test public void Orig_app() { // .oga is clicked; get file
fxt.Init_orig_db(Xof_orig_arg.new_comm_file("A.oga"));
fxt.Init_fsdb_db(Xof_fsdb_arg.new_comm_file("A.oga"));
fxt.Exec_get(Xof_exec_arg.new_orig("A.oga").Exec_tid_(Xof_exec_tid.Tid_viewer_app).Rslt_orig_exists_y().Rslt_file_exists_y());
fxt.Test_fsys_exists_y("mem/root/common/orig/4/f/A.oga");
}
}

View File

@@ -0,0 +1,37 @@
/*
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.fsdb.tsts; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*; import gplx.xowa.files.fsdb.*;
import org.junit.*;
import gplx.xowa.files.bins.*;
public class Xof_file_ext__ogg_tst {
@Before public void init() {fxt.Reset();} private final Xof_file_fxt fxt = new Xof_file_fxt();
@After public void term() {fxt.Rls();}
// @Test public void Video() { // disabled; .ogg will never be video; DATE:2014-02-02
// fxt.Init_orig_db(Xof_orig_arg.new_comm("A.ogg", 440, 400));
// fxt.Init_fsdb_db(Xof_fsdb_arg.new_comm_thumb("A.ogg", 440, 400)); // create a thumb at 440,400 (needed for preview of video)
// fxt.Exec_get(Xof_exec_arg.new_orig("A.ogg").Rslt_orig_missing().Rslt_fsdb_xowa().Rslt_conv_n());
// fxt.Test_fsys("mem/root/common/thumb/4/2/A.ogg/440px.jpg", "440,400");
// Xof_fsdb_itm itm = fxt.Test_regy_pass("A.ogg");
// fxt.Test_itm_ext(itm, Xof_ext_.Id_ogv);// chk that file is now ogv
// }
@Test public void Audio() {
fxt.Init_orig_db(Xof_orig_arg.new_comm("A.ogg", 0, 0)); // audio has no size
fxt.Init_fsdb_db(Xof_fsdb_arg.new_comm_thumb("A.ogg", 440, 400)); // create a thumb but it should never be used
fxt.Exec_get(Xof_exec_arg.new_orig("A.ogg").Exec_tid_(Xof_exec_tid.Tid_viewer_app).Rslt_orig_exists_y().Rslt_file_exists_n().Rslt_file_resized_n());
}
}

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.fsdb.tsts; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*; import gplx.xowa.files.fsdb.*;
import org.junit.*;
public class Xof_file_ext__ogv_tst {
@Before public void init() {fxt.Reset();} private final Xof_file_fxt fxt = new Xof_file_fxt();
@After public void term() {fxt.Rls();}
@Test public void Copy_orig() {
fxt.Init_orig_db(Xof_orig_arg.new_comm("A.ogv", 440, 400));
fxt.Init_fsdb_db(Xof_fsdb_arg.new_comm_thumb("A.ogv", 440, 400));
fxt.Exec_get(Xof_exec_arg.new_orig("A.ogv").Rslt_orig_exists_y().Rslt_file_exists_y().Rslt_file_resized_n());
fxt.Test_fsys("mem/root/common/thumb/d/0/A.ogv/440px.jpg", "440,400");
}
@Test public void Copy_orig_w_thumbtime() {
fxt.Init_orig_db(Xof_orig_arg.new_comm("A.ogv", 440, 400));
fxt.Init_fsdb_db(Xof_fsdb_arg.new_comm_thumb("A.ogv", 440, 400, 10));
fxt.Exec_get(Xof_exec_arg.new_orig("A.ogv").Lnki_time_(10).Rslt_orig_exists_y().Rslt_file_exists_y().Rslt_file_resized_n());
fxt.Test_fsys("mem/root/common/thumb/d/0/A.ogv/440px-10.jpg", "440,400");
// fxt.Exec_get(Xof_exec_arg.new_thumb("A.png", Xop_lnki_tkn.Width_null, 130)); DELETE: not needed; tests if new A.png can be resized from existing; DATE:2015-03-03
}
}

View File

@@ -0,0 +1,29 @@
/*
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.fsdb.tsts; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*; import gplx.xowa.files.fsdb.*;
import org.junit.*;
public class Xof_file_ext__pdf_tst {
@Before public void init() {fxt.Reset();} private final Xof_file_fxt fxt = new Xof_file_fxt();
@After public void term() {fxt.Rls();}
@Test public void Copy_thumb() {// PURPOSE: download pdf thumb only; [[File:Physical world.pdf|thumb]]
fxt.Init_orig_db(Xof_orig_arg.new_comm("A.pdf", 2200, 1700));
fxt.Init_fsdb_db(Xof_fsdb_arg.new_comm_thumb("A.pdf", 220, 170));
fxt.Exec_get(Xof_exec_arg.new_thumb("A.pdf", 220));
fxt.Test_fsys("mem/root/common/thumb/e/f/A.pdf/220px.jpg", "220,170");
}
}

View File

@@ -0,0 +1,63 @@
/*
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.fsdb.tsts; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*; import gplx.xowa.files.fsdb.*;
import org.junit.*; import gplx.xowa.parsers.lnkis.*;
public class Xof_file_ext__png_tst {
@Before public void init() {fxt.Reset();} private final Xof_file_fxt fxt = new Xof_file_fxt();
@After public void term() {fxt.Rls();}
@Test public void Copy_thumb() {
fxt.Init_orig_db(Xof_orig_arg.new_comm("A.png", 440, 400));
fxt.Init_fsdb_db(Xof_fsdb_arg.new_comm_thumb("A.png"));
fxt.Exec_get(Xof_exec_arg.new_thumb("A.png").Rslt_orig_exists_y().Rslt_file_exists_y());
fxt.Test_fsys("mem/root/common/thumb/7/0/A.png/220px.png", "220,200");
}
@Test public void Copy_orig() {
fxt.Init__orig_w_fsdb__commons_orig("A.png", 440, 400);
fxt.Exec_get(Xof_exec_arg.new_orig("A.png").Rslt_orig_exists_y().Rslt_file_exists_y());
fxt.Test_fsys("mem/root/common/orig/7/0/A.png", "440,400");
}
@Test public void Copy_orig_w_width() { // PURPOSE: if not thumb, but width is specified; do not download orig and convert; EX: [[File:The Earth seen from Apollo 17.jpg|250px]]
fxt.Init_orig_db(Xof_orig_arg.new_comm("A.png", 440, 400));
fxt.Init_fsdb_db(Xof_fsdb_arg.new_comm_thumb("A.png", 220, 200));
fxt.Exec_get(Xof_exec_arg.new_("A.png", Xop_lnki_type.Id_null, 220, Xop_lnki_tkn.Height_null).Rslt_orig_exists_y().Rslt_file_exists_y());
fxt.Test_fsys("mem/root/common/thumb/7/0/A.png/220px.png", "220,200");
}
@Test public void Make_thumb() {
fxt.Init__orig_w_fsdb__commons_orig("A.png", 440, 400);
fxt.Exec_get(Xof_exec_arg.new_thumb("A.png").Rslt_orig_exists_y().Rslt_file_exists_y().Rslt_file_resized_y());
fxt.Test_fsys("mem/root/common/thumb/7/0/A.png/220px.png", "220,200");
}
@Test public void Height_only() { // PURPOSE.fix: height only was still using old infer-size code; EX:w:[[File:Upper and Middle Manhattan.jpg|x120px]]; DATE:2012-12-27
fxt.Init_orig_db(Xof_orig_arg.new_comm("A.png", 12591, 1847));
fxt.Init_fsdb_db(Xof_fsdb_arg.new_comm_thumb("A.png", 887, 130));
fxt.Exec_get(Xof_exec_arg.new_thumb("A.png", Xop_lnki_tkn.Width_null, 130));
fxt.Test_fsys("mem/root/common/thumb/7/0/A.png/887px.png", "887,130");
}
@Test public void Width_only_height_ignored() {// PURPOSE.fix: if height is not specified, do not recalc; needed when true scaled height is 150x151 but WM has 150x158; defect would discard 150x158; EX:[[File:Tokage_2011-07-15.jpg|150px]] simple.wikipedia.org/wiki/2011_Pacific_typhoon_season; DATE:2013-06-03
fxt.Init_orig_db(Xof_orig_arg.new_comm("A.png", 4884, 4932));
fxt.Init_fsdb_db(Xof_fsdb_arg.new_comm_thumb("A.png", 150, 150));
fxt.Exec_get(Xof_exec_arg.new_thumb("A.png", 150, Xop_lnki_tkn.Height_null));
fxt.Test_fsys("mem/root/common/thumb/7/0/A.png/150px.png", "150,150");
}
@Test public void Upright() { // PURPOSE.fix: upright not working; EX: w:Beethoven; [[File:Rudolf-habsburg-olmuetz.jpg|thumb|upright|]]
fxt.Init_orig_db(Xof_orig_arg.new_comm("A.png", 1378, 1829));
fxt.Init_fsdb_db(Xof_fsdb_arg.new_comm_thumb("A.png", 170, 226));
fxt.Exec_get(Xof_exec_arg.new_thumb("A.png", Xop_lnki_tkn.Width_null, Xop_lnki_tkn.Height_null).Lnki_upright_(Xof_img_size.Upright_default_marker));
fxt.Test_fsys("mem/root/common/thumb/7/0/A.png/170px.png", "170,226");
}
}

View File

@@ -0,0 +1,40 @@
/*
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.fsdb.tsts; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*; import gplx.xowa.files.fsdb.*;
import org.junit.*;
public class Xof_file_ext__svg_tst {
@Before public void init() {fxt.Reset();} private final Xof_file_fxt fxt = new Xof_file_fxt();
@After public void term() {fxt.Rls();}
@Test public void Make_orig() {
fxt.Init_orig_db(Xof_orig_arg.new_comm("A.svg", 440, 400));
fxt.Init_fsdb_db(Xof_fsdb_arg.new_comm_orig("A.svg", 440, 400));
fxt.Exec_get(Xof_exec_arg.new_orig("A.svg").Rslt_orig_exists_y().Rslt_file_exists_y().Rslt_file_resized_y());
fxt.Test_fsys("mem/root/common/thumb/7/5/A.svg/440px.png", "440,400");
}
@Test public void Make_thumb() {
fxt.Init_orig_db(Xof_orig_arg.new_comm("A.svg", 440, 400));
fxt.Init_fsdb_db(Xof_fsdb_arg.new_comm_orig("A.svg", 440, 400));
fxt.Exec_get(Xof_exec_arg.new_thumb("A.svg").Rslt_orig_exists_y().Rslt_file_exists_y().Rslt_file_resized_y());
fxt.Test_fsys("mem/root/common/thumb/7/5/A.svg/220px.png", "220,200");
}
@Test public void Thumb_can_be_bigger_than_orig() {// PURPOSE: svg thumbs allowed to exceed orig in size; EX: w:Portal:Music; [[File:Treble a.svg|left|160px]]
fxt.Init__orig_w_fsdb__commons_orig("A.svg", 110, 100); // create orig of 110,100
fxt.Exec_get(Xof_exec_arg.new_thumb("A.svg", 330).Rslt_file_exists_y()); // get 330
fxt.Test_fsys("mem/root/common/thumb/7/5/A.svg/330px.png", "330,300");
}
}

View File

@@ -0,0 +1,35 @@
/*
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.fsdb.tsts; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*; import gplx.xowa.files.fsdb.*;
import org.junit.*;
public class Xof_file_ext__unknown_tst {
@Before public void init() {fxt.Reset();} private final Xof_file_fxt fxt = new Xof_file_fxt();
@After public void term() {fxt.Rls();}
@Test public void Orig_page() { // .bin is on page [[File:A.bin]]; check orig (since orig may redirect) but do not get file; (since file is not "viewable" immediately); DATE:2014-08-17
fxt.Init_orig_db(Xof_orig_arg.new_comm_file("A.bin"));
fxt.Init_fsdb_db(Xof_fsdb_arg.new_comm_file("A.bin"));
fxt.Exec_get(Xof_exec_arg.new_orig("A.bin").Rslt_orig_exists_y().Rslt_file_exists_n());
fxt.Test_fsys_exists_n("mem/root/common/orig/f/b/A.bin");
}
@Test public void Orig_app() { // .bin is clicked; get file
fxt.Init_orig_db(Xof_orig_arg.new_comm_file("A.bin"));
fxt.Init_fsdb_db(Xof_fsdb_arg.new_comm_file("A.bin"));
fxt.Exec_get(Xof_exec_arg.new_orig("A.bin").Exec_tid_(Xof_exec_tid.Tid_viewer_app).Rslt_orig_exists_y().Rslt_file_exists_y());
fxt.Test_fsys_exists_y("mem/root/common/orig/f/b/A.bin");
}
}

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.fsdb.tsts; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*; import gplx.xowa.files.fsdb.*;
import org.junit.*;
import gplx.xowa.files.bins.*;
public class Xof_file_ext__wav_tst {
@Before public void init() {fxt.Reset();} private final Xof_file_fxt fxt = new Xof_file_fxt();
@After public void term() {fxt.Rls();}
@Test public void Orig_page() { // .wav is on page [[File:A.wav]]; check orig (since orig may redirect) but do not get file; (since file is not "viewable" immediately); DATE:2014-08-17
fxt.Init_orig_db(Xof_orig_arg.new_comm_file("A.wav"));
fxt.Init_fsdb_db(Xof_fsdb_arg.new_comm_file("A.wav"));
fxt.Exec_get(Xof_exec_arg.new_orig("A.wav").Rslt_orig_exists_y().Rslt_file_exists_n());
fxt.Test_fsys_exists_n("mem/root/common/orig/c/3/A.wav");
}
@Test public void Orig_app() { // .wav is clicked; get file
fxt.Init_orig_db(Xof_orig_arg.new_comm_file("A.wav"));
fxt.Init_fsdb_db(Xof_fsdb_arg.new_comm_file("A.wav"));
fxt.Exec_get(Xof_exec_arg.new_orig("A.wav").Exec_tid_(Xof_exec_tid.Tid_viewer_app).Rslt_orig_exists_y().Rslt_file_exists_y());
fxt.Test_fsys_exists_y("mem/root/common/orig/c/3/A.wav");
}
}

View File

@@ -0,0 +1,35 @@
/*
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.fsdb.tsts; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*; import gplx.xowa.files.fsdb.*;
import org.junit.*;
public class Xof_file_ext__xcf_tst {
@Before public void init() {fxt.Reset();} private final Xof_file_fxt fxt = new Xof_file_fxt();
@After public void term() {fxt.Rls();}
@Test public void Make_orig() {
fxt.Init_orig_db(Xof_orig_arg.new_comm("A.xcf", 440, 400));
fxt.Init_fsdb_db(Xof_fsdb_arg.new_comm_orig("A.xcf", 440, 400));
fxt.Exec_get(Xof_exec_arg.new_orig("A.xcf").Rslt_orig_exists_y().Rslt_file_exists_y().Rslt_file_resized_y());
fxt.Test_fsys("mem/root/common/thumb/4/4/A.xcf/440px.png", "440,400");
}
@Test public void Make_thumb() {
fxt.Init_orig_db(Xof_orig_arg.new_comm("A.xcf", 440, 400));
fxt.Init_fsdb_db(Xof_fsdb_arg.new_comm_orig("A.xcf", 440, 400));
fxt.Exec_get(Xof_exec_arg.new_thumb("A.xcf").Rslt_orig_exists_y().Rslt_file_exists_y().Rslt_file_resized_y());
fxt.Test_fsys("mem/root/common/thumb/4/4/A.xcf/220px.png", "220,200");
}
}

Some files were not shown because too many files have changed in this diff Show More