Fix default remote lib not using cache
[fanfix.git] / src / be / nikiroo / fanfix / supported / Epub.java
CommitLineData
08fe2e33
NR
1package be.nikiroo.fanfix.supported;
2
3import java.awt.image.BufferedImage;
4import java.io.File;
5import java.io.FileInputStream;
6import java.io.IOException;
7import java.io.InputStream;
8import java.net.URL;
778d8d85 9import java.net.URLDecoder;
68686a37 10import java.util.ArrayList;
08fe2e33
NR
11import java.util.List;
12import java.util.Map.Entry;
13import java.util.zip.ZipEntry;
14import java.util.zip.ZipInputStream;
15
08fe2e33 16import be.nikiroo.fanfix.Instance;
68686a37 17import be.nikiroo.fanfix.data.MetaData;
08fe2e33 18import be.nikiroo.utils.IOUtils;
326093dc 19import be.nikiroo.utils.ImageUtils;
08fe2e33 20import be.nikiroo.utils.MarkableFileInputStream;
ed08c171 21import be.nikiroo.utils.Progress;
b7afbe42 22import be.nikiroo.utils.StringUtils;
08fe2e33
NR
23
24/**
25 * Support class for EPUB files created with this program (as we need some
26 * metadata available in those we create).
27 *
28 * @author niki
29 */
68686a37 30class Epub extends InfoText {
68686a37 31 protected MetaData meta;
b7afbe42
NR
32 private File tmp;
33 private String desc;
08fe2e33 34
68686a37
NR
35 private URL fakeSource;
36 private InputStream fakeIn;
08fe2e33
NR
37
38 @Override
39 public String getSourceName() {
40 return "epub";
41 }
42
43 @Override
44 protected boolean supports(URL url) {
45 if (url.getPath().toLowerCase().endsWith(".epub")) {
46 return true;
47 }
48
49 return false;
50 }
51
52 @Override
68686a37
NR
53 protected MetaData getMeta(URL source, InputStream in) throws IOException {
54 return meta;
08fe2e33
NR
55 }
56
57 @Override
58 protected String getDesc(URL source, InputStream in) throws IOException {
b7afbe42
NR
59 if (desc != null) {
60 return desc;
61 }
62
68686a37
NR
63 if (fakeIn != null) {
64 fakeIn.reset();
65 return super.getDesc(fakeSource, fakeIn);
08fe2e33
NR
66 }
67
68 return null;
69 }
70
71 @Override
ed08c171
NR
72 protected List<Entry<String, URL>> getChapters(URL source, InputStream in,
73 Progress pg) throws IOException {
68686a37
NR
74 if (fakeIn != null) {
75 fakeIn.reset();
ed08c171 76 return super.getChapters(fakeSource, fakeIn, pg);
08fe2e33
NR
77 }
78
79 return null;
80 }
81
82 @Override
ed08c171
NR
83 protected String getChapterContent(URL source, InputStream in, int number,
84 Progress pg) throws IOException {
68686a37
NR
85 if (fakeIn != null) {
86 fakeIn.reset();
ed08c171 87 return super.getChapterContent(fakeSource, fakeIn, number, pg);
08fe2e33
NR
88 }
89
90 return null;
91 }
92
93 @Override
68686a37 94 protected void preprocess(URL source, InputStream in) throws IOException {
08fe2e33
NR
95 // Note: do NOT close this stream, as it would also close "in"
96 ZipInputStream zipIn = new ZipInputStream(in);
97 tmp = File.createTempFile("fanfic-reader-parser_", ".tmp");
68686a37 98 File tmpInfo = new File(tmp + ".info");
08fe2e33 99 fakeSource = tmp.toURI().toURL();
68686a37 100 BufferedImage cover = null;
08fe2e33 101
b7afbe42
NR
102 String url = source.toString();
103 String title = null;
104 String author = null;
105
08fe2e33
NR
106 for (ZipEntry entry = zipIn.getNextEntry(); entry != null; entry = zipIn
107 .getNextEntry()) {
108 if (!entry.isDirectory()
109 && entry.getName().startsWith(getDataPrefix())) {
110 String entryLName = entry.getName().toLowerCase();
b7afbe42 111
08fe2e33
NR
112 boolean imageEntry = false;
113 for (String ext : getImageExt(false)) {
114 if (entryLName.endsWith(ext)) {
115 imageEntry = true;
116 }
117 }
118
119 if (entry.getName().equals(getDataPrefix() + "version")) {
120 // Nothing to do for now ("first"
121 // version is 3.0)
122 } else if (entryLName.endsWith(".info")) {
123 // Info file
124 IOUtils.write(zipIn, tmpInfo);
125 } else if (imageEntry) {
126 // Cover
127 if (getCover()) {
128 try {
326093dc 129 cover = ImageUtils.fromStream(zipIn);
08fe2e33 130 } catch (Exception e) {
62c63b07 131 Instance.getTraceHandler().error(e);
08fe2e33
NR
132 }
133 }
134 } else if (entry.getName().equals(getDataPrefix() + "URL")) {
b7afbe42
NR
135 String[] descArray = StringUtils
136 .unhtml(IOUtils.readSmallStream(zipIn)).trim()
137 .split("\n");
138 if (descArray.length > 0) {
139 url = descArray[0].trim();
140 }
08fe2e33 141 } else if (entry.getName().equals(getDataPrefix() + "SUMMARY")) {
b7afbe42
NR
142 String[] descArray = StringUtils
143 .unhtml(IOUtils.readSmallStream(zipIn)).trim()
144 .split("\n");
145 int skip = 0;
146 if (descArray.length > 1) {
147 title = descArray[0].trim();
148 skip = 1;
149 if (descArray.length > 2
150 && descArray[1].startsWith("©")) {
151 author = descArray[1].substring(1).trim();
152 skip = 2;
153 }
154 }
155 this.desc = "";
156 for (int i = skip; i < descArray.length; i++) {
157 this.desc += descArray[i].trim() + "\n";
158 }
159
160 this.desc = this.desc.trim();
08fe2e33
NR
161 } else {
162 // Hopefully the data file
163 IOUtils.write(zipIn, tmp);
164 }
165 }
166 }
167
168 if (requireInfo() && (!tmp.exists() || !tmpInfo.exists())) {
169 throw new IOException(
170 "file not supported (maybe not created with this program or corrupt)");
171 }
172
173 if (tmp.exists()) {
68686a37
NR
174 this.fakeIn = new MarkableFileInputStream(new FileInputStream(tmp));
175 }
176
177 if (tmpInfo.exists()) {
57f02339 178 meta = InfoReader.readMeta(tmpInfo, true);
68686a37
NR
179 if (cover != null) {
180 meta.setCover(cover);
181 }
182 tmpInfo.delete();
183 } else {
778d8d85
NR
184 if (title == null || title.isEmpty()) {
185 title = new File(source.getPath()).getName();
186 if (title.toLowerCase().endsWith(".cbz")) {
187 title = title.substring(0, title.length() - 4);
188 }
189 title = URLDecoder.decode(title, "UTF-8").trim();
190 }
191
68686a37 192 meta = new MetaData();
68686a37
NR
193 meta.setLang("EN");
194 meta.setTags(new ArrayList<String>());
195 meta.setSource(getSourceName());
b7afbe42
NR
196 meta.setUuid(url);
197 meta.setUrl(url);
198 meta.setTitle(title);
199 meta.setAuthor(author);
08fe2e33
NR
200 }
201 }
202
203 @Override
204 protected void close() throws IOException {
68686a37
NR
205 if (tmp != null && tmp.exists()) {
206 if (!tmp.delete()) {
207 tmp.deleteOnExit();
08fe2e33
NR
208 }
209 }
210
211 tmp = null;
08fe2e33 212
dea63313
NR
213 if (fakeIn != null) {
214 fakeIn.close();
215 }
216
68686a37 217 super.close();
08fe2e33
NR
218 }
219
220 protected String getDataPrefix() {
221 return "DATA/";
222 }
223
224 protected boolean requireInfo() {
225 return true;
226 }
227
228 protected boolean getCover() {
229 return true;
230 }
08fe2e33 231}