synchronized void openBookInternal(Book book, Bookmark bookmark) { if (book == null) { book = Library.Instance().getRecentBook(); if (book == null || !book.File.exists()) { book = Book.getByFile(Library.getHelpFile()); } if (book == null) { return; } } if (Model != null) { if (bookmark == null & book.File.getPath().equals(Model.Book.File.getPath())) { return; } } if (book != null) { onViewChanged(); if (Model != null) { Model.Book.storePosition(BookTextView.getStartCursor()); } BookTextView.setModel(null); FootnoteView.setModel(null); clearTextCaches(); Model = null; System.gc(); System.gc(); try { Model = BookModel.createModel(book); ZLTextHyphenator.Instance().load(book.getLanguage()); BookTextView.setModel(Model.getTextModel()); BookTextView.gotoPosition(book.getStoredPosition()); if (bookmark == null) { setView(BookTextView); } else { gotoBookmark(bookmark); } Library.Instance().addBookToRecentList(book); final StringBuilder title = new StringBuilder(book.getTitle()); if (!book.authors().isEmpty()) { boolean first = true; for (Author a : book.authors()) { title.append(first ? " (" : ", "); title.append(a.DisplayName); first = false; } title.append(")"); } setTitle(title.toString()); } catch (BookReadingException e) { processException(e); } } getViewWidget().reset(); getViewWidget().repaint(); }
@Override public void detectLanguageAndEncoding(Book book) throws BookReadingException { InputStream stream = null; try { stream = book.File.getInputStream(); final PdbHeader header = new PdbHeader(stream); PdbUtil.skip(stream, header.Offsets[0] + 16 - header.length()); if (PdbUtil.readInt(stream) != 0x4D4F4249) /* "MOBI" */ { throw new BookReadingException("unsupportedFileFormat", book.File); } final int length = (int) PdbUtil.readInt(stream); PdbUtil.skip(stream, 4); final int encodingCode = (int) PdbUtil.readInt(stream); final Encoding encoding = supportedEncodings().getEncoding(encodingCode); final String encodingName = encoding != null ? encoding.Name : "utf-8"; book.setEncoding(encodingName); PdbUtil.skip(stream, 52); final int fullNameOffset = (int) PdbUtil.readInt(stream); final int fullNameLength = (int) PdbUtil.readInt(stream); final int languageCode = (int) PdbUtil.readInt(stream); book.setLanguage( ZLLanguageUtil.languageByIntCode(languageCode & 0xFF, (languageCode >> 8) & 0xFF)); } catch (IOException e) { throw new BookReadingException(e, book.File); } finally { if (stream != null) { try { stream.close(); } catch (IOException e) { } } } }
private void openBook(Book book) { startActivity( new Intent(getApplicationContext(), FBReader.class) .setAction(Intent.ACTION_VIEW) .putExtra(FBReader.BOOK_PATH_KEY, book.File.getPath()) .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)); }
@Override public synchronized void readMetaInfo(Book book) throws BookReadingException { final int code = readMetaInfoNative(book); if (code != 0) { throw new BookReadingException( "nativeCodeFailure", book.File, new String[] {String.valueOf(code), book.File.getPath()}); } }
public void removeBook(Book book, boolean deleteFromDisk) { synchronized (myBooksByFile) { myBooksByFile.remove(book.File); myBooksById.remove(book.getId()); final List<Long> ids = myDatabase.loadRecentBookIds(); if (ids.remove(book.getId())) { myDatabase.saveRecentBookIds(ids); } if (deleteFromDisk) { book.File.getPhysicalFile().delete(); } } fireBookEvent(BookEvent.Removed, book); }
public static void shareBook(Activity activity, Book book) { try { final ZLPhysicalFile file = book.File.getPhysicalFile(); if (file == null) { // That should be impossible return; } final CharSequence sharedFrom = Html.fromHtml(ZLResource.resource("sharing").getResource("sharedFrom").getValue()); activity.startActivity( new Intent(Intent.ACTION_SEND) .setType(FileTypeCollection.Instance.simplifiedMimeType(file).Name) .putExtra(Intent.EXTRA_SUBJECT, book.getTitle()) .putExtra(Intent.EXTRA_TEXT, sharedFrom) .putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file.javaFile()))); } catch (ActivityNotFoundException e) { // TODO: show toast } }
@Override public void readMetaInfo(Book book) throws BookReadingException { InputStream stream = null; try { stream = book.File.getInputStream(); final PdbHeader header = new PdbHeader(stream); PdbUtil.skip(stream, header.Offsets[0] + 16 - header.length()); if (PdbUtil.readInt(stream) != 0x4D4F4249) /* "MOBI" */ { throw new BookReadingException("unsupportedFileFormat", book.File); } final int length = (int) PdbUtil.readInt(stream); PdbUtil.skip(stream, 4); final int encodingCode = (int) PdbUtil.readInt(stream); final Encoding encoding = supportedEncodings().getEncoding(encodingCode); final String encodingName = encoding != null ? encoding.Name : "utf-8"; book.setEncoding(encodingName); PdbUtil.skip(stream, 52); final int fullNameOffset = (int) PdbUtil.readInt(stream); final int fullNameLength = (int) PdbUtil.readInt(stream); final int languageCode = (int) PdbUtil.readInt(stream); book.setLanguage( ZLLanguageUtil.languageByIntCode(languageCode & 0xFF, (languageCode >> 8) & 0xFF)); PdbUtil.skip(stream, 32); int offset = 132; if ((PdbUtil.readInt(stream) & 0x40) != 0) { PdbUtil.skip(stream, length - 116); offset = length + 20; if (PdbUtil.readInt(stream) == 0x45585448) /* "EXTH" */ { PdbUtil.skip(stream, 4); final int recordsNumber = (int) PdbUtil.readInt(stream); offset += 8; for (int i = 0; i < recordsNumber; ++i) { final int type = (int) PdbUtil.readInt(stream); final int size = (int) PdbUtil.readInt(stream); offset += size; if (size <= 8) { continue; } switch (type) { default: PdbUtil.skip(stream, size - 8); break; case 100: { final byte[] buffer = new byte[size - 8]; stream.read(buffer); String author = new String(buffer, encodingName); final int index = author.indexOf(','); if (index != -1) { author = author.substring(index + 1).trim() + ' ' + author.substring(0, index).trim(); } else { author = author.trim(); } book.addAuthor(author); break; } case 105: { final byte[] buffer = new byte[size - 8]; stream.read(buffer); book.addTag(new String(buffer, encodingName)); break; } } } } } PdbUtil.skip(stream, fullNameOffset - offset); final byte[] titleBuffer = new byte[fullNameLength]; stream.read(titleBuffer); book.setTitle(new String(titleBuffer, encodingName)); } catch (IOException e) { throw new BookReadingException(e, book.File); } finally { if (stream != null) { try { stream.close(); } catch (IOException e) { } } } }
private void build() { // Step 0: get database books marked as "existing" final FileInfoSet fileInfos = new FileInfoSet(myDatabase); final Map<Long, Book> savedBooksByFileId = myDatabase.loadBooks(fileInfos, true); final Map<Long, Book> savedBooksByBookId = new HashMap<Long, Book>(); for (Book b : savedBooksByFileId.values()) { savedBooksByBookId.put(b.getId(), b); } // Step 1: check if files corresponding to "existing" books really exists; // add books to library if yes (and reload book info if needed); // remove from recent/favorites list if no; // collect newly "orphaned" books final Set<Book> orphanedBooks = new HashSet<Book>(); final Set<ZLPhysicalFile> physicalFiles = new HashSet<ZLPhysicalFile>(); int count = 0; for (Book book : savedBooksByFileId.values()) { final ZLPhysicalFile file = book.File.getPhysicalFile(); if (file != null) { physicalFiles.add(file); } if (file != book.File && file != null && file.getPath().endsWith(".epub")) { continue; } if (book.File.exists()) { boolean doAdd = true; if (file == null) { continue; } if (!fileInfos.check(file, true)) { try { book.readMetaInfo(); saveBook(book, false); } catch (BookReadingException e) { doAdd = false; } file.setCached(false); } if (doAdd) { // loaded from db addBook(book, false); } } else { orphanedBooks.add(book); } } myDatabase.setExistingFlag(orphanedBooks, false); // Step 2: collect books from physical files; add new, update already added, // unmark orphaned as existing again, collect newly added final Map<Long, Book> orphanedBooksByFileId = myDatabase.loadBooks(fileInfos, false); final Set<Book> newBooks = new HashSet<Book>(); final List<ZLPhysicalFile> physicalFilesList = collectPhysicalFiles(BookDirectories); for (ZLPhysicalFile file : physicalFilesList) { if (physicalFiles.contains(file)) { continue; } collectBooks( file, fileInfos, savedBooksByFileId, orphanedBooksByFileId, newBooks, !fileInfos.check(file, true)); file.setCached(false); } // Step 3: add help file try { final ZLFile helpFile = BookUtil.getHelpFile(); Book helpBook = savedBooksByFileId.get(fileInfos.getId(helpFile)); if (helpBook == null) { helpBook = new Book(helpFile); } saveBook(helpBook, false); // saved addBook(helpBook, false); } catch (BookReadingException e) { // that's impossible e.printStackTrace(); } // Step 4: save changes into database fileInfos.save(); myDatabase.executeAsTransaction( new Runnable() { public void run() { for (Book book : newBooks) { saveBook(book, false); } } }); myDatabase.setExistingFlag(newBooks, true); }
protected void showBookInfo(Book book) { startActivityForResult( new Intent(getApplicationContext(), BookInfoActivity.class) .putExtra(BookInfoActivity.CURRENT_BOOK_PATH_KEY, book.File.getPath()), BOOK_INFO_REQUEST); }