diff --git a/jni/Android.mk b/jni/Android.mk index 4f1b16ae4..099dcbc04 100644 --- a/jni/Android.mk +++ b/jni/Android.mk @@ -38,6 +38,7 @@ LOCAL_SRC_FILES := \ NativeFormats/JavaNativeFormatPlugin.cpp \ NativeFormats/JavaPluginCollection.cpp \ NativeFormats/util/AndroidUtil.cpp \ + NativeFormats/zlibrary/core/src/encoding/DummyEncodingConverter.cpp \ NativeFormats/zlibrary/core/src/encoding/ZLEncodingCollection.cpp \ NativeFormats/zlibrary/core/src/encoding/ZLEncodingConverter.cpp \ NativeFormats/zlibrary/core/src/filesystem/ZLDir.cpp \ @@ -58,7 +59,11 @@ LOCAL_SRC_FILES := \ NativeFormats/zlibrary/core/src/xml/ZLAsynchronousInputStream.cpp \ NativeFormats/zlibrary/core/src/xml/ZLXMLReader.cpp \ NativeFormats/zlibrary/core/src/xml/expat/ZLXMLReaderInternal.cpp \ + NativeFormats/zlibrary/core/src/unix/filesystem/ZLUnixFSDir.cpp \ + NativeFormats/zlibrary/core/src/unix/filesystem/ZLUnixFSManager.cpp \ NativeFormats/zlibrary/core/src/unix/library/ZLUnixLibrary.cpp \ + NativeFormats/zlibrary/ui/src/android/filesystem/JavaFSDir.cpp \ + NativeFormats/zlibrary/ui/src/android/filesystem/JavaInputStream.cpp \ NativeFormats/zlibrary/ui/src/android/filesystem/ZLAndroidFSManager.cpp \ NativeFormats/zlibrary/ui/src/android/library/ZLAndroidLibraryImplementation.cpp \ NativeFormats/fbreader/src/formats/FormatPlugin.cpp \ diff --git a/jni/NativeFormats/util/AndroidUtil.cpp b/jni/NativeFormats/util/AndroidUtil.cpp index 3475c5a42..ad9703298 100644 --- a/jni/NativeFormats/util/AndroidUtil.cpp +++ b/jni/NativeFormats/util/AndroidUtil.cpp @@ -37,6 +37,9 @@ jmethodID AndroidUtil::MID_ZLibrary_getVersionName; jmethodID AndroidUtil::SMID_PluginCollection_Instance; +jmethodID AndroidUtil::MID_ZLFile_size; +jmethodID AndroidUtil::MID_ZLFile_exists; +jmethodID AndroidUtil::MID_ZLFile_isDirectory; jmethodID AndroidUtil::MID_ZLFile_getPath; jfieldID AndroidUtil::FID_Book_File; @@ -71,6 +74,9 @@ bool AndroidUtil::init(JavaVM* jvm) { env->DeleteLocalRef(cls); CHECK_NULL( cls = env->FindClass(Class_ZLFile) ); + CHECK_NULL( MID_ZLFile_size = env->GetMethodID(cls, "size", "()J") ); + CHECK_NULL( MID_ZLFile_exists = env->GetMethodID(cls, "exists", "()Z") ); + CHECK_NULL( MID_ZLFile_isDirectory = env->GetMethodID(cls, "isDirectory", "()Z") ); CHECK_NULL( MID_ZLFile_getPath = env->GetMethodID(cls, "getPath", "()Ljava/lang/String;") ); env->DeleteLocalRef(cls); @@ -86,6 +92,15 @@ bool AndroidUtil::init(JavaVM* jvm) { env->DeleteLocalRef(cls); } +jobject AndroidUtil::createZLFile(JNIEnv *env, const std::string &path) { + jstring javaPath = env->NewStringUTF(path.c_str()); + jclass cls = env->FindClass(Class_ZLFile); + jobject javaFile = env->CallStaticObjectMethod(cls, SMID_ZLFile_createFileByPath, javaPath); + env->DeleteLocalRef(cls); + env->DeleteLocalRef(javaPath); + return javaFile; +} + bool AndroidUtil::extractJavaString(JNIEnv *env, jstring from, std::string &to) { if (from == 0) { return false; diff --git a/jni/NativeFormats/util/AndroidUtil.h b/jni/NativeFormats/util/AndroidUtil.h index 06085d032..0af0e60b6 100644 --- a/jni/NativeFormats/util/AndroidUtil.h +++ b/jni/NativeFormats/util/AndroidUtil.h @@ -30,6 +30,7 @@ private: static JavaVM *ourJavaVM; public: + static const char * const Class_java_util_Collection; static const char * const Class_java_util_Locale; static const char * const Class_ZLibrary; static const char * const Class_ZLFile; @@ -38,12 +39,19 @@ public: static const char * const Class_Book; static const char * const Class_Tag; + static jmethodID MID_java_util_Collection_toArray; + static jmethodID SMID_java_util_Locale_getDefault; static jmethodID MID_java_util_Locale_getLanguage; static jmethodID SMID_ZLibrary_Instance; static jmethodID MID_ZLibrary_getVersionName; + static jmethodID SMID_ZLFile_createFileByPath; + static jmethodID MID_ZLFile_children; + static jmethodID MID_ZLFile_size; + static jmethodID MID_ZLFile_exists; + static jmethodID MID_ZLFile_isDirectory; static jmethodID MID_ZLFile_getPath; static jmethodID SMID_PluginCollection_Instance; @@ -59,6 +67,7 @@ public: static bool init(JavaVM* jvm); static JNIEnv *getEnv(); + static jobject createZLFile(JNIEnv *env, const std::string &path); static bool extractJavaString(JNIEnv *env, jstring from, std::string &to); static jstring createJavaString(JNIEnv* env, const std::string &str); }; diff --git a/jni/NativeFormats/zlibrary/core/src/encoding/DummyEncodingConverter.cpp b/jni/NativeFormats/zlibrary/core/src/encoding/DummyEncodingConverter.cpp new file mode 100644 index 000000000..ecfb277cf --- /dev/null +++ b/jni/NativeFormats/zlibrary/core/src/encoding/DummyEncodingConverter.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include + +#include "DummyEncodingConverter.h" + +class DummyEncodingConverter : public ZLEncodingConverter { + +private: + DummyEncodingConverter(); + +public: + ~DummyEncodingConverter(); + void convert(std::string &dst, const char *srcStart, const char *srcEnd); + void reset(); + bool fillTable(int *map); + +friend class DummyEncodingConverterProvider; +}; + +bool DummyEncodingConverterProvider::providesConverter(const std::string &encoding) { + const std::string lowerCasedEncoding = ZLUnicodeUtil::toLower(encoding); + return (lowerCasedEncoding == "utf-8") || (lowerCasedEncoding == "us-ascii"); +} + +shared_ptr DummyEncodingConverterProvider::createConverter() { + return new DummyEncodingConverter(); +} + +shared_ptr DummyEncodingConverterProvider::createConverter(const std::string&) { + return createConverter(); +} + +DummyEncodingConverter::DummyEncodingConverter() { +} + +DummyEncodingConverter::~DummyEncodingConverter() { +} + +void DummyEncodingConverter::convert(std::string &dst, const char *srcStart, const char *srcEnd) { + dst.append(srcStart, srcEnd - srcStart); +} + +void DummyEncodingConverter::reset() { +} + +bool DummyEncodingConverter::fillTable(int *map) { + for (int i = 0; i < 255; ++i) { + map[i] = i; + } + return true; +} diff --git a/jni/NativeFormats/zlibrary/core/src/unix/filesystem/ZLUnixFSDir.cpp b/jni/NativeFormats/zlibrary/core/src/unix/filesystem/ZLUnixFSDir.cpp new file mode 100644 index 000000000..43dadf0cc --- /dev/null +++ b/jni/NativeFormats/zlibrary/core/src/unix/filesystem/ZLUnixFSDir.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include +#include +#include + +#include "ZLUnixFSDir.h" + +void ZLUnixFSDir::collectSubDirs(std::vector &names, bool includeSymlinks) { + DIR *dir = opendir(path().c_str()); + if (dir != 0) { + const std::string namePrefix = path() + delimiter(); + const dirent *file; + struct stat fileInfo; + std::string shortName; + while ((file = readdir(dir)) != 0) { + shortName = file->d_name; + if ((shortName == ".") || (shortName == "..")) { + continue; + } + const std::string path = namePrefix + shortName; + if (includeSymlinks) { + stat(path.c_str(), &fileInfo); + } else { + lstat(path.c_str(), &fileInfo); + } + if (S_ISDIR(fileInfo.st_mode)) { + names.push_back(shortName); + } + } + closedir(dir); + } +} + +void ZLUnixFSDir::collectFiles(std::vector &names, bool includeSymlinks) { + DIR *dir = opendir(path().c_str()); + if (dir != 0) { + const std::string namePrefix = path() + delimiter(); + const dirent *file; + struct stat fileInfo; + std::string shortName; + while ((file = readdir(dir)) != 0) { + shortName = file->d_name; + if ((shortName == ".") || (shortName == "..")) { + continue; + } + const std::string path = namePrefix + shortName; + if (includeSymlinks) { + stat(path.c_str(), &fileInfo); + } else { + lstat(path.c_str(), &fileInfo); + } + if (S_ISREG(fileInfo.st_mode)) { + names.push_back(shortName); + } + } + closedir(dir); + } +} diff --git a/jni/NativeFormats/zlibrary/core/src/unix/filesystem/ZLUnixFSDir.h b/jni/NativeFormats/zlibrary/core/src/unix/filesystem/ZLUnixFSDir.h new file mode 100644 index 000000000..7efbc4c19 --- /dev/null +++ b/jni/NativeFormats/zlibrary/core/src/unix/filesystem/ZLUnixFSDir.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef __ZLUNIXFSDIR_H__ +#define __ZLUNIXFSDIR_H__ + +#include "../../filesystem/ZLFSDir.h" + +class ZLUnixFSDir : public ZLFSDir { + +public: + ZLUnixFSDir(const std::string &name) : ZLFSDir(name) {} + + void collectSubDirs(std::vector &names, bool includeSymlinks); + void collectFiles(std::vector &names, bool includeSymlinks); +}; + +#endif /* __ZLUNIXFSDIR_H__ */ diff --git a/jni/NativeFormats/zlibrary/core/src/unix/filesystem/ZLUnixFSManager.cpp b/jni/NativeFormats/zlibrary/core/src/unix/filesystem/ZLUnixFSManager.cpp new file mode 100644 index 000000000..0c6ceb73f --- /dev/null +++ b/jni/NativeFormats/zlibrary/core/src/unix/filesystem/ZLUnixFSManager.cpp @@ -0,0 +1,192 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include +#include +#include +#include + +#include + +#include + +#include "ZLUnixFSManager.h" +#include "ZLUnixFSDir.h" +#include "ZLUnixFileInputStream.h" +#include "ZLUnixFileOutputStream.h" + +static std::string getPwdDir() { + char *pwd = getenv("PWD"); + return (pwd != 0) ? pwd : ""; +} + +static std::string getHomeDir() { + char *home = getenv("HOME"); + return (home != 0) ? home : ""; +} + +ZLFileInfo ZLUnixFSManager::fileInfo(const std::string &path) const { + ZLFileInfo info; + struct stat fileStat; + info.Exists = stat(path.c_str(), &fileStat) == 0; + if (info.Exists) { + info.Size = fileStat.st_size; + info.IsDirectory = S_ISDIR(fileStat.st_mode); + } + return info; +} + +std::string ZLUnixFSManager::resolveSymlink(const std::string &path) const { + std::set names; + std::string current = path; + for (int i = 0; i < 256; ++i) { + names.insert(current); + + std::string buffer(2048, '\0'); + int len = readlink(current.c_str(), (char*)buffer.data(), 2048); + if ((len == 2048) || (len <= 0)) { + return current; + } + buffer.erase(len); + if (buffer[0] != '/') { + buffer = parentPath(current) + '/' + buffer; + } + normalizeRealPath(buffer); + if (names.find(buffer) != names.end()) { + return buffer; + } + current = buffer; + } + return ""; +} + +void ZLUnixFSManager::normalizeRealPath(std::string &path) const { + static std::string HomeDir = getHomeDir(); + static std::string PwdDir = getPwdDir(); + + if (path.empty()) { + path = PwdDir; + } else if (path[0] == '~') { + if ((path.length() == 1) || (path[1] == '/')) { + path = HomeDir + path.substr(1); + } + } else if (path[0] != '/') { + path = PwdDir + '/' + path; + } + int last = path.length() - 1; + while ((last > 0) && (path[last] == '/')) { + --last; + } + if (last < (int)path.length() - 1) { + path = path.substr(0, last + 1); + } + + int index; + while ((index = path.find("/../")) != -1) { + int prevIndex = std::max((int)path.rfind('/', index - 1), 0); + path.erase(prevIndex, index + 3 - prevIndex); + } + int len = path.length(); + if ((len >= 3) && (path.substr(len - 3) == "/..")) { + int prevIndex = std::max((int)path.rfind('/', len - 4), 0); + path.erase(prevIndex); + } + while ((index = path.find("/./")) != -1) { + path.erase(index, 2); + } + while (path.length() >= 2 && + path.substr(path.length() - 2) == "/.") { + path.erase(path.length() - 2); + } + while ((index = path.find("//")) != -1) { + path.erase(index, 1); + } +} + +ZLFSDir *ZLUnixFSManager::createNewDirectory(const std::string &path) const { + std::vector subpaths; + std::string current = path; + + while (current.length() > 1) { + struct stat fileStat; + if (stat(current.c_str(), &fileStat) == 0) { + if (!S_ISDIR(fileStat.st_mode)) { + return 0; + } + break; + } else { + subpaths.push_back(current); + int index = current.rfind('/'); + if (index == -1) { + return 0; + } + current.erase(index); + } + } + + for (int i = subpaths.size() - 1; i >= 0; --i) { + if (mkdir(subpaths[i].c_str(), 0x1FF) != 0) { + return 0; + } + } + return createPlainDirectory(path); +} + +ZLFSDir *ZLUnixFSManager::createPlainDirectory(const std::string &path) const { + return new ZLUnixFSDir(path); +} + +ZLInputStream *ZLUnixFSManager::createPlainInputStream(const std::string &path) const { + return new ZLUnixFileInputStream(path); +} + +ZLOutputStream *ZLUnixFSManager::createOutputStream(const std::string &path) const { + return new ZLUnixFileOutputStream(path); +} + +bool ZLUnixFSManager::removeFile(const std::string &path) const { + return unlink(path.c_str()) == 0; +} + +int ZLUnixFSManager::findArchiveFileNameDelimiter(const std::string &path) const { + return path.rfind(':'); +} + +static const std::string RootPath = "/"; + +shared_ptr ZLUnixFSManager::rootDirectory() const { + return createPlainDirectory(RootPath); +} + +const std::string &ZLUnixFSManager::rootDirectoryPath() const { + return RootPath; +} + +std::string ZLUnixFSManager::parentPath(const std::string &path) const { + if (path == RootPath) { + return path; + } + int index = findLastFileNameDelimiter(path); + return (index <= 0) ? RootPath : path.substr(0, index); +} + +bool ZLUnixFSManager::canRemoveFile(const std::string &path) const { + return access(parentPath(path).c_str(), W_OK) == 0; +} + diff --git a/jni/NativeFormats/zlibrary/core/src/unix/filesystem/ZLUnixFileInputStream.h b/jni/NativeFormats/zlibrary/core/src/unix/filesystem/ZLUnixFileInputStream.h new file mode 100644 index 000000000..5653c6214 --- /dev/null +++ b/jni/NativeFormats/zlibrary/core/src/unix/filesystem/ZLUnixFileInputStream.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef __ZLUNIXFILEINPUTSTREAM_H__ +#define __ZLUNIXFILEINPUTSTREAM_H__ + +#include + +#include + +class ZLUnixFileInputStream : public ZLInputStream { + +public: + ZLUnixFileInputStream(const std::string &name); + ~ZLUnixFileInputStream(); + bool open(); + size_t read(char *buffer, size_t maxSize); + void close(); + + void seek(int offset, bool absoluteOffset); + size_t offset() const; + size_t sizeOfOpened(); + +private: + std::string myName; + FILE *myFile; + bool myNeedRepositionToStart; +}; + +#endif /* __ZLUNIXFILEINPUTSTREAM_H__ */ diff --git a/jni/NativeFormats/zlibrary/core/src/unix/filesystem/ZLUnixFileOutputStream.h b/jni/NativeFormats/zlibrary/core/src/unix/filesystem/ZLUnixFileOutputStream.h new file mode 100644 index 000000000..f0badb1c5 --- /dev/null +++ b/jni/NativeFormats/zlibrary/core/src/unix/filesystem/ZLUnixFileOutputStream.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef __ZLUNIXFILEOUTPUTSTREAM_H__ +#define __ZLUNIXFILEOUTPUTSTREAM_H__ + +#include + +#include + +class ZLUnixFileOutputStream : public ZLOutputStream { + +public: + ZLUnixFileOutputStream(const std::string &name); + ~ZLUnixFileOutputStream(); + bool open(); + void write(const char *data, size_t len); + void write(const std::string &str); + void close(); + +private: + std::string myName; + std::string myTemporaryName; + bool myHasErrors; + FILE *myFile; +}; + +#endif /* __ZLUNIXFILEOUTPUTSTREAM_H__ */