mirror of
https://github.com/geometer/FBReaderJ.git
synced 2025-10-03 17:59:33 +02:00
better RTF encoding detection; don't fail on RTF files with .doc extension; fixed XML serialisation
This commit is contained in:
parent
a6c8ead2bf
commit
7e9d47bba9
5 changed files with 84 additions and 33 deletions
|
@ -6,11 +6,13 @@
|
|||
* (planned) Fixed authors list/tags list editing
|
||||
* (planned) CSS selectors priority
|
||||
|
||||
===== 2.3 (Feb ??, 2015) =====
|
||||
===== 2.3 (Feb 14, 2015) =====
|
||||
* File format filter option (can be changed from the bookshelf plugin)
|
||||
* Samsung multi-window support
|
||||
* Bookshelf view item in the library
|
||||
* Updated Persian localisation by biomanw (https://github.com/biomanw)
|
||||
* Better RTF encoding detection
|
||||
* Don't fail on RTF files with .doc extension
|
||||
|
||||
===== 2.2.7 (Jan 30, 2015) =====
|
||||
* Fixed behaviour for pages with multiple images (fb2.zip only)
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<node name="txt" value="txt"/>
|
||||
<node name="msdoc" value="Microsoft Word"/>
|
||||
<node name="HTML" value="HTML"/>
|
||||
<node name="rtf" value="RTF"/>
|
||||
<node name="RTF" value="RTF"/>
|
||||
<node name="PDF" value="PDF"/>
|
||||
<node name="DjVu" value="DjVu"/>
|
||||
<node name="CBZ" value="Comic book archive (cbz, cbr)"/>
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "DocMetaInfoReader.h"
|
||||
#include "DocBookReader.h"
|
||||
#include "DocStreams.h"
|
||||
#include "../rtf/RtfPlugin.h"
|
||||
#include "../../bookmodel/BookModel.h"
|
||||
#include "../../library/Book.h"
|
||||
|
||||
|
@ -36,6 +37,17 @@ DocPlugin::DocPlugin() {
|
|||
DocPlugin::~DocPlugin() {
|
||||
}
|
||||
|
||||
static bool isRtf(const Book &book) {
|
||||
shared_ptr<ZLInputStream> stream = book.file().inputStream();
|
||||
if (stream.isNull() || !stream->open()) {
|
||||
return false;
|
||||
}
|
||||
char buffer[6] = { 0 };
|
||||
stream->read(buffer, 5);
|
||||
static const std::string RTF_BYTES = "{\\rtf";
|
||||
return RTF_BYTES == buffer;
|
||||
}
|
||||
|
||||
bool DocPlugin::providesMetainfo() const {
|
||||
return true;
|
||||
}
|
||||
|
@ -49,6 +61,10 @@ bool DocPlugin::acceptsFile(const ZLFile &file) const {
|
|||
}
|
||||
|
||||
bool DocPlugin::readMetainfo(Book &book) const {
|
||||
if (::isRtf(book)) {
|
||||
return RtfPlugin().readMetainfo(book);
|
||||
}
|
||||
|
||||
if (!DocMetaInfoReader(book).readMetainfo()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -71,5 +87,9 @@ bool DocPlugin::readLanguageAndEncoding(Book &/*book*/) const {
|
|||
}
|
||||
|
||||
bool DocPlugin::readModel(BookModel &model) const {
|
||||
if (::isRtf(*model.book())) {
|
||||
return RtfPlugin().readModel(model);
|
||||
}
|
||||
|
||||
return DocBookReader(model, model.book()->encoding()).readBook();
|
||||
}
|
||||
|
|
|
@ -34,23 +34,16 @@ bool RtfPlugin::providesMetainfo() const {
|
|||
}
|
||||
|
||||
const std::string RtfPlugin::supportedFileType() const {
|
||||
return "rtf";
|
||||
return "RTF";
|
||||
}
|
||||
|
||||
bool RtfPlugin::readMetainfo(Book &book) const {
|
||||
readLanguageAndEncoding(book);
|
||||
|
||||
if (!RtfDescriptionReader(book).readDocument(book.file())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (book.encoding().empty()) {
|
||||
book.setEncoding(ZLEncodingConverter::UTF8);
|
||||
} else if (book.language().empty()) {
|
||||
shared_ptr<ZLInputStream> stream = new RtfReaderStream(book.file(), 50000);
|
||||
if (!stream.isNull()) {
|
||||
detectLanguage(book, *stream, book.encoding());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -64,5 +57,19 @@ bool RtfPlugin::readModel(BookModel &model) const {
|
|||
}
|
||||
|
||||
bool RtfPlugin::readLanguageAndEncoding(Book &book) const {
|
||||
if (book.encoding().empty()) {
|
||||
shared_ptr<ZLInputStream> stream = new RtfReaderStream(book.file(), 50000);
|
||||
if (!stream.isNull()) {
|
||||
detectEncodingAndLanguage(book, *stream);
|
||||
}
|
||||
if (book.encoding().empty()) {
|
||||
book.setEncoding(ZLEncodingConverter::UTF8);
|
||||
}
|
||||
} else if (book.language().empty()) {
|
||||
shared_ptr<ZLInputStream> stream = new RtfReaderStream(book.file(), 50000);
|
||||
if (!stream.isNull()) {
|
||||
detectLanguage(book, *stream, book.encoding());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -35,9 +35,13 @@ import org.geometerplus.zlibrary.core.util.ZLColor;
|
|||
import org.geometerplus.zlibrary.text.view.ZLTextPosition;
|
||||
|
||||
class XMLSerializer extends AbstractSerializer {
|
||||
private StringBuilder builder() {
|
||||
return new StringBuilder("<?xml version='1.1' encoding='UTF-8'?>");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String serialize(BookQuery query) {
|
||||
final StringBuilder buffer = new StringBuilder();
|
||||
final StringBuilder buffer = builder();
|
||||
appendTag(buffer, "query", false,
|
||||
"limit", String.valueOf(query.Limit),
|
||||
"page", String.valueOf(query.Page)
|
||||
|
@ -136,7 +140,7 @@ class XMLSerializer extends AbstractSerializer {
|
|||
|
||||
@Override
|
||||
public String serialize(BookmarkQuery query) {
|
||||
final StringBuilder buffer = new StringBuilder();
|
||||
final StringBuilder buffer = builder();
|
||||
appendTag(buffer, "query", false,
|
||||
"visible", String.valueOf(query.Visible),
|
||||
"limit", String.valueOf(query.Limit),
|
||||
|
@ -164,7 +168,7 @@ class XMLSerializer extends AbstractSerializer {
|
|||
|
||||
@Override
|
||||
public String serialize(Book book) {
|
||||
final StringBuilder buffer = new StringBuilder();
|
||||
final StringBuilder buffer = builder();
|
||||
serialize(buffer, book);
|
||||
return buffer.toString();
|
||||
}
|
||||
|
@ -262,7 +266,7 @@ class XMLSerializer extends AbstractSerializer {
|
|||
|
||||
@Override
|
||||
public String serialize(Bookmark bookmark) {
|
||||
final StringBuilder buffer = new StringBuilder();
|
||||
final StringBuilder buffer = builder();
|
||||
appendTag(
|
||||
buffer, "bookmark", false,
|
||||
"id", String.valueOf(bookmark.getId()),
|
||||
|
@ -325,7 +329,7 @@ class XMLSerializer extends AbstractSerializer {
|
|||
|
||||
@Override
|
||||
public String serialize(HighlightingStyle style) {
|
||||
final StringBuilder buffer = new StringBuilder();
|
||||
final StringBuilder buffer = builder();
|
||||
final ZLColor bgColor = style.getBackgroundColor();
|
||||
final ZLColor fgColor = style.getForegroundColor();
|
||||
appendTag(buffer, "style", true,
|
||||
|
@ -441,23 +445,41 @@ class XMLSerializer extends AbstractSerializer {
|
|||
}
|
||||
}
|
||||
|
||||
private static String escapeForXml(String data) {
|
||||
if (data.indexOf('&') != -1) {
|
||||
data = data.replaceAll("&", "&");
|
||||
private static CharSequence escapeForXml(String data) {
|
||||
final StringBuilder buffer = new StringBuilder();
|
||||
|
||||
final int len = data.length();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
final char ch = data.charAt(i);
|
||||
switch (ch) {
|
||||
case '\u0009':
|
||||
buffer.append(ch);
|
||||
break;
|
||||
default:
|
||||
if ((ch >= '\u0020' && ch <= '\uD7FF') ||
|
||||
(ch >= '\u0E00' && ch <= '\uFFFD')) {
|
||||
buffer.append(ch);
|
||||
}
|
||||
break;
|
||||
case '&':
|
||||
buffer.append("&");
|
||||
break;
|
||||
case '<':
|
||||
buffer.append("<");
|
||||
break;
|
||||
case '>':
|
||||
buffer.append(">");
|
||||
break;
|
||||
case '"':
|
||||
buffer.append(""");
|
||||
break;
|
||||
case '\'':
|
||||
buffer.append("'");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (data.indexOf('<') != -1) {
|
||||
data = data.replaceAll("<", "<");
|
||||
}
|
||||
if (data.indexOf('>') != -1) {
|
||||
data = data.replaceAll(">", ">");
|
||||
}
|
||||
if (data.indexOf('\'') != -1) {
|
||||
data = data.replaceAll("'", "'");
|
||||
}
|
||||
if (data.indexOf('"') != -1) {
|
||||
data = data.replaceAll("\"", """);
|
||||
}
|
||||
return data;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
private static void clear(StringBuilder buffer) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue