From d8d9f708036a0014b05d8f6eaa2ab775501dfd06 Mon Sep 17 00:00:00 2001 From: Miguel Borges de Freitas <92enen@gmail.com> Date: Fri, 17 Nov 2023 17:08:29 +0000 Subject: [PATCH] Add EXIV2_ENABLE_FILESYSTEM_ACCESS option --- CMakeLists.txt | 5 +++++ README.md | 1 + cmake/config.h.cmake | 3 +++ cmake/findDependencies.cmake | 4 +++- cmake/generateConfigFile.cmake | 9 +++++---- cmake/printSummary.cmake | 1 + include/exiv2/basicio.hpp | 4 +++- include/exiv2/exif.hpp | 6 ++++++ include/exiv2/preview.hpp | 2 ++ meson.build | 1 + src/basicio.cpp | 32 +++++++++++++++++--------------- src/exif.cpp | 6 ++++++ src/futils.cpp | 10 ++++++++++ src/image.cpp | 14 +++++++++++++- src/makernote_int.cpp | 8 +++++++- src/preview.cpp | 2 ++ src/tiffcomposite_int.cpp | 2 +- 17 files changed, 86 insertions(+), 24 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d5ae28dd6..cd339a6213 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,6 +46,7 @@ option(EXIV2_ENABLE_BMFF "Build with BMFF support" ON) option(EXIV2_ENABLE_BROTLI "Use Brotli for JPEG XL compressed boxes (BMFF)" ON) option(EXIV2_ENABLE_VIDEO "Build with video support" ON) option(EXIV2_ENABLE_INIH "Use inih library" ON) +option(EXIV2_ENABLE_FILESYSTEM_ACCESS "Build with filesystem access" ON) option(EXIV2_BUILD_SAMPLES "Build sample applications" OFF) option(EXIV2_BUILD_EXIV2_COMMAND "Build exiv2 command-line executable" ON) @@ -100,18 +101,22 @@ include(cmake/compilerFlagsExiv2.cmake REQUIRED) add_subdirectory(src) if(BUILD_TESTING AND EXIV2_BUILD_UNIT_TESTS) + set(EXIV2_ENABLE_FILESYSTEM_ACCESS ON) add_subdirectory(unitTests) endif() if(EXIV2_BUILD_FUZZ_TESTS) + set(EXIV2_ENABLE_FILESYSTEM_ACCESS ON) add_subdirectory(fuzz) endif() if(EXIV2_BUILD_EXIV2_COMMAND) add_subdirectory(app) + set(EXIV2_ENABLE_FILESYSTEM_ACCESS ON) if(EXIV2_BUILD_SAMPLES) add_subdirectory(samples) + set(EXIV2_ENABLE_FILESYSTEM_ACCESS ON) get_directory_property(SAMPLES DIRECTORY samples DEFINITION APPLICATIONS) if(BUILD_TESTING AND Python3_Interpreter_FOUND) diff --git a/README.md b/README.md index ce3cb72ebf..d1d0d643a8 100644 --- a/README.md +++ b/README.md @@ -252,6 +252,7 @@ option( EXIV2_ENABLE_PNG "Build with png support (requires libz)" ... option( EXIV2_ENABLE_BMFF "Build with BMFF support (brotli recommended)" ON ) option( EXIV2_ENABLE_BROTLI "Use Brotli for JPEG XL compressed boxes (BMFF)" ON ) +option( EXIV2_ENABLE_FILESYSTEM_ACCESS "Build with filesystem access" ON ) 577 rmills@rmillsmm:~/gnu/github/exiv2/exiv2 $ ``` diff --git a/cmake/config.h.cmake b/cmake/config.h.cmake index a817d2d1b6..f24cd4a635 100644 --- a/cmake/config.h.cmake +++ b/cmake/config.h.cmake @@ -6,6 +6,9 @@ // Define to 1 if you want to use libcurl in httpIO. #cmakedefine EXV_USE_CURL +// Define to 1 if you want to enable filesystem access +#cmakedefine EXV_ENABLE_FILESYSTEM + // Define if you require webready support. #cmakedefine EXV_ENABLE_WEBREADY diff --git a/cmake/findDependencies.cmake b/cmake/findDependencies.cmake index 393138d26b..5e116730ef 100644 --- a/cmake/findDependencies.cmake +++ b/cmake/findDependencies.cmake @@ -37,7 +37,9 @@ if(BUILD_TESTING) endif() endif() -find_package(Filesystem COMPONENTS Experimental Final REQUIRED) +if(EXIV2_ENABLE_FILESYSTEM_ACCESS) + find_package(Filesystem COMPONENTS Experimental Final REQUIRED) +endif() # don't use Frameworks on the Mac (#966) if (APPLE) diff --git a/cmake/generateConfigFile.cmake b/cmake/generateConfigFile.cmake index 49c9a10f6c..20e331c045 100644 --- a/cmake/generateConfigFile.cmake +++ b/cmake/generateConfigFile.cmake @@ -6,10 +6,11 @@ include(CheckCXXSymbolExists) if (${EXIV2_ENABLE_WEBREADY}) set(EXV_USE_CURL ${EXIV2_ENABLE_CURL}) endif() -set(EXV_ENABLE_BMFF ${EXIV2_ENABLE_BMFF}) -set(EXV_ENABLE_WEBREADY ${EXIV2_ENABLE_WEBREADY}) -set(EXV_HAVE_LENSDATA ${EXIV2_ENABLE_LENSDATA}) -set(EXV_ENABLE_INIH ${EXIV2_ENABLE_INIH}) +set(EXV_ENABLE_BMFF ${EXIV2_ENABLE_BMFF}) +set(EXV_ENABLE_WEBREADY ${EXIV2_ENABLE_WEBREADY}) +set(EXV_HAVE_LENSDATA ${EXIV2_ENABLE_LENSDATA}) +set(EXV_ENABLE_INIH ${EXIV2_ENABLE_INIH}) +set(EXV_ENABLE_FILESYSTEM ${EXIV2_ENABLE_FILESYSTEM_ACCESS}) set(EXV_PACKAGE_NAME ${PROJECT_NAME}) set(EXV_PACKAGE_VERSION ${PROJECT_VERSION}) diff --git a/cmake/printSummary.cmake b/cmake/printSummary.cmake index 224524110a..07e3c82237 100644 --- a/cmake/printSummary.cmake +++ b/cmake/printSummary.cmake @@ -69,4 +69,5 @@ OptionOutput( "Building unit tests: " EXIV2_BUILD_UNIT_TESTS AND OptionOutput( "Building fuzz tests: " EXIV2_BUILD_FUZZ_TESTS ) OptionOutput( "Building doc: " EXIV2_BUILD_DOC ) OptionOutput( "Building with coverage flags: " BUILD_WITH_COVERAGE ) +OptionOutput( "Building with filesystem access " EXIV2_ENABLE_FILESYSTEM_ACCESS ) OptionOutput( "Using ccache: " BUILD_WITH_CCACHE ) diff --git a/include/exiv2/basicio.hpp b/include/exiv2/basicio.hpp index 179220464a..71155136d9 100644 --- a/include/exiv2/basicio.hpp +++ b/include/exiv2/basicio.hpp @@ -276,6 +276,7 @@ class EXIV2API IoCloser { IoCloser& operator=(const IoCloser&) = delete; }; // class IoCloser +#ifdef EXV_ENABLE_FILESYSTEM /*! @brief Provides binary file IO by implementing the BasicIo interface. @@ -479,6 +480,7 @@ class EXIV2API FileIo : public BasicIo { std::unique_ptr p_; }; // class FileIo +#endif /*! @brief Provides binary IO on blocks of memory by implementing the BasicIo @@ -686,7 +688,7 @@ class EXIV2API XPathIo : public MemIo { */ void ReadDataUri(const std::string& path); }; // class XPathIo -#else +#elif defined(EXV_ENABLE_FILESYSTEM) class EXIV2API XPathIo : public FileIo { public: /*! diff --git a/include/exiv2/exif.hpp b/include/exiv2/exif.hpp index 8b1d3d6a4b..1228b5dd4f 100644 --- a/include/exiv2/exif.hpp +++ b/include/exiv2/exif.hpp @@ -229,6 +229,7 @@ class EXIV2API ExifThumbC { data buffer and %DataBuf ensures that it will be deleted. */ [[nodiscard]] DataBuf copy() const; +#ifdef EXV_ENABLE_FILESYSTEM /*! @brief Write the thumbnail image to a file. @@ -240,6 +241,7 @@ class EXIV2API ExifThumbC { @return The number of bytes written. */ [[nodiscard]] size_t writeFile(const std::string& path) const; +#endif /*! @brief Return the MIME type of the thumbnail, either \c "image/tiff" or \c "image/jpeg". @@ -279,6 +281,7 @@ class EXIV2API ExifThumb : public ExifThumbC { //! @name Manipulators //@{ +#ifdef EXV_ENABLE_FILESYSTEM /*! @brief Set the Exif thumbnail to the JPEG image \em path. Set XResolution, YResolution and ResolutionUnit to \em xres, @@ -297,6 +300,7 @@ class EXIV2API ExifThumb : public ExifThumbC { application that comes with OS X for one.) - David Harvey. */ void setJpegThumbnail(const std::string& path, URational xres, URational yres, uint16_t unit); +#endif /*! @brief Set the Exif thumbnail to the JPEG image pointed to by \em buf, and size \em size. Set XResolution, YResolution and @@ -315,6 +319,7 @@ class EXIV2API ExifThumb : public ExifThumbC { application that comes with OS X for one.) - David Harvey. */ void setJpegThumbnail(const byte* buf, size_t size, URational xres, URational yres, uint16_t unit); +#ifdef EXV_ENABLE_FILESYSTEM /*! @brief Set the Exif thumbnail to the JPEG image \em path. @@ -329,6 +334,7 @@ class EXIV2API ExifThumb : public ExifThumbC { @note Additional existing Exif thumbnail tags are not modified. */ void setJpegThumbnail(const std::string& path); +#endif /*! @brief Set the Exif thumbnail to the JPEG image pointed to by \em buf, and size \em size. diff --git a/include/exiv2/preview.hpp b/include/exiv2/preview.hpp index 295c35b5c4..db069ec8c6 100644 --- a/include/exiv2/preview.hpp +++ b/include/exiv2/preview.hpp @@ -68,6 +68,7 @@ class EXIV2API PreviewImage { @brief Return the size of the preview image in bytes. */ [[nodiscard]] uint32_t size() const; +#ifdef EXV_ENABLE_FILESYSTEM /*! @brief Write the thumbnail image to a file. @@ -79,6 +80,7 @@ class EXIV2API PreviewImage { @return The number of bytes written. */ [[nodiscard]] size_t writeFile(const std::string& path) const; +#endif /*! @brief Return the MIME type of the preview image, usually either \c "image/tiff" or \c "image/jpeg". diff --git a/meson.build b/meson.build index ff72e3d633..a9f02a3380 100644 --- a/meson.build +++ b/meson.build @@ -121,6 +121,7 @@ cdata.set('EXV_HAVE_LIBZ', zlib_dep.found()) cdata.set('EXV_ENABLE_WEBREADY', get_option('webready')) cdata.set('EXV_USE_CURL', curl_dep.found()) cdata.set('EXV_ENABLE_NLS', intl_dep.found()) +cdata.set('EXV_ENABLE_FILESYSTEM', true) cfile = configure_file( input: 'cmake/config.h.cmake', diff --git a/src/basicio.cpp b/src/basicio.cpp index 609b3f088a..3971cb50ce 100644 --- a/src/basicio.cpp +++ b/src/basicio.cpp @@ -35,6 +35,7 @@ #include #endif +#ifdef EXV_ENABLE_FILESYSTEM #ifdef _WIN32 #include #include @@ -47,19 +48,7 @@ namespace fs = std::filesystem; #include namespace fs = std::experimental::filesystem; #endif - -// ***************************************************************************** -// class member definitions -namespace { -/// @brief replace each substring of the subject that matches the given search string with the given replacement. -void ReplaceStringInPlace(std::string& subject, std::string_view search, std::string_view replace) { - auto pos = subject.find(search); - while (pos != std::string::npos) { - subject.replace(pos, search.length(), replace); - pos += subject.find(search, pos + replace.length()); - } -} -} // namespace +#endif namespace Exiv2 { void BasicIo::readOrThrow(byte* buf, size_t rcount, ErrorCode err) { @@ -73,6 +62,7 @@ void BasicIo::seekOrThrow(int64_t offset, Position pos, ErrorCode err) { Internal::enforce(r == 0, err); } +#ifdef EXV_ENABLE_FILESYSTEM //! Internal Pimpl structure of class FileIo. class FileIo::Impl { public: @@ -550,6 +540,7 @@ const std::string& FileIo::path() const noexcept { void FileIo::populateFakeData() { } +#endif //! Internal Pimpl structure of class MemIo. class MemIo::Impl final { @@ -898,7 +889,7 @@ void XPathIo::ReadDataUri(const std::string& path) { delete[] decodeData; } -#else +#elif defined(EXV_ENABLE_FILESYSTEM) XPathIo::XPathIo(const std::string& orgPath) : FileIo(XPathIo::writeDataToFile(orgPath)), tempFilePath_(path()) { } @@ -913,6 +904,16 @@ void XPathIo::transfer(BasicIo& src) { if (isTemp_) { // replace temp path to gent path. auto currentPath = path(); + + // replace each substring of the subject that matches the given search string with the given replacement. + auto ReplaceStringInPlace = [](std::string& subject, std::string_view search, std::string_view replace) { + auto pos = subject.find(search); + while (pos != std::string::npos) { + subject.replace(pos, search.length(), replace); + pos += subject.find(search, pos + replace.length()); + } + }; + ReplaceStringInPlace(currentPath, XPathIo::TEMP_FILE_EXT, XPathIo::GEN_FILE_EXT); setPath(currentPath); @@ -1707,7 +1708,7 @@ CurlIo::CurlIo(const std::string& url, size_t blockSize) { // ************************************************************************* // free functions - +#ifdef EXV_ENABLE_FILESYSTEM DataBuf readFile(const std::string& path) { FileIo file(path); if (file.open("rb") != 0) { @@ -1727,6 +1728,7 @@ size_t writeFile(const DataBuf& buf, const std::string& path) { } return file.write(buf.c_data(), buf.size()); } +#endif #ifdef EXV_USE_CURL size_t curlWriter(char* data, size_t size, size_t nmemb, std::string* writerData) { diff --git a/src/exif.cpp b/src/exif.cpp index 4f61b074c2..9c300e5311 100644 --- a/src/exif.cpp +++ b/src/exif.cpp @@ -375,6 +375,7 @@ DataBuf ExifThumbC::copy() const { return thumbnail->copy(exifData_); } +#ifdef EXV_ENABLE_FILESYSTEM size_t ExifThumbC::writeFile(const std::string& path) const { auto thumbnail = Thumbnail::create(exifData_); if (!thumbnail) @@ -387,6 +388,7 @@ size_t ExifThumbC::writeFile(const std::string& path) const { return Exiv2::writeFile(buf, name); } +#endif const char* ExifThumbC::mimeType() const { auto thumbnail = Thumbnail::create(exifData_); @@ -405,10 +407,12 @@ const char* ExifThumbC::extension() const { ExifThumb::ExifThumb(ExifData& exifData) : ExifThumbC(exifData), exifData_(exifData) { } +#ifdef EXV_ENABLE_FILESYSTEM void ExifThumb::setJpegThumbnail(const std::string& path, URational xres, URational yres, uint16_t unit) { DataBuf thumb = readFile(path); // may throw setJpegThumbnail(thumb.c_data(), thumb.size(), xres, yres, unit); } +#endif void ExifThumb::setJpegThumbnail(const byte* buf, size_t size, URational xres, URational yres, uint16_t unit) { setJpegThumbnail(buf, size); @@ -417,10 +421,12 @@ void ExifThumb::setJpegThumbnail(const byte* buf, size_t size, URational xres, U exifData_["Exif.Thumbnail.ResolutionUnit"] = unit; } +#ifdef EXV_ENABLE_FILESYSTEM void ExifThumb::setJpegThumbnail(const std::string& path) { DataBuf thumb = readFile(path); // may throw setJpegThumbnail(thumb.c_data(), thumb.size()); } +#endif void ExifThumb::setJpegThumbnail(const byte* buf, size_t size) { exifData_["Exif.Thumbnail.Compression"] = static_cast(6); diff --git a/src/futils.cpp b/src/futils.cpp index 98bf8db787..94629a3e30 100644 --- a/src/futils.cpp +++ b/src/futils.cpp @@ -15,6 +15,7 @@ #include #include +#ifdef EXV_ENABLE_FILESYSTEM #if __has_include() #include namespace fs = std::filesystem; @@ -22,6 +23,7 @@ namespace fs = std::filesystem; #include namespace fs = std::experimental::filesystem; #endif +#endif #if defined(_WIN32) // clang-format off @@ -231,7 +233,11 @@ bool fileExists(const std::string& path) { if (fileProtocol(path) != pFile) { return true; } +#ifdef EXV_ENABLE_FILESYSTEM return fs::exists(path); +#else + return false; +#endif } std::string strError() { @@ -341,6 +347,7 @@ Uri Uri::Parse(const std::string& uri) { } std::string getProcessPath() { +#ifdef EXV_ENABLE_FILESYSTEM #if defined(__FreeBSD__) std::string ret("unknown"); unsigned int n; @@ -382,5 +389,8 @@ std::string getProcessPath() { return "unknown"; } #endif +#else + return "unknown"; +#endif } } // namespace Exiv2 diff --git a/src/image.cpp b/src/image.cpp index 60ef4a2fd0..589ba43413 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -120,11 +120,13 @@ constexpr Registry registry[] = { #endif // EXV_ENABLE_BMFF }; +#ifdef EXV_ENABLE_FILESYSTEM std::string pathOfFileUrl(const std::string& url) { std::string path = url.substr(7); size_t found = path.find('/'); return (found == std::string::npos) ? path : path.substr(found); } +#endif } // namespace @@ -782,9 +784,13 @@ bool ImageFactory::checkType(ImageType type, BasicIo& io, bool advance) { return false; } -ImageType ImageFactory::getType(const std::string& path) { +ImageType ImageFactory::getType([[maybe_unused]] const std::string& path) { +#ifdef EXV_ENABLE_FILESYSTEM FileIo fileIo(path); return getType(fileIo); +#else + return ImageType::none; +#endif } ImageType ImageFactory::getType(const byte* data, size_t size) { @@ -817,12 +823,16 @@ BasicIo::UniquePtr ImageFactory::createIo(const std::string& path, [[maybe_unuse if (fProt == pHttp) return std::make_unique(path); // may throw #endif +#ifdef EXV_ENABLE_FILESYSTEM if (fProt == pFileUri) return std::make_unique(pathOfFileUrl(path)); if (fProt == pStdin || fProt == pDataUri) return std::make_unique(path); // may throw return std::make_unique(path); +#else + return nullptr; +#endif } // ImageFactory::createIo Image::UniquePtr ImageFactory::open(const std::string& path, bool useCurl) { @@ -851,6 +861,7 @@ Image::UniquePtr ImageFactory::open(BasicIo::UniquePtr io) { return nullptr; } +#ifdef EXV_ENABLE_FILESYSTEM Image::UniquePtr ImageFactory::create(ImageType type, const std::string& path) { auto fileIo = std::make_unique(path); // Create or overwrite the file, then close it @@ -865,6 +876,7 @@ Image::UniquePtr ImageFactory::create(ImageType type, const std::string& path) { throw Error(ErrorCode::kerUnsupportedImageType, static_cast(type)); return image; } +#endif Image::UniquePtr ImageFactory::create(ImageType type) { auto image = create(type, std::make_unique()); diff --git a/src/makernote_int.cpp b/src/makernote_int.cpp index 44332ae8b3..40ffb8b267 100644 --- a/src/makernote_int.cpp +++ b/src/makernote_int.cpp @@ -18,6 +18,7 @@ #include #include +#ifdef EXV_ENABLE_FILESYSTEM #if __has_include() #include namespace fs = std::filesystem; @@ -25,6 +26,7 @@ namespace fs = std::filesystem; #include namespace fs = std::experimental::filesystem; #endif +#endif #if !defined(_WIN32) #include @@ -59,6 +61,7 @@ namespace Exiv2::Internal { // If not found in cwd, we return the default path // which is the user profile path on win and the home dir on linux std::string getExiv2ConfigPath() { +#ifdef EXV_ENABLE_FILESYSTEM #ifdef _WIN32 std::string inifile("exiv2.ini"); #else @@ -81,13 +84,16 @@ std::string getExiv2ConfigPath() { currentPath = std::string(pw ? pw->pw_dir : ""); #endif return (currentPath / inifile).string(); +#else + return ""; +#endif } std::string readExiv2Config([[maybe_unused]] const std::string& section, [[maybe_unused]] const std::string& value, const std::string& def) { std::string result = def; -#ifdef EXV_ENABLE_INIH +#if defined(EXV_ENABLE_INIH) && defined(EXV_ENABLE_FILESYSTEM) INIReader reader(Exiv2::Internal::getExiv2ConfigPath()); if (reader.ParseError() == 0) { result = reader.Get(section, value, def); diff --git a/src/preview.cpp b/src/preview.cpp index e341610d04..6a0a58f7bc 100644 --- a/src/preview.cpp +++ b/src/preview.cpp @@ -967,12 +967,14 @@ PreviewImage& PreviewImage::operator=(const PreviewImage& rhs) { return *this; } +#ifdef EXV_ENABLE_FILESYSTEM size_t PreviewImage::writeFile(const std::string& path) const { std::string name = path + extension(); // Todo: Creating a DataBuf here unnecessarily copies the memory DataBuf buf(pData(), size()); return Exiv2::writeFile(buf, name); } +#endif DataBuf PreviewImage::copy() const { return {pData(), size()}; diff --git a/src/tiffcomposite_int.cpp b/src/tiffcomposite_int.cpp index 56c04f8de1..cfc5cdf2bf 100644 --- a/src/tiffcomposite_int.cpp +++ b/src/tiffcomposite_int.cpp @@ -1099,7 +1099,7 @@ size_t TiffBinaryArray::doWrite(IoWrapper& ioWrapper, ByteOrder byteOrder, size_ } DataBuf buf = cryptFct(tag(), mio.mmap(), mio.size(), pRoot_); if (!buf.empty()) { - mio.seek(0, Exiv2::FileIo::beg); + mio.seek(0, Exiv2::BasicIo::beg); mio.write(buf.c_data(), buf.size()); } }