Fix some perf/space problems, add a cover for e621
[fanfix.git] / src / be / nikiroo / fanfix / supported / Epub.java
1 package be.nikiroo.fanfix.supported;
2
3 import java.awt.image.BufferedImage;
4 import java.io.File;
5 import java.io.FileInputStream;
6 import java.io.IOException;
7 import java.io.InputStream;
8 import java.net.URL;
9 import java.util.ArrayList;
10 import java.util.List;
11 import java.util.Map.Entry;
12 import java.util.zip.ZipEntry;
13 import java.util.zip.ZipInputStream;
14
15 import be.nikiroo.fanfix.Instance;
16 import be.nikiroo.fanfix.data.MetaData;
17 import be.nikiroo.utils.IOUtils;
18 import be.nikiroo.utils.MarkableFileInputStream;
19
20 /**
21 * Support class for EPUB files created with this program (as we need some
22 * metadata available in those we create).
23 *
24 * @author niki
25 */
26 class Epub extends InfoText {
27 private File tmp;
28 protected MetaData meta;
29
30 private URL fakeSource;
31 private InputStream fakeIn;
32
33 @Override
34 public String getSourceName() {
35 return "epub";
36 }
37
38 @Override
39 protected boolean supports(URL url) {
40 if (url.getPath().toLowerCase().endsWith(".epub")) {
41 return true;
42 }
43
44 return false;
45 }
46
47 @Override
48 protected MetaData getMeta(URL source, InputStream in) throws IOException {
49 return meta;
50 }
51
52 @Override
53 protected String getDesc(URL source, InputStream in) throws IOException {
54 if (fakeIn != null) {
55 fakeIn.reset();
56 return super.getDesc(fakeSource, fakeIn);
57 }
58
59 return null;
60 }
61
62 @Override
63 protected List<Entry<String, URL>> getChapters(URL source, InputStream in)
64 throws IOException {
65 if (fakeIn != null) {
66 fakeIn.reset();
67 return super.getChapters(fakeSource, fakeIn);
68 }
69
70 return null;
71 }
72
73 @Override
74 protected String getChapterContent(URL source, InputStream in, int number)
75 throws IOException {
76 if (fakeIn != null) {
77 fakeIn.reset();
78 return super.getChapterContent(fakeSource, fakeIn, number);
79 }
80
81 return null;
82 }
83
84 @Override
85 protected void preprocess(URL source, InputStream in) throws IOException {
86 // Note: do NOT close this stream, as it would also close "in"
87 ZipInputStream zipIn = new ZipInputStream(in);
88 tmp = File.createTempFile("fanfic-reader-parser_", ".tmp");
89 File tmpInfo = new File(tmp + ".info");
90 fakeSource = tmp.toURI().toURL();
91 BufferedImage cover = null;
92
93 for (ZipEntry entry = zipIn.getNextEntry(); entry != null; entry = zipIn
94 .getNextEntry()) {
95 if (!entry.isDirectory()
96 && entry.getName().startsWith(getDataPrefix())) {
97 String entryLName = entry.getName().toLowerCase();
98
99 boolean imageEntry = false;
100 for (String ext : getImageExt(false)) {
101 if (entryLName.endsWith(ext)) {
102 imageEntry = true;
103 }
104 }
105
106 if (entry.getName().equals(getDataPrefix() + "version")) {
107 // Nothing to do for now ("first"
108 // version is 3.0)
109 } else if (entryLName.endsWith(".info")) {
110 // Info file
111 IOUtils.write(zipIn, tmpInfo);
112 } else if (imageEntry) {
113 // Cover
114 if (getCover()) {
115 try {
116 cover = IOUtils.toImage(zipIn);
117 } catch (Exception e) {
118 Instance.syserr(e);
119 }
120 }
121 } else if (entry.getName().equals(getDataPrefix() + "URL")) {
122 // Do nothing
123 } else if (entry.getName().equals(getDataPrefix() + "SUMMARY")) {
124 // Do nothing
125 } else {
126 // Hopefully the data file
127 IOUtils.write(zipIn, tmp);
128 }
129 }
130 }
131
132 if (requireInfo() && (!tmp.exists() || !tmpInfo.exists())) {
133 throw new IOException(
134 "file not supported (maybe not created with this program or corrupt)");
135 }
136
137 if (tmp.exists()) {
138 this.fakeIn = new MarkableFileInputStream(new FileInputStream(tmp));
139 }
140
141 if (tmpInfo.exists()) {
142 meta = InfoReader.readMeta(tmpInfo);
143 if (cover != null) {
144 meta.setCover(cover);
145 }
146 tmpInfo.delete();
147 } else {
148 meta = new MetaData();
149 meta.setUuid(source.toString());
150 meta.setLang("EN");
151 meta.setTags(new ArrayList<String>());
152 meta.setSource(getSourceName());
153 meta.setUrl(source.toString());
154 }
155 }
156
157 @Override
158 protected void close() throws IOException {
159 if (tmp != null && tmp.exists()) {
160 if (!tmp.delete()) {
161 tmp.deleteOnExit();
162 }
163 }
164
165 tmp = null;
166
167 fakeIn.close();
168 super.close();
169 }
170
171 protected String getDataPrefix() {
172 return "DATA/";
173 }
174
175 protected boolean requireInfo() {
176 return true;
177 }
178
179 protected boolean getCover() {
180 return true;
181 }
182 }