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