Initial commit

This commit is contained in:
Aryan 2026-02-24 17:37:40 +05:30
commit 6072b2ba29
844 changed files with 220532 additions and 0 deletions

95
app/src/main/cpp/CMakeLists.txt vendored Normal file
View file

@ -0,0 +1,95 @@
# CMakeLists.txt
# Sets the minimum version of CMake required.
cmake_minimum_required(VERSION 3.22.1)
# Declares the project name.
project("reader-native")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-z,max-page-size=16384")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,max-page-size=16384")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
# --- CONFIGURE SUBPROJECTS ---
# Force subprojects to build as static libraries. This is critical for Android.
set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build shared libraries" FORCE)
set(BROTLI_DISABLE_TESTS ON CACHE BOOL "Disable Brotli tests" FORCE)
# ===================================================================
# WOFF2 DEPENDENCY SETUP
# ===================================================================
# 1. Add the brotli project. This defines the `brotlidec-static` target.
add_subdirectory(woff2/brotli)
# 2. Manually define the variables that the woff2/CMakeLists.txt script expects.
set(BROTLIDEC_FOUND TRUE)
set(BROTLIENC_FOUND TRUE)
set(BROTLIDEC_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/woff2/brotli/c/include)
set(BROTLIENC_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/woff2/brotli/c/include)
set(BROTLIDEC_LIBRARIES brotlidec-static)
set(BROTLIENC_LIBRARIES brotlienc-static)
# 3. Add the woff2 project. This defines the `woff2dec` target.
add_subdirectory(woff2)
# ===================================================================
# LIBMOBI DEPENDENCY SETUP
# ===================================================================
# 4. Set libmobi options before adding it.
# We disable libxml2 to use the internal writer, simplifying dependencies.
# We also disable encryption for now for the same reason.
set(USE_LIBXML2 OFF CACHE BOOL "Use libxml2" FORCE)
set(USE_ENCRYPTION OFF CACHE BOOL "Enable encryption" FORCE)
# Temporarily enable shared libs to build libmobi as a .so file for LGPL compliance.
set(BUILD_SHARED_LIBS ON)
# 5. Add the libmobi project. This will define the `mobi` target as a shared library.
add_subdirectory(libmobi)
set_target_properties(mobi PROPERTIES VERSION "" SOVERSION "")
# Revert back to building static libs for any subsequent dependencies.
set(BUILD_SHARED_LIBS OFF)
# Force all symbols in the mobi shared library to be visible.
# This is necessary because some internal functions we use (like mobi_determine_flowpart_type)
# are not explicitly exported by the library's public API for shared builds.
set_target_properties(mobi PROPERTIES C_VISIBILITY_PRESET default)
# ===================================================================
# FINAL NATIVE LIBRARY FOR THE APP
# ===================================================================
# 6. Define our final JNI wrapper library.
# This single .so file will be loaded by the Android app.
add_library(
native-lib
SHARED
Woff2Converter.cpp
mobi_jni_bridge.c # The placeholder file you created
)
# 7. Tell our library where to find all necessary header files.
target_include_directories(native-lib
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/woff2/include
${CMAKE_CURRENT_SOURCE_DIR}/libmobi/src
)
# 8. Find the Android logging and zlib libraries.
find_library(log-lib log)
find_library(z-lib z)
# 9. Link our final library against all the static libraries and Android libraries.
target_link_libraries(
native-lib
PRIVATE
woff2dec # From woff2
mobi # From libmobi
${log-lib}
${z-lib} # libmobi requires zlib
)

56
app/src/main/cpp/Woff2Converter.cpp vendored Normal file
View file

@ -0,0 +1,56 @@
#include <jni.h>
#include <string>
#include <vector>
// This is the correct header for the public API
#include <woff2/decode.h>
extern "C" JNIEXPORT jbyteArray JNICALL
Java_com_aryan_reader_paginatedreader_Woff2Converter_convertWoff2ToTtf(
JNIEnv *env,
jobject /* this */,
jbyteArray woff2_data) {
// Get the input WOFF2 data from the jbyteArray
jbyte* woff2_bytes = env->GetByteArrayElements(woff2_data, nullptr);
jsize woff2_size = env->GetArrayLength(woff2_data);
const uint8_t* woff2_input = reinterpret_cast<const uint8_t*>(woff2_bytes);
// Calculate the required size using the correct function name from your header
size_t ttf_size = woff2::ComputeWOFF2FinalSize(woff2_input, woff2_size);
if (ttf_size == 0) {
// This indicates an error in the input font data
env->ReleaseByteArrayElements(woff2_data, woff2_bytes, JNI_ABORT);
return nullptr;
}
// Create the output buffer
std::vector<uint8_t> ttf_output(ttf_size);
// Perform the conversion using the deprecated function signature that matches your header
bool success = woff2::ConvertWOFF2ToTTF(
ttf_output.data(), ttf_size,
woff2_input, woff2_size
);
// Release the input byte array
env->ReleaseByteArrayElements(woff2_data, woff2_bytes, JNI_ABORT);
// If conversion failed, return null
if (!success) {
return nullptr;
}
// Create a new Java byte array for the result
jbyteArray ttf_data = env->NewByteArray(ttf_size);
if (ttf_data == nullptr) {
// Out of memory error
return nullptr;
}
// Copy the converted data to the Java byte array
env->SetByteArrayRegion(ttf_data, 0, ttf_size,
reinterpret_cast<const jbyte*>(ttf_output.data()));
return ttf_data;
}

View file

@ -0,0 +1,101 @@
name: Build
on:
push:
branches: [ public ]
pull_request:
branches: [ public ]
jobs:
unix-build:
runs-on: ubuntu-latest
defaults:
run:
shell: bash
strategy:
fail-fast: false
matrix:
config:
- name: default build with debug
options: --enable-debug
- name: bulid with internal libs
options: --with-zlib=no --with-libxml2=no
- name: build without encryption
options: --disable-encryption
steps:
- uses: actions/checkout@v4
- name: install dependencies
run: |
if [ "${{ runner.os }}" = "Linux" ]; then
sudo apt-get update -qq;
sudo apt-get install -y autotools-dev pkg-config automake autoconf libtool;
sudo apt-get install -y zlib1g-dev libxml2-dev;
elif [ "${{ runner.os }}" = "macOS" ]; then
brew update > /dev/null;
brew outdated autoconf || brew upgrade autoconf;
brew outdated automake || brew upgrade automake;
brew outdated libtool || brew upgrade libtool;
fi
- name: autogen
run: ./autogen.sh
- name: configure
run: ./configure ${{ matrix.config.options }}
- name: make
run: make -j `nproc`
- name: make check
run: make -j `nproc` check
- name: make distcheck
run: make -j `nproc` distcheck
- name: upload debug artifacts
uses: actions/upload-artifact@v4
if: ${{ failure() }}
with:
name: test-logs-${{ matrix.runs-on }}
path: |
**/tests/test-suite.log
**/tests/samples/*.log
win64-build:
runs-on: windows-latest
defaults:
run:
shell: msys2 {0}
steps:
- name: setup-msys2
uses: msys2/setup-msys2@v2
with:
msystem: MINGW64
path-type: minimal
update: true
install: >-
git
autotools
base-devel
mingw-w64-x86_64-toolchain
mingw-w64-x86_64-libtool
mingw-w64-x86_64-libxml2
mingw-w64-x86_64-zlib
- name: checkout
uses: actions/checkout@v4
- name: autogen
run: sh ./autogen.sh
- name: configure
run: ./configure --enable-debug
- name: make
run: make -j$(nproc)
- name: make check
run: make -j$(nproc) check
- name: make distcheck
run: make -j$(nproc) distcheck
- name: upload debug artifacts
uses: actions/upload-artifact@v4
if: ${{ failure() }}
with:
name: test-logs-${{ matrix.runs-on }}
path: |
**/tests/test-suite.log
**/tests/samples/*.log

View file

@ -0,0 +1,71 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ public ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ public ]
schedule:
- cron: '19 13 * * 3'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'cpp' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

View file

@ -0,0 +1,54 @@
name: coverity-scan
on:
push:
branches: [ public ]
jobs:
coverity-build:
runs-on: ubuntu-latest
defaults:
run:
shell: bash
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: install dependencies
run: |
sudo apt-get update -qq;
sudo apt-get install -y autotools-dev pkg-config automake autoconf libtool;
sudo apt-get install -y zlib1g-dev libxml2-dev;
- name: download coverity tools
run: |
curl -Lf \
-o cov-analysis-linux64.tar.gz \
--form project=bfabiszewski/libmobi \
--form token=$TOKEN \
https://scan.coverity.com/download/linux64
mkdir cov-analysis-linux64
tar xzf cov-analysis-linux64.tar.gz --strip 1 -C cov-analysis-linux64
env:
TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
- name: autogen
run: ./autogen.sh
- name: configure
run: ./configure ${{ matrix.config.options }}
- name: build with cov-build
run: |
export PATH=`pwd`/cov-analysis-linux64/bin:$PATH
cov-build --dir cov-int make -j `nproc`
- name: upload results to coverity-scan
run: |
tar czvf cov-int.tgz cov-int
curl -Lf \
--form token=$TOKEN \
--form email=scan.coverity@fabiszewski.net \
--form file=@cov-int.tgz \
--form version="`git describe --tags`" \
--form description="libmobi `git describe --tags`" \
"https://scan.coverity.com/builds?project=bfabiszewski/libmobi"
env:
TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}

39
app/src/main/cpp/libmobi/.travis.yml vendored Normal file
View file

@ -0,0 +1,39 @@
os:
- linux
# - osx
language: c
compiler:
- clang
- gcc
before_install:
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then
sudo apt-get update -qq;
sudo apt-get install -y autotools-dev pkg-config automake autoconf libtool;
sudo apt-get install -y zlib1g-dev libxml2-dev;
elif [ "$TRAVIS_OS_NAME" == "osx" ]; then
brew update > /dev/null;
brew outdated autoconf || brew upgrade autoconf;
brew outdated automake || brew upgrade automake;
brew outdated libtool || brew upgrade libtool;
fi
- git config --global user.name "Travis CI (libmobi)"
- git config --global user.email $HOSTNAME":not-for-mail@travis-ci.org"
script:
- ./autogen.sh
- ./configure --enable-debug && make && make test
- make clean
- ./configure --with-zlib=no --with-libxml2=no && make && make test
env:
global:
- secure: "ShIL3IDvH59cJx4QAKWhVTs7ynCAfID11DqK8pIWJX2UtvXc4pdDQUq6U5ZRLUT0BR6kmLNxYrQUpUKvZ9sYnPuj4X5o9jzXzXsJPXTy/qpjiLK4MCZLIlI4OAHexfAuZTOVZHOoE/B8ABpk8nGYUXk02++LxlmwtE/fIWOOWHs="
addons:
coverity_scan:
project:
name: "bfabiszewski/libmobi"
description: "Build submitted via Travis CI"
notification_email: scan.coverity@fabiszewski.net
build_command_prepend: "./autogen.sh && ./configure"
build_command: "make -j 4"
branch_pattern: public

0
app/src/main/cpp/libmobi/AUTHORS vendored Normal file
View file

118
app/src/main/cpp/libmobi/CMakeLists.txt vendored Normal file
View file

@ -0,0 +1,118 @@
# Copyright (c) 2022 Bartek Fabiszewski
# http://www.fabiszewski.net
#
# This file is part of libmobi.
# Licensed under LGPL, either version 3, or any later.
# See <http://www.gnu.org/licenses/>
cmake_minimum_required(VERSION 3.12)
project(LIBMOBI C)
set(CMAKE_C_STANDARD 99)
file(STRINGS ${LIBMOBI_SOURCE_DIR}/configure.ac VERSION_LINE REGEX "AC_INIT\\(\\[libmobi\\], \\[(.*)\\]\\)")
string(REGEX MATCH "([0-9]+\\.[0-9]+)" PACKAGE_VERSION "${VERSION_LINE}")
message(STATUS "libmobi version ${PACKAGE_VERSION}")
add_definitions(-DPACKAGE_VERSION="${PACKAGE_VERSION}")
string(REPLACE "." ";" VERSION_LIST ${PACKAGE_VERSION})
list(GET VERSION_LIST 0 PACKAGE_VERSION_MAJOR)
list(GET VERSION_LIST 1 PACKAGE_VERSION_MINOR)
# Option to enable encryption
option(USE_ENCRYPTION "Enable encryption" ON)
# Option to enable static tools compilation
option(TOOLS_STATIC "Enable static tools compilation" OFF)
# Option to use libxml2
option(USE_LIBXML2 "Use libxml2 instead of internal xmlwriter" ON)
# Option to use zlib
option(USE_ZLIB "Use zlib" ON)
# Option to enable XMLWRITER
option(USE_XMLWRITER "Enable xmlwriter (for opf support)" ON)
# Option to enable debug
option(MOBI_DEBUG "Enable debug" OFF)
# Option to enable debug alloc
option(MOBI_DEBUG_ALLOC "Enable debug alloc" OFF)
option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
if(TOOLS_STATIC)
set(BUILD_SHARED_LIBS OFF)
endif(TOOLS_STATIC)
if(USE_ENCRYPTION)
add_definitions(-DUSE_ENCRYPTION)
endif(USE_ENCRYPTION)
if(USE_XMLWRITER)
add_definitions(-DUSE_XMLWRITER)
if(USE_LIBXML2)
add_definitions(-DUSE_LIBXML2)
find_package(LibXml2 REQUIRED)
include_directories(${LIBXML2_INCLUDE_DIR})
endif(USE_LIBXML2)
endif(USE_XMLWRITER)
if(MOBI_DEBUG)
add_definitions(-DMOBI_DEBUG)
message(STATUS "CMAKE_CXX_COMPILER_ID=${CMAKE_C_COMPILER_ID}")
if(CMAKE_C_COMPILER_ID MATCHES "Clang|GNU")
add_compile_options(-pedantic -Wall -Wextra -Werror)
endif()
endif(MOBI_DEBUG)
if(MOBI_DEBUG_ALLOC)
add_definitions(-DMOBI_DEBUG_ALLOC)
endif(MOBI_DEBUG_ALLOC)
if(USE_ZLIB)
find_package(ZLIB REQUIRED)
include_directories(${ZLIB_INCLUDE_DIR})
else()
add_definitions(-DUSE_MINIZ)
endif(USE_ZLIB)
include(CheckIncludeFile)
include(CheckFunctionExists)
check_include_file(unistd.h HAVE_UNISTD_H)
if(HAVE_UNISTD_H)
add_definitions(-DHAVE_UNISTD_H)
endif(HAVE_UNISTD_H)
check_function_exists(getopt HAVE_GETOPT)
if(HAVE_GETOPT)
add_definitions(-DHAVE_GETOPT)
endif(HAVE_GETOPT)
check_function_exists(strdup HAVE_STRDUP)
if(HAVE_STRDUP)
add_definitions(-DHAVE_STRDUP)
endif(HAVE_STRDUP)
check_include_file(sys/resource.h HAVE_SYS_RESOURCE_H)
if(HAVE_SYS_RESOURCE_H)
add_definitions(-DHAVE_SYS_RESOURCE_H)
endif(HAVE_SYS_RESOURCE_H)
include(CheckCSourceCompiles)
foreach(keyword "inline" "__inline__" "__inline")
check_c_source_compiles("${keyword} void func(); void func() { } int main() { func(); return 0; }" HAVE_INLINE)
if(HAVE_INLINE)
add_definitions(-DMOBI_INLINE=${keyword})
break()
endif(HAVE_INLINE)
endforeach(keyword)
check_c_source_compiles("void func() { } __attribute__((noreturn)); int main() { func(); return 0; }" HAVE_ATTRIBUTE_NORETURN)
if(HAVE_ATTRIBUTE_NORETURN)
add_definitions(-DHAVE_ATTRIBUTE_NORETURN)
endif(HAVE_ATTRIBUTE_NORETURN)
add_subdirectory(src)
# add_subdirectory(tools)

165
app/src/main/cpp/libmobi/COPYING vendored Normal file
View file

@ -0,0 +1,165 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

372
app/src/main/cpp/libmobi/ChangeLog vendored Normal file
View file

@ -0,0 +1,372 @@
2024-10-29: Update github actions
2024-10-29: Fix CMake build, closes #49
2024-07-04: Minor rewording in man page
2024-06-17: Fix typo
2024-06-17: Version 0.12
2024-02-04: Fix: missing header with libxml2 >= 2.12
2024-02-04: Max index count value is too low for some dictionaries
2023-08-10: Fix CMake debug build with MSVC, fixes #46
2023-07-11: Clean up unused value
2023-07-11: Fix clang warning about missing function prototypes (-Wstrict-prototypes)
2023-02-21: Update Xcode project settings
2023-02-21: Replace deprecated functions
2023-02-21: Try to reconstruct sources even on broken indices
2023-02-05: Refactor mobi_buffer_get_varlen_internal to be compatible with other buffer functions. Update documentation with information about mobi_buffer_get_varlen_dec limitation.
2022-06-26: Fix undefined behavior with null pointer arithmetics in case of corrupt input
2022-05-28: Version 0.11
2022-05-27: Fix potential null pointer dereference on corrupt input when inflections CNCX record is not initialized
2022-05-23: Fix index entries count
2022-05-23: Prevent leak of index entries on corrupt data
2022-05-23: Add checks for fragments part in case of corrupt data
2022-05-17: Fix potential integer overflow with corrupt data
2022-05-05: Fix: index entry label not being zero-terminated with corrupt input
2022-05-03: Fix boundary checking error in markup search, that could cause buffer over-read with corrupt input
2022-05-02: Fix typo in macro name
2022-04-27: Fix undefined behavior when passing null to strdup
2022-04-27: Fix wrong boundary checks in inflections parser resulting in stack buffer over-read with corrupt input
2022-04-26: Fix text formatting
2022-04-26: Fix array boundary check when parsing inflections which could result in buffer over-read with corrupt input
2022-04-23: Fix formatting
2022-04-23: Fix checking boundary of deobfuscation key which could cause buffer over-read with corrupt data
2022-04-23: Fix issue with corrupt data with empty lookup string which could lead to read beyond buffer
2022-04-23: Fix faulty checks for array boundary which caused buffer over-read with corrupt input
2022-04-23: Fix issue with corrupt files with tagvalues_count = 0 that caused null pointer dereference
2022-04-23: Fix issues when mobi_buffer_getpointer returns null. With corrupt data this could lead to out-of-bounds read
2022-04-13: Add packaging status [skip ci]
2022-04-10: Make random generation return proper error codes
2022-04-10: Rewrite randombytes for libmobi
2022-04-07: Add libsodium randombytes.c
2022-04-10: Fix "fallthrough" spelling
2022-04-10: Make declaration match definition
2022-04-10: Fix different sign comparison warning
2022-04-10: Update Xcode project
2022-04-10: Don't run tests if bash is missing
2022-04-10: Looking for libxml2, first try pkg-config
2022-04-04: Update MSVC project
2022-04-02: Add support for GNU/kFreeBSD and GNU/Hurd
2022-04-02: Check for inline, noreturn support in CMake
2022-03-27: Fix format truncation warning
2022-03-21: Version 0.10
2022-03-21: Update Xcode project [skip ci]
2022-03-21: Add functions for retrieving orthographic index entries
2022-02-27: Add basic CMake support
2022-02-26: GHA: fetch tags with checkout
2022-02-26: Minor refactoring of file path manipulation function
2022-02-26: Fix memory handling issues
2022-02-26: Add coverity scan workflow
2022-02-25: Remove obsolete changelog
2022-02-25: Fix md5sum output on Windows
2022-02-25: Fix inconsistent separators in path on Windows builds
2022-02-25: GHA: fix log paths
2022-02-25: GHA: fix workflow syntax
2022-02-25: GHA: upload test logs on failure
2022-02-24: Fix printf format specifier
2022-02-24: Fix sample path in Makefile
2022-02-24: Missing autotools in mingw workflow
2022-02-24: Windows doesn't accept asterisk in file names
2022-02-24: Update workflow, add badge
2022-02-24: Add mingw workflow
2022-02-24: Fix tests in out-of-tree build
2022-02-24: Update man pages
2022-02-24: Replace non-portable strptime
2022-02-24: Make sure both validity period dates are set
2022-02-21: Fix strptime not found on linux build
2022-02-21: Add build github action
2022-02-21: Update README
2022-02-21: Minor code cleanups
2022-02-21: Unify boolean and static usage in tools
2022-02-21: mobimeta: fix null pointer dereference when parsing malformed option
2022-02-18: Add hybrid spit option to mobitool
2022-02-18: Update documentation
2022-02-18: Test both encrypted hybrid parts
2022-02-18: Fix: fast decryption routine fails for non-huffman compression
2022-02-18: Fix mobitool serial decryption
2022-02-18: Add DRM tests
2022-02-17: Fix build with encryption disabled
2022-02-17: Update tests samples
2022-02-16: Add -h option to tools, update man pages
2022-02-16: Update Xcode settings
2022-02-16: Restructure, cleanup encryption related code, add mobidrm tool
2021-11-19: Improve getopt loop, fix config.h to be accessible from all tools
2021-11-10: Update xcode project
2021-11-10: Add functions to split hybrid files
2021-11-10: Avoid modifying existing records, as caller may keep reference to them
2021-11-05: Fix: tests fail if pid contains asterisk
2021-11-05: Fix: decryption may fail for some records with standard compression
2021-11-05: Replace test samples with self-generated smaller ones
2021-11-05: Skip test in case of missing checksums
2021-10-20: Version 0.9
2021-10-24: Fix out-of-tree build
2021-10-22: Fix mingw build, code formatting
2021-10-14: Fix gcc format truncation warning
2021-10-14: Include autogen.sh in distribution bundle
2021-10-14: Create codeql-analysis.yml
2021-10-14: Fix autoconf 2.70 warnings, clean up
2021-10-14: Build fails with autoconf 2.70
2021-10-11: Version 0.8
2021-10-11: Update Xcode project
2021-10-11: Fix warnings about changed signedness
2021-09-18: Fix potential out-of-buffer read while parsing corrupt file, closes #38
2021-09-18: Fix potential out-of-buffer read while parsing corrupt file, closes #35, #36
2021-09-09: Version 0.7
2021-09-09: fix oob write bug inside libmobi
2021-06-07: Add reference to brew formula
2020-09-02: Fix null pointer dereference in case of broken fragment
2020-08-01: Update changelog
2020-08-01: Version 0.6
2020-07-31: Fix typo
2020-07-31: Add Readme to dist package
2020-07-31: Remove anchor on truncated link
2020-07-31: Fix missing option in man page
2020-07-30: Include test samples in dist package
2020-07-25: Fix gcc 7+ warnings about implicit fall through and format truncation
2020-07-24: Unique names for internal functions to avoid confilicts with static linking
2020-06-24: Close file in error branch
2020-06-24: Fix static compilation with miniz on gcc
2020-06-24: Minor documentation fixes
2020-06-23: Version 0.5
2020-06-23: mobitool: add dump cover option
2020-06-23: Minor documentation improvement
2020-06-23: Fix potential buffer over-read
2019-03-18: Fix: try also "name" attribute when searching for link anchor tags, closes #24
2019-02-22: Add mobi_is_replica function
2019-02-22: Fix potential read beyond buffer
2019-02-22: Travis migration
2018-08-07: Fix: missing items in recreated ncx file
2018-06-20: Fix: printf format warning on some gcc versions
2018-06-20: Fix: make dist broken by nonexistent header files
2018-06-20: VERSION 0.4
2018-06-20: Fix: buffer overflow (CVE-2018-11726)
2018-06-20: Fix: buffer overflow (CVE-2018-11724)
2018-06-20: Fix: read beyond buffer (CVE-2018-11725)
2018-06-20: Fix: buffer overflow (mobitool), closes #18
2018-06-20: Fix: read beyond buffer with corrupted KF8 Boundary record, closes #19
2018-06-20: Fix: read beyond buffer, closes #16, #17
2018-06-20: Updated xcode project files
2018-04-03: Fix: ncx part was not scanned for links, fixes #12
2018-04-02: Fix regression, potential use after free
2018-04-02: Skip broken resources, fixes #10
2018-03-05: Allow processing zero length text records, fixes #9
2017-12-25: Skip broken first resource offset instead of dying
2017-12-18: Skip broken links reconstruction instead of dying
2017-11-27: Disable travis OS X builds, as they usually time out
2017-11-16: Fix: increase max number of dictionary entries per record
2017-11-14: Fix for some encrypted documents with palmdoc encoding
2017-11-06: Fix: potential null pointer dereference
2017-10-16: Manpage cleanup
2017-09-27: Update README
2017-09-26: Increase maximum length of attribute name and value, closes #5
2017-02-26: Remove obsolete files from VS build (closes #3) [ci skip]
2016-11-05: Mobitool: use epub extension if extracted source resource is epub
2016-06-10: Update docs
2016-06-10: Update test files
2016-06-10: Fix: out of bounds read in corrupt font resource
2016-06-10: Prevent memory leak in case of corrupt font resources
2016-06-10: Calculate deobfuscation buffer limit from key length
2016-06-10: Fix: USE_LIBXML2 macro was not included from config.h
2016-06-10: Fix: USE_LIBXML2 macro was not included from config.h
2016-06-09: Fix: memory leak in tools
2016-06-09: Fix: potential out of bounds read
2016-06-09: Fix: memory leak in internal xmlwriter
2016-06-01: Update README
2016-05-19: Feature: verify decryption key type
2016-05-19: Cleanup converting little endian buffer to 32-bit integer
2016-05-19: Feature: check drm expiration dates
2016-05-18: Fix: memory leaks in encryption
2016-05-18: Fix concurrent autotools builds
2016-05-18: use relative path, as $(top_srcdir) fails to be substituted (?)
2016-05-18: update vcxproj
2016-05-18: Include headers in automake sources
2016-05-18: Fix: automake out-of-tree miniz build
2016-05-18: Fix: wrongly detected fdst record broke some ancient documents
2016-05-18: Fix: improve index header parsing, some old dictionaries might not load
2016-05-18: Fix: convert encoding of opf strings from cp1252 indices
2016-05-18: Quiet warnings about unused values of wiped variables
2016-05-18: Fix: potential memory leak
2016-05-18: Fix: wrongly decoded "&copy;" entity
2016-05-16: Fix: huffdic decompression fails in case of huge documents
2016-05-14: Simplify buffer_init_null() function
2016-05-14: Use ARRAYSIZE macro
2016-05-14: Feature: calculate pid for decryption from device serial number
2016-04-29: Use endian-independent byte swapping
2016-04-29: Exclude unused miniz functions from binary
2016-04-29: Add SHA-1 routines
2016-04-27: Fix miniz.c formatting
2016-04-27: Documentation
2016-04-20: Update changelog
2016-04-20: Fix potential null pointer dereference
2016-04-20: Remove useless check
2016-04-20: Fix text record size calculation
2016-04-20: Fix buffer checking and freeing
2016-04-19: Update docs
2016-04-19: Update ChangeLog
2016-04-19: Fix comparison between signed and unsigned integer
2016-04-19: use strdup on linux/glibc
2016-04-19: Add initial write and metadata editing support. Add mobimeta tool.
2016-04-19: Always check whether memory allocation succeeded
2016-04-18: Fix: guarantee array resize step is at least 1
2016-04-13: Workaround to read some old mobipocket files
2016-04-13: Improve pdb dates resolving
2016-04-07: Minor documentation edit
2016-04-07: Update changelog
2016-04-06: Fix format warning
2016-04-06: Update test checksums
2016-04-06: Fix: <dc:date> "event" attribute needs "opf" namespace
2016-04-06: Fix: id attributes in ncx file should be unique
2016-04-06: Store full name in MOBIMobiHeader structure
2016-04-05: Fix formatting
2016-04-05: Fix signedness warning
2016-04-04: Fix potential buffer overflow, closes #2
2016-04-04: Fix potential null pointer dereference
2016-03-23: Fix signedness warnings
2016-03-22: Fix: _mkdir needs direct.h on MinGW
2016-03-22: Fix tests on Windows
2016-03-22: Fix: palmdoc decompression may fail with zero byte in input buffer
2016-03-21: VERSION 03: internal xmlwriter, metadata handling functions, bug fixes
2016-03-21: Feature: add helper functions for metadata extraction
2016-03-21: Load also kf8 data when only kf7 version is requested
2016-03-21: Fix: wrong exth header length check could discard some valid headers
2016-03-20: Get rid of extended attributes in release archive on OS X
2016-03-19: Mobitool: add descriptive error messages based on libmobi return codes
2016-03-04: Add extra length check for CMET record extraction
2016-03-04: Always check buffer allocation result
2016-03-04: Add functions to extract conversion source and log, also add this feature to mobitool
2016-03-04: Remove some stray printfs
2016-03-03: Remove not used AC_FUNC_MALLOC/REALLOC macros that break cross-compilation
2016-03-03: Fix potential illegal memory access in miniz.c
2016-03-03: Fix potential dereference of null pointer in miniz.c
2016-03-03: Fix for Android bionic libc bug (SIZE_MAX missing in stdint.h)
2016-03-03: Fix mobitool compilation on MSVC++
2016-03-03: Add EPUB creation feature to mobitool
2016-03-02: Fix potential buffer overflow, null pointer dereference
2016-03-02: Add travis test for no-external-dependency build
2016-03-02: Fix missing strdup on linux
2016-03-02: Add internal xmlwriter (as an alternative to libxml2)
2016-03-01: Feature: decode html entities in exth header strings
2016-02-29: Fix: potential buffer overflow
2016-02-29: Fix: wrong pid calculation (regression introduced in 0.2)
2016-02-26: VERSION 0.2: increased stability, lots of bugs fixed
2016-02-26: Add Xcode project file
2016-02-26: Preliminary support for MSVC++ compiler
2016-02-26: Do not use variable length arrays
2016-02-26: Refactor mobi_reconstruct_parts() to use MOBIFragment list
2016-02-26: Fix compiler warning about sign conversion
2016-02-26: Fix compiler warning about type conversion
2016-02-26: Check the result of malloc/calloc
2016-02-26: Fix inconsistent use of const between some definitions and declarations
2016-02-24: Fix inconsistence between function declaration and definition
2016-02-24: Fix various potential crashes in case of corrupt input (afl-fuzz)
2016-02-24: Fix dead code warnings in miniz
2015-11-26: Export mobi_get_first_resource_record() function
2015-11-26: Fix: double free on corrupt cdic
2015-11-02: Update docs
2015-11-02: Feature: add helper functions to find resources by flow id
2015-11-02: Feature: export MOBI_NOTSET macro
2015-11-02: Feature: give more options to parse rawml function
2015-10-24: Restore travis.yml
2015-10-24: Fix OSX travis build
2015-10-24: Fix OSX travis build
2015-10-24: Fix multiline inline script
2015-10-24: Enable multi-OS feature
2015-10-24: Fix: unique temporary name for parallel tests
2015-10-24: Fix: decoding video resources falsely reported as failed
2015-10-24: Fix: tests, some md5sum implementations insert double spaces
2015-10-24: Fix for automake < 1.13
2015-10-23: Add simple tests framework
2015-10-23: Fix: increase max index entries per record count, as some rare samples fail
2015-10-22: Fix: incorrectly decoded video/audio resources
2015-10-22: Feature: add option to specify output path
2015-10-14: Add some internal functions to public API: mobi_get_flow_by_uid, mobi_get_resource_by_uid, mobi_get_part_by_uid, mobi_get_exthrecord_by_tag
2015-06-13: update changelog
2015-06-13: fix: various invalid memory access
2015-06-13: don't quit on invalid input, instead substitute with replacement character
2015-06-12: fix typo
2015-06-12: update changelog
2015-06-12: fix: reconstruction failed when there were gaps between fragments
2015-06-12: add EXTH tags
2015-06-12: prevent return of garbage value check return value in case of failed malloc
2015-06-12: fix invalid memory access
2015-04-12: Fix reconstruction of "kindle:embed" links without mime type (regression)
2015-04-12: Add sanity checks to link reconstruction functions, allow skipping some malformed patterns
2015-04-12: Fix infinite loop in guide build while unknown tag was found
2015-04-12: Increase max recursion level for huffman decompression
2015-03-28: update docs
2015-03-28: fix solaris studio compiler warnings
2015-03-28: fix solaris studio compiler build
2015-02-18: Fix "more than one: -compatibility_version specified" error on powerpc
2014-11-24: improve docs
2014-11-24: simplify public header
2014-11-21: changelog update [ci skip]
2014-11-21: README
2014-11-21: fix: add sanity checks
2014-11-21: Fix: add sanity checks
2014-11-21: add sanity check to huffcdic indices count
2014-11-21: fix number of leaks and other minor issues (by coverity scan)
2014-11-20: missing notification email kills coverity scan
2014-11-20: update travis.yml
2014-11-20: upgrade travis.ml with covert scan
2014-11-20: update README.md
2014-11-20: add .travis.yml
2014-11-20: update REAME.md
2014-11-20: update README.md
2014-11-20: update docs
2014-11-20: feature: add decryption support
2014-11-20: mkdir cleanup
2014-11-17: documentation
2014-11-17: strip unneeded <aid/> tags
2014-11-16: fix: potential leak
2014-11-16: fix: regression, some image tags were not reconstructed
2014-11-16: fix: improve ligatures handling
2014-11-16: override darwin linker default versioning
2014-11-15: fix: get proper LIGT entries count from index header
2014-11-15: feature: unpack records into new folder
2014-11-14: make README readable on github
2014-11-14: add README for mobitool
2014-11-14: fix: dictionaries with large inflection rules failed
2014-11-14: feature: support encoded ligatures in index entry labels
2014-11-14: readme
2014-11-14: update changelog
2014-11-13: feature: support for older inflections scheme
2014-11-13: bug: files with short tagx header won't open
2014-11-13: cleanup unneeded include
2014-11-13: use strdup on linux/glibc
2014-11-13: debugging cleanup
2014-11-13: reorganize source files
2014-11-13: use strdup on linux/glibc
2014-11-11: update changelog
2014-11-11: update changeling
2014-11-11: fix: documents with text record size > 4096 failed to load
2014-11-11: add: function to decode flat index entries
2014-11-11: debug: add functions for debugging indices
2014-11-11: cleanup
2014-11-11: fix: variable length value wrongly calculated when going backwards
2014-11-08: update documentation
2014-11-08: update changelog
2014-11-08: add support for reconstructing inflections index entries
2014-11-08: parsing of exth header failed in some cases
2014-11-08: fix: some links reconstruction in kf7 failed
2014-11-08: improve debug info
2014-11-08: failed malloc false reports
2014-11-03: fix problem with uncompressed documents
2014-11-03: fix broken locales
2014-11-03: remove obsolete includes
2014-11-03: git log > changelog
2014-11-03: improved buffer handling
2014-11-03: improved OPF for dictionaries
2014-11-03: proper rawml->orth initialization and freeing
2014-11-03: fix subject field in opf
2014-11-03: handle UTF-16 surrogates, make ORDT lookups locale independent
2014-11-01: move dict reconstruction to separate function
2014-11-01: cleanup
2014-11-01: quiet gcc warning on printf format
2014-11-01: reconstruction of orth dictionary entries
2014-09-27: use mobi_list_del_all()
2014-09-25: postpone conversion to utf8 after all source reconstructions
2014-09-24: comment
2014-09-24: comments
2014-09-12: doxygen comment
2014-09-12: data size in comment
2014-09-05: MOBIArray data type fix
2014-09-05: config.h fixes
2014-06-29: merge master
2014-04-11: initial commit

12
app/src/main/cpp/libmobi/Makefile.am vendored Normal file
View file

@ -0,0 +1,12 @@
# project Makefile.am
SUBDIRS = src tools tests
EXTRA_DIST = README.md autogen.sh
test: check
ACLOCAL_AMFLAGS = -I m4
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libmobi.pc

0
app/src/main/cpp/libmobi/NEWS vendored Normal file
View file

142
app/src/main/cpp/libmobi/README.md vendored Normal file
View file

@ -0,0 +1,142 @@
# Libmobi
C library for handling Mobipocket/Kindle (MOBI) ebook format documents.
Library comes with several [command line tools](https://github.com/bfabiszewski/libmobi/tree/public/tools) for working with mobi ebooks.
The tools source may also be used as an example on how to use the library.
## Features:
- reading and parsing:
- some older text Palmdoc formats (pdb),
- Mobipocket files (prc, mobi),
- newer MOBI files including KF8 format (azw, azw3),
- Replica Print files (azw4)
- recreating source files using indices
- reconstructing references (links and embedded) in html files
- reconstructing source structure that can be fed back to kindlegen
- reconstructing dictionary markup (orth, infl tags)
- writing back loaded documents
- metadata editing
- handling encrypted documents
- encrypting documents for use on eInk Kindles
## Todo:
- improve writing
- serialize rawml into raw records
- process RESC records
## Doxygen documentation:
- [functions](http://www.fabiszewski.net/libmobi/group__mobi__export.html),
- [structures for the raw, unparsed records metadata and data](http://www.fabiszewski.net/libmobi/group__raw__structs.html),
- [structures for the parsed records metadata and data](http://www.fabiszewski.net/libmobi/group__parsed__structs.html),
- [enums](http://www.fabiszewski.net/libmobi/group__mobi__enums.html)
## Source:
- [on github](https://github.com/bfabiszewski/libmobi/)
## Packages:
[![Packaging status](https://repology.org/badge/vertical-allrepos/libmobi.svg)](https://repology.org/project/libmobi/versions)
## Installation:
[for git] $ ./autogen.sh
$ ./configure
$ make
[optionally] $ make test
$ sudo make install
On macOS, you can install via [Homebrew](https://brew.sh/) with `brew install libmobi`.
## Alternative build systems
- The supported way of building project is by using autotools.
- Optionally project provides basic support for CMake, Xcode and MSVC++ systems. However these alternative configurations are not covering all options of autotools project. They are also not tested and not updated regularly.
## Usage
- single include file: `#include <mobi.h>`
- linker flag: `-lmobi`
- basic usage:
```c
#include <mobi.h>
/* Initialize main MOBIData structure */
/* Must be deallocated with mobi_free() when not needed */
MOBIData *m = mobi_init();
if (m == NULL) {
return ERROR;
}
/* Open file for reading */
FILE *file = fopen(fullpath, "rb");
if (file == NULL) {
mobi_free(m);
return ERROR;
}
/* Load file into MOBIData structure */
/* This structure will hold raw data/metadata from mobi document */
MOBI_RET mobi_ret = mobi_load_file(m, file);
fclose(file);
if (mobi_ret != MOBI_SUCCESS) {
mobi_free(m);
return ERROR;
}
/* Initialize MOBIRawml structure */
/* Must be deallocated with mobi_free_rawml() when not needed */
/* In the next step this structure will be filled with parsed data */
MOBIRawml *rawml = mobi_init_rawml(m);
if (rawml == NULL) {
mobi_free(m);
return ERROR;
}
/* Raw data from MOBIData will be converted to html, css, fonts, media resources */
/* Parsed data will be available in MOBIRawml structure */
mobi_ret = mobi_parse_rawml(rawml, m);
if (mobi_ret != MOBI_SUCCESS) {
mobi_free(m);
mobi_free_rawml(rawml);
return ERROR;
}
/* Do something useful here */
/* ... */
/* For examples how to access data in MOBIRawml structure see mobitool.c */
/* Free MOBIRawml structure */
mobi_free_rawml(rawml);
/* Free MOBIData structure */
mobi_free(m);
return SUCCESS;
```
- for examples of usage, see [tools](https://github.com/bfabiszewski/libmobi/tree/public/tools)
## Requirements
- compiler supporting C99
- zlib (optional, configure --with-zlib=no to use included miniz.c instead)
- libxml2 (optional, configure --with-libxml2=no to use internal xmlwriter)
- tested with gcc (>=4.2.4), clang (llvm >=3.4), sun c (>=5.13), MSVC++ (2015)
- builds on Linux, MacOS, Windows (MSVC++, MinGW), Android, Solaris
- tested architectures: x86, x86-64, arm, ppc
- works cross-compiled on Kindle :)
## Tests
- [![Github Action status](https://github.com/bfabiszewski/libmobi/actions/workflows/build.yml/badge.svg)](https://github.com/bfabiszewski/libmobi/actions)
- [![Travis status](https://travis-ci.com/bfabiszewski/libmobi.svg?branch=public)](https://travis-ci.com/bfabiszewski/libmobi)
- [![Coverity status](https://scan.coverity.com/projects/3521/badge.svg)](https://scan.coverity.com/projects/3521)
## Projects using libmobi
- [KyBook 2 Reader](http://kybook-reader.com)
- [@Voice Aloud Reader](http://www.hyperionics.com/atVoice/)
- [QLMobi quicklook plugin](https://github.com/bfabiszewski/QLMobi/tree/master/QLMobi)
- [Librera Reader](http://librera.mobi)
- ... (let me know to include your project)
## License:
- LGPL, either version 3, or any later
## Credits:
- The huffman decompression and KF8 parsing algorithms were learned by studying python source code of [KindleUnpack](https://github.com/kevinhendricks/KindleUnpack).
- Thanks to all contributors of Mobileread [MOBI wiki](http://wiki.mobileread.com/wiki/MOBI)

3
app/src/main/cpp/libmobi/autogen.sh vendored Normal file
View file

@ -0,0 +1,3 @@
#!/bin/sh
mkdir -p m4 && \
autoreconf --force --install -I m4

419
app/src/main/cpp/libmobi/configure.ac vendored Normal file
View file

@ -0,0 +1,419 @@
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.62])
AC_INIT([libmobi], [0.12])
AC_CONFIG_SRCDIR([src/buffer.c])
# Enable automake
AM_INIT_AUTOMAKE([1.11 -Wall foreign subdir-objects])
# all defined C macros (HAVE_*) will be saved to this file
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4])
# Checks for programs.
AC_PROG_CC
m4_version_prereq([2.70], [], [AC_PROG_CC_C99])
AM_PROG_CC_C_O
AC_PROG_INSTALL
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
# Init libtool
m4_ifdef([LT_INIT], [LT_INIT], [AC_PROG_LIBTOOL])
# Checks for libraries.
# Checks for header files.
AC_HEADER_STDBOOL
AC_CHECK_HEADERS([stdlib.h string.h utime.h unistd.h sys/resource.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_INT32_T
AC_TYPE_INT64_T
AC_TYPE_INT8_T
AC_TYPE_SIZE_T
AC_TYPE_UINT16_T
AC_TYPE_UINT32_T
AC_TYPE_UINT64_T
AC_TYPE_UINT8_T
# Checks for library functions.
AC_FUNC_MKTIME
AC_CHECK_FUNCS([memmove memset mkdir strdup strpbrk strrchr strstr strtoul utime])
# check for getopt() function
AC_MSG_CHECKING([for getopt])
saved_CFLAGS="$CFLAGS"
CFLAGS="-Werror"
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
[[#if HAVE_UNISTD_H
# include <unistd.h>
#endif]],
[[return getopt(0, NULL, NULL);]])],
[have_getopt=yes
AC_DEFINE([HAVE_GETOPT], [1], [Define whether getopt() function is available])],
[have_getopt=no])
CFLAGS="$saved_CFLAGS"
AC_MSG_RESULT([$have_getopt])
AM_CONDITIONAL([USE_INTERNAL_GETOPT], [test x$have_getopt = xno])
# Check for oracle solaris studio c compiler
AC_CHECK_DECL([__SUNPRO_C], [SUNCC=yes], [SUNCC=no])
# Get rid of extended attributes in release archive on macOS
case "$host" in
*-*-darwin*)
am__tar="COPY_EXTENDED_ATTRIBUTES_DISABLE=1 COPYFILE_DISABLE=1 ${am__tar}"
esac
# Check for -fvisibility=hidden to determine if we can do GNU-style
# visibility attributes for symbol export control
AC_MSG_CHECKING([for visibility hidden compiler flag])
VISIBILITY_HIDDEN=
if test x$SUNCC = xyes; then
# check if we can use -xldscope=hidden
saved_CFLAGS="$CFLAGS"
CFLAGS="-xldscope=hidden"
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([[]], [[]])],
[enable_fvisibility_hidden=yes],
[enable_fvisibility_hidden=no])
CFLAGS="$saved_CFLAGS"
AS_IF([test x$enable_fvisibility_hidden = xyes], [VISIBILITY_HIDDEN="-xldscope=hidden"])
else
case "$host" in
*-*-mingw*)
# on mingw32 we do -fvisibility=hidden and __declspec(dllexport)
VISIBILITY_HIDDEN="-fvisibility=hidden"
;;
*)
# on other compilers, check if we can do -fvisibility=hidden
saved_CFLAGS="$CFLAGS"
CFLAGS="-fvisibility=hidden -Werror"
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([[]], [[]])],
[enable_fvisibility_hidden=yes],
[enable_fvisibility_hidden=no])
CFLAGS="$saved_CFLAGS"
AS_IF([test x$enable_fvisibility_hidden = xyes], [VISIBILITY_HIDDEN="-fvisibility=hidden"])
;;
esac
fi
AC_MSG_RESULT([$VISIBILITY_HIDDEN])
AC_SUBST([VISIBILITY_HIDDEN])
# MinGW seems to need this
case "$host" in
*-*-mingw*)
NO_UNDEFINED="-no-undefined"
AVOID_VERSION="-avoid-version"
ISO99_SOURCE="-D_ISOC99_SOURCE=1"
WIN32=yes
;;
*)
NO_UNDEFINED=
AVOID_VERSION=
ISO99_SOURCE=
WIN32=no
;;
esac
AC_SUBST([NO_UNDEFINED])
AC_SUBST([AVOID_VERSION])
AC_SUBST([ISO99_SOURCE])
AC_SUBST([WIN32])
# Override default versioning of Darwin linker
case "$host" in
*-*-darwin*)
case "$host" in
# exclude ppc as it breaks linker
ppc-* | powerpc-*)
DARWIN_LDFLAGS=
;;
*)
MAJOR=`echo "${PACKAGE_VERSION}" | cut -d . -f 1`
DARWIN_LDFLAGS="-Wl,-compatibility_version,${MAJOR} -Wl,-current_version,${PACKAGE_VERSION}"
;;
esac
;;
*)
DARWIN_LDFLAGS=
;;
esac
AC_SUBST([DARWIN_LDFLAGS])
# Check for --allow-multiple-definition support in linker
AC_MSG_CHECKING([whether linker supports --allow-multiple-definition flag])
MOBI_ALLOW_MULTIPLE=
saved_CFLAGS="$CFLAGS"
CFLAGS="-Wl,--allow-multiple-definition -Werror"
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([[]], [[]])],
[def_allow_multiple=yes],
[def_allow_multiple=no])
CFLAGS="$saved_CFLAGS"
AS_IF([test x$def_allow_multiple = xyes], [MOBI_ALLOW_MULTIPLE="-Wl,--allow-multiple-definition"])
AC_MSG_RESULT([$def_allow_multiple])
AC_SUBST([MOBI_ALLOW_MULTIPLE])
# Check for non-broken inline under various spellings
AC_MSG_CHECKING([for inline keyword])
def_inline=""
for inline_key in inline __inline__ __inline
do
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
[[]],
[[} $inline_key int foo() { return 0; } int bar() { return foo();]])],
[def_inline=$inline_key; break])
done
AC_MSG_RESULT([$def_inline])
AC_DEFINE_UNQUOTED([MOBI_INLINE], [$def_inline], [How to obtain function inlining.])
# Check for noreturn attribute support
AC_MSG_CHECKING([whether compiler supports noreturn attribute])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM([[]], [[void foo( void ) __attribute__((noreturn));]])],
[AC_MSG_RESULT([yes])
AC_DEFINE([HAVE_ATTRIBUTE_NORETURN], [1], [Define to 1 if compiler supports __attribute__((noreturn))])],
[AC_MSG_RESULT([no])]
)
# Check --enable-xmlwriter
XMLWRITER_OPT=""
AC_MSG_CHECKING([whether enable xmlwriter (for opf support)])
AC_ARG_ENABLE(
[xmlwriter],
[AS_HELP_STRING([--enable-xmlwriter], [enable xmlwriter (for opf support) @<:@default=yes@:>@])],
[case "$enableval" in
yes) xmlwriter=yes ;;
no) xmlwriter=no ;;
*) AC_MSG_ERROR([bad value $enableval for --enable-xmlwriter]) ;;
esac],
[xmlwriter=yes])
AC_MSG_RESULT([$xmlwriter])
AM_CONDITIONAL([USE_XMLWRITER], [test x$xmlwriter = xyes])
if test x$xmlwriter = xyes; then
AC_DEFINE([USE_XMLWRITER], [1], [Define whether enable xmlwriter (for opf support)])
# test for --with-libxml2
AC_MSG_CHECKING([whether compile with libxml2])
AC_ARG_WITH(
[libxml2],
[AS_HELP_STRING([--with-libxml2], [Use libxml2 instead of internal xmlwriter @<:@default=yes@:>@])],
[if test "x$withval" = xyes; then use_libxml2=yes; else use_libxml2=no; fi],
[use_libxml2=yes])
AC_MSG_RESULT([$use_libxml2])
if test x$use_libxml2 = xyes; then
AC_ARG_VAR([XML2_CONFIG], [path to xml2-config utility])
AC_CHECK_PROGS([XML2_CONFIG], [xml2-config])
AC_CHECK_PROGS([PKG_CONFIG], [pkg-config])
AC_MSG_CHECKING([for libxml2 path supplier])
if test -n "$PKG_CONFIG" && $PKG_CONFIG --exists libxml-2.0; then
LIBXML2_CFLAGS="`$PKG_CONFIG --cflags libxml-2.0`"
LIBXML2_LDFLAGS="`$PKG_CONFIG --libs libxml-2.0`"
AC_MSG_RESULT([pkg-config])
elif test -n "$XML2_CONFIG"; then
LIBXML2_CFLAGS="`$XML2_CONFIG --cflags`"
LIBXML2_LDFLAGS="`$XML2_CONFIG --libs`"
AC_MSG_RESULT([xml2-config])
else
LIBXML2_CFLAGS=-I/usr/include/libxml2
LIBXML2_LDFLAGS=-lxml2
AC_MSG_RESULT([generic])
fi
saved_CPPFLAGS=$CPPFLAGS
CPPFLAGS="$CPPFLAGS $LIBXML2_CFLAGS"
AC_CHECK_HEADER(
[libxml/xmlwriter.h],
[AC_DEFINE([USE_LIBXML2], [1], [Define if you want to use libxml2 library])],
[AC_MSG_ERROR([couldn't find libxml2])])
CPPFLAGS=$saved_CPPFLAGS
else
LIBXML2_LDFLAGS=
LIBXML2_CFLAGS=
fi
AC_SUBST([LIBXML2_LDFLAGS])
AC_SUBST([LIBXML2_CFLAGS])
XMLWRITER_OPT="yes"
fi
AM_CONDITIONAL([USE_LIBXML2], [test x$use_libxml2 = xyes])
AC_SUBST([XMLWRITER_OPT])
# Check --enable-encryption
ENCRYPTION_OPT=""
AC_MSG_CHECKING([whether enable encryption])
AC_ARG_ENABLE(
[encryption],
[AS_HELP_STRING([--enable-encryption], [enable encryption @<:@default=yes@:>@])],
[case "$enableval" in
yes) encryption=yes ;;
no) encryption=no ;;
*) AC_MSG_ERROR([bad value $enableval for --enable-encryption]) ;;
esac],
[encryption=yes])
AC_MSG_RESULT([$encryption])
AM_CONDITIONAL([USE_ENCRYPTION], [test x$encryption = xyes])
if test x$encryption = xyes; then
AC_DEFINE([USE_ENCRYPTION], [1], [Enable encryption])
ENCRYPTION_OPT="yes"
AC_CHECK_HEADERS([sys/random.h])
AC_MSG_CHECKING([for getrandom with a standard API])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[[#include <stdlib.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_SYS_RANDOM_H
# include <sys/random.h>
#endif]],
[[unsigned char buf;
if (&getrandom != NULL) {
(void) getrandom((void *) &buf, 1U, 0U);
}]])],
[AC_MSG_RESULT([yes])
AC_CHECK_FUNCS([getrandom])],
[AC_MSG_RESULT([no])])
fi
AC_SUBST([ENCRYPTION_OPT])
# Check --enable-debug
AC_MSG_CHECKING([whether enable debugging])
AC_ARG_ENABLE(
[debug],
[AS_HELP_STRING([--enable-debug], [enable debugging @<:@default=no@:>@])],
[case "$enableval" in
yes) debug=yes ;;
no) debug=no ;;
*) AC_MSG_ERROR([bad value $enableval for --enable-debug]) ;;
esac],
[debug=no])
AC_MSG_RESULT([$debug])
DEBUG_CFLAGS=
if test x$debug = xyes; then
AC_DEFINE([MOBI_DEBUG], [1], [Enable debugging])
if test x$SUNCC = xyes; then
DEBUG_CFLAGS="-v -errwarn"
else
DEBUG_CFLAGS="-pedantic -Wall -Wextra -Werror"
fi
fi
AC_SUBST([DEBUG_CFLAGS])
# Check --enable-debug-alloc
AC_MSG_CHECKING([whether enable alloc debugging])
AC_ARG_ENABLE(
[debug_alloc],
[AS_HELP_STRING([--enable-debug-alloc], [enable memory allocation debugging @<:@default=no@:>@])],
[case "$enableval" in
yes) debug_alloc=yes ;;
no) debug_alloc=no ;;
*) AC_MSG_ERROR([bad value $enableval for --enable-debug-alloc]) ;;
esac],
[debug_alloc=no])
AC_MSG_RESULT([$debug_alloc])
if test x$debug_alloc = xyes; then
AC_DEFINE([MOBI_DEBUG_ALLOC], [1], [Enable alloc debugging])
fi
# Check --enable-tools-static
AC_MSG_CHECKING([whether link tools against static libmobi])
AC_ARG_ENABLE(
[tools_static],
[AS_HELP_STRING([--enable-tools-static], [link tools against static libmobi @<:@default=no@:>@])],
[case "$enableval" in
yes) tools_static=yes ;;
no) tools_static=no ;;
*) AC_MSG_ERROR([bad value $enableval for --enable-tools-static]) ;;
esac],
[tools_static=no])
AC_MSG_RESULT([$tools_static])
TOOLS_STATIC=
if test x$tools_static = xyes; then
TOOLS_STATIC="-static"
fi
AC_SUBST([TOOLS_STATIC])
# test for --with-zlib
AC_MSG_CHECKING([whether compile with zlib])
AC_ARG_WITH(
[zlib],
[AS_HELP_STRING([--with-zlib], [Use zlib instead of included miniz @<:@default=yes@:>@])],
[if test "x$withval" = xyes; then use_zlib=yes; else use_zlib=no; fi],
[use_zlib=yes])
AC_MSG_RESULT([$use_zlib])
AM_CONDITIONAL([USE_ZLIB], [test x$use_zlib = xyes])
AM_CONDITIONAL([USE_MINIZ], [test x$use_zlib = xno])
AM_CONDITIONAL([USE_STATIC], [test x$tools_static = xyes])
if test x$use_zlib = xyes; then
AC_CHECK_HEADER(
[zlib.h],
[AC_DEFINE([USE_ZLIB], [1], [Define if you want to use system zlib library])
LIBZ_LDFLAGS=-lz
MINIZ_CFLAGS=],
[AC_MSG_ERROR([couldn't find zlib header])])
else
AC_DEFINE([USE_MINIZ], [1], [Define if you want to use included miniz library])
MINIZ_CFLAGS="-D_POSIX_C_SOURCE=200112L"
LIBZ_LDFLAGS=
fi
AC_SUBST([LIBZ_LDFLAGS])
AC_SUBST([MINIZ_CFLAGS])
# Check for md5 or md5sum program, needed for tests
AC_ARG_VAR([MD5PROG], [md5 hashing program executable])
AS_IF([test -z "$MD5PROG"], [AC_CHECK_PROG([MD5PROG], [md5sum], [md5sum -t])], [])
AS_IF([test -z "$MD5PROG"], [AC_CHECK_PROG([MD5PROG], [md5], [md5 -r])], [])
AS_IF([test -z "$MD5PROG"], [AC_MSG_WARN([md5 hashing program not found, some tests will be skipped])], [])
AC_PATH_PROG([BASH_PATH], [bash])
AS_IF(
[test -z "$BASH_PATH"],
[AC_MSG_WARN([bash not found, tests will be skipped])
RUN_TESTS="no"],
[RUN_TESTS="yes"
AC_SUBST([BASH_PATH])])
AC_SUBST([RUN_TESTS])
if test x$RUN_TESTS = xyes; then
# List test files
cur_dir=`pwd`
cd "$srcdir"/tests
for sample_path in samples/*.mobi
do
TESTLIST="${TESTLIST} ${sample_path} \\
"
done
for sample_path in samples/*.fail
do
TESTLIST="${TESTLIST} ${sample_path} \\
"
FAILLIST="${FAILLIST} ${sample_path} \\
"
done
cd $cur_dir
fi
AC_SUBST([TESTLIST])
AC_SUBST([FAILLIST])
AC_CONFIG_FILES([Makefile])
AC_CONFIG_FILES([libmobi.pc])
AC_CONFIG_FILES([src/Makefile])
AC_CONFIG_FILES([tools/Makefile])
AC_CONFIG_FILES([tools/mobitool.1])
AC_CONFIG_FILES([tools/mobimeta.1])
AC_CONFIG_FILES([tools/mobidrm.1])
AC_CONFIG_FILES([tests/Makefile])
AC_CONFIG_FILES([tests/test.sh], [chmod +x tests/test.sh])
AC_OUTPUT

13
app/src/main/cpp/libmobi/libmobi.pc.in vendored Normal file
View file

@ -0,0 +1,13 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: libmobi
Description: MOBI ebook format handling library
URL: http://www.fabiszewski.net/libmobi
Version: @VERSION@
Requires:
Libs: -L${libdir} -lmobi
Libs.private: @LIBZ_LDFLAGS@ @LIBXML2_LDFLAGS@
Cflags: -I${includedir}

View file

@ -0,0 +1,879 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
1502448F1CD3A18F0075F4EC /* sha1.c in Sources */ = {isa = PBXBuildFile; fileRef = 1502448D1CD3A18F0075F4EC /* sha1.c */; };
150244901CD3A18F0075F4EC /* sha1.h in Headers */ = {isa = PBXBuildFile; fileRef = 1502448E1CD3A18F0075F4EC /* sha1.h */; };
1504FD851CBE880B002AA042 /* meta.c in Sources */ = {isa = PBXBuildFile; fileRef = 1504FD831CBE880B002AA042 /* meta.c */; };
1504FD861CBE880B002AA042 /* meta.h in Headers */ = {isa = PBXBuildFile; fileRef = 1504FD841CBE880B002AA042 /* meta.h */; };
150A318D18E19BF9001A7AD7 /* write.c in Sources */ = {isa = PBXBuildFile; fileRef = 150A318C18E19BF9001A7AD7 /* write.c */; };
151A46661909312900FAF3F4 /* miniz.c in Sources */ = {isa = PBXBuildFile; fileRef = 151A46651909312900FAF3F4 /* miniz.c */; settings = {COMPILER_FLAGS = "-w"; }; };
152FD1E6270509A900AF276A /* randombytes.h in Headers */ = {isa = PBXBuildFile; fileRef = 152FD1E4270509A900AF276A /* randombytes.h */; };
152FD1E7270509A900AF276A /* randombytes.c in Sources */ = {isa = PBXBuildFile; fileRef = 152FD1E5270509A900AF276A /* randombytes.c */; };
153D91DB18E9630000E807B6 /* memory.c in Sources */ = {isa = PBXBuildFile; fileRef = 153D91DA18E9630000E807B6 /* memory.c */; };
1543065B1CB78A45006AB398 /* mobimeta.c in Sources */ = {isa = PBXBuildFile; fileRef = 151185A31CB6C28500201C8A /* mobimeta.c */; };
1543065E1CB78BA8006AB398 /* libmobi.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 150039BB18E06BC100D33077 /* libmobi.dylib */; };
154C2D401CC64A170041DD0E /* common.c in Sources */ = {isa = PBXBuildFile; fileRef = 154C2D3E1CC64A170041DD0E /* common.c */; };
154C2D411CC64A170041DD0E /* common.c in Sources */ = {isa = PBXBuildFile; fileRef = 154C2D3E1CC64A170041DD0E /* common.c */; };
1550ADC318E427D7006F9257 /* buffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 1550ADC218E427D7006F9257 /* buffer.c */; };
1550ADCE18E4B925006F9257 /* compression.c in Sources */ = {isa = PBXBuildFile; fileRef = 1550ADCD18E4B925006F9257 /* compression.c */; };
1553330118E359AE00334E23 /* read.c in Sources */ = {isa = PBXBuildFile; fileRef = 1553330018E359AE00334E23 /* read.c */; };
1553332118E37FC400334E23 /* libmobi.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 150039BB18E06BC100D33077 /* libmobi.dylib */; };
15603889192D2E1A002EDB1A /* opf.c in Sources */ = {isa = PBXBuildFile; fileRef = 15603888192D2E1A002EDB1A /* opf.c */; };
15615F0818F58C85004EBB6E /* mobitool.c in Sources */ = {isa = PBXBuildFile; fileRef = 15615F0718F58C85004EBB6E /* mobitool.c */; };
1563314718EC36A200D4B858 /* debug.c in Sources */ = {isa = PBXBuildFile; fileRef = 1563314618EC36A200D4B858 /* debug.c */; };
156AA65D1C81A3860085335A /* xmlwriter.c in Sources */ = {isa = PBXBuildFile; fileRef = 156AA65B1C81A3860085335A /* xmlwriter.c */; };
156AA65E1C81A3860085335A /* xmlwriter.h in Headers */ = {isa = PBXBuildFile; fileRef = 156AA65C1C81A3860085335A /* xmlwriter.h */; };
157BEA732747BEDA004984B8 /* libmobi.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 150039BB18E06BC100D33077 /* libmobi.dylib */; };
157BEA852747BF13004984B8 /* mobidrm.c in Sources */ = {isa = PBXBuildFile; fileRef = 157BEA6B2747B4EC004984B8 /* mobidrm.c */; };
157BEA8A2747BF26004984B8 /* common.c in Sources */ = {isa = PBXBuildFile; fileRef = 154C2D3E1CC64A170041DD0E /* common.c */; };
157DF7AD191A514D00191502 /* index.c in Sources */ = {isa = PBXBuildFile; fileRef = 157DF7AC191A514D00191502 /* index.c */; };
15AB2CB419572C2800EB7F74 /* parse_rawml.c in Sources */ = {isa = PBXBuildFile; fileRef = 15AB2CB319572C2800EB7F74 /* parse_rawml.c */; };
15EA81DF1A14D5AC00138554 /* structure.c in Sources */ = {isa = PBXBuildFile; fileRef = 15EA81DE1A14D5AC00138554 /* structure.c */; };
15F1A1D118F4192D009CFE05 /* util.c in Sources */ = {isa = PBXBuildFile; fileRef = 15F1A1D018F4192D009CFE05 /* util.c */; };
15FB2BB21A1A32970052D5C5 /* encryption.c in Sources */ = {isa = PBXBuildFile; fileRef = 15FB2BB01A1A32970052D5C5 /* encryption.c */; };
15FB2BB31A1A32970052D5C5 /* encryption.h in Headers */ = {isa = PBXBuildFile; fileRef = 15FB2BB11A1A32970052D5C5 /* encryption.h */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
1543065C1CB78B78006AB398 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 150039B318E06BC100D33077 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 150039BA18E06BC100D33077;
remoteInfo = mobi;
};
1553331F18E37FB800334E23 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 150039B318E06BC100D33077 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 150039BA18E06BC100D33077;
remoteInfo = mobi;
};
157BEA6E2747BEDA004984B8 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 150039B318E06BC100D33077 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 150039BA18E06BC100D33077;
remoteInfo = mobi;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
154306521CB78A3D006AB398 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = /usr/share/man/man1/;
dstSubfolderSpec = 0;
files = (
);
runOnlyForDeploymentPostprocessing = 1;
};
1553331418E37F7000334E23 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = /usr/share/man/man1;
dstSubfolderSpec = 0;
files = (
);
runOnlyForDeploymentPostprocessing = 1;
};
157BEA742747BEDA004984B8 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = /usr/share/man/man1;
dstSubfolderSpec = 0;
files = (
);
runOnlyForDeploymentPostprocessing = 1;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
150039BB18E06BC100D33077 /* libmobi.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libmobi.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
150039C218E06C1B00D33077 /* mobi.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = mobi.h; path = src/mobi.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
1502448D1CD3A18F0075F4EC /* sha1.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sha1.c; path = src/sha1.c; sourceTree = "<group>"; };
1502448E1CD3A18F0075F4EC /* sha1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sha1.h; path = src/sha1.h; sourceTree = "<group>"; };
1504FD831CBE880B002AA042 /* meta.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = meta.c; path = src/meta.c; sourceTree = "<group>"; };
1504FD841CBE880B002AA042 /* meta.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = meta.h; path = src/meta.h; sourceTree = "<group>"; };
150A318B18E19BD8001A7AD7 /* write.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = write.h; path = src/write.h; sourceTree = "<group>"; };
150A318C18E19BF9001A7AD7 /* write.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; lineEnding = 0; name = write.c; path = src/write.c; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.c; };
151185A31CB6C28500201C8A /* mobimeta.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mobimeta.c; path = tools/mobimeta.c; sourceTree = SOURCE_ROOT; };
151A46641909302C00FAF3F4 /* miniz.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = miniz.h; path = src/miniz.h; sourceTree = "<group>"; };
151A46651909312900FAF3F4 /* miniz.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = miniz.c; path = src/miniz.c; sourceTree = "<absolute>"; };
152D509E1BD79AE400E91C09 /* test.sh.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; name = test.sh.in; path = tests/test.sh.in; sourceTree = "<group>"; };
152D50A01BD7A08300E91C09 /* Makefile.am */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; name = Makefile.am; path = tests/Makefile.am; sourceTree = "<group>"; usesTabs = 1; xcLanguageSpecificationIdentifier = xcode.lang.sh; };
152E5D1218F5DEB100B05EC9 /* configure.ac */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = configure.ac; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.csh; };
152E5D1318F5DEB100B05EC9 /* Makefile.am */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.am; sourceTree = "<group>"; usesTabs = 1; };
152E5D1418F5DEC000B05EC9 /* Makefile.am */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; name = Makefile.am; path = src/Makefile.am; sourceTree = "<group>"; usesTabs = 1; };
152E5D1518F5DECF00B05EC9 /* Makefile.am */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; name = Makefile.am; path = tools/Makefile.am; sourceTree = "<group>"; usesTabs = 1; };
152E5D1618F5E22000B05EC9 /* autogen.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = autogen.sh; sourceTree = "<group>"; };
152ED797195EFBD900ACD1AD /* ChangeLog */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ChangeLog; sourceTree = "<group>"; };
152FD1E4270509A900AF276A /* randombytes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = randombytes.h; path = src/randombytes.h; sourceTree = "<group>"; };
152FD1E5270509A900AF276A /* randombytes.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = randombytes.c; path = src/randombytes.c; sourceTree = "<group>"; };
153967601907C0AA00EDC923 /* COPYING */ = {isa = PBXFileReference; lastKnownFileType = text; path = COPYING; sourceTree = "<group>"; };
153D91DA18E9630000E807B6 /* memory.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; lineEnding = 0; name = memory.c; path = src/memory.c; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.c; };
153D91DC18E9633500E807B6 /* memory.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = memory.h; path = src/memory.h; sourceTree = "<group>"; };
1542B8041C7FA5E800C5122F /* getopt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = getopt.c; path = tools/win32/getopt.c; sourceTree = SOURCE_ROOT; };
1542B8051C7FA5E900C5122F /* getopt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = getopt.h; path = tools/win32/getopt.h; sourceTree = SOURCE_ROOT; };
154306541CB78A3D006AB398 /* mobimeta */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mobimeta; sourceTree = BUILT_PRODUCTS_DIR; };
154C2D3E1CC64A170041DD0E /* common.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = common.c; path = tools/common.c; sourceTree = SOURCE_ROOT; };
154C2D3F1CC64A170041DD0E /* common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = common.h; path = tools/common.h; sourceTree = SOURCE_ROOT; };
1550ADC218E427D7006F9257 /* buffer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = buffer.c; path = src/buffer.c; sourceTree = "<group>"; };
1550ADC418E42842006F9257 /* buffer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = buffer.h; path = src/buffer.h; sourceTree = "<group>"; };
1550ADCD18E4B925006F9257 /* compression.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; lineEnding = 0; name = compression.c; path = src/compression.c; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.c; };
1550ADCF18E4BB83006F9257 /* compression.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = compression.h; path = src/compression.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
1553330018E359AE00334E23 /* read.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; lineEnding = 0; name = read.c; path = src/read.c; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.c; };
1553330218E359B900334E23 /* read.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = read.h; path = src/read.h; sourceTree = "<group>"; };
1553331618E37F7000334E23 /* mobitool */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mobitool; sourceTree = BUILT_PRODUCTS_DIR; };
1559D790191BB06700636661 /* config.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = config.h; path = src/config.h; sourceTree = "<group>"; };
15603888192D2E1A002EDB1A /* opf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = opf.c; path = src/opf.c; sourceTree = "<group>"; };
1560388A192D2E34002EDB1A /* opf.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = opf.h; path = src/opf.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.c; };
15615F0718F58C85004EBB6E /* mobitool.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; lineEnding = 0; name = mobitool.c; path = tools/mobitool.c; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.c; };
1563314518EC367300D4B858 /* debug.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = debug.h; path = src/debug.h; sourceTree = "<group>"; };
1563314618EC36A200D4B858 /* debug.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = debug.c; path = src/debug.c; sourceTree = "<group>"; };
156AA65B1C81A3860085335A /* xmlwriter.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = xmlwriter.c; path = src/xmlwriter.c; sourceTree = "<group>"; };
156AA65C1C81A3860085335A /* xmlwriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = xmlwriter.h; path = src/xmlwriter.h; sourceTree = "<group>"; };
157BEA6B2747B4EC004984B8 /* mobidrm.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = mobidrm.c; path = tools/mobidrm.c; sourceTree = SOURCE_ROOT; };
157BEA782747BEDA004984B8 /* mobidrm */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mobidrm; sourceTree = BUILT_PRODUCTS_DIR; };
157DF7AC191A514D00191502 /* index.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = index.c; path = src/index.c; sourceTree = "<group>"; };
157DF7AE191A51A400191502 /* index.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = index.h; path = src/index.h; sourceTree = "<group>"; };
15843DFE19215D0400587C89 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = text; path = README.md; sourceTree = "<group>"; };
158F44DC191E88010000F44A /* libmobi.pc.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = libmobi.pc.in; sourceTree = "<group>"; };
15AB2CB319572C2800EB7F74 /* parse_rawml.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = parse_rawml.c; path = src/parse_rawml.c; sourceTree = "<group>"; };
15AB2CB519572C4400EB7F74 /* parse_rawml.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = parse_rawml.h; path = src/parse_rawml.h; sourceTree = "<group>"; };
15B4311D2767840300B7E6A7 /* mobidrm.1.in */ = {isa = PBXFileReference; explicitFileType = text.man; name = mobidrm.1.in; path = tools/mobidrm.1.in; sourceTree = SOURCE_ROOT; };
15D7CFD71A167A3A00F08927 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = tools/README.md; sourceTree = "<group>"; };
15E5FAD91CC58B4D00F700D1 /* mobimeta.1.in */ = {isa = PBXFileReference; explicitFileType = text.man; name = mobimeta.1.in; path = tools/mobimeta.1.in; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.man; };
15E65B5E1A1DF1DA00B7FBBD /* mobitool.1.in */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; name = mobitool.1.in; path = tools/mobitool.1.in; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.man; };
15E65B5F1A1E0FC100B7FBBD /* .travis.yml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = .travis.yml; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.simpleColoring; };
15EA81DD1A14D58500138554 /* structure.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = structure.h; path = src/structure.h; sourceTree = SOURCE_ROOT; };
15EA81DE1A14D5AC00138554 /* structure.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = structure.c; path = src/structure.c; sourceTree = "<group>"; };
15F1A1D018F4192D009CFE05 /* util.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; lineEnding = 0; name = util.c; path = src/util.c; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.c; };
15F1A1D218F4195A009CFE05 /* util.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = util.h; path = src/util.h; sourceTree = "<group>"; };
15FB2BB01A1A32970052D5C5 /* encryption.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = encryption.c; path = src/encryption.c; sourceTree = "<group>"; };
15FB2BB11A1A32970052D5C5 /* encryption.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = encryption.h; path = src/encryption.h; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
150039B818E06BC100D33077 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
154306511CB78A3D006AB398 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
1543065E1CB78BA8006AB398 /* libmobi.dylib in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
1553331318E37F7000334E23 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
1553332118E37FC400334E23 /* libmobi.dylib in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
157BEA722747BEDA004984B8 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
157BEA732747BEDA004984B8 /* libmobi.dylib in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
150039B218E06BC100D33077 = {
isa = PBXGroup;
children = (
152D509F1BD79AED00E91C09 /* tests */,
1539675F1907BC0600EDC923 /* docs */,
1550ADC218E427D7006F9257 /* buffer.c */,
1550ADC418E42842006F9257 /* buffer.h */,
1550ADCD18E4B925006F9257 /* compression.c */,
1550ADCF18E4BB83006F9257 /* compression.h */,
1559D790191BB06700636661 /* config.h */,
1563314618EC36A200D4B858 /* debug.c */,
1563314518EC367300D4B858 /* debug.h */,
15FB2BB01A1A32970052D5C5 /* encryption.c */,
15FB2BB11A1A32970052D5C5 /* encryption.h */,
157DF7AC191A514D00191502 /* index.c */,
157DF7AE191A51A400191502 /* index.h */,
153D91DA18E9630000E807B6 /* memory.c */,
153D91DC18E9633500E807B6 /* memory.h */,
1504FD831CBE880B002AA042 /* meta.c */,
1504FD841CBE880B002AA042 /* meta.h */,
151A46651909312900FAF3F4 /* miniz.c */,
151A46641909302C00FAF3F4 /* miniz.h */,
150039C218E06C1B00D33077 /* mobi.h */,
15603888192D2E1A002EDB1A /* opf.c */,
1560388A192D2E34002EDB1A /* opf.h */,
15AB2CB319572C2800EB7F74 /* parse_rawml.c */,
15AB2CB519572C4400EB7F74 /* parse_rawml.h */,
152FD1E4270509A900AF276A /* randombytes.h */,
152FD1E5270509A900AF276A /* randombytes.c */,
1553330018E359AE00334E23 /* read.c */,
1553330218E359B900334E23 /* read.h */,
1502448D1CD3A18F0075F4EC /* sha1.c */,
1502448E1CD3A18F0075F4EC /* sha1.h */,
15EA81DE1A14D5AC00138554 /* structure.c */,
15EA81DD1A14D58500138554 /* structure.h */,
15F1A1D018F4192D009CFE05 /* util.c */,
15F1A1D218F4195A009CFE05 /* util.h */,
150A318C18E19BF9001A7AD7 /* write.c */,
150A318B18E19BD8001A7AD7 /* write.h */,
156AA65B1C81A3860085335A /* xmlwriter.c */,
156AA65C1C81A3860085335A /* xmlwriter.h */,
1553331718E37F7100334E23 /* tools */,
150039BC18E06BC100D33077 /* Products */,
152E5CFE18F5DB3200B05EC9 /* autotools */,
);
sourceTree = "<group>";
};
150039BC18E06BC100D33077 /* Products */ = {
isa = PBXGroup;
children = (
150039BB18E06BC100D33077 /* libmobi.dylib */,
1553331618E37F7000334E23 /* mobitool */,
154306541CB78A3D006AB398 /* mobimeta */,
157BEA782747BEDA004984B8 /* mobidrm */,
);
name = Products;
sourceTree = "<group>";
};
152D509F1BD79AED00E91C09 /* tests */ = {
isa = PBXGroup;
children = (
152D509E1BD79AE400E91C09 /* test.sh.in */,
152D50A01BD7A08300E91C09 /* Makefile.am */,
);
name = tests;
sourceTree = "<group>";
};
152E5CFE18F5DB3200B05EC9 /* autotools */ = {
isa = PBXGroup;
children = (
152E5D1618F5E22000B05EC9 /* autogen.sh */,
152E5D1218F5DEB100B05EC9 /* configure.ac */,
158F44DC191E88010000F44A /* libmobi.pc.in */,
152E5D1518F5DECF00B05EC9 /* Makefile.am */,
152E5D1418F5DEC000B05EC9 /* Makefile.am */,
152E5D1318F5DEB100B05EC9 /* Makefile.am */,
);
name = autotools;
sourceTree = "<group>";
};
1539675F1907BC0600EDC923 /* docs */ = {
isa = PBXGroup;
children = (
152ED797195EFBD900ACD1AD /* ChangeLog */,
15843DFE19215D0400587C89 /* README.md */,
15D7CFD71A167A3A00F08927 /* README.md */,
15E65B5F1A1E0FC100B7FBBD /* .travis.yml */,
153967601907C0AA00EDC923 /* COPYING */,
15B4311D2767840300B7E6A7 /* mobidrm.1.in */,
15E65B5E1A1DF1DA00B7FBBD /* mobitool.1.in */,
15E5FAD91CC58B4D00F700D1 /* mobimeta.1.in */,
);
name = docs;
sourceTree = "<group>";
};
1553331718E37F7100334E23 /* tools */ = {
isa = PBXGroup;
children = (
151185A31CB6C28500201C8A /* mobimeta.c */,
15615F0718F58C85004EBB6E /* mobitool.c */,
1542B8041C7FA5E800C5122F /* getopt.c */,
1542B8051C7FA5E900C5122F /* getopt.h */,
154C2D3E1CC64A170041DD0E /* common.c */,
154C2D3F1CC64A170041DD0E /* common.h */,
157BEA6B2747B4EC004984B8 /* mobidrm.c */,
);
name = tools;
path = test;
sourceTree = SOURCE_ROOT;
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
150039B918E06BC100D33077 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
15FB2BB31A1A32970052D5C5 /* encryption.h in Headers */,
152FD1E6270509A900AF276A /* randombytes.h in Headers */,
150244901CD3A18F0075F4EC /* sha1.h in Headers */,
156AA65E1C81A3860085335A /* xmlwriter.h in Headers */,
1504FD861CBE880B002AA042 /* meta.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
150039BA18E06BC100D33077 /* mobi */ = {
isa = PBXNativeTarget;
buildConfigurationList = 150039BF18E06BC100D33077 /* Build configuration list for PBXNativeTarget "mobi" */;
buildPhases = (
150039B718E06BC100D33077 /* Sources */,
150039B818E06BC100D33077 /* Frameworks */,
150039B918E06BC100D33077 /* Headers */,
);
buildRules = (
);
dependencies = (
);
name = mobi;
productName = libmobi;
productReference = 150039BB18E06BC100D33077 /* libmobi.dylib */;
productType = "com.apple.product-type.library.dynamic";
};
154306531CB78A3D006AB398 /* mobimeta */ = {
isa = PBXNativeTarget;
buildConfigurationList = 1543065A1CB78A3D006AB398 /* Build configuration list for PBXNativeTarget "mobimeta" */;
buildPhases = (
154306501CB78A3D006AB398 /* Sources */,
154306511CB78A3D006AB398 /* Frameworks */,
154306521CB78A3D006AB398 /* CopyFiles */,
);
buildRules = (
);
dependencies = (
1543065D1CB78B78006AB398 /* PBXTargetDependency */,
);
name = mobimeta;
productName = write_test;
productReference = 154306541CB78A3D006AB398 /* mobimeta */;
productType = "com.apple.product-type.tool";
};
1553331518E37F7000334E23 /* mobitool */ = {
isa = PBXNativeTarget;
buildConfigurationList = 1553331C18E37F7100334E23 /* Build configuration list for PBXNativeTarget "mobitool" */;
buildPhases = (
1553331218E37F7000334E23 /* Sources */,
1553331318E37F7000334E23 /* Frameworks */,
1553331418E37F7000334E23 /* CopyFiles */,
);
buildRules = (
);
dependencies = (
1553332018E37FB800334E23 /* PBXTargetDependency */,
);
name = mobitool;
productName = test;
productReference = 1553331618E37F7000334E23 /* mobitool */;
productType = "com.apple.product-type.tool";
};
157BEA6C2747BEDA004984B8 /* mobidrm */ = {
isa = PBXNativeTarget;
buildConfigurationList = 157BEA752747BEDA004984B8 /* Build configuration list for PBXNativeTarget "mobidrm" */;
buildPhases = (
157BEA6F2747BEDA004984B8 /* Sources */,
157BEA722747BEDA004984B8 /* Frameworks */,
157BEA742747BEDA004984B8 /* CopyFiles */,
);
buildRules = (
);
dependencies = (
157BEA6D2747BEDA004984B8 /* PBXTargetDependency */,
);
name = mobidrm;
productName = test;
productReference = 157BEA782747BEDA004984B8 /* mobidrm */;
productType = "com.apple.product-type.tool";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
150039B318E06BC100D33077 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1420;
ORGANIZATIONNAME = "Bartek Fabiszewski";
TargetAttributes = {
154306531CB78A3D006AB398 = {
CreatedOnToolsVersion = 7.3;
};
};
};
buildConfigurationList = 150039B618E06BC100D33077 /* Build configuration list for PBXProject "mobi" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 150039B218E06BC100D33077;
productRefGroup = 150039BC18E06BC100D33077 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
150039BA18E06BC100D33077 /* mobi */,
1553331518E37F7000334E23 /* mobitool */,
154306531CB78A3D006AB398 /* mobimeta */,
157BEA6C2747BEDA004984B8 /* mobidrm */,
);
};
/* End PBXProject section */
/* Begin PBXSourcesBuildPhase section */
150039B718E06BC100D33077 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
1550ADCE18E4B925006F9257 /* compression.c in Sources */,
15EA81DF1A14D5AC00138554 /* structure.c in Sources */,
1563314718EC36A200D4B858 /* debug.c in Sources */,
15F1A1D118F4192D009CFE05 /* util.c in Sources */,
1502448F1CD3A18F0075F4EC /* sha1.c in Sources */,
15603889192D2E1A002EDB1A /* opf.c in Sources */,
150A318D18E19BF9001A7AD7 /* write.c in Sources */,
1550ADC318E427D7006F9257 /* buffer.c in Sources */,
1553330118E359AE00334E23 /* read.c in Sources */,
157DF7AD191A514D00191502 /* index.c in Sources */,
153D91DB18E9630000E807B6 /* memory.c in Sources */,
156AA65D1C81A3860085335A /* xmlwriter.c in Sources */,
15AB2CB419572C2800EB7F74 /* parse_rawml.c in Sources */,
152FD1E7270509A900AF276A /* randombytes.c in Sources */,
15FB2BB21A1A32970052D5C5 /* encryption.c in Sources */,
1504FD851CBE880B002AA042 /* meta.c in Sources */,
151A46661909312900FAF3F4 /* miniz.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
154306501CB78A3D006AB398 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
154C2D411CC64A170041DD0E /* common.c in Sources */,
1543065B1CB78A45006AB398 /* mobimeta.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
1553331218E37F7000334E23 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
154C2D401CC64A170041DD0E /* common.c in Sources */,
15615F0818F58C85004EBB6E /* mobitool.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
157BEA6F2747BEDA004984B8 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
157BEA8A2747BF26004984B8 /* common.c in Sources */,
157BEA852747BF13004984B8 /* mobidrm.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
1543065D1CB78B78006AB398 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 150039BA18E06BC100D33077 /* mobi */;
targetProxy = 1543065C1CB78B78006AB398 /* PBXContainerItemProxy */;
};
1553332018E37FB800334E23 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 150039BA18E06BC100D33077 /* mobi */;
targetProxy = 1553331F18E37FB800334E23 /* PBXContainerItemProxy */;
};
157BEA6D2747BEDA004984B8 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 150039BA18E06BC100D33077 /* mobi */;
targetProxy = 157BEA6E2747BEDA004984B8 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
150039BD18E06BC100D33077 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_GCD_PERFORMANCE = YES;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES;
CLANG_CXX_LANGUAGE_STANDARD = "compiler-default";
CLANG_CXX_LIBRARY = "compiler-default";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_ASSIGN_ENUM = NO;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_COMPLETION_HANDLER_MISUSE = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_FRAMEWORK_INCLUDE_PRIVATE_FROM_PUBLIC = YES;
CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_SEMICOLON_BEFORE_METHOD_BODY = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES_AGGRESSIVE;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = YES;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = "compiler-default";
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES;
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES;
GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES;
GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
GCC_WARN_PEDANTIC = YES;
GCC_WARN_SHADOW = YES;
GCC_WARN_SIGN_COMPARE = YES;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNKNOWN_PRAGMAS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_LABEL = YES;
GCC_WARN_UNUSED_PARAMETER = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
/usr/include/libxml2,
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
ONLY_ACTIVE_ARCH = YES;
OTHER_CFLAGS = (
"-DHAVE_CONFIG_H",
"-DHAVE_STRDUP",
);
OTHER_LDFLAGS = "-lz";
SDKROOT = macosx;
USER_HEADER_SEARCH_PATHS = "";
};
name = Debug;
};
150039BE18E06BC100D33077 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_GCD_PERFORMANCE = YES;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES;
CLANG_CXX_LANGUAGE_STANDARD = "compiler-default";
CLANG_CXX_LIBRARY = "compiler-default";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_ASSIGN_ENUM = NO;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_COMPLETION_HANDLER_MISUSE = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_FRAMEWORK_INCLUDE_PRIVATE_FROM_PUBLIC = YES;
CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_SEMICOLON_BEFORE_METHOD_BODY = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES_AGGRESSIVE;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = YES;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = "compiler-default";
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_NO_COMMON_BLOCKS = YES;
GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES;
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES;
GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES;
GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
GCC_WARN_PEDANTIC = YES;
GCC_WARN_SHADOW = YES;
GCC_WARN_SIGN_COMPARE = YES;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNKNOWN_PRAGMAS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_LABEL = YES;
GCC_WARN_UNUSED_PARAMETER = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
/usr/include/libxml2,
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
ONLY_ACTIVE_ARCH = NO;
OTHER_CFLAGS = (
"-DHAVE_CONFIG_H",
"-DHAVE_STRDUP",
);
OTHER_LDFLAGS = "-lz";
SDKROOT = macosx;
USER_HEADER_SEARCH_PATHS = "";
};
name = Release;
};
150039C018E06BC100D33077 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
COMBINE_HIDPI_IMAGES = YES;
DEAD_CODE_STRIPPING = YES;
EXECUTABLE_PREFIX = lib;
GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES;
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/include/libxml2,
);
OTHER_CFLAGS = (
"-DHAVE_CONFIG_H",
"-DHAVE_STRDUP",
);
OTHER_LDFLAGS = (
"-lxml2",
"-lz",
);
PRODUCT_NAME = mobi;
};
name = Debug;
};
150039C118E06BC100D33077 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
COMBINE_HIDPI_IMAGES = YES;
DEAD_CODE_STRIPPING = YES;
EXECUTABLE_PREFIX = lib;
GCC_OPTIMIZATION_LEVEL = 3;
GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES;
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/include/libxml2,
);
OTHER_LDFLAGS = (
"-lxml2",
"-lz",
);
PRODUCT_NAME = mobi;
};
name = Release;
};
154306581CB78A3D006AB398 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_WARN_UNREACHABLE_CODE = YES;
CODE_SIGN_IDENTITY = "-";
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
HEADER_SEARCH_PATHS = (
"$(inherited)",
./src,
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MTL_ENABLE_DEBUG_INFO = YES;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
154306591CB78A3D006AB398 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_WARN_UNREACHABLE_CODE = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = YES;
DEAD_CODE_STRIPPING = YES;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
HEADER_SEARCH_PATHS = (
"$(inherited)",
./src,
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MTL_ENABLE_DEBUG_INFO = NO;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
1553331D18E37F7100334E23 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES;
CODE_SIGN_IDENTITY = "-";
DEAD_CODE_STRIPPING = YES;
FRAMEWORK_SEARCH_PATHS = "";
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
HEADER_SEARCH_PATHS = ./src;
"HEADER_SEARCH_PATHS[arch=*]" = ./src;
MACOSX_DEPLOYMENT_TARGET = 10.15;
PRODUCT_NAME = mobitool;
};
name = Debug;
};
1553331E18E37F7100334E23 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES;
CODE_SIGN_IDENTITY = "-";
DEAD_CODE_STRIPPING = YES;
FRAMEWORK_SEARCH_PATHS = "";
HEADER_SEARCH_PATHS = ./src;
MACOSX_DEPLOYMENT_TARGET = 10.15;
PRODUCT_NAME = mobitool;
};
name = Release;
};
157BEA762747BEDA004984B8 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES;
CODE_SIGN_IDENTITY = "-";
DEAD_CODE_STRIPPING = YES;
FRAMEWORK_SEARCH_PATHS = "";
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
HEADER_SEARCH_PATHS = ./src;
"HEADER_SEARCH_PATHS[arch=*]" = ./src;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
157BEA772747BEDA004984B8 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES;
CODE_SIGN_IDENTITY = "-";
DEAD_CODE_STRIPPING = YES;
FRAMEWORK_SEARCH_PATHS = "";
HEADER_SEARCH_PATHS = ./src;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
150039B618E06BC100D33077 /* Build configuration list for PBXProject "mobi" */ = {
isa = XCConfigurationList;
buildConfigurations = (
150039BD18E06BC100D33077 /* Debug */,
150039BE18E06BC100D33077 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
150039BF18E06BC100D33077 /* Build configuration list for PBXNativeTarget "mobi" */ = {
isa = XCConfigurationList;
buildConfigurations = (
150039C018E06BC100D33077 /* Debug */,
150039C118E06BC100D33077 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
1543065A1CB78A3D006AB398 /* Build configuration list for PBXNativeTarget "mobimeta" */ = {
isa = XCConfigurationList;
buildConfigurations = (
154306581CB78A3D006AB398 /* Debug */,
154306591CB78A3D006AB398 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
1553331C18E37F7100334E23 /* Build configuration list for PBXNativeTarget "mobitool" */ = {
isa = XCConfigurationList;
buildConfigurations = (
1553331D18E37F7100334E23 /* Debug */,
1553331E18E37F7100334E23 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
157BEA752747BEDA004984B8 /* Build configuration list for PBXNativeTarget "mobidrm" */ = {
isa = XCConfigurationList;
buildConfigurations = (
157BEA762747BEDA004984B8 /* Debug */,
157BEA772747BEDA004984B8 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 150039B318E06BC100D33077 /* Project object */;
}

View file

@ -0,0 +1,97 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.1.32328.378
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmobi", "libmobi.vcxproj", "{A48F597C-ADBC-499E-B282-0F8A2B1A4B5F}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mobidrm", "mobidrm\mobidrm.vcxproj", "{288A84A9-2AFD-4995-A397-E4554C8087AE}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mobitool", "mobitool\mobitool.vcxproj", "{D8E9C708-FBD0-400C-B5B6-F8555FDE8767}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mobimeta", "mobimeta\mobimeta.vcxproj", "{2790D05E-6891-48E5-8450-F8D030763AD6}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
NoDependenciesDebug|x64 = NoDependenciesDebug|x64
NoDependenciesDebug|x86 = NoDependenciesDebug|x86
NoDependenciesRelease|x64 = NoDependenciesRelease|x64
NoDependenciesRelease|x86 = NoDependenciesRelease|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A48F597C-ADBC-499E-B282-0F8A2B1A4B5F}.Debug|x64.ActiveCfg = Debug|x64
{A48F597C-ADBC-499E-B282-0F8A2B1A4B5F}.Debug|x64.Build.0 = Debug|x64
{A48F597C-ADBC-499E-B282-0F8A2B1A4B5F}.Debug|x86.ActiveCfg = Debug|Win32
{A48F597C-ADBC-499E-B282-0F8A2B1A4B5F}.Debug|x86.Build.0 = Debug|Win32
{A48F597C-ADBC-499E-B282-0F8A2B1A4B5F}.NoDependenciesDebug|x64.ActiveCfg = NoDependenciesDebug|x64
{A48F597C-ADBC-499E-B282-0F8A2B1A4B5F}.NoDependenciesDebug|x64.Build.0 = NoDependenciesDebug|x64
{A48F597C-ADBC-499E-B282-0F8A2B1A4B5F}.NoDependenciesDebug|x86.ActiveCfg = NoDependenciesDebug|Win32
{A48F597C-ADBC-499E-B282-0F8A2B1A4B5F}.NoDependenciesDebug|x86.Build.0 = NoDependenciesDebug|Win32
{A48F597C-ADBC-499E-B282-0F8A2B1A4B5F}.NoDependenciesRelease|x64.ActiveCfg = NoDependenciesRelease|x64
{A48F597C-ADBC-499E-B282-0F8A2B1A4B5F}.NoDependenciesRelease|x64.Build.0 = NoDependenciesRelease|x64
{A48F597C-ADBC-499E-B282-0F8A2B1A4B5F}.NoDependenciesRelease|x86.ActiveCfg = NoDependenciesRelease|Win32
{A48F597C-ADBC-499E-B282-0F8A2B1A4B5F}.NoDependenciesRelease|x86.Build.0 = NoDependenciesRelease|Win32
{A48F597C-ADBC-499E-B282-0F8A2B1A4B5F}.Release|x64.ActiveCfg = Release|x64
{A48F597C-ADBC-499E-B282-0F8A2B1A4B5F}.Release|x64.Build.0 = Release|x64
{A48F597C-ADBC-499E-B282-0F8A2B1A4B5F}.Release|x86.ActiveCfg = Release|Win32
{A48F597C-ADBC-499E-B282-0F8A2B1A4B5F}.Release|x86.Build.0 = Release|Win32
{288A84A9-2AFD-4995-A397-E4554C8087AE}.Debug|x64.ActiveCfg = Debug|x64
{288A84A9-2AFD-4995-A397-E4554C8087AE}.Debug|x64.Build.0 = Debug|x64
{288A84A9-2AFD-4995-A397-E4554C8087AE}.Debug|x86.ActiveCfg = Debug|Win32
{288A84A9-2AFD-4995-A397-E4554C8087AE}.Debug|x86.Build.0 = Debug|Win32
{288A84A9-2AFD-4995-A397-E4554C8087AE}.NoDependenciesDebug|x64.ActiveCfg = Debug|x64
{288A84A9-2AFD-4995-A397-E4554C8087AE}.NoDependenciesDebug|x64.Build.0 = Debug|x64
{288A84A9-2AFD-4995-A397-E4554C8087AE}.NoDependenciesDebug|x86.ActiveCfg = Debug|Win32
{288A84A9-2AFD-4995-A397-E4554C8087AE}.NoDependenciesDebug|x86.Build.0 = Debug|Win32
{288A84A9-2AFD-4995-A397-E4554C8087AE}.NoDependenciesRelease|x64.ActiveCfg = Release|x64
{288A84A9-2AFD-4995-A397-E4554C8087AE}.NoDependenciesRelease|x64.Build.0 = Release|x64
{288A84A9-2AFD-4995-A397-E4554C8087AE}.NoDependenciesRelease|x86.ActiveCfg = Release|Win32
{288A84A9-2AFD-4995-A397-E4554C8087AE}.NoDependenciesRelease|x86.Build.0 = Release|Win32
{288A84A9-2AFD-4995-A397-E4554C8087AE}.Release|x64.ActiveCfg = Release|x64
{288A84A9-2AFD-4995-A397-E4554C8087AE}.Release|x64.Build.0 = Release|x64
{288A84A9-2AFD-4995-A397-E4554C8087AE}.Release|x86.ActiveCfg = Release|Win32
{288A84A9-2AFD-4995-A397-E4554C8087AE}.Release|x86.Build.0 = Release|Win32
{D8E9C708-FBD0-400C-B5B6-F8555FDE8767}.Debug|x64.ActiveCfg = Debug|x64
{D8E9C708-FBD0-400C-B5B6-F8555FDE8767}.Debug|x64.Build.0 = Debug|x64
{D8E9C708-FBD0-400C-B5B6-F8555FDE8767}.Debug|x86.ActiveCfg = Debug|Win32
{D8E9C708-FBD0-400C-B5B6-F8555FDE8767}.Debug|x86.Build.0 = Debug|Win32
{D8E9C708-FBD0-400C-B5B6-F8555FDE8767}.NoDependenciesDebug|x64.ActiveCfg = Debug|x64
{D8E9C708-FBD0-400C-B5B6-F8555FDE8767}.NoDependenciesDebug|x64.Build.0 = Debug|x64
{D8E9C708-FBD0-400C-B5B6-F8555FDE8767}.NoDependenciesDebug|x86.ActiveCfg = Debug|Win32
{D8E9C708-FBD0-400C-B5B6-F8555FDE8767}.NoDependenciesDebug|x86.Build.0 = Debug|Win32
{D8E9C708-FBD0-400C-B5B6-F8555FDE8767}.NoDependenciesRelease|x64.ActiveCfg = Release|x64
{D8E9C708-FBD0-400C-B5B6-F8555FDE8767}.NoDependenciesRelease|x64.Build.0 = Release|x64
{D8E9C708-FBD0-400C-B5B6-F8555FDE8767}.NoDependenciesRelease|x86.ActiveCfg = Release|Win32
{D8E9C708-FBD0-400C-B5B6-F8555FDE8767}.NoDependenciesRelease|x86.Build.0 = Release|Win32
{D8E9C708-FBD0-400C-B5B6-F8555FDE8767}.Release|x64.ActiveCfg = Release|x64
{D8E9C708-FBD0-400C-B5B6-F8555FDE8767}.Release|x64.Build.0 = Release|x64
{D8E9C708-FBD0-400C-B5B6-F8555FDE8767}.Release|x86.ActiveCfg = Release|Win32
{D8E9C708-FBD0-400C-B5B6-F8555FDE8767}.Release|x86.Build.0 = Release|Win32
{2790D05E-6891-48E5-8450-F8D030763AD6}.Debug|x64.ActiveCfg = Debug|x64
{2790D05E-6891-48E5-8450-F8D030763AD6}.Debug|x64.Build.0 = Debug|x64
{2790D05E-6891-48E5-8450-F8D030763AD6}.Debug|x86.ActiveCfg = Debug|Win32
{2790D05E-6891-48E5-8450-F8D030763AD6}.Debug|x86.Build.0 = Debug|Win32
{2790D05E-6891-48E5-8450-F8D030763AD6}.NoDependenciesDebug|x64.ActiveCfg = Debug|x64
{2790D05E-6891-48E5-8450-F8D030763AD6}.NoDependenciesDebug|x64.Build.0 = Debug|x64
{2790D05E-6891-48E5-8450-F8D030763AD6}.NoDependenciesDebug|x86.ActiveCfg = Debug|Win32
{2790D05E-6891-48E5-8450-F8D030763AD6}.NoDependenciesDebug|x86.Build.0 = Debug|Win32
{2790D05E-6891-48E5-8450-F8D030763AD6}.NoDependenciesRelease|x64.ActiveCfg = Release|x64
{2790D05E-6891-48E5-8450-F8D030763AD6}.NoDependenciesRelease|x64.Build.0 = Release|x64
{2790D05E-6891-48E5-8450-F8D030763AD6}.NoDependenciesRelease|x86.ActiveCfg = Release|Win32
{2790D05E-6891-48E5-8450-F8D030763AD6}.NoDependenciesRelease|x86.Build.0 = Release|Win32
{2790D05E-6891-48E5-8450-F8D030763AD6}.Release|x64.ActiveCfg = Release|x64
{2790D05E-6891-48E5-8450-F8D030763AD6}.Release|x64.Build.0 = Release|x64
{2790D05E-6891-48E5-8450-F8D030763AD6}.Release|x86.ActiveCfg = Release|Win32
{2790D05E-6891-48E5-8450-F8D030763AD6}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {673B11AC-E877-465E-89D0-97CAA6C1B389}
EndGlobalSection
EndGlobal

View file

@ -0,0 +1,395 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="NoDependenciesDebug|Win32">
<Configuration>NoDependenciesDebug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="NoDependenciesDebug|x64">
<Configuration>NoDependenciesDebug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="NoDependenciesRelease|Win32">
<Configuration>NoDependenciesRelease</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="NoDependenciesRelease|x64">
<Configuration>NoDependenciesRelease</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<ProjectGuid>{A48F597C-ADBC-499E-B282-0F8A2B1A4B5F}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='NoDependenciesDebug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='NoDependenciesRelease|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='NoDependenciesDebug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='NoDependenciesRelease|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='NoDependenciesDebug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='NoDependenciesRelease|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='NoDependenciesDebug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='NoDependenciesRelease|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<Linkage-libxml2>static</Linkage-libxml2>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='NoDependenciesDebug|Win32'">
<LinkIncremental>true</LinkIncremental>
<Linkage-libxml2>static</Linkage-libxml2>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='NoDependenciesRelease|Win32'">
<LinkIncremental>true</LinkIncremental>
<Linkage-libxml2>static</Linkage-libxml2>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>true</LinkIncremental>
<Linkage-libxml2>static</Linkage-libxml2>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Linkage-libxml2>static</Linkage-libxml2>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Linkage-libxml2>static</Linkage-libxml2>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='NoDependenciesDebug|x64'">
<Linkage-libxml2>static</Linkage-libxml2>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='NoDependenciesRelease|x64'">
<Linkage-libxml2>static</Linkage-libxml2>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PreprocessorDefinitions>HAVE_CONFIG_H;USE_XMLWRITER;USE_ENCRYPTION;MOBI_DEBUG=1;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
</Link>
<ProjectReference />
<ProjectReference />
<PreBuildEvent>
<Command>for /f "tokens=4 delims=[]" %%a in ('type "$(SolutionDir)..\configure.ac" ^| find "AC_INIT"') do (
set version=%%a
)
echo Compiling libmobi version %version%
echo #define PACKAGE_VERSION "%version%" &gt; "$(SolutionDir)..\config.h"</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='NoDependenciesDebug|Win32'">
<ClCompile>
<PreprocessorDefinitions>HAVE_CONFIG_H;USE_XMLWRITER;USE_ENCRYPTION;MOBI_DEBUG=1;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
</Link>
<ProjectReference />
<ProjectReference />
<PreBuildEvent>
<Command>for /f "tokens=4 delims=[]" %%a in ('type "$(SolutionDir)..\configure.ac" ^| find "AC_INIT"') do (
set version=%%a
)
echo Compiling libmobi version %version%
echo #define PACKAGE_VERSION "%version%" &gt; "$(SolutionDir)..\config.h"</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='NoDependenciesRelease|Win32'">
<ClCompile>
<PreprocessorDefinitions>HAVE_CONFIG_H;USE_XMLWRITER;USE_ENCRYPTION;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>MaxSpeed</Optimization>
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<MinimalRebuild>false</MinimalRebuild>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
</Link>
<ProjectReference />
<ProjectReference />
<PreBuildEvent>
<Command>for /f "tokens=4 delims=[]" %%a in ('type "$(SolutionDir)..\configure.ac" ^| find "AC_INIT"') do (
set version=%%a
)
echo Compiling libmobi version %version%
echo #define PACKAGE_VERSION "%version%" &gt; "$(SolutionDir)..\config.h"</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PreprocessorDefinitions>HAVE_CONFIG_H;USE_XMLWRITER;USE_ENCRYPTION;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
<ProjectReference />
<ProjectReference />
<PreBuildEvent>
<Command>for /f "tokens=4 delims=[]" %%a in ('type "$(SolutionDir)..\configure.ac" ^| find "AC_INIT"') do (
set version=%%a
)
echo Compiling libmobi version %version%
echo #define PACKAGE_VERSION "%version%" &gt; "$(SolutionDir)..\config.h"</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ProjectReference />
<ClCompile>
<PreprocessorDefinitions>HAVE_CONFIG_H;USE_XMLWRITER;USE_ENCRYPTION;MOBI_DEBUG=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<ProjectReference />
<ProjectReference />
<PreBuildEvent>
<Command>for /f "tokens=4 delims=[]" %%a in ('type "$(SolutionDir)..\configure.ac" ^| find "AC_INIT"') do (
set version=%%a
)
echo Compiling libmobi version %version%
echo #define PACKAGE_VERSION "%version%" &gt; "$(SolutionDir)..\config.h"</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='NoDependenciesDebug|x64'">
<ProjectReference />
<ClCompile>
<PreprocessorDefinitions>HAVE_CONFIG_H;USE_XMLWRITER;USE_ENCRYPTION;MOBI_DEBUG=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<ProjectReference />
<ProjectReference />
<PreBuildEvent>
<Command>for /f "tokens=4 delims=[]" %%a in ('type "$(SolutionDir)..\configure.ac" ^| find "AC_INIT"') do (
set version=%%a
)
echo Compiling libmobi version %version%
echo #define PACKAGE_VERSION "%version%" &gt; "$(SolutionDir)..\config.h"</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='NoDependenciesRelease|x64'">
<ProjectReference />
<ClCompile>
<PreprocessorDefinitions>HAVE_CONFIG_H;USE_XMLWRITER;USE_ENCRYPTION;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>MaxSpeed</Optimization>
<MinimalRebuild>false</MinimalRebuild>
</ClCompile>
<ProjectReference />
<ProjectReference />
<PreBuildEvent>
<Command>for /f "tokens=4 delims=[]" %%a in ('type "$(SolutionDir)..\configure.ac" ^| find "AC_INIT"') do (
set version=%%a
)
echo Compiling libmobi version %version%
echo #define PACKAGE_VERSION "%version%" &gt; "$(SolutionDir)..\config.h"</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ProjectReference />
<ClCompile>
<PreprocessorDefinitions>HAVE_CONFIG_H;USE_XMLWRITER;USE_ENCRYPTION;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<ProjectReference />
<ProjectReference />
<PreBuildEvent>
<Command>for /f "tokens=4 delims=[]" %%a in ('type "$(SolutionDir)..\configure.ac" ^| find "AC_INIT"') do (
set version=%%a
)
echo Compiling libmobi version %version%
echo #define PACKAGE_VERSION "%version%" &gt; "$(SolutionDir)..\config.h"</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\src\buffer.c" />
<ClCompile Include="..\src\compression.c" />
<ClCompile Include="..\src\debug.c" />
<ClCompile Include="..\src\encryption.c" />
<ClCompile Include="..\src\index.c" />
<ClCompile Include="..\src\memory.c" />
<ClCompile Include="..\src\meta.c" />
<ClCompile Include="..\src\miniz.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='NoDependenciesDebug|x64'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='NoDependenciesRelease|x64'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='NoDependenciesDebug|Win32'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='NoDependenciesRelease|Win32'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\src\opf.c" />
<ClCompile Include="..\src\parse_rawml.c" />
<ClCompile Include="..\src\randombytes.c" />
<ClCompile Include="..\src\read.c" />
<ClCompile Include="..\src\sha1.c" />
<ClCompile Include="..\src\structure.c" />
<ClCompile Include="..\src\util.c" />
<ClCompile Include="..\src\write.c" />
<ClCompile Include="..\src\xmlwriter.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='NoDependenciesDebug|x64'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='NoDependenciesRelease|x64'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='NoDependenciesDebug|Win32'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='NoDependenciesRelease|Win32'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\src\buffer.h" />
<ClInclude Include="..\src\compression.h" />
<ClInclude Include="..\src\config.h" />
<ClInclude Include="..\src\debug.h" />
<ClInclude Include="..\src\encryption.h" />
<ClInclude Include="..\src\index.h" />
<ClInclude Include="..\src\memory.h" />
<ClInclude Include="..\src\meta.h" />
<ClInclude Include="..\src\miniz.h">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='NoDependenciesDebug|x64'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='NoDependenciesRelease|x64'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='NoDependenciesDebug|Win32'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='NoDependenciesRelease|Win32'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClInclude>
<ClInclude Include="..\src\mobi.h" />
<ClInclude Include="..\src\opf.h" />
<ClInclude Include="..\src\parse_rawml.h" />
<ClInclude Include="..\src\randombytes.h" />
<ClInclude Include="..\src\read.h" />
<ClInclude Include="..\src\sha1.h" />
<ClInclude Include="..\src\structure.h" />
<ClInclude Include="..\src\util.h" />
<ClInclude Include="..\src\write.h" />
<ClInclude Include="..\src\xmlwriter.h">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='NoDependenciesDebug|x64'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='NoDependenciesRelease|x64'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='NoDependenciesDebug|Win32'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='NoDependenciesRelease|Win32'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="packages.config">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='NoDependenciesDebug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='NoDependenciesRelease|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='NoDependenciesDebug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='NoDependenciesRelease|x64'">true</ExcludedFromBuild>
</None>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="packages\zlib128-vc140-static-32_64.1.2.8\build\native\zlib128-vc140-static-32_64.targets" Condition="Exists('packages\zlib128-vc140-static-32_64.1.2.8\build\native\zlib128-vc140-static-32_64.targets')" />
<Import Project="packages\libxml2-vc140-static-32_64.2.9.4.1\build\native\libxml2-vc140-static-32_64.targets" Condition="Exists('packages\libxml2-vc140-static-32_64.2.9.4.1\build\native\libxml2-vc140-static-32_64.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('packages\zlib128-vc140-static-32_64.1.2.8\build\native\zlib128-vc140-static-32_64.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\zlib128-vc140-static-32_64.1.2.8\build\native\zlib128-vc140-static-32_64.targets'))" />
<Error Condition="!Exists('packages\libxml2-vc140-static-32_64.2.9.4.1\build\native\libxml2-vc140-static-32_64.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\libxml2-vc140-static-32_64.2.9.4.1\build\native\libxml2-vc140-static-32_64.targets'))" />
</Target>
</Project>

View file

@ -0,0 +1,182 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\tools\common.c" />
<ClCompile Include="..\..\tools\mobidrm.c" />
<ClCompile Include="..\..\tools\win32\getopt.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\tools\common.h" />
<ClInclude Include="..\..\tools\win32\getopt.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\libmobi.vcxproj">
<Project>{a48f597c-adbc-499e-b282-0f8a2b1a4b5f}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{288a84a9-2afd-4995-a397-e4554c8087ae}</ProjectGuid>
<RootNamespace>mobidrm</RootNamespace>
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Linkage-libxml2>static</Linkage-libxml2>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Linkage-libxml2>static</Linkage-libxml2>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Linkage-libxml2>static</Linkage-libxml2>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Linkage-libxml2>static</Linkage-libxml2>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>USE_XMLWRITER;USE_ENCRYPTION;_CRT_SECURE_NO_WARNINGS;MOBI_DEBUG=1;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(SolutionDir)\..\src</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalOptions>/NODEFAULTLIB:libcmtd.lib</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>USE_XMLWRITER;USE_ENCRYPTION;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(SolutionDir)\..\src</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalOptions>/NODEFAULTLIB:libcmt.lib</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>USE_XMLWRITER;USE_ENCRYPTION;_CRT_SECURE_NO_WARNINGS;MOBI_DEBUG=1;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(SolutionDir)\..\src</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalOptions>/NODEFAULTLIB:libcmtd.lib</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>USE_XMLWRITER;USE_ENCRYPTION;_CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(SolutionDir)\..\src</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalOptions>/NODEFAULTLIB:libcmt.lib</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="..\packages\zlib128-vc140-static-32_64.1.2.8\build\native\zlib128-vc140-static-32_64.targets" Condition="Exists('..\packages\zlib128-vc140-static-32_64.1.2.8\build\native\zlib128-vc140-static-32_64.targets')" />
<Import Project="..\packages\libxml2-vc140-static-32_64.2.9.4.1\build\native\libxml2-vc140-static-32_64.targets" Condition="Exists('..\packages\libxml2-vc140-static-32_64.2.9.4.1\build\native\libxml2-vc140-static-32_64.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\zlib128-vc140-static-32_64.1.2.8\build\native\zlib128-vc140-static-32_64.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\zlib128-vc140-static-32_64.1.2.8\build\native\zlib128-vc140-static-32_64.targets'))" />
<Error Condition="!Exists('..\packages\libxml2-vc140-static-32_64.2.9.4.1\build\native\libxml2-vc140-static-32_64.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\libxml2-vc140-static-32_64.2.9.4.1\build\native\libxml2-vc140-static-32_64.targets'))" />
</Target>
</Project>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="libxml2-vc140-static-32_64" version="2.9.4.1" targetFramework="native" />
<package id="zlib128-vc140-static-32_64" version="1.2.8" targetFramework="native" />
</packages>

View file

@ -0,0 +1,182 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\tools\common.c" />
<ClCompile Include="..\..\tools\mobimeta.c" />
<ClCompile Include="..\..\tools\win32\getopt.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\tools\common.h" />
<ClInclude Include="..\..\tools\win32\getopt.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\libmobi.vcxproj">
<Project>{a48f597c-adbc-499e-b282-0f8a2b1a4b5f}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{2790d05e-6891-48e5-8450-f8d030763ad6}</ProjectGuid>
<RootNamespace>mobimeta</RootNamespace>
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Linkage-libxml2>static</Linkage-libxml2>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Linkage-libxml2>static</Linkage-libxml2>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Linkage-libxml2>static</Linkage-libxml2>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Linkage-libxml2>static</Linkage-libxml2>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>USE_XMLWRITER;USE_ENCRYPTION;_CRT_SECURE_NO_WARNINGS;MOBI_DEBUG=1;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(SolutionDir)\..\src</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalOptions>/NODEFAULTLIB:libcmtd.lib</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>USE_XMLWRITER;USE_ENCRYPTION;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(SolutionDir)\..\src</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalOptions>/NODEFAULTLIB:libcmt.lib</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>USE_XMLWRITER;USE_ENCRYPTION;_CRT_SECURE_NO_WARNINGS;MOBI_DEBUG=1;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(SolutionDir)\..\src</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalOptions>/NODEFAULTLIB:libcmtd.lib</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>USE_XMLWRITER;USE_ENCRYPTION;_CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(SolutionDir)\..\src</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalOptions>/NODEFAULTLIB:libcmt.lib</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="..\packages\zlib128-vc140-static-32_64.1.2.8\build\native\zlib128-vc140-static-32_64.targets" Condition="Exists('..\packages\zlib128-vc140-static-32_64.1.2.8\build\native\zlib128-vc140-static-32_64.targets')" />
<Import Project="..\packages\libxml2-vc140-static-32_64.2.9.4.1\build\native\libxml2-vc140-static-32_64.targets" Condition="Exists('..\packages\libxml2-vc140-static-32_64.2.9.4.1\build\native\libxml2-vc140-static-32_64.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\zlib128-vc140-static-32_64.1.2.8\build\native\zlib128-vc140-static-32_64.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\zlib128-vc140-static-32_64.1.2.8\build\native\zlib128-vc140-static-32_64.targets'))" />
<Error Condition="!Exists('..\packages\libxml2-vc140-static-32_64.2.9.4.1\build\native\libxml2-vc140-static-32_64.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\libxml2-vc140-static-32_64.2.9.4.1\build\native\libxml2-vc140-static-32_64.targets'))" />
</Target>
</Project>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="libxml2-vc140-static-32_64" version="2.9.4.1" targetFramework="native" />
<package id="zlib128-vc140-static-32_64" version="1.2.8" targetFramework="native" />
</packages>

View file

@ -0,0 +1,184 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\miniz.c" />
<ClCompile Include="..\..\tools\common.c" />
<ClCompile Include="..\..\tools\mobitool.c" />
<ClCompile Include="..\..\tools\win32\getopt.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\miniz.h" />
<ClInclude Include="..\..\tools\common.h" />
<ClInclude Include="..\..\tools\win32\getopt.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\libmobi.vcxproj">
<Project>{a48f597c-adbc-499e-b282-0f8a2b1a4b5f}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{d8e9c708-fbd0-400c-b5b6-f8555fde8767}</ProjectGuid>
<RootNamespace>mobitool</RootNamespace>
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Linkage-libxml2>static</Linkage-libxml2>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Linkage-libxml2>static</Linkage-libxml2>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Linkage-libxml2>static</Linkage-libxml2>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Linkage-libxml2>static</Linkage-libxml2>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>USE_XMLWRITER;USE_ENCRYPTION;_CRT_SECURE_NO_WARNINGS;MOBI_DEBUG=1;MOBI_DEBUG=1WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(SolutionDir)\..\src</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalOptions>/NODEFAULTLIB:libcmtd.lib</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>USE_XMLWRITER;USE_ENCRYPTION;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(SolutionDir)\..\src</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalOptions>/NODEFAULTLIB:libcmt.lib</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>USE_XMLWRITER;USE_ENCRYPTION;_CRT_SECURE_NO_WARNINGS;MOBI_DEBUG=1;MOBI_DEBUG=1_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(SolutionDir)\..\src</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalOptions>/NODEFAULTLIB:libcmtd.lib</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>USE_XMLWRITER;USE_ENCRYPTION;_CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(SolutionDir)\..\src</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalOptions>/NODEFAULTLIB:libcmt.lib</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="..\packages\zlib128-vc140-static-32_64.1.2.8\build\native\zlib128-vc140-static-32_64.targets" Condition="Exists('..\packages\zlib128-vc140-static-32_64.1.2.8\build\native\zlib128-vc140-static-32_64.targets')" />
<Import Project="..\packages\libxml2-vc140-static-32_64.2.9.4.1\build\native\libxml2-vc140-static-32_64.targets" Condition="Exists('..\packages\libxml2-vc140-static-32_64.2.9.4.1\build\native\libxml2-vc140-static-32_64.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\zlib128-vc140-static-32_64.1.2.8\build\native\zlib128-vc140-static-32_64.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\zlib128-vc140-static-32_64.1.2.8\build\native\zlib128-vc140-static-32_64.targets'))" />
<Error Condition="!Exists('..\packages\libxml2-vc140-static-32_64.2.9.4.1\build\native\libxml2-vc140-static-32_64.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\libxml2-vc140-static-32_64.2.9.4.1\build\native\libxml2-vc140-static-32_64.targets'))" />
</Target>
</Project>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="libxml2-vc140-static-32_64" version="2.9.4.1" targetFramework="native" />
<package id="zlib128-vc140-static-32_64" version="1.2.8" targetFramework="native" />
</packages>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="libxml2-vc140-static-32_64" version="2.9.4.1" targetFramework="native" />
<package id="zlib128-vc140-static-32_64" version="1.2.8" targetFramework="native" />
</packages>

View file

@ -0,0 +1,87 @@
# Copyright (c) 2022 Bartek Fabiszewski
# http://www.fabiszewski.net
#
# This file is part of libmobi.
# Licensed under LGPL, either version 3, or any later.
# See <http://www.gnu.org/licenses/>
set(mobi_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/buffer.c
${CMAKE_CURRENT_SOURCE_DIR}/buffer.h
${CMAKE_CURRENT_SOURCE_DIR}/compression.c
${CMAKE_CURRENT_SOURCE_DIR}/compression.h
${CMAKE_CURRENT_SOURCE_DIR}/config.h
${CMAKE_CURRENT_SOURCE_DIR}/debug.c
${CMAKE_CURRENT_SOURCE_DIR}/debug.h
${CMAKE_CURRENT_SOURCE_DIR}/index.c
${CMAKE_CURRENT_SOURCE_DIR}/index.h
${CMAKE_CURRENT_SOURCE_DIR}/memory.c
${CMAKE_CURRENT_SOURCE_DIR}/memory.h
${CMAKE_CURRENT_SOURCE_DIR}/meta.c
${CMAKE_CURRENT_SOURCE_DIR}/meta.h
${CMAKE_CURRENT_SOURCE_DIR}/mobi.h
${CMAKE_CURRENT_SOURCE_DIR}/parse_rawml.c
${CMAKE_CURRENT_SOURCE_DIR}/parse_rawml.h
${CMAKE_CURRENT_SOURCE_DIR}/read.c
${CMAKE_CURRENT_SOURCE_DIR}/read.h
${CMAKE_CURRENT_SOURCE_DIR}/structure.c
${CMAKE_CURRENT_SOURCE_DIR}/structure.h
${CMAKE_CURRENT_SOURCE_DIR}/util.c
${CMAKE_CURRENT_SOURCE_DIR}/util.h
${CMAKE_CURRENT_SOURCE_DIR}/write.c
${CMAKE_CURRENT_SOURCE_DIR}/write.h
)
if(USE_ENCRYPTION)
list(APPEND mobi_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/encryption.c
${CMAKE_CURRENT_SOURCE_DIR}/encryption.h
${CMAKE_CURRENT_SOURCE_DIR}/sha1.c
${CMAKE_CURRENT_SOURCE_DIR}/sha1.h
${CMAKE_CURRENT_SOURCE_DIR}/randombytes.c
${CMAKE_CURRENT_SOURCE_DIR}/randombytes.h)
endif(USE_ENCRYPTION)
if(USE_XMLWRITER)
list(APPEND mobi_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/opf.c
${CMAKE_CURRENT_SOURCE_DIR}/opf.h)
if(NOT USE_LIBXML2)
list(APPEND mobi_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/xmlwriter.c
${CMAKE_CURRENT_SOURCE_DIR}/xmlwriter.h)
endif(NOT USE_LIBXML2)
endif(USE_XMLWRITER)
add_library(mobi ${mobi_SOURCES})
set_target_properties(mobi PROPERTIES
OUTPUT_NAME "mobi"
SOVERSION ${PACKAGE_VERSION_MAJOR}
VERSION "${PACKAGE_VERSION}"
POSITION_INDEPENDENT_CODE ${BUILD_SHARED_LIBS}
C_VISIBILITY_PRESET hidden
VISIBILITY_INLINES_HIDDEN ON
MACOSX_RPATH 1)
if(USE_MINIZ)
set(miniz_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/miniz.c
${CMAKE_CURRENT_SOURCE_DIR}/miniz.h
)
add_library(miniz OBJECT ${miniz_SOURCES})
target_compile_definitions(miniz PRIVATE
MINIZ_NO_STDIO
MINIZ_NO_ZLIB_COMPATIBLE_NAMES
MINIZ_NO_TIME
MINIZ_NO_ARCHIVE_APIS
MINIZ_NO_ARCHIVE_WRITING_APIS
_POSIX_C_SOURCE=200112L)
target_link_libraries(mobi PRIVATE miniz)
endif(USE_MINIZ)
if(USE_LIBXML2)
target_link_libraries(mobi PUBLIC LibXml2::LibXml2)
endif(USE_LIBXML2)
if(USE_ZLIB)
target_link_libraries(mobi PUBLIC ZLIB::ZLIB)
endif(USE_ZLIB)

View file

@ -0,0 +1,27 @@
# libmobi
lib_LTLIBRARIES = libmobi.la
libmobi_la_SOURCES = buffer.c buffer.h compression.c compression.h config.h debug.c debug.h index.c index.h memory.c memory.h \
meta.c meta.h parse_rawml.c parse_rawml.h read.c read.h structure.c structure.h util.c util.h write.c write.h
if USE_XMLWRITER
libmobi_la_SOURCES += opf.c opf.h
if !USE_LIBXML2
libmobi_la_SOURCES += xmlwriter.c xmlwriter.h
endif
endif
if USE_ENCRYPTION
libmobi_la_SOURCES += encryption.c encryption.h randombytes.c randombytes.h sha1.c sha1.h
endif
EXTRA_LTLIBRARIES = libminiz.la
libminiz_la_SOURCES = miniz.c miniz.h
libminiz_la_CFLAGS = $(VISIBILITY_HIDDEN) $(MINIZ_CFLAGS) \
-DMINIZ_NO_STDIO -DMINIZ_NO_ZLIB_COMPATIBLE_NAMES \
-DMINIZ_NO_TIME -DMINIZ_NO_ARCHIVE_APIS -DMINIZ_NO_ARCHIVE_WRITING_APIS
libminiz_la_LDFLAGS =
if USE_MINIZ
libmobi_la_LIBADD = libminiz.la
endif
include_HEADERS = mobi.h
libmobi_la_LDFLAGS = $(AVOID_VERSION) $(NO_UNDEFINED) $(DARWIN_LDFLAGS) $(LIBZ_LDFLAGS) $(LIBXML2_LDFLAGS)
libmobi_la_CFLAGS = $(VISIBILITY_HIDDEN) $(ISO99_SOURCE) $(DEBUG_CFLAGS) $(LIBXML2_CFLAGS)

637
app/src/main/cpp/libmobi/src/buffer.c vendored Normal file
View file

@ -0,0 +1,637 @@
/** @file buffer.c
* @brief Functions to read/write raw big endian data
*
* Copyright (c) 2014 Bartek Fabiszewski
* http://www.fabiszewski.net
*
* This file is part of libmobi.
* Licensed under LGPL, either version 3, or any later.
* See <http://www.gnu.org/licenses/>
*/
#include <stdlib.h>
#include <string.h>
#include "buffer.h"
#include "debug.h"
/**
@brief Initializer for MOBIBuffer structure
It allocates memory for structure and for data.
Memory should be freed with mobi_buffer_free().
@param[in] len Size of data to be allocated for the buffer
@return MOBIBuffer on success, NULL otherwise
*/
MOBIBuffer * mobi_buffer_init(const size_t len) {
unsigned char *data = malloc(len);
if (data == NULL) {
debug_print("%s", "Buffer data allocation failed\n");
return NULL;
}
MOBIBuffer *buf = mobi_buffer_init_null(data, len);
if (buf == NULL) {
free(data);
}
return buf;
}
/**
@brief Initializer for MOBIBuffer structure
It allocates memory for structure but, unlike mobi_buffer_init(), it does not allocate memory for data.
Instead it works on external data.
Memory should be freed with mobi_buffer_free_null() (buf->data will not be deallocated).
@param[in,out] data Set data as buffer data
@param[in] len Size of data held by the buffer
@return MOBIBuffer on success, NULL otherwise
*/
MOBIBuffer * mobi_buffer_init_null(unsigned char *data, const size_t len) {
MOBIBuffer *buf = malloc(sizeof(MOBIBuffer));
if (buf == NULL) {
debug_print("%s", "Buffer allocation failed\n");
return NULL;
}
buf->data = data;
buf->offset = 0;
buf->maxlen = len;
buf->error = MOBI_SUCCESS;
return buf;
}
/**
@brief Resize buffer
Smaller size than offset will cause data truncation.
@param[in,out] buf MOBIBuffer structure to be filled with data
@param[in] newlen New buffer size
*/
void mobi_buffer_resize(MOBIBuffer *buf, const size_t newlen) {
unsigned char *tmp = realloc(buf->data, newlen);
if (tmp == NULL) {
debug_print("%s", "Buffer allocation failed\n");
buf->error = MOBI_MALLOC_FAILED;
return;
}
buf->data = tmp;
buf->maxlen = newlen;
if (buf->offset >= newlen) {
buf->offset = newlen - 1;
}
debug_print("Buffer successfully resized to %zu\n", newlen);
buf->error = MOBI_SUCCESS;
}
/**
@brief Adds 8-bit value to MOBIBuffer
@param[in,out] buf MOBIBuffer structure to be filled with data
@param[in] data Integer to be put into the buffer
*/
void mobi_buffer_add8(MOBIBuffer *buf, const uint8_t data) {
if (buf->offset + 1 > buf->maxlen) {
debug_print("%s", "Buffer full\n");
buf->error = MOBI_BUFFER_END;
return;
}
buf->data[buf->offset++] = data;
}
/**
@brief Adds 16-bit value to MOBIBuffer
@param[in,out] buf MOBIBuffer structure to be filled with data
@param[in] data Integer to be put into the buffer
*/
void mobi_buffer_add16(MOBIBuffer *buf, const uint16_t data) {
if (buf->offset + 2 > buf->maxlen) {
debug_print("%s", "Buffer full\n");
buf->error = MOBI_BUFFER_END;
return;
}
unsigned char *buftr = buf->data + buf->offset;
*buftr++ = (uint8_t)((uint32_t)(data & 0xff00U) >> 8);
*buftr = (uint8_t)((uint32_t)(data & 0xffU));
buf->offset += 2;
}
/**
@brief Adds 32-bit value to MOBIBuffer
@param[in,out] buf MOBIBuffer structure to be filled with data
@param[in] data Integer to be put into the buffer
*/
void mobi_buffer_add32(MOBIBuffer *buf, const uint32_t data) {
if (buf->offset + 4 > buf->maxlen) {
debug_print("%s", "Buffer full\n");
buf->error = MOBI_BUFFER_END;
return;
}
unsigned char *buftr = buf->data + buf->offset;
*buftr++ = (uint8_t)((uint32_t)(data & 0xff000000U) >> 24);
*buftr++ = (uint8_t)((uint32_t)(data & 0xff0000U) >> 16);
*buftr++ = (uint8_t)((uint32_t)(data & 0xff00U) >> 8);
*buftr = (uint8_t)((uint32_t)(data & 0xffU));
buf->offset += 4;
}
/**
@brief Adds raw data to MOBIBuffer
@param[in,out] buf MOBIBuffer structure to be filled with data
@param[in] data Pointer to read data
@param[in] len Size of the read data
*/
void mobi_buffer_addraw(MOBIBuffer *buf, const unsigned char* data, const size_t len) {
if (buf->offset + len > buf->maxlen) {
debug_print("%s", "Buffer full\n");
buf->error = MOBI_BUFFER_END;
return;
}
memcpy(buf->data + buf->offset, data, len);
buf->offset += len;
}
/**
@brief Adds string to MOBIBuffer without null terminator
@param[in,out] buf MOBIBuffer structure to be filled with data
@param[in] str Pointer to string
*/
void mobi_buffer_addstring(MOBIBuffer *buf, const char *str) {
const size_t len = strlen(str);
mobi_buffer_addraw(buf, (const unsigned char *) str, len);
}
/**
@brief Adds count of zeroes to MOBIBuffer
@param[in,out] buf MOBIBuffer structure to be filled with data
@param[in] count Number of zeroes to be put into the buffer
*/
void mobi_buffer_addzeros(MOBIBuffer *buf, const size_t count) {
if (buf->offset + count > buf->maxlen) {
debug_print("%s", "Buffer full\n");
buf->error = MOBI_BUFFER_END;
return;
}
memset(buf->data + buf->offset, 0, count);
buf->offset += count;
}
/**
@brief Reads 8-bit value from MOBIBuffer
@param[in] buf MOBIBuffer structure containing data
@return Read value, 0 if end of buffer is encountered
*/
uint8_t mobi_buffer_get8(MOBIBuffer *buf) {
if (buf->offset + 1 > buf->maxlen) {
debug_print("%s", "End of buffer\n");
buf->error = MOBI_BUFFER_END;
return 0;
}
return buf->data[buf->offset++];
}
/**
@brief Reads 16-bit value from MOBIBuffer
@param[in] buf MOBIBuffer structure containing data
@return Read value, 0 if end of buffer is encountered
*/
uint16_t mobi_buffer_get16(MOBIBuffer *buf) {
if (buf->offset + 2 > buf->maxlen) {
debug_print("%s", "End of buffer\n");
buf->error = MOBI_BUFFER_END;
return 0;
}
uint16_t val;
val = (uint16_t)((uint16_t) buf->data[buf->offset] << 8 | (uint16_t) buf->data[buf->offset + 1]);
buf->offset += 2;
return val;
}
/**
@brief Reads 32-bit value from MOBIBuffer
@param[in] buf MOBIBuffer structure containing data
@return Read value, 0 if end of buffer is encountered
*/
uint32_t mobi_buffer_get32(MOBIBuffer *buf) {
if (buf->offset + 4 > buf->maxlen) {
debug_print("%s", "End of buffer\n");
buf->error = MOBI_BUFFER_END;
return 0;
}
uint32_t val;
val = (uint32_t) buf->data[buf->offset] << 24 | (uint32_t) buf->data[buf->offset + 1] << 16 | (uint32_t) buf->data[buf->offset + 2] << 8 | (uint32_t) buf->data[buf->offset + 3];
buf->offset += 4;
return val;
}
/**
@brief Reads variable length value from MOBIBuffer
Internal function for wrappers:
mobi_buffer_get_varlen();
mobi_buffer_get_varlen_dec();
Reads maximum 4 bytes from the buffer. Stops when byte has bit 7 set.
This function has a limitation while reading backwards.
In such case it will not read first byte in a buffer, as it would cause buffer offset to underflow.
That means that going bacwards it cannot read variable length values that are placed at the beginning of a buffer.
This will result in an error.
@param[in] buf MOBIBuffer structure containing data
@param[out] len Value will be increased by number of bytes read
@param[in] direction 1 - read buffer forward, -1 - read buffer backwards
@return Read value, 0 if end of buffer is encountered
*/
static uint32_t mobi_buffer_get_varlen_internal(MOBIBuffer *buf, size_t *len, const int direction) {
bool has_stop = false;
uint32_t val = 0;
uint8_t byte_count = 0;
size_t max_count = direction == 1 ? buf->maxlen - buf->offset : buf->offset;
if (buf->offset < buf->maxlen && max_count) {
max_count = max_count < 4 ? max_count : 4;
uint8_t byte;
const uint8_t stop_flag = 0x80;
const uint8_t mask = 0x7f;
uint32_t shift = 0;
unsigned char *p = buf->data + buf->offset;
do {
if (direction == 1) {
byte = *p++;
val <<= 7;
val |= (byte & mask);
} else {
byte = *p--;
val = val | (uint32_t)(byte & mask) << shift;
shift += 7;
}
byte_count++;
has_stop = byte & stop_flag;
} while (!has_stop && (byte_count < max_count));
}
if (!has_stop) {
debug_print("%s", "End of buffer\n");
buf->error = MOBI_BUFFER_END;
return 0;
}
*len += byte_count;
buf->offset = direction == 1 ? buf->offset + byte_count : buf->offset - byte_count;
return val;
}
/**
@brief Reads variable length value from MOBIBuffer
Reads maximum 4 bytes from the buffer. Stops when byte has bit 7 set.
@param[in] buf MOBIBuffer structure containing data
@param[out] len Value will be increased by number of bytes read
@return Read value, 0 if end of buffer is encountered
*/
uint32_t mobi_buffer_get_varlen(MOBIBuffer *buf, size_t *len) {
return mobi_buffer_get_varlen_internal(buf, len, 1);
}
/**
@brief Reads variable length value from MOBIBuffer going backwards
Reads maximum 4 bytes from the buffer. Stops when byte has bit 7 set.
This function has a limitation. It will not read first byte in a buffer, as it would cause buffer offset to underflow.
That means that it cannot read variable length values that are placed at the beginning of a buffer.
This will result in an error.
@param[in] buf MOBIBuffer structure containing data
@param[out] len Value will be increased by number of bytes read
@return Read value, 0 if end of buffer is encountered
*/
uint32_t mobi_buffer_get_varlen_dec(MOBIBuffer *buf, size_t *len) {
return mobi_buffer_get_varlen_internal(buf, len, -1);
}
/**
@brief Reads raw data from MOBIBuffer and pads it with zero character
@param[out] str Destination for string read from buffer. Length must be (len + 1)
@param[in] buf MOBIBuffer structure containing data
@param[in] len Length of the data to be read from buffer
*/
void mobi_buffer_getstring(char *str, MOBIBuffer *buf, const size_t len) {
if (!str) {
buf->error = MOBI_PARAM_ERR;
return;
}
if (buf->offset + len > buf->maxlen) {
debug_print("%s", "End of buffer\n");
buf->error = MOBI_BUFFER_END;
str[0] = '\0';
return;
}
memcpy(str, buf->data + buf->offset, len);
str[len] = '\0';
buf->offset += len;
}
/**
@brief Reads raw data from MOBIBuffer, appends it to a string and pads it with zero character
@param[in,out] str A string to which data will be appended
@param[in] buf MOBIBuffer structure containing data
@param[in] len Length of the data to be read from buffer
*/
void mobi_buffer_appendstring(char *str, MOBIBuffer *buf, const size_t len) {
if (!str) {
buf->error = MOBI_PARAM_ERR;
return;
}
if (buf->offset + len > buf->maxlen) {
debug_print("%s", "End of buffer\n");
buf->error = MOBI_BUFFER_END;
return;
}
size_t str_len = strlen(str);
memcpy(str + str_len, buf->data + buf->offset, len);
str[str_len + len] = '\0';
buf->offset += len;
}
/**
@brief Reads raw data from MOBIBuffer
@param[out] data Destination to which data will be appended
@param[in] buf MOBIBuffer structure containing data
@param[in] len Length of the data to be read from buffer
*/
void mobi_buffer_getraw(void *data, MOBIBuffer *buf, const size_t len) {
if (!data) {
buf->error = MOBI_PARAM_ERR;
return;
}
if (buf->offset + len > buf->maxlen) {
debug_print("%s", "End of buffer\n");
buf->error = MOBI_BUFFER_END;
return;
}
memcpy(data, buf->data + buf->offset, len);
buf->offset += len;
}
/**
@brief Get pointer to MOBIBuffer data at offset
@param[in] buf MOBIBuffer structure containing data
@param[in] len Check if requested length is available in buffer
@return Pointer to offset, or NULL on failure
*/
unsigned char * mobi_buffer_getpointer(MOBIBuffer *buf, const size_t len) {
if (buf->offset + len > buf->maxlen) {
debug_print("%s", "End of buffer\n");
buf->error = MOBI_BUFFER_END;
return NULL;
}
buf->offset += len;
return buf->data + buf->offset - len;
}
/**
@brief Read 8-bit value from MOBIBuffer into allocated memory
Read 8-bit value from buffer into memory allocated by the function.
Returns pointer to the value, which must be freed later.
If the data is not accessible function will return null pointer.
@param[out] val Pointer to value or null pointer on failure
@param[in] buf MOBIBuffer structure containing data
*/
void mobi_buffer_dup8(uint8_t **val, MOBIBuffer *buf) {
*val = NULL;
if (buf->offset + 1 > buf->maxlen) {
return;
}
*val = malloc(sizeof(uint8_t));
if (*val == NULL) {
return;
}
**val = mobi_buffer_get8(buf);
}
/**
@brief Read 16-bit value from MOBIBuffer into allocated memory
Read 16-bit value from buffer into allocated memory.
Returns pointer to the value, which must be freed later.
If the data is not accessible function will return null pointer.
@param[out] val Pointer to value or null pointer on failure
@param[in] buf MOBIBuffer structure containing data
*/
void mobi_buffer_dup16(uint16_t **val, MOBIBuffer *buf) {
*val = NULL;
if (buf->offset + 2 > buf->maxlen) {
return;
}
*val = malloc(sizeof(uint16_t));
if (*val == NULL) {
return;
}
**val = mobi_buffer_get16(buf);
}
/**
@brief Read 32-bit value from MOBIBuffer into allocated memory
Read 32-bit value from buffer into allocated memory.
Returns pointer to the value, which must be freed later.
If the data is not accessible function will return null pointer.
@param[out] val Pointer to value
@param[in] buf MOBIBuffer structure containing data
*/
void mobi_buffer_dup32(uint32_t **val, MOBIBuffer *buf) {
*val = NULL;
if (buf->offset + 4 > buf->maxlen) {
return;
}
*val = malloc(sizeof(uint32_t));
if (*val == NULL) {
return;
}
**val = mobi_buffer_get32(buf);
}
/**
@brief Copy 8-bit value from one MOBIBuffer into another
@param[out] dest Destination buffer
@param[in] source Source buffer
*/
void mobi_buffer_copy8(MOBIBuffer *dest, MOBIBuffer *source) {
mobi_buffer_add8(dest, mobi_buffer_get8(source));
}
/**
@brief Copy raw value from one MOBIBuffer into another
@param[out] dest Destination buffer
@param[in] source Source buffer
@param[in] len Number of bytes to copy
*/
void mobi_buffer_copy(MOBIBuffer *dest, MOBIBuffer *source, const size_t len) {
if (source->offset + len > source->maxlen) {
debug_print("%s", "End of buffer\n");
source->error = MOBI_BUFFER_END;
return;
}
if (dest->offset + len > dest->maxlen) {
debug_print("%s", "End of buffer\n");
dest->error = MOBI_BUFFER_END;
return;
}
memcpy(dest->data + dest->offset, source->data + source->offset, len);
dest->offset += len;
source->offset += len;
}
/**
@brief Copy raw value within one MOBIBuffer
Memmove len bytes from offset (relative to current position)
to current position in buffer and advance buffer position.
Data may overlap.
@param[out] buf Buffer
@param[in] offset Offset to read from
@param[in] len Number of bytes to copy
*/
void mobi_buffer_move(MOBIBuffer *buf, const int offset, const size_t len) {
size_t aoffset = (size_t) abs(offset);
unsigned char *source = buf->data + buf->offset;
if (offset >= 0) {
if (buf->offset + aoffset + len > buf->maxlen) {
debug_print("%s", "End of buffer\n");
buf->error = MOBI_BUFFER_END;
return;
}
source += aoffset;
} else {
if ( (buf->offset < aoffset) || (buf->offset + len > buf->maxlen) ) {
debug_print("%s", "Beyond start/end of buffer\n");
buf->error = MOBI_BUFFER_END;
return;
}
source -= aoffset;
}
memmove(buf->data + buf->offset, source, len);
buf->offset += len;
}
/**
@brief Check if buffer data header contains magic signature
@param[in] buf MOBIBuffer buffer containing data
@param[in] magic Magic signature
@return boolean true on match, false otherwise
*/
bool mobi_buffer_match_magic(MOBIBuffer *buf, const char *magic) {
const size_t magic_length = strlen(magic);
if (buf->offset + magic_length > buf->maxlen) {
return false;
}
if (memcmp(buf->data + buf->offset, magic, magic_length) == 0) {
return true;
}
return false;
}
/**
@brief Check if buffer contains magic signature at given offset
@param[in] buf MOBIBuffer buffer containing data
@param[in] magic Magic signature
@param[in] offset Offset
@return boolean true on match, false otherwise
*/
bool mobi_buffer_match_magic_offset(MOBIBuffer *buf, const char *magic, const size_t offset) {
bool match = false;
if (offset <= buf->maxlen) {
const size_t save_offset = buf->offset;
buf->offset = offset;
match = mobi_buffer_match_magic(buf, magic);
buf->offset = save_offset;
}
return match;
}
/**
@brief Move current buffer offset by diff bytes
@param[in,out] buf MOBIBuffer buffer containing data
@param[in] diff Number of bytes by which the offset is adjusted
*/
void mobi_buffer_seek(MOBIBuffer *buf, const int diff) {
size_t adiff = (size_t) abs(diff);
if (diff >= 0) {
if (buf->offset + adiff <= buf->maxlen) {
buf->offset += adiff;
return;
}
} else {
if (buf->offset >= adiff) {
buf->offset -= adiff;
return;
}
}
buf->error = MOBI_BUFFER_END;
debug_print("%s", "End of buffer\n");
}
/**
@brief Set buffer offset to pos position
@param[in,out] buf MOBIBuffer buffer containing data
@param[in] pos New position
*/
void mobi_buffer_setpos(MOBIBuffer *buf, const size_t pos) {
if (pos <= buf->maxlen) {
buf->offset = pos;
return;
}
buf->error = MOBI_BUFFER_END;
debug_print("%s", "End of buffer\n");
}
/**
@brief Free pointer to MOBIBuffer structure and pointer to data
Free data initialized with mobi_buffer_init();
@param[in] buf MOBIBuffer structure
*/
void mobi_buffer_free(MOBIBuffer *buf) {
if (buf == NULL) { return; }
if (buf->data != NULL) {
free(buf->data);
}
free(buf);
}
/**
@brief Free pointer to MOBIBuffer structure
Free data initialized with mobi_buffer_init_null();
Unlike mobi_buffer_free() it will not free pointer to buf->data
@param[in] buf MOBIBuffer structure
*/
void mobi_buffer_free_null(MOBIBuffer *buf) {
if (buf == NULL) { return; }
free(buf);
}

58
app/src/main/cpp/libmobi/src/buffer.h vendored Normal file
View file

@ -0,0 +1,58 @@
/** @file buffer.h
*
* Copyright (c) 2014 Bartek Fabiszewski
* http://www.fabiszewski.net
*
* This file is part of libmobi.
* Licensed under LGPL, either version 3, or any later.
* See <http://www.gnu.org/licenses/>
*/
#ifndef libmobi_buffer_h
#define libmobi_buffer_h
#include "config.h"
#include "mobi.h"
/**
@brief Buffer to read to/write from
*/
typedef struct {
size_t offset; /**< Current offset in respect to buffer start */
size_t maxlen; /**< Length of the buffer data */
unsigned char *data; /**< Pointer to buffer data */
MOBI_RET error; /**< MOBI_SUCCESS = 0 if operation on buffer is successful, non-zero value on failure */
} MOBIBuffer;
MOBIBuffer * mobi_buffer_init(const size_t len);
MOBIBuffer * mobi_buffer_init_null(unsigned char *data, const size_t len);
void mobi_buffer_resize(MOBIBuffer *buf, const size_t newlen);
void mobi_buffer_add8(MOBIBuffer *buf, const uint8_t data);
void mobi_buffer_add16(MOBIBuffer *buf, const uint16_t data);
void mobi_buffer_add32(MOBIBuffer *buf, const uint32_t data);
void mobi_buffer_addraw(MOBIBuffer *buf, const unsigned char* data, const size_t len);
void mobi_buffer_addstring(MOBIBuffer *buf, const char *str);
void mobi_buffer_addzeros(MOBIBuffer *buf, const size_t count);
uint8_t mobi_buffer_get8(MOBIBuffer *buf);
uint16_t mobi_buffer_get16(MOBIBuffer *buf);
uint32_t mobi_buffer_get32(MOBIBuffer *buf);
uint32_t mobi_buffer_get_varlen(MOBIBuffer *buf, size_t *len);
uint32_t mobi_buffer_get_varlen_dec(MOBIBuffer *buf, size_t *len);
void mobi_buffer_dup8(uint8_t **val, MOBIBuffer *buf);
void mobi_buffer_dup16(uint16_t **val, MOBIBuffer *buf);
void mobi_buffer_dup32(uint32_t **val, MOBIBuffer *buf);
void mobi_buffer_getstring(char *str, MOBIBuffer *buf, const size_t len);
void mobi_buffer_appendstring(char *str, MOBIBuffer *buf, const size_t len);
void mobi_buffer_getraw(void *data, MOBIBuffer *buf, const size_t len);
unsigned char * mobi_buffer_getpointer(MOBIBuffer *buf, const size_t len);
void mobi_buffer_copy8(MOBIBuffer *dest, MOBIBuffer *source);
void mobi_buffer_move(MOBIBuffer *buf, const int offset, const size_t len);
void mobi_buffer_copy(MOBIBuffer *dest, MOBIBuffer *source, const size_t len);
bool mobi_buffer_match_magic(MOBIBuffer *buf, const char *magic);
bool mobi_buffer_match_magic_offset(MOBIBuffer *buf, const char *magic, const size_t offset);
void mobi_buffer_seek(MOBIBuffer *buf, const int diff);
void mobi_buffer_setpos(MOBIBuffer *buf, const size_t pos);
void mobi_buffer_free(MOBIBuffer *buf);
void mobi_buffer_free_null(MOBIBuffer *buf);
#endif

View file

@ -0,0 +1,221 @@
/** @file compression.c
* @brief Functions handling compression
*
* Copyright (c) 2014 Bartek Fabiszewski
* http://www.fabiszewski.net
*
* This file is part of libmobi.
* Licensed under LGPL, either version 3, or any later.
* See <http://www.gnu.org/licenses/>
*/
#include <string.h>
#include "compression.h"
#include "buffer.h"
#include "mobi.h"
#include "debug.h"
/**
@brief Decompressor fo PalmDOC version of LZ77 compression
Decompressor based on this algorithm:
http://en.wikibooks.org/wiki/Data_Compression/Dictionary_compression#PalmDoc
@param[out] out Decompressed destination data
@param[in] in Compressed source data
@param[in,out] len_out Size of the memory reserved for decompressed data.
On return it is set to actual size of decompressed data
@param[in] len_in Size of compressed data
@return MOBI_RET status code (on success MOBI_SUCCESS)
*/
MOBI_RET mobi_decompress_lz77(unsigned char *out, const unsigned char *in, size_t *len_out, const size_t len_in) {
MOBI_RET ret = MOBI_SUCCESS;
MOBIBuffer *buf_in = mobi_buffer_init_null((unsigned char *) in, len_in);
if (buf_in == NULL) {
debug_print("%s\n", "Memory allocation failed");
return MOBI_MALLOC_FAILED;
}
MOBIBuffer *buf_out = mobi_buffer_init_null(out, *len_out);
if (buf_out == NULL) {
mobi_buffer_free_null(buf_in);
debug_print("%s\n", "Memory allocation failed");
return MOBI_MALLOC_FAILED;
}
while (ret == MOBI_SUCCESS && buf_in->offset < buf_in->maxlen) {
uint8_t byte = mobi_buffer_get8(buf_in);
/* byte pair: space + char */
if (byte >= 0xc0) {
mobi_buffer_add8(buf_out, ' ');
mobi_buffer_add8(buf_out, byte ^ 0x80);
}
/* length, distance pair */
/* 0x8000 + (distance << 3) + ((length-3) & 0x07) */
else if (byte >= 0x80) {
uint8_t next = mobi_buffer_get8(buf_in);
uint16_t distance = ((((byte << 8) | ((uint8_t)next)) >> 3) & 0x7ff);
uint8_t length = (next & 0x7) + 3;
while (length--) {
mobi_buffer_move(buf_out, -distance, 1);
}
}
/* single char, not modified */
else if (byte >= 0x09) {
mobi_buffer_add8(buf_out, byte);
}
/* val chars not modified */
else if (byte >= 0x01) {
mobi_buffer_copy(buf_out, buf_in, byte);
}
/* char '\0', not modified */
else {
mobi_buffer_add8(buf_out, byte);
}
if (buf_in->error || buf_out->error) {
ret = MOBI_BUFFER_END;
}
}
*len_out = buf_out->offset;
mobi_buffer_free_null(buf_out);
mobi_buffer_free_null(buf_in);
return ret;
}
/**
@brief Read at most 8 bytes from buffer, big-endian
If buffer data is shorter returned value is padded with zeroes
@param[in] buf MOBIBuffer structure to read from
@return 64-bit value
*/
static MOBI_INLINE uint64_t mobi_buffer_fill64(MOBIBuffer *buf) {
uint64_t val = 0;
uint8_t i = 8;
size_t bytesleft = buf->maxlen - buf->offset;
unsigned char *ptr = buf->data + buf->offset;
while (i-- && bytesleft--) {
val |= (uint64_t) *ptr++ << (i * 8);
}
/* increase counter by 4 bytes only, 4 bytes overlap on each call */
buf->offset += 4;
return val;
}
/**
@brief Internal function for huff/cdic decompression
Decompressor and HUFF/CDIC records parsing based on:
perl EBook::Tools::Mobipocket
python mobiunpack.py, calibre
@param[out] buf_out MOBIBuffer structure with decompressed data
@param[in] buf_in MOBIBuffer structure with compressed data
@param[in] huffcdic MOBIHuffCdic structure with parsed data from huff/cdic records
@param[in] depth Depth of current recursion level
@return MOBI_RET status code (on success MOBI_SUCCESS)
*/
static MOBI_RET mobi_decompress_huffman_internal(MOBIBuffer *buf_out, MOBIBuffer *buf_in, const MOBIHuffCdic *huffcdic, size_t depth) {
if (depth > MOBI_HUFFMAN_MAXDEPTH) {
debug_print("Too many levels of recursion: %zu\n", depth);
return MOBI_DATA_CORRUPT;
}
MOBI_RET ret = MOBI_SUCCESS;
int8_t bitcount = 32;
/* this cast should be safe: max record size is 4096 */
int bitsleft = (int) (buf_in->maxlen * 8);
uint8_t code_length = 0;
uint64_t buffer = mobi_buffer_fill64(buf_in);
while (ret == MOBI_SUCCESS) {
if (bitcount <= 0) {
bitcount += 32;
buffer = mobi_buffer_fill64(buf_in);
}
uint32_t code = (buffer >> bitcount) & 0xffffffffU;
/* lookup code in table1 */
uint32_t t1 = huffcdic->table1[code >> 24];
/* get maxcode and codelen from t1 */
code_length = t1 & 0x1f;
uint32_t maxcode = (((t1 >> 8) + 1) << (32 - code_length)) - 1;
/* check termination bit */
if (!(t1 & 0x80)) {
/* get offset from mincode, maxcode tables */
while (code < huffcdic->mincode_table[code_length]) {
if (++code_length >= HUFF_CODETABLE_SIZE) {
debug_print("Wrong offset to mincode table: %hhu\n", code_length);
return MOBI_DATA_CORRUPT;
}
}
maxcode = huffcdic->maxcode_table[code_length];
}
bitcount -= code_length;
bitsleft -= code_length;
if (bitsleft < 0) {
break;
}
/* get index for symbol offset */
uint32_t index = (uint32_t) (maxcode - code) >> (32 - code_length);
/* check which part of cdic to use */
uint16_t cdic_index = (uint16_t) ((uint32_t)index >> huffcdic->code_length);
if (index >= huffcdic->index_count) {
debug_print("Wrong symbol offsets index: %u\n", index);
return MOBI_DATA_CORRUPT;
}
/* get offset */
uint32_t offset = huffcdic->symbol_offsets[index];
uint32_t symbol_length = (uint32_t) huffcdic->symbols[cdic_index][offset] << 8 | (uint32_t) huffcdic->symbols[cdic_index][offset + 1];
/* 1st bit is is_decompressed flag */
int is_decompressed = symbol_length >> 15;
/* get rid of flag */
symbol_length &= 0x7fff;
if (is_decompressed) {
/* symbol is at (offset + 2), 2 bytes used earlier for symbol length */
mobi_buffer_addraw(buf_out, (huffcdic->symbols[cdic_index] + offset + 2), symbol_length);
ret = buf_out->error;
} else {
/* symbol is compressed */
/* TODO cache uncompressed symbols? */
MOBIBuffer buf_sym;
buf_sym.data = huffcdic->symbols[cdic_index] + offset + 2;
buf_sym.offset = 0;
buf_sym.maxlen = symbol_length;
buf_sym.error = MOBI_SUCCESS;
ret = mobi_decompress_huffman_internal(buf_out, &buf_sym, huffcdic, depth + 1);
}
}
return ret;
}
/**
@brief Decompressor for huff/cdic compressed text records
Decompressor and HUFF/CDIC records parsing based on:
perl EBook::Tools::Mobipocket
python mobiunpack.py, calibre
@param[out] out Decompressed destination data
@param[in] in Compressed source data
@param[in,out] len_out Size of the memory reserved for decompressed data.
On return it is set to actual size of decompressed data
@param[in] len_in Size of compressed data
@param[in] huffcdic MOBIHuffCdic structure with parsed data from huff/cdic records
@return MOBI_RET status code (on success MOBI_SUCCESS)
*/
MOBI_RET mobi_decompress_huffman(unsigned char *out, const unsigned char *in, size_t *len_out, size_t len_in, const MOBIHuffCdic *huffcdic) {
MOBIBuffer *buf_in = mobi_buffer_init_null((unsigned char *) in, len_in);
if (buf_in == NULL) {
debug_print("%s\n", "Memory allocation failed");
return MOBI_MALLOC_FAILED;
}
MOBIBuffer *buf_out = mobi_buffer_init_null(out, *len_out);
if (buf_out == NULL) {
mobi_buffer_free_null(buf_in);
debug_print("%s\n", "Memory allocation failed");
return MOBI_MALLOC_FAILED;
}
MOBI_RET ret = mobi_decompress_huffman_internal(buf_out, buf_in, huffcdic, 0);
*len_out = buf_out->offset;
mobi_buffer_free_null(buf_out);
mobi_buffer_free_null(buf_in);
return ret;
}

View file

@ -0,0 +1,43 @@
/** @file compression.h
*
* Copyright (c) 2014 Bartek Fabiszewski
* http://www.fabiszewski.net
*
* This file is part of libmobi.
* Licensed under LGPL, either version 3, or any later.
* See <http://www.gnu.org/licenses/>
*/
#ifndef libmobi_compression_h
#define libmobi_compression_h
#include "config.h"
#include "mobi.h"
#ifndef MOBI_INLINE
#define MOBI_INLINE /**< Syntax for compiler inline keyword from config.h */
#endif
/* FIXME: what is the reasonable value? */
#define MOBI_HUFFMAN_MAXDEPTH 20 /**< Maximal recursion level for huffman decompression routine */
#define HUFF_CODETABLE_SIZE 33 /**< Size of min- and maxcode tables */
/**
@brief Parsed data from HUFF and CDIC records needed to unpack huffman compressed text
*/
typedef struct {
size_t index_count; /**< Total number of indices in all CDIC records, stored in each CDIC record header */
size_t index_read; /**< Number of indices parsed, used by parser */
size_t code_length; /**< Code length value stored in CDIC record header */
uint32_t table1[256]; /**< Table of big-endian indices from HUFF record data1 */
uint32_t mincode_table[HUFF_CODETABLE_SIZE]; /**< Table of big-endian mincodes from HUFF record data2 */
uint32_t maxcode_table[HUFF_CODETABLE_SIZE]; /**< Table of big-endian maxcodes from HUFF record data2 */
uint16_t *symbol_offsets; /**< Index of symbol offsets parsed from CDIC records (index_count entries) */
unsigned char **symbols; /**< Array of pointers to start of symbols data in each CDIC record (index = number of CDIC record) */
} MOBIHuffCdic;
MOBI_RET mobi_decompress_lz77(unsigned char *out, const unsigned char *in, size_t *len_out, const size_t len_in);
MOBI_RET mobi_decompress_huffman(unsigned char *out, const unsigned char *in, size_t *len_out, size_t len_in, const MOBIHuffCdic *huffcdic);
#endif

18
app/src/main/cpp/libmobi/src/config.h vendored Normal file
View file

@ -0,0 +1,18 @@
/** @file src/config.h
*
* Copyright (c) 2014 Bartek Fabiszewski
* http://www.fabiszewski.net
*
* This file is part of libmobi.
* Licensed under LGPL, either version 3, or any later.
* See <http://www.gnu.org/licenses/>
*/
#ifndef mobi_config_h
#define mobi_config_h
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#endif

159
app/src/main/cpp/libmobi/src/debug.c vendored Normal file
View file

@ -0,0 +1,159 @@
/** @file debug.c
* @brief Debugging functions, enable by running configure --enable-debug
*
* Copyright (c) 2014 Bartek Fabiszewski
* http://www.fabiszewski.net
*
* This file is part of libmobi.
* Licensed under LGPL, either version 3, or any later.
* See <http://www.gnu.org/licenses/>
*/
#include <stdlib.h>
#include "debug.h"
#include "index.h"
/**
@brief Debugging wrapper for free(void *ptr)
@param[in] ptr Pointer
@param[in] file Calling file
@param[in] line Calling line
*/
void debug_free(void *ptr, const char *file, const int line) {
printf("%s:%d: free(%p)\n",file, line, ptr);
(free)(ptr);
}
/**
@brief Debugging wrapper for malloc(size_t size)
@param[in] size Size of memory
@param[in] file Calling file
@param[in] line Calling line
@return A pointer to the allocated memory block on success, NULL on failure
*/
void *debug_malloc(const size_t size, const char *file, const int line) {
void *ptr = (malloc)(size);
printf("%s:%d: malloc(%d)=%p\n", file, line, (int)size, ptr);
return ptr;
}
/**
@brief Debugging wrapper for realloc(void* ptr, size_t size)
@param[in] ptr Pointer
@param[in] size Size of memory
@param[in] file Calling file
@param[in] line Calling line
@return A pointer to the reallocated memory block on success, NULL on failure
*/
void *debug_realloc(void *ptr, const size_t size, const char *file, const int line) {
printf("%s:%d: realloc(%p", file, line, ptr);
void *rptr = (realloc)(ptr, size);
printf(", %d)=%p\n", (int)size, rptr);
return rptr;
}
/**
@brief Debugging wrapper for calloc(size_t num, size_t size)
@param[in] num Number of elements to allocate
@param[in] size Size of each element
@param[in] file Calling file
@param[in] line Calling line
@return A pointer to the allocated memory block on success, NULL on failure
*/
void *debug_calloc(const size_t num, const size_t size, const char *file, const int line) {
void *ptr = (calloc)(num, size);
printf("%s:%d: calloc(%d, %d)=%p\n", file, line, (int)num, (int)size, ptr);
return ptr;
}
/**
@brief Dump index values
@param[in] indx Parsed index
*/
void print_indx(const MOBIIndx *indx) {
if (indx == NULL) { return; }
for (size_t i = 0; i < indx->entries_count; i++) {
MOBIIndexEntry e = indx->entries[i];
printf("entry[%zu]: \"%s\"\n", i, e.label);
for (size_t j = 0; j < e.tags_count; j++) {
MOBIIndexTag t = e.tags[j];
printf(" tag[%zu] ", t.tagid);
for (size_t k = 0; k < t.tagvalues_count; k++) {
printf("[%u] ", t.tagvalues[k]);
}
printf("\n");
}
}
}
/**
@brief Dump inflections index (old version)
@param[in] indx Parsed index
*/
void print_indx_infl_old(const MOBIIndx *indx) {
if (indx == NULL) { return; }
for (size_t i = 0; i < indx->entries_count; i++) {
MOBIIndexEntry e = indx->entries[i];
printf("entry[%zu]: \"%s\"\n", i, e.label);
for (size_t j = 0; j < e.tags_count; j++) {
MOBIIndexTag t = e.tags[j];
printf(" tag[%zu] ", t.tagid);
if (t.tagid == 7) {
for (size_t k = 0; k < t.tagvalues_count; k += 2) {
uint32_t len = t.tagvalues[k];
uint32_t offset = t.tagvalues[k + 1];
char *string = mobi_get_cncx_string_flat(indx->cncx_record, offset, len);
if (string) {
printf("\"%s\" [%u] [%u]", string, len, offset);
free(string);
}
}
} else {
for (size_t k = 0; k < t.tagvalues_count; k++) {
printf("[%u] ", t.tagvalues[k]);
}
}
printf("\n");
}
}
}
/**
@brief Dump orthographic index (old version)
@param[in] indx Parsed index
*/
void print_indx_orth_old(const MOBIIndx *indx) {
if (indx == NULL) { return; }
for (size_t i = 0; i < indx->entries_count; i++) {
MOBIIndexEntry e = indx->entries[i];
printf("entry[%zu]: \"%s\"\n", i, e.label);
for (size_t j = 0; j < e.tags_count; j++) {
MOBIIndexTag t = e.tags[j];
printf(" tag[%zu] ", t.tagid);
if (t.tagid >= 69) {
for (size_t k = 0; k < t.tagvalues_count; k++) {
uint32_t offset = t.tagvalues[k];
char *string = mobi_get_cncx_string(indx->cncx_record, offset);
if (string) {
printf("\"%s\" [%u] ", string, t.tagvalues[k]);
free(string);
}
}
} else {
for (size_t k = 0; k < t.tagvalues_count; k++) {
printf("[%u] ", t.tagvalues[k]);
}
}
printf("\n");
}
}
}

57
app/src/main/cpp/libmobi/src/debug.h vendored Normal file
View file

@ -0,0 +1,57 @@
/** @file debug.h
*
* Copyright (c) 2014 Bartek Fabiszewski
* http://www.fabiszewski.net
*
* This file is part of libmobi.
* Licensed under LGPL, either version 3, or any later.
* See <http://www.gnu.org/licenses/>
*/
#ifndef libmobi_debug_h
#define libmobi_debug_h
#include "config.h"
#include "mobi.h"
#ifndef MOBI_DEBUG
#define MOBI_DEBUG 0 /**< Turn on debugging, set this on by running "configure --enable-debug" */
#endif
#if MOBI_DEBUG_ALLOC
/**
@defgroup mobi_debug Debug wrappers for memory allocation functions
Set this on by running "configure --enable-debug-alloc"
@{
*/
#define free(x) debug_free(x, __FILE__, __LINE__)
#define malloc(x) debug_malloc(x, __FILE__, __LINE__)
#define realloc(x, y) debug_realloc(x, y, __FILE__, __LINE__)
#define calloc(x, y) debug_calloc(x, y, __FILE__, __LINE__)
/** @} */
#endif
void debug_free(void *ptr, const char *file, const int line);
void *debug_malloc(const size_t size, const char *file, const int line);
void *debug_realloc(void *ptr, const size_t size, const char *file, const int line);
void *debug_calloc(const size_t num, const size_t size, const char *file, const int line);
void print_indx(const MOBIIndx *indx);
void print_indx_infl_old(const MOBIIndx *indx);
void print_indx_orth_old(const MOBIIndx *indx);
/**
@brief Macro for printing debug info to stderr. Wrapper for fprintf
@param[in] fmt Format
@param[in] ... Additional arguments
*/
#if (MOBI_DEBUG)
#define debug_print(fmt, ...) { \
fprintf(stderr, "%s:%d:%s(): " fmt, __FILE__, \
__LINE__, __func__, __VA_ARGS__); \
}
#else
#define debug_print(fmt, ...)
#endif
#endif

1515
app/src/main/cpp/libmobi/src/encryption.c vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,47 @@
/** @file encryption.h
*
* Copyright (c) 2014 Bartek Fabiszewski
* http://www.fabiszewski.net
*
* This file is part of libmobi.
* Licensed under LGPL, either version 3, or any later.
* See <http://www.gnu.org/licenses/>
*/
#ifndef mobi_encryption_h
#define mobi_encryption_h
#include "config.h"
#include "mobi.h"
#include "buffer.h"
/**
@brief Drm cookie data
*/
typedef struct {
unsigned char *pid; /**< PIDs for decryption, NULL if not set */
uint32_t valid_from; /**< validity period start time, unix time in minutes, 0 if not set */
uint32_t valid_to; /**< validity period end time, unix time in minutes, MOBI_NOTSET if not set */
} MOBICookie;
/**
@brief Drm data
*/
typedef struct {
unsigned char *key; /**< key for decryption, NULL if not set */
uint32_t cookies_count; /**< Cookies count */
MOBICookie **cookies; /**< DRM cookie */
} MOBIDrm;
void mobi_free_drm(MOBIData *m);
MOBI_RET mobi_buffer_decrypt(unsigned char *out, const unsigned char *in, const size_t length, const MOBIData *m);
MOBI_RET mobi_drmkey_set(MOBIData *m, const char *pid);
MOBI_RET mobi_drmkey_set_serial(MOBIData *m, const char *serial);
MOBI_RET mobi_drmkey_delete(MOBIData *m);
MOBI_RET mobi_voucher_add(MOBIData *m, const char *serial, const time_t valid_from, const time_t valid_to,
const MOBIExthTag *tamperkeys, const size_t tamperkeys_count);
MOBI_RET mobi_drm_serialize_v1(MOBIBuffer *buf, const MOBIData *m);
MOBI_RET mobi_drm_serialize_v2(MOBIBuffer *buf, const MOBIData *m);
#endif /* defined(mobi_encryption_h) */

1092
app/src/main/cpp/libmobi/src/index.c vendored Normal file

File diff suppressed because it is too large Load diff

128
app/src/main/cpp/libmobi/src/index.h vendored Normal file
View file

@ -0,0 +1,128 @@
/** @file index.h
*
* Copyright (c) 2014 Bartek Fabiszewski
* http://www.fabiszewski.net
*
* This file is part of libmobi.
* Licensed under LGPL, either version 3, or any later.
* See <http://www.gnu.org/licenses/>
*/
#ifndef mobi_index_h
#define mobi_index_h
#include "config.h"
#include "structure.h"
#include "mobi.h"
/**
@defgroup index_tag Predefined tag arrays: {tagid, tagindex} for mobi_get_indxentry_tagvalue()
@{
*/
#define INDX_TAG_GUIDE_TITLE_CNCX (unsigned[]) {1, 0} /**< Guide title CNCX offset */
#define INDX_TAG_NCX_FILEPOS (unsigned[]) {1, 0} /**< NCX filepos offset */
#define INDX_TAG_NCX_TEXT_CNCX (unsigned[]) {3, 0} /**< NCX text CNCX offset */
#define INDX_TAG_NCX_LEVEL (unsigned[]) {4, 0} /**< NCX level */
#define INDX_TAG_NCX_KIND_CNCX (unsigned[]) {5, 0} /**< NCX kind CNCX offset */
#define INDX_TAG_NCX_POSFID (unsigned[]) {6, 0} /**< NCX pos:fid */
#define INDX_TAG_NCX_POSOFF (unsigned[]) {6, 1} /**< NCX pos:off */
#define INDX_TAG_NCX_PARENT (unsigned[]) {21, 0} /**< NCX parent */
#define INDX_TAG_NCX_CHILD_START (unsigned[]) {22, 0} /**< NCX start child */
#define INDX_TAG_NCX_CHILD_END (unsigned[]) {23, 0} /**< NCX last child */
#define INDX_TAG_SKEL_COUNT (unsigned[]) {1, 0} /**< Skel fragments count */
#define INDX_TAG_SKEL_POSITION (unsigned[]) {6, 0} /**< Skel position */
#define INDX_TAG_SKEL_LENGTH (unsigned[]) {6, 1} /**< Skel length */
#define INDX_TAG_FRAG_AID_CNCX (unsigned[]) {2, 0} /**< Frag aid CNCX offset */
#define INDX_TAG_FRAG_FILE_NR (unsigned[]) {3, 0} /**< Frag file number */
#define INDX_TAG_FRAG_SEQUENCE_NR (unsigned[]) {4, 0} /**< Frag sequence number */
#define INDX_TAG_FRAG_POSITION (unsigned[]) {6, 0} /**< Frag position */
#define INDX_TAG_FRAG_LENGTH (unsigned[]) {6, 1} /**< Frag length */
#define INDX_TAG_ORTH_POSITION (unsigned[]) {1, 0} /**< Orth entry start position */
#define INDX_TAG_ORTH_LENGTH (unsigned[]) {2, 0} /**< Orth entry end position */
#define INDX_TAGARR_ORTH_INFL 42 /**< Inflection groups for orth entry */
#define INDX_TAGARR_INFL_GROUPS 5 /**< Inflection groups in infl index */
#define INDX_TAGARR_INFL_PARTS_V2 26 /**< Inflection particles in infl index */
#define INDX_TAGARR_INFL_PARTS_V1 7 /**< Inflection particles in old type infl index */
/** @} */
#define INDX_LABEL_SIZEMAX 1000 /**< Max size of index label */
#define INDX_INFLTAG_SIZEMAX 25000 /**< Max size of inflections tags per entry */
#define INDX_INFLBUF_SIZEMAX 500 /**< Max size of index label */
#define INDX_INFLSTRINGS_MAX 500 /**< Max number of inflected strings */
#define ORDT_RECORD_MAXCNT 256 /* max entries count in old ordt */
#define CNCX_RECORD_MAXCNT 0xf /* max entries count */
#define INDX_RECORD_MAXCNT 10000 /* max index entries per record */
#define INDX_TOTAL_MAXCNT ((size_t) INDX_RECORD_MAXCNT * 0xffff) /* max total index entries */
#define INDX_NAME_SIZEMAX 0xff
/**
@brief Maximum value of tag values in index entry (MOBIIndexTag)
*/
#define INDX_TAGVALUES_MAX 100
/**
@brief Tag entries in TAGX section (for internal INDX parsing)
*/
typedef struct {
uint8_t tag; /**< Tag */
uint8_t values_count; /**< Number of values */
uint8_t bitmask; /**< Bitmask */
uint8_t control_byte; /**< EOF control byte */
} TAGXTags;
/**
@brief Parsed TAGX section (for internal INDX parsing)
TAGX tags hold metadata of index entries.
It is present in the first index record.
*/
typedef struct {
TAGXTags *tags; /**< Array of tag entries */
size_t tags_count; /**< Number of tag entries */
size_t control_byte_count; /**< Number of control bytes */
} MOBITagx;
/**
@brief Parsed IDXT section (for internal INDX parsing)
IDXT section holds offsets to index entries
*/
typedef struct {
uint32_t *offsets; /**< Offsets to index entries */
size_t offsets_count; /**< Offsets count */
} MOBIIdxt;
/**
@brief Parsed ORDT sections (for internal INDX parsing)
ORDT sections hold data for decoding index labels.
It is mapping of encoded chars to unicode.
*/
typedef struct {
uint8_t *ordt1; /**< ORDT1 offsets */
uint16_t *ordt2; /**< ORDT2 offsets */
size_t type; /**< Type (0: 16, 1: 8 bit offsets) */
size_t ordt1_pos; /**< Offset of ORDT1 data */
size_t ordt2_pos; /**< Offset of ORDT2 data */
size_t offsets_count; /**< Offsets count */
} MOBIOrdt;
MOBI_RET mobi_parse_index(const MOBIData *m, MOBIIndx *indx, const size_t indx_record_number);
MOBI_RET mobi_parse_indx(const MOBIPdbRecord *indx_record, MOBIIndx *indx, MOBITagx *tagx, MOBIOrdt *ordt);
MOBI_RET mobi_get_indxentry_tagvalue(uint32_t *tagvalue, const MOBIIndexEntry *entry, const unsigned tag_arr[]);
size_t mobi_get_indxentry_tagarray(uint32_t **tagarr, const MOBIIndexEntry *entry, const size_t tagid);
bool mobi_indx_has_tag(const MOBIIndx *indx, const size_t tagid);
char * mobi_get_cncx_string(const MOBIPdbRecord *cncx_record, const uint32_t cncx_offset);
char * mobi_get_cncx_string_utf8(const MOBIPdbRecord *cncx_record, const uint32_t cncx_offset, MOBIEncoding cncx_encoding);
char * mobi_get_cncx_string_flat(const MOBIPdbRecord *cncx_record, const uint32_t cncx_offset, const size_t length);
MOBI_RET mobi_decode_infl(unsigned char *decoded, int *decoded_size, const unsigned char *rule);
MOBI_RET mobi_trie_insert_infl(MOBITrie **root, const MOBIIndx *indx, size_t i);
size_t mobi_trie_get_inflgroups(char **infl_strings, MOBITrie * const root, const char *string);
#endif

444
app/src/main/cpp/libmobi/src/memory.c vendored Normal file
View file

@ -0,0 +1,444 @@
/** @file memory.c
* @brief Functions for initializing and releasing structures and data containers
*
* Copyright (c) 2014 Bartek Fabiszewski
* http://www.fabiszewski.net
*
* This file is part of libmobi.
* Licensed under LGPL, either version 3, or any later.
* See <http://www.gnu.org/licenses/>
*/
#include <stdlib.h>
#include "memory.h"
#include "debug.h"
#include "util.h"
/**
@brief Initializer for MOBIData structure
It allocates memory for structure.
Memory should be freed with mobi_free().
@return MOBIData on success, NULL otherwise
*/
MOBIData * mobi_init(void) {
MOBIData *m = NULL;
m = calloc(1, sizeof(MOBIData));
if (m == NULL) { return NULL; }
m->use_kf8 = true;
m->kf8_boundary_offset = MOBI_NOTSET;
m->drm_key = NULL;
m->ph = NULL;
m->rh = NULL;
m->mh = NULL;
m->eh = NULL;
m->rec = NULL;
m->next = NULL;
m->internals = NULL;
return m;
}
/**
@brief Free MOBIMobiHeader structure
@param[in] mh MOBIMobiHeader structure
*/
void mobi_free_mh(MOBIMobiHeader *mh) {
if (mh == NULL) {
return;
}
free(mh->header_length);
free(mh->mobi_type);
free(mh->text_encoding);
free(mh->uid);
free(mh->version);
free(mh->orth_index);
free(mh->infl_index);
free(mh->names_index);
free(mh->keys_index);
free(mh->extra0_index);
free(mh->extra1_index);
free(mh->extra2_index);
free(mh->extra3_index);
free(mh->extra4_index);
free(mh->extra5_index);
free(mh->non_text_index);
free(mh->full_name_offset);
free(mh->full_name_length);
free(mh->locale);
free(mh->dict_input_lang);
free(mh->dict_output_lang);
free(mh->min_version);
free(mh->image_index);
free(mh->huff_rec_index);
free(mh->huff_rec_count);
free(mh->datp_rec_index);
free(mh->datp_rec_count);
free(mh->exth_flags);
free(mh->unknown6);
free(mh->drm_offset);
free(mh->drm_count);
free(mh->drm_size);
free(mh->drm_flags);
free(mh->fdst_index);
free(mh->first_text_index);
free(mh->last_text_index);
free(mh->fdst_section_count);
//free(mh->unknown9);
free(mh->fcis_index);
free(mh->fcis_count);
free(mh->flis_index);
free(mh->flis_count);
free(mh->unknown10);
free(mh->unknown11);
free(mh->srcs_index);
free(mh->srcs_count);
free(mh->unknown12);
free(mh->unknown13);
free(mh->extra_flags);
free(mh->ncx_index);
free(mh->fragment_index);
free(mh->skeleton_index);
free(mh->unknown14);
free(mh->unknown15);
free(mh->datp_index);
free(mh->guide_index);
free(mh->unknown16);
free(mh->unknown17);
free(mh->unknown18);
free(mh->unknown19);
free(mh->unknown20);
free(mh->full_name);
free(mh);
mh = NULL;
}
/**
@brief Free all MOBIPdbRecord structures and its respective data attached to MOBIData structure
Each MOBIPdbRecord structure holds metadata and data for each pdb record
@param[in,out] m MOBIData structure
*/
void mobi_free_rec(MOBIData *m) {
MOBIPdbRecord *curr, *tmp;
curr = m->rec;
while (curr != NULL) {
tmp = curr;
curr = curr->next;
free(tmp->data);
free(tmp);
tmp = NULL;
}
m->rec = NULL;
}
/**
@brief Free all MOBIExthHeader structures and its respective data attached to MOBIData structure
Each MOBIExthHeader structure holds metadata and data for each EXTH record
@param[in,out] m MOBIData structure
*/
void mobi_free_eh(MOBIData *m) {
MOBIExthHeader *curr, *tmp;
curr = m->eh;
while (curr != NULL) {
tmp = curr;
curr = curr->next;
free(tmp->data);
free(tmp);
tmp = NULL;
}
m->eh = NULL;
}
/**
@brief Free MOBIData structure for currenly unused hybrid part and all its children
@param[in] m MOBIData structure
*/
void mobi_free_next(MOBIData *m) {
if (m && m->next) {
mobi_free_mh(m->next->mh);
mobi_free_eh(m->next);
free(m->next->rh);
free(m->next);
m->next = NULL;
}
}
/**
@brief Free MOBIData structure and all its children
@param[in] m MOBIData structure
*/
void mobi_free(MOBIData *m) {
if (m == NULL) {
return;
}
mobi_free_mh(m->mh);
mobi_free_eh(m);
mobi_free_rec(m);
free(m->ph);
free(m->rh);
mobi_free_next(m);
mobi_free_internals(m);
free(m);
m = NULL;
}
/**
@brief Initialize and return MOBIHuffCdic structure.
MOBIHuffCdic structure holds parsed data from HUFF, CDIC records.
It is used for huffman decompression.
Initialized structure is a child of MOBIData structure.
It must be freed with mobi_free_huffcdic().
@return MOBIHuffCdic on success, NULL otherwise
*/
MOBIHuffCdic * mobi_init_huffcdic(void) {
MOBIHuffCdic *huffcdic = calloc(1, sizeof(MOBIHuffCdic));
if (huffcdic == NULL) {
debug_print("%s", "Memory allocation for huffcdic structure failed\n");
return NULL;
}
return huffcdic;
}
/**
@brief Free MOBIHuffCdic structure and all its children
@param[in] huffcdic MOBIData structure
*/
void mobi_free_huffcdic(MOBIHuffCdic *huffcdic) {
if (huffcdic == NULL) {
return;
}
free(huffcdic->symbol_offsets);
free(huffcdic->symbols);
free(huffcdic);
huffcdic = NULL;
}
/**
@brief Initialize and return MOBIRawml structure.
MOBIRawml structure holds parsed text record metadata.
It is used in the process of parsing rawml text data.
It must be freed with mobi_free_rawml().
@param[in] m Initialized MOBIData structure
@return MOBIRawml on success, NULL otherwise
*/
MOBIRawml * mobi_init_rawml(const MOBIData *m) {
MOBIRawml *rawml = malloc(sizeof(MOBIRawml));
if (rawml == NULL) {
debug_print("%s", "Memory allocation failed for rawml structure\n");
return NULL;
}
rawml->version = mobi_get_fileversion(m);
rawml->fdst = NULL;
rawml->skel = NULL;
rawml->frag = NULL;
rawml->guide = NULL;
rawml->ncx = NULL;
rawml->orth = NULL;
rawml->infl = NULL;
rawml->flow = NULL;
rawml->markup = NULL;
rawml->resources = NULL;
return rawml;
}
/**
@brief Free MOBIFdst structure and all its children
@param[in] fdst MOBIFdst structure
*/
void mobi_free_fdst(MOBIFdst *fdst) {
if (fdst == NULL) {
return;
}
if (fdst->fdst_section_count > 0) {
free(fdst->fdst_section_starts);
free(fdst->fdst_section_ends);
}
free(fdst);
fdst = NULL;
}
/**
@brief Initialize and return MOBIIndx structure.
MOBIIndx structure holds INDX index record entries.
Must be freed with mobi_free_indx()
@return MOBIIndx on success, NULL otherwise
*/
MOBIIndx * mobi_init_indx(void) {
MOBIIndx *indx = calloc(1, sizeof(MOBIIndx));
if (indx == NULL) {
debug_print("%s", "Memory allocation failed for indx structure\n");
return NULL;
}
indx->entries = NULL;
indx->cncx_record = NULL;
indx->orth_index_name = NULL;
return indx;
}
/**
@brief Free index entries data and all its children
@param[in] indx MOBIIndx structure that holds indx->entries
*/
void mobi_free_index_entries(MOBIIndx *indx) {
if (indx == NULL || indx->entries == NULL) {
return;
}
size_t i = 0;
while (i < indx->entries_count) {
free(indx->entries[i].label);
if (indx->entries[i].tags != NULL) {
size_t j = 0;
while (j < indx->entries[i].tags_count) {
free(indx->entries[i].tags[j++].tagvalues);
}
free(indx->entries[i].tags);
}
i++;
}
free(indx->entries);
indx->entries = NULL;
}
/**
@brief Free MOBIIndx structure and all its children
@param[in] indx MOBIIndx structure that holds indx->entries
*/
void mobi_free_indx(MOBIIndx *indx) {
if (indx == NULL) {
return;
}
mobi_free_index_entries(indx);
if (indx->orth_index_name) {
free(indx->orth_index_name);
}
free(indx);
indx = NULL;
}
/**
@brief Free MOBITagx structure and all its children
@param[in] tagx MOBITagx structure
*/
void mobi_free_tagx(MOBITagx *tagx) {
if (tagx == NULL) {
return;
}
free(tagx->tags);
free(tagx);
tagx = NULL;
}
/**
@brief Free MOBIOrdt structure and all its children
@param[in] ordt MOBIOrdt structure
*/
void mobi_free_ordt(MOBIOrdt *ordt) {
if (ordt == NULL) {
return;
}
free(ordt->ordt1);
free(ordt->ordt2);
free(ordt);
ordt = NULL;
}
/**
@brief Free MOBIPart structure
Pointer to data may point to memory area also used by record->data.
So we need a flag to leave the memory allocated, while freeing MOBIPart structure
@param[in] part MOBIPart structure
@param[in] free_data Flag, if set - a pointer to part->data is also released, otherwise not released
*/
void mobi_free_part(MOBIPart *part, int free_data) {
MOBIPart *curr, *tmp;
curr = part;
while (curr != NULL) {
tmp = curr;
curr = curr->next;
if (free_data) { free(tmp->data); }
free(tmp);
}
part = NULL;
}
/**
@brief Free MOBIPart structure for opf and ncx data
@param[in] part MOBIPart structure
*/
void mobi_free_opf_data(MOBIPart *part) {
while (part != NULL) {
if (part->type == T_NCX || part->type == T_OPF) {
free(part->data);
}
part = part->next;
}
}
/**
@brief Free MOBIPart structure for decoded font data
@param[in] part MOBIPart structure
*/
void mobi_free_font_data(MOBIPart *part) {
while (part != NULL) {
if (part->type == T_OTF || part->type == T_TTF) {
free(part->data);
}
part = part->next;
}
}
/**
@brief Free MOBIRawml structure allocated by mobi_init_rawml()
Pointer to data may point to memory area also used by record->data.
So we need a flag to leave the memory allocated, while freeing MOBIPart structure
@param[in] rawml MOBIRawml structure
*/
void mobi_free_rawml(MOBIRawml *rawml) {
if (rawml == NULL) {
return;
}
mobi_free_fdst(rawml->fdst);
mobi_free_indx(rawml->skel);
mobi_free_indx(rawml->frag);
mobi_free_indx(rawml->guide);
mobi_free_indx(rawml->ncx);
mobi_free_indx(rawml->orth);
mobi_free_indx(rawml->infl);
mobi_free_part(rawml->flow, true);
mobi_free_part(rawml->markup,true);
/* do not free resources data, these are links to records data */
/* only free opf and ncx data */
mobi_free_opf_data(rawml->resources);
/* and free decoded fonts data */
mobi_free_font_data(rawml->resources);
mobi_free_part(rawml->resources, false);
free(rawml);
rawml = NULL;
}

33
app/src/main/cpp/libmobi/src/memory.h vendored Normal file
View file

@ -0,0 +1,33 @@
/** @file memory.h
*
* Copyright (c) 2014 Bartek Fabiszewski
* http://www.fabiszewski.net
*
* This file is part of libmobi.
* Licensed under LGPL, either version 3, or any later.
* See <http://www.gnu.org/licenses/>
*/
#ifndef libmobi_memory_h
#define libmobi_memory_h
#include "config.h"
#include "index.h"
#include "compression.h"
#include "mobi.h"
void mobi_free_mh(MOBIMobiHeader *mh);
void mobi_free_rec(MOBIData *m);
void mobi_free_eh(MOBIData *m);
void mobi_free_next(MOBIData *m);
MOBIHuffCdic * mobi_init_huffcdic(void);
void mobi_free_huffcdic(MOBIHuffCdic *huffcdic);
MOBIIndx * mobi_init_indx(void);
void mobi_free_indx(MOBIIndx *indx);
void mobi_free_tagx(MOBITagx *tagx);
void mobi_free_ordt(MOBIOrdt *ordt);
void mobi_free_index_entries(MOBIIndx *indx);
#endif

864
app/src/main/cpp/libmobi/src/meta.c vendored Normal file
View file

@ -0,0 +1,864 @@
/** @file meta.c
* @brief Functions for metadata manipulation
*
* Copyright (c) 2016 Bartek Fabiszewski
* http://www.fabiszewski.net
*
* This file is part of libmobi.
* Licensed under LGPL, either version 3, or any later.
* See <http://www.gnu.org/licenses/>
*/
#define _GNU_SOURCE 1
#ifndef __USE_BSD
#define __USE_BSD /* for strdup on linux/glibc */
#endif
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "meta.h"
#include "util.h"
/**
@brief Get document metadata from exth string
Returned string must be deallocated by caller
@param[in] m MOBIData structure with loaded data
@param[in] exth_tag MOBIExthTag
@return Pointer to null terminated string, NULL on failure
*/
char * mobi_meta_get_exthstring(const MOBIData *m, const MOBIExthTag exth_tag) {
char *string = NULL;
MOBIExthHeader *exth;
MOBIExthHeader *start = NULL;
while ((exth = mobi_next_exthrecord_by_tag(m, exth_tag, &start))) {
char *exth_string = mobi_decode_exthstring(m, exth->data, exth->size);
if (string == NULL) {
string = exth_string;
} else if (exth_string) {
const char *separator = "; ";
size_t new_length = strlen(string) + strlen(exth_string) + strlen(separator) + 1;
char *new = malloc(new_length);
if (new == NULL) {
free(string);
free(exth_string);
return NULL;
}
strcpy(new, string);
strcat(new, separator);
strcat(new, exth_string);
free(string);
free(exth_string);
string = new;
}
if (start == NULL) {
break;
}
}
return string;
}
/**
@brief Get document title metadata
Returned string must be deallocated by caller
@param[in] m MOBIData structure with loaded data
@return Pointer to null terminated string, NULL on failure
*/
char * mobi_meta_get_title(const MOBIData *m) {
if (m == NULL) {
return NULL;
}
char *title = mobi_meta_get_exthstring(m, EXTH_UPDATEDTITLE);
if (title) {
return title;
}
char fullname[MOBI_TITLE_SIZEMAX + 1];
MOBI_RET ret = mobi_get_fullname(m, fullname, MOBI_TITLE_SIZEMAX);
if (ret == MOBI_SUCCESS) {
title = strdup(fullname);
} else if (m->ph) {
title = strdup(m->ph->name);
}
return title;
}
/**
@brief Add document title metadata
@param[in,out] m MOBIData structure with loaded data
@param[in] title String value
@return Pointer to null terminated string, NULL on failure
*/
MOBI_RET mobi_meta_add_title(MOBIData *m, const char *title) {
if (title == NULL) {
return MOBI_PARAM_ERR;
}
size_t size = min(strlen(title), UINT32_MAX);
return mobi_add_exthrecord(m, EXTH_UPDATEDTITLE, (uint32_t) size, title);
}
/**
@brief Delete all title metadata
@param[in,out] m MOBIData structure with loaded data
@return Pointer to null terminated string, NULL on failure
*/
MOBI_RET mobi_meta_delete_title(MOBIData *m) {
if (mobi_exists_mobiheader(m) && m->mh->full_name) {
m->mh->full_name[0] = '\0';
}
if (mobi_is_hybrid(m) && mobi_exists_mobiheader(m->next) && m->next->mh->full_name) {
m->next->mh->full_name[0] = '\0';
}
return mobi_delete_exthrecord_by_tag(m, EXTH_UPDATEDTITLE);
}
/**
@brief Set document title metadata
Replaces all title metadata with new string
@param[in,out] m MOBIData structure with loaded data
@param[in] title String value
@return Pointer to null terminated string, NULL on failure
*/
MOBI_RET mobi_meta_set_title(MOBIData *m, const char *title) {
if (title == NULL) {
return MOBI_PARAM_ERR;
}
/* set title in mobi header */
MOBI_RET ret = mobi_set_fullname(m, title);
if (ret != MOBI_SUCCESS) {
return ret;
}
/* set title in palm header */
ret = mobi_set_pdbname(m, title);
if (ret != MOBI_SUCCESS) {
return ret;
}
/* set title in exth header */
ret = mobi_delete_exthrecord_by_tag(m, EXTH_UPDATEDTITLE);
if (ret == MOBI_SUCCESS) {
ret = mobi_meta_add_title(m, title);
}
return ret;
}
/**
@brief Get document author metadata
Returned string must be deallocated by caller
@param[in] m MOBIData structure with loaded data
@return Pointer to null terminated string, NULL on failure
*/
char * mobi_meta_get_author(const MOBIData *m) {
return mobi_meta_get_exthstring(m, EXTH_AUTHOR);
}
/**
@brief Add document author metadata
@param[in,out] m MOBIData structure with loaded data
@param[in] author String value
@return Pointer to null terminated string, NULL on failure
*/
MOBI_RET mobi_meta_add_author(MOBIData *m, const char *author) {
if (author == NULL) {
return MOBI_PARAM_ERR;
}
size_t size = min(strlen(author), UINT32_MAX);
return mobi_add_exthrecord(m, EXTH_AUTHOR, (uint32_t) size, author);
}
/**
@brief Delete all author metadata
@param[in,out] m MOBIData structure with loaded data
@return Pointer to null terminated string, NULL on failure
*/
MOBI_RET mobi_meta_delete_author(MOBIData *m) {
return mobi_delete_exthrecord_by_tag(m, EXTH_AUTHOR);
}
/**
@brief Set document author metadata
Replaces all author metadata with new string
@param[in,out] m MOBIData structure with loaded data
@param[in] author String value
@return Pointer to null terminated string, NULL on failure
*/
MOBI_RET mobi_meta_set_author(MOBIData *m, const char *author) {
if (author == NULL) {
return MOBI_PARAM_ERR;
}
MOBI_RET ret = mobi_meta_delete_author(m);
if (ret == MOBI_SUCCESS) {
ret = mobi_meta_add_author(m, author);
}
return ret;
}
/**
@brief Get document subject metadata
Returned string must be deallocated by caller
@param[in] m MOBIData structure with loaded data
@return Pointer to null terminated string, NULL on failure
*/
char * mobi_meta_get_subject(const MOBIData *m) {
return mobi_meta_get_exthstring(m, EXTH_SUBJECT);
}
/**
@brief Add document subject metadata
@param[in,out] m MOBIData structure with loaded data
@param[in] subject String value
@return Pointer to null terminated string, NULL on failure
*/
MOBI_RET mobi_meta_add_subject(MOBIData *m, const char *subject) {
if (subject == NULL) {
return MOBI_PARAM_ERR;
}
size_t size = min(strlen(subject), UINT32_MAX);
return mobi_add_exthrecord(m, EXTH_SUBJECT, (uint32_t) size, subject);
}
/**
@brief Delete all subject metadata
@param[in,out] m MOBIData structure with loaded data
@return Pointer to null terminated string, NULL on failure
*/
MOBI_RET mobi_meta_delete_subject(MOBIData *m) {
return mobi_delete_exthrecord_by_tag(m, EXTH_SUBJECT);
}
/**
@brief Set document subject metadata
Replaces all subject metadata with new string
@param[in,out] m MOBIData structure with loaded data
@param[in] subject String value
@return Pointer to null terminated string, NULL on failure
*/
MOBI_RET mobi_meta_set_subject(MOBIData *m, const char *subject) {
if (subject == NULL) {
return MOBI_PARAM_ERR;
}
MOBI_RET ret = mobi_meta_delete_subject(m);
if (ret == MOBI_SUCCESS) {
ret = mobi_meta_add_subject(m, subject);
}
return ret;
}
/**
@brief Get document publisher metadata
Returned string must be deallocated by caller
@param[in] m MOBIData structure with loaded data
@return Pointer to null terminated string, NULL on failure
*/
char * mobi_meta_get_publisher(const MOBIData *m) {
return mobi_meta_get_exthstring(m, EXTH_PUBLISHER);
}
/**
@brief Add document publisher metadata
@param[in,out] m MOBIData structure with loaded data
@param[in] publisher String value
@return Pointer to null terminated string, NULL on failure
*/
MOBI_RET mobi_meta_add_publisher(MOBIData *m, const char *publisher) {
if (publisher == NULL) {
return MOBI_PARAM_ERR;
}
size_t size = min(strlen(publisher), UINT32_MAX);
return mobi_add_exthrecord(m, EXTH_PUBLISHER, (uint32_t) size, publisher);
}
/**
@brief Delete all publisher metadata
@param[in,out] m MOBIData structure with loaded data
@return Pointer to null terminated string, NULL on failure
*/
MOBI_RET mobi_meta_delete_publisher(MOBIData *m) {
return mobi_delete_exthrecord_by_tag(m, EXTH_PUBLISHER);
}
/**
@brief Set document publisher metadata
Replaces all publisher metadata with new string
@param[in,out] m MOBIData structure with loaded data
@param[in] publisher String value
@return Pointer to null terminated string, NULL on failure
*/
MOBI_RET mobi_meta_set_publisher(MOBIData *m, const char *publisher) {
if (publisher == NULL) {
return MOBI_PARAM_ERR;
}
MOBI_RET ret = mobi_meta_delete_publisher(m);
if (ret == MOBI_SUCCESS) {
ret = mobi_meta_add_publisher(m, publisher);
}
return ret;
}
/**
@brief Get document publishing date metadata
Returned string must be deallocated by caller
@param[in] m MOBIData structure with loaded data
@return Pointer to null terminated string, NULL on failure
*/
char * mobi_meta_get_publishdate(const MOBIData *m) {
return mobi_meta_get_exthstring(m, EXTH_PUBLISHINGDATE);
}
/**
@brief Add document publishdate metadata
@param[in,out] m MOBIData structure with loaded data
@param[in] publishdate String value
@return Pointer to null terminated string, NULL on failure
*/
MOBI_RET mobi_meta_add_publishdate(MOBIData *m, const char *publishdate) {
if (publishdate == NULL) {
return MOBI_PARAM_ERR;
}
size_t size = min(strlen(publishdate), UINT32_MAX);
return mobi_add_exthrecord(m, EXTH_PUBLISHINGDATE, (uint32_t) size, publishdate);
}
/**
@brief Delete all publishdate metadata
@param[in,out] m MOBIData structure with loaded data
@return Pointer to null terminated string, NULL on failure
*/
MOBI_RET mobi_meta_delete_publishdate(MOBIData *m) {
return mobi_delete_exthrecord_by_tag(m, EXTH_PUBLISHINGDATE);
}
/**
@brief Set document publishdate metadata
Replaces all publishdate metadata with new string
@param[in,out] m MOBIData structure with loaded data
@param[in] publishdate String value
@return Pointer to null terminated string, NULL on failure
*/
MOBI_RET mobi_meta_set_publishdate(MOBIData *m, const char *publishdate) {
if (publishdate == NULL) {
return MOBI_PARAM_ERR;
}
MOBI_RET ret = mobi_meta_delete_publishdate(m);
if (ret == MOBI_SUCCESS) {
ret = mobi_meta_add_publishdate(m, publishdate);
}
return ret;
}
/**
@brief Get document description metadata
Returned string must be deallocated by caller
@param[in] m MOBIData structure with loaded data
@return Pointer to null terminated string, NULL on failure
*/
char * mobi_meta_get_description(const MOBIData *m) {
return mobi_meta_get_exthstring(m, EXTH_DESCRIPTION);
}
/**
@brief Add document description metadata
@param[in,out] m MOBIData structure with loaded data
@param[in] description String value
@return Pointer to null terminated string, NULL on failure
*/
MOBI_RET mobi_meta_add_description(MOBIData *m, const char *description) {
if (description == NULL) {
return MOBI_PARAM_ERR;
}
size_t size = min(strlen(description), UINT32_MAX);
return mobi_add_exthrecord(m, EXTH_DESCRIPTION, (uint32_t) size, description);
}
/**
@brief Delete all description metadata
@param[in,out] m MOBIData structure with loaded data
@return Pointer to null terminated string, NULL on failure
*/
MOBI_RET mobi_meta_delete_description(MOBIData *m) {
return mobi_delete_exthrecord_by_tag(m, EXTH_DESCRIPTION);
}
/**
@brief Set document description metadata
Replaces all description metadata with new string
@param[in,out] m MOBIData structure with loaded data
@param[in] description String value
@return Pointer to null terminated string, NULL on failure
*/
MOBI_RET mobi_meta_set_description(MOBIData *m, const char *description) {
if (description == NULL) {
return MOBI_PARAM_ERR;
}
MOBI_RET ret = mobi_meta_delete_description(m);
if (ret == MOBI_SUCCESS) {
ret = mobi_meta_add_description(m, description);
}
return ret;
}
/**
@brief Get document imprint metadata
Returned string must be deallocated by caller
@param[in] m MOBIData structure with loaded data
@return Pointer to null terminated string, NULL on failure
*/
char * mobi_meta_get_imprint(const MOBIData *m) {
return mobi_meta_get_exthstring(m, EXTH_IMPRINT);
}
/**
@brief Add document imprint metadata
@param[in,out] m MOBIData structure with loaded data
@param[in] imprint String value
@return Pointer to null terminated string, NULL on failure
*/
MOBI_RET mobi_meta_add_imprint(MOBIData *m, const char *imprint) {
if (imprint == NULL) {
return MOBI_PARAM_ERR;
}
size_t size = min(strlen(imprint), UINT32_MAX);
return mobi_add_exthrecord(m, EXTH_IMPRINT, (uint32_t) size, imprint);
}
/**
@brief Delete all imprint metadata
@param[in,out] m MOBIData structure with loaded data
@return Pointer to null terminated string, NULL on failure
*/
MOBI_RET mobi_meta_delete_imprint(MOBIData *m) {
return mobi_delete_exthrecord_by_tag(m, EXTH_IMPRINT);
}
/**
@brief Set document imprint metadata
Replaces all imprint metadata with new string
@param[in,out] m MOBIData structure with loaded data
@param[in] imprint String value
@return Pointer to null terminated string, NULL on failure
*/
MOBI_RET mobi_meta_set_imprint(MOBIData *m, const char *imprint) {
if (imprint == NULL) {
return MOBI_PARAM_ERR;
}
MOBI_RET ret = mobi_meta_delete_imprint(m);
if (ret == MOBI_SUCCESS) {
ret = mobi_meta_add_imprint(m, imprint);
}
return ret;
}
/**
@brief Get document contributor metadata
Returned string must be deallocated by caller
@param[in] m MOBIData structure with loaded data
@return Pointer to null terminated string, NULL on failure
*/
char * mobi_meta_get_contributor(const MOBIData *m) {
return mobi_meta_get_exthstring(m, EXTH_CONTRIBUTOR);
}
/**
@brief Add document contributor metadata
@param[in,out] m MOBIData structure with loaded data
@param[in] contributor String value
@return Pointer to null terminated string, NULL on failure
*/
MOBI_RET mobi_meta_add_contributor(MOBIData *m, const char *contributor) {
if (contributor == NULL) {
return MOBI_PARAM_ERR;
}
size_t size = min(strlen(contributor), UINT32_MAX);
return mobi_add_exthrecord(m, EXTH_CONTRIBUTOR, (uint32_t) size, contributor);
}
/**
@brief Delete all contributor metadata
@param[in,out] m MOBIData structure with loaded data
@return Pointer to null terminated string, NULL on failure
*/
MOBI_RET mobi_meta_delete_contributor(MOBIData *m) {
return mobi_delete_exthrecord_by_tag(m, EXTH_CONTRIBUTOR);
}
/**
@brief Set document contributor metadata
Replaces all contributor metadata with new string
@param[in,out] m MOBIData structure with loaded data
@param[in] contributor String value
@return Pointer to null terminated string, NULL on failure
*/
MOBI_RET mobi_meta_set_contributor(MOBIData *m, const char *contributor) {
if (contributor == NULL) {
return MOBI_PARAM_ERR;
}
MOBI_RET ret = mobi_meta_delete_contributor(m);
if (ret == MOBI_SUCCESS) {
ret = mobi_meta_add_contributor(m, contributor);
}
return ret;
}
/**
@brief Get document review metadata
Returned string must be deallocated by caller
@param[in] m MOBIData structure with loaded data
@return Pointer to null terminated string, NULL on failure
*/
char * mobi_meta_get_review(const MOBIData *m) {
return mobi_meta_get_exthstring(m, EXTH_REVIEW);
}
/**
@brief Add document review metadata
@param[in,out] m MOBIData structure with loaded data
@param[in] review String value
@return Pointer to null terminated string, NULL on failure
*/
MOBI_RET mobi_meta_add_review(MOBIData *m, const char *review) {
if (review == NULL) {
return MOBI_PARAM_ERR;
}
size_t size = min(strlen(review), UINT32_MAX);
return mobi_add_exthrecord(m, EXTH_REVIEW, (uint32_t) size, review);
}
/**
@brief Delete all review metadata
@param[in,out] m MOBIData structure with loaded data
@return Pointer to null terminated string, NULL on failure
*/
MOBI_RET mobi_meta_delete_review(MOBIData *m) {
return mobi_delete_exthrecord_by_tag(m, EXTH_REVIEW);
}
/**
@brief Set document review metadata
Replaces all review metadata with new string
@param[in,out] m MOBIData structure with loaded data
@param[in] review String value
@return Pointer to null terminated string, NULL on failure
*/
MOBI_RET mobi_meta_set_review(MOBIData *m, const char *review) {
if (review == NULL) {
return MOBI_PARAM_ERR;
}
MOBI_RET ret = mobi_meta_delete_review(m);
if (ret == MOBI_SUCCESS) {
ret = mobi_meta_add_review(m, review);
}
return ret;
}
/**
@brief Get document copyright metadata
Returned string must be deallocated by caller
@param[in] m MOBIData structure with loaded data
@return Pointer to null terminated string, NULL on failure
*/
char * mobi_meta_get_copyright(const MOBIData *m) {
return mobi_meta_get_exthstring(m, EXTH_RIGHTS);
}
/**
@brief Add document copyright metadata
@param[in,out] m MOBIData structure with loaded data
@param[in] copyright String value
@return Pointer to null terminated string, NULL on failure
*/
MOBI_RET mobi_meta_add_copyright(MOBIData *m, const char *copyright) {
if (copyright == NULL) {
return MOBI_PARAM_ERR;
}
size_t size = min(strlen(copyright), UINT32_MAX);
return mobi_add_exthrecord(m, EXTH_RIGHTS, (uint32_t) size, copyright);
}
/**
@brief Delete all copyright metadata
@param[in,out] m MOBIData structure with loaded data
@return Pointer to null terminated string, NULL on failure
*/
MOBI_RET mobi_meta_delete_copyright(MOBIData *m) {
return mobi_delete_exthrecord_by_tag(m, EXTH_RIGHTS);
}
/**
@brief Set document copyright metadata
Replaces all copyright metadata with new string
@param[in,out] m MOBIData structure with loaded data
@param[in] copyright String value
@return Pointer to null terminated string, NULL on failure
*/
MOBI_RET mobi_meta_set_copyright(MOBIData *m, const char *copyright) {
if (copyright == NULL) {
return MOBI_PARAM_ERR;
}
MOBI_RET ret = mobi_meta_delete_copyright(m);
if (ret == MOBI_SUCCESS) {
ret = mobi_meta_add_copyright(m, copyright);
}
return ret;
}
/**
@brief Get document ISBN metadata
Returned string must be deallocated by caller
@param[in] m MOBIData structure with loaded data
@return Pointer to null terminated string, NULL on failure
*/
char * mobi_meta_get_isbn(const MOBIData *m) {
return mobi_meta_get_exthstring(m, EXTH_ISBN);
}
/**
@brief Add document isbn metadata
@param[in,out] m MOBIData structure with loaded data
@param[in] isbn String value
@return Pointer to null terminated string, NULL on failure
*/
MOBI_RET mobi_meta_add_isbn(MOBIData *m, const char *isbn) {
if (isbn == NULL) {
return MOBI_PARAM_ERR;
}
size_t size = min(strlen(isbn), UINT32_MAX);
return mobi_add_exthrecord(m, EXTH_ISBN, (uint32_t) size, isbn);
}
/**
@brief Delete all isbn metadata
@param[in,out] m MOBIData structure with loaded data
@return Pointer to null terminated string, NULL on failure
*/
MOBI_RET mobi_meta_delete_isbn(MOBIData *m) {
return mobi_delete_exthrecord_by_tag(m, EXTH_ISBN);
}
/**
@brief Set document isbn metadata
Replaces all isbn metadata with new string
@param[in,out] m MOBIData structure with loaded data
@param[in] isbn String value
@return Pointer to null terminated string, NULL on failure
*/
MOBI_RET mobi_meta_set_isbn(MOBIData *m, const char *isbn) {
if (isbn == NULL) {
return MOBI_PARAM_ERR;
}
MOBI_RET ret = mobi_meta_delete_isbn(m);
if (ret == MOBI_SUCCESS) {
ret = mobi_meta_add_isbn(m, isbn);
}
return ret;
}
/**
@brief Get document ASIN metadata
Returned string must be deallocated by caller
@param[in] m MOBIData structure with loaded data
@return Pointer to null terminated string, NULL on failure
*/
char * mobi_meta_get_asin(const MOBIData *m) {
return mobi_meta_get_exthstring(m, EXTH_ASIN);
}
/**
@brief Add document asin metadata
@param[in,out] m MOBIData structure with loaded data
@param[in] asin String value
@return Pointer to null terminated string, NULL on failure
*/
MOBI_RET mobi_meta_add_asin(MOBIData *m, const char *asin) {
if (asin == NULL) {
return MOBI_PARAM_ERR;
}
size_t size = min(strlen(asin), UINT32_MAX);
return mobi_add_exthrecord(m, EXTH_ASIN, (uint32_t) size, asin);
}
/**
@brief Delete all asin metadata
@param[in,out] m MOBIData structure with loaded data
@return Pointer to null terminated string, NULL on failure
*/
MOBI_RET mobi_meta_delete_asin(MOBIData *m) {
return mobi_delete_exthrecord_by_tag(m, EXTH_ASIN);
}
/**
@brief Set document asin metadata
Replaces all asin metadata with new string
@param[in,out] m MOBIData structure with loaded data
@param[in] asin String value
@return Pointer to null terminated string, NULL on failure
*/
MOBI_RET mobi_meta_set_asin(MOBIData *m, const char *asin) {
if (asin == NULL) {
return MOBI_PARAM_ERR;
}
MOBI_RET ret = mobi_meta_delete_asin(m);
if (ret == MOBI_SUCCESS) {
ret = mobi_meta_add_asin(m, asin);
}
return ret;
}
/**
@brief Get document language code metadata
Locale strings are based on IANA language-subtag registry with some custom Mobipocket modifications.
See mobi_locale array.
Returned string must be deallocated by caller
@param[in] m MOBIData structure with loaded data
@return Pointer to null terminated string, NULL on failure
*/
char * mobi_meta_get_language(const MOBIData *m) {
if (m == NULL) {
return NULL;
}
char *lang = mobi_meta_get_exthstring(m, EXTH_LANGUAGE);
if(lang == NULL && m->mh && m->mh->locale && *m->mh->locale) {
const char *locale_string = mobi_get_locale_string(*m->mh->locale);
if (locale_string) {
lang = strdup(locale_string);
}
}
return lang;
}
/**
@brief Add document language code metadata
Locale strings are based on IANA language-subtag registry with some custom Mobipocket modifications.
See mobi_locale array.
@param[in,out] m MOBIData structure with loaded data
@param[in] language String value
@return Pointer to null terminated string, NULL on failure
*/
MOBI_RET mobi_meta_add_language(MOBIData *m, const char *language) {
if (language == NULL) {
return MOBI_PARAM_ERR;
}
size_t size = min(strlen(language), UINT32_MAX);
return mobi_add_exthrecord(m, EXTH_LANGUAGE, (uint32_t) size, language);
}
/**
@brief Delete all language code metadata
@param[in,out] m MOBIData structure with loaded data
@return Pointer to null terminated string, NULL on failure
*/
MOBI_RET mobi_meta_delete_language(MOBIData *m) {
if(mobi_exists_mobiheader(m) && m->mh->locale) {
*m->mh->locale = 0;
}
if(mobi_is_hybrid(m) && mobi_exists_mobiheader(m->next) && m->next->mh->locale) {
*m->next->mh->locale = 0;
}
return mobi_delete_exthrecord_by_tag(m, EXTH_LANGUAGE);
}
/**
@brief Set document language code metadata
Replaces all language metadata with new string
Locale strings are based on IANA language-subtag registry with some custom Mobipocket modifications.
See mobi_locale array.
@param[in,out] m MOBIData structure with loaded data
@param[in] language String value
@return Pointer to null terminated string, NULL on failure
*/
MOBI_RET mobi_meta_set_language(MOBIData *m, const char *language) {
if (language == NULL) {
return MOBI_PARAM_ERR;
}
MOBI_RET ret = mobi_meta_delete_language(m);
if (ret == MOBI_SUCCESS) {
ret = mobi_meta_add_language(m, language);
}
if(mobi_exists_mobiheader(m) && m->mh->locale) {
*m->mh->locale = (uint32_t) mobi_get_locale_number(language);
}
if(mobi_is_hybrid(m) && mobi_exists_mobiheader(m->next) && m->next->mh->locale) {
*m->next->mh->locale = (uint32_t) mobi_get_locale_number(language);
}
return ret;
}

17
app/src/main/cpp/libmobi/src/meta.h vendored Normal file
View file

@ -0,0 +1,17 @@
/** @file meta.h
*
* Copyright (c) 2016 Bartek Fabiszewski
* http://www.fabiszewski.net
*
* This file is part of libmobi.
* Licensed under LGPL, either version 3, or any later.
* See <http://www.gnu.org/licenses/>
*/
#ifndef libmobi_meta_h
#define libmobi_meta_h
#include "config.h"
#include "mobi.h"
#endif /* libmobi_meta_h */

5164
app/src/main/cpp/libmobi/src/miniz.c vendored Normal file

File diff suppressed because it is too large Load diff

24
app/src/main/cpp/libmobi/src/miniz.h vendored Normal file
View file

@ -0,0 +1,24 @@
/** @file miniz.h
* @brief header file for third party miniz.c, zlib replacement
*
* Copyright (c) 2014 Bartek Fabiszewski
* http://www.fabiszewski.net
*
* This file is part of libmobi.
* Licensed under LGPL, either version 3, or any later.
* See <http://www.gnu.org/licenses/>
*/
#ifndef libmobi_miniz_h
#define libmobi_miniz_h
#define MINIZ_HEADER_FILE_ONLY
#define MINIZ_NO_STDIO
#define MINIZ_NO_ARCHIVE_APIS
#define MINIZ_NO_ZLIB_COMPATIBLE_NAMES
#define MINIZ_NO_TIME
#define MINIZ_NO_ARCHIVE_WRITING_APIS
#include "miniz.c"
#endif

623
app/src/main/cpp/libmobi/src/mobi.h vendored Normal file
View file

@ -0,0 +1,623 @@
/** @file mobi.h
* @brief Libmobi main header file
*
* This file is installed with the library.
* Include it in your project with "#include <mobi.h>".
* See aryan of usage in mobitool.c, mobimeta.c, mobidrm.c
*
* Copyright (c) 2014-2022 Bartek Fabiszewski
* http://www.fabiszewski.net
*
* This file is part of libmobi.
* Licensed under LGPL, either version 3, or any later.
* See <http://www.gnu.org/licenses/>
*/
#ifndef libmobi_mobi_h
#define libmobi_mobi_h
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <time.h>
/** @brief Visibility attributes for symbol export */
#if defined (__CYGWIN__) || defined (__MINGW32__)
#define MOBI_EXPORT __attribute__((visibility("default"))) __declspec(dllexport) extern
#elif defined (_WIN32)
#define MOBI_EXPORT __declspec(dllexport)
#else
#define MOBI_EXPORT __attribute__((__visibility__("default")))
#endif
/**
@brief Usually 32-bit values in mobi records
with value 0xffffffff mean "value not set"
*/
#define MOBI_NOTSET UINT32_MAX
#define MOBI_ENCRYPTION_NONE 0 /**< Text record encryption type: none */
#define MOBI_ENCRYPTION_V1 1 /**< Text record encryption type: old mobipocket */
#define MOBI_ENCRYPTION_V2 2 /**< Text record encryption type: mobipocket */
#define MOBI_COMPRESSION_NONE 1 /**< Text record compression type: none */
#define MOBI_COMPRESSION_PALMDOC 2 /**< Text record compression type: palmdoc */
#define MOBI_COMPRESSION_HUFFCDIC 17480 /**< Text record compression type: huff/cdic */
#ifdef __cplusplus
extern "C"
{
#endif
/**
@defgroup mobi_enums Exported enums
@{
*/
/**
@brief Error codes returned by functions
*/
typedef enum {
MOBI_SUCCESS = 0, /**< Generic success return value */
MOBI_ERROR = 1, /**< Generic error return value */
MOBI_PARAM_ERR = 2, /**< Wrong function parameter */
MOBI_DATA_CORRUPT = 3, /**< Corrupted data */
MOBI_FILE_NOT_FOUND = 4, /**< File not found */
MOBI_FILE_ENCRYPTED = 5, /**< Unsupported encrypted data */
MOBI_FILE_UNSUPPORTED = 6, /**< Unsupported document type */
MOBI_MALLOC_FAILED = 7, /**< Memory allocation error */
MOBI_INIT_FAILED = 8, /**< Initialization error */
MOBI_BUFFER_END = 9, /**< Out of buffer error */
MOBI_XML_ERR = 10, /**< XMLwriter error */
MOBI_DRM_PIDINV = 11, /**< Invalid DRM PID */
MOBI_DRM_KEYNOTFOUND = 12, /**< Key not found */
MOBI_DRM_UNSUPPORTED = 13, /**< DRM support not included */
MOBI_WRITE_FAILED = 14, /**< Writing to file failed */
MOBI_DRM_EXPIRED = 15, /**< DRM expired */
MOBI_DRM_RANDOM_ERR = 16 /**< DRM random bytes generation failed */
} MOBI_RET;
/**
@brief EXTH record types
*/
typedef enum {
EXTH_NUMERIC = 0,
EXTH_STRING = 1,
EXTH_BINARY = 2
} MOBIExthType;
/**
@brief EXTH record tags
*/
typedef enum {
EXTH_DRMSERVER = 1,
EXTH_DRMCOMMERCE = 2,
EXTH_DRMEBOOKBASE = 3,
EXTH_TITLE = 99, /**< <dc:title> */
EXTH_AUTHOR = 100, /**< <dc:creator> */
EXTH_PUBLISHER = 101, /**< <dc:publisher> */
EXTH_IMPRINT = 102, /**< <imprint> */
EXTH_DESCRIPTION = 103, /**< <dc:description> */
EXTH_ISBN = 104, /**< <dc:identifier opf:scheme="ISBN"> */
EXTH_SUBJECT = 105, /**< <dc:subject> */
EXTH_PUBLISHINGDATE = 106, /**< <dc:date> */
EXTH_REVIEW = 107, /**< <review> */
EXTH_CONTRIBUTOR = 108, /**< <dc:contributor> */
EXTH_RIGHTS = 109, /**< <dc:rights> */
EXTH_SUBJECTCODE = 110, /**< <dc:subject BASICCode="subjectcode"> */
EXTH_TYPE = 111, /**< <dc:type> */
EXTH_SOURCE = 112, /**< <dc:source> */
EXTH_ASIN = 113,
EXTH_VERSION = 114,
EXTH_SAMPLE = 115,
EXTH_STARTREADING = 116, /**< Start reading */
EXTH_ADULT = 117, /**< <adult> */
EXTH_PRICE = 118, /**< <srp> */
EXTH_CURRENCY = 119, /**< <srp currency="currency"> */
EXTH_KF8BOUNDARY = 121,
EXTH_FIXEDLAYOUT = 122, /**< <fixed-layout> */
EXTH_BOOKTYPE = 123, /**< <book-type> */
EXTH_ORIENTATIONLOCK = 124, /**< <orientation-lock> */
EXTH_COUNTRESOURCES = 125,
EXTH_ORIGRESOLUTION = 126, /**< <original-resolution> */
EXTH_ZEROGUTTER = 127, /**< <zero-gutter> */
EXTH_ZEROMARGIN = 128, /**< <zero-margin> */
EXTH_KF8COVERURI = 129,
EXTH_RESCOFFSET = 131,
EXTH_REGIONMAGNI = 132, /**< <region-mag> */
EXTH_DICTNAME = 200, /**< <DictionaryVeryShortName> */
EXTH_COVEROFFSET = 201, /**< <EmbeddedCover> */
EXTH_THUMBOFFSET = 202,
EXTH_HASFAKECOVER = 203,
EXTH_CREATORSOFT = 204,
EXTH_CREATORMAJOR = 205,
EXTH_CREATORMINOR = 206,
EXTH_CREATORBUILD = 207,
EXTH_WATERMARK = 208,
EXTH_TAMPERKEYS = 209,
EXTH_FONTSIGNATURE = 300,
EXTH_CLIPPINGLIMIT = 401,
EXTH_PUBLISHERLIMIT = 402,
EXTH_UNK403 = 403,
EXTH_TTSDISABLE = 404,
EXTH_READFORFREE = 405, // uint32_t, rental related, ReadForFree
EXTH_RENTAL = 406, // uint64_t
EXTH_UNK407 = 407,
EXTH_UNK450 = 450,
EXTH_UNK451 = 451,
EXTH_UNK452 = 452,
EXTH_UNK453 = 453,
EXTH_DOCTYPE = 501, /**< PDOC - Personal Doc; EBOK - ebook; EBSP - ebook sample; */
EXTH_LASTUPDATE = 502,
EXTH_UPDATEDTITLE = 503,
EXTH_ASIN504 = 504,
EXTH_TITLEFILEAS = 508,
EXTH_CREATORFILEAS = 517,
EXTH_PUBLISHERFILEAS = 522,
EXTH_LANGUAGE = 524, /**< <dc:language> */
EXTH_ALIGNMENT = 525, /**< <primary-writing-mode> */
EXTH_CREATORSTRING = 526,
EXTH_PAGEDIR = 527,
EXTH_OVERRIDEFONTS = 528, /**< <override-kindle-fonts> */
EXTH_SORCEDESC = 529,
EXTH_DICTLANGIN = 531,
EXTH_DICTLANGOUT = 532,
EXTH_INPUTSOURCE = 534,
EXTH_CREATORBUILDREV = 535,
} MOBIExthTag;
/**
@brief Types of files stored in database records
*/
typedef enum {
T_UNKNOWN, /**< unknown */
/* markup */
T_HTML, /**< html */
T_CSS, /**< css */
T_SVG, /**< svg */
T_OPF, /**< opf */
T_NCX, /**< ncx */
/* images */
T_JPG, /**< jpg */
T_GIF, /**< gif */
T_PNG, /**< png */
T_BMP, /**< bmp */
/* fonts */
T_OTF, /**< otf */
T_TTF, /**< ttf */
/* media */
T_MP3, /**< mp3 */
T_MPG, /**< mp3 */
T_PDF, /**< pdf */
/* generic types */
T_FONT, /**< encoded font */
T_AUDIO, /**< audio resource */
T_VIDEO, /**< video resource */
T_BREAK /**< end of file */
} MOBIFiletype;
/**
@brief Metadata of file types
*/
typedef struct {
MOBIFiletype type; /**< MOBIFiletype type */
char extension[5]; /**< file extension */
char mime_type[30]; /**< mime-type */
} MOBIFileMeta;
/**
@brief Encoding types in MOBI header (offset 28)
*/
typedef enum {
MOBI_CP1252 = 1252, /**< cp-1252 encoding */
MOBI_UTF8 = 65001, /**< utf-8 encoding */
MOBI_UTF16 = 65002, /**< utf-16 encoding */
} MOBIEncoding;
/** @} */
/**
@defgroup raw_structs Exported structures for the raw, unparsed records metadata and data
@{
*/
/**
@brief Header of palmdoc database file
*/
typedef struct {
char name[33]; /**< 0: Database name, zero terminated, trimmed title (+author) */
uint16_t attributes; /**< 32: Attributes bitfield, PALMDB_ATTRIBUTE_DEFAULT */
uint16_t version; /**< 34: File version, PALMDB_VERSION_DEFAULT */
uint32_t ctime; /**< 36: Creation time */
uint32_t mtime; /**< 40: Modification time */
uint32_t btime; /**< 44: Backup time */
uint32_t mod_num; /**< 48: Modification number, PALMDB_MODNUM_DEFAULT */
uint32_t appinfo_offset; /**< 52: Offset to application info (if present) or zero, PALMDB_APPINFO_DEFAULT */
uint32_t sortinfo_offset; /**< 56: Offset to sort info (if present) or zero, PALMDB_SORTINFO_DEFAULT */
char type[5]; /**< 60: Database type, zero terminated, PALMDB_TYPE_DEFAULT */
char creator[5]; /**< 64: Creator type, zero terminated, PALMDB_CREATOR_DEFAULT */
uint32_t uid; /**< 68: Used internally to identify record */
uint32_t next_rec; /**< 72: Used only when database is loaded into memory, PALMDB_NEXTREC_DEFAULT */
uint16_t rec_count; /**< 76: Number of records in the file */
} MOBIPdbHeader;
/**
@brief Metadata and data of a record. All records form a linked list.
*/
typedef struct MOBIPdbRecord {
uint32_t offset; /**< Offset of the record data from the start of the database */
size_t size; /**< Calculated size of the record data */
uint8_t attributes; /**< Record attributes */
uint32_t uid; /**< Record unique id, usually sequential even numbers */
unsigned char *data; /**< Record data */
struct MOBIPdbRecord *next; /**< Pointer to the next record or NULL */
} MOBIPdbRecord;
/**
@brief Metadata and data of a EXTH record. All records form a linked list.
*/
typedef struct MOBIExthHeader {
uint32_t tag; /**< Record tag */
uint32_t size; /**< Data size */
void *data; /**< Record data */
struct MOBIExthHeader *next; /**< Pointer to the next record or NULL */
} MOBIExthHeader;
/**
@brief EXTH tag metadata
*/
typedef struct {
MOBIExthTag tag; /**< Record tag id */
MOBIExthType type; /**< EXTH_NUMERIC, EXTH_STRING or EXTH_BINARY */
char *name; /**< Tag name */
} MOBIExthMeta;
/**
@brief Header of the Record 0 meta-record
*/
typedef struct {
/* PalmDOC header (extended), offset 0, length 16 */
uint16_t compression_type; /**< 0; 1 == no compression, 2 = PalmDOC compression, 17480 = HUFF/CDIC compression */
/* uint16_t unused; // 2; 0 */
uint32_t text_length; /**< 4; uncompressed length of the entire text of the book */
uint16_t text_record_count; /**< 8; number of PDB records used for the text of the book */
uint16_t text_record_size; /**< 10; maximum size of each record containing text, always 4096 */
uint16_t encryption_type; /**< 12; 0 == no encryption, 1 = Old Mobipocket Encryption, 2 = Mobipocket Encryption */
uint16_t unknown1; /**< 14; usually 0 */
} MOBIRecord0Header;
/**
@brief MOBI header which follows Record 0 header
All MOBI header fields are pointers. Some fields are not present in the header, then the pointer is NULL.
*/
typedef struct {
/* MOBI header, offset 16 */
char mobi_magic[5]; /**< 16: M O B I { 77, 79, 66, 73 }, zero terminated */
uint32_t *header_length; /**< 20: the length of the MOBI header, including the previous 4 bytes */
uint32_t *mobi_type; /**< 24: mobipocket file type */
MOBIEncoding *text_encoding; /**< 28: 1252 = CP1252, 65001 = UTF-8 */
uint32_t *uid; /**< 32: unique id */
uint32_t *version; /**< 36: mobipocket format */
uint32_t *orth_index; /**< 40: section number of orthographic meta index. MOBI_NOTSET if index is not available. */
uint32_t *infl_index; /**< 44: section number of inflection meta index. MOBI_NOTSET if index is not available. */
uint32_t *names_index; /**< 48: section number of names meta index. MOBI_NOTSET if index is not available. */
uint32_t *keys_index; /**< 52: section number of keys meta index. MOBI_NOTSET if index is not available. */
uint32_t *extra0_index; /**< 56: section number of extra 0 meta index. MOBI_NOTSET if index is not available. */
uint32_t *extra1_index; /**< 60: section number of extra 1 meta index. MOBI_NOTSET if index is not available. */
uint32_t *extra2_index; /**< 64: section number of extra 2 meta index. MOBI_NOTSET if index is not available. */
uint32_t *extra3_index; /**< 68: section number of extra 3 meta index. MOBI_NOTSET if index is not available. */
uint32_t *extra4_index; /**< 72: section number of extra 4 meta index. MOBI_NOTSET if index is not available. */
uint32_t *extra5_index; /**< 76: section number of extra 5 meta index. MOBI_NOTSET if index is not available. */
uint32_t *non_text_index; /**< 80: first record number (starting with 0) that's not the book's text */
uint32_t *full_name_offset; /**< 84: offset in record 0 (not from start of file) of the full name of the book */
uint32_t *full_name_length; /**< 88: length of the full name */
uint32_t *locale; /**< 92: first byte is main language: 09 = English, next byte is dialect, 08 = British, 04 = US */
uint32_t *dict_input_lang; /**< 96: input language for a dictionary */
uint32_t *dict_output_lang; /**< 100: output language for a dictionary */
uint32_t *min_version; /**< 104: minimum mobipocket version support needed to read this file. */
uint32_t *image_index; /**< 108: first record number (starting with 0) that contains an image (sequential) */
uint32_t *huff_rec_index; /**< 112: first huffman compression record */
uint32_t *huff_rec_count; /**< 116: huffman compression records count */
uint32_t *datp_rec_index; /**< 120: section number of DATP record */
uint32_t *datp_rec_count; /**< 124: DATP records count */
uint32_t *exth_flags; /**< 128: bitfield. if bit 6 (0x40) is set, then there's an EXTH record */
/* 32 unknown bytes, usually 0, related to encryption and unknown6 */
/* unknown2 */
/* unknown3 */
/* unknown4 */
/* unknown5 */
uint32_t *unknown6; /**< 164: use MOBI_NOTSET , related to encryption*/
uint32_t *drm_offset; /**< 168: offset to DRM key info in DRMed files. MOBI_NOTSET if no DRM */
uint32_t *drm_count; /**< 172: number of entries in DRM info */
uint32_t *drm_size; /**< 176: number of bytes in DRM info */
uint32_t *drm_flags; /**< 180: some flags concerning DRM info, bit 0 set if password encryption */
/* 8 unknown bytes 0? */
/* unknown7 */
/* unknown8 */
uint16_t *first_text_index; /**< 192: section number of first text record */
uint16_t *last_text_index; /**< 194: */
uint32_t *fdst_index; /**< 192 (KF8) section number of FDST record */
//uint32_t *unknown9; /**< 196: */
uint32_t *fdst_section_count; /**< 196 (KF8) */
uint32_t *fcis_index; /**< 200: section number of FCIS record */
uint32_t *fcis_count; /**< 204: FCIS records count */
uint32_t *flis_index; /**< 208: section number of FLIS record */
uint32_t *flis_count; /**< 212: FLIS records count */
uint32_t *unknown10; /**< 216: */
uint32_t *unknown11; /**< 220: */
uint32_t *srcs_index; /**< 224: section number of SRCS record */
uint32_t *srcs_count; /**< 228: SRCS records count */
uint32_t *unknown12; /**< 232: */
uint32_t *unknown13; /**< 236: */
/* uint16_t fill 0 */
uint16_t *extra_flags; /**< 242: extra flags */
uint32_t *ncx_index; /**< 244: section number of NCX record */
uint32_t *unknown14; /**< 248: */
uint32_t *fragment_index; /**< 248 (KF8) section number of fragments record */
uint32_t *unknown15; /**< 252: */
uint32_t *skeleton_index; /**< 252 (KF8) section number of SKEL record */
uint32_t *datp_index; /**< 256: section number of DATP record */
uint32_t *unknown16; /**< 260: */
uint32_t *guide_index; /**< 260 (KF8) section number of guide record */
uint32_t *unknown17; /**< 264: */
uint32_t *unknown18; /**< 268: */
uint32_t *unknown19; /**< 272: */
uint32_t *unknown20; /**< 276: */
char *full_name; /**< variable offset (full_name_offset): full name */
} MOBIMobiHeader;
/**
@brief Main structure holding all metadata and unparsed records data
In case of hybrid KF7/KF8 file there are two Records 0.
In such case MOBIData is a circular linked list of two independent records, one structure per each Record 0 header.
Records data (MOBIPdbRecord structure) is not duplicated in such case - each struct holds same pointers to all records data.
*/
typedef struct MOBIData {
bool use_kf8; /**< Flag: if set to true (default), KF8 part of hybrid file is parsed, if false - KF7 part will be parsed */
uint32_t kf8_boundary_offset; /**< Set to KF8 boundary rec number if present, otherwise: MOBI_NOTSET */
unsigned char *drm_key; /**< @deprecated Will be removed in future versions */
MOBIPdbHeader *ph; /**< Palmdoc database header structure or NULL if not loaded */
MOBIRecord0Header *rh; /**< Record0 header structure or NULL if not loaded */
MOBIMobiHeader *mh; /**< MOBI header structure or NULL if not loaded */
MOBIExthHeader *eh; /**< Linked list of EXTH records or NULL if not loaded */
MOBIPdbRecord *rec; /**< Linked list of palmdoc database records or NULL if not loaded */
struct MOBIData *next; /**< Pointer to the other part of hybrid file or NULL if not a hybrid file */
void *internals; /**< Used internally*/
} MOBIData;
/** @} */ // end of raw_structs group
/**
@defgroup parsed_structs Exported structures for the parsed records metadata and data
@{
*/
/**
@brief Parsed FDST record
FDST record contains offsets of main sections in RAWML - raw text data.
The sections are usually html part, css parts, svg part.
*/
typedef struct {
size_t fdst_section_count; /**< Number of main sections */
uint32_t *fdst_section_starts; /**< Array of section start offsets */
uint32_t *fdst_section_ends; /**< Array of section end offsets */
} MOBIFdst;
/**
@brief Parsed tag for an index entry
*/
typedef struct {
size_t tagid; /**< Tag id */
size_t tagvalues_count; /**< Number of tag values */
uint32_t *tagvalues; /**< Array of tag values */
} MOBIIndexTag;
/**
@brief Parsed INDX index entry
*/
typedef struct {
char *label; /**< Entry string, zero terminated */
size_t tags_count; /**< Number of tags */
MOBIIndexTag *tags; /**< Array of tags */
} MOBIIndexEntry;
/**
@brief Parsed INDX record
*/
typedef struct {
size_t type; /**< Index type: 0 - normal, 2 - inflection */
size_t entries_count; /**< Index entries count */
MOBIEncoding encoding; /**< Index encoding */
size_t total_entries_count; /**< Total index entries count */
size_t ordt_offset; /**< ORDT offset */
size_t ligt_offset; /**< LIGT offset */
size_t ligt_entries_count; /**< LIGT index entries count */
size_t cncx_records_count; /**< Number of compiled NCX records */
MOBIPdbRecord *cncx_record; /**< Link to CNCX record */
MOBIIndexEntry *entries; /**< Index entries array */
char *orth_index_name; /**< Orth index name */
} MOBIIndx;
/**
@brief Reconstructed source file.
All file parts are organized in a linked list.
*/
typedef struct MOBIPart {
size_t uid; /**< Unique id */
MOBIFiletype type; /**< File type */
size_t size; /**< File size */
unsigned char *data; /**< File data */
struct MOBIPart *next; /**< Pointer to next part or NULL */
} MOBIPart;
/**
@brief Main structure containing reconstructed source parts and indices
*/
typedef struct {
size_t version; /**< Version of Mobipocket document */
MOBIFdst *fdst; /**< Parsed FDST record or NULL if not present */
MOBIIndx *skel; /**< Parsed skeleton index or NULL if not present */
MOBIIndx *frag; /**< Parsed fragments index or NULL if not present */
MOBIIndx *guide; /**< Parsed guide index or NULL if not present */
MOBIIndx *ncx; /**< Parsed NCX index or NULL if not present */
MOBIIndx *orth; /**< Parsed orth index or NULL if not present */
MOBIIndx *infl; /**< Parsed infl index or NULL if not present */
MOBIPart *flow; /**< Linked list of reconstructed main flow parts or NULL if not present */
MOBIPart *markup; /**< Linked list of reconstructed markup files or NULL if not present */
MOBIPart *resources; /**< Linked list of reconstructed resources files or NULL if not present */
} MOBIRawml;
/** @} */ // end of parsed_structs group
/**
@defgroup mobi_export Functions exported by the library
@{
*/
MOBI_EXPORT const char * mobi_version(void);
MOBI_EXPORT MOBI_RET mobi_load_file(MOBIData *m, FILE *file);
MOBI_EXPORT MOBI_RET mobi_load_filename(MOBIData *m, const char *path);
MOBI_EXPORT MOBIData * mobi_init(void);
MOBI_EXPORT void mobi_free(MOBIData *m);
MOBI_EXPORT MOBI_RET mobi_parse_kf7(MOBIData *m);
MOBI_EXPORT MOBI_RET mobi_parse_kf8(MOBIData *m);
MOBI_EXPORT MOBI_RET mobi_parse_rawml(MOBIRawml *rawml, const MOBIData *m);
MOBI_EXPORT MOBI_RET mobi_parse_rawml_opt(MOBIRawml *rawml, const MOBIData *m, bool parse_toc, bool parse_dict, bool reconstruct);
MOBI_EXPORT MOBI_RET mobi_get_rawml(const MOBIData *m, char *text, size_t *len);
MOBI_EXPORT MOBI_RET mobi_dump_rawml(const MOBIData *m, FILE *file);
MOBI_EXPORT MOBI_RET mobi_decode_font_resource(unsigned char **decoded_font, size_t *decoded_size, MOBIPart *part);
MOBI_EXPORT MOBI_RET mobi_decode_audio_resource(unsigned char **decoded_resource, size_t *decoded_size, MOBIPart *part);
MOBI_EXPORT MOBI_RET mobi_decode_video_resource(unsigned char **decoded_resource, size_t *decoded_size, MOBIPart *part);
MOBI_EXPORT MOBI_RET mobi_get_embedded_source(unsigned char **data, size_t *size, const MOBIData *m);
MOBI_EXPORT MOBI_RET mobi_get_embedded_log(unsigned char **data, size_t *size, const MOBIData *m);
MOBI_EXPORT MOBIPdbRecord * mobi_get_record_by_uid(const MOBIData *m, const size_t uid);
MOBI_EXPORT MOBIPdbRecord * mobi_get_record_by_seqnumber(const MOBIData *m, const size_t uid);
MOBI_EXPORT MOBIPart * mobi_get_flow_by_uid(const MOBIRawml *rawml, const size_t uid);
MOBI_EXPORT MOBIPart * mobi_get_flow_by_fid(const MOBIRawml *rawml, const char *fid);
MOBI_EXPORT MOBIPart * mobi_get_resource_by_uid(const MOBIRawml *rawml, const size_t uid);
MOBI_EXPORT MOBIPart * mobi_get_resource_by_fid(const MOBIRawml *rawml, const char *fid);
MOBI_EXPORT MOBIPart * mobi_get_part_by_uid(const MOBIRawml *rawml, const size_t uid);
MOBI_EXPORT MOBI_RET mobi_get_fullname(const MOBIData *m, char *fullname, const size_t len);
MOBI_EXPORT size_t mobi_get_first_resource_record(const MOBIData *m);
MOBI_EXPORT size_t mobi_get_text_maxsize(const MOBIData *m);
MOBI_EXPORT uint16_t mobi_get_textrecord_maxsize(const MOBIData *m);
MOBI_EXPORT size_t mobi_get_kf8offset(const MOBIData *m);
MOBI_EXPORT size_t mobi_get_kf8boundary_seqnumber(const MOBIData *m);
MOBI_EXPORT size_t mobi_get_record_extrasize(const MOBIPdbRecord *record, const uint16_t flags);
MOBI_EXPORT size_t mobi_get_record_mb_extrasize(const MOBIPdbRecord *record, const uint16_t flags);
MOBI_EXPORT size_t mobi_get_fileversion(const MOBIData *m);
MOBI_EXPORT size_t mobi_get_fdst_record_number(const MOBIData *m);
MOBI_EXPORT MOBIExthHeader * mobi_get_exthrecord_by_tag(const MOBIData *m, const MOBIExthTag tag);
MOBI_EXPORT MOBIExthHeader * mobi_next_exthrecord_by_tag(const MOBIData *m, const MOBIExthTag tag, MOBIExthHeader **start);
MOBI_EXPORT MOBI_RET mobi_delete_exthrecord_by_tag(MOBIData *m, const MOBIExthTag tag);
MOBI_EXPORT MOBI_RET mobi_add_exthrecord(MOBIData *m, const MOBIExthTag tag, const uint32_t size, const void *value);
MOBI_EXPORT MOBIExthMeta mobi_get_exthtagmeta_by_tag(const MOBIExthTag tag);
MOBI_EXPORT MOBIFileMeta mobi_get_filemeta_by_type(const MOBIFiletype type);
MOBI_EXPORT uint32_t mobi_decode_exthvalue(const unsigned char *data, const size_t size);
MOBI_EXPORT char * mobi_decode_exthstring(const MOBIData *m, const unsigned char *data, const size_t size);
MOBI_EXPORT struct tm * mobi_pdbtime_to_time(const long pdb_time);
MOBI_EXPORT const char * mobi_get_locale_string(const uint32_t locale);
MOBI_EXPORT size_t mobi_get_locale_number(const char *locale_string);
MOBI_EXPORT uint32_t mobi_get_orth_entry_offset(const MOBIIndexEntry *entry);
MOBI_EXPORT uint32_t mobi_get_orth_entry_length(const MOBIIndexEntry *entry);
MOBI_EXPORT MOBI_RET mobi_remove_hybrid_part(MOBIData *m, const bool remove_kf8);
MOBI_EXPORT bool mobi_exists_mobiheader(const MOBIData *m);
MOBI_EXPORT bool mobi_exists_fdst(const MOBIData *m);
MOBI_EXPORT bool mobi_exists_skel_indx(const MOBIData *m);
MOBI_EXPORT bool mobi_exists_frag_indx(const MOBIData *m);
MOBI_EXPORT bool mobi_exists_guide_indx(const MOBIData *m);
MOBI_EXPORT bool mobi_exists_ncx(const MOBIData *m);
MOBI_EXPORT bool mobi_exists_orth(const MOBIData *m);
MOBI_EXPORT bool mobi_exists_infl(const MOBIData *m);
MOBI_EXPORT bool mobi_is_hybrid(const MOBIData *m);
MOBI_EXPORT bool mobi_is_encrypted(const MOBIData *m);
MOBI_EXPORT bool mobi_is_mobipocket(const MOBIData *m);
MOBI_EXPORT bool mobi_is_dictionary(const MOBIData *m);
MOBI_EXPORT bool mobi_is_kf8(const MOBIData *m);
MOBI_EXPORT bool mobi_is_replica(const MOBIData *m);
MOBI_EXPORT bool mobi_is_rawml_kf8(const MOBIRawml *rawml);
MOBI_EXPORT MOBIRawml * mobi_init_rawml(const MOBIData *m);
MOBI_EXPORT void mobi_free_rawml(MOBIRawml *rawml);
MOBI_EXPORT char * mobi_meta_get_title(const MOBIData *m);
MOBI_EXPORT char * mobi_meta_get_author(const MOBIData *m);
MOBI_EXPORT char * mobi_meta_get_publisher(const MOBIData *m);
MOBI_EXPORT char * mobi_meta_get_imprint(const MOBIData *m);
MOBI_EXPORT char * mobi_meta_get_description(const MOBIData *m);
MOBI_EXPORT char * mobi_meta_get_isbn(const MOBIData *m);
MOBI_EXPORT char * mobi_meta_get_subject(const MOBIData *m);
MOBI_EXPORT char * mobi_meta_get_publishdate(const MOBIData *m);
MOBI_EXPORT char * mobi_meta_get_review(const MOBIData *m);
MOBI_EXPORT char * mobi_meta_get_contributor(const MOBIData *m);
MOBI_EXPORT char * mobi_meta_get_copyright(const MOBIData *m);
MOBI_EXPORT char * mobi_meta_get_asin(const MOBIData *m);
MOBI_EXPORT char * mobi_meta_get_language(const MOBIData *m);
MOBI_EXPORT MOBI_RET mobi_meta_set_title(MOBIData *m, const char *title);
MOBI_EXPORT MOBI_RET mobi_meta_add_title(MOBIData *m, const char *title);
MOBI_EXPORT MOBI_RET mobi_meta_delete_title(MOBIData *m);
MOBI_EXPORT MOBI_RET mobi_meta_set_author(MOBIData *m, const char *author);
MOBI_EXPORT MOBI_RET mobi_meta_add_author(MOBIData *m, const char *author);
MOBI_EXPORT MOBI_RET mobi_meta_delete_author(MOBIData *m);
MOBI_EXPORT MOBI_RET mobi_meta_set_publisher(MOBIData *m, const char *publisher);
MOBI_EXPORT MOBI_RET mobi_meta_add_publisher(MOBIData *m, const char *publisher);
MOBI_EXPORT MOBI_RET mobi_meta_delete_publisher(MOBIData *m);
MOBI_EXPORT MOBI_RET mobi_meta_set_imprint(MOBIData *m, const char *imprint);
MOBI_EXPORT MOBI_RET mobi_meta_add_imprint(MOBIData *m, const char *imprint);
MOBI_EXPORT MOBI_RET mobi_meta_delete_imprint(MOBIData *m);
MOBI_EXPORT MOBI_RET mobi_meta_set_description(MOBIData *m, const char *description);
MOBI_EXPORT MOBI_RET mobi_meta_add_description(MOBIData *m, const char *description);
MOBI_EXPORT MOBI_RET mobi_meta_delete_description(MOBIData *m);
MOBI_EXPORT MOBI_RET mobi_meta_set_isbn(MOBIData *m, const char *isbn);
MOBI_EXPORT MOBI_RET mobi_meta_add_isbn(MOBIData *m, const char *isbn);
MOBI_EXPORT MOBI_RET mobi_meta_delete_isbn(MOBIData *m);
MOBI_EXPORT MOBI_RET mobi_meta_set_subject(MOBIData *m, const char *subject);
MOBI_EXPORT MOBI_RET mobi_meta_add_subject(MOBIData *m, const char *subject);
MOBI_EXPORT MOBI_RET mobi_meta_delete_subject(MOBIData *m);
MOBI_EXPORT MOBI_RET mobi_meta_set_publishdate(MOBIData *m, const char *publishdate);
MOBI_EXPORT MOBI_RET mobi_meta_add_publishdate(MOBIData *m, const char *publishdate);
MOBI_EXPORT MOBI_RET mobi_meta_delete_publishdate(MOBIData *m);
MOBI_EXPORT MOBI_RET mobi_meta_set_review(MOBIData *m, const char *review);
MOBI_EXPORT MOBI_RET mobi_meta_add_review(MOBIData *m, const char *review);
MOBI_EXPORT MOBI_RET mobi_meta_delete_review(MOBIData *m);
MOBI_EXPORT MOBI_RET mobi_meta_set_contributor(MOBIData *m, const char *contributor);
MOBI_EXPORT MOBI_RET mobi_meta_add_contributor(MOBIData *m, const char *contributor);
MOBI_EXPORT MOBI_RET mobi_meta_delete_contributor(MOBIData *m);
MOBI_EXPORT MOBI_RET mobi_meta_set_copyright(MOBIData *m, const char *copyright);
MOBI_EXPORT MOBI_RET mobi_meta_add_copyright(MOBIData *m, const char *copyright);
MOBI_EXPORT MOBI_RET mobi_meta_delete_copyright(MOBIData *m);
MOBI_EXPORT MOBI_RET mobi_meta_set_asin(MOBIData *m, const char *asin);
MOBI_EXPORT MOBI_RET mobi_meta_add_asin(MOBIData *m, const char *asin);
MOBI_EXPORT MOBI_RET mobi_meta_delete_asin(MOBIData *m);
MOBI_EXPORT MOBI_RET mobi_meta_set_language(MOBIData *m, const char *language);
MOBI_EXPORT MOBI_RET mobi_meta_add_language(MOBIData *m, const char *language);
MOBI_EXPORT MOBI_RET mobi_meta_delete_language(MOBIData *m);
MOBI_EXPORT MOBI_RET mobi_drm_setkey(MOBIData *m, const char *pid);
MOBI_EXPORT MOBI_RET mobi_drm_setkey_serial(MOBIData *m, const char *serial);
MOBI_EXPORT MOBI_RET mobi_drm_addvoucher(MOBIData *m, const char *serial, const time_t valid_from, const time_t valid_to,
const MOBIExthTag *tamperkeys, const size_t tamperkeys_count);
MOBI_EXPORT MOBI_RET mobi_drm_delkey(MOBIData *m);
MOBI_EXPORT MOBI_RET mobi_drm_decrypt(MOBIData *m);
MOBI_EXPORT MOBI_RET mobi_drm_encrypt(MOBIData *m);
MOBI_EXPORT MOBI_RET mobi_write_file(FILE *file, MOBIData *m);
/** @} */ // end of mobi_export group
#ifdef __cplusplus
}
#endif
#endif

2059
app/src/main/cpp/libmobi/src/opf.c vendored Normal file

File diff suppressed because it is too large Load diff

164
app/src/main/cpp/libmobi/src/opf.h vendored Normal file
View file

@ -0,0 +1,164 @@
/** @file opf.h
*
* Copyright (c) 2014 Bartek Fabiszewski
* http://www.fabiszewski.net
*
* This file is part of libmobi.
* Licensed under LGPL, either version 3, or any later.
* See <http://www.gnu.org/licenses/>
*/
#ifndef libmobi_opf_h
#define libmobi_opf_h
#include "config.h"
#include "mobi.h"
/** @brief Maximum number of opf meta tags */
#define OPF_META_MAX_TAGS 256
/**
@defgroup mobi_opf OPF handling structures
@{
*/
/** @brief OPF <dc:identifier/> element structure
At least one identifier must have an id specified,
so it can be referenced from the package unique-identifier attribute.
*/
typedef struct {
char *value; /**< element value */
char *id; /**< id attribute */
char *scheme; /**< opf:scheme (optional) */
} OPFidentifier;
/** @brief OPF <dc:creator/> element structure
Also applies to <dc:contributor/> element
*/
typedef struct {
char *value; /**< element value */
char *file_as; /**< opf:file-as attribute (optional) */
char *role; /**< opf:role attribute (optional) */
} OPFcreator;
/** @brief OPF <dc:subject/> element structure */
typedef struct {
char *value; /**< element value */
char *basic_code; /**< BASICCode attribute (optional, non-standard) */
} OPFsubject;
/** @brief OPF <dc:date/> element structure
Format: YYYY[-MM[-DD]]
*/
typedef struct {
char *value; /**< element value */
char *event; /**< opf:event attribute (optional) */
} OPFdate;
/** @brief OPF <dc-metadata/> element structure */
typedef struct {
OPFcreator **contributor; /**< <dc:contributor/> element (optional) */
OPFcreator **creator; /**< <dc:creator/> element (optional) */
OPFidentifier **identifier; /**< <dc:identifier/> element (required) */
OPFsubject **subject; /**< <dc:subject/> element (optional) */
OPFdate **date; /**< <dc:date/> element (optional) */
char **description; /**< <dc:description/> element (optional) */
char **language; /**< <dc:language/> element (required) */
char **publisher; /**< <dc:publisher/> element (optional) */
char **rights; /**< <dc:rights/> element (optional) */
char **source; /**< <dc:source/> element (optional) */
char **title; /**< <dc:title/> element (required) */
char **type; /**< <dc:type/> element (optional) */
} OPFdcmeta;
/** @brief OPF <srp/> element structure */
typedef struct {
char *value; /**< element value */
char *currency; /**< currency attribute */
} OPFsrp;
/** @brief OPF <x-metadata/> element structure */
typedef struct {
OPFsrp **srp; /**< <srp/> element */
char **adult; /**< <adult/> element */
char **default_lookup_index; /**< <DefaultLookupIndex/> element */
char **dict_short_name; /**< <DictionaryVeryShortName/> element */
char **dictionary_in_lang; /**< <DictionaryInLanguage/> element */
char **dictionary_out_lang; /**< <DictionaryOutLanguage/> element */
char **embedded_cover; /**< <EmbeddedCover/> element */
char **imprint; /**< <imprint/> element */
char **review; /**< <review/> element */
} OPFxmeta;
/** @brief OPF <meta/> element structure */
typedef struct {
char *name; /**< name attribute (required) */
char *content; /**< content attribute (required) */
} OPFmeta;
/** @brief OPF <metadata/> element structure */
typedef struct {
OPFmeta **meta; /**< <meta/> element (optional) */
OPFdcmeta *dc_meta; /**< <dc-metadata/> element */
OPFxmeta *x_meta; /**< <x-metadata/> element */
} OPFmetadata;
/** @brief OPF <item/> element structure */
typedef struct {
char *id; /**< id attribute (required) */
char *href; /**< href attribute (required) */
char *media_type; /**< media-type attribute (required) */
} OPFitem;
/** @brief OPF <manifest/> element structure */
typedef struct {
OPFitem **item; /**< <item/> element */
} OPFmanifest;
/** @brief OPF <spine/> element structure */
typedef struct {
char *toc; /**< toc attribute (required) */
char **itemref; /**< <itemref idref="xxx"/> element */
} OPFspine;
/** @brief OPF <reference/> tag structure */
typedef struct {
char *type; /**< type attribute (required) */
char *title; /**< title attribute */
char *href; /**< href attribute (required) */
} OPFreference;
/** @brief OPF <guide/> element structure */
typedef struct {
OPFreference **reference; /**< <reference/> element tag */
} OPFguide;
/** @brief OPF <package/> element structure */
typedef struct {
//char *uid; /**< <package unique-identifier="uid"/> */
OPFmetadata *metadata; /**< <metadata/> (required) */
OPFmanifest *manifest; /**< <manifest/> (required) */
OPFspine *spine; /**< <spine/> (required) */
OPFguide *guide; /**< <guide/> (optional) */
} OPF;
/** @brief NCX index entry structure */
typedef struct {
size_t id; /**< Sequential id */
char *text; /**< Entry text content */
char *target; /**< Entry target reference */
size_t level; /**< Entry level */
size_t parent; /**< Entry parent */
size_t first_child; /**< First child id */
size_t last_child; /**< Last child id */
} NCX;
/** @} */
MOBI_RET mobi_build_opf(MOBIRawml *rawml, const MOBIData *m);
MOBI_RET mobi_build_ncx(MOBIRawml *rawml, const OPF *opf);
#endif

2199
app/src/main/cpp/libmobi/src/parse_rawml.c vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,42 @@
/** @file parse_rawml.h
*
* Copyright (c) 2014 Bartek Fabiszewski
* http://www.fabiszewski.net
*
* This file is part of libmobi.
* Licensed under LGPL, either version 3, or any later.
* See <http://www.gnu.org/licenses/>
*/
#ifndef mobi_parse_rawml_h
#define mobi_parse_rawml_h
#include "config.h"
#include "mobi.h"
#define MOBI_ATTRNAME_MAXSIZE 150 /**< Maximum length of tag attribute name, like "href" */
#define MOBI_ATTRVALUE_MAXSIZE 150 /**< Maximum length of tag attribute value */
/**
@brief Result data returned by mobi_search_links_kf7() and mobi_search_links_kf8()
*/
typedef struct {
unsigned char *start; /**< Beginning data to be replaced */
unsigned char *end; /**< End of data to be replaced */
char value[MOBI_ATTRVALUE_MAXSIZE + 1]; /**< Attribute value */
bool is_url; /**< True if value is part of css url attribute */
} MOBIResult;
/**
@brief HTML attribute type
*/
typedef enum {
ATTR_ID = 0, /**< Attribute 'id' */
ATTR_NAME /**< Attribute 'name' */
} MOBIAttrType;
MOBI_RET mobi_get_id_by_posoff(uint32_t *file_number, char *id, const MOBIRawml *rawml, const size_t pos_fid, const size_t pos_off, MOBIAttrType *pref_attr);
MOBI_RET mobi_find_attrvalue(MOBIResult *result, const unsigned char *data_start, const unsigned char *data_end, const MOBIFiletype type, const char *needle);
#endif

View file

@ -0,0 +1,375 @@
/** @file randombytes.c
* @brief Portable function for generating random data
*
* Copyright (c) 2022 Bartek Fabiszewski
* http://www.fabiszewski.net
*
* This file is part of libmobi.
* Licensed under LGPL, either version 3, or any later.
* See <http://www.gnu.org/licenses/>
*
* This code is based on libsodium's randombytes_buf function
* We just extract the single function we need from libsodium and adjust it for our use.
* Most of the code originates from:
* https://github.com/jedisct1/libsodium/blob/d250858c7445b7de94e912b529b81defe20d4aaa/src/libsodium/randombytes/sysrandom/randombytes_sysrandom.c
* Original code uses following license:
*
* ISC License
*
* Copyright (c) 2013-2022
* Frank Denis <j at pureftpd dot org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdint.h>
#include <string.h>
#ifndef _WIN32
# include <unistd.h>
#endif
#include <stdlib.h>
#include "config.h"
#include "randombytes.h"
#include "debug.h"
#include <sys/types.h>
#ifndef _WIN32
# include <sys/stat.h>
# include <sys/time.h>
#endif
#ifdef __linux__
# define _LINUX_SOURCE
#endif
#ifdef HAVE_SYS_RANDOM_H
# include <sys/random.h>
#endif
#ifdef __linux__
# define BLOCK_ON_DEV_RANDOM
# include <poll.h>
# ifdef HAVE_GETRANDOM
# define HAVE_LINUX_COMPATIBLE_GETRANDOM
# else
# include <sys/syscall.h>
# if defined(SYS_getrandom) && defined(__NR_getrandom)
# define getrandom(B, S, F) syscall(SYS_getrandom, (B), (int) (S), (F))
# define HAVE_LINUX_COMPATIBLE_GETRANDOM
# endif
# endif
#elif defined(__FreeBSD__) || defined(__DragonFly__)
# include <sys/param.h>
# if (defined(__FreeBSD_version) && __FreeBSD_version >= 1200000) || \
(defined(__DragonFly_version) && __DragonFly_version >= 500700)
# define HAVE_LINUX_COMPATIBLE_GETRANDOM
# endif
#endif
#define UNUSED(x) (void)(x)
typedef struct {
int random_data_source_fd;
int getrandom_available;
} MOBIRandom;
#ifdef _WIN32
# include <windows.h>
# define RtlGenRandom SystemFunction036
# if defined(__cplusplus)
extern "C"
# endif
BOOLEAN NTAPI RtlGenRandom(PVOID RandomBuffer, ULONG RandomBufferLength);
# ifdef _MSC_VER
# pragma comment(lib, "advapi32.lib")
# endif
#endif
#if defined(__OpenBSD__) || defined(__CloudABI__) || defined(__wasi__)
# define HAVE_SAFE_ARC4RANDOM
#endif
#ifdef HAVE_SAFE_ARC4RANDOM
/**
@brief Read a buffer of random bytes using arc4random_buf call
@param[in,out] handle Handle
@param[in,out] buf Buffer
@param[in] size Buffer size
@return MOBI_RET status code (on success MOBI_SUCCESS)
*/
static MOBI_RET mobi_randombytes_sysrandom_buf(MOBIRandom *handle, void *buf, const size_t size) {
UNUSED(handle);
arc4random_buf(buf, size);
return MOBI_SUCCESS;
}
#else /* HAVE_SAFE_ARC4RANDOM */
# ifndef _WIN32
/**
@brief Read a buffer of random bytes from file descriptoir
@param[in] fd File descriptior
@param[in,out] buf_ Buffer
@param[in] size Buffer size
@return Number of bytes read
*/
static ssize_t mobi_safe_read(const int fd, void *buf_, size_t size) {
unsigned char *buf = (unsigned char *) buf_;
ssize_t readnb;
do {
while ((readnb = read(fd, buf, size)) < (ssize_t) 0 && (errno == EINTR || errno == EAGAIN));
if (readnb < (ssize_t) 0) {
return readnb;
}
if (readnb == (ssize_t) 0) {
break;
}
size -= (size_t) readnb;
buf += readnb;
} while (size > (ssize_t) 0);
return (ssize_t) (buf - (unsigned char *) buf_);
}
# ifdef BLOCK_ON_DEV_RANDOM
/**
@brief Block on /dev/random until enough entropy is available
@return MOBI_RET status code (on success MOBI_SUCCESS)
*/
static MOBI_RET mobi_randombytes_block_on_dev_random(void) {
int fd = open("/dev/random", O_RDONLY);
if (fd == -1) {
return MOBI_SUCCESS;
}
struct pollfd pfd;
pfd.fd = fd;
pfd.events = POLLIN;
pfd.revents = 0;
int pret;
do {
pret = poll(&pfd, 1, -1);
} while (pret < 0 && (errno == EINTR || errno == EAGAIN));
if (pret != 1) {
(void) close(fd);
errno = EIO;
return MOBI_DRM_RANDOM_ERR;
}
if (close(fd) != 0) {
return MOBI_DRM_RANDOM_ERR;
}
return MOBI_SUCCESS;
}
# endif /* BLOCK_ON_DEV_RANDOM */
/**
@brief Open random device, wait for enough entropy if supported
@return Random device file descriptor
*/
static int mobi_randombytes_sysrandom_random_dev_open(void) {
# ifdef BLOCK_ON_DEV_RANDOM
if (mobi_randombytes_block_on_dev_random() != MOBI_SUCCESS) {
return -1;
}
# endif
static const char *devices[] = {
"/dev/urandom",
"/dev/random", NULL
};
const char **device = devices;
do {
int fd = open(*device, O_RDONLY);
if (fd != -1) {
struct stat st;
if (fstat(fd, &st) == 0 &&
# ifdef S_ISNAM
(S_ISNAM(st.st_mode) || S_ISCHR(st.st_mode))
# else
S_ISCHR(st.st_mode)
# endif
) {
# if defined(F_SETFD) && defined(FD_CLOEXEC)
(void) fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
# endif
return fd;
}
(void) close(fd);
} else if (errno == EINTR) {
continue;
}
device++;
} while (*device != NULL);
errno = EIO;
return -1;
}
# ifdef HAVE_LINUX_COMPATIBLE_GETRANDOM
/**
@brief Read a buffer of random bytes using getrandom system call
In libmobi we only need small KEYSIZE buffer, so we don't have to handle buffers over 256 bytes and read chunks
@param[in,out] buf Buffer
@param[in] size Buffer size (up to 256 bytes)
@return MOBI_RET status code (on success MOBI_SUCCESS)
*/
static MOBI_RET mobi_randombytes_linux_getrandom(void *buf, const size_t size) {
if (size > 256U) {
debug_print("This function can only handle buffer size up to 256 bytes (%zu requested)\n", size);
return MOBI_PARAM_ERR;
}
int readnb;
do {
readnb = getrandom(buf, size, 0);
} while (readnb < 0 && (errno == EINTR || errno == EAGAIN));
if (readnb != (int) size) {
debug_print("Getrandom failed (%s)\n", strerror(errno));
return MOBI_DRM_RANDOM_ERR;
}
return MOBI_SUCCESS;
}
# endif /* HAVE_LINUX_COMPATIBLE_GETRANDOM */
/**
@brief Initialize random data source
@param[in,out] handle Handle
@return MOBI_RET status code (on success MOBI_SUCCESS)
*/
static MOBI_RET mobi_randombytes_sysrandom_init(MOBIRandom *handle) {
# define NEEDS_INIT
const int errno_save = errno;
# ifdef HAVE_LINUX_COMPATIBLE_GETRANDOM
{
unsigned char fodder[16];
if (mobi_randombytes_linux_getrandom(fodder, sizeof fodder) == MOBI_SUCCESS) {
handle->getrandom_available = 1;
errno = errno_save;
return MOBI_SUCCESS;
}
handle->getrandom_available = 0;
}
# endif
if ((handle->random_data_source_fd = mobi_randombytes_sysrandom_random_dev_open()) == -1) {
debug_print("Couldn't open random device (%s)\n", strerror(errno));
return MOBI_DRM_RANDOM_ERR;
}
errno = errno_save;
return MOBI_SUCCESS;
}
/**
@brief Initialize random data source
@param[in,out] handle Handle
@return MOBI_RET status code (on success MOBI_SUCCESS)
*/
static MOBI_RET mobi_randombytes_sysrandom_close(MOBIRandom *handle) {
# define NEEDS_CLOSE
MOBI_RET ret = MOBI_DRM_RANDOM_ERR;
if (handle->random_data_source_fd != -1 && close(handle->random_data_source_fd) == 0) {
handle->random_data_source_fd = -1;
ret = MOBI_SUCCESS;
}
# ifdef HAVE_LINUX_COMPATIBLE_GETRANDOM
if (handle->getrandom_available != 0) {
ret = MOBI_SUCCESS;
}
# endif
return ret;
}
# endif /* _WIN32 */
/**
@brief Read a buffer of random bytes
@param[in,out] handle Handle
@param[in,out] buf Buffer
@param[in] size Buffer size (up to 256 bytes)
@return MOBI_RET status code (on success MOBI_SUCCESS)
*/
static MOBI_RET mobi_randombytes_sysrandom_buf(MOBIRandom *handle, void *buf, const size_t size) {
# ifndef _WIN32
# ifdef HAVE_LINUX_COMPATIBLE_GETRANDOM
if (handle->getrandom_available != 0) {
return mobi_randombytes_linux_getrandom(buf, size);
}
# endif
if (handle->random_data_source_fd == -1 ||
mobi_safe_read(handle->random_data_source_fd, buf, size) != (ssize_t) size) {
return MOBI_DRM_RANDOM_ERR;
}
# else /* _WIN32 */
UNUSED(handle);
if (! RtlGenRandom((PVOID) buf, (ULONG) size)) {
return MOBI_DRM_RANDOM_ERR;
}
# endif /* _WIN32 */
return MOBI_SUCCESS;
}
#endif /* HAVE_SAFE_ARC4RANDOM */
/**
@brief Fill buffer with random bytes
@param[in,out] buf Buffer
@param[in] size Buffer size (up to 256 bytes)
@return MOBI_RET status code (on success MOBI_SUCCESS)
*/
MOBI_RET mobi_randombytes(void *buf, const size_t size) {
MOBIRandom handle = {
.random_data_source_fd = -1,
.getrandom_available = 0
};
MOBI_RET ret;
#ifdef NEEDS_INIT
ret = mobi_randombytes_sysrandom_init(&handle);
if (ret != MOBI_SUCCESS) {
return ret;
}
#endif
if (size > (size_t) 0U) {
ret = mobi_randombytes_sysrandom_buf(&handle, buf, size);
if (ret != MOBI_SUCCESS) {
debug_print("%s\n", "Generating random data failed");
return ret;
}
}
#ifdef NEEDS_CLOSE
if (mobi_randombytes_sysrandom_close(&handle) != MOBI_SUCCESS) {
debug_print("%s\n", "Closing random data source failed");
}
#endif
return MOBI_SUCCESS;
}

View file

@ -0,0 +1,25 @@
/** @file randombytes.h
*
* Copyright (c) 2021 Bartek Fabiszewski
* http://www.fabiszewski.net
*
* This file is part of libmobi.
* Licensed under LGPL, either version 3, or any later.
* See <http://www.gnu.org/licenses/>
*/
#ifndef libmobi_randombytes_h
#define libmobi_randombytes_h
#include "mobi.h"
/**
@brief Write n random bytes of high quality to buf
@param[in,out] buf Buffer to be filled with random bytes
@param[in] len Buffer length
@return On success returns MOBI_SUCCESS
*/
MOBI_RET mobi_randombytes(void *buf, const size_t len);
#endif

924
app/src/main/cpp/libmobi/src/read.c vendored Normal file
View file

@ -0,0 +1,924 @@
/** @file read.c
* @brief Functions for reading and parsing of MOBI document
*
* Copyright (c) 2014 Bartek Fabiszewski
* http://www.fabiszewski.net
*
* This file is part of libmobi.
* Licensed under LGPL, either version 3, or any later.
* See <http://www.gnu.org/licenses/>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "read.h"
#include "util.h"
#include "index.h"
#include "debug.h"
/**
@brief Read palm database header from file into MOBIData structure (MOBIPdbHeader)
@param[in,out] m MOBIData structure to be filled with read data
@param[in] file Filedescriptor to read from
@return MOBI_RET status code (on success MOBI_SUCCESS)
*/
MOBI_RET mobi_load_pdbheader(MOBIData *m, FILE *file) {
if (m == NULL) {
debug_print("%s", "Mobi structure not initialized\n");
return MOBI_INIT_FAILED;
}
if (!file) {
return MOBI_FILE_NOT_FOUND;
}
MOBIBuffer *buf = mobi_buffer_init(PALMDB_HEADER_LEN);
if (buf == NULL) {
debug_print("%s\n", "Memory allocation failed");
return MOBI_MALLOC_FAILED;
}
const size_t len = fread(buf->data, 1, PALMDB_HEADER_LEN, file);
if (len != PALMDB_HEADER_LEN) {
mobi_buffer_free(buf);
return MOBI_DATA_CORRUPT;
}
m->ph = calloc(1, sizeof(MOBIPdbHeader));
if (m->ph == NULL) {
debug_print("%s", "Memory allocation for pdb header failed\n");
mobi_buffer_free(buf);
return MOBI_MALLOC_FAILED;
}
/* parse header */
mobi_buffer_getstring(m->ph->name, buf, PALMDB_NAME_SIZE_MAX);
m->ph->attributes = mobi_buffer_get16(buf);
m->ph->version = mobi_buffer_get16(buf);
m->ph->ctime = mobi_buffer_get32(buf);
m->ph->mtime = mobi_buffer_get32(buf);
m->ph->btime = mobi_buffer_get32(buf);
m->ph->mod_num = mobi_buffer_get32(buf);
m->ph->appinfo_offset = mobi_buffer_get32(buf);
m->ph->sortinfo_offset = mobi_buffer_get32(buf);
mobi_buffer_getstring(m->ph->type, buf, 4);
mobi_buffer_getstring(m->ph->creator, buf, 4);
m->ph->uid = mobi_buffer_get32(buf);
m->ph->next_rec = mobi_buffer_get32(buf);
m->ph->rec_count = mobi_buffer_get16(buf);
mobi_buffer_free(buf);
return MOBI_SUCCESS;
}
/**
@brief Read list of database records from file into MOBIData structure (MOBIPdbRecord)
@param[in,out] m MOBIData structure to be filled with read data
@param[in] file Filedescriptor to read from
@return MOBI_RET status code (on success MOBI_SUCCESS)
*/
MOBI_RET mobi_load_reclist(MOBIData *m, FILE *file) {
if (m == NULL) {
debug_print("%s", "Mobi structure not initialized\n");
return MOBI_INIT_FAILED;
}
if (!file) {
debug_print("%s", "File not ready\n");
return MOBI_FILE_NOT_FOUND;
}
m->rec = calloc(1, sizeof(MOBIPdbRecord));
if (m->rec == NULL) {
debug_print("%s", "Memory allocation for pdb record failed\n");
return MOBI_MALLOC_FAILED;
}
MOBIPdbRecord *curr = m->rec;
for (int i = 0; i < m->ph->rec_count; i++) {
MOBIBuffer *buf = mobi_buffer_init(PALMDB_RECORD_INFO_SIZE);
if (buf == NULL) {
debug_print("%s\n", "Memory allocation failed");
return MOBI_MALLOC_FAILED;
}
const size_t len = fread(buf->data, 1, PALMDB_RECORD_INFO_SIZE, file);
if (len != PALMDB_RECORD_INFO_SIZE) {
mobi_buffer_free(buf);
return MOBI_DATA_CORRUPT;
}
if (i > 0) {
curr->next = calloc(1, sizeof(MOBIPdbRecord));
if (curr->next == NULL) {
debug_print("%s", "Memory allocation for pdb record failed\n");
mobi_buffer_free(buf);
return MOBI_MALLOC_FAILED;
}
curr = curr->next;
}
curr->offset = mobi_buffer_get32(buf);
curr->attributes = mobi_buffer_get8(buf);
const uint8_t h = mobi_buffer_get8(buf);
const uint16_t l = mobi_buffer_get16(buf);
curr->uid = (uint32_t) h << 16 | l;
curr->next = NULL;
mobi_buffer_free(buf);
}
return MOBI_SUCCESS;
}
/**
@brief Read record data and size from file into MOBIData structure (MOBIPdbRecord)
@param[in,out] m MOBIData structure to be filled with read data
@param[in] file Filedescriptor to read from
@return MOBI_RET status code (on success MOBI_SUCCESS)
*/
MOBI_RET mobi_load_rec(MOBIData *m, FILE *file) {
MOBI_RET ret;
if (m == NULL) {
debug_print("%s", "Mobi structure not initialized\n");
return MOBI_INIT_FAILED;
}
MOBIPdbRecord *curr = m->rec;
while (curr != NULL) {
MOBIPdbRecord *next;
size_t size;
if (curr->next != NULL) {
next = curr->next;
size = next->offset - curr->offset;
} else {
fseek(file, 0, SEEK_END);
long diff = ftell(file) - curr->offset;
if (diff <= 0) {
debug_print("Wrong record size: %li\n", diff);
return MOBI_DATA_CORRUPT;
}
size = (size_t) diff;
next = NULL;
}
curr->size = size;
ret = mobi_load_recdata(curr, file);
if (ret != MOBI_SUCCESS) {
debug_print("Error loading record uid %i data\n", curr->uid);
mobi_free_rec(m);
return ret;
}
curr = next;
}
return MOBI_SUCCESS;
}
/**
@brief Read record data from file into MOBIPdbRecord structure
@param[in,out] rec MOBIPdbRecord structure to be filled with read data
@param[in] file Filedescriptor to read from
@return MOBI_RET status code (on success MOBI_SUCCESS)
*/
MOBI_RET mobi_load_recdata(MOBIPdbRecord *rec, FILE *file) {
const int ret = fseek(file, rec->offset, SEEK_SET);
if (ret != 0) {
debug_print("Record %i not found\n", rec->uid);
return MOBI_DATA_CORRUPT;
}
rec->data = malloc(rec->size);
if (rec->data == NULL) {
debug_print("%s", "Memory allocation for pdb record data failed\n");
return MOBI_MALLOC_FAILED;
}
const size_t len = fread(rec->data, 1, rec->size, file);
if (len < rec->size) {
debug_print("Truncated data in record %i\n", rec->uid);
return MOBI_DATA_CORRUPT;
}
return MOBI_SUCCESS;
}
/**
@brief Parse EXTH header from Record 0 into MOBIData structure (MOBIExthHeader)
@param[in,out] m MOBIData structure to be filled with parsed data
@param[in] buf MOBIBuffer buffer to read from
@return MOBI_RET status code (on success MOBI_SUCCESS)
*/
MOBI_RET mobi_parse_extheader(MOBIData *m, MOBIBuffer *buf) {
if (m == NULL) {
debug_print("%s", "Mobi structure not initialized\n");
return MOBI_INIT_FAILED;
}
char exth_magic[5];
const size_t header_length = 12;
mobi_buffer_getstring(exth_magic, buf, 4);
const size_t exth_length = mobi_buffer_get32(buf) - header_length;
const size_t rec_count = mobi_buffer_get32(buf);
if (strncmp(exth_magic, EXTH_MAGIC, 4) != 0 ||
exth_length + buf->offset > buf->maxlen ||
rec_count == 0 || rec_count > MOBI_EXTH_MAXCNT) {
debug_print("%s", "Sanity checks for EXTH header failed\n");
return MOBI_DATA_CORRUPT;
}
const size_t saved_maxlen = buf->maxlen;
buf->maxlen = exth_length + buf->offset;
m->eh = calloc(1, sizeof(MOBIExthHeader));
if (m->eh == NULL) {
debug_print("%s", "Memory allocation for EXTH header failed\n");
return MOBI_MALLOC_FAILED;
}
MOBIExthHeader *curr = m->eh;
for (size_t i = 0; i < rec_count; i++) {
if (curr->data) {
curr->next = calloc(1, sizeof(MOBIExthHeader));
if (curr->next == NULL) {
debug_print("%s", "Memory allocation for EXTH header failed\n");
mobi_free_eh(m);
return MOBI_MALLOC_FAILED;
}
curr = curr->next;
}
curr->tag = mobi_buffer_get32(buf);
/* data size = record size minus 8 bytes for uid and size */
curr->size = mobi_buffer_get32(buf) - 8;
if (curr->size == 0) {
debug_print("Skip record %i, data too short\n", curr->tag);
continue;
}
if (buf->offset + curr->size > buf->maxlen) {
debug_print("Record %i too long\n", curr->tag);
mobi_free_eh(m);
return MOBI_DATA_CORRUPT;
}
curr->data = malloc(curr->size);
if (curr->data == NULL) {
debug_print("Memory allocation for EXTH record %i failed\n", curr->tag);
mobi_free_eh(m);
return MOBI_MALLOC_FAILED;
}
mobi_buffer_getraw(curr->data, buf, curr->size);
curr->next = NULL;
}
buf->maxlen = saved_maxlen;
return MOBI_SUCCESS;
}
/**
@brief Parse MOBI header from Record 0 into MOBIData structure (MOBIMobiHeader)
@param[in,out] m MOBIData structure to be filled with parsed data
@param[in] buf MOBIBuffer buffer to read from
@return MOBI_RET status code (on success MOBI_SUCCESS)
*/
MOBI_RET mobi_parse_mobiheader(MOBIData *m, MOBIBuffer *buf) {
int isKF8 = 0;
if (m == NULL) {
debug_print("%s", "Mobi structure not initialized\n");
return MOBI_INIT_FAILED;
}
m->mh = calloc(1, sizeof(MOBIMobiHeader));
if (m->mh == NULL) {
debug_print("%s", "Memory allocation for MOBI header failed\n");
return MOBI_MALLOC_FAILED;
}
mobi_buffer_getstring(m->mh->mobi_magic, buf, 4);
mobi_buffer_dup32(&m->mh->header_length, buf);
if (strcmp(m->mh->mobi_magic, MOBI_MAGIC) != 0 || m->mh->header_length == NULL) {
debug_print("%s", "MOBI header not found\n");
mobi_free_mh(m->mh);
m->mh = NULL;
return MOBI_DATA_CORRUPT;
}
const size_t saved_maxlen = buf->maxlen;
/* some old files declare zero length mobi header, try to read first 24 bytes anyway */
uint32_t header_length = (*m->mh->header_length > 0) ? *m->mh->header_length : 24;
/* read only declared MOBI header length (curr offset minus 8 already read bytes) */
const size_t left_length = header_length + buf->offset - 8;
buf->maxlen = saved_maxlen < left_length ? saved_maxlen : left_length;
mobi_buffer_dup32(&m->mh->mobi_type, buf);
uint32_t encoding = mobi_buffer_get32(buf);
if (encoding == 1252) {
m->mh->text_encoding = malloc(sizeof(MOBIEncoding));
if (m->mh->text_encoding == NULL) {
debug_print("%s", "Memory allocation for MOBI header failed\n");
return MOBI_MALLOC_FAILED;
}
*m->mh->text_encoding = MOBI_CP1252;
}
else if (encoding == 65001) {
m->mh->text_encoding = malloc(sizeof(MOBIEncoding));
if (m->mh->text_encoding == NULL) {
debug_print("%s", "Memory allocation for MOBI header failed\n");
return MOBI_MALLOC_FAILED;
}
*m->mh->text_encoding = MOBI_UTF8;
} else {
debug_print("Unknown encoding in mobi header: %i\n", encoding);
}
mobi_buffer_dup32(&m->mh->uid, buf);
mobi_buffer_dup32(&m->mh->version, buf);
if (header_length >= MOBI_HEADER_V7_SIZE
&& m->mh->version && *m->mh->version == 8) {
isKF8 = 1;
}
mobi_buffer_dup32(&m->mh->orth_index, buf);
mobi_buffer_dup32(&m->mh->infl_index, buf);
mobi_buffer_dup32(&m->mh->names_index, buf);
mobi_buffer_dup32(&m->mh->keys_index, buf);
mobi_buffer_dup32(&m->mh->extra0_index, buf);
mobi_buffer_dup32(&m->mh->extra1_index, buf);
mobi_buffer_dup32(&m->mh->extra2_index, buf);
mobi_buffer_dup32(&m->mh->extra3_index, buf);
mobi_buffer_dup32(&m->mh->extra4_index, buf);
mobi_buffer_dup32(&m->mh->extra5_index, buf);
mobi_buffer_dup32(&m->mh->non_text_index, buf);
mobi_buffer_dup32(&m->mh->full_name_offset, buf);
mobi_buffer_dup32(&m->mh->full_name_length, buf);
mobi_buffer_dup32(&m->mh->locale, buf);
mobi_buffer_dup32(&m->mh->dict_input_lang, buf);
mobi_buffer_dup32(&m->mh->dict_output_lang, buf);
mobi_buffer_dup32(&m->mh->min_version, buf);
mobi_buffer_dup32(&m->mh->image_index, buf);
mobi_buffer_dup32(&m->mh->huff_rec_index, buf);
mobi_buffer_dup32(&m->mh->huff_rec_count, buf);
mobi_buffer_dup32(&m->mh->datp_rec_index, buf);
mobi_buffer_dup32(&m->mh->datp_rec_count, buf);
mobi_buffer_dup32(&m->mh->exth_flags, buf);
mobi_buffer_seek(buf, 32); /* 32 unknown bytes */
mobi_buffer_dup32(&m->mh->unknown6, buf);
mobi_buffer_dup32(&m->mh->drm_offset, buf);
mobi_buffer_dup32(&m->mh->drm_count, buf);
mobi_buffer_dup32(&m->mh->drm_size, buf);
mobi_buffer_dup32(&m->mh->drm_flags, buf);
mobi_buffer_seek(buf, 8); /* 8 unknown bytes */
if (isKF8) {
mobi_buffer_dup32(&m->mh->fdst_index, buf);
} else {
mobi_buffer_dup16(&m->mh->first_text_index, buf);
mobi_buffer_dup16(&m->mh->last_text_index, buf);
}
mobi_buffer_dup32(&m->mh->fdst_section_count, buf);
mobi_buffer_dup32(&m->mh->fcis_index, buf);
mobi_buffer_dup32(&m->mh->fcis_count, buf);
mobi_buffer_dup32(&m->mh->flis_index, buf);
mobi_buffer_dup32(&m->mh->flis_count, buf);
mobi_buffer_dup32(&m->mh->unknown10, buf);
mobi_buffer_dup32(&m->mh->unknown11, buf);
mobi_buffer_dup32(&m->mh->srcs_index, buf);
mobi_buffer_dup32(&m->mh->srcs_count, buf);
mobi_buffer_dup32(&m->mh->unknown12, buf);
mobi_buffer_dup32(&m->mh->unknown13, buf);
mobi_buffer_seek(buf, 2); /* 2 byte fill */
mobi_buffer_dup16(&m->mh->extra_flags, buf);
mobi_buffer_dup32(&m->mh->ncx_index, buf);
if (isKF8) {
mobi_buffer_dup32(&m->mh->fragment_index, buf);
mobi_buffer_dup32(&m->mh->skeleton_index, buf);
} else {
mobi_buffer_dup32(&m->mh->unknown14, buf);
mobi_buffer_dup32(&m->mh->unknown15, buf);
}
mobi_buffer_dup32(&m->mh->datp_index, buf);
if (isKF8) {
mobi_buffer_dup32(&m->mh->guide_index, buf);
} else {
mobi_buffer_dup32(&m->mh->unknown16, buf);
}
mobi_buffer_dup32(&m->mh->unknown17, buf);
mobi_buffer_dup32(&m->mh->unknown18, buf);
mobi_buffer_dup32(&m->mh->unknown19, buf);
mobi_buffer_dup32(&m->mh->unknown20, buf);
if (buf->maxlen > buf->offset) {
debug_print("Skipping %zu unknown bytes in MOBI header\n", (buf->maxlen - buf->offset));
mobi_buffer_setpos(buf, buf->maxlen);
}
buf->maxlen = saved_maxlen;
/* get full name stored at m->mh->full_name_offset */
if (m->mh->full_name_offset && m->mh->full_name_length) {
const size_t saved_offset = buf->offset;
const uint32_t full_name_length = min(*m->mh->full_name_length, MOBI_TITLE_SIZEMAX);
mobi_buffer_setpos(buf, *m->mh->full_name_offset);
m->mh->full_name = malloc(full_name_length + 1);
if (m->mh->full_name == NULL) {
debug_print("%s", "Memory allocation for full name failed\n");
return MOBI_MALLOC_FAILED;
}
if (full_name_length) {
mobi_buffer_getstring(m->mh->full_name, buf, full_name_length);
} else {
m->mh->full_name[0] = '\0';
}
mobi_buffer_setpos(buf, saved_offset);
}
return MOBI_SUCCESS;
}
/**
@brief Parse Record 0 into MOBIData structure
This function will parse MOBIRecord0Header, MOBIMobiHeader and MOBIExthHeader
@param[in,out] m MOBIData structure to be filled with parsed data
@param[in] seqnumber Sequential number of the palm database record
@return MOBI_RET status code (on success MOBI_SUCCESS)
*/
MOBI_RET mobi_parse_record0(MOBIData *m, const size_t seqnumber) {
MOBI_RET ret;
if (m == NULL) {
debug_print("%s", "Mobi structure not initialized\n");
return MOBI_INIT_FAILED;
}
const MOBIPdbRecord *record0 = mobi_get_record_by_seqnumber(m, seqnumber);
if (record0 == NULL) {
debug_print("%s", "Record 0 not loaded\n");
return MOBI_DATA_CORRUPT;
}
if (record0->size < RECORD0_HEADER_LEN) {
debug_print("%s", "Record 0 too short\n");
return MOBI_DATA_CORRUPT;
}
MOBIBuffer *buf = mobi_buffer_init_null(record0->data, record0->size);
if (buf == NULL) {
debug_print("%s\n", "Memory allocation failed");
return MOBI_MALLOC_FAILED;
}
m->rh = calloc(1, sizeof(MOBIRecord0Header));
if (m->rh == NULL) {
debug_print("%s", "Memory allocation for record 0 header failed\n");
mobi_buffer_free_null(buf);
return MOBI_MALLOC_FAILED;
}
/* parse palmdoc header */
const uint16_t compression = mobi_buffer_get16(buf);
mobi_buffer_seek(buf, 2); // unused 2 bytes, zeroes
if ((compression != MOBI_COMPRESSION_NONE &&
compression != MOBI_COMPRESSION_PALMDOC &&
compression != MOBI_COMPRESSION_HUFFCDIC)) {
debug_print("Wrong record0 header: %c%c%c%c\n", record0->data[0], record0->data[1], record0->data[2], record0->data[3]);
mobi_buffer_free_null(buf);
free(m->rh);
m->rh = NULL;
return MOBI_DATA_CORRUPT;
}
m->rh->compression_type = compression;
m->rh->text_length = mobi_buffer_get32(buf);
m->rh->text_record_count = mobi_buffer_get16(buf);
m->rh->text_record_size = mobi_buffer_get16(buf);
m->rh->encryption_type = mobi_buffer_get16(buf);
m->rh->unknown1 = mobi_buffer_get16(buf);
if (mobi_is_mobipocket(m)) {
/* parse mobi header if present */
ret = mobi_parse_mobiheader(m, buf);
if (ret == MOBI_SUCCESS) {
/* parse exth header if present */
mobi_parse_extheader(m, buf);
}
}
mobi_buffer_free_null(buf);
return MOBI_SUCCESS;
}
/**
@brief Calculate the size of extra bytes at the end of text record
@param[in] record MOBIPdbRecord structure containing the record
@param[in] flags Flags from MOBI header (extra_flags)
@return The size of trailing bytes, MOBI_NOTSET on failure
*/
size_t mobi_get_record_extrasize(const MOBIPdbRecord *record, const uint16_t flags) {
size_t extra_size = 0;
MOBIBuffer *buf = mobi_buffer_init_null(record->data, record->size);
if (buf == NULL) {
debug_print("%s", "Buffer init in extrasize failed\n");
return MOBI_NOTSET;
}
/* set pointer at the end of the record data */
mobi_buffer_setpos(buf, buf->maxlen - 1);
for (int bit = 15; bit > 0; bit--) {
if (flags & (1 << bit)) {
/* bit is set */
size_t len = 0;
/* size contains varlen itself and optional data */
const uint32_t size = mobi_buffer_get_varlen_dec(buf, &len);
/* skip data */
/* TODO: read and store in record struct */
mobi_buffer_seek(buf, - (int)(size - len));
extra_size += size;
}
}
/* check bit 0 */
if (flags & 1) {
const uint8_t b = mobi_buffer_get8(buf);
/* two first bits hold size */
extra_size += (b & 0x3) + 1;
}
mobi_buffer_free_null(buf);
return extra_size;
}
/**
@brief Calculate the size of extra multibyte section at the end of text record
@param[in] record MOBIPdbRecord structure containing the record
@param[in] flags Flags from MOBI header (extra_flags)
@return The size of trailing bytes, MOBI_NOTSET on failure
*/
size_t mobi_get_record_mb_extrasize(const MOBIPdbRecord *record, const uint16_t flags) {
size_t extra_size = 0;
if (flags & 1) {
MOBIBuffer *buf = mobi_buffer_init_null(record->data, record->size);
if (buf == NULL) {
debug_print("%s", "Buffer init in extrasize failed\n");
return MOBI_NOTSET;
}
/* set pointer at the end of the record data */
mobi_buffer_setpos(buf, buf->maxlen - 1);
for (int bit = 15; bit > 0; bit--) {
if (flags & (1 << bit)) {
/* bit is set */
size_t len = 0;
/* size contains varlen itself and optional data */
const uint32_t size = mobi_buffer_get_varlen_dec(buf, &len);
/* skip data */
/* TODO: read and store in record struct */
mobi_buffer_seek(buf, - (int)(size - len));
}
}
/* read multibyte section */
const uint8_t b = mobi_buffer_get8(buf);
/* two first bits hold size */
extra_size += (b & 0x3) + 1;
mobi_buffer_free_null(buf);
}
return extra_size;
}
/**
@brief Parse HUFF record into MOBIHuffCdic structure
@param[in,out] huffcdic MOBIHuffCdic structure to be filled with parsed data
@param[in] record MOBIPdbRecord structure containing the record
@return MOBI_RET status code (on success MOBI_SUCCESS)
*/
MOBI_RET mobi_parse_huff(MOBIHuffCdic *huffcdic, const MOBIPdbRecord *record) {
MOBIBuffer *buf = mobi_buffer_init_null(record->data, record->size);
if (buf == NULL) {
debug_print("%s\n", "Memory allocation failed");
return MOBI_MALLOC_FAILED;
}
char huff_magic[5];
mobi_buffer_getstring(huff_magic, buf, 4);
const size_t header_length = mobi_buffer_get32(buf);
if (strncmp(huff_magic, HUFF_MAGIC, 4) != 0 || header_length < HUFF_HEADER_LEN) {
debug_print("HUFF wrong magic: %s\n", huff_magic);
mobi_buffer_free_null(buf);
return MOBI_DATA_CORRUPT;
}
const size_t data1_offset = mobi_buffer_get32(buf);
const size_t data2_offset = mobi_buffer_get32(buf);
/* skip little-endian table offsets */
mobi_buffer_setpos(buf, data1_offset);
if (buf->offset + (256 * 4) > buf->maxlen) {
debug_print("%s", "HUFF data1 too short\n");
mobi_buffer_free_null(buf);
return MOBI_DATA_CORRUPT;
}
/* read 256 indices from data1 big-endian */
for (int i = 0; i < 256; i++) {
huffcdic->table1[i] = mobi_buffer_get32(buf);
}
mobi_buffer_setpos(buf, data2_offset);
if (buf->offset + (64 * 4) > buf->maxlen) {
debug_print("%s", "HUFF data2 too short\n");
mobi_buffer_free_null(buf);
return MOBI_DATA_CORRUPT;
}
/* read 32 mincode-maxcode pairs from data2 big-endian */
huffcdic->mincode_table[0] = 0;
huffcdic->maxcode_table[0] = 0xFFFFFFFF;
for (int i = 1; i < HUFF_CODETABLE_SIZE; i++) {
const uint32_t mincode = mobi_buffer_get32(buf);
const uint32_t maxcode = mobi_buffer_get32(buf);
huffcdic->mincode_table[i] = mincode << (32 - i);
huffcdic->maxcode_table[i] = ((maxcode + 1) << (32 - i)) - 1;
}
mobi_buffer_free_null(buf);
return MOBI_SUCCESS;
}
/**
@brief Parse CDIC record into MOBIHuffCdic structure
@param[in,out] huffcdic MOBIHuffCdic structure to be filled with parsed data
@param[in] record MOBIPdbRecord structure containing the record
@param[in] num Number of CDIC record in a set, starting from zero
@return MOBI_RET status code (on success MOBI_SUCCESS)
*/
MOBI_RET mobi_parse_cdic(MOBIHuffCdic *huffcdic, const MOBIPdbRecord *record, const size_t num) {
MOBIBuffer *buf = mobi_buffer_init_null(record->data, record->size);
if (buf == NULL) {
debug_print("%s\n", "Memory allocation failed");
return MOBI_MALLOC_FAILED;
}
char cdic_magic[5];
mobi_buffer_getstring(cdic_magic, buf, 4);
const size_t header_length = mobi_buffer_get32(buf);
if (strncmp(cdic_magic, CDIC_MAGIC, 4) != 0 || header_length < CDIC_HEADER_LEN) {
debug_print("CDIC wrong magic: %s or declared header length: %zu\n", cdic_magic, header_length);
mobi_buffer_free_null(buf);
return MOBI_DATA_CORRUPT;
}
/* variables in huffcdic initialized to zero with calloc */
/* save initial count and length */
size_t index_count = mobi_buffer_get32(buf);
const size_t code_length = mobi_buffer_get32(buf);
if (huffcdic->code_length && huffcdic->code_length != code_length) {
debug_print("CDIC different code length %zu in record %i, previous was %zu\n", huffcdic->code_length, record->uid, code_length);
mobi_buffer_free_null(buf);
return MOBI_DATA_CORRUPT;
}
if (huffcdic->index_count && huffcdic->index_count != index_count) {
debug_print("CDIC different index count %zu in record %i, previous was %zu\n", huffcdic->index_count, record->uid, index_count);
mobi_buffer_free_null(buf);
return MOBI_DATA_CORRUPT;
}
if (code_length == 0 || code_length > HUFF_CODELEN_MAX) {
debug_print("Code length exceeds sanity checks (%zu)\n", code_length);
mobi_buffer_free_null(buf);
return MOBI_DATA_CORRUPT;
}
huffcdic->code_length = code_length;
huffcdic->index_count = index_count;
if (index_count == 0) {
debug_print("%s", "CDIC index count is null");
mobi_buffer_free_null(buf);
return MOBI_DATA_CORRUPT;
}
/* allocate memory for symbol offsets if not already allocated */
if (num == 0) {
if (index_count > (1 << HUFF_CODELEN_MAX) * CDIC_RECORD_MAXCNT) {
debug_print("CDIC index count too large %zu\n", index_count);
mobi_buffer_free_null(buf);
return MOBI_DATA_CORRUPT;
}
huffcdic->symbol_offsets = malloc(index_count * sizeof(*huffcdic->symbol_offsets));
if (huffcdic->symbol_offsets == NULL) {
debug_print("%s", "CDIC cannot allocate memory");
mobi_buffer_free_null(buf);
return MOBI_MALLOC_FAILED;
}
}
index_count -= huffcdic->index_read;
/* limit number of records read to code_length bits */
if (index_count >> code_length) {
index_count = (1 << code_length);
}
if (buf->offset + (index_count * 2) > buf->maxlen) {
debug_print("%s", "CDIC indices data too short\n");
mobi_buffer_free_null(buf);
return MOBI_DATA_CORRUPT;
}
/* read i * 2 byte big-endian indices */
while (index_count--) {
const uint16_t offset = mobi_buffer_get16(buf);
const size_t saved_pos = buf->offset;
mobi_buffer_setpos(buf, offset + CDIC_HEADER_LEN);
const size_t len = mobi_buffer_get16(buf) & 0x7fff;
if (buf->error != MOBI_SUCCESS || buf->offset + len > buf->maxlen) {
debug_print("%s", "CDIC offset beyond buffer\n");
mobi_buffer_free_null(buf);
return MOBI_DATA_CORRUPT;
}
mobi_buffer_setpos(buf, saved_pos);
huffcdic->symbol_offsets[huffcdic->index_read++] = offset;
}
if (buf->offset + code_length > buf->maxlen) {
debug_print("%s", "CDIC dictionary data too short\n");
mobi_buffer_free_null(buf);
return MOBI_DATA_CORRUPT;
}
/* copy pointer to data */
huffcdic->symbols[num] = record->data + CDIC_HEADER_LEN;
/* free buffer */
mobi_buffer_free_null(buf);
return MOBI_SUCCESS;
}
/**
@brief Parse a set of HUFF and CDIC records into MOBIHuffCdic structure
@param[in] m MOBIData structure with loaded MOBI document
@param[in,out] huffcdic MOBIHuffCdic structure to be filled with parsed data
@return MOBI_RET status code (on success MOBI_SUCCESS)
*/
MOBI_RET mobi_parse_huffdic(const MOBIData *m, MOBIHuffCdic *huffcdic) {
MOBI_RET ret;
const size_t offset = mobi_get_kf8offset(m);
if (m->mh == NULL || m->mh->huff_rec_index == NULL || m->mh->huff_rec_count == NULL) {
debug_print("%s", "HUFF/CDIC records metadata not found in MOBI header\n");
return MOBI_DATA_CORRUPT;
}
const size_t huff_rec_index = *m->mh->huff_rec_index + offset;
const size_t huff_rec_count = *m->mh->huff_rec_count;
if (huff_rec_count > HUFF_RECORD_MAXCNT) {
debug_print("Too many HUFF record (%zu)\n", huff_rec_count);
return MOBI_DATA_CORRUPT;
}
const MOBIPdbRecord *curr = mobi_get_record_by_seqnumber(m, huff_rec_index);
if (curr == NULL || huff_rec_count < 2) {
debug_print("%s", "HUFF/CDIC record not found\n");
return MOBI_DATA_CORRUPT;
}
if (curr->size < HUFF_RECORD_MINSIZE) {
debug_print("HUFF record too short (%zu b)\n", curr->size);
return MOBI_DATA_CORRUPT;
}
ret = mobi_parse_huff(huffcdic, curr);
if (ret != MOBI_SUCCESS) {
debug_print("%s", "HUFF parsing failed\n");
return ret;
}
curr = curr->next;
/* allocate memory for symbols data in each CDIC record */
huffcdic->symbols = malloc((huff_rec_count - 1) * sizeof(*huffcdic->symbols));
if (huffcdic->symbols == NULL) {
debug_print("%s\n", "Memory allocation failed");
return MOBI_MALLOC_FAILED;
}
/* get following CDIC records */
size_t i = 0;
while (i < huff_rec_count - 1) {
if (curr == NULL) {
debug_print("%s\n", "CDIC record not found");
return MOBI_DATA_CORRUPT;
}
ret = mobi_parse_cdic(huffcdic, curr, i++);
if (ret != MOBI_SUCCESS) {
debug_print("%s", "CDIC parsing failed\n");
return ret;
}
curr = curr->next;
}
if (huffcdic->index_count != huffcdic->index_read) {
debug_print("CDIC: wrong read index count: %zu, total: %zu\n", huffcdic->index_read, huffcdic->index_count);
return MOBI_DATA_CORRUPT;
}
return MOBI_SUCCESS;
}
/**
@brief Parse FDST record into MOBIRawml structure (MOBIFdst member)
@param[in] m MOBIData structure with loaded MOBI document
@param[in,out] rawml MOBIRawml structure to be filled with parsed data
@return MOBI_RET status code (on success MOBI_SUCCESS)
*/
MOBI_RET mobi_parse_fdst(const MOBIData *m, MOBIRawml *rawml) {
if (m == NULL) {
debug_print("%s", "Mobi structure not initialized\n");
return MOBI_INIT_FAILED;
}
const size_t fdst_record_number = mobi_get_fdst_record_number(m);
if (fdst_record_number == MOBI_NOTSET) {
return MOBI_DATA_CORRUPT;
}
const MOBIPdbRecord *fdst_record = mobi_get_record_by_seqnumber(m, fdst_record_number);
if (fdst_record == NULL) {
return MOBI_DATA_CORRUPT;
}
MOBIBuffer *buf = mobi_buffer_init_null(fdst_record->data, fdst_record->size);
if (buf == NULL) {
debug_print("%s\n", "Memory allocation failed");
return MOBI_MALLOC_FAILED;
}
char fdst_magic[5];
mobi_buffer_getstring(fdst_magic, buf, 4);
const size_t data_offset = mobi_buffer_get32(buf);
const size_t section_count = mobi_buffer_get32(buf);
if (strncmp(fdst_magic, FDST_MAGIC, 4) != 0 ||
section_count <= 1 ||
section_count != *m->mh->fdst_section_count ||
data_offset != 12) {
debug_print("FDST wrong magic: %s, sections count: %zu or data offset: %zu\n", fdst_magic, section_count, data_offset);
mobi_buffer_free_null(buf);
return MOBI_DATA_CORRUPT;
}
if ((buf->maxlen - buf->offset) < section_count * 8) {
debug_print("%s", "Record FDST too short\n");
mobi_buffer_free_null(buf);
return MOBI_DATA_CORRUPT;
}
rawml->fdst = malloc(sizeof(MOBIFdst));
if (rawml->fdst == NULL) {
debug_print("%s\n", "Memory allocation failed");
mobi_buffer_free_null(buf);
return MOBI_MALLOC_FAILED;
}
rawml->fdst->fdst_section_count = section_count;
rawml->fdst->fdst_section_starts = malloc(sizeof(*rawml->fdst->fdst_section_starts) * section_count);
if (rawml->fdst->fdst_section_starts == NULL) {
debug_print("%s\n", "Memory allocation failed");
mobi_buffer_free_null(buf);
free(rawml->fdst);
rawml->fdst = NULL;
return MOBI_MALLOC_FAILED;
}
rawml->fdst->fdst_section_ends = malloc(sizeof(*rawml->fdst->fdst_section_ends) * section_count);
if (rawml->fdst->fdst_section_ends == NULL) {
debug_print("%s\n", "Memory allocation failed");
mobi_buffer_free_null(buf);
free(rawml->fdst->fdst_section_starts);
free(rawml->fdst);
rawml->fdst = NULL;
return MOBI_MALLOC_FAILED;
}
size_t i = 0;
while (i < section_count) {
rawml->fdst->fdst_section_starts[i] = mobi_buffer_get32(buf);
rawml->fdst->fdst_section_ends[i] = mobi_buffer_get32(buf);
debug_print("FDST[%zu]:\t%i\t%i\n", i, rawml->fdst->fdst_section_starts[i], rawml->fdst->fdst_section_ends[i]);
i++;
}
mobi_buffer_free_null(buf);
return MOBI_SUCCESS;
}
/**
@brief Read MOBI document from file into MOBIData structure
@param[in,out] m MOBIData structure to be filled with read data
@param[in] file File descriptor to read from
@return MOBI_RET status code (on success MOBI_SUCCESS)
*/
MOBI_RET mobi_load_file(MOBIData *m, FILE *file) {
MOBI_RET ret;
if (m == NULL) {
debug_print("%s", "Mobi structure not initialized\n");
return MOBI_INIT_FAILED;
}
ret = mobi_load_pdbheader(m, file);
if (ret != MOBI_SUCCESS) {
return ret;
}
if (strcmp(m->ph->type, "BOOK") != 0 && strcmp(m->ph->type, "TEXt") != 0) {
debug_print("Unsupported file type: %s\n", m->ph->type);
return MOBI_FILE_UNSUPPORTED;
}
if (m->ph->rec_count == 0) {
debug_print("%s", "No records found\n");
return MOBI_DATA_CORRUPT;
}
ret = mobi_load_reclist(m, file);
if (ret != MOBI_SUCCESS) {
return ret;
}
ret = mobi_load_rec(m, file);
if (ret != MOBI_SUCCESS) {
return ret;
}
ret = mobi_parse_record0(m, 0);
if (ret != MOBI_SUCCESS) {
return ret;
}
if (m->rh && m->rh->encryption_type == MOBI_ENCRYPTION_V1) {
/* try to set key for encryption type 1 */
debug_print("Trying to set key for encryption type 1%s", "\n");
mobi_drm_setkey(m, NULL);
}
/* if EXTH is loaded parse KF8 record0 for hybrid KF7/KF8 file */
if (m->eh) {
const size_t boundary_rec_number = mobi_get_kf8boundary_seqnumber(m);
if (boundary_rec_number != MOBI_NOTSET && boundary_rec_number < UINT32_MAX) {
/* it is a hybrid KF7/KF8 file */
m->kf8_boundary_offset = (uint32_t) boundary_rec_number;
m->next = mobi_init();
/* link pdb header and records data to KF8data structure */
m->next->ph = m->ph;
m->next->rec = m->rec;
m->next->drm_key = m->drm_key;
m->next->internals = m->internals;
/* close next loop */
m->next->next = m;
ret = mobi_parse_record0(m->next, boundary_rec_number + 1);
if (ret != MOBI_SUCCESS) {
return ret;
}
/* swap to kf8 part if use_kf8 flag is set */
if (m->use_kf8) {
mobi_swap_mobidata(m);
}
}
}
return MOBI_SUCCESS;
}
/**
@brief Read MOBI document from a path into MOBIData structure
@param[in,out] m MOBIData structure to be filled with read data
@param[in] path Path to a MOBI document on disk (eg. /home/me/test.mobi)
@return MOBI_RET status code (on success MOBI_SUCCESS)
*/
MOBI_RET mobi_load_filename(MOBIData *m, const char *path) {
FILE *file = fopen(path, "rb");
if (file == NULL) {
debug_print("%s", "File not found\n");
return MOBI_FILE_NOT_FOUND;
}
const MOBI_RET ret = mobi_load_file(m, file);
fclose(file);
return ret;
}

28
app/src/main/cpp/libmobi/src/read.h vendored Normal file
View file

@ -0,0 +1,28 @@
/** @file read.h
*
* Copyright (c) 2014 Bartek Fabiszewski
* http://www.fabiszewski.net
*
* This file is part of libmobi.
* Licensed under LGPL, either version 3, or any later.
* See <http://www.gnu.org/licenses/>
*/
#ifndef libmobi_read_h
#define libmobi_read_h
#include "config.h"
#include "mobi.h"
#include "memory.h"
#include "compression.h"
#define MOBI_EXTH_MAXCNT 1024
MOBI_RET mobi_parse_fdst(const MOBIData *m, MOBIRawml *rawml);
MOBI_RET mobi_parse_huffdic(const MOBIData *m, MOBIHuffCdic *cdic);
MOBI_RET mobi_load_pdbheader(MOBIData *m, FILE *file);
MOBI_RET mobi_load_reclist(MOBIData *m, FILE *file);
MOBI_RET mobi_load_rec(MOBIData *m, FILE *file);
MOBI_RET mobi_load_recdata(MOBIPdbRecord *rec, FILE *file);
#endif

281
app/src/main/cpp/libmobi/src/sha1.c vendored Normal file
View file

@ -0,0 +1,281 @@
/*
SHA-1 in C
By Steve Reid <sreid@sea-to-sky.net>
100% Public Domain
-----------------
Modified 7/98
By James H. Brown <jbrown@burgoyne.com>
Still 100% Public Domain
Corrected a problem which generated improper hash values on 16 bit machines
Routine SHA1Update changed from
void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int
len)
to
void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned
long len)
The 'len' parameter was declared an int which works fine on 32 bit machines.
However, on 16 bit machines an int is too small for the shifts being done
against
it. This caused the hash function to generate incorrect values if len was
greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update().
Since the file IO in main() reads 16K at a time, any file 8K or larger would
be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million
"a"s).
I also changed the declaration of variables i & j in SHA1Update to
unsigned long from unsigned int for the same reason.
These changes should make no difference to any 32 bit implementations since
an
int and a long are the same size in those environments.
--
I also corrected a few compiler warnings generated by Borland C.
1. Added #include <process.h> for exit() prototype
2. Removed unused variable 'j' in SHA1Final
3. Changed exit(0) to return(0) at end of main.
ALL changes I made can be located by searching for comments containing 'JHB'
-----------------
Modified 8/98
By Steve Reid <sreid@sea-to-sky.net>
Still 100% public domain
1- Removed #include <process.h> and used return() instead of exit()
2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall)
3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net
-----------------
Modified 4/01
By Saul Kravitz <Saul.Kravitz@celera.com>
Still 100% PD
Modified to run on Compaq Alpha hardware.
-----------------
Modified 07/2002
By Ralph Giles <giles@ghostscript.com>
Still 100% public domain
modified for use with stdint types, autoconf
code cleanup, removed attribution comments
switched SHA1Final() argument order for consistency
use SHA1_ prefix for public api
move public api to sha1.h
*/
/*
Test Vectors (from FIPS PUB 180-1)
"abc"
A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
A million repetitions of "a"
34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
*/
/* #define SHA1HANDSOFF */
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include "sha1.h"
#define UNUSED(x) (void)(x)
void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64]);
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
/* blk0() and blk() perform the initial expand. */
/* I got the idea of expanding during the round function from SSLeay */
#define blk0(i) (block->l[i] = (((uint32_t)block->c[i*4 ] << 24) | \
((uint32_t)block->c[i*4 + 1] << 16) | \
((uint32_t)block->c[i*4 + 2] << 8) | \
((uint32_t)block->c[i*4 + 3] )))
#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
^block->l[(i+2)&15]^block->l[i&15],1))
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
#ifdef VERBOSE /* SAK */
void SHAPrintContext(SHA1_CTX *context, char *msg) {
printf("%s (%d,%d) %x %x %x %x %x\n",
msg,
context->count[0], context->count[1],
context->state[0],
context->state[1],
context->state[2],
context->state[3],
context->state[4]);
}
#endif /* VERBOSE */
/* Hash a single 512-bit block. This is the core of the algorithm. */
void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64]) {
uint32_t a, b, c, d, e;
typedef union {
uint8_t c[64];
uint32_t l[16];
} CHAR64LONG16;
CHAR64LONG16* block;
#ifdef SHA1HANDSOFF
static uint8_t workspace[64];
block = (CHAR64LONG16*) workspace;
memcpy(block, buffer, 64);
#else
block = (CHAR64LONG16*) buffer;
#endif
/* Copy context->state[] to working vars */
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
/* 4 rounds of 20 operations each. Loop unrolled. */
R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
/* Add the working vars back into context.state[] */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
/* Wipe variables */
a = b = c = d = e = 0;
UNUSED(a);UNUSED(b);UNUSED(c);UNUSED(d);UNUSED(e);
}
/* SHA1Init - Initialize new context */
void SHA1_Init(SHA1_CTX* context) {
/* SHA1 initialization constants */
context->state[0] = 0x67452301;
context->state[1] = 0xEFCDAB89;
context->state[2] = 0x98BADCFE;
context->state[3] = 0x10325476;
context->state[4] = 0xC3D2E1F0;
context->count[0] = context->count[1] = 0;
}
/* Run your data through this. */
void SHA1_Update(SHA1_CTX* context, const uint8_t* data, const size_t len) {
size_t i, j;
#ifdef VERBOSE
SHAPrintContext(context, "before");
#endif
j = (context->count[0] >> 3) & 63;
if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
context->count[1] += (len >> 29);
if ((j + len) > 63) {
memcpy(&context->buffer[j], data, (i = 64-j));
SHA1_Transform(context->state, context->buffer);
for ( ; i + 63 < len; i += 64) {
SHA1_Transform(context->state, data + i);
}
j = 0;
}
else i = 0;
memcpy(&context->buffer[j], &data[i], len - i);
#ifdef VERBOSE
SHAPrintContext(context, "after ");
#endif
}
/* Add padding and return the message digest. */
void SHA1_Final(SHA1_CTX* context, uint8_t digest[SHA1_DIGEST_SIZE]) {
uint32_t i;
uint8_t finalcount[8];
for (i = 0; i < 8; i++) {
finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
>> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
}
SHA1_Update(context, (uint8_t *)"\200", 1);
while ((context->count[0] & 504) != 448) {
SHA1_Update(context, (uint8_t *)"\0", 1);
}
SHA1_Update(context, finalcount, 8); /* Should cause a SHA1_Transform() */
for (i = 0; i < SHA1_DIGEST_SIZE; i++) {
digest[i] = (uint8_t)
((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
}
/* Wipe variables */
i = 0;
UNUSED(i);
memset(context->buffer, 0, 64);
memset(context->state, 0, 20);
memset(context->count, 0, 8);
memset(finalcount, 0, 8); /* SWR */
#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite its own static vars */
SHA1_Transform(context->state, context->buffer);
#endif
}
/*************************************************************/
#ifdef TEST
int main(int argc, char** argv) {
int i, j;
SHA1_CTX context;
unsigned char digest[SHA1_DIGEST_SIZE], buffer[16384];
FILE* file;
if (argc > 2) {
puts("Public domain SHA-1 implementation - by Steve Reid <sreid@sea-to-sky.net>");
puts("Modified for 16 bit environments 7/98 - by James H. Brown <jbrown@burgoyne.com>"); /* JHB */
puts("Produces the SHA-1 hash of a file, or stdin if no file is specified.");
return(0);
}
if (argc < 2) {
file = stdin;
}
else {
if (!(file = fopen(argv[1], "rb"))) {
fputs("Unable to open file.", stderr);
return(-1);
}
}
SHA1_Init(&context);
while (!feof(file)) { /* note: what if ferror(file) */
i = fread(buffer, 1, 16384, file);
SHA1_Update(&context, buffer, i);
}
SHA1_Final(&context, digest);
fclose(file);
for (i = 0; i < SHA1_DIGEST_SIZE/4; i++) {
for (j = 0; j < 4; j++) {
printf("%02X", digest[i*4+j]);
}
putchar(' ');
}
putchar('\n');
return(0); /* JHB */
}
#endif

27
app/src/main/cpp/libmobi/src/sha1.h vendored Normal file
View file

@ -0,0 +1,27 @@
/** @file sha1.h
* @brief Header for sha1.c
*
* Copyright (c) 2014 Bartek Fabiszewski
* http://www.fabiszewski.net
*
* This file is part of libmobi.
* Licensed under LGPL, either version 3, or any later.
* See <http://www.gnu.org/licenses/>
*/
#ifndef mobi_sha1_h
#define mobi_sha1_h
typedef struct {
uint32_t state[5];
uint32_t count[2];
uint8_t buffer[64];
} SHA1_CTX;
#define SHA1_DIGEST_SIZE 20
void SHA1_Init(SHA1_CTX *context);
void SHA1_Update(SHA1_CTX *context, const uint8_t *data, const size_t len);
void SHA1_Final(SHA1_CTX *context, uint8_t digest[SHA1_DIGEST_SIZE]);
#endif /* sha1_h */

566
app/src/main/cpp/libmobi/src/structure.c vendored Normal file
View file

@ -0,0 +1,566 @@
/** @file structure.c
* @brief Data structures
*
* Copyright (c) 2014 Bartek Fabiszewski
* http://www.fabiszewski.net
*
* This file is part of libmobi.
* Licensed under LGPL, either version 3, or any later.
* See <http://www.gnu.org/licenses/>
*/
#include <stdlib.h>
#include <string.h>
#include "structure.h"
#include "debug.h"
#if defined(__BIONIC__) && !defined(SIZE_MAX)
#include <limits.h> /* for SIZE_MAX */
#endif
/**
@brief Initializer for MOBIArray structure
It allocates memory for structure and for data: array of uint32_t variables.
Memory should be freed with array_free().
@param[in] len Initial size of the array
@return MOBIArray on success, NULL otherwise
*/
MOBIArray * array_init(const size_t len) {
MOBIArray *arr = NULL;
arr = malloc(sizeof(MOBIArray));
if (arr == NULL) {
debug_print("%s", "Array allocation failed\n");
return NULL;
}
arr->data = malloc(len * sizeof(*arr->data));
if (arr->data == NULL) {
free(arr);
debug_print("%s", "Array data allocation failed\n");
return NULL;
}
arr->maxsize = len;
arr->step = len ? len : 1;
arr->size = 0;
return arr;
}
/**
@brief Inserts value into MOBIArray array
@param[in,out] arr MOBIArray array
@param[in] value Value to be inserted
@return MOBI_RET status code (on success MOBI_SUCCESS)
*/
MOBI_RET array_insert(MOBIArray *arr, const uint32_t value) {
if (!arr || arr->maxsize == 0) {
return MOBI_INIT_FAILED;
}
if (arr->maxsize == arr->size) {
arr->maxsize += arr->step;
uint32_t *tmp = realloc(arr->data, arr->maxsize * sizeof(*arr->data));
if (!tmp) {
free(arr->data);
arr->data = NULL;
debug_print("%s\n", "Memory allocation failed");
return MOBI_MALLOC_FAILED;
}
arr->data = tmp;
}
arr->data[arr->size] = value;
arr->size++;
return MOBI_SUCCESS;
}
/**
@brief Helper for qsort in array_sort() function.
@param[in] a First element to compare
@param[in] b Second element to compare
@return -1 if a < b; 1 if a > b; 0 if a = b
*/
static int array_compare(const void *a, const void *b) {
if (*(uint32_t *) a < *(uint32_t *) b) {
return -1;
};
if (*(uint32_t *) a > *(uint32_t *) b) {
return 1;
};
return 0;
}
/**
@brief Sort MOBIArray in ascending order.
When unique is set to true, duplicate values are discarded.
@param[in,out] arr MOBIArray array
@param[in] unique Discard duplicate values if true
*/
void array_sort(MOBIArray *arr, const bool unique) {
if (!arr || !arr->data || arr->size == 0) {
return;
}
qsort(arr->data, arr->size, sizeof(*arr->data), array_compare);
if (unique) {
size_t i = 1;
size_t j = 1;
while (i < arr->size) {
if (arr->data[j - 1] == arr->data[i]) {
i++;
continue;
}
arr->data[j++] = arr->data[i++];
}
arr->size = j;
}
}
/**
@brief Get size of the array
@param[in] arr MOBIArray structure
@return Array size
*/
size_t array_size(MOBIArray *arr) {
return arr->size;
}
/**
@brief Free MOBIArray structure and contained data
Free data initialized with array_init();
@param[in] arr MOBIArray structure
*/
void array_free(MOBIArray *arr) {
if (!arr) { return; }
if (arr->data) {
free(arr->data);
}
free(arr);
}
/**
@brief Create and return MOBITrie structure
@return MOBITrie stucture initialized with zeroes
*/
static MOBITrie * mobi_trie_mknode(void) {
MOBITrie *node = calloc(1, sizeof(MOBITrie));
if (node == NULL) {
debug_print("Memory allocation failed%s", "\n");
}
return node;
}
/**
@brief Recursively free MOBITrie trie starting from node
@param[in] node Starting node
*/
void mobi_trie_free(MOBITrie *node) {
if (node) {
mobi_trie_free(node->next);
mobi_trie_free(node->children);
free(node->values);
free(node);
}
}
/**
@brief Insert value into array at given MOBITrie node
@param[in,out] node Starting node
@param[in] value Value to be inserted
@return MOBI_RET status code (on success MOBI_SUCCESS)
*/
static MOBI_RET mobi_trie_addvalue(MOBITrie *node, char *value) {
if (node->values) {
size_t cnt = ++node->values_count;
void *new_values = realloc(node->values, cnt * sizeof(*node->values));
if (new_values == NULL) {
debug_print("Memory allocation failed%s", "\n");
return MOBI_MALLOC_FAILED;
}
node->values = new_values;
node->values[cnt - 1] = value;
} else {
node->values = malloc(sizeof(*node->values));
if (node->values == NULL) {
debug_print("Memory allocation failed%s", "\n");
return MOBI_MALLOC_FAILED;
}
node->values[0] = value;
node->values_count = 1;
}
return MOBI_SUCCESS;
}
/**
@brief Insert key character and value (if given) at MOBITrie node
@param[in,out] node Starting node
@param[in] c Key character
@param[in] value Value to be inserted at terminal node, or NULL if not terminal
@return MOBITrie node: current node if value inserted (terminal),
children node (if transitional) or NULL on error
*/
static MOBITrie * mobi_trie_insert_char(MOBITrie *node, char c, char *value) {
if (!node) { return NULL; }
while (true) {
if (node->c == c) {
break;
}
if (node->next == NULL) {
node->next = mobi_trie_mknode();
node = node->next;
break;
}
node = node->next;
}
if (node->c == 0) {
node->c = c;
}
if (value) {
/* terminal node */
if (mobi_trie_addvalue(node, value) == MOBI_SUCCESS) {
return node;
}
return NULL;
}
if (node->children == NULL) {
node->children = mobi_trie_mknode();
}
return node->children;
}
/**
@brief Insert reversed string into MOBITrie trie
@param[in,out] root Root node
@param[in] string String to be inserted
@param[in] value Value associated with the string
@return MOBI_RET status code (on success MOBI_SUCCESS)
*/
MOBI_RET mobi_trie_insert_reversed(MOBITrie **root, char *string, char *value) {
size_t length = strlen(string);
if (length == 0) {
debug_print("Skipping empty lookup string in trie node%s", "\n");
return MOBI_SUCCESS;
}
if (*root == NULL) {
*root = mobi_trie_mknode();
if (*root == NULL) {
return MOBI_MALLOC_FAILED;
}
}
MOBITrie *node = *root;
while (length > 1) {
node = mobi_trie_insert_char(node, string[length - 1], NULL);
if (node == NULL) {
return MOBI_MALLOC_FAILED;
}
length--;
}
node = mobi_trie_insert_char(node, string[length - 1], value);
if (node == NULL) {
return MOBI_MALLOC_FAILED;
}
return MOBI_SUCCESS;
}
/**
@brief Fetch values for key c from MOBITrie trie's current level starting at node
@param[in,out] values Array of values to be fetched
@param[in,out] values_count Array size
@param[in] node MOBITrie node to start search
@param[in] c Key character
@return MOBITrie children node of the node with c key or NULL if not found
*/
MOBITrie * mobi_trie_get_next(char ***values, size_t *values_count, const MOBITrie *node, const char c) {
if (!node) { return NULL; }
while (node) {
if (node->c == c) {
*values = (char**) node->values;
*values_count = node->values_count;
return node->children;
}
node = node->next;
}
return NULL;
}
#if 0
/* Simple imprementation of binary tree, storing key strings
and associated arrays of values
currently not used, save for later */
typedef struct MOBIBtree {
char *key; /**< key */
char **array; /**< array of strings */
size_t value_count; /**< strings count */
struct MOBIBtree *left; /**< left child */
struct MOBIBtree *right; /**< right child */
} MOBIBtree;
/**
@brief Search MOBIBtree tree for string key
@param[in] node MOBIBtree node to start search
@param[in] key Key string
@return MOBIBtree node or NULL if not found
*/
MOBIBtree *mobi_btree_search(MOBIBtree *node, const char *key) {
MOBIBtree *found = NULL;
int compare = strcmp(key, node->key);
if (compare < 0) {
found = mobi_btree_search(node->left, key);
} else if (compare > 0) {
found = mobi_btree_search(node->right, key);
} else {
found = node;
}
return found;
}
/**
@brief Insert key and value (into array) into MOBIBtree tree
@param[in] node MOBIBtree root node
@param[in] key Key string
@param[in] value Value string will be inserted into array
@return MOBI_RET status code (on success MOBI_SUCCESS)
*/
MOBI_RET mobi_btree_insert(MOBIBtree **node, char *key, char *value) {
MOBI_RET ret = MOBI_SUCCESS;
if (*node == NULL) {
*node = malloc(sizeof(MOBIBtree));
if (*node == NULL) {
return MOBI_MALLOC_FAILED;
}
(*node)->key = key;
(*node)->value_count = 1;
(*node)->array = malloc(sizeof(*(*node)->array));
if ((*node)->array == NULL) {
free(*node);
return MOBI_MALLOC_FAILED;
}
(*node)->array[0] = value;
(*node)->left = NULL;
(*node)->right = NULL;
return MOBI_SUCCESS;
}
int compare = strcmp(key, (*node)->key);
if (compare < 0) {
ret = mobi_btree_insert(&(*node)->left, key, value);
} else if (compare > 0) {
ret = mobi_btree_insert(&(*node)->right, key, value);
} else {
size_t cnt = ++(*node)->value_count;
char **new_array = realloc((*node)->array, cnt * sizeof(*(*node)->array));
if (new_array) {
(*node)->array = new_array;
(*node)->array[cnt - 1] = value;
} else {
return MOBI_MALLOC_FAILED;
}
}
return ret;
}
#endif
/**
@brief Allocate fragment, fill with data and return
@param[in] raw_offset Fragment offset in raw markup,
SIZE_MAX if not present in original markup
@param[in] fragment Fragment data
@param[in] size Size data
@param[in] is_malloc is_maloc data
@return Fragment structure filled with data
*/
static MOBIFragment * mobi_list_init(size_t raw_offset, unsigned char *fragment, const size_t size, const bool is_malloc) {
MOBIFragment *curr = calloc(1, sizeof(MOBIFragment));
if (curr == NULL) {
if (is_malloc) {
free(fragment);
}
return NULL;
}
curr->raw_offset = raw_offset;
curr->fragment = fragment;
curr->size = size;
curr->is_malloc = is_malloc;
return curr;
}
/**
@brief Allocate fragment, fill with data, append to linked list
@param[in] curr Last fragment in linked list
@param[in] raw_offset Fragment offset in raw markup,
SIZE_MAX if not present in original markup
@param[in] fragment Fragment data
@param[in] size Size data
@param[in] is_malloc is_maloc data
@return Fragment structure filled with data
*/
MOBIFragment * mobi_list_add(MOBIFragment *curr, size_t raw_offset, unsigned char *fragment, const size_t size, const bool is_malloc) {
if (!curr) {
return mobi_list_init(raw_offset, fragment, size, is_malloc);
}
curr->next = calloc(1, sizeof(MOBIFragment));
if (curr->next == NULL) {
if (is_malloc) {
free(fragment);
}
return NULL;
}
MOBIFragment *next = curr->next;
next->raw_offset = raw_offset;
next->fragment = fragment;
next->size = size;
next->is_malloc = is_malloc;
return next;
}
/**
@brief Allocate fragment, fill with data,
insert into linked list at given offset
Starts to search for offset at given fragment. The pointer to input fragment will be replaced by newly added one.
@param[in,out] fragment Fragment where search starts, on success pointer to new fragment structure filled with data
@param[in] raw_offset Fragment offset in raw markup, SIZE_MAX if not present in original markup
@param[in] data Fragment data
@param[in] size Size data
@param[in] is_malloc is_maloc data
@param[in] offset offset where new chunk will be inserted
@return MOBI_RET status code (on success MOBI_SUCCESS, on offset not found MOBI_DATA_CORRUPT)
*/
MOBI_RET mobi_list_insert(MOBIFragment **fragment, size_t raw_offset, unsigned char *data, const size_t size, const bool is_malloc, const size_t offset) {
MOBIFragment *curr = *fragment;
MOBIFragment *prev = NULL;
while (curr) {
if (curr->raw_offset != SIZE_MAX && curr->raw_offset <= offset && curr->raw_offset + curr->size >= offset ) {
break;
}
prev = curr;
curr = curr->next;
}
if (!curr) {
debug_print("Offset not found: %zu\n", offset);
if (is_malloc) {
free(data);
}
return MOBI_DATA_CORRUPT;
}
MOBIFragment *new = calloc(1, sizeof(MOBIFragment));
if (new == NULL) {
if (is_malloc) {
free(data);
}
return MOBI_MALLOC_FAILED;
}
new->raw_offset = raw_offset;
new->fragment = data;
new->size = size;
new->is_malloc = is_malloc;
MOBIFragment *new2 = NULL;
if (curr->raw_offset == offset) {
/* prepend chunk */
if (prev) {
prev->next = new;
new->next = curr;
} else {
/* save curr */
MOBIFragment tmp;
tmp.raw_offset = curr->raw_offset;
tmp.fragment = curr->fragment;
tmp.size = curr->size;
tmp.is_malloc = curr->is_malloc;
tmp.next = curr->next;
/* move new to curr */
curr->raw_offset = new->raw_offset;
curr->fragment = new->fragment;
curr->size = new->size;
curr->is_malloc = new->is_malloc;
curr->next = new;
/* restore tmp to new */
new->raw_offset = tmp.raw_offset;
new->fragment = tmp.fragment;
new->size = tmp.size;
new->is_malloc = tmp.is_malloc;
new->next = tmp.next;
*fragment = curr;
return MOBI_SUCCESS;
}
} else if (curr->raw_offset + curr->size == offset) {
/* append chunk */
new->next = curr->next;
curr->next = new;
} else {
/* split fragment and insert new chunk */
new2 = calloc(1, sizeof(MOBIFragment));
if (new2 == NULL) {
free(new);
if (is_malloc) {
free(data);
}
return MOBI_MALLOC_FAILED;
}
size_t rel_offset = offset - curr->raw_offset;
new2->next = curr->next;
new2->size = curr->size - rel_offset;
new2->raw_offset = offset;
new2->fragment = curr->fragment + rel_offset;
new2->is_malloc = false;
curr->next = new;
curr->size = rel_offset;
new->next = new2;
}
/* correct offsets */
if (raw_offset != SIZE_MAX) {
curr = new->next;
while (curr) {
if (curr->raw_offset != SIZE_MAX) {
curr->raw_offset += new->size;
}
curr = curr->next;
}
}
*fragment = new;
return MOBI_SUCCESS;
}
/**
@brief Delete fragment from linked list
@param[in] curr Fragment to be deleted
@return Next fragment in the linked list or NULL if absent
*/
MOBIFragment * mobi_list_del(MOBIFragment *curr) {
MOBIFragment *del = curr;
curr = curr->next;
if (del->is_malloc) {
free(del->fragment);
}
free(del);
del = NULL;
return curr;
}
/**
@brief Delete all fragments from linked list
@param[in] first First fragment from the list
*/
void mobi_list_del_all(MOBIFragment *first) {
while (first) {
first = mobi_list_del(first);
}
}

View file

@ -0,0 +1,66 @@
/** @file structure.h
*
* Copyright (c) 2014 Bartek Fabiszewski
* http://www.fabiszewski.net
*
* This file is part of libmobi.
* Licensed under LGPL, either version 3, or any later.
* See <http://www.gnu.org/licenses/>
*/
#ifndef mobi_structure_h
#define mobi_structure_h
#include "config.h"
#include "mobi.h"
/**
@brief Dynamic array of uint32_t values structure
*/
typedef struct {
uint32_t *data; /**< Array */
size_t maxsize; /**< Allocated size */
size_t step; /**< Step by which array will be enlarged if out of memory */
size_t size; /**< Current size */
} MOBIArray;
MOBIArray * array_init(const size_t len);
MOBI_RET array_insert(MOBIArray *arr, const uint32_t value);
void array_sort(MOBIArray *arr, const bool unique);
size_t array_size(MOBIArray *arr);
void array_free(MOBIArray *arr);
/**
@brief Trie storing arrays of values for character keys
*/
typedef struct MOBITrie {
char c; /**< Key character */
void **values; /**< Array of values */
size_t values_count; /**< Array size */
struct MOBITrie *next; /**< Next node at the same level */
struct MOBITrie *children; /**< Link to children nodes, lower level */
} MOBITrie;
MOBI_RET mobi_trie_insert_reversed(MOBITrie **root, char *string, char *value);
MOBITrie * mobi_trie_get_next(char ***values, size_t *values_count, const MOBITrie *node, const char c);
void mobi_trie_free(MOBITrie *node);
/**
@brief Structure for links reconstruction.
Linked list of Fragment structures forms whole document part
*/
typedef struct MOBIFragment {
size_t raw_offset; /**< fragment offset in raw markup, SIZE_MAX if not present in original markup */
unsigned char *fragment; /**< Fragment data */
size_t size; /**< Fragment size */
bool is_malloc; /**< Is it needed to free this fragment or is it just an alias to part data */
struct MOBIFragment *next; /**< Link to next fragment */
} MOBIFragment;
MOBIFragment * mobi_list_add(MOBIFragment *curr, size_t raw_offset, unsigned char *fragment, const size_t size, const bool is_malloc);
MOBIFragment * mobi_list_del(MOBIFragment *curr);
MOBI_RET mobi_list_insert(MOBIFragment **curr, size_t raw_offset, unsigned char *fragment, const size_t size, const bool is_malloc, const size_t offset);
void mobi_list_del_all(MOBIFragment *first);
#endif

3561
app/src/main/cpp/libmobi/src/util.c vendored Normal file

File diff suppressed because it is too large Load diff

157
app/src/main/cpp/libmobi/src/util.h vendored Normal file
View file

@ -0,0 +1,157 @@
/** @file util.h
*
* Copyright (c) 2014 Bartek Fabiszewski
* http://www.fabiszewski.net
*
* This file is part of libmobi.
* Licensed under LGPL, either version 3, or any later.
* See <http://www.gnu.org/licenses/>
*/
#ifndef libmobi_util_h
#define libmobi_util_h
#include "config.h"
#include "mobi.h"
#include "memory.h"
#include "buffer.h"
#include "read.h"
#include "compression.h"
#ifndef HAVE_STRDUP
/** @brief strdup replacement */
#define strdup mobi_strdup
#endif
#ifdef USE_MINIZ
#include "miniz.h"
#define m_uncompress mz_uncompress
#define m_crc32 mz_crc32
#define M_OK MZ_OK
#else
#include <zlib.h>
#define m_uncompress uncompress
#define m_crc32 crc32
#define M_OK Z_OK
#endif
#define UNUSED(x) (void)(x)
/** @brief Magic numbers of records */
#define AUDI_MAGIC "AUDI"
#define CDIC_MAGIC "CDIC"
#define CMET_MAGIC "CMET"
#define EXTH_MAGIC "EXTH"
#define FDST_MAGIC "FDST"
#define FONT_MAGIC "FONT"
#define HUFF_MAGIC "HUFF"
#define IDXT_MAGIC "IDXT"
#define INDX_MAGIC "INDX"
#define LIGT_MAGIC "LIGT"
#define MOBI_MAGIC "MOBI"
#define ORDT_MAGIC "ORDT"
#define RESC_MAGIC "RESC"
#define SRCS_MAGIC "SRCS"
#define TAGX_MAGIC "TAGX"
#define VIDE_MAGIC "VIDE"
#define BOUNDARY_MAGIC "BOUNDARY"
#define EOF_MAGIC "\xe9\x8e\r\n"
#define REPLICA_MAGIC "%MOP"
/** @brief Difference in seconds between epoch time and mac time */
#define EPOCH_MAC_DIFF 2082844800UL
/**
@defgroup mobi_pdb Params for pdb record header structure
@{
*/
#define PALMDB_HEADER_LEN 78 /**< Length of header without record info headers */
#define PALMDB_NAME_SIZE_MAX 32 /**< Max length of db name stored at offset 0 */
#define PALMDB_RECORD_INFO_SIZE 8 /**< Record info header size of each pdb record */
/** @} */
/**
@defgroup mobi_pdb_defs Default values for pdb record header structure
@{
*/
#define PALMDB_ATTRIBUTE_DEFAULT 0
#define PALMDB_VERSION_DEFAULT 0
#define PALMDB_MODNUM_DEFAULT 0
#define PALMDB_APPINFO_DEFAULT 0
#define PALMDB_SORTINFO_DEFAULT 0
#define PALMDB_TYPE_DEFAULT "BOOK"
#define PALMDB_CREATOR_DEFAULT "MOBI"
#define PALMDB_NEXTREC_DEFAULT 0
/** @} */
/**
@defgroup mobi_rec0 Params for record0 header structure
@{
*/
#define RECORD0_HEADER_LEN 16 /**< Length of Record 0 header */
#define RECORD0_TEXT_SIZE_MAX 4096 /**< Max size of uncompressed text record */
#define RECORD0_FULLNAME_SIZE_MAX 1024 /**< Max size to full name string */
/** @} */
/**
@defgroup mobi_len Header length / size of records
@{
*/
#define CDIC_HEADER_LEN 16
#define CDIC_RECORD_MAXCNT 1024
#define HUFF_CODELEN_MAX 16
#define HUFF_HEADER_LEN 24
#define HUFF_RECORD_MAXCNT 1024
#define HUFF_RECORD_MINSIZE 2584
#define FONT_HEADER_LEN 24
#define MEDIA_HEADER_LEN 12
#define FONT_SIZEMAX (50 * 1024 * 1024)
#define RAWTEXT_SIZEMAX 0xfffffff
#define MOBI_HEADER_V2_SIZE 0x18
#define MOBI_HEADER_V3_SIZE 0x74
#define MOBI_HEADER_V4_SIZE 0xd0
#define MOBI_HEADER_V5_SIZE 0xe4
#define MOBI_HEADER_V6_SIZE 0xe4
#define MOBI_HEADER_V6_EXT_SIZE 0xe8
#define MOBI_HEADER_V7_SIZE 0xe4
/** @} */
#ifndef max
#define max(a, b) ((a) > (b) ? (a) : (b))
#endif
#ifndef min
#define min(a, b) ((a) < (b) ? (a) : (b))
#endif
#define ARRAYSIZE(arr) (sizeof(arr) / sizeof(arr[0]))
#define MOBI_TITLE_SIZEMAX 1024
int mobi_bitcount(const uint8_t byte);
MOBI_RET mobi_delete_record_by_seqnumber(MOBIData *m, const size_t num);
MOBI_RET mobi_swap_mobidata(MOBIData *m);
char * mobi_strdup(const char *s);
bool mobi_is_cp1252(const MOBIData *m);
bool mobi_has_drmkey(const MOBIData *m);
bool mobi_has_drmcookies(const MOBIData *m);
MOBI_RET mobi_cp1252_to_utf8(char *output, const char *input, size_t *outsize, const size_t insize);
MOBI_RET mobi_utf8_to_cp1252(char *output, const char *input, size_t *outsize, const size_t insize);
uint8_t mobi_ligature_to_cp1252(const uint8_t byte1, const uint8_t byte2);
uint16_t mobi_ligature_to_utf16(const uint32_t byte1, const uint32_t byte2);
MOBIFiletype mobi_determine_resource_type(const MOBIPdbRecord *record);
MOBIFiletype mobi_determine_flowpart_type(const MOBIRawml *rawml, const size_t part_number);
MOBI_RET mobi_base32_decode(uint32_t *decoded, const char *encoded);
MOBIFiletype mobi_get_resourcetype_by_uid(const MOBIRawml *rawml, const size_t uid);
uint32_t mobi_get_exthsize(const MOBIData *m);
uint32_t mobi_get_drmsize(const MOBIData *m);
uint16_t mobi_get_records_count(const MOBIData *m);
void mobi_remove_zeros(unsigned char *buffer, size_t *len);
MOBI_RET mobi_add_audio_resource(MOBIPart *part);
MOBI_RET mobi_add_video_resource(MOBIPart *part);
MOBI_RET mobi_add_font_resource(MOBIPart *part);
MOBI_RET mobi_set_fullname(MOBIData *m, const char *fullname);
MOBI_RET mobi_set_pdbname(MOBIData *m, const char *name);
void mobi_free_internals(MOBIData *m);
uint32_t mobi_get32be(const unsigned char buf[4]);
uint32_t mobi_get32le(const unsigned char buf[4]);
#endif

540
app/src/main/cpp/libmobi/src/write.c vendored Normal file
View file

@ -0,0 +1,540 @@
/** @file write.c
* @brief Writing functions
*
* Copyright (c) 2016 Bartek Fabiszewski
* http://www.fabiszewski.net
*
* This file is part of libmobi.
* Licensed under LGPL, either version 3, or any later.
* See <http://www.gnu.org/licenses/>
*/
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "write.h"
#include "util.h"
#include "debug.h"
#ifdef USE_ENCRYPTION
#include "encryption.h"
#endif
#define MOBI_HEADER_MAXLEN 280
#define MOBI_RECORD0_PADDING 0x2002
/**
@brief Write buffer contents to file
@param[in,out] file File descriptor
@param[in] buf Buffer
@return MOBI_RET status code (MOBI_SUCCESS on success)
*/
MOBI_RET mobi_write_buffer(FILE *file, const MOBIBuffer *buf) {
const size_t written = fwrite(buf->data, 1, buf->maxlen, file);
if (written != buf->maxlen) {
debug_print("Writing failed (%s)\n", strerror(errno));
return MOBI_WRITE_FAILED;
}
return MOBI_SUCCESS;
}
/**
@brief Write palm database header to file
@param[in,out] file File descriptor
@param[in] m MOBIData structure
@return MOBI_RET status code (MOBI_SUCCESS on success)
*/
MOBI_RET mobi_write_pdbheader(FILE *file, const MOBIData *m) {
if (m == NULL || m->ph == NULL) {
debug_print("%s", "Mobi structure not initialized\n");
return MOBI_INIT_FAILED;
}
if (file == NULL) {
debug_print("%s", "File not initialized\n");
return MOBI_PARAM_ERR;
}
MOBIBuffer *buf = mobi_buffer_init(PALMDB_HEADER_LEN);
if (buf == NULL) {
debug_print("%s\n", "Memory allocation failed");
return MOBI_MALLOC_FAILED;
}
mobi_buffer_addstring(buf, m->ph->name);
size_t len = strlen(m->ph->name);
mobi_buffer_addzeros(buf, PALMDB_NAME_SIZE_MAX - len);
mobi_buffer_add16(buf, m->ph->attributes);
mobi_buffer_add16(buf, m->ph->version);
mobi_buffer_add32(buf, m->ph->ctime);
mobi_buffer_add32(buf, m->ph->mtime);
mobi_buffer_add32(buf, m->ph->btime);
mobi_buffer_add32(buf, m->ph->mod_num);
mobi_buffer_add32(buf, m->ph->appinfo_offset);
mobi_buffer_add32(buf, m->ph->sortinfo_offset);
mobi_buffer_addstring(buf, m->ph->type);
mobi_buffer_addstring(buf, m->ph->creator);
mobi_buffer_add32(buf, m->ph->uid);
mobi_buffer_add32(buf, m->ph->next_rec);
m->ph->rec_count = mobi_get_records_count(m);
if (m->ph->rec_count == 0) {
mobi_buffer_free(buf);
debug_print("%s", "Zero records count\n");
return MOBI_DATA_CORRUPT;
}
mobi_buffer_add16(buf, m->ph->rec_count);
if (buf->error != MOBI_SUCCESS) {
mobi_buffer_free(buf);
return MOBI_DATA_CORRUPT;
}
MOBI_RET ret = mobi_write_buffer(file, buf);
mobi_buffer_free(buf);
return ret;
}
/**
@brief Serialize mobi header to buffer
@param[in,out] buf output buffer
@param[in] m MOBIData structure
@param[in] exthsize Size of exth record
@return MOBI_RET status code (MOBI_SUCCESS on success)
*/
MOBI_RET mobi_serialize_mobiheader(MOBIBuffer *buf, const MOBIData *m, const uint32_t exthsize) {
if (m == NULL || m->mh == NULL || buf == NULL) {
debug_print("%s", "Mobi structure not initialized\n");
return MOBI_INIT_FAILED;
}
size_t buffer_init = buf->offset;
mobi_buffer_addstring(buf, m->mh->mobi_magic);
if (buf->offset > UINT32_MAX) {
debug_print("Offset too large: %zu\n", buf->offset);
return MOBI_DATA_CORRUPT;
}
uint32_t length_offset = (uint32_t) buf->offset;
uint32_t name_offset = 0;
uint32_t drm_offset = 0;
mobi_buffer_add32(buf, 0); /* dummy length */
if (m->mh->mobi_type) { mobi_buffer_add32(buf, *m->mh->mobi_type); } else { goto finalize; }
if (m->mh->text_encoding) { mobi_buffer_add32(buf, *m->mh->text_encoding); } else { goto finalize; }
if (m->mh->uid) { mobi_buffer_add32(buf, *m->mh->uid); } else { goto finalize; }
bool isKF8 = false;
if (m->mh->version) {
mobi_buffer_add32(buf, *m->mh->version);
if (*m->mh->version == 8) {
isKF8 = true;
}
} else { goto finalize; }
if (m->mh->orth_index) { mobi_buffer_add32(buf, *m->mh->orth_index); } else { goto finalize; }
if (m->mh->infl_index) { mobi_buffer_add32(buf, *m->mh->infl_index); } else { goto finalize; }
if (m->mh->names_index) { mobi_buffer_add32(buf, *m->mh->names_index); } else { goto finalize; }
if (m->mh->keys_index) { mobi_buffer_add32(buf, *m->mh->keys_index); } else { goto finalize; }
if (m->mh->extra0_index) { mobi_buffer_add32(buf, *m->mh->extra0_index); } else { goto finalize; }
if (m->mh->extra1_index) { mobi_buffer_add32(buf, *m->mh->extra1_index); } else { goto finalize; }
if (m->mh->extra2_index) { mobi_buffer_add32(buf, *m->mh->extra2_index); } else { goto finalize; }
if (m->mh->extra3_index) { mobi_buffer_add32(buf, *m->mh->extra3_index); } else { goto finalize; }
if (m->mh->extra4_index) { mobi_buffer_add32(buf, *m->mh->extra4_index); } else { goto finalize; }
if (m->mh->extra5_index) { mobi_buffer_add32(buf, *m->mh->extra5_index); } else { goto finalize; }
if (m->mh->non_text_index) { mobi_buffer_add32(buf, *m->mh->non_text_index); } else { goto finalize; }
if (m->mh->full_name) {
if (buf->offset > UINT32_MAX) {
debug_print("Offset too large: %zu\n", buf->offset);
return MOBI_DATA_CORRUPT;
}
name_offset = (uint32_t) buf->offset;
mobi_buffer_add32(buf, MOBI_NOTSET);
mobi_buffer_add32(buf, 0);
} else { goto finalize; }
if (m->mh->locale) { mobi_buffer_add32(buf, *m->mh->locale); } else { goto finalize; }
if (m->mh->dict_input_lang) { mobi_buffer_add32(buf, *m->mh->dict_input_lang); } else { goto finalize; }
if (m->mh->dict_output_lang) { mobi_buffer_add32(buf, *m->mh->dict_output_lang); } else { goto finalize; }
if (m->mh->min_version) { mobi_buffer_add32(buf, *m->mh->min_version); } else { goto finalize; }
if (m->mh->image_index) { mobi_buffer_add32(buf, *m->mh->image_index); } else { goto finalize; }
if (m->mh->huff_rec_index) { mobi_buffer_add32(buf, *m->mh->huff_rec_index); } else { goto finalize; }
if (m->mh->huff_rec_count) { mobi_buffer_add32(buf, *m->mh->huff_rec_count); } else { goto finalize; }
if (m->mh->datp_rec_index) { mobi_buffer_add32(buf, *m->mh->datp_rec_index); } else { goto finalize; }
if (m->mh->datp_rec_count) { mobi_buffer_add32(buf, *m->mh->datp_rec_count); } else { goto finalize; }
if (m->mh->exth_flags) { mobi_buffer_add32(buf, *m->mh->exth_flags); } else { goto finalize; }
mobi_buffer_addzeros(buf, 32); /* 32 unknown bytes */
if (m->mh->unknown6) { mobi_buffer_add32(buf, *m->mh->unknown6); } else { goto finalize; }
if (m->mh->drm_offset) {
drm_offset = (uint32_t) buf->offset;
mobi_buffer_add32(buf, *m->mh->drm_offset);
} else { goto finalize; }
if (m->mh->drm_count) { mobi_buffer_add32(buf, *m->mh->drm_count); } else { goto finalize; }
if (m->mh->drm_size) { mobi_buffer_add32(buf, *m->mh->drm_size); } else { goto finalize; }
if (m->mh->drm_flags) { mobi_buffer_add32(buf, *m->mh->drm_flags); } else { goto finalize; }
mobi_buffer_addzeros(buf, 8); /* 8 unknown bytes */
if (isKF8) {
if (m->mh->fdst_index) { mobi_buffer_add32(buf, *m->mh->fdst_index); } else { goto finalize; }
} else {
if (m->mh->first_text_index) { mobi_buffer_add16(buf, *m->mh->first_text_index); } else { goto finalize; }
if (m->mh->last_text_index) { mobi_buffer_add16(buf, *m->mh->last_text_index); } else { goto finalize; }
}
if (m->mh->fdst_section_count) { mobi_buffer_add32(buf, *m->mh->fdst_section_count); } else { goto finalize; }
if (m->mh->fcis_index) { mobi_buffer_add32(buf, *m->mh->fcis_index); } else { goto finalize; }
if (m->mh->fcis_count) { mobi_buffer_add32(buf, *m->mh->fcis_count); } else { goto finalize; }
if (m->mh->flis_index) { mobi_buffer_add32(buf, *m->mh->flis_index); } else { goto finalize; }
if (m->mh->flis_count) { mobi_buffer_add32(buf, *m->mh->flis_count); } else { goto finalize; }
if (m->mh->unknown10) { mobi_buffer_add32(buf, *m->mh->unknown10); } else { goto finalize; }
if (m->mh->unknown11) { mobi_buffer_add32(buf, *m->mh->unknown11); } else { goto finalize; }
if (m->mh->srcs_index) { mobi_buffer_add32(buf, *m->mh->srcs_index); } else { goto finalize; }
if (m->mh->srcs_count) { mobi_buffer_add32(buf, *m->mh->srcs_count); } else { goto finalize; }
if (m->mh->unknown12) { mobi_buffer_add32(buf, *m->mh->unknown12); } else { goto finalize; }
if (m->mh->unknown13) { mobi_buffer_add32(buf, *m->mh->unknown13); } else { goto finalize; }
mobi_buffer_addzeros(buf, 2); /* 2 unknown bytes */
if (m->mh->extra_flags) { mobi_buffer_add16(buf, *m->mh->extra_flags); } else { goto finalize; }
if (m->mh->ncx_index) { mobi_buffer_add32(buf, *m->mh->ncx_index); } else { goto finalize; }
if (isKF8) {
if (m->mh->fragment_index) { mobi_buffer_add32(buf, *m->mh->fragment_index); } else { goto finalize; }
if (m->mh->skeleton_index) { mobi_buffer_add32(buf, *m->mh->skeleton_index); } else { goto finalize; }
} else {
if (m->mh->unknown14) { mobi_buffer_add32(buf, *m->mh->unknown14); } else { goto finalize; }
if (m->mh->unknown15) { mobi_buffer_add32(buf, *m->mh->unknown15); } else { goto finalize; }
}
if (m->mh->datp_index) { mobi_buffer_add32(buf, *m->mh->datp_index); } else { goto finalize; }
if (isKF8) {
if (m->mh->guide_index) { mobi_buffer_add32(buf, *m->mh->guide_index); } else { goto finalize; }
} else {
if (m->mh->unknown16) { mobi_buffer_add32(buf, *m->mh->unknown16); } else { goto finalize; }
}
if (m->mh->unknown17) { mobi_buffer_add32(buf, *m->mh->unknown17); } else { goto finalize; }
if (m->mh->unknown18) { mobi_buffer_add32(buf, *m->mh->unknown18); } else { goto finalize; }
if (m->mh->unknown19) { mobi_buffer_add32(buf, *m->mh->unknown19); } else { goto finalize; }
if (m->mh->unknown20) { mobi_buffer_add32(buf, *m->mh->unknown20); } else { goto finalize; }
finalize:
if (buf->error != MOBI_SUCCESS) {
return MOBI_DATA_CORRUPT;
}
size_t headersize = buf->offset - buffer_init;
if (headersize > UINT32_MAX) {
debug_print("Header too large: %zu\n", headersize);
return MOBI_DATA_CORRUPT;
}
size_t saved_offset = buf->offset;
/* write header length at offset 20 */
mobi_buffer_setpos(buf, length_offset);
mobi_buffer_add32(buf, (uint32_t) headersize);
*m->mh->header_length = (uint32_t) headersize;
uint32_t drmsize = 0;
#ifdef USE_ENCRYPTION
if (m->rh->encryption_type == MOBI_ENCRYPTION_V2 &&
m->mh->drm_size && m->mh->drm_offset && *m->mh->drm_size > 0) {
drmsize = mobi_get_drmsize(m);
*m->mh->drm_offset = RECORD0_HEADER_LEN + (uint32_t) headersize + exthsize;
mobi_buffer_setpos(buf, drm_offset);
mobi_buffer_add32(buf, *m->mh->drm_offset);
} else if (m->rh->encryption_type == MOBI_ENCRYPTION_V1) {
drmsize = mobi_get_drmsize(m);
}
#endif
if (m->mh->full_name) {
/* full name's offset is after exth records */
uint32_t fullname_offset = RECORD0_HEADER_LEN + (uint32_t) headersize + exthsize + drmsize;
size_t fullname_length = strlen(m->mh->full_name);
if (fullname_length > MOBI_TITLE_SIZEMAX) {
fullname_length = MOBI_TITLE_SIZEMAX;
m->mh->full_name[MOBI_TITLE_SIZEMAX] = '\0';
}
/* write fullname offset and length */
mobi_buffer_setpos(buf, name_offset);
mobi_buffer_add32(buf, fullname_offset);
mobi_buffer_add32(buf, (uint32_t) fullname_length);
if (m->mh->full_name_offset == NULL) {
m->mh->full_name_offset = malloc(sizeof(uint32_t));
if (m->mh->full_name_offset == NULL) {
debug_print("Memory allocation failed%s", "\n");
return MOBI_MALLOC_FAILED;
}
}
*m->mh->full_name_offset = fullname_offset;
if (m->mh->full_name_length == NULL) {
m->mh->full_name_length = malloc(sizeof(uint32_t));
if (m->mh->full_name_length == NULL) {
debug_print("Memory allocation failed%s", "\n");
return MOBI_MALLOC_FAILED;
}
}
*m->mh->full_name_length = (uint32_t) fullname_length;
}
mobi_buffer_setpos(buf, saved_offset);
if (buf->error != MOBI_SUCCESS) {
return MOBI_DATA_CORRUPT;
}
return MOBI_SUCCESS;
}
/**
@brief Serialize exth header to buffer
@param[in,out] buf output buffer
@param[in] m MOBIData structure
@return MOBI_RET status code (MOBI_SUCCESS on success)
*/
MOBI_RET mobi_serialize_extheader(MOBIBuffer *buf, const MOBIData *m) {
if (m == NULL || m->eh == NULL) {
debug_print("%s", "Mobi structure not initialized\n");
return MOBI_INIT_FAILED;
}
MOBIExthHeader *curr = m->eh;
mobi_buffer_addstring(buf, EXTH_MAGIC);
const size_t length_offset = buf->offset;
size_t length = 12; /* start with header length */
mobi_buffer_add32(buf, 0);
const size_t count_offset = buf->offset;
size_t count = 0;
mobi_buffer_add32(buf, 0);
while (curr) {
/* total size = data size plus 8 bytes for uid and size */
const uint32_t size = curr->size + 8;
length += size;
count++;
mobi_buffer_add32(buf, curr->tag);
mobi_buffer_add32(buf, size);
mobi_buffer_addraw(buf, curr->data, curr->size);
if (buf->error != MOBI_SUCCESS) {
return MOBI_DATA_CORRUPT;
}
curr = curr->next;
}
if (length > UINT32_MAX || count > UINT32_MAX) {
debug_print("Length (%zu) or count (%zu) too large\n", length, count);
return MOBI_DATA_CORRUPT;
}
/* add padding */
const size_t padding_size = length % 4;
length += padding_size;
mobi_buffer_addzeros(buf, padding_size);
const size_t saved_offset = buf->offset;
mobi_buffer_setpos(buf, length_offset);
mobi_buffer_add32(buf, (uint32_t) length);
mobi_buffer_setpos(buf, count_offset);
mobi_buffer_add32(buf, (uint32_t) count);
mobi_buffer_setpos(buf, saved_offset);
return MOBI_SUCCESS;
}
/**
@brief Serialize record0 and update record in MOBIData structure.
Record0 sequential number may be greater than zero in case
of hybrid file with two info records
@param[in,out] m MOBIData structure
@param[in] seqnumber Record0 sequential number
@return MOBI_RET status code (MOBI_SUCCESS on success)
*/
MOBI_RET mobi_update_record0(MOBIData *m, const size_t seqnumber) {
if (m == NULL || m->rh == NULL || m->rec == NULL) {
debug_print("%s", "Mobi structure not initialized\n");
return MOBI_INIT_FAILED;
}
size_t padding = MOBI_RECORD0_PADDING;
if (!mobi_exists_mobiheader(m)) {
padding = 0;
} else if (mobi_get_fileversion(m) < 8) {
padding -= 12;
}
size_t record0_maxlen = RECORD0_HEADER_LEN + MOBI_HEADER_MAXLEN;
uint32_t exthsize = mobi_get_exthsize(m);
uint32_t drmsize = mobi_get_drmsize(m);
record0_maxlen += exthsize;
record0_maxlen += drmsize;
record0_maxlen += MOBI_TITLE_SIZEMAX;
record0_maxlen += padding;
MOBIBuffer *buf = mobi_buffer_init(record0_maxlen);
if (buf == NULL) {
debug_print("%s\n", "Memory allocation failed");
return MOBI_MALLOC_FAILED;
}
mobi_buffer_add16(buf, m->rh->compression_type);
mobi_buffer_addzeros(buf, 2);
mobi_buffer_add32(buf, m->rh->text_length);
mobi_buffer_add16(buf, m->rh->text_record_count);
mobi_buffer_add16(buf, m->rh->text_record_size);
mobi_buffer_add16(buf, m->rh->encryption_type);
mobi_buffer_add16(buf, m->rh->unknown1);
if (m->mh) {
MOBI_RET ret = mobi_serialize_mobiheader(buf, m, exthsize);
if (ret != MOBI_SUCCESS) {
mobi_buffer_free(buf);
return ret;
}
if (m->eh) {
ret = mobi_serialize_extheader(buf, m);
if (ret != MOBI_SUCCESS) {
mobi_buffer_free(buf);
return ret;
}
}
#ifdef USE_ENCRYPTION
if (m->rh->encryption_type == MOBI_ENCRYPTION_V1) {
ret = mobi_drm_serialize_v1(buf, m);
} else if (m->rh->encryption_type == MOBI_ENCRYPTION_V2) {
ret = mobi_drm_serialize_v2(buf, m);
}
if (ret != MOBI_SUCCESS) {
mobi_buffer_free(buf);
return ret;
}
#endif
if (m->mh->full_name && m->mh->full_name_offset) {
mobi_buffer_setpos(buf, *m->mh->full_name_offset);
mobi_buffer_addstring(buf, m->mh->full_name);
if (buf->error != MOBI_SUCCESS) {
mobi_buffer_free(buf);
return MOBI_DATA_CORRUPT;
}
}
}
#ifdef USE_ENCRYPTION
else if (m->rh->encryption_type == MOBI_ENCRYPTION_V1) {
MOBI_RET ret = mobi_drm_serialize_v1(buf, m);
if (ret != MOBI_SUCCESS) {
mobi_buffer_free(buf);
return ret;
}
mobi_buffer_setpos(buf, 14 + drmsize);
}
#endif
mobi_buffer_addzeros(buf, padding);
if (buf->error) {
mobi_buffer_free(buf);
return MOBI_DATA_CORRUPT;
}
MOBIPdbRecord *record0 = mobi_get_record_by_seqnumber(m, seqnumber);
if (record0 == NULL) {
debug_print("%s", "Record 0 not initialized\n");
mobi_buffer_free(buf);
return MOBI_DATA_CORRUPT;
}
unsigned char *data = malloc(buf->offset);
if (data == NULL) {
mobi_buffer_free(buf);
return MOBI_MALLOC_FAILED;
}
memcpy(data, buf->data, buf->offset);
record0->size = buf->offset;
mobi_buffer_free(buf);
if (record0->data) {
free(record0->data);
}
record0->data = data;
return MOBI_SUCCESS;
}
/**
@brief Write palm database records to file
@param[in,out] file File descriptor
@param[in] m MOBIData structure
@return MOBI_RET status code (MOBI_SUCCESS on success)
*/
MOBI_RET mobi_write_records(FILE *file, const MOBIData *m) {
if (m == NULL || m->rec == NULL) {
debug_print("%s", "Mobi structure not initialized\n");
return MOBI_INIT_FAILED;
}
if (file == NULL) {
return MOBI_PARAM_ERR;
}
long pos = ftell(file);
if (pos < 0) {
return MOBI_WRITE_FAILED;
}
uint32_t offset = (uint32_t) pos;
/* 8 bytes per record meta plus 2 bytes padding */
offset += 8 * m->ph->rec_count + 2;
MOBIPdbRecord *curr = m->rec;
uint32_t i = 0;
while (curr) {
if (offset > UINT32_MAX) {
return MOBI_DATA_CORRUPT;
}
MOBIBuffer *buf = mobi_buffer_init(PALMDB_RECORD_INFO_SIZE);
if (buf == NULL) {
return MOBI_MALLOC_FAILED;
}
mobi_buffer_add32(buf, (uint32_t) offset);
offset += curr->size;
mobi_buffer_add8(buf, curr->attributes);
curr->uid = 2 * i++;
const uint8_t h = (uint8_t) ((curr->uid & 0xff0000U) >> 16);
const uint16_t l = (uint16_t) (curr->uid & 0xffffU);
mobi_buffer_add8(buf, h);
mobi_buffer_add16(buf, l);
if (buf->error != MOBI_SUCCESS) {
mobi_buffer_free(buf);
return MOBI_DATA_CORRUPT;
}
MOBI_RET ret = mobi_write_buffer(file, buf);
mobi_buffer_free(buf);
if (ret != MOBI_SUCCESS) {
return ret;
}
curr = curr->next;
}
char padding[2] = { 0 };
size_t written = fwrite(padding, 1, sizeof(padding), file);
if (written != sizeof(padding)) {
debug_print("Writing failed (%s)\n", strerror(errno));
return MOBI_WRITE_FAILED;
}
curr = m->rec;
while (curr) {
written = fwrite(curr->data, 1, curr->size, file);
if (written != curr->size) {
debug_print("Writing failed (%s)\n", strerror(errno));
return MOBI_WRITE_FAILED;
}
curr = curr->next;
}
return MOBI_SUCCESS;
}
/**
@brief Write mobi document to file.
Serializes metadata from MOBIData into raw records also stored in MOBIData (m->rec).
Later writes palm database to file.
@param[in,out] file File descriptor
@param[in,out] m MOBIData structure
@return MOBI_RET status code (MOBI_SUCCESS on success)
*/
MOBI_RET mobi_write_file(FILE *file, MOBIData *m) {
MOBI_RET ret = mobi_write_pdbheader(file, m);
if (ret != MOBI_SUCCESS) {
return ret;
}
MOBIData *m_kf7 = m;
if (mobi_is_hybrid(m) && m->next) {
MOBIData *m_kf8 = m;
if (m->use_kf8 == false) {
m_kf8 = m->next;
} else {
m_kf7 = m->next;
}
const size_t record0_kf8_offset = m_kf8->kf8_boundary_offset + 1;
ret = mobi_update_record0(m_kf8, record0_kf8_offset);
if (ret != MOBI_SUCCESS) {
return ret;
}
}
ret = mobi_update_record0(m_kf7, 0);
if (ret != MOBI_SUCCESS) {
return ret;
}
ret = mobi_write_records(file, m);
if (ret != MOBI_SUCCESS) {
return ret;
}
return MOBI_SUCCESS;
}

18
app/src/main/cpp/libmobi/src/write.h vendored Normal file
View file

@ -0,0 +1,18 @@
/*
* Copyright (c) 2014 Bartek Fabiszewski
* http://www.fabiszewski.net
*
* This file is part of libmobi.
* Licensed under LGPL, either version 3, or any later.
* See <http://www.gnu.org/licenses/>
*/
#ifndef libmobi_write_h
#define libmobi_write_h
#include "config.h"
#include "mobi.h"
#include "buffer.h"
#endif

918
app/src/main/cpp/libmobi/src/xmlwriter.c vendored Normal file
View file

@ -0,0 +1,918 @@
/** @file xmlwriter.c
* @brief Implements a simplified subset of libxml2 functions used in libmobi.
*
* Copyright (c) 2016 Bartek Fabiszewski
* http://www.fabiszewski.net
*
* This file is part of libmobi.
* Licensed under LGPL, either version 3, or any later.
* See <http://www.gnu.org/licenses/>
*/
#define _GNU_SOURCE 1
#ifndef __USE_BSD
#define __USE_BSD /* for strdup on linux/glibc */
#endif
#include <stdlib.h>
#include <string.h>
#include "xmlwriter.h"
#include "debug.h"
#include "util.h"
#include "parse_rawml.h"
#define MOBI_XML_BUFFERSIZE 4096
#define MOBI_XML_STATESSIZE 200
#define XML_ERROR -1
#define XML_OK 0
/**
@brief Initiate xml states with first name and mode pair
@param[in] name MOBIRawml State element name
@param[in] mode MOBIRawml State mode
@return New state
*/
static MOBIXmlState * mobi_xml_state_init(const char *name, const MOBI_XML_MODE mode) {
MOBIXmlState *curr = calloc(1, sizeof(MOBIXmlState));
if (curr == NULL) {
return NULL;
}
curr->name = strdup(name);
if (curr->name == NULL) {
free(curr);
return NULL;
}
curr->mode = mode;
return curr;
}
/**
@brief Get current active state from the list
@param[in] writer xmlTextWriter
@return State
*/
static MOBIXmlState * mobi_xml_state_current(const xmlTextWriterPtr writer) {
return writer->states;
}
/**
@brief Add new state to the list
@param[in,out] writer xmlTextWriter
@param[in] name MOBIRawml State element name
@param[in] mode MOBIRawml State mode
@return Added state
*/
static MOBIXmlState * mobi_xml_state_push(xmlTextWriterPtr writer, const char *name, const MOBI_XML_MODE mode) {
MOBIXmlState *new = mobi_xml_state_init(name, mode);
MOBIXmlState *first = writer->states;
if (!first) {
writer->states = new;
} else {
new->next = first;
writer->states = new;
}
return writer->states;
}
/**
@brief Remove state from the list
@param[in] state State structure that will be deleted
@return Next state in the list or NULL if not present
*/
static MOBIXmlState * mobi_xml_state_del(MOBIXmlState *state) {
MOBIXmlState *del = state;
state = state->next;
free(del->name);
free(del);
del = NULL;
return state;
}
/**
@brief Remove state from the beginning of the list
@param[in,out] writer xmlTextWriter
@return Next state or NULL if not present
*/
static MOBIXmlState * mobi_xml_state_pop(xmlTextWriterPtr writer) {
writer->states = mobi_xml_state_del(writer->states);
return writer->states;
}
/**
@brief Remove all states from the list
@param[in,out] first First state from the list
*/
static void mobi_xml_state_delall(MOBIXmlState *first) {
while (first) {
first = mobi_xml_state_del(first);
}
}
/**
@brief Get current level of nested element
@param[in] writer xmlTextWriter
@return Level
*/
static size_t mobi_xml_level(const xmlTextWriterPtr writer) {
MOBIXmlState *curr = writer->states;
size_t level = 0;
while (curr) {
level++;
if (curr->next == NULL) {
break;
}
curr = curr->next;
}
return level;
}
/**
@brief Write string to xml buffer
@param[in,out] writer xmlTextWriter
@param[in] string String
@return MOBI_RET status code (on success MOBI_SUCCESS)
*/
static MOBI_RET mobi_xml_buffer_addstring(xmlTextWriterPtr writer, const char *string) {
if (writer == NULL || writer->xmlbuf == NULL || writer->xmlbuf->mobibuffer == NULL || string == NULL) {
return MOBI_INIT_FAILED;
}
MOBIBuffer *buf = writer->xmlbuf->mobibuffer;
mobi_buffer_addstring(buf, string);
if (buf->error == MOBI_BUFFER_END) {
mobi_buffer_resize(buf, buf->maxlen * 2);
if (buf->error != MOBI_SUCCESS) {
return buf->error;
}
/* update xmlbuf->content */
writer->xmlbuf->content = writer->xmlbuf->mobibuffer->data;
mobi_xml_buffer_addstring(writer, string);
}
return buf->error;
}
/**
@brief Write character to xml buffer
@param[in,out] writer xmlTextWriter
@param[in] c Character
@return MOBI_RET status code (on success MOBI_SUCCESS)
*/
static MOBI_RET mobi_xml_buffer_addchar(xmlTextWriterPtr writer, const unsigned char c) {
if (writer == NULL || writer->xmlbuf == NULL || writer->xmlbuf->mobibuffer == NULL) {
return MOBI_INIT_FAILED;
}
MOBIBuffer *buf = writer->xmlbuf->mobibuffer;
mobi_buffer_add8(buf, c);
if (buf->error == MOBI_BUFFER_END) {
mobi_buffer_resize(buf, buf->maxlen * 2);
if (buf->error != MOBI_SUCCESS) {
return buf->error;
}
/* update xmlbuf->content */
writer->xmlbuf->content = writer->xmlbuf->mobibuffer->data;
mobi_xml_buffer_addchar(writer, c);
}
return buf->error;
}
/**
@brief Write terminating null character to xml buffer
@param[in,out] writer xmlTextWriter
@return MOBI_RET status code (on success MOBI_SUCCESS)
*/
static MOBI_RET mobi_xml_buffer_flush(xmlTextWriterPtr writer) {
return mobi_xml_buffer_addchar(writer, '\0');
}
/**
@brief Write string with encoded reserved characters to xml buffer
@param[in,out] writer xmlTextWriter
@param[in] string String
@return MOBI_RET status code (on success MOBI_SUCCESS)
*/
static MOBI_RET mobi_xml_buffer_addencoded(xmlTextWriterPtr writer, const char *string) {
if (string == NULL) {
return MOBI_INIT_FAILED;
}
MOBI_RET ret = MOBI_SUCCESS;
unsigned char *p = (unsigned char *)string;
unsigned char c;
while ((c = *p++)) {
switch (c) {
case '<':
ret = mobi_xml_buffer_addstring(writer, "&lt;");
break;
case '>':
ret = mobi_xml_buffer_addstring(writer, "&gt;");
break;
case '&':
ret = mobi_xml_buffer_addstring(writer, "&amp;");
break;
case '"':
ret = mobi_xml_buffer_addstring(writer, "&quot;");
break;
case '\r':
ret = mobi_xml_buffer_addstring(writer, "&#13;");
break;
default:
ret = mobi_xml_buffer_addchar(writer, c);
break;
}
if (ret != MOBI_SUCCESS) {
break;
}
}
return ret;
}
/**
@brief Write attribute value with encoded reserved characters to xml buffer
@param[in,out] writer xmlTextWriter
@param[in] string String
@return MOBI_RET status code (on success MOBI_SUCCESS)
*/
static MOBI_RET mobi_xml_buffer_addencoded_attr(xmlTextWriterPtr writer, const char *string) {
if (string == NULL) {
return MOBI_INIT_FAILED;
}
MOBI_RET ret = MOBI_SUCCESS;
unsigned char *p = (unsigned char *)string;
unsigned char c;
while ((c = *p++)) {
switch (c) {
case '<':
ret = mobi_xml_buffer_addstring(writer, "&lt;");
break;
case '>':
ret = mobi_xml_buffer_addstring(writer, "&gt;");
break;
case '&':
ret = mobi_xml_buffer_addstring(writer, "&amp;");
break;
case '"':
ret = mobi_xml_buffer_addstring(writer, "&quot;");
break;
case '\r':
ret = mobi_xml_buffer_addstring(writer, "&#13;");
break;
case '\n':
ret = mobi_xml_buffer_addstring(writer, "&#10;");
break;
case '\t':
ret = mobi_xml_buffer_addstring(writer, "&#9;");
break;
default:
ret = mobi_xml_buffer_addchar(writer, c);
break;
}
if (ret != MOBI_SUCCESS) {
break;
}
}
return ret;
}
/**
@brief Write indent to xml buffer
@param[in,out] writer xmlTextWriter
@return MOBI_RET status code (on success MOBI_SUCCESS)
*/
static MOBI_RET mobi_xml_write_indent(xmlTextWriterPtr writer) {
if (writer == NULL) {
debug_print("%s\n", "XML writer init failed");
return MOBI_INIT_FAILED;
}
size_t levels_count = mobi_xml_level(writer);
if (levels_count > 0) {
/* don't indent first level */
levels_count--;
}
MOBI_RET ret = MOBI_SUCCESS;
while (levels_count--) {
ret = mobi_xml_buffer_addchar(writer, ' ');
if (ret != MOBI_SUCCESS) {
break;
}
}
return ret;
}
/**
@brief Write namespace declaration if needed
@param[in,out] writer xmlTextWriter
*/
static void mobi_xml_write_ns(xmlTextWriterPtr writer) {
if (writer && writer->nsname && writer->nsvalue) {
xmlTextWriterWriteAttribute(writer, (unsigned char *) writer->nsname, (unsigned char *) writer->nsvalue);
free(writer->nsname);
writer->nsname = NULL;
free(writer->nsvalue);
writer->nsvalue = NULL;
}
}
/**
@brief Save namespace declaration parameters
@param[in,out] writer xmlTextWriter
@param[in] nsname NS attribute name
@param[in] nsvalue NS attribute value
@return MOBI_RET status code (on success MOBI_SUCCESS)
*/
static MOBI_RET mobi_xml_save_ns(xmlTextWriterPtr writer, const char *nsname, const char *nsvalue) {
/* Only one declaration should be enough for libmobi */
if (writer && writer->nsname == NULL && writer->nsvalue == NULL) {
writer->nsname = strdup(nsname);
if (writer->nsname == NULL) {
return MOBI_MALLOC_FAILED;
}
writer->nsvalue = strdup(nsvalue);
if (writer->nsvalue == NULL) {
return MOBI_MALLOC_FAILED;
}
}
return MOBI_SUCCESS;
}
/*
Libxml2 compatible functions
*/
/**
@brief Create xml buffer
Libxml2 compatibility wrapper for MOBIBuffer structure.
Must be deallocated with xmlBufferFree
@return Buffer pointer
*/
xmlBufferPtr xmlBufferCreate(void) {
xmlBufferPtr xmlbuf = NULL;
xmlbuf = malloc(sizeof(xmlBuffer));
if (xmlbuf == NULL) {
debug_print("%s", "Buffer allocation failed\n");
return NULL;
}
unsigned int size = MOBI_XML_BUFFERSIZE;
MOBIBuffer *buf = mobi_buffer_init(size);
if (buf == NULL) {
free(xmlbuf);
return NULL;
}
xmlbuf->content = buf->data;
xmlbuf->mobibuffer = buf;
return xmlbuf;
}
/**
@brief Free XML buffer
@param[in,out] buf XML buffer
*/
void xmlBufferFree(xmlBufferPtr buf) {
if (buf == NULL) { return; }
if (buf->mobibuffer != NULL) {
mobi_buffer_free(buf->mobibuffer);
}
free(buf);
}
/**
@brief Initialize TextWriter structure
@param[in] xmlbuf Initialized xml output buffer
@param[in] compression Unused
@return TextWriter pointer
*/
xmlTextWriterPtr xmlNewTextWriterMemory(xmlBufferPtr xmlbuf, int compression) {
UNUSED(compression);
if (xmlbuf == NULL) {
debug_print("%s", "XML buffer not initialized\n");
return NULL;
}
xmlTextWriterPtr writer = NULL;
writer = malloc(sizeof(xmlTextWriter));
if (writer == NULL) {
debug_print("%s", "XML writer allocation failed\n");
return NULL;
}
writer->xmlbuf = xmlbuf;
writer->states = NULL;
writer->nsname = NULL;
writer->nsvalue = NULL;
writer->indent_enable = false;
writer->indent_next = false;
return writer;
}
/**
@brief Deallocate TextWriter instance and all its resources
@param[in,out] writer TextWriter
*/
void xmlFreeTextWriter(xmlTextWriterPtr writer) {
if (writer == NULL) { return; }
if (writer->states != NULL) {
mobi_xml_state_delall(writer->states);
writer->states = NULL;
}
free(writer->nsname);
free(writer->nsvalue);
free(writer);
}
/**
@brief Start xml document
Only utf-8 encoding supported.
@param[in] writer TextWriter
@param[in] version Value of version attribute, "1.0" if NULL
@param[in] encoding Unused, defaults to utf-8
@param[in] standalone Unused, omitted in declaration
@return TextWriter pointer
*/
int xmlTextWriterStartDocument(xmlTextWriterPtr writer, const char *version,
const char *encoding, const char *standalone) {
UNUSED(encoding);
UNUSED(standalone);
if (writer == NULL) {
debug_print("%s\n", "XML writer init failed");
return XML_ERROR;
}
if (mobi_xml_level(writer) > 0) {
debug_print("%s\n", "XML document already started");
return XML_ERROR;
}
MOBI_RET ret = mobi_xml_buffer_addstring(writer, "<?xml version=");
if (ret != MOBI_SUCCESS) { return XML_ERROR; }
if (version == NULL) {
ret = mobi_xml_buffer_addstring(writer, "\"1.0\"");
} else {
ret = mobi_xml_buffer_addstring(writer, version);
}
if (ret != MOBI_SUCCESS) { return XML_ERROR; }
ret = mobi_xml_buffer_addstring(writer, "?>\n");
if (ret != MOBI_SUCCESS) { return XML_ERROR; }
return XML_OK;
}
/**
@brief End xml document
All open elements will be closed.
xmlBuffer will be flushed.
@param[in] writer TextWriter
@return XML_OK (0) on success, XML_ERROR (-1) on failure
*/
int xmlTextWriterEndDocument(xmlTextWriterPtr writer) {
if (writer == NULL) {
debug_print("%s\n", "XML writer init failed");
return XML_ERROR;
}
MOBIXmlState *state = NULL;
while((state = mobi_xml_state_current(writer))) {
switch (state->mode) {
case MOBI_XMLMODE_NAME:
case MOBI_XMLMODE_ATTR:
case MOBI_XMLMODE_TEXT:
xmlTextWriterEndElement(writer);
break;
default:
break;
}
}
MOBI_RET ret;
if (!writer->indent_enable) {
ret = mobi_xml_buffer_addstring(writer, "\n");
if (ret != MOBI_SUCCESS) { return XML_ERROR; }
}
ret = mobi_xml_buffer_flush(writer);
if (ret != MOBI_SUCCESS) { return XML_ERROR; }
return XML_OK;
}
/**
@brief Start xml element
@param[in,out] writer TextWriter
@param[in] name Element name
@return XML_OK (0) on success, XML_ERROR (-1) on failure
*/
int xmlTextWriterStartElement(xmlTextWriterPtr writer, const xmlChar *name) {
if (writer == NULL || name == NULL || *name == '\0') {
debug_print("%s\n", "XML writer init failed");
return XML_ERROR;
}
MOBI_RET ret = MOBI_SUCCESS;
MOBIXmlState *state = mobi_xml_state_current(writer);
if (state) {
switch (state->mode) {
case MOBI_XMLMODE_ATTR:
if (xmlTextWriterEndAttribute(writer) == XML_ERROR) { return XML_ERROR; }
/* fallthrough */
case MOBI_XMLMODE_NAME:
/* TODO: output ns declarations */
mobi_xml_write_ns(writer);
ret = mobi_xml_buffer_addstring(writer, ">");
if (ret != MOBI_SUCCESS) { return XML_ERROR; }
if (writer->indent_enable) {
ret = mobi_xml_buffer_addstring(writer, "\n");
if (ret != MOBI_SUCCESS) { return XML_ERROR; }
}
state->mode = MOBI_XMLMODE_TEXT;
if (ret != MOBI_SUCCESS) { return XML_ERROR; }
break;
default:
break;
}
}
mobi_xml_state_push(writer, (char *) name, MOBI_XMLMODE_NAME);
if (writer->indent_enable) {
ret = mobi_xml_write_indent(writer);
if (ret != MOBI_SUCCESS) { return XML_ERROR; }
}
ret = mobi_xml_buffer_addstring(writer, "<");
if (ret != MOBI_SUCCESS) { return XML_ERROR; }
ret = mobi_xml_buffer_addstring(writer, (const char *) name);
if (ret != MOBI_SUCCESS) { return XML_ERROR; }
return XML_OK;
}
/**
@brief End current element
@param[in] writer TextWriter
@return XML_OK (0) on success, XML_ERROR (-1) on failure
*/
int xmlTextWriterEndElement(xmlTextWriterPtr writer) {
if (writer == NULL) {
debug_print("%s\n", "XML writer init failed");
return XML_ERROR;
}
MOBI_RET ret = MOBI_SUCCESS;
MOBIXmlState *state = mobi_xml_state_current(writer);
if (state == NULL) { return XML_ERROR; }
switch (state->mode) {
case MOBI_XMLMODE_ATTR:
if (xmlTextWriterEndAttribute(writer) == XML_ERROR) { return XML_ERROR; }
mobi_xml_state_pop(writer);
/* fallthrough */
case MOBI_XMLMODE_NAME:
/* output namespace declarations */
mobi_xml_write_ns(writer);
if (writer->indent_enable) {
writer->indent_next = true;
}
ret = mobi_xml_buffer_addstring(writer, "/>");
if (ret != MOBI_SUCCESS) { return XML_ERROR; }
break;
case MOBI_XMLMODE_TEXT:
if (writer->indent_enable && writer->indent_next) {
ret = mobi_xml_write_indent(writer);
if (ret != MOBI_SUCCESS) { return XML_ERROR; }
writer->indent_next = true;
} else {
writer->indent_next = true;
}
ret = mobi_xml_buffer_addstring(writer, "</");
if (ret != MOBI_SUCCESS) { return XML_ERROR; }
ret = mobi_xml_buffer_addstring(writer, state->name);
if (ret != MOBI_SUCCESS) { return XML_ERROR; }
ret = mobi_xml_buffer_addstring(writer, ">");
if (ret != MOBI_SUCCESS) { return XML_ERROR; }
break;
default:
break;
}
if (writer->indent_enable) {
ret = mobi_xml_buffer_addstring(writer, "\n");
if (ret != MOBI_SUCCESS) { return XML_ERROR; }
}
mobi_xml_state_pop(writer);
return XML_OK;
}
/**
@brief Start attribute for current xml element
@param[in,out] writer TextWriter
@param[in] name Attribute name
@return XML_OK (0) on success, XML_ERROR (-1) on failure
*/
int xmlTextWriterStartAttribute(xmlTextWriterPtr writer, const xmlChar *name) {
if (writer == NULL) {
debug_print("%s\n", "XML writer init failed");
return XML_ERROR;
}
if (name == NULL || *name == '\0') {
debug_print("%s\n", "XML writer init failed");
return XML_ERROR;
}
MOBI_RET ret = MOBI_SUCCESS;
MOBIXmlState *state = mobi_xml_state_current(writer);
if (state) {
switch (state->mode) {
case MOBI_XMLMODE_ATTR:
if (xmlTextWriterEndAttribute(writer) == XML_ERROR) { return XML_ERROR; }
/* fallthrough */
case MOBI_XMLMODE_NAME:
ret = mobi_xml_buffer_addstring(writer, " ");
if (ret != MOBI_SUCCESS) { return XML_ERROR; }
ret = mobi_xml_buffer_addstring(writer, (const char *) name);
if (ret != MOBI_SUCCESS) { return XML_ERROR; }
ret = mobi_xml_buffer_addstring(writer, "=\"");
if (ret != MOBI_SUCCESS) { return XML_ERROR; }
state->mode = MOBI_XMLMODE_ATTR;
break;
default:
return XML_ERROR;
}
}
return XML_OK;
}
/**
@brief End current attribute
@param[in,out] writer TextWriter
@return XML_OK (0) on success, XML_ERROR (-1) on failure
*/
int xmlTextWriterEndAttribute(xmlTextWriterPtr writer) {
if (writer == NULL) {
debug_print("%s\n", "XML writer init failed");
return XML_ERROR;
}
MOBI_RET ret = MOBI_SUCCESS;
MOBIXmlState *state = mobi_xml_state_current(writer);
if (state) {
switch (state->mode) {
case MOBI_XMLMODE_ATTR:
state->mode = MOBI_XMLMODE_NAME;
ret = mobi_xml_buffer_addstring(writer, "\"");
if (ret != MOBI_SUCCESS) { return XML_ERROR; }
break;
default:
return XML_ERROR;
}
}
return XML_OK;
}
/**
@brief Write attribute with given name and content
@param[in,out] writer TextWriter
@param[in] name Attribute name
@param[in] content Attribute content
@return XML_OK (0) on success, XML_ERROR (-1) on failure
*/
int xmlTextWriterWriteAttribute(xmlTextWriterPtr writer, const xmlChar *name,
const xmlChar * content) {
if (xmlTextWriterStartAttribute(writer, name) == XML_ERROR) { return XML_ERROR; }
if (xmlTextWriterWriteString(writer, content) == XML_ERROR) { return XML_ERROR; }
if (xmlTextWriterEndAttribute(writer) == XML_ERROR) { return XML_ERROR; }
return XML_OK;
}
/**
@brief Start attribute with namespace support for current xml element
@param[in,out] writer TextWriter
@param[in] prefix Namespace prefix or NULL
@param[in] name Attribute name
@param[in] namespaceURI Namespace uri or NULL
@return XML_OK (0) on success, XML_ERROR (-1) on failure
*/
int xmlTextWriterStartAttributeNS(xmlTextWriterPtr writer,
const xmlChar *prefix, const xmlChar *name,
const xmlChar *namespaceURI) {
if (writer == NULL || name == NULL || *name == '\0') {
debug_print("%s\n", "XML writer init failed");
return XML_ERROR;
}
if (namespaceURI != NULL) {
char namespace[] = "xmlns";
if (prefix != NULL) {
size_t length = sizeof(namespace) - 1 + strlen((char *) prefix) + 1; /* add one for ":" */
char *prefixed = malloc(length + 1);
if (prefixed == NULL) {
debug_print("%s\n", "Memory allocation failed");
return XML_ERROR;
}
snprintf(prefixed, length + 1, "%s:%s", namespace, prefix);
MOBI_RET ret = mobi_xml_save_ns(writer, prefixed, (char *) namespaceURI);
free(prefixed);
if (ret != MOBI_SUCCESS) {
return XML_ERROR;
}
} else {
MOBI_RET ret = mobi_xml_save_ns(writer, namespace, (char *) namespaceURI);
if (ret != MOBI_SUCCESS) {
return XML_ERROR;
}
}
}
if (prefix != NULL) {
size_t length = strlen((char *) prefix) + strlen((char *) name) + 1; /* add one for ":" */
char *prefixed = malloc(length + 1);
if (prefixed == NULL) {
debug_print("%s\n", "Memory allocation failed");
return XML_ERROR;
}
snprintf(prefixed, length + 1, "%s:%s", prefix, name);
int ret = xmlTextWriterStartAttribute(writer, (xmlChar *)prefixed);
free(prefixed);
if (ret == XML_ERROR) {
return XML_ERROR;
}
} else {
int ret = xmlTextWriterStartAttribute(writer, name);
if (ret == XML_ERROR) {
return XML_ERROR;
}
}
return XML_OK;
}
/**
@brief Write attribute with namespace support
@param[in,out] writer TextWriter
@param[in] prefix Namespace prefix or NULL
@param[in] name Attribute name
@param[in] namespaceURI Namespace uri or NULL
@param[in] content Attribute content
@return XML_OK (0) on success, XML_ERROR (-1) on failure
*/
int xmlTextWriterWriteAttributeNS(xmlTextWriterPtr writer,
const xmlChar *prefix, const xmlChar *name,
const xmlChar *namespaceURI,
const xmlChar *content) {
if (xmlTextWriterStartAttributeNS(writer, prefix, name, namespaceURI) == XML_ERROR) { return XML_ERROR; }
if (xmlTextWriterWriteString(writer, content) == XML_ERROR) { return XML_ERROR; }
if (xmlTextWriterEndAttribute(writer) == XML_ERROR) { return XML_ERROR; }
return XML_OK;
}
/**
@brief Start element with namespace support
@param[in,out] writer TextWriter
@param[in] prefix Namespace prefix or NULL
@param[in] name Element name
@param[in] namespaceURI Namespace uri or NULL
@return XML_OK (0) on success, XML_ERROR (-1) on failure
*/
int xmlTextWriterStartElementNS(xmlTextWriterPtr writer,
const xmlChar *prefix, const xmlChar *name,
const xmlChar *namespaceURI) {
if (writer == NULL || name == NULL || *name == '\0') {
debug_print("%s\n", "XML writer init failed");
return XML_ERROR;
}
if (prefix != NULL) {
size_t length = strlen((char *) prefix) + strlen((char *) name) + 1;
char *prefixed = malloc(length + 1);
if (prefixed == NULL) {
debug_print("%s\n", "Memory allocation failed");
return XML_ERROR;
}
snprintf(prefixed, length + 1, "%s:%s", prefix, name);
int ret = xmlTextWriterStartElement(writer, (xmlChar *)prefixed);
free(prefixed);
if (ret == XML_ERROR) { return XML_ERROR; }
} else {
if (xmlTextWriterStartElement(writer, name) == XML_ERROR) { return XML_ERROR; }
}
if (namespaceURI != NULL) {
char namespace[] = "xmlns";
if (prefix != NULL) {
size_t length = sizeof(namespace) - 1 + strlen((char *) prefix) + 1;
char *prefixed = malloc(length + 1);
if (prefixed == NULL) {
debug_print("%s\n", "Memory allocation failed");
return XML_ERROR;
}
snprintf(prefixed, length + 1, "%s:%s", namespace, prefix);
MOBI_RET ret = mobi_xml_save_ns(writer, prefixed, (char *) namespaceURI);
free(prefixed);
if (ret != MOBI_SUCCESS) {
return XML_ERROR;
}
} else {
MOBI_RET ret = mobi_xml_save_ns(writer, namespace, (char *) namespaceURI);
if (ret != MOBI_SUCCESS) {
return XML_ERROR;
}
}
}
return XML_OK;
}
/**
@brief Write element with namespace support
@param[in,out] writer TextWriter
@param[in] prefix Namespace prefix or NULL
@param[in] name Element name
@param[in] namespaceURI Namespace uri or NULL
@param[in] content Element content
@return XML_OK (0) on success, XML_ERROR (-1) on failure
*/
int xmlTextWriterWriteElementNS(xmlTextWriterPtr writer, const xmlChar *prefix,
const xmlChar *name, const xmlChar *namespaceURI,
const xmlChar *content) {
if (xmlTextWriterStartElementNS(writer, prefix, name, namespaceURI) == XML_ERROR) { return XML_ERROR; }
if (xmlTextWriterWriteString(writer, content) == XML_ERROR) { return XML_ERROR; }
if (xmlTextWriterEndElement(writer) == XML_ERROR) { return XML_ERROR; }
return XML_OK;
}
/**
@brief Write xml string
@param[in,out] writer TextWriter
@param[in] content Attribute content
@return XML_OK (0) on success, XML_ERROR (-1) on failure
*/
int xmlTextWriterWriteString(xmlTextWriterPtr writer, const xmlChar *content) {
if (writer == NULL || content == NULL) {
debug_print("%s\n", "XML writer init failed");
return XML_ERROR;
}
MOBI_RET ret = MOBI_SUCCESS;
MOBI_XML_MODE mode = MOBI_XMLMODE_NONE;
MOBIXmlState *state = mobi_xml_state_current(writer);
if (state != NULL) {
mode = state->mode;
}
switch (mode) {
case MOBI_XMLMODE_NAME:
// output namespace decl
mobi_xml_write_ns(writer);
ret = mobi_xml_buffer_addstring(writer, ">");
if (ret != MOBI_SUCCESS) { return XML_ERROR; }
state->mode = MOBI_XMLMODE_TEXT;
/* fallthrough */
case MOBI_XMLMODE_TEXT:
ret = mobi_xml_buffer_addencoded(writer, (const char *) content);
if (writer->indent_enable) {
writer->indent_next = false;
}
break;
case MOBI_XMLMODE_ATTR:
ret = mobi_xml_buffer_addencoded_attr(writer, (const char *) content);
break;
default:
ret = mobi_xml_buffer_addstring(writer, (const char *) content);
if (writer->indent_enable) {
writer->indent_next = false;
}
break;
}
if (ret != MOBI_SUCCESS) { return XML_ERROR; }
return XML_OK;
}
/**
@brief Set indentation option
@param[in,out] writer TextWriter
@param[in] indent Indent output if value greater than zero
@return XML_OK (0) on success, XML_ERROR (-1) on failure
*/
int xmlTextWriterSetIndent(xmlTextWriterPtr writer, int indent) {
if (writer == NULL) {
debug_print("%s\n", "XML writer init failed");
return XML_ERROR;
}
writer->indent_enable = (indent != 0);
writer->indent_next = true;
return XML_OK;
}

View file

@ -0,0 +1,94 @@
/** @file xmlwriter.h
*
* Copyright (c) 2016 Bartek Fabiszewski
* http://www.fabiszewski.net
*
* This file is part of libmobi.
* Licensed under LGPL, either version 3, or any later.
* See <http://www.gnu.org/licenses/>
*/
#ifndef mobi_minixml_h
#define mobi_minixml_h
#include <stdio.h>
#include "buffer.h"
#include "structure.h"
#define BAD_CAST (xmlChar *)
#define LIBXML_TEST_VERSION
#define xmlCleanupParser()
typedef unsigned char xmlChar;
/**
@brief Buffer for xml output.
For libxml2 compatibility, it is a wrapper for MOBIBuffer
*/
typedef struct {
xmlChar *content; /**< Points to mobibuffer->data */
MOBIBuffer *mobibuffer; /**< Dynamic buffer */
} xmlBuffer;
typedef xmlBuffer *xmlBufferPtr;
/**
@brief Xml writer states
*/
typedef enum {
MOBI_XMLMODE_NONE = 0,
MOBI_XMLMODE_NAME,
MOBI_XMLMODE_ATTR,
MOBI_XMLMODE_TEXT
} MOBI_XML_MODE;
/**
@brief Xml writer states list structure
First element in the list is currently processed element.
Last element is root of the document
*/
typedef struct MOBIXmlState {
char *name; /**< Element name */
MOBI_XML_MODE mode; /**< State mode */
struct MOBIXmlState *next; /**< Next list item */
} MOBIXmlState;
/**
@brief Xml TextWriter structure
*/
typedef struct {
xmlBufferPtr xmlbuf; /**< XML buffer */
MOBIXmlState *states; /**< TextWriter states list */
char *nsname; /**< Namespace attribute name */
char *nsvalue; /**< Namespace attribute value */
bool indent_enable; /**< Enable indentation */
bool indent_next; /**< Indentation needed */
} xmlTextWriter;
typedef xmlTextWriter *xmlTextWriterPtr;
xmlBufferPtr xmlBufferCreate(void);
void xmlBufferFree(xmlBufferPtr buf);
xmlTextWriterPtr xmlNewTextWriterMemory(xmlBufferPtr xmlbuf, int compression);
void xmlFreeTextWriter(xmlTextWriterPtr writer);
int xmlTextWriterStartDocument(xmlTextWriterPtr writer, const char *version,
const char *encoding, const char *standalone);
int xmlTextWriterEndDocument(xmlTextWriterPtr writer);
int xmlTextWriterStartElement(xmlTextWriterPtr writer, const xmlChar *name);
int xmlTextWriterEndElement(xmlTextWriterPtr writer);
int xmlTextWriterWriteAttribute(xmlTextWriterPtr writer, const xmlChar *name,
const xmlChar *content);
int xmlTextWriterEndAttribute(xmlTextWriterPtr writer);
int xmlTextWriterWriteAttributeNS(xmlTextWriterPtr writer,
const xmlChar * prefix, const xmlChar * name,
const xmlChar * namespaceURI,
const xmlChar * content);
int xmlTextWriterStartElementNS(xmlTextWriterPtr writer,
const xmlChar *prefix, const xmlChar *name,
const xmlChar * namespaceURI);
int xmlTextWriterWriteElementNS(xmlTextWriterPtr writer, const xmlChar *prefix,
const xmlChar *name, const xmlChar *namespaceURI,
const xmlChar *content);
int xmlTextWriterWriteString(xmlTextWriterPtr writer, const xmlChar *content);
int xmlTextWriterSetIndent(xmlTextWriterPtr writer, int indent);
#endif

View file

@ -0,0 +1,42 @@
# Parallel tests suite
# Files for testing should be placed in samples directory.
# Normal files must have ".mobi" extension.
# Files that are expected to fail the tests should have ".fail" extension.
# Test script will try to recreate markup sources and dump rawml file.
# Script may additionally check md5 checksums of the produced output.
# In order to enable md5 verification files with checksums must be present in md5 directory.
# Name of the file with md5 checksums is md5 checksum of the sample file plus
# suffix "_rawml" for rawml checksum and "_markup" for all markup files checksums.
# Re-run ./configure after adding new samples
# Exclude large samples from dist package
EXTRA_DIST = md5 \
samples/sample-cp1252.mobi \
samples/sample-dict-infl2.mobi \
samples/sample-drm_pidLTKULBB^5V-v2.mobi \
samples/sample-drm-v1.mobi \
samples/sample-multimedia.mobi \
samples/sample-ncx.mobi \
samples/sample-obfuscated-fonts.mobi \
samples/sample-textread.mobi \
samples/sample-unicode-huffdic.mobi \
samples/sample-unicode-uncompressed.mobi \
samples/sample-invalid-indx.fail
AUTOMAKE_OPTIONS = parallel-tests
TESTS = @TESTLIST@
XFAIL_TESTS = @FAILLIST@
TEST_EXTENSIONS = .mobi .fail
MOBI_LOG_COMPILER = ./test.sh
FAIL_LOG_COMPILER = ./test.sh
clean-local:
-rm -rf tmp
all-local:
@if test x@RUN_TESTS@ = xno; then \
echo "============================================================================"; \
echo "WARNING: All tests will be skipped, because bash was not found in your PATH."; \
echo " Please install bash and rerun configure script."; \
echo "============================================================================"; \
fi

View file

@ -0,0 +1,6 @@
4a7d6afd2ce8bac1333c6d46f74773a4 part00000.html
0945cf5525eab95452b12e396d4f5ae4 resource00000.jpg
0945cf5525eab95452b12e396d4f5ae4 resource00001.jpg
90fdcc4e447f9e8babb418e9a8677311 resource00002.jpg
62a722e40769ec8b222b6c788b8f3463 resource00003.ncx
e2ba461f8530066d31572a57dde6129a resource00004.opf

View file

@ -0,0 +1 @@
9f397e35c0608a9777e02efa416665a0

View file

@ -0,0 +1,6 @@
5af19c35a5bcc1443bd661f4d226ea27 part00000.html
2eb4a36ae5534b3e0d976ddc459d209a resource00000.jpg
7ab80fa12ddee2f2bfc16498da537028 resource00001.jpg
688aeffb0a078da56295bbc37ab2d28d resource00002.jpg
a480fcdcf016467f646f283140457d1c resource00003.ncx
2815cf0ccbf3acbbb2649200f337567a resource00004.opf

View file

@ -0,0 +1 @@
14118d6e0c526b307b94cec17d8d5395

View file

@ -0,0 +1,5 @@
72912a00456b9b3c194de09e651c70bc part00000.html
b19e40b775c1727a8ff0311caeb5b098 part00001.html
1ea860339fc7c535a801566dea0d5901 part00002.html
547d4f2b211ddabc77fe1db54143b087 resource00000.ncx
70b805f6b13dd9366bfc0d94c2f4f785 resource00001.opf

View file

@ -0,0 +1 @@
448a891b3bd94fb78045704fbb5988cc

View file

@ -0,0 +1,8 @@
f03d1a71d2ef80b53d9d48823e2aad2d part00000.html
dd2fab65a653934d60369b0f9c4b84ee resource00000.jpg
48e11be0e511cd31d5c1aca1dc52a644 resource00001.jpg
8bf1a77a6df6333344bc0a97012d8ccb resource00002.jpg
bf2727a10ab068bb5d3eafa0b7ace4e0 resource00004.jpg
bbc069268a93c1153286924bf72a82b1 resource00005.jpg
b898ff28a9c8236ea6fdc41aadadd527 resource00006.ncx
3e5ae3fdd385fc6c9e7e592e66e5e255 resource00007.opf

View file

@ -0,0 +1 @@
c4158a8a1cf16101dd6ceeee53b6aef1

View file

@ -0,0 +1,4 @@
51d871a7dd9269977d26d8d3c48ca2d6 part00000.html
3eb21f0515c65686a1339136bd70fc67 resource00025.bmp
df1392d0768b9aa2a359af03f91224ed resource00026.ncx
7c12f209822e2566e66173d1bfb74edf resource00027.opf

View file

@ -0,0 +1 @@
a644174e53c23cd0ac108b91200e0ff7

View file

@ -0,0 +1,6 @@
5af19c35a5bcc1443bd661f4d226ea27 part00000.html
2eb4a36ae5534b3e0d976ddc459d209a resource00000.jpg
7ab80fa12ddee2f2bfc16498da537028 resource00001.jpg
688aeffb0a078da56295bbc37ab2d28d resource00002.jpg
a480fcdcf016467f646f283140457d1c resource00003.ncx
2815cf0ccbf3acbbb2649200f337567a resource00004.opf

View file

@ -0,0 +1 @@
14118d6e0c526b307b94cec17d8d5395

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1 @@
a2756abde16983fda113fcabb09db648

View file

@ -0,0 +1,6 @@
3b25aa92cdb90e71f860506d7733b903 flow00001.css
91203ddb7a64f4e72040512f73428aa4 flow00002.css
aa9d0636b917baed54e6c68308adba07 part00000.html
01ede3cdbd26439b7f30fdc2f7b525cb resource00000.otf
0de6fa741a35160233f0ac1078afb02f resource00001.ncx
eb550aed365cfb13b59bfb6589775c35 resource00002.opf

View file

@ -0,0 +1 @@
20c60c1766bdc00ae49cfd0631bff2c4

View file

@ -0,0 +1,7 @@
5d00d50e7d9d4ba11e87557d9f4edd1c part00000.html
7dee30a6b9bc07b5ec92cda6f424b7db part00001.html
ae0198f50c282044c65082a256852fa5 resource00000.jpg
7ab80fa12ddee2f2bfc16498da537028 resource00001.jpg
688aeffb0a078da56295bbc37ab2d28d resource00003.jpg
815dea478c839572d5772819d2292f0c resource00004.ncx
2c8e8b057b5511ace63e4343c7a43b6e resource00005.opf

View file

@ -0,0 +1 @@
02cf5a2f37faee76dfcafaefe4fd27cf

View file

@ -0,0 +1,3 @@
abf7fd0126f52f722b14129c7958e397 part00000.html
e37c79f0fe27d40f85c66e59dbc725f3 resource00000.ncx
99c3f883921a92fd97511f983a21691d resource00001.opf

View file

@ -0,0 +1 @@
b355c36f0d55450cedab86f0eefc2c82

View file

@ -0,0 +1,9 @@
6d1e99d90451bcda489bb7cbe014ba7e part00000.html
c2691922730c85a07b30c558987cc478 resource00000.jpg
06bc4024a3a146f8d0141336d3f6944a resource00001.gif
c5e8e3dd8333e7227accfbdfcd120726 resource00002.gif
0e6356f75416cf28601ba3efd2b4abf6 resource00003.gif
c2691922730c85a07b30c558987cc478 resource00004.jpg
8a3b469a251fcf8128982c6c1d30a12f resource00005.jpg
3a7d9108f54fbee998fe9e0e22cc90b3 resource00006.ncx
192f37b64ab8bb41dedb8c337de1f2d3 resource00007.opf

View file

@ -0,0 +1 @@
4917156e4ca233fff89ab981e2efd055

View file

@ -0,0 +1,5 @@
b70fe0a8219e18d24e999dfff61e4453 part00000.pdf
2cef05b936c837a10c0d54f17e706169 resource00000.jpg
7c6036efcb8c2ad515cf66fa266fd04b resource00001.jpg
e85af0383e60aa2dfd8fdf1aeb775dfc resource00002.ncx
b66e20cc9d0d8eb63b855b5f260c6b08 resource00003.opf

View file

@ -0,0 +1 @@
e5b12b435fc5e273057aa25b89d1c0e1

View file

@ -0,0 +1,4 @@
ceb9b0f0c8e7c26084855a4d446dabe0 part00000.html
3eb21f0515c65686a1339136bd70fc67 resource00025.bmp
df1392d0768b9aa2a359af03f91224ed resource00026.ncx
7c12f209822e2566e66173d1bfb74edf resource00027.opf

View file

@ -0,0 +1 @@
1986e790ec56faf9b56f84fb01789cdc

View file

@ -0,0 +1,7 @@
4dc443c6782ba0edca2a967c00fdc14e part00000.html
7dee30a6b9bc07b5ec92cda6f424b7db part00001.html
ae0198f50c282044c65082a256852fa5 resource00000.jpg
7ab80fa12ddee2f2bfc16498da537028 resource00001.jpg
688aeffb0a078da56295bbc37ab2d28d resource00003.jpg
a6e51d4765a655e9e2171a5036335aed resource00004.ncx
24225add64b8f31efef3979e714573c2 resource00005.opf

View file

@ -0,0 +1 @@
7e18714ea6470149d2a56b71517286f4

View file

@ -0,0 +1,3 @@
a930d33cf6e4e37c96471e87c0c41a1c part00000.html
465c4ddf4fd259c9ede01bd63dfbd337 resource00000.ncx
5de9bbc64b8ddbba11612ca008361edb resource00001.opf

View file

@ -0,0 +1 @@
248ac1e6f0f88b53302c102215cee8b0

View file

@ -0,0 +1,9 @@
ced7b4f1735bd56e1e61a2e633ffe5f5 part00000.html
7dee30a6b9bc07b5ec92cda6f424b7db part00001.html
ae0198f50c282044c65082a256852fa5 resource00000.jpg
a68d962903b87b88131f75b9cda8249a resource00001.mpg
0cf790e01e20741cdac79d6a7385545b resource00002.mp3
7ab80fa12ddee2f2bfc16498da537028 resource00003.jpg
688aeffb0a078da56295bbc37ab2d28d resource00005.jpg
cbce4b484c3eb3b9d2a6a3f11dba01dc resource00006.ncx
c13611644beefd62840be10a6f98efd4 resource00007.opf

View file

@ -0,0 +1 @@
3f5586c0d20cd93544b86b09b3cf7ddd

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show more