separate support name and BasicSupport
[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;
7445f856 7import java.net.URISyntaxException;
08fe2e33 8import java.net.URL;
778d8d85 9import java.net.URLDecoder;
68686a37 10import java.util.ArrayList;
08fe2e33
NR
11import java.util.zip.ZipEntry;
12import java.util.zip.ZipInputStream;
13
7445f856
NR
14import org.jsoup.nodes.Document;
15
08fe2e33 16import be.nikiroo.fanfix.Instance;
68686a37 17import be.nikiroo.fanfix.data.MetaData;
08fe2e33 18import be.nikiroo.utils.IOUtils;
16a81ef7 19import be.nikiroo.utils.Image;
08fe2e33 20import be.nikiroo.utils.MarkableFileInputStream;
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 {
7445f856 30 private MetaData meta;
2aac79c7 31 private File tmpDir;
b7afbe42 32 private String desc;
08fe2e33 33
68686a37
NR
34 private URL fakeSource;
35 private InputStream fakeIn;
08fe2e33 36
7445f856 37 public File getSourceFileOriginal() {
298d405a 38 return super.getSourceFile();
08fe2e33
NR
39 }
40
41 @Override
7445f856
NR
42 protected File getSourceFile() {
43 try {
44 return new File(fakeSource.toURI());
45 } catch (URISyntaxException e) {
46 Instance.getTraceHandler()
47 .error(new IOException(
48 "Cannot get the source file from the info-text URL",
49 e));
08fe2e33
NR
50 }
51
52 return null;
53 }
54
55 @Override
7445f856 56 protected InputStream getInput() {
298d405a
NR
57 if (fakeIn != null) {
58 try {
59 fakeIn.reset();
60 } catch (IOException e) {
61 Instance.getTraceHandler()
62 .error(new IOException(
63 "Cannot reset the Epub Text stream", e));
64 }
65
66 return fakeIn;
67 }
68
69 return null;
08fe2e33
NR
70 }
71
72 @Override
7445f856
NR
73 protected boolean supports(URL url) {
74 return url.getPath().toLowerCase().endsWith(".epub");
75 }
08fe2e33 76
7445f856
NR
77 @Override
78 protected MetaData getMeta() throws IOException {
79 return meta;
08fe2e33
NR
80 }
81
82 @Override
7445f856
NR
83 protected Document loadDocument(URL source) throws IOException {
84 super.loadDocument(source); // prepares super.getSourceFile() and
85 // super.getInput()
86
87 InputStream in = super.getInput();
88 ZipInputStream zipIn = null;
89 try {
90 zipIn = new ZipInputStream(in);
91 tmpDir = Instance.getTempFiles().createTempDir(
92 "fanfic-reader-parser");
93 File tmp = new File(tmpDir, "file.txt");
94 File tmpInfo = new File(tmpDir, "file.info");
95
96 fakeSource = tmp.toURI().toURL();
97 Image cover = null;
98
99 String url;
100 try {
101 url = getSource().toURI().toURL().toString();
102 } catch (URISyntaxException e1) {
103 url = getSource().toString();
104 }
105 String title = null;
106 String author = null;
107
108 for (ZipEntry entry = zipIn.getNextEntry(); entry != null; entry = zipIn
109 .getNextEntry()) {
110 if (!entry.isDirectory()
111 && entry.getName().startsWith(getDataPrefix())) {
112 String entryLName = entry.getName().toLowerCase();
113
114 boolean imageEntry = false;
115 for (String ext : BasicSupportImages.getImageExt(false)) {
116 if (entryLName.endsWith(ext)) {
117 imageEntry = true;
118 }
08fe2e33 119 }
08fe2e33 120
7445f856
NR
121 if (entry.getName().equals(getDataPrefix() + "version")) {
122 // Nothing to do for now ("first"
123 // version is 3.0)
124 } else if (entryLName.endsWith(".info")) {
125 // Info file
126 IOUtils.write(zipIn, tmpInfo);
127 } else if (imageEntry) {
128 // Cover
129 if (getCover()) {
130 try {
131 cover = new Image(zipIn);
132 } catch (Exception e) {
133 Instance.getTraceHandler().error(e);
134 }
08fe2e33 135 }
7445f856
NR
136 } else if (entry.getName().equals(getDataPrefix() + "URL")) {
137 String[] descArray = StringUtils
138 .unhtml(IOUtils.readSmallStream(zipIn)).trim()
139 .split("\n");
140 if (descArray.length > 0) {
141 url = descArray[0].trim();
142 }
143 } else if (entry.getName().equals(
144 getDataPrefix() + "SUMMARY")) {
145 String[] descArray = StringUtils
146 .unhtml(IOUtils.readSmallStream(zipIn)).trim()
147 .split("\n");
148 int skip = 0;
149 if (descArray.length > 1) {
150 title = descArray[0].trim();
151 skip = 1;
152 if (descArray.length > 2
153 && descArray[1].startsWith("©")) {
154 author = descArray[1].substring(1).trim();
155 skip = 2;
156 }
157 }
158 this.desc = "";
159 for (int i = skip; i < descArray.length; i++) {
160 this.desc += descArray[i].trim() + "\n";
b7afbe42 161 }
b7afbe42 162
7445f856
NR
163 this.desc = this.desc.trim();
164 } else {
165 // Hopefully the data file
166 IOUtils.write(zipIn, tmp);
167 }
08fe2e33
NR
168 }
169 }
08fe2e33 170
7445f856
NR
171 if (requireInfo() && (!tmp.exists() || !tmpInfo.exists())) {
172 throw new IOException(
173 "file not supported (maybe not created with this program or corrupt)");
174 }
68686a37 175
7445f856
NR
176 if (tmp.exists()) {
177 this.fakeIn = new MarkableFileInputStream(new FileInputStream(
178 tmp));
68686a37 179 }
7445f856
NR
180
181 if (tmpInfo.exists()) {
182 meta = InfoReader.readMeta(tmpInfo, true);
7445f856
NR
183 tmpInfo.delete();
184 } else {
185 if (title == null || title.isEmpty()) {
186 title = getSourceFileOriginal().getName();
187 if (title.toLowerCase().endsWith(".cbz")) {
188 title = title.substring(0, title.length() - 4);
189 }
190 title = URLDecoder.decode(title, "UTF-8").trim();
778d8d85 191 }
778d8d85 192
7445f856
NR
193 meta = new MetaData();
194 meta.setLang("en");
195 meta.setTags(new ArrayList<String>());
727108fe 196 meta.setSource(getType().getSourceName());
7445f856
NR
197 meta.setUuid(url);
198 meta.setUrl(url);
199 meta.setTitle(title);
200 meta.setAuthor(author);
201 meta.setImageDocument(isImagesDocumentByDefault());
202 }
bb7021f2
NR
203
204 if (meta.getCover() == null) {
205 if (cover != null) {
206 meta.setCover(cover);
207 } else {
bb7021f2
NR
208 meta.setCover(InfoReader
209 .getCoverByName(getSourceFileOriginal().toURI()
210 .toURL()));
211 }
212 }
7445f856
NR
213 } finally {
214 if (zipIn != null) {
215 zipIn.close();
216 }
217 if (in != null) {
218 in.close();
219 }
08fe2e33 220 }
7445f856
NR
221
222 return null;
08fe2e33
NR
223 }
224
225 @Override
0ffa4754 226 protected void close() {
2aac79c7
NR
227 if (tmpDir != null) {
228 IOUtils.deltree(tmpDir);
08fe2e33
NR
229 }
230
2aac79c7 231 tmpDir = null;
dea63313 232
68686a37 233 super.close();
08fe2e33
NR
234 }
235
236 protected String getDataPrefix() {
237 return "DATA/";
238 }
239
240 protected boolean requireInfo() {
241 return true;
242 }
243
244 protected boolean getCover() {
245 return true;
246 }
e4fa48a0
NR
247
248 protected boolean isImagesDocumentByDefault() {
249 return false;
250 }
08fe2e33 251}