Fix tests
[fanfix.git] / src / be / nikiroo / fanfix / supported / Epub.java
CommitLineData
08fe2e33
NR
1package be.nikiroo.fanfix.supported;
2
08fe2e33
NR
3import java.io.File;
4import java.io.FileInputStream;
5import java.io.IOException;
6import java.io.InputStream;
7import java.net.URL;
778d8d85 8import java.net.URLDecoder;
68686a37 9import java.util.ArrayList;
08fe2e33
NR
10import java.util.List;
11import java.util.Map.Entry;
12import java.util.zip.ZipEntry;
13import java.util.zip.ZipInputStream;
14
08fe2e33 15import be.nikiroo.fanfix.Instance;
68686a37 16import be.nikiroo.fanfix.data.MetaData;
08fe2e33 17import be.nikiroo.utils.IOUtils;
16a81ef7 18import be.nikiroo.utils.Image;
08fe2e33 19import be.nikiroo.utils.MarkableFileInputStream;
ed08c171 20import be.nikiroo.utils.Progress;
b7afbe42 21import be.nikiroo.utils.StringUtils;
08fe2e33
NR
22
23/**
24 * Support class for EPUB files created with this program (as we need some
25 * metadata available in those we create).
26 *
27 * @author niki
28 */
68686a37 29class Epub extends InfoText {
68686a37 30 protected MetaData meta;
2aac79c7 31 private File tmpDir;
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);
2aac79c7
NR
97 tmpDir = Instance.getTempFiles().createTempDir("fanfic-reader-parser");
98 tmp = new File(tmpDir, "file.txt");
99 File tmpInfo = new File(tmpDir, "file.info");
08fe2e33 100 fakeSource = tmp.toURI().toURL();
16a81ef7 101 Image cover = null;
08fe2e33 102
b7afbe42
NR
103 String url = source.toString();
104 String title = null;
105 String author = null;
106
08fe2e33
NR
107 for (ZipEntry entry = zipIn.getNextEntry(); entry != null; entry = zipIn
108 .getNextEntry()) {
109 if (!entry.isDirectory()
110 && entry.getName().startsWith(getDataPrefix())) {
111 String entryLName = entry.getName().toLowerCase();
b7afbe42 112
08fe2e33
NR
113 boolean imageEntry = false;
114 for (String ext : getImageExt(false)) {
115 if (entryLName.endsWith(ext)) {
116 imageEntry = true;
117 }
118 }
119
120 if (entry.getName().equals(getDataPrefix() + "version")) {
121 // Nothing to do for now ("first"
122 // version is 3.0)
123 } else if (entryLName.endsWith(".info")) {
124 // Info file
125 IOUtils.write(zipIn, tmpInfo);
126 } else if (imageEntry) {
127 // Cover
128 if (getCover()) {
129 try {
16a81ef7 130 cover = new Image(zipIn);
08fe2e33 131 } catch (Exception e) {
62c63b07 132 Instance.getTraceHandler().error(e);
08fe2e33
NR
133 }
134 }
135 } else if (entry.getName().equals(getDataPrefix() + "URL")) {
b7afbe42
NR
136 String[] descArray = StringUtils
137 .unhtml(IOUtils.readSmallStream(zipIn)).trim()
138 .split("\n");
139 if (descArray.length > 0) {
140 url = descArray[0].trim();
141 }
08fe2e33 142 } else if (entry.getName().equals(getDataPrefix() + "SUMMARY")) {
b7afbe42
NR
143 String[] descArray = StringUtils
144 .unhtml(IOUtils.readSmallStream(zipIn)).trim()
145 .split("\n");
146 int skip = 0;
147 if (descArray.length > 1) {
148 title = descArray[0].trim();
149 skip = 1;
150 if (descArray.length > 2
151 && descArray[1].startsWith("©")) {
152 author = descArray[1].substring(1).trim();
153 skip = 2;
154 }
155 }
156 this.desc = "";
157 for (int i = skip; i < descArray.length; i++) {
158 this.desc += descArray[i].trim() + "\n";
159 }
160
161 this.desc = this.desc.trim();
08fe2e33
NR
162 } else {
163 // Hopefully the data file
164 IOUtils.write(zipIn, tmp);
165 }
166 }
167 }
168
169 if (requireInfo() && (!tmp.exists() || !tmpInfo.exists())) {
170 throw new IOException(
171 "file not supported (maybe not created with this program or corrupt)");
172 }
173
174 if (tmp.exists()) {
68686a37
NR
175 this.fakeIn = new MarkableFileInputStream(new FileInputStream(tmp));
176 }
177
178 if (tmpInfo.exists()) {
57f02339 179 meta = InfoReader.readMeta(tmpInfo, true);
68686a37
NR
180 if (cover != null) {
181 meta.setCover(cover);
182 }
183 tmpInfo.delete();
184 } else {
778d8d85
NR
185 if (title == null || title.isEmpty()) {
186 title = new File(source.getPath()).getName();
187 if (title.toLowerCase().endsWith(".cbz")) {
188 title = title.substring(0, title.length() - 4);
189 }
190 title = URLDecoder.decode(title, "UTF-8").trim();
191 }
192
68686a37 193 meta = new MetaData();
276f95c6 194 meta.setLang("en");
68686a37
NR
195 meta.setTags(new ArrayList<String>());
196 meta.setSource(getSourceName());
b7afbe42
NR
197 meta.setUuid(url);
198 meta.setUrl(url);
199 meta.setTitle(title);
200 meta.setAuthor(author);
e4fa48a0 201 meta.setImageDocument(isImagesDocumentByDefault());
08fe2e33
NR
202 }
203 }
204
205 @Override
0ffa4754 206 protected void close() {
2aac79c7
NR
207 if (tmpDir != null) {
208 IOUtils.deltree(tmpDir);
08fe2e33
NR
209 }
210
2aac79c7 211 tmpDir = null;
08fe2e33 212 tmp = null;
08fe2e33 213
dea63313 214 if (fakeIn != null) {
0ffa4754
NR
215 try {
216 fakeIn.close();
217 } catch (Exception e) {
218 Instance.getTraceHandler().error(e);
219 }
dea63313
NR
220 }
221
68686a37 222 super.close();
08fe2e33
NR
223 }
224
225 protected String getDataPrefix() {
226 return "DATA/";
227 }
228
229 protected boolean requireInfo() {
230 return true;
231 }
232
233 protected boolean getCover() {
234 return true;
235 }
e4fa48a0
NR
236
237 protected boolean isImagesDocumentByDefault() {
238 return false;
239 }
08fe2e33 240}