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

View File

@@ -0,0 +1,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.ios.*;
import gplx.fsdb.data.*; import gplx.fsdb.meta.*; import gplx.xowa.files.fsdb.*;
public class Xof_bin_updater {
private final Fsd_img_itm tmp_img_itm = new Fsd_img_itm(); private final Fsd_thm_itm tmp_thm_itm = Fsd_thm_itm.new_(); private final Fsd_fil_itm tmp_fil_itm = new Fsd_fil_itm();
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()) { // does not add .pdf and .djvu b/c latter do not have w,h for fsdb_img
mnt.Insert_img(tmp_img_itm, 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 = tmp_img_itm.Fil_id();
}
else {
mnt.Insert_fil(tmp_fil_itm, atr_fil, bin_fil, fsdb.Orig_repo_name(), fsdb.Orig_ttl(), orig_ext_id, rdr_len, rdr);
db_uid = tmp_fil_itm.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,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; import gplx.*; import gplx.xowa.*;
public class Xof_exec_tid {
public static final int Tid_wiki_page = 1, Tid_wiki_file = 2, Tid_viewer_app = 3;
}

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, Int_obj_val.new_(val));}
private static final Hash_adp_bry ext_hash = Hash_adp_bry.ci_ascii_()
.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 Exc_.new_("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_finder.Find_bwd(ttl, Byte_ascii.Dot);
byte[] ext = (dot_pos == Bry_.NotFound || dot_pos == ttl_len) ? Bry_.Empty : Bry_.Xto_str_lower(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_finder.Find_bwd(ttl, Byte_ascii.Dot);
int ttl_len = ttl.length;
if (dot_pos == Bry_.NotFound || 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_thumbtime(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,49 @@
/*
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.I.InitEngine_mem();
Db_conn_bldr.I.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.I.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) {
wiki.File_mgr().Orig_mgr().Insert(Xof_repo_itm_.Repo_by_bool(repo_is_commons), Bry_.new_u8(orig_ttl), orig_ext_id, orig_w, orig_h, Bry_.new_u8(orig_redirect));
}
}

View File

@@ -0,0 +1,64 @@
/*
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.gui.*; 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();
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();
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();
void File_exists_(boolean 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 Meta_is_new();
}

View File

@@ -0,0 +1,135 @@
/*
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.ios.*;
import gplx.fsdb.*; import gplx.fsdb.meta.*; import gplx.fsdb.data.*; import gplx.xowa.files.fsdb.*;
import gplx.xowa.files.repos.*; import gplx.xowa.files.origs.*; import gplx.xowa.files.bins.*; import gplx.xowa.files.caches.*; import gplx.xowa.files.gui.*;
import gplx.xowa.html.hdumps.core.*;
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_.I; this.repo_mgr = repo_mgr; this.js_wkr = js_wkr;
this.hpg = hpg; this.imgs = imgs;
}
public String Name() {return "xowa.load_imgs";}
public boolean Resume() {return true;}
public void Exec() {
int len = imgs.Count();
for (int i = 0; i < len; ++i)
Ctor_by_hdump(hpg, (Xohd_data_itm__base)imgs.Get_at(i));
Xoa_app_.Usr_dlg().Prog_none("", "", "");
}
private void Ctor_by_hdump(Xoa_page hpg, Xohd_data_itm__base hdump) {
Xof_fsdb_itm fsdb = new Xof_fsdb_itm();
fsdb.Init_at_lnki(Xof_exec_tid.Tid_wiki_page, hpg.Wiki().Domain_itm().Abrv_xo(), hdump.Lnki_ttl(), hdump.Lnki_type(), hdump.Lnki_upright(), hdump.Lnki_w(), hdump.Lnki_h(), hdump.Lnki_time(), hdump.Lnki_page(), Xof_patch_upright_tid_.Tid_all);
fsdb.Init_at_hdoc(hdump.Html_uid(), hdump.Html_elem_tid());
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);
}
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;
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.I.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: 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);
cache_mgr.Update(fsdb);
return true;
} catch (Exception e) {
usr_dlg.Warn_many("", "", "file.unknown: ~{0}", Err_.Message_gplx_brief(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(Xof_repo_itm_.Mode_by_bool(!fsdb.File_is_orig()), repo, 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.I.QueryFil(html_url).Size();
Io_stream_rdr rdr = gplx.ios.Io_stream_rdr_.file_(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(e));
}
finally {rdr.Rls();}
}
}

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; import gplx.*; import gplx.xowa.*;
public class Xof_file_wkr_ {
public static final Url_encoder Md5_decoder = Url_encoder.new_http_url_().Itms_raw_same_many(Byte_ascii.Plus);
public static byte[] Md5_fast(byte[] v) {return Bry_.new_a7(gplx.security.HashAlgo_.Md5.CalcHash(ConsoleDlg_.Null, gplx.ios.IoStream_.ary_(v)));}
public static byte[] Md5_(byte[] ttl) {
ttl = Md5_decoder.Decode_lax(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[] ttl) {
int ttl_len = ttl.length;
for (int i = 0; i < ttl_len; i++) { // convert all spaces to _; NOTE: not same as lnki.Ttl().Page_url(), b/c Page_url does incompatible encoding
byte b = ttl[i];
if (b == Byte_ascii.Space) ttl[i] = Byte_ascii.Underline;
if (i == 0) {
if (b > 96 && b < 123) ttl[i] -= 32; // NOTE: file automatically uppercases 1st letter
}
}
return ttl;
}
}

View File

@@ -0,0 +1,147 @@
/*
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.ios.*;
import gplx.xowa.files.gui.*; import gplx.xowa.files.repos.*;
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_itm_.Repo_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 Meta_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_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 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_null_deprecated;
}
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.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 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);
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();
}
}
}

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.*;
public class Xof_fsdb_mode {
private int tid;
Xof_fsdb_mode(int tid) {this.tid = tid;}
// public boolean Tid_v0() {return tid == Tid_int_v0;}
public boolean Tid_v2_gui() {return tid == Tid_int_v2_gui;}
public boolean Tid_v2_bld() {return tid == Tid_int_v2_bld;}
public void Tid_v2_bld_y_() {tid = Tid_int_v2_bld;}
private static final int
Tid_int_v0 = 1
, Tid_int_v2_gui = 2
, Tid_int_v2_bld = 3
;
public static Xof_fsdb_mode new_v0() {return new Xof_fsdb_mode(Tid_int_v0);}
public static Xof_fsdb_mode new_v2_gui() {return new Xof_fsdb_mode(Tid_int_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;
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,166 @@
/*
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_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) {
this.Clear(); // always clear before calc; caller should be responsible, but just to be safe.
if (Enm_.HasInt(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;
}
}
// private static boolean Calc_limit_size(int exec_tid, int lnki_type, int lnki_ext) {
// if (lnki_type != Xop_lnki_type.Id_thumb) return false; // only limit to size for thumb; EX:[[File:A.png|thumb|999x999px]] does not get limited but [[File:A.png|999x999px]] does
// if (lnki_ext == Xof_ext_.Id_svg) // if svg...
// return exec_tid == Xof_exec_tid.Tid_wiki_file; // ... only limit to size if [[File]] page
// else // not svg and thumb; always limit to size
// return true;
// }
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_null_deprecated = -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,102 @@
/*
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.*;
public class Xof_img_size_tst {
@Before public void init() {
fxt.Reset();
fxt.Orig_(400, 200);
} private Xof_img_size_fxt fxt = new Xof_img_size_fxt();
@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_.MaxValue, 90).Orig_(900, 600).Test_html(135, 90, Bool_.N); // NOTE: used to be Int_.MaxValue,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_(Enm_.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
}
}
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,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.*;
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,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.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_.Xto_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_thumbtime(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, Int_obj_val.new_(val));}
}

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_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 Enm_.AddInt(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 Enm_.HasInt(tid, Tid_use_thumb_w);}
public static boolean Split_fix_default(int tid) {return Enm_.HasInt(tid, Tid_fix_default);}
}

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.*;
import gplx.core.threads.*;
import gplx.xowa.files.gui.*;
class Xof_redlink_wkr implements Gfo_thread_wkr {
private Xog_js_wkr js_wkr; private int[] uids;
public Xof_redlink_wkr(Xog_js_wkr js_wkr, int[] uids) {
this.js_wkr = js_wkr; this.uids = uids;
}
public String Name() {return "xowa.redlinks";}
public boolean Resume() {return true;}
public void Exec() {
int len = uids.length;
for (int i = 0; i < len; ++i) {
int uid = uids[i];
js_wkr.Html_atr_set(Int_.Xto_str(uid), "", "");
}
}
}

View File

@@ -0,0 +1,202 @@
/*
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.repos.*; import gplx.xowa.files.fsdb.*;
public class Xof_url_bldr {
private final Bry_bfr bfr = Bry_bfr.reset_(400);
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[] root; private byte dir_spr; private boolean fsys_tid_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_root(byte[] root, byte dir_spr, boolean wmf_dir_hive, boolean wmf_protocol_is_file, int md5_dir_depth) {
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_tid_is_wnt = Op_sys.Cur().Tid_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_tid_is_wnt) this.ttl = Xof_repo_itm_.Ttl_invalid_fsys_chars(bfr, ttl); // NOTE: changed ttl does not change md5
this.file_is_thumb = mode == Xof_repo_itm_.Mode_thumb;
this.area = Xof_repo_itm_.Mode_names_key[mode];
return this;
}
public Xof_url_bldr Init_for_src_file(byte mode, Xof_repo_itm repo, byte[] ttl, byte[] md5, Xof_ext ext, int file_w, double time, int page) {
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(ttl); this.md5 = md5; this.ext = ext;
this.file_is_thumb = mode == Xof_repo_itm_.Mode_thumb; this.file_w = file_w; this.time = time; this.page = page;
return this;
}
public Xof_url_bldr Init_for_trg_file(byte mode, Xof_repo_itm repo, byte[] ttl, byte[] md5, Xof_ext ext, int file_w, double time, int page) {
return Init(Bool_.N, Bool_.N, repo.Dir_spr(), repo.Root_bry()
, repo.Mode_names()[mode], repo.Dir_depth(), repo.Gen_name_trg(ttl, md5, ext), md5, ext, mode, file_w, time, page);
}
public Xof_url_bldr Init_for_trg_html(byte mode, Xof_repo_itm repo, byte[] ttl, byte[] md5, Xof_ext ext, int file_w, double time, int page) {
return Init(Bool_.N, Bool_.N, Byte_ascii.Slash, repo.Root_http()
, repo.Mode_names()[mode], repo.Dir_depth(), repo.Gen_name_trg(ttl, md5, ext), md5, ext, mode, file_w, time, page);
}
public Xof_url_bldr Init(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.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_repo_itm_.Mode_thumb; this.file_w = file_w; this.time = time; this.page = page;
return this;
}
public byte[] Xto_bry() {Bld(); byte[] rv = bfr.Xto_bry_and_clear(); Clear(); return rv;}
public String Xto_str() {Bld(); String rv = bfr.Xto_str(); Clear(); return rv;}
public Io_url Xto_url() {Bld(); Io_url rv = Io_url_.new_fil_(bfr.Xto_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_repo_itm_.Mode_orig : Xof_repo_itm_.Mode_thumb;
return this.Init_for_trg_file(mode, repo_itm, itm.Orig_ttl(), itm.Orig_ttl_md5(), itm.Orig_ext(), itm.Html_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_repo_itm_.Mode_orig : Xof_repo_itm_.Mode_thumb;
return this.Init_for_trg_file(mode, repo_itm, itm.Orig_ttl(), itm.Orig_ttl_md5(), itm.Orig_ext_itm(), itm.Html_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_repo_itm_.Mode_orig : Xof_repo_itm_.Mode_thumb;
return this.Init_for_trg_file(mode, repo_itm, itm.Orig_ttl(), itm.Orig_ttl_md5(), itm.Orig_ext(), itm.Html_w(), itm.Lnki_time(), itm.Lnki_page()).Xto_url();
}
private void Bld() {
Add_core();
if (file_is_thumb) {
if (wmf_dir_hive) Add_thumb_wmf();
else Add_thumb_xowa();
}
}
private Xof_url_bldr Add_core() {
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
bfr.Add(area).Add_byte(dir_spr); // add area; EX: "thumb\"
byte b0 = md5[0];
if (wmf_dir_hive) {
bfr.Add_byte(b0).Add_byte(dir_spr); // add md5_0 EX: "0/"
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++)
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)
bfr.Add(ttl); // NOTE: file_names are not url-encoded; this includes symbols (') and foreign characters (ö)
else // wmf_http
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
bfr.Add(ttl); // add title; EX: "A.png"
return this;
}
private Xof_url_bldr Add_thumb_xowa() {
bfr.Add_byte(dir_spr); // add dir_spr; EX: "\"
bfr.Add_int_variable(file_w).Add(Bry_px); // add file_w; EX: "220px"
if (Xof_lnki_time.Null_n(time))
bfr.Add_byte(time_dlm).Add_str(Xof_lnki_time.X_str(time)); // add time EX: "@5"
else if (page != Xof_lnki_page.Null)
bfr.Add_byte(Byte_ascii.Dash).Add_int_variable(page); // add page EX: "-5"
bfr.Add_byte(Byte_ascii.Dot); // add . EX: "."
if (file_is_thumb)
bfr.Add(ext.Ext_view()); // add view_ext EX: ".png"
else
bfr.Add(ext.Ext()); // add orig_ext EX: ".svg"
return this;
}
private Xof_url_bldr Add_thumb_wmf() {
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:
if (Xof_lnki_time.Null_n(time))
bfr.Add(Bry_seek).Add_str(Xof_lnki_time.X_str(time)).Add_byte(Byte_ascii.Dash);// add seek; EX: "seek%3D5-"
else
bfr.Add(Bry_mid); // add mid; EX: "mid-"
break;
case Xof_ext_.Id_tif:
case Xof_ext_.Id_tiff:
Add_thumb_wmf_page(Bry_lossy_page1, Bry_lossy_page);
bfr.Add_int_variable(file_w); // add file_w; EX: "220"
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);
bfr.Add_int_variable(file_w); // add file_w; EX: "220"
bfr.Add(Bry_px_dash); // add px; EX: "px-"
break;
default:
bfr.Add_int_variable(file_w); // add file_w; EX: "220"
bfr.Add(Bry_px_dash); // add px; EX: "px-"
break;
}
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:
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:
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))
bfr.Add(bry_page_1); // add "lossy-page1-" EX: "lossy-page1-"
else {
bfr.Add(bry_page); // add "lossy-page" EX: "lossy-page"
bfr.Add_int_variable(page); // add page EX: 123
bfr.Add_byte(Byte_ascii.Dash); // add - EX: "-"
}
}
private Xof_url_bldr Clear() {
root = area = ttl = md5 = null;
file_w = 0; time = Xof_lnki_time.Null;
ext = null;
bfr.Clear();
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_mid = Bry_.new_a7("mid-")
;
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 final Xof_url_bldr Temp = new Xof_url_bldr();
private static final Url_encoder encoder_src_http = Url_encoder.new_http_url_(); // NOTE: changed from new_html_href_mw_ to new_url_ on 2012-11-19; issues with A%2Cb becoming A%252Cb
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,53 @@
/*
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.*; import gplx.xowa.files.repos.*;
public class Xof_url_bldr_tst {
private Xof_url_bldr_fxt fxt = new Xof_url_bldr_fxt();
@Before public void init() {fxt.ini();}
@Test public void Ogv() {fxt.Dir_spr_http_().Root_("http://test/").Md5_("d0").Ttl_("A.ogv").Expd_src_("http://test/thumb/d/d0/A.ogv/mid-A.ogv.jpg").tst();}
@Test public void Ogv_seek() {fxt.Dir_spr_http_().Root_("http://test/").Md5_("d0").Ttl_("A.ogv").Expd_src_("http://test/thumb/d/d0/A.ogv/seek%3D5-A.ogv.jpg").Seek_(5).tst();}
@Test public void Xcf() {fxt.Dir_spr_http_().Root_("http://test/").Md5_("44").Ttl_("A.xcf").Expd_src_("http://test/thumb/4/44/A.xcf/0px-A.xcf.png").tst();}
@Test public void Bmp() {fxt.Dir_spr_http_().Root_("http://test/").Md5_("70").Ttl_("A.bmp").Expd_src_("http://test/thumb/7/70/A.bmp/0px-A.bmp.png").tst();}
@Test public void Pdf_none() {fxt.Dir_spr_http_().Root_("http://test/").Md5_("ef").Ttl_("A.pdf").Expd_src_("http://test/thumb/e/ef/A.pdf/page1-0px-A.pdf.jpg").tst();}
@Test public void Pdf_page_2() {fxt.Dir_spr_http_().Root_("http://test/").Md5_("ef").Ttl_("A.pdf").Page_(2).Expd_src_("http://test/thumb/e/ef/A.pdf/page2-0px-A.pdf.jpg").tst();}
}
class Xof_url_bldr_fxt {
private final Xof_url_bldr url_bldr = new Xof_url_bldr();
public Xof_url_bldr_fxt ini() {this.Clear(); 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 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 Expd_src_(String v) {expd_src = v; return this;} private String expd_src;
private void Clear() {
dir_spr = Byte_.Zero; ext = null; root = md5 = ttl = expd_src = null;
seek = Xof_lnki_time.Null;
page = Xof_lnki_page.Null;
}
public Xof_url_bldr_fxt tst() {
url_bldr.Init_by_root(Bry_.new_u8(root), dir_spr, Bool_.Y, Bool_.N, 2);
url_bldr.Init_by_itm (Xof_repo_itm_.Mode_thumb, Bry_.new_u8(ttl), Bry_.new_u8(md5), ext, 0, seek, page);
Tfds.Eq(expd_src, url_bldr.Xto_str());
return this;
}
}

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; import gplx.*; import gplx.xowa.*;
import gplx.xowa.files.fsdb.*;
class Xof_wkr_mgr implements GfoInvkAble {
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 GfoInvkAble_.Rv_unhandled;
}
private static final String Invk_get = "get";
private Xof_fsdb_mgr Get_or_new(String key) {
Xof_fsdb_mgr rv = null;
if (String_.Eq(key, "fs.dir"))
rv = new gplx.xowa.files.fsdb.fs_roots.Fs_root_fsdb_mgr(file_mgr.Wiki());
else
throw Exc_.new_unhandled(key);
file_mgr.Fsdb_mgr_(rv);
return rv;
}
}

View File

@@ -0,0 +1,305 @@
/*
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.gui.*; import gplx.xowa.files.repos.*;
public class Xof_xfer_itm implements Xof_file_itm {
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 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 Meta_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 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 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_lax(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
}
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_lax(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 Meta_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 Xof_url_bldr Url_bldr(){ return url_bldr;}
public void Url_bldr_(Xof_url_bldr v) {url_bldr = v;} private Xof_url_bldr url_bldr = Xof_url_bldr.Temp;
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 url_bldr.Init_for_trg_file(mode_id, trg_repo_itm, 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 url_bldr.Init_for_trg_file(mode_id, trg_repo_itm, 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_repo_itm_.Mode_orig, Xof_img_size.Size_null_deprecated);
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_repo_itm_.Mode_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_repo_itm_.Mode_orig, Xof_img_size.Size_null_deprecated);
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_repo_itm_.Mode_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_repo_itm_.Mode_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_repo_itm_.Mode_thumb : Xof_repo_itm_.Mode_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_repo_itm_.Mode_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_repo_itm_.Mode_thumb, model_w); // note that thumb.Width is used (the actual file width), not html_w
file_exists = true;
return true;
}
}
/*
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,94 @@
/*
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.gfui.*;
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,66 @@
/*
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.gfui.*; import gplx.xowa.files.*;
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,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.files.gui.*;
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 Name() {return "xowa.gui.html.redlinks.set";}
public boolean Resume() {return true;}
public void Exec() {
int len = redlink_ary.length;
for (int i = 0; i < len; ++i) {
js_wkr.Html_redlink(gplx.xowa.parsers.lnkis.redlinks.Xopg_redlink_lnki_list.Lnki_id_prefix + Int_.Xto_str(redlink_ary[i]));
}
}
}

View File

@@ -0,0 +1,138 @@
/*
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.*;
public class Xow_file_mgr implements GfoInvkAble {
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.I.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;} // 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 Meta_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 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 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) return; // no fsdb_core found; exit
if (db_core == null) {
db_core = Fsdb_db_mgr__v2_bldr.I.Get_or_make(wiki, false);
}
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 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 GfoInvkAble_.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.I.CopyFil(src, trg, true); return true;}
catch (Exception exc) {Exc_.Noop(exc); return false;}
}
public boolean Save_as_bry(Bry_obj_ref bry_ref) {
try {
byte[] bry = Io_mgr.I.LoadFilBry(src);
bry_ref.Val_(bry);
return true;
}
catch (Exception exc) {Exc_.Noop(exc); return false;}
}
}
class Bin_fetcher_http implements Bin_fetcher {
private gplx.ios.IoEngine_xrg_downloadFil download = gplx.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) {Exc_.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,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.bins; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.core.primitives.*; import gplx.ios.*;
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.wmfs.*;
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_.I;
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 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_.file_(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.Html_w(), trg, save_to_fsys, rdr_wrapper, fsdb, wkr);
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.Html_w(), trg, save_to_fsys, rdr_wrapper, fsdb, wkr);
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_.file_(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.I.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.ios.*;
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.I;
else if (String_.Eq(key, Xof_bin_skip_wkr_.Key__small_size)) rv = Xof_bin_skip_wkr__small_size.I;
else throw Exc_.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 I = 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 I = 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.ios.*;
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.ios.*; import gplx.cache.*; 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_.MaxValue, 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,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.bins; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.ios.*;
import gplx.xowa.files.fsdb.*; import gplx.xowa.files.repos.*;
public abstract class Xof_bin_wkr__fsys_base implements Xof_bin_wkr, GfoInvkAble {
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_repo_itm_.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.ios.Io_stream_rdr_.Noop : gplx.ios.Io_stream_rdr_.file_(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_repo_itm_.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.I.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 GfoInvkAble_.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_root(Bry_.Empty, Op_sys.Cur().Fsys_dir_spr_byte(), Bool_.Y, Bool_.Y, Xof_repo_itm_.Dir_depth_wmf);
}
}
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_root(Bry_.Empty, Op_sys.Cur().Fsys_dir_spr_byte(), Bool_.N, Bool_.N, Xof_repo_itm_.Dir_depth_xowa);
}
}

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.bins; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.ios.*; import gplx.core.threads.*; import gplx.xowa.files.fsdb.*; import gplx.xowa.files.repos.*;
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 Xof_url_bldr url_bldr = new Xof_url_bldr();
public Xof_bin_wkr__http_wmf(Xow_repo_mgr repo_mgr, gplx.ios.IoEngine_xrg_downloadFil download_wkr) {this.repo_mgr = repo_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) {
Download_init(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_wkr.Exec_as_rdr();
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();
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) {
Download_init(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 Download_init(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_repo_itm_.Mode_thumb : Xof_repo_itm_.Mode_orig;
Xof_repo_pair repo_itm = repo_mgr.Repos_get_by_wiki(orig_repo);
String src = url_bldr.Init_for_src_file(mode, repo_itm.Src(), orig_ttl, orig_md5, orig_ext, file_w, lnki_time, lnki_page).Xto_str();
download_wkr.Init(src, file_url);
}
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 GfoInvkAble_.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 Xof_bin_wkr__http_wmf(wiki.File__repo_mgr(), wiki.App().Wmf_mgr().Download_wkr().Download_xrg());}
}

View File

@@ -0,0 +1,80 @@
/*
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.xowa.files.fsdb.*; import gplx.xowa2.files.*; import gplx.xowa.wikis.*;
public class Xof_cache_mgr implements GfoInvkAble {
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_brief(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_brief(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.I.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 GfoInvkAble_.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 ? "xowa_cfg" : "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_.I.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_.I.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 RlsAble {
private String tbl_name = "file_cache_dir"; private final Db_meta_fld_list flds = Db_meta_fld_list.new_();
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) {
Db_meta_tbl meta = Db_meta_tbl.new_(tbl_name, flds
, Db_meta_idx.new_normal_by_tbl(tbl_name, "name", fld_name)
);
conn.Ddl_create_tbl(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 Exc_.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_brief(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, Db_meta_fld.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 Db_conn_.Select_fld0_as_int_or(conn, "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 = DateAdp_.Now().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.Xto_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.Xto_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,149 @@
/*
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.*;
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();
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_brief(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_repo_itm_.Mode_orig : Xof_repo_itm_.Mode_thumb;
byte[] wiki_domain = dir_mgr.Get_by_id(itm.Dir_id()).Name();
Xowe_wiki wiki = wiki_mgr.Get_by_key_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(mode_id, trg_repo, 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.I.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_.I.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_.I.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 RlsAble {
private String tbl_name = "file_cache_fil"; private final Db_meta_fld_list flds = Db_meta_fld_list.new_();
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 = Db_meta_fld.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) {
Db_meta_tbl meta = Db_meta_tbl.new_(tbl_name, flds
, Db_meta_idx.new_normal_by_tbl(tbl_name, "fil", fld_name, fld_is_orig, fld_w, fld_h, fld_time, fld_cache_time, fld_uid)
);
conn.Ddl_create_tbl(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 Exc_.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_brief(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, Db_meta_fld.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_.I.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 Db_conn_.Select_fld0_as_int_or(conn, "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,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 = DateAdp_.Now().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.Xto_bry_and_clear();
}
}
class Xof_cache_mgr_sorter implements gplx.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 I = new Xof_cache_mgr_sorter(); Xof_cache_mgr_sorter() {}
}

View File

@@ -0,0 +1,215 @@
/*
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.xowa2.files.*; import gplx.xowa.files.repos.*;
import gplx.xowa.wikis.*; import gplx.xowa.wikis.domains.*; import gplx.xowa.users.data.*;
public class Xou_cache_mgr {
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 key_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 int Fsys_count_cur() {return hash.Count();}
public long Fsys_size_cur() {return fsys_size_cur;} private long fsys_size_cur = 0;
public long Fsys_size_min() {return fsys_size_min;} public void Fsys_size_min_(long v) {fsys_size_min = v;} private long fsys_size_min = Io_mgr.Len_mb * 75;
public long Fsys_size_max() {return fsys_size_max;} public void Fsys_size_max_(long v) {fsys_size_max = v;} private long fsys_size_max = Io_mgr.Len_mb * 100;
public KeyVal[] Info() {
long view_date = Long_.MaxValue;
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.ios.Io_size_.To_str(fsys_size))
, KeyVal_.new_("file count", len)
, KeyVal_.new_("oldest file", view_date == Long_.MaxValue ? "" : DateAdp_.unixtime_utc_seconds_(view_date).XtoStr_fmt_iso_8561())
);
}
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) {
synchronized (thread_lock) {
this.Page_bgn();
byte[] key = Xou_cache_itm.Key_gen(key_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(key_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, DateAdp_.Now().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(key_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();
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 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(key_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.I); // 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
deleted.Add(grp);
else
fsys_size_calc = fsys_size_temp;
}
len = deleted.Count();
Db_conn conn = cache_tbl.Conn();
conn.Txn_bgn();
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.I.Delete_dir_empty(cache_dir);
}
catch (Exception e) {Xoa_app_.Usr_dlg().Warn_many("", "", "failed to compress cache: err=~{0}", Err_.Message_gplx_brief(e)); return;}
}
Xoa_app_.Usr_dlg().Note_many("", "", "cache compress done");
}
private Io_url Calc_url(Xou_cache_itm cache) {
byte[] wiki_domain = Xow_domain_abrv_xo_.To_itm(cache.Lnki_wiki_abrv()).Domain_bry();
Xow_wiki wiki = wiki_mgr.Get_by_key_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(orig_ttl, orig_md5, orig_ext);
byte mode_id = cache.File_is_orig() ? Xof_repo_itm_.Mode_orig : Xof_repo_itm_.Mode_thumb;
return url_bldr.Init_for_trg_file(mode_id, trg_repo, 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();
}
}
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.ios.IoItmFil fil = Io_mgr.I.QueryFil(itm.File_url());
if (fil.Exists()) {
Io_mgr.I.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.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 I = new Xou_cache_grp_sorter(); Xou_cache_grp_sorter() {}
}

View File

@@ -0,0 +1,113 @@
/*
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;
public void Clear() {
Tfds.Now_set(DateAdp_.new_(1970, 1, 1, 0, 0, 0, 0));
Io_mgr.I.InitEngine_mem();
Db_conn_bldr.I.Reg_default_mem();
Xoae_app app = Xoa_app_fxt.app_();
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.wiki_(app, "en.wikipedia.org"));
Xoa_app_fxt.repo_(app, Xoa_app_fxt.wiki_(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) {
mgr.Fsys_size_min_(min);
mgr.Fsys_size_max_(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_itm_.Repo_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(mgr.Fsys_size_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 RlsAble {
private String tbl_name = "file_cache"; private final Db_meta_fld_list flds = Db_meta_fld_list.new_();
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() {
Db_meta_tbl meta = Db_meta_tbl.new_(tbl_name, flds
, Db_meta_idx.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)
, Db_meta_idx.new_normal_by_tbl(tbl_name, "size", fld_file_size)
, Db_meta_idx.new_normal_by_tbl(tbl_name, "date", fld_view_date)
);
conn.Ddl_create_tbl(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, Db_meta_fld.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 Exc_.new_unhandled(itm.Db_state());
}
itm.Db_state_(Db_cmd_mode.Tid_ignore);
} catch (Exception e) {stmt_bldr.Rls(); throw Exc_.new_exc(e, "xo", "db_save failed");}
}
@gplx.Internal protected Db_rdr Select_all_for_test() {return conn.Stmt_select(tbl_name, flds, Db_meta_fld.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_(255);
private Xou_cache_tbl tbl;
public void Clear() {
Io_mgr.I.InitEngine_mem();
Db_conn_bldr.I.Reg_default_mem();
Db_conn_bldr_data conn_data = Db_conn_bldr.I.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,62 @@
/*
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.ios.*;
import gplx.xowa.files.origs.*; import gplx.xowa.files.repos.*; import gplx.xowa.files.fsdb.*; import gplx.xowa.files.bins.*; import gplx.xowa.files.gui.*;
public class Xou_file_itm_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_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();
try {
if (wiki.File__fsdb_mode().Tid_v2_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.I.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_brief(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,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.cnvs; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.core.primitives.*; import gplx.xowa.wmfs.*;
public class Xof_img_wkr_resize_img_imageMagick implements Xof_img_wkr_resize_img {
private final Xowmf_mgr wmf_mgr; private final ProcessAdp cmd_convert, cmd_convert_svg_to_png;
private boolean init_needed = true;
public Xof_img_wkr_resize_img_imageMagick(Xowmf_mgr wmf_mgr, ProcessAdp cmd_convert, ProcessAdp 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.I.ExistsFil(src)) return false;
Io_mgr.I.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);
}
ProcessAdp 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,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.cnvs; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.core.primitives.*; import gplx.gfui.*; 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 Exc_.new_("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.I.SaveFilStr(trg, SizeAdp_.new_(trg_w, trg_h).XtoStr());
return true;
}
public static final Xof_img_wkr_resize_img_mok _ = new Xof_img_wkr_resize_img_mok(); Xof_img_wkr_resize_img_mok() {}
}

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.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.ios.*;
public class Xof_download_wkr_io implements Xof_download_wkr {
IoEngine_xrg_downloadFil xrg = Io_mgr.I.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.I.ExistsFil(src_url)) return IoEngine_xrg_downloadFil.Rslt_fail_file_not_found;
try {Io_mgr.I.CopyFil(src_url, trg_url, true);}
catch (Exception exc) {Exc_.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.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.I.CreateDirIfAbsent(trg_url.OwnerDir());
Io_url src_url = Io_url_.new_fil_(src_str);
if (!Io_mgr.I.ExistsFil(src_url)) return IoEngine_xrg_downloadFil.Rslt_fail_file_not_found;
try {Io_mgr.I.CopyFil(src_url, trg_url, true);}
catch (Exception exc) {Exc_.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 GfoInvkAble {
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 GfoInvkAble_.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 GfoInvkAble {
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.ios.Io_size_.Load_int_(m);
else if (ctx.Match(k, Invk_view_max_)) view_max = gplx.ios.Io_size_.Load_int_(m);
else return GfoInvkAble_.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 GfoInvkAble {
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 GfoInvkAble_.Rv_unhandled;
} private static final String Invk_set = "set";
}

View File

@@ -0,0 +1,77 @@
/*
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.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.*;
import gplx.fsdb.*; import gplx.fsdb.data.*; import gplx.fsdb.meta.*;
import gplx.xowa.files.bins.*; import gplx.xowa.files.origs.*; import gplx.xowa.files.caches.*; import gplx.xowa.files.gui.*;
public interface Xof_fsdb_mgr {
Xof_bin_mgr Bin_mgr();
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, Xog_js_wkr js_wkr);
}

View File

@@ -0,0 +1,69 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.files.fsdb; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.core.primitives.*;
import gplx.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.files.gui.*;
public class Xof_fsdb_mgr__sql implements Xof_fsdb_mgr, GfoInvkAble {
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 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 Exc_.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_.I;
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);
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 Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_mnt_mgr)) return mnt_mgr;
else return GfoInvkAble_.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,110 @@
/*
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_dir {
private Gfo_usr_dlg usr_dlg; private Xof_img_wkr_query_img_size img_size_wkr;
private Io_url url; 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 fil_tbl;
private int fil_id_next = 0;
public void Init(Io_url url, Orig_fil_tbl fil_tbl, Gfo_usr_dlg usr_dlg, Xof_img_wkr_query_img_size img_size_wkr) {
this.url = url;
this.fil_tbl = fil_tbl; this.usr_dlg = usr_dlg; this.img_size_wkr = img_size_wkr;
}
public Orig_fil_itm Get_by_ttl(byte[] lnki_ttl) {
Orig_fil_itm rv = (Orig_fil_itm)cache.Get_by_ttl(lnki_ttl);
if (rv == null) {
rv = Get_from_db(lnki_ttl);
if (rv == null) {
rv = Get_from_fs(lnki_ttl);
if (rv == null) return Orig_fil_itm.Null;
}
cache.Add(rv);
}
return rv;
}
private Orig_fil_itm Get_from_db(byte[] lnki_ttl) {
if (conn == null) conn = Init_db_fil_mgr();
Orig_fil_itm rv = fil_tbl.Select_itm(lnki_ttl);
if (rv == null) return Orig_fil_itm.Null; // not in db
return rv;
}
private Orig_fil_itm Get_from_fs(byte[] lnki_ttl) {
if (fs_fil_mgr == null) fs_fil_mgr = Init_fs_fil_mgr();
Orig_fil_itm rv = fs_fil_mgr.Get_by_ttl(lnki_ttl);
if (rv == null) return Orig_fil_itm.Null; // not in fs
SizeAdp img_size = SizeAdp_.Zero;
if (Xof_ext_.Id_is_image(rv.Fil_ext_id()))
img_size = img_size_wkr.Exec(rv.Fil_url());
rv.Init_by_size(++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);
fil_tbl.Insert(rv);
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[] fils = Io_mgr.I.QueryDir_args(url).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 = Xto_fil_bry(fil);
Orig_fil_itm fil_itm = rv.Get_by_ttl(fil_name_bry);
if (fil_itm != Orig_fil_itm.Null) {
usr_dlg.Warn_many("", "", "file already exists: cur=~{0} new=~{1}", fil_itm.Fil_url().Raw(), fil.Raw());
continue;
}
Xof_ext ext = Xof_ext_.new_by_ttl_(fil_name_bry);
fil_itm = new Orig_fil_itm().Init_by_make(fil, fil_name_bry, ext.Id());
rv.Add(fil_itm);
}
return rv;
}
private Db_conn Init_db_fil_mgr() {
Io_url db_url = url.GenSubFil("^orig_regy.sqlite3");
boolean created = false; boolean schema_is_1 = Bool_.Y;
Db_conn conn = Db_conn_bldr.I.Get(db_url);
if (conn == null) {
conn = Db_conn_bldr.I.New(db_url);
created = true;
}
cfg_tbl = new Db_cfg_tbl(conn, schema_is_1 ? "fsdb_cfg" : "xowa_cfg");
fil_tbl.Conn_(conn, created, 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);
}
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();
fil_tbl.Rls();
}
private static final String Cfg_grp_root_dir = "xowa.root_dir", Cfg_key_fil_id_next = "fil_id_next";
public static byte[] Xto_fil_bry(Io_url url) {
byte[] rv = Bry_.new_u8(url.NameAndExt());
rv = Bry_.Replace(rv, Byte_ascii.Space, Byte_ascii.Underline);
rv = Bry_.Upper_1st(rv);
return rv;
}
}

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.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_dir_tst {
@Before public void init() {fxt.Reset();} private Fs_root_dir_fxt fxt = new Fs_root_dir_fxt();
@Test public void Basic() {
fxt.Init_fs("mem/dir/A.png", 200, 100);
fxt.Test_get("A.png", fxt.itm_().Url_("mem/dir/A.png").Size_(200, 100));
fxt.Test_db("A.png", fxt.itm_().Init(1, "mem/dir/A.png", 200, 100));
}
@Test public void Recurse() {
fxt.Init_fs("mem/dir/sub1/A1.png", 200, 100);
fxt.Test_get("A1.png", fxt.itm_().Url_("mem/dir/sub1/A1.png").Size_(200, 100));
}
@Test public void Xto_fil_bry() {
fxt.Test_xto_fil_bry("/dir/A.png" , "A.png"); // basic
fxt.Test_xto_fil_bry("/dir/A b.png" , "A_b.png"); // lower
fxt.Test_xto_fil_bry("/dir/a.png" , "A.png"); // title
}
}
class Fs_root_dir_fxt {
private Fs_root_dir root_dir = new Fs_root_dir();
private Orig_fil_tbl orig_fil_tbl;
private Io_url url;
public void Reset() {
Db_conn_bldr.I.Reg_default_mem();
Io_mgr.I.InitEngine_mem();
url = Io_url_.mem_dir_("mem/dir/");
root_dir = new Fs_root_dir();
orig_fil_tbl = new Orig_fil_tbl();
Xof_img_wkr_query_img_size img_size_wkr = new Xof_img_wkr_query_img_size_test();
root_dir.Init(url, orig_fil_tbl, Gfo_usr_dlg_.Noop, img_size_wkr);
}
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_itm 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_itm actl = orig_fil_tbl.Select_itm(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.I.SaveFilStr(url, img_size.XtoStr());
}
public void Test_xto_fil_bry(String url_str, String expd) {
Io_url url = Io_url_.new_fil_(url_str);
Tfds.Eq(expd, String_.new_u8(Fs_root_dir.Xto_fil_bry(url)));
}
}
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_itm actl) {
if (actl == null) Tfds.Fail("actl itm is null");
if (w != -1) Tfds.Eq(w, actl.Fil_w());
if (h != -1) Tfds.Eq(h, actl.Fil_h());
if (url != null) Tfds.Eq(url, actl.Fil_url().Raw());
if (uid != -1) Tfds.Eq(uid, actl.Fil_uid());
if (ext_id != -1) Tfds.Eq(uid, actl.Fil_ext_id());
if (name != null) Tfds.Eq(name, String_.new_u8(actl.Fil_name()));
}
}

View File

@@ -0,0 +1,49 @@
/*
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.ios.*;
import gplx.fsdb.*; import gplx.fsdb.data.*; import gplx.fsdb.meta.*;
import gplx.xowa.files.gui.*; import gplx.xowa.files.origs.*; import gplx.xowa.files.bins.*; import gplx.xowa.files.caches.*;
public class Fs_root_fsdb_mgr implements Xof_fsdb_mgr, GfoInvkAble { // read images from file-system dir
private Xowe_wiki wiki; private Fs_root_wkr_fsdb fsdb_wkr;
public Fs_root_fsdb_mgr(Xowe_wiki wiki) {this.Init_by_wiki(wiki); fsdb_wkr = new Fs_root_wkr_fsdb(wiki);}
public void Init_by_wiki(Xow_wiki wiki) {this.wiki = (Xowe_wiki)wiki;}
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();
for (int i = 0; i < itms_len; i++) {
Xof_fsdb_itm itm = (Xof_fsdb_itm)itms.Get_at(i);
if (fsdb_wkr.Find_file(itm))
Js_img_mgr.Update_img(page, js_wkr, itm);
}
}
private Io_url Xto_url(byte[] v) {
if (Op_sys.Cur().Tid_is_wnt())
v = Bry_.Replace(v, Byte_ascii.Slash, Byte_ascii.Backslash);
return Bry_fmtr_eval_mgr_.Eval_url(wiki.Appe().Url_cmd_eval(), v);
}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_root_dir_)) fsdb_wkr.Root_dir_(Xto_url(m.ReadBry("v")));
else if (ctx.Match(k, Invk_orig_dir_)) fsdb_wkr.Orig_dir_(Xto_url(m.ReadBry("v")));
else if (ctx.Match(k, Invk_thumb_dir_)) fsdb_wkr.Thumb_dir_(Xto_url(m.ReadBry("v")));
else return GfoInvkAble_.Rv_unhandled;
return this;
} private static final String Invk_root_dir_ = "root_dir_", Invk_orig_dir_ = "orig_dir_", Invk_thumb_dir_ = "thumb_dir_";
public Xof_bin_mgr Bin_mgr() {throw Exc_.new_unimplemented();}
public Fsm_mnt_mgr Mnt_mgr() {return null;}
public void Rls() {}
}

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.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.repos.*; import gplx.fsdb.meta.*;
public class Fs_root_wkr_fsdb {
private Xowe_wiki wiki;
private Io_url orig_dir, thumb_dir;
private Fs_root_dir orig_dir_mgr = new Fs_root_dir();
private String_obj_ref tmp_resize_result = String_obj_ref.null_();
private Xof_img_size img_size = new Xof_img_size();
public Fs_root_wkr_fsdb(Xowe_wiki wiki) {this.wiki = wiki;}
public boolean Find_file(Xof_fsdb_itm fsdb_itm) {
byte[] orig_ttl = fsdb_itm.Orig_ttl();
Orig_fil_itm orig_itm = orig_dir_mgr.Get_by_ttl(orig_ttl);
if (orig_itm == Orig_fil_itm.Null) return false;
Io_url orig_url = orig_itm.Fil_url();
if (fsdb_itm.File_is_orig()) {
fsdb_itm.Html_size_(orig_itm.Fil_w(), orig_itm.Fil_h());
fsdb_itm.Html_view_url_(orig_url);
fsdb_itm.Html_orig_url_(orig_url);
return true;
}
else {
String thumb_rel = orig_url.GenRelUrl_orEmpty(orig_dir);
int upright_patch = wiki.File_mgr().Patch_upright();
img_size.Html_size_calc(fsdb_itm.Lnki_exec_tid(), fsdb_itm.Lnki_w(), fsdb_itm.Lnki_h(), fsdb_itm.Lnki_type(), upright_patch, fsdb_itm.Lnki_upright(), fsdb_itm.Orig_ext().Id(), orig_itm.Fil_w(), orig_itm.Fil_h(), Xof_img_size.Thumb_width_img);
int html_w = img_size.Html_w(), html_h = img_size.Html_h();
String thumb_name = Int_.Xto_str(html_w) + orig_url.Ext();
Io_url thumb_url = thumb_dir.GenSubFil_ary(thumb_rel + orig_url.Info().DirSpr(), thumb_name);
if (!Io_mgr.I.ExistsFil(thumb_url)) {
if (!wiki.Appe().File_mgr().Img_mgr().Wkr_resize_img().Resize_exec(orig_url, thumb_url, html_w, html_h, fsdb_itm.Orig_ext().Id(), tmp_resize_result))
return false;
}
fsdb_itm.Html_size_(html_w, html_h);
fsdb_itm.Html_view_url_(thumb_url);
fsdb_itm.Html_orig_url_(orig_url);
return true;
}
}
public void Root_dir_(Io_url v) {
Io_url root_dir = v;
orig_dir = root_dir.GenSubDir("orig");
thumb_dir = root_dir.GenSubDir("thumb");
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) {
orig_dir_mgr.Init(orig_dir, new Orig_fil_tbl(), wiki.Appe().Usr_dlg(), wiki.Appe().File_mgr().Img_mgr().Wkr_query_img_size());
}
public void Thumb_dir_(Io_url v) {
thumb_dir = v;
}
}

View File

@@ -0,0 +1,46 @@
/*
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.*;
public class Orig_fil_itm {
public Orig_fil_itm() {}
public Orig_fil_itm(int uid, byte[] name, int ext_id, int w, int h, byte[] dir_url) {
this.fil_uid = uid; this.fil_name = name; this.fil_ext_id = ext_id; this.fil_w = w; this.fil_h = h; this.fil_dir_url = dir_url;
}
public int Fil_uid() {return fil_uid;} private int fil_uid;
public byte[] Fil_name() {return fil_name;} private byte[] fil_name;
public int Fil_ext_id() {return fil_ext_id;} private int fil_ext_id;
public int Fil_w() {return fil_w;} private int fil_w;
public int Fil_h() {return fil_h;} private int fil_h;
public byte[] Fil_dir_url() {return fil_dir_url;} private byte[] fil_dir_url;
public Io_url Fil_url() {
if (fil_url == null) {
byte[] fil_url_bry = Bry_.Add(fil_dir_url, fil_name);
fil_url = Io_url_.new_fil_(String_.new_u8(fil_url_bry));
}
return fil_url;
} private Io_url fil_url;
public Orig_fil_itm Init_by_make(Io_url url, byte[] name_bry, int ext_id) {
this.fil_url = url;
this.fil_name = name_bry;
this.fil_dir_url = Bry_.new_u8(url.OwnerDir().Raw());
this.fil_ext_id = ext_id;
return this;
}
public Orig_fil_itm Init_by_size(int uid, int w, int h) {this.fil_uid = uid; this.fil_w = w; this.fil_h = h; return this;}
public static final Orig_fil_itm Null = null;
}

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 Ordered_hash hash = Ordered_hash_.new_bry_();
public boolean Has(byte[] lnki_ttl) {return hash.Has(lnki_ttl);}
public Orig_fil_itm Get_by_ttl(byte[] lnki_ttl) {return (Orig_fil_itm)hash.Get_by(lnki_ttl);}
public void Add(Orig_fil_itm fil) {hash.Add(fil.Fil_name(), fil);}
}

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.fsdb.fs_roots; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*; import gplx.xowa.files.fsdb.*;
import gplx.dbs.*;
public class Orig_fil_tbl implements RlsAble {
private String tbl_name = "orig_fil"; private final Db_meta_fld_list flds = Db_meta_fld_list.new_();
private String fld_uid, fld_name, fld_ext_id, fld_w, fld_h, fld_dir_url;
private Db_conn conn; private Db_stmt stmt_insert, stmt_select;
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) {
fld_prefix = "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
if (created) {
Db_meta_tbl meta = Db_meta_tbl.new_(tbl_name, flds
, Db_meta_idx.new_unique_by_tbl(tbl_name, "main", fld_name)
);
conn.Ddl_create_tbl(meta);
}
stmt_insert = stmt_select = null;
conn.Rls_reg(this);
}
public void Rls() {
stmt_insert = Db_stmt_.Rls(stmt_insert);
stmt_select = Db_stmt_.Rls(stmt_select);
}
public Orig_fil_itm Select_itm(byte[] ttl) {
if (stmt_select == null) stmt_select = conn.Stmt_select(tbl_name, flds, fld_name);
Orig_fil_itm rv = Orig_fil_itm.Null;
Db_rdr rdr = stmt_select.Clear().Crt_bry_as_str(fld_name, ttl).Exec_select__rls_manual();
try {
if (rdr.Move_next())
rv = Load_itm(rdr);
return rv;
}
finally {rdr.Rls();}
}
private Orig_fil_itm Load_itm(Db_rdr rdr) {
return new Orig_fil_itm
( rdr.Read_int(fld_uid)
, rdr.Read_bry_by_str(fld_name)
, rdr.Read_int(fld_ext_id)
, rdr.Read_int(fld_w)
, rdr.Read_int(fld_h)
, rdr.Read_bry_by_str(fld_dir_url)
);
}
public void Insert(Orig_fil_itm fil_itm) {
if (stmt_insert == null) stmt_insert = conn.Stmt_insert(tbl_name, flds);
stmt_insert.Clear()
.Val_int(fld_uid, fil_itm.Fil_uid())
.Val_bry_as_str(fld_name, fil_itm.Fil_name())
.Val_int(fld_ext_id, fil_itm.Fil_ext_id())
.Val_int(fld_w, fil_itm.Fil_w())
.Val_int(fld_h, fil_itm.Fil_h())
.Val_bry_as_str(fld_dir_url, fil_itm.Fil_dir_url())
.Exec_insert();
}
}

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.*;
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");
}
}

View File

@@ -0,0 +1,189 @@
/*
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 gplx.fsdb.*; import gplx.fsdb.meta.*; import gplx.dbs.*; import gplx.xowa.files.origs.*; import gplx.xowa.files.bins.*; import gplx.xowa.files.cnvs.*; import gplx.xowa.files.exts.*; import gplx.xowa.files.gui.*;
import gplx.xowa.wikis.*; import gplx.xowa.files.repos.*; import gplx.xowa.wikis.data.*;
import gplx.fsdb.data.*;
class Xof_file_fxt {
private Xoae_app app; private Xof_fsdb_mgr__sql fsdb_mgr; private Xowe_wiki wiki; private Xof_orig_mgr orig_mgr;
private final Fsd_thm_itm tmp_thm = Fsd_thm_itm.new_(); private final Fsd_img_itm tmp_img = new Fsd_img_itm();
public void Rls() {}
public void Reset() {
Io_mgr.I.InitEngine_mem(); // NOTE: files are downloaded to mem_engine, regardless of Db being mem or sqlite; always reset
Io_url root_url = Xoa_test_.Url_root();
Xoa_test_.Db_init(root_url);
app = Xoa_app_fxt.app_(Op_sys.Cur().Os_name(), root_url);
wiki = Xoa_app_fxt.wiki_tst_(app);
wiki.File__fsdb_mode().Tid_v2_bld_y_();
this.fsdb_mgr = (Xof_fsdb_mgr__sql)wiki.File_mgr().Fsdb_mgr();
this.orig_mgr = wiki.File__orig_mgr();
Xof_repo_fxt.Repos_init(app.File_mgr(), true, wiki);
Xowe_wiki_bldr.Create(wiki, 1, "dump.xml");
Xowd_db_file text_db = wiki.Data__core_mgr().Dbs__make_by_tid(Xowd_db_file_.Tid_text); text_db.Tbl__text().Create_tbl();
Fsdb_db_mgr__v2 fsdb_core = Fsdb_db_mgr__v2_bldr.I.Get_or_make(wiki, Bool_.Y);
fsdb_mgr.Mnt_mgr().Ctor_by_load(fsdb_core);
fsdb_mgr.Mnt_mgr().Mnts__get_main().Bin_mgr().Dbs__make("temp.xowa");
wiki.File_mgr().Init_file_mgr_by_load(wiki);
fsdb_mgr.Bin_mgr().Wkrs__del(Xof_bin_wkr_.Key_http_wmf); // never use http_wmf wkr for these tests
Xof_bin_wkr__fsdb_sql bin_wkr_fsdb = (Xof_bin_wkr__fsdb_sql)fsdb_mgr.Bin_mgr().Wkrs__get_or_null(Xof_bin_wkr_.Key_fsdb_wiki);
fsdb_mgr.Bin_mgr().Resizer_(Xof_img_wkr_resize_img_mok._);
bin_wkr_fsdb.Resize_allowed_(true);
}
public void Init__orig_w_fsdb__commons_orig(String ttl, int w, int h) {
this.Init_fsdb_db(Xof_fsdb_arg.new_comm(Bool_.N, ttl, w, h));
this.Init_orig_db(Xof_orig_arg.new_comm(ttl, w, h));
}
public void Init_orig_db(Xof_orig_arg arg) {
orig_mgr.Insert(arg.Repo(), arg.Page(), Xof_ext_.new_by_ttl_(arg.Page()).Id(), arg.W(), arg.H(), arg.Redirect());
}
public void Init_fsdb_db(Xof_fsdb_arg arg) {
Fsm_mnt_itm mnt_itm = fsdb_mgr.Mnt_mgr().Mnts__get_main();
Fsm_atr_fil atr_fil = mnt_itm.Atr_mgr().Db__core();
Fsm_bin_fil bin_fil = mnt_itm.Bin_mgr().Dbs__get_nth();
if (arg.Is_thumb())
mnt_itm.Insert_thm(tmp_thm, atr_fil, bin_fil, arg.Wiki(), arg.Ttl(), arg.Ext(), arg.W(), arg.H(), arg.Time(), arg.Page(), arg.Bin().length, gplx.ios.Io_stream_rdr_.mem_(arg.Bin()));
else
mnt_itm.Insert_img(tmp_img, atr_fil, bin_fil, arg.Wiki(), arg.Ttl(), arg.Ext(), arg.W(), arg.H(), arg.Bin().length, gplx.ios.Io_stream_rdr_.mem_(arg.Bin()));
}
public void Exec_get(Xof_exec_arg arg) {
byte[] ttl_bry = arg.Ttl();
Xof_fsdb_itm itm = new Xof_fsdb_itm();
itm.Init_at_lnki(arg.Exec_tid(), wiki.Domain_itm().Abrv_xo(), ttl_bry, arg.Lnki_type(), arg.Lnki_upright(), arg.Lnki_w(), arg.Lnki_h(), arg.Lnki_time(), Xof_lnki_page.Null, Xof_patch_upright_tid_.Tid_all);
List_adp itms_list = List_adp_.new_(); itms_list.Add(itm);
orig_mgr.Find_by_list(Ordered_hash_.new_bry_(), itms_list, Xof_exec_tid.Tid_wiki_page);
Xoa_ttl ttl = Xoa_ttl.parse_(wiki, Xow_ns_.Id_main, ttl_bry);
Xoae_page page = Xoae_page.new_(wiki, ttl);
fsdb_mgr.Fsdb_search_by_list(itms_list, wiki, page, Xog_js_wkr_.Noop);
if (arg.Rslt_orig_exists() != Bool_.__byte) Tfds.Eq(arg.Rslt_orig_exists() == Bool_.Y_byte, itm.Orig_exists(), "orig_exists");
if (arg.Rslt_file_exists() != Bool_.__byte) Tfds.Eq(arg.Rslt_file_exists() == Bool_.Y_byte, itm.File_exists(), "file_exists");
if (arg.Rslt_file_resized() != Bool_.__byte) Tfds.Eq(arg.Rslt_file_resized() == Bool_.Y_byte, itm.File_resized(), "file_resize");
}
public void Test_fsys_exists_y(String url) {Test_fsys_exists(url, Bool_.Y);}
public void Test_fsys_exists_n(String url) {Test_fsys_exists(url, Bool_.N);}
public void Test_fsys_exists(String url, boolean expd) {Tfds.Eq(expd, Io_mgr.I.ExistsFil(Io_url_.new_any_(url)));}
public void Test_fsys(String url, String expd_bin) {Tfds.Eq(expd_bin, Io_mgr.I.LoadFilStr(url));}
}
class Xof_repo_fxt {
public static void Repos_init(Xof_file_mgr file_mgr, boolean src_repo_is_wmf, Xowe_wiki wiki) {
byte[] src_commons = Bry_.new_a7("src_commons");
byte[] src_en_wiki = Bry_.new_a7("src_en_wiki");
byte[] trg_commons = Bry_.new_a7("trg_commons");
byte[] trg_en_wiki = Bry_.new_a7("trg_en_wiki");
Ini_repo_add(file_mgr, src_commons, "mem/src/commons.wikimedia.org/", Xow_domain_.Domain_str_commons, false);
Ini_repo_add(file_mgr, src_en_wiki, "mem/src/en.wikipedia.org/" , Xow_domain_.Domain_str_enwiki, false);
Ini_repo_add(file_mgr, trg_commons, "mem/root/common/", Xow_domain_.Domain_str_commons, true).Primary_(true);
Ini_repo_add(file_mgr, trg_en_wiki, "mem/root/enwiki/", Xow_domain_.Domain_str_enwiki, true).Primary_(true);
Xowe_repo_mgr wiki_repo_mgr = wiki.File_mgr().Repo_mgr();
Xof_repo_pair pair = null;
pair = wiki_repo_mgr.Add_repo(src_commons, trg_commons);
pair.Src().Fsys_is_wnt_(true).Wmf_fsys_(src_repo_is_wmf).Tarball_(!src_repo_is_wmf);
pair.Trg().Fsys_is_wnt_(true);
pair = wiki_repo_mgr.Add_repo(src_en_wiki, trg_en_wiki);
pair.Src().Fsys_is_wnt_(true).Wmf_fsys_(src_repo_is_wmf);
pair.Trg().Fsys_is_wnt_(true);
}
private static Xof_repo_itm Ini_repo_add(Xof_file_mgr file_mgr, byte[] key, String root, String wiki, boolean trg) {
return file_mgr.Repo_mgr().Set(String_.new_u8(key), root, wiki).Ext_rules_(Xof_rule_grp.Grp_app_default).Dir_depth_(2);
}
}
class Xof_orig_arg {
Xof_orig_arg(byte repo, byte[] page, int w, int h, byte[] redirect) {this.repo = repo; this.page = page; this.w = w; this.h = h; this.redirect = redirect;}
public byte Repo() {return repo;} private final byte repo;
public byte[] Page() {return page;} private final byte[] page;
public int W() {return w;} private final int w;
public int H() {return h;} private final int h;
public byte[] Redirect() {return redirect;} private final byte[] redirect;
public static Xof_orig_arg new_comm_file(String page) {return new_(Bool_.Y, page, Xof_img_size.Size_null, Xof_img_size.Size_null);}
public static Xof_orig_arg new_comm(String page, int w, int h) {return new_(Bool_.Y, page, w, h);}
public static Xof_orig_arg new_wiki(String page, int w, int h) {return new_(Bool_.N, page, w, h);}
public static Xof_orig_arg new_wiki_redirect(String src, String trg) {return new_(Bool_.N, src, 440, 400, trg);}
public static Xof_orig_arg new_comm_redirect(String src, String trg) {return new_(Bool_.Y, src, 440, 400, trg);}
private static Xof_orig_arg new_(boolean repo_is_commons, String page, int w, int h) {return new_(repo_is_commons, page, w, h, null);}
public static Xof_orig_arg new_(boolean repo_is_commons, String page, int w, int h, String redirect_str) {
byte repo = repo_is_commons ? Xof_repo_itm_.Repo_remote : Xof_repo_itm_.Repo_local;
byte[] redirect = redirect_str == null ? Bry_.Empty : Bry_.new_u8(redirect_str);
return new Xof_orig_arg(repo, Bry_.new_u8(page), w, h, redirect);
}
}
class Xof_fsdb_arg {
Xof_fsdb_arg(byte[] wiki, byte[] ttl, boolean is_thumb, int ext, int w, int h, int time, byte[] bin) {
this.wiki = wiki; this.ttl = ttl; this.is_thumb = is_thumb; this.w = w; this.h = h; this.time = time; this.ext = ext; this.bin = bin;
}
public byte[] Wiki() {return wiki;} private final byte[] wiki;
public byte[] Ttl() {return ttl;} private final byte[] ttl;
public int Ext() {return ext;} private final int ext;
public boolean Is_thumb() {return is_thumb;} private final boolean is_thumb;
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 = Xof_lnki_page.Null;
public byte[] Bin() {return bin;} private final byte[] bin;
public DateAdp Modified() {return modified;} private final DateAdp modified = Fsd_thm_tbl.Modified_null;
public String Hash() {return hash;} private final String hash = Fsd_thm_tbl.Hash_null;
public static Xof_fsdb_arg new_comm_file(String ttl) {return new_(Xow_domain_.Domain_bry_commons, Bool_.N, ttl, Xof_img_size.Null, Xof_img_size.Null, Xof_lnki_time.Null_as_int);}
public static Xof_fsdb_arg new_comm_thumb(String ttl) {return new_(Xow_domain_.Domain_bry_commons, Bool_.Y, ttl, W_default, H_default, Xof_lnki_time.Null_as_int);}
public static Xof_fsdb_arg new_comm_thumb(String ttl, int w, int h) {return new_(Xow_domain_.Domain_bry_commons, Bool_.Y, ttl, w, h, Xof_lnki_time.Null_as_int);}
public static Xof_fsdb_arg new_comm_thumb(String ttl, int w, int h, int s) {return new_(Xow_domain_.Domain_bry_commons, Bool_.Y, ttl, w, h, s);}
public static Xof_fsdb_arg new_comm_orig(String ttl, int w, int h) {return new_(Xow_domain_.Domain_bry_commons, Bool_.N, ttl, w, h, Xof_lnki_time.Null_as_int);}
public static Xof_fsdb_arg new_comm(boolean thumb, String ttl, int w, int h) {return new_(Xow_domain_.Domain_bry_commons, thumb, ttl, w, h, Xof_lnki_time.Null_as_int);}
public static Xof_fsdb_arg new_wiki_thumb(String ttl, int w, int h) {return new_(Xow_domain_.Domain_bry_enwiki, Bool_.Y, ttl, w, h, Xof_lnki_time.Null_as_int);}
public static Xof_fsdb_arg new_wiki_orig(String ttl, int w, int h) {return new_(Xow_domain_.Domain_bry_enwiki, Bool_.N, ttl, w, h, Xof_lnki_time.Null_as_int);}
public static Xof_fsdb_arg new_(byte[] wiki, boolean is_thumb, String ttl_str, int w, int h, int time) {
byte[] ttl = Bry_.new_u8(ttl_str);
int ext = Xof_ext_.new_by_ttl_(ttl).Id();
String bin_str = ext == Xof_ext_.Id_svg ? file_svg_(w, h) : file_img_(w, h);
byte[] bin = Bry_.new_a7(bin_str);
return new Xof_fsdb_arg(wiki, ttl, is_thumb, ext, w, h, time, bin);
}
private static final int W_default = 220, H_default = 200;
private static String file_img_(int w, int h) {return String_.Format("{0},{1}", w, h);}
private static String file_svg_(int w, int h) {return String_.Format("<svg width=\"{0}\" height=\"{1}\" />", w, h);}
}
class Xof_exec_arg {
public byte[] Ttl() {return ttl;} private byte[] ttl;
public byte Lnki_type() {return lnki_type;} private byte lnki_type = Xop_lnki_type.Id_thumb;
public int Lnki_w() {return lnki_w;} private int lnki_w;
public int Lnki_h() {return lnki_h;} private int lnki_h = Xop_lnki_tkn.Height_null;
public double Lnki_upright() {return lnki_upright;} public Xof_exec_arg Lnki_upright_(double v) {lnki_upright = v; return this;} private double lnki_upright = Xop_lnki_tkn.Upright_null;
public int Lnki_time() {return lnki_time;} public Xof_exec_arg Lnki_time_(int v) {lnki_time = v; return this;} private int lnki_time = Xof_lnki_time.Null_as_int;
public int Lnki_page() {return lnki_page;} public Xof_exec_arg Lnki_page_(int v) {lnki_page = v; return this;} private int lnki_page = Xof_lnki_page.Null;
public int Exec_tid() {return exec_tid;} public Xof_exec_arg Exec_tid_(int v) {exec_tid = v; return this;} private int exec_tid = Xof_exec_tid.Tid_wiki_page;
public byte Rslt_orig_exists() {return rslt_orig_exists;} private byte rslt_orig_exists = Bool_.__byte;
public byte Rslt_file_exists() {return rslt_file_exists;} private byte rslt_file_exists = Bool_.__byte;
public byte Rslt_file_resized() {return rslt_file_resized;} private byte rslt_file_resized = Bool_.__byte;
public boolean Lnki_type_is_thumb() {return Xop_lnki_type.Id_defaults_to_thumb(lnki_type);}
public Xof_exec_arg Rslt_orig_exists_n() {rslt_orig_exists = Bool_.N_byte; return this;}
public Xof_exec_arg Rslt_orig_exists_y() {rslt_orig_exists = Bool_.Y_byte; return this;}
public Xof_exec_arg Rslt_file_exists_n() {rslt_file_exists = Bool_.N_byte; return this;}
public Xof_exec_arg Rslt_file_exists_y() {rslt_file_exists = Bool_.Y_byte; return this;}
public Xof_exec_arg Rslt_file_resized_n() {rslt_file_resized = Bool_.N_byte; return this;}
public Xof_exec_arg Rslt_file_resized_y() {rslt_file_resized = Bool_.Y_byte; return this;}
public static Xof_exec_arg new_thumb(String ttl) {return new_(ttl, Xop_lnki_type.Id_thumb, 220, Xop_lnki_tkn.Height_null);}
public static Xof_exec_arg new_thumb(String ttl, int w) {return new_(ttl, Xop_lnki_type.Id_thumb, w, Xop_lnki_tkn.Height_null);}
public static Xof_exec_arg new_thumb(String ttl, int w, int h) {return new_(ttl, Xop_lnki_type.Id_thumb, w, h);}
public static Xof_exec_arg new_orig(String ttl) {return new_(ttl, Xop_lnki_type.Id_null, Xop_lnki_tkn.Width_null, Xop_lnki_tkn.Height_null);}
public static Xof_exec_arg new_(String ttl, byte type, int w, int h) {
Xof_exec_arg rv = new Xof_exec_arg();
rv.ttl = Bry_.new_u8(ttl);
rv.lnki_type = type;
rv.lnki_w = w;
rv.lnki_h = h;
return rv;
}
}

View File

@@ -0,0 +1,66 @@
/*
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_redirect_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 Same_wiki_orig_copy() {
fxt.Init_orig_db(Xof_orig_arg.new_wiki("A.png", 440, 400));
fxt.Init_fsdb_db(Xof_fsdb_arg.new_wiki_orig("A.png", 440, 400));
fxt.Init_orig_db(Xof_orig_arg.new_wiki_redirect("B.png", "A.png"));
fxt.Exec_get(Xof_exec_arg.new_orig("B.png").Rslt_file_exists_y());
fxt.Test_fsys("mem/root/enwiki/orig/7/0/A.png", "440,400");
}
@Test public void Same_wiki_thumb_copy() {
fxt.Init_orig_db(Xof_orig_arg.new_wiki("A.png", 440, 400));
fxt.Init_fsdb_db(Xof_fsdb_arg.new_wiki_thumb("A.png", 220, 200));
fxt.Init_orig_db(Xof_orig_arg.new_wiki_redirect("B.png", "A.png"));
fxt.Exec_get(Xof_exec_arg.new_thumb("B.png", 220).Rslt_file_exists_y());
fxt.Test_fsys("mem/root/enwiki/thumb/7/0/A.png/220px.png", "220,200");
}
@Test public void Same_wiki_thumb_make() {
fxt.Init_orig_db(Xof_orig_arg.new_wiki("A.png", 440, 400));
fxt.Init_fsdb_db(Xof_fsdb_arg.new_wiki_orig("A.png", 440, 400));
fxt.Init_orig_db(Xof_orig_arg.new_wiki_redirect("B.png", "A.png"));
fxt.Exec_get(Xof_exec_arg.new_thumb("B.png", 220).Rslt_file_exists_y().Rslt_file_resized_y());
fxt.Test_fsys("mem/root/enwiki/thumb/7/0/A.png/220px.png", "220,200");
}
@Test public void Diff_wiki_orig_copy() {
fxt.Init_orig_db(Xof_orig_arg.new_comm("A.png", 440, 400));
fxt.Init_fsdb_db(Xof_fsdb_arg.new_comm_orig("A.png", 440, 400));
fxt.Init_orig_db(Xof_orig_arg.new_comm_redirect("B.png", "A.png"));
fxt.Exec_get(Xof_exec_arg.new_orig("B.png").Rslt_file_exists_y());
fxt.Test_fsys("mem/root/common/orig/7/0/A.png", "440,400");
}
// @Test public void Cross_wiki() {
// fxt.Init__orig_w_fsdb__commons_orig("A.png", 440, 400);
// fxt.Init_orig_db(Xof_orig_arg.new_wiki_redirect("B.png", "A.png"));
// fxt.Exec_get(Xof_exec_arg.new_orig("B.png").Rslt_fsdb_xowa());
// fxt.Test_fsys("mem/root/common/orig/7/0/A.png", "440,400");
// fxt .ini_page_create_en_wiki_redirect ("File:B.png", "File:A.png");
// fxt .ini_page_create_commons ("File:A.png");
// fxt .Lnki_orig_("B.png")
// .Src( fxt.img_("mem/src/commons.wikimedia.org/7/70/A.png", 900, 800))
// .Trg( fxt.img_("mem/trg/commons.wikimedia.org/raw/7/0/A.png", 900, 800)
// , fxt.reg_("mem/xowa/file/#meta/en.wikipedia.org/5/57.csv" , "B.png|y|A.png|1?900,800|")
// );
// fxt.tst();
// }
}

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.gui; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.xowa.xtns.gallery.*;
import gplx.xowa.files.fsdb.*; import gplx.xowa.gui.views.*;
public class Js_img_mgr {
public static void Update_img(Xoa_page page, Xog_js_wkr js_wkr, Xof_file_itm itm) {
Js_img_mgr.Update_img(page, js_wkr, itm.Html_img_wkr(), itm.Html_uid(), itm.Lnki_type(), itm.Html_elem_tid(), itm.Html_w(), itm.Html_h(), itm.Html_view_url(), itm.Orig_w(), itm.Orig_h(), itm.Html_orig_url(), itm.Orig_ttl(), itm.Html_gallery_mgr_h());
}
public static void Update_link_missing(Xog_html_itm html_itm, String html_id) {
html_itm.Html_redlink(html_id);
}
private static void Update_img(Xoa_page page, Xog_js_wkr js_wkr, Js_img_wkr img_wkr, int uid, byte lnki_type, byte elem_tid, int html_w, int html_h, Io_url html_view_url, int orig_w, int orig_h, Io_url html_orig_url, byte[] lnki_ttl, int gallery_mgr_h) {
if (!page.Wiki().App().App_type().Uid_is_gui()) return; // do not update html widget unless app is gui; null ref on http server; DATE:2014-09-17
switch (elem_tid) {
case Xof_html_elem.Tid_gallery_v2:
img_wkr.Html_update(page, js_wkr, uid, html_w, html_h, html_view_url, orig_w, orig_h, html_orig_url, lnki_ttl);
return;
}
String html_id = To_doc_uid(uid);
js_wkr.Html_img_update(html_id, html_view_url.To_http_file_str(), html_w, html_h);
if (Xop_lnki_type.Id_is_thumbable(lnki_type)) { // thumb needs to set cls and width
js_wkr.Html_atr_set(html_id, "class", gplx.xowa.html.lnkis.Xoh_lnki_consts.Str_img_cls_thumbimage);
js_wkr.Html_atr_set("xowa_file_div_" + uid, "style", "width:" + html_w + "px;");
}
switch (elem_tid) {
case Xof_html_elem.Tid_gallery:
js_wkr.Html_atr_set("xowa_gallery_div3_" + uid, "style", "margin:" + Gallery_html_wtr_utl.Calc_vpad(gallery_mgr_h, html_h) + "px auto;");
break;
case Xof_html_elem.Tid_imap:
img_wkr.Html_update(page, js_wkr, uid, html_w, html_h, html_view_url, orig_w, orig_h, html_orig_url, lnki_ttl);
break;
case Xof_html_elem.Tid_vid:
String html_id_vid = "xowa_file_play_" + uid;
js_wkr.Html_atr_set(html_id_vid, "style", "width:" + html_w + "px;max-width:" + (html_w - 2) + "px;");
js_wkr.Html_atr_set(html_id_vid, "href", html_orig_url.To_http_file_str());
break;
}
}
public static String To_doc_uid(int html_uid) {return "xowa_file_img_" + Int_.Xto_str(html_uid);}
}

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.gui; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.xowa.gui.views.*;
public interface Js_img_wkr {
void Html_update(Xoa_page page, Xog_js_wkr js_wkr, int html_uid, int html_w, int html_h, Io_url html_view_url, int orig_w, int orig_h, Io_url html_orig_url, byte[] lnki_ttl);
}

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.gui; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
public interface Xog_js_wkr {
void Html_img_update (String uid, String src, int w, int h);
void Html_redlink (String html_uid);
void Html_atr_set (String uid, String key, String val);
void Html_elem_replace_html (String uid, String html);
void Html_elem_append_above (String uid, String html);
}

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.gui; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
public class Xog_js_wkr_ {
public static final Xog_js_wkr Noop = new Xog_js_wkr__noop();
}
class Xog_js_wkr__noop implements Xog_js_wkr {
public void Html_img_update (String uid, String src, int w, int h) {}
public void Html_atr_set (String uid, String key, String val) {}
public void Html_elem_replace_html (String uid, String html) {}
public void Html_elem_append_above (String uid, String html) {}
public void Html_redlink (String html_uid) {}
}

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.gui; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
public class Xog_js_wkr__log implements Xog_js_wkr {
private final List_adp log_list = List_adp_.new_();
public void Html_img_update (String uid, String src, int w, int h) {log_list.Add(Object_.Ary(Proc_img_update, uid, src, w, h));}
public void Html_atr_set (String uid, String key, String val) {log_list.Add(Object_.Ary(Proc_atr_set, uid, key, val));}
public void Html_redlink (String uid) {log_list.Add(Object_.Ary(Proc_redlink, uid));}
public void Html_elem_replace_html (String uid, String html) {log_list.Add(Object_.Ary(Proc_replace_html, uid, html));}
public void Html_elem_append_above (String uid, String html) {log_list.Add(Object_.Ary(Proc_append_above, uid, html));}
public void Log__clear() {log_list.Clear();}
public int Log__len() {return log_list.Count();}
public Object[] Log__get_at(int i) {return (Object[])log_list.Get_at(i);}
public static final String
Proc_img_update = "img_update", Proc_atr_set = "atr_set", Proc_redlink = "redlink", Proc_replace_html = "replace_html", Proc_append_above = "append_above"
;
}

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.imgs; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.xowa.apps.progs.*; import gplx.xowa.wmfs.*; import gplx.xowa.files.cnvs.*;
public class Xof_img_mgr {
public Xof_img_wkr_resize_img Wkr_resize_img() {return wkr_resize_img;} public void Wkr_resize_img_(Xof_img_wkr_resize_img v) {wkr_resize_img = v;} private Xof_img_wkr_resize_img wkr_resize_img;
public Xof_img_wkr_query_img_size Wkr_query_img_size() {return wkr_query_img_size;} public void Wkr_query_img_size_(Xof_img_wkr_query_img_size v) {wkr_query_img_size = v;} private Xof_img_wkr_query_img_size wkr_query_img_size;
public Xof_img_wkr_convert_djvu_to_tiff Wkr_convert_djvu_to_tiff() {return wkr_convert_djvu_to_tiff;} public Xof_img_mgr Wkr_convert_djvu_to_tiff_(Xof_img_wkr_convert_djvu_to_tiff v) {wkr_convert_djvu_to_tiff = v; return this;} private Xof_img_wkr_convert_djvu_to_tiff wkr_convert_djvu_to_tiff;
public void Init_by_app(Xowmf_mgr wmf_mgr, Xoa_prog_mgr prog_mgr) {
wkr_resize_img = new Xof_img_wkr_resize_img_imageMagick(wmf_mgr, prog_mgr.App_resize_img(), prog_mgr.App_convert_svg_to_png());
wkr_query_img_size = new Xof_img_wkr_query_img_size_imageMagick(wmf_mgr, prog_mgr.App_query_img_size());
wkr_convert_djvu_to_tiff = new Xof_img_wkr_convert_djvu_to_tiff_app(prog_mgr.App_convert_djvu_to_tiff());
}
}

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.imgs; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
public interface Xof_img_wkr_convert_djvu_to_tiff {
boolean Exec(Io_url src, Io_url trg);
}

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.imgs; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
public class Xof_img_wkr_convert_djvu_to_tiff_ {
public static Xof_img_wkr_convert_djvu_to_tiff new_app(ProcessAdp process) {return new Xof_img_wkr_convert_djvu_to_tiff_app(process);}
public static Xof_img_wkr_convert_djvu_to_tiff new_mok(int w, int h) {return new Xof_img_wkr_convert_djvu_to_tiff_mok(w, h);}
}
class Xof_img_wkr_convert_djvu_to_tiff_app implements Xof_img_wkr_convert_djvu_to_tiff {
public Xof_img_wkr_convert_djvu_to_tiff_app(ProcessAdp process) {this.process = process;} ProcessAdp process;
public boolean Exec(Io_url src, Io_url trg) {
process.Run(src, trg);
return process.Exit_code_pass();
}
}
class Xof_img_wkr_convert_djvu_to_tiff_mok implements Xof_img_wkr_convert_djvu_to_tiff {
public Xof_img_wkr_convert_djvu_to_tiff_mok(int w, int h) {this.w = w; this.h = h;} private int w, h;
public boolean Exec(Io_url src, Io_url trg) {
Io_mgr.I.SaveFilStr(trg, gplx.gfui.SizeAdp_.new_(w, h).XtoStr());
return true;
}
}

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.imgs; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.gfui.*;
import gplx.xowa.wmfs.*;
public interface Xof_img_wkr_query_img_size {
SizeAdp Exec(Io_url url);
}
class Xof_img_wkr_query_img_size_imageMagick implements Xof_img_wkr_query_img_size {
private final Xowmf_mgr wmf_mgr; private final ProcessAdp cmd;
public Xof_img_wkr_query_img_size_imageMagick(Xowmf_mgr wmf_mgr, ProcessAdp cmd) {this.wmf_mgr = wmf_mgr; this.cmd = cmd;}
public SizeAdp Exec(Io_url url) {
cmd.Prog_fmt_(String_.Replace(wmf_mgr.Download_wkr().Download_xrg().Prog_fmt_hdr(), "~", "~~") + " querying: ~{process_seconds} second(s); ~{process_exe_name} ~{process_exe_args}");
cmd.Run(url);
String size_str = cmd.Rslt_out();
int pos_bgn = String_.FindFwd(size_str, "<{", 0); if (pos_bgn == String_.Find_none) return SizeAdp_.Zero; // NOTE: RE: "FindFwd(,0)"; multiple frames are possible; 1st frame must be used as last frame is not accurate; EX:w.Chess:[[File:ChessCastlingMovie.gif|thumb|250px]]
int pos_end = String_.FindFwd(size_str, "}>", pos_bgn); if (pos_end == String_.Find_none) return SizeAdp_.Zero;
size_str = String_.Mid(size_str, pos_bgn + Marker_bgn_len, pos_end);
return SizeAdp_.parse_or_(size_str, SizeAdp_.Zero);
}
static final String Marker_bgn = "<{", Marker_end = "}>"; static final int Marker_bgn_len = String_.Len(Marker_bgn);
}

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.imgs; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.gfui.*;
public class Xof_img_wkr_query_img_size_test implements Xof_img_wkr_query_img_size {
public SizeAdp Exec(Io_url url) {
ImageAdp image = ImageAdp_.txt_fil_(url);
return image.Size();
}
}

View File

@@ -0,0 +1,120 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.files.origs; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.dbs.*; import gplx.dbs.engines.sqlite.*; import gplx.xowa.bldrs.*; import gplx.fsdb.*;
public class Xob_orig_tbl_bldr extends Xob_itm_basic_base implements Xob_cmd {
private Db_conn conn; private boolean schema_1;
public Xob_orig_tbl_bldr(Xob_bldr bldr, Xowe_wiki wiki) {this.Cmd_ctor(bldr, wiki);}
public String Cmd_key() {return Xob_cmd_keys.Key_file_orig_reg;}
public void Cmd_init(Xob_bldr bldr) {}
public void Cmd_bgn(Xob_bldr bldr) {
Xof_fsdb_mode fsdb_mode = wiki.File__fsdb_mode();
fsdb_mode.Tid_v2_bld_y_();
wiki.Init_assert();
Fsdb_db_mgr db_core_mgr = Fsdb_db_mgr_.new_detect(wiki, wiki.Fsys_mgr().Root_dir(), wiki.Fsys_mgr().File_dir());
this.schema_1 = db_core_mgr.File__schema_is_1();
conn = db_core_mgr.File__orig_tbl_ary()[gplx.fsdb.meta.Fsm_mnt_mgr.Mnt_idx_main].Conn();
Io_url make_db_url = Xob_db_file.new__file_make(wiki.Fsys_mgr().Root_dir()).Url();
Sqlite_engine_.Db_attach(conn, "make_db", make_db_url.Raw());
}
public void Cmd_run() {Exec();}
public void Cmd_end() {}
public void Cmd_term() {}
private void Exec() {
String tbl_name = "orig_reg", fld_status = "orig_status";
if (schema_1) {
tbl_name = "wiki_orig";
fld_status = "status";
}
conn.Exec_sql_plog_txn("orig_wkr.deleting orig_reg" , String_.Format(Sql_delete_wiki_orig, tbl_name)); // always delete orig_reg, else will not pick up changed sizes / moved repos; DATE:2014-07-21
conn.Exec_sql_plog_txn("orig_wkr.inserting xfer direct" , String_.Format(Sql_create_xfer_direct, tbl_name, fld_status));
conn.Exec_sql_plog_txn("orig_wkr.inserting xfer redirect" , String_.Format(Sql_create_xfer_redirect, tbl_name, fld_status));
conn.Exec_sql_plog_txn("orig_wkr.inserting orig direct" , String_.Format(Sql_create_orig_direct, tbl_name, fld_status));
conn.Exec_sql_plog_txn("orig_wkr.inserting orig redirect" , String_.Format(Sql_create_orig_redirect, tbl_name, fld_status));
}
private static final String
Sql_delete_wiki_orig = "DELETE FROM {0};"
, Sql_create_xfer_direct = String_.Concat_lines_nl
( "INSERT INTO {0} "
, "(orig_ttl, {1}, orig_repo, orig_ext, orig_w, orig_h, orig_redirect)"
, "SELECT DISTINCT"
, " xfer.lnki_ttl"
, ", 1 --pass"
, ", xfer.orig_repo"
, ", xfer.lnki_ext"
, ", xfer.orig_w"
, ", xfer.orig_h"
, ", ''"
, "FROM make_db.xfer_regy xfer"
, " LEFT JOIN {0} cur ON xfer.lnki_ttl = cur.orig_ttl"
, "WHERE cur.orig_ttl IS NULL"
)
, Sql_create_xfer_redirect = String_.Concat_lines_nl
( "INSERT INTO {0} "
, "(orig_ttl, {1}, orig_repo, orig_ext, orig_w, orig_h, orig_redirect)"
, "SELECT DISTINCT"
, " xfer.orig_redirect_src"
, ", 1 --pass"
, ", xfer.orig_repo"
, ", xfer.lnki_ext"
, ", xfer.orig_w"
, ", xfer.orig_h"
, ", xfer.lnki_ttl"
, "FROM make_db.xfer_regy xfer"
, " LEFT JOIN {0} cur ON xfer.orig_redirect_src = cur.orig_ttl"
, "WHERE cur.orig_ttl IS NULL"
, "AND Coalesce(xfer.orig_redirect_src, '') != ''"
)
, Sql_create_orig_direct = String_.Concat_lines_nl
( "INSERT INTO {0} "
, "(orig_ttl, {1}, orig_repo, orig_ext, orig_w, orig_h, orig_redirect)"
, "SELECT DISTINCT"
, " orig.lnki_ttl"
, ", 0 --unknown"
, ", orig.orig_repo"
, ", orig.lnki_ext"
, ", orig.orig_w"
, ", orig.orig_h"
, ", ''"
, "FROM make_db.orig_regy orig"
, " LEFT JOIN {0} cur ON orig.lnki_ttl = cur.orig_ttl"
, "WHERE cur.orig_ttl IS NULL" // not already in orig_reg
, "AND orig.orig_repo IS NOT NULL" // not found in oimg_image.sqlite3
, "AND Coalesce(orig.orig_w , -1) != -1" // ignore entries that are either ext_id = 0 ("File:1") or don't have any width / height info (makes it useless); need to try to get again from wmf_api
, "AND Coalesce(orig.orig_redirect_ttl, '') == ''" // direct
)
, Sql_create_orig_redirect = String_.Concat_lines_nl
( "INSERT INTO {0} "
, "(orig_ttl, {1}, orig_repo, orig_ext, orig_w, orig_h, orig_redirect)"
, "SELECT DISTINCT"
, " orig.orig_redirect_ttl"
, ", 0 --unknown"
, ", orig.orig_repo"
, ", orig.lnki_ext"
, ", orig.orig_w"
, ", orig.orig_h"
, ", ''"
, "FROM make_db.orig_regy orig"
, " LEFT JOIN {0} cur ON orig.orig_redirect_ttl = cur.orig_ttl"
, "WHERE cur.orig_ttl IS NULL" // not already in orig_reg
, "AND orig.orig_repo IS NOT NULL" // not found in oimg_image.sqlite3
, "AND Coalesce(orig.orig_w, -1) != -1" // ignore entries that are either ext_id = 0 ("File:1") or don't have any width / height info (makes it useless); need to try to get again from wmf_api
, "AND Coalesce(orig.orig_redirect_ttl, '') != ''" // redirect
)
;
}

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.origs; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.xowa.wikis.*; import gplx.xowa.files.*;
public class Xof_orig_itm {
public byte Repo() {return repo;} private byte repo;
public byte[] Ttl() {return ttl;} private byte[] ttl; // without file ns; EX: "A.png" not "File:A.png"
public int Ext_id() {return ext_id;} private int ext_id;
public Xof_ext Ext() {if (ext == null) ext = Xof_ext_.new_by_id_(ext_id); return ext;} private Xof_ext ext;
public int W() {return w;} private int w;
public int H() {return h;} private int h;
public byte[] Redirect() {return redirect;} private byte[] redirect; // redirect trg; EX: A.png is redirected to B.jpg; record will have A.png|jpg|220|200|B.jpg where jpg|220|200 are the attributes of B.jpg
public boolean Insert_new() {return insert_new;} public void Insert_new_y_() {insert_new = Bool_.Y;} private boolean insert_new;
public void Clear() {
this.repo = Repo_null;
this.ttl = this.redirect = null;
this.ext_id = Xof_ext_.Id_unknown;
this.w = this.h = Xof_img_size.Null;
this.ext = null;
}
public Xof_orig_itm Init(byte repo, byte[] ttl, int ext_id, int w, int h, byte[] redirect) {
this.repo = repo; this.ttl = ttl; this.ext_id = ext_id;
this.w = w; this.h = h; this.redirect = redirect;
return this;
}
public static final byte Repo_comm = 0, Repo_wiki = 1, Repo_null = Byte_.Max_value_127; // SERIALIZED: "wiki_orig.orig_repo"
public static final Xof_orig_itm Null = null;
public static final int File_len_null = -1; // file_len used for filters (EX: don't download ogg > 1 MB)
public static String dump(Xof_orig_itm itm) {
if (itm == null)
return "NULL";
Bry_bfr bfr = Bry_bfr.new_(255);
bfr.Add_str_a7("repo").Add_byte_eq().Add_int_variable((int)itm.repo).Add_byte_semic();
bfr.Add_str_a7("ttl").Add_byte_eq().Add(itm.ttl).Add_byte_semic();
bfr.Add_str_a7("ext_id").Add_byte_eq().Add_int_variable(itm.ext_id).Add_byte_semic();
bfr.Add_str_a7("w").Add_byte_eq().Add_int_variable(itm.w).Add_byte_semic();
bfr.Add_str_a7("h").Add_byte_eq().Add_int_variable(itm.h).Add_byte_semic();
bfr.Add_str_a7("redirect").Add_byte_eq().Add(itm.redirect).Add_byte_semic();
return bfr.Xto_str_and_clear();
}
}

View File

@@ -0,0 +1,94 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.files.origs; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.core.primitives.*; import gplx.dbs.*;
import gplx.xowa.files.repos.*; import gplx.xowa.files.fsdb.*; import gplx.xowa.wmfs.apis.*; import gplx.xowa.files.downloads.*;
public class Xof_orig_mgr {
private Xof_orig_wkr[] wkrs; private int wkrs_len;
private Xof_url_bldr url_bldr; private Xow_repo_mgr repo_mgr; private final Xof_img_size img_size = new Xof_img_size();
public Xof_orig_mgr() {this.Wkrs__clear();}
public void Init_by_wiki(Xow_wiki wiki, Xof_fsdb_mode fsdb_mode, Xof_orig_tbl[] orig_tbls, Xof_url_bldr url_bldr) {
this.repo_mgr = wiki.File__repo_mgr(); this.url_bldr = url_bldr;
// if (!fsdb_mode.Tid_v0()) { // add view,make; don't add if wmf
int orig_tbls_len = orig_tbls.length;
for (int i = 0; i < orig_tbls_len; ++i) {
Xof_orig_tbl orig_tbl = orig_tbls[i];
this.Wkrs__add_many(new Xof_orig_wkr__orig_db(orig_tbl, i == orig_tbls_len - 1));
}
// }
if (!fsdb_mode.Tid_v2_bld()) { // add if gui, but not if bld
Io_url wiki_meta_dir = wiki.App().Fsys_mgr().File_dir().GenSubDir_nest("#meta", wiki.Domain_str());
if (Io_mgr.I.ExistsDir(wiki_meta_dir)) {
Xof_orig_wkr__xo_meta xo_meta = new Xof_orig_wkr__xo_meta(wiki_meta_dir);
this.Wkrs__add_many(xo_meta);
}
this.Wkrs__add_many(new Xof_orig_wkr__wmf_api(new Xoapi_orig_wmf(), wiki.App().Wmf_mgr().Download_wkr(), repo_mgr, wiki.Domain_bry()));
}
}
public Xof_orig_itm Find_by_ttl_or_null(byte[] ttl) {return Find_by_ttl_or_null(ttl, 0, 1);}
public Xof_orig_itm Find_by_ttl_or_null(byte[] ttl, int list_idx, int list_len) {
for (int i = 0; i < wkrs_len; i++) {
Xof_orig_wkr wkr = wkrs[i];
Xof_orig_itm orig = wkr.Find_as_itm(ttl, list_idx, list_len); if (orig == Xof_orig_itm.Null) continue;
if (orig.Insert_new()) this.Insert(orig.Repo(), ttl, orig.Ext_id(), orig.W(), orig.H(), orig.Redirect()); // NOTE: orig_page must be same as find_arg not orig.Page() else will not be found for next call; DATE:2015-04-14
return orig;
}
return Xof_orig_itm.Null;
}
public void Find_by_list(Ordered_hash rv, List_adp itms, int exec_tid) {
for (int i = 0; i < wkrs_len; i++) {
Xof_orig_wkr wkr = wkrs[i];
wkr.Find_by_list(rv, itms);
}
int len = itms.Count();
for (int i = 0; i < len; i++) {
try {
Xof_fsdb_itm fsdb = (Xof_fsdb_itm)itms.Get_at(i);
fsdb.Orig_exists_n_(); // default to status = missing
Xof_orig_itm orig = (Xof_orig_itm)rv.Get_by(fsdb.Lnki_ttl()); if (orig == Xof_orig_itm.Null) continue;
if (orig.Insert_new()) this.Insert(orig.Repo(), fsdb.Lnki_ttl(), orig.Ext_id(), orig.W(), orig.H(), orig.Redirect()); // NOTE: orig_page must be same as find_arg not orig.Page() else will not be found for next call; DATE:2015-04-14
Xof_file_wkr.Eval_orig(orig, fsdb, url_bldr, repo_mgr, img_size);
if (!Io_mgr.I.ExistsFil(fsdb.Html_view_url()))
fsdb.File_exists_n_();
} catch (Exception e) {
Xoa_app_.Usr_dlg().Warn_many("", "", "orig: ~{0}", Err_.Message_gplx_brief(e));
}
}
}
public void Insert(byte repo, byte[] page, int ext, int w, int h, byte[] redirect) {
for (int i = 0; i < wkrs_len; i++) {
Xof_orig_wkr wkr = wkrs[i];
if (wkr.Add_orig(repo, page, ext, w, h, redirect)) break;
}
}
private void Wkrs__clear() {wkrs = Xof_orig_wkr_.Ary_empty; wkrs_len = 0;}
private void Wkrs__add_many(Xof_orig_wkr... v) {
wkrs = (Xof_orig_wkr[])Array_.Resize_add(wkrs, v);
wkrs_len += v.length;
}
public void Wkrs_del(byte tid) {
List_adp list = List_adp_.new_();
for (int i = 0; i < wkrs_len; ++i) {
Xof_orig_wkr wkr = wkrs[i];
if (wkr.Tid() == tid) continue; // do not add deleted wkr
list.Add(wkr);
}
wkrs = (Xof_orig_wkr[])list.To_ary_and_clear(Xof_orig_wkr.class);
wkrs_len = wkrs.length;
}
}

View File

@@ -0,0 +1,115 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.files.origs; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.core.primitives.*;
import gplx.dbs.*; import gplx.dbs.utls.*;
import gplx.xowa.files.fsdb.*; import gplx.xowa.files.repos.*;
public class Xof_orig_tbl implements RlsAble {
private final String tbl_name; private final Db_meta_fld_list flds = Db_meta_fld_list.new_();
private final String fld_repo, fld_ttl, fld_status, fld_ext, fld_w, fld_h, fld_redirect;
private final Db_conn conn; private final Xof_orig_tbl__in_wkr select_in_wkr = new Xof_orig_tbl__in_wkr();
public Db_conn Conn() {return conn;}
public Xof_orig_tbl(Db_conn conn, boolean schema_is_1) {
this.conn = conn;
String fld_status_name = "orig_status";
if (schema_is_1) {tbl_name = "wiki_orig"; fld_status_name = "status";}
else {tbl_name = "orig_reg";}
fld_ttl = flds.Add_str("orig_ttl", 1024);
fld_repo = flds.Add_byte("orig_repo");
fld_status = flds.Add_byte(fld_status_name);
fld_ext = flds.Add_int("orig_ext");
fld_w = flds.Add_int("orig_w");
fld_h = flds.Add_int("orig_h");
fld_redirect = flds.Add_str("orig_redirect", 1024);
select_in_wkr.Ctor(this, tbl_name, flds, fld_ttl);
conn.Rls_reg(this);
}
public void Rls() {}
public void Create_tbl() {conn.Ddl_create_tbl(Db_meta_tbl.new_(tbl_name, flds, Db_meta_idx.new_normal_by_tbl(tbl_name, "main", fld_ttl)));}
public void Select_by_list(Ordered_hash rv, List_adp itms) {select_in_wkr.Init(rv, itms).Select_in(Cancelable_.Never, conn, 0, itms.Count());}
public Xof_orig_itm Select_itm(byte[] ttl) {
Xof_orig_itm rv = Xof_orig_itm.Null;
Db_rdr rdr = conn.Stmt_select(tbl_name, flds, fld_ttl).Clear().Crt_bry_as_str(fld_ttl, ttl).Exec_select__rls_auto();
try {
if (rdr.Move_next())
rv = Make_itm(rdr);
}
finally {rdr.Rls();}
return rv;
}
public boolean Exists__repo_ttl(byte repo, byte[] ttl) {
Db_rdr rdr = conn.Stmt_select(tbl_name, flds, fld_repo, fld_ttl).Crt_byte(fld_repo, repo).Crt_bry_as_str(fld_ttl, ttl).Exec_select__rls_auto();
try {return rdr.Move_next();}
finally {rdr.Rls();}
}
public void Insert(byte repo, byte[] ttl, int ext, int w, int h, byte[] redirect) {
Db_stmt stmt = conn.Stmt_insert(tbl_name, flds);
stmt.Clear()
.Val_bry_as_str(fld_ttl, ttl).Val_byte(fld_repo, repo).Val_byte(fld_status, Status_found)
.Val_int(fld_ext, ext).Val_int(fld_w, w).Val_int(fld_h, h).Val_bry_as_str(fld_redirect, redirect)
.Exec_insert();
}
public void Update(byte repo, byte[] ttl, int ext, int w, int h, byte[] redirect) {
Db_stmt stmt = conn.Stmt_update_exclude(tbl_name, flds, String_.Ary(fld_repo, fld_ttl));
stmt.Clear()
.Val_byte(fld_status, Status_found)
.Val_int(fld_ext, ext).Val_int(fld_w, w).Val_int(fld_h, h).Val_bry_as_str(fld_redirect, redirect)
.Crt_byte(fld_repo, repo).Crt_bry_as_str(fld_ttl, ttl)
.Exec_update();
}
public Xof_orig_itm Make_itm(Db_rdr rdr) {
byte repo = rdr.Read_byte(fld_repo);
Xof_orig_itm rv = new Xof_orig_itm().Init
( repo
, rdr.Read_bry_by_str(fld_ttl)
, rdr.Read_int(fld_ext)
, rdr.Read_int(fld_w)
, rdr.Read_int(fld_h)
, rdr.Read_bry_by_str(fld_redirect)
);
return rv.W() == Xof_img_size.Null ? Xof_orig_itm.Null : rv;
}
private static final byte Status_found = 1;
}
class Xof_orig_tbl__in_wkr extends Db_in_wkr__base {
private Xof_orig_tbl tbl; private String tbl_name; private Db_meta_fld_list flds; private String fld_ttl;
private List_adp itms; private Ordered_hash rv;
public void Ctor(Xof_orig_tbl tbl, String tbl_name, Db_meta_fld_list flds, String fld_ttl) {
this.tbl = tbl; this.tbl_name = tbl_name; this.flds = flds; this.fld_ttl = fld_ttl;
}
public Xof_orig_tbl__in_wkr Init(Ordered_hash rv, List_adp itms) {this.itms = itms; this.rv = rv; return this;}
@Override protected Db_qry Make_qry(int bgn, int end) {
Object[] part_ary = In_ary(end - bgn);
return Db_qry_.select_cols_(tbl_name, Db_crt_.in_(fld_ttl, part_ary), flds.To_str_ary());
}
@Override protected void Fill_stmt(Db_stmt stmt, int bgn, int end) {
for (int i = bgn; i < end; i++) {
Xof_fsdb_itm fsdb_itm = (Xof_fsdb_itm)itms.Get_at(i);
stmt.Crt_bry_as_str(fld_ttl, fsdb_itm.Lnki_ttl());
}
}
@Override protected void Read_data(Cancelable cancelable, Db_rdr rdr) {
while (rdr.Move_next()) {
if (cancelable.Canceled()) return;
Xof_orig_itm itm = tbl.Make_itm(rdr);
if (itm == Xof_orig_itm.Null) continue;
byte[] itm_ttl = itm.Ttl();
rv.Add_if_dupe_use_1st(itm_ttl, itm); // guard against dupes; fails on en.w:Paris; DATE:2015-03-08
}
}
}

View File

@@ -0,0 +1,75 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.files.origs; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import org.junit.*;
import gplx.dbs.*; import gplx.xowa.*;
import gplx.xowa.files.*; import gplx.xowa.files.fsdb.*;
public class Xof_orig_tbl_tst {
@Before public void init() {fxt.Clear();} private Xof_orig_tbl_fxt fxt = new Xof_orig_tbl_fxt();
@Test public void Select_in() {
Xof_orig_itm itm_1 = fxt.Exec_insert("A.png", 220, 330);
fxt.Exec_insert("B.png", 220, 330);
Xof_orig_itm itm_3 = fxt.Exec_insert("C.png", 220, 330);
fxt.Test_select_in(String_.Ary("A.png", "C.png"), itm_1, itm_3);
}
}
class Xof_orig_tbl_fxt {
private Xof_orig_tbl tbl;
public void Clear() {
Io_url test_url = Io_url_.mem_fil_("mem/file/en.wikipedia.org/file/orig_regy");
Db_conn_bldr.I.Reg_default_mem();
Db_conn conn = Db_conn_bldr.I.New(test_url);
tbl = new Xof_orig_tbl(conn, Bool_.Y);
tbl.Create_tbl();
}
public Xof_orig_itm Exec_insert(String ttl, int w, int h) {
byte[] ttl_bry = Bry_.new_u8(ttl);
Xof_orig_itm rv = new Xof_orig_itm().Init(Xof_orig_itm.Repo_comm, ttl_bry, Xof_ext_.new_by_ttl_(ttl_bry).Id(), w, h, Bry_.Empty);
tbl.Insert(rv.Repo(), rv.Ttl(), rv.Ext_id(), rv.W(), rv.H(), rv.Redirect());
return rv;
}
public void Test_select_in(String[] itms, Xof_orig_itm... expd) {
Ordered_hash rv = Ordered_hash_.new_();
List_adp list = List_adp_.new_();
int itms_len = itms.length;
for (int i = 0; i < itms_len; ++i) {
String itm = itms[i];
Xof_fsdb_itm fsdb_itm = new Xof_fsdb_itm();
fsdb_itm.Init_at_lnki(Xof_exec_tid.Tid_wiki_page, Bry_.new_a7("en.w"), Bry_.new_u8(itm), Xop_lnki_type.Id_none, Xof_img_size.Upright_null, Xof_img_size.Null, Xof_img_size.Null, Xof_lnki_time.Null, Xof_lnki_page.Null, Xof_patch_upright_tid_.Tid_all);
list.Add(fsdb_itm);
}
tbl.Select_by_list(rv, list);
Tfds.Eq_str_lines(To_str_ary(expd), To_str_ary((Xof_orig_itm[])rv.To_ary(Xof_orig_itm.class)));
}
private static String To_str_ary(Xof_orig_itm... ary) {
Bry_bfr bfr = Bry_bfr.reset_(255);
int len = ary.length;
for (int i = 0; i < len; ++i) {
Xof_orig_itm itm = ary[i];
bfr .Add_byte(itm.Repo()).Add_byte_pipe()
.Add(itm.Ttl()).Add_byte_pipe()
.Add_int_variable(itm.Ext_id()).Add_byte_pipe()
.Add_int_variable(itm.W()).Add_byte_pipe()
.Add_int_variable(itm.H()).Add_byte_pipe()
.Add(itm.Redirect()).Add_byte_pipe()
;
bfr.Add_byte_nl();
}
return bfr.Xto_str_and_clear();
}
}

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.origs; import gplx.*; import gplx.xowa.*; import gplx.xowa.files.*;
import gplx.xowa.files.fsdb.*;
public interface Xof_orig_wkr {
byte Tid();
Xof_orig_itm Find_as_itm(byte[] ttl, int list_idx, int list_len);
void Find_by_list(Ordered_hash rv, List_adp itms);
boolean Add_orig(byte repo, byte[] page, int ext_id, int w, int h, byte[] redirect);
void Db_txn_save();
void Db_rls();
}

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