diff --git a/CMakeLists.txt b/CMakeLists.txt index e9f14f7224..fec1b58864 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,7 @@ option( EXIV2_ENABLE_BMFF "Build with BMFF support" 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 ) @@ -95,17 +96,21 @@ add_subdirectory( src ) if( EXIV2_BUILD_UNIT_TESTS ) add_subdirectory ( unitTests ) + set(EXIV2_ENABLE_FILESYSTEM_ACCESS ON) endif() if( EXIV2_BUILD_FUZZ_TESTS ) add_subdirectory ( fuzz ) + set(EXIV2_ENABLE_FILESYSTEM_ACCESS ON) 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 (Python3_Interpreter_FOUND) diff --git a/README.md b/README.md index 63c9a1c4f5..331065363f 100644 --- a/README.md +++ b/README.md @@ -254,6 +254,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 68c24f9ad4..b0897c323c 100644 --- a/cmake/findDependencies.cmake +++ b/cmake/findDependencies.cmake @@ -35,7 +35,9 @@ if (NOT Python3_Interpreter_FOUND) message(WARNING "Python3 was not found. Python tests under the 'tests' folder will not be executed") 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 854323ba05..06b2745a24 100644 --- a/cmake/printSummary.cmake +++ b/cmake/printSummary.cmake @@ -69,4 +69,5 @@ OptionOutput( "Building unit tests: " EXIV2_BUILD_UNIT_TESTS 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 ce16d6a647..66ff8f519b 100644 --- a/meson.build +++ b/meson.build @@ -120,6 +120,7 @@ cdata.set('EXV_HAVE_LIBZ', zlib_dep.found()) cdata.set('EXV_ENABLE_WEBREADY', web_dep.found()) 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 6b99509e91..66e78831dd 100644 --- a/src/basicio.cpp +++ b/src/basicio.cpp @@ -36,6 +36,7 @@ #include #endif +#ifdef EXV_ENABLE_FILESYSTEM #ifdef _WIN32 using mode_t = unsigned short; #include @@ -49,19 +50,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) { @@ -75,6 +64,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: @@ -567,6 +557,7 @@ const std::string& FileIo::path() const noexcept { void FileIo::populateFakeData() { } +#endif //! Internal Pimpl structure of class MemIo. class MemIo::Impl final { @@ -915,7 +906,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()) { } @@ -930,6 +921,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); @@ -1725,7 +1726,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) { @@ -1749,6 +1750,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 2316ee6885..e2adc97353 100644 --- a/src/futils.cpp +++ b/src/futils.cpp @@ -16,6 +16,7 @@ #include #include +#ifdef EXV_ENABLE_FILESYSTEM #if __has_include() #include namespace fs = std::filesystem; @@ -23,6 +24,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 b9752c47e9..f06660cf77 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -116,11 +116,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 @@ -748,9 +750,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) { @@ -783,12 +789,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) { @@ -817,6 +827,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 @@ -831,6 +842,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 0d2e0443f4..0579d2596c 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 @@ -62,6 +64,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 @@ -83,13 +86,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 18fe6122bb..993c3b7496 100644 --- a/src/preview.cpp +++ b/src/preview.cpp @@ -966,12 +966,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 33967b427e..95ce450c7d 100644 --- a/src/tiffcomposite_int.cpp +++ b/src/tiffcomposite_int.cpp @@ -1095,7 +1095,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()); } }