X-Git-Url: http://git.nikiroo.be/?p=fanfix.git;a=blobdiff_plain;f=src%2Fbe%2Fnikiroo%2Ffanfix%2Fsupported%2FEpub.java;h=783d724e36aaa84e822f1fb5f4c6590371a4a8fd;hp=82ebb2b0ea025bdeb77c88a323b193f1a266b9ed;hb=0a264fbe3d5a43516006052574a5f322d9d38897;hpb=fe999aa400c2627291325558f1ae8c734da7900c diff --git a/src/be/nikiroo/fanfix/supported/Epub.java b/src/be/nikiroo/fanfix/supported/Epub.java index 82ebb2b..783d724 100644 --- a/src/be/nikiroo/fanfix/supported/Epub.java +++ b/src/be/nikiroo/fanfix/supported/Epub.java @@ -1,22 +1,25 @@ package be.nikiroo.fanfix.supported; -import java.awt.image.BufferedImage; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; +import java.net.URISyntaxException; import java.net.URL; -import java.util.List; -import java.util.Map.Entry; +import java.net.URLDecoder; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; -import javax.imageio.ImageIO; +import org.jsoup.nodes.Document; import be.nikiroo.fanfix.Instance; -import be.nikiroo.fanfix.bundles.Config; +import be.nikiroo.fanfix.data.MetaData; import be.nikiroo.utils.IOUtils; -import be.nikiroo.utils.MarkableFileInputStream; +import be.nikiroo.utils.Image; +import be.nikiroo.utils.StringUtils; +import be.nikiroo.utils.streams.MarkableFileInputStream; /** * Support class for EPUB files created with this program (as we need some @@ -24,247 +27,225 @@ import be.nikiroo.utils.MarkableFileInputStream; * * @author niki */ -class Epub extends BasicSupport { - private InfoText base; - private URL fakeSource; - - private File tmpCover; - private File tmpInfo; - private File tmp; - - /** Only used by {@link Epub#getInput()} so it is always reset. */ - private InputStream in; - - @Override - public String getSourceName() { - return "epub"; - } - - @Override - protected boolean supports(URL url) { - if (url.getPath().toLowerCase().endsWith(".epub")) { - return true; - } - - return false; - } - - @Override - protected boolean isHtml() { - if (tmpInfo.exists()) { - return base.isHtml(); - } - - return false; - } - - @Override - protected String getTitle(URL source, InputStream in) throws IOException { - if (tmpInfo.exists()) { - return base.getTitle(fakeSource, getFakeInput()); - } - - return source.toString(); - } - - @Override - protected String getAuthor(URL source, InputStream in) throws IOException { - if (tmpInfo.exists()) { - return base.getAuthor(fakeSource, getFakeInput()); - } - - return null; - } - - @Override - protected String getDate(URL source, InputStream in) throws IOException { - if (tmpInfo.exists()) { - return base.getDate(fakeSource, getFakeInput()); - } +class Epub extends InfoText { + private MetaData meta; + private File tmpDir; + private String desc; - return null; - } - - @Override - protected String getSubject(URL source, InputStream in) throws IOException { - if (tmpInfo.exists()) { - return base.getSubject(fakeSource, getFakeInput()); - } + private URL fakeSource; + private InputStream fakeIn; - return null; + public File getSourceFileOriginal() { + return super.getSourceFile(); } @Override - protected String getDesc(URL source, InputStream in) throws IOException { - if (tmpInfo.exists()) { - return base.getDesc(fakeSource, getFakeInput()); + protected File getSourceFile() { + try { + return new File(fakeSource.toURI()); + } catch (URISyntaxException e) { + Instance.getInstance().getTraceHandler().error(new IOException( + "Cannot get the source file from the info-text URL", e)); } return null; } @Override - protected URL getCover(URL source, InputStream in) throws IOException { - if (tmpCover.exists()) { - return tmpCover.toURI().toURL(); - } - - return null; - } + protected InputStream getInput() { + if (fakeIn != null) { + try { + fakeIn.reset(); + } catch (IOException e) { + Instance.getInstance().getTraceHandler().error(new IOException( + "Cannot reset the Epub Text stream", e)); + } - @Override - protected List> getChapters(URL source, InputStream in) - throws IOException { - if (tmpInfo.exists()) { - return base.getChapters(fakeSource, getFakeInput()); + return fakeIn; } return null; } @Override - protected String getChapterContent(URL source, InputStream in, int number) - throws IOException { - if (tmpInfo.exists()) { - return base.getChapterContent(fakeSource, getFakeInput(), number); - } - - return null; - } - - @Override - protected String getLang(URL source, InputStream in) throws IOException { - if (tmpInfo.exists()) { - return base.getLang(fakeSource, getFakeInput()); - } - - return super.getLang(source, in); + protected boolean supports(URL url) { + return url.getPath().toLowerCase().endsWith(".epub"); } @Override - protected String getPublisher(URL source, InputStream in) - throws IOException { - if (tmpInfo.exists()) { - return base.getPublisher(fakeSource, getFakeInput()); - } - - return super.getPublisher(source, in); + protected MetaData getMeta() throws IOException { + return meta; } @Override - protected List getTags(URL source, InputStream in) - throws IOException { - if (tmpInfo.exists()) { - return base.getTags(fakeSource, getFakeInput()); - } + protected Document loadDocument(URL source) throws IOException { + super.loadDocument(source); // prepares super.getSourceFile() and + // super.getInput() - return super.getTags(source, in); - } - - @Override - protected String getUuid(URL source, InputStream in) throws IOException { - if (tmpInfo.exists()) { - return base.getUuid(fakeSource, getFakeInput()); - } + InputStream in = super.getInput(); + ZipInputStream zipIn = null; + try { + zipIn = new ZipInputStream(in); + tmpDir = Instance.getInstance().getTempFiles() + .createTempDir("fanfic-reader-parser"); + File tmp = new File(tmpDir, "file.txt"); + File tmpInfo = new File(tmpDir, "file.info"); + + fakeSource = tmp.toURI().toURL(); + Image cover = null; + + String url; + try { + url = getSource().toURI().toURL().toString(); + } catch (URISyntaxException e1) { + url = getSource().toString(); + } + String title = null; + String author = null; + + for (ZipEntry entry = zipIn + .getNextEntry(); entry != null; entry = zipIn + .getNextEntry()) { + if (!entry.isDirectory() + && entry.getName().startsWith(getDataPrefix())) { + String entryLName = entry.getName().toLowerCase(); + entryLName = entryLName.substring(getDataPrefix().length()); + + boolean imageEntry = false; + for (String ext : bsImages.getImageExt(false)) { + if (entryLName.endsWith(ext)) { + imageEntry = true; + } + } - return super.getUuid(source, in); - } + if (entryLName.equals("version")) { + // Nothing to do for now ("first" + // version is 3.0) + } else if (entryLName.endsWith(".info")) { + // Info file + IOUtils.write(zipIn, tmpInfo); + } else if (imageEntry) { + // Cover + if (getCover() && cover == null) { + try { + Image img = new Image(zipIn); + if (img.getSize() == 0) { + img.close(); + throw new IOException( + "Empty image not accepted"); + } + cover = img; + } catch (Exception e) { + Instance.getInstance().getTraceHandler() + .error(e); + } + } + } else if (entryLName.equals("url")) { + String[] descArray = StringUtils + .unhtml(IOUtils.readSmallStream(zipIn)).trim() + .split("\n"); + if (descArray.length > 0) { + url = descArray[0].trim(); + } + } else if (entryLName.endsWith(".desc")) { + // // For old files + // if (this.desc != null) { + // this.desc = IOUtils.readSmallStream(zipIn).trim(); + // } + } else if (entryLName.equals("summary")) { + String[] descArray = StringUtils + .unhtml(IOUtils.readSmallStream(zipIn)).trim() + .split("\n"); + int skip = 0; + if (descArray.length > 1) { + title = descArray[0].trim(); + skip = 1; + if (descArray.length > 2 + && descArray[1].startsWith("©")) { + author = descArray[1].substring(1).trim(); + skip = 2; + } + } + // this.desc = ""; + // for (int i = skip; i < descArray.length; i++) { + // this.desc += descArray[i].trim() + "\n"; + // } + // + // this.desc = this.desc.trim(); + } else { + // Hopefully the data file + IOUtils.write(zipIn, tmp); + } + } + } - @Override - protected String getLuid(URL source, InputStream in) throws IOException { - if (tmpInfo.exists()) { - return base.getLuid(fakeSource, getFakeInput()); - } + if (requireInfo() && !tmp.exists()) { + throw new IOException( + "file not supported (maybe not created with this program or corrupt)"); + } - return super.getLuid(source, in); - } + if (tmp.exists()) { + this.fakeIn = new MarkableFileInputStream(tmp); + } - @Override - protected void preprocess(InputStream in) throws IOException { - // Note: do NOT close this stream, as it would also close "in" - ZipInputStream zipIn = new ZipInputStream(in); - tmp = File.createTempFile("fanfic-reader-parser_", ".tmp"); - tmpInfo = new File(tmp + ".info"); - tmpCover = File.createTempFile("fanfic-reader-parser_", ".tmp"); - - base = new InfoText(); - fakeSource = tmp.toURI().toURL(); - - for (ZipEntry entry = zipIn.getNextEntry(); entry != null; entry = zipIn - .getNextEntry()) { - if (!entry.isDirectory() - && entry.getName().startsWith(getDataPrefix())) { - String entryLName = entry.getName().toLowerCase(); - - boolean imageEntry = false; - for (String ext : getImageExt(false)) { - if (entryLName.endsWith(ext)) { - imageEntry = true; + if (tmpInfo.exists()) { + meta = InfoReader.readMeta(tmpInfo, true); + tmpInfo.delete(); + } else { + if (title == null || title.isEmpty()) { + title = getSourceFileOriginal().getName(); + String exts[] = new String[] {".epub", ".cbz"}; + for (String ext : exts) { + if (title.toLowerCase().endsWith(ext)) { + title = title.substring(0, + title.length() - ext.length()); + } } + title = URLDecoder.decode(title, "UTF-8").trim(); } - if (entry.getName().equals(getDataPrefix() + "version")) { - // Nothing to do for now ("first" - // version is 3.0) - } else if (entryLName.endsWith(".info")) { - // Info file - IOUtils.write(zipIn, tmpInfo); - } else if (imageEntry) { - // Cover - if (getCover()) { - try { - BufferedImage image = ImageIO.read(zipIn); - ImageIO.write(image, Instance.getConfig() - .getString(Config.IMAGE_FORMAT_COVER) - .toLowerCase(), tmpCover); - } catch (Exception e) { - Instance.syserr(e); - } - } - } else if (entry.getName().equals(getDataPrefix() + "URL")) { - // Do nothing - } else if (entry.getName().equals(getDataPrefix() + "SUMMARY")) { - // Do nothing + meta = new MetaData(); + meta.setLang("en"); + meta.setTags(Arrays.asList("[no_info]")); + meta.setSource(getType().getSourceName()); + meta.setUuid(url); + meta.setUrl(url); + meta.setTitle(title); + meta.setAuthor(author); + meta.setImageDocument(isImagesDocumentByDefault()); + + InfoReader.completeMeta(tmp, meta); + } + + if (meta.getCover() == null) { + if (cover != null) { + meta.setCover(cover); } else { - // Hopefully the data file - IOUtils.write(zipIn, tmp); + meta.setCover(InfoReader.getCoverByName( + getSourceFileOriginal().toURI().toURL())); } } + } finally { + if (zipIn != null) { + zipIn.close(); + } + if (in != null) { + in.close(); + } } - if (requireInfo() && (!tmp.exists() || !tmpInfo.exists())) { - throw new IOException( - "file not supported (maybe not created with this program or corrupt)"); - } - - if (tmp.exists()) { - this.in = new MarkableFileInputStream(new FileInputStream(tmp)); - } + return null; } @Override - protected void close() throws IOException { - for (File file : new File[] { tmp, tmpInfo, tmpCover }) { - if (file != null && file.exists()) { - if (!file.delete()) { - file.deleteOnExit(); - } - } + protected void close() { + if (tmpDir != null) { + IOUtils.deltree(tmpDir); } - tmp = null; - tmpInfo = null; - tmpCover = null; - fakeSource = null; + tmpDir = null; - try { - if (in != null) { - in.close(); - } - } finally { - in = null; - base.close(); - } + super.close(); } protected String getDataPrefix() { @@ -279,16 +260,7 @@ class Epub extends BasicSupport { return true; } - /** - * Reset then return {@link Epub#in}. - * - * @return {@link Epub#in} - * - * @throws IOException - * in case of I/O error - */ - private InputStream getFakeInput() throws IOException { - in.reset(); - return in; + protected boolean isImagesDocumentByDefault() { + return false; } }