Merge branch 'main' into TestVideoData

main
Mohamed Ali Chebbi 2 years ago committed by Mohamed Ali Chebbi
commit a36e4dd1e8

@ -143,8 +143,17 @@ if (EXIV2_TEAM_PACKAGING)
include(cmake/packaging.cmake)
endif()
join_paths(libdir_for_pc_file "\${prefix}" "${CMAKE_INSTALL_LIBDIR}")
join_paths(includedir_for_pc_file "\${prefix}" "${CMAKE_INSTALL_INCLUDEDIR}")
# Handle both relative and absolute paths (e.g. NixOS) for a relocatable package
if(IS_ABSOLUTE "${CMAKE_INSTALL_LIBDIR}")
set(libdir_for_pc_file "${CMAKE_INSTALL_LIBDIR}")
else()
join_paths(libdir_for_pc_file "\${exec_prefix}" "${CMAKE_INSTALL_LIBDIR}")
endif()
if(IS_ABSOLUTE "${CMAKE_INSTALL_INCLUDEDIR}")
set(includedir_for_pc_file "${CMAKE_INSTALL_INCLUDEDIR}")
else()
join_paths(includedir_for_pc_file "\${prefix}" "${CMAKE_INSTALL_INCLUDEDIR}")
endif()
configure_file(cmake/exiv2.pc.in exiv2.pc @ONLY)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/exiv2.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)

@ -17,17 +17,16 @@
#include "types.hpp"
#include "xmp_exiv2.hpp"
// + standard includes
#include <sys/stat.h> // for stat()
#include <sys/types.h> // for stat()
#include <filesystem>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <mutex>
#include <sstream>
#ifdef EXV_HAVE_UNISTD_H
// + standard includes
#include <sys/stat.h> // for stat()
#include <sys/types.h> // for stat()
#if __has_include(<unistd.h>)
#include <unistd.h> // for stat()
#endif
@ -46,7 +45,13 @@
} while (false)
#endif
#if __has_include(<filesystem>)
#include <filesystem>
namespace fs = std::filesystem;
#else
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#endif
// *****************************************************************************
// local declarations
@ -631,7 +636,7 @@ int Rename::run(const std::string& path) {
return 1;
}
std::string v = md->toString();
if (v.length() == 0 || v[0] == ' ') {
if (v.empty() || v.front() == ' ') {
std::cerr << _("Image file creation timestamp not set in the file") << " " << path << "\n";
return 1;
}
@ -1408,30 +1413,32 @@ int Adjust::adjustDateTime(Exiv2::ExifData& exifData, const std::string& key, co
}
// bounds checking for yearAdjustment_
enforce<std::overflow_error>(yearAdjustment_ >= std::numeric_limits<decltype(tm.tm_year)>::min(),
"year adjustment too low");
enforce<std::overflow_error>(yearAdjustment_ <= std::numeric_limits<decltype(tm.tm_year)>::max(),
"year adjustment too high");
Exiv2::Internal::enforce<std::overflow_error>(yearAdjustment_ >= std::numeric_limits<decltype(tm.tm_year)>::min(),
"year adjustment too low");
Exiv2::Internal::enforce<std::overflow_error>(yearAdjustment_ <= std::numeric_limits<decltype(tm.tm_year)>::max(),
"year adjustment too high");
const auto yearAdjustment = static_cast<decltype(tm.tm_year)>(yearAdjustment_);
// bounds checking for monthAdjustment_
enforce<std::overflow_error>(monthAdjustment_ >= std::numeric_limits<decltype(tm.tm_mon)>::min(),
"month adjustment too low");
enforce<std::overflow_error>(monthAdjustment_ <= std::numeric_limits<decltype(tm.tm_mon)>::max(),
"month adjustment too high");
Exiv2::Internal::enforce<std::overflow_error>(monthAdjustment_ >= std::numeric_limits<decltype(tm.tm_mon)>::min(),
"month adjustment too low");
Exiv2::Internal::enforce<std::overflow_error>(monthAdjustment_ <= std::numeric_limits<decltype(tm.tm_mon)>::max(),
"month adjustment too high");
const auto monthAdjustment = static_cast<decltype(tm.tm_mon)>(monthAdjustment_);
// bounds checking for dayAdjustment_
static constexpr time_t secondsInDay = 24 * 60 * 60;
enforce<std::overflow_error>(dayAdjustment_ >= std::numeric_limits<time_t>::min() / secondsInDay,
"day adjustment too low");
enforce<std::overflow_error>(dayAdjustment_ <= std::numeric_limits<time_t>::max() / secondsInDay,
"day adjustment too high");
Exiv2::Internal::enforce<std::overflow_error>(dayAdjustment_ >= std::numeric_limits<time_t>::min() / secondsInDay,
"day adjustment too low");
Exiv2::Internal::enforce<std::overflow_error>(dayAdjustment_ <= std::numeric_limits<time_t>::max() / secondsInDay,
"day adjustment too high");
const auto dayAdjustment = static_cast<time_t>(dayAdjustment_);
// bounds checking for adjustment_
enforce<std::overflow_error>(adjustment_ >= std::numeric_limits<time_t>::min(), "seconds adjustment too low");
enforce<std::overflow_error>(adjustment_ <= std::numeric_limits<time_t>::max(), "seconds adjustment too high");
Exiv2::Internal::enforce<std::overflow_error>(adjustment_ >= std::numeric_limits<time_t>::min(),
"seconds adjustment too low");
Exiv2::Internal::enforce<std::overflow_error>(adjustment_ <= std::numeric_limits<time_t>::max(),
"seconds adjustment too high");
const auto adjustment = static_cast<time_t>(adjustment_);
const auto monOverflow = Safe::add(tm.tm_mon, monthAdjustment) / 12;
@ -1602,7 +1609,7 @@ int Timestamp::touch(const std::string& path) const {
//! @endcond
int str2Tm(const std::string& timeStr, struct tm* tm) {
if (timeStr.length() == 0 || timeStr[0] == ' ')
if (timeStr.empty() || timeStr.front() == ' ')
return 1;
if (timeStr.length() < 19)
return 2;

@ -41,12 +41,19 @@ constexpr auto emptyYodAdjust_ = std::array{
};
//! List of all command identifiers and corresponding strings
constexpr auto cmdIdAndString = std::array{
std::pair(CmdId::add, "add"),
std::pair(CmdId::set, "set"),
std::pair(CmdId::del, "del"),
std::pair(CmdId::reg, "reg"),
std::pair(CmdId::invalid, "invalidCmd"), // End of list marker
constexpr struct CmdIdAndString {
CmdId cmdId_;
const char* string_;
//! Comparison operator for \em string
bool operator==(const std::string& string) const {
return string == string_;
}
} cmdIdAndString[] = {
{CmdId::add, "add"},
{CmdId::set, "set"},
{CmdId::del, "del"},
{CmdId::reg, "reg"},
{CmdId::invalid, "invalidCmd"}, // End of list marker
};
// Return a command Id for a command string
@ -1433,8 +1440,8 @@ bool parseLine(ModifyCmd& modifyCmd, const std::string& line, int num) {
} // parseLine
CmdId commandId(const std::string& cmdString) {
auto it = std::find_if(cmdIdAndString.begin(), cmdIdAndString.end(), [&](auto cs) { return cs.second == cmdString; });
return it != cmdIdAndString.end() ? it->first : CmdId::invalid;
auto it = Exiv2::find(cmdIdAndString, cmdString);
return it ? it->cmdId_ : CmdId::invalid;
}
std::string parseEscapes(const std::string& input) {

@ -5,9 +5,14 @@
#include <cstdio>
#include <cstring>
#include <filesystem>
#if __has_include(<filesystem>)
#include <filesystem>
namespace fs = std::filesystem;
#else
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#endif
namespace Util {
// https://raw.githubusercontent.com/skeeto/getopt/master/getopt.h

@ -1,132 +0,0 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
# This code is disabled for Visual Studio as explained in README.md
if ( NOT MSVC )
#[=======================================================================[.rst:
FindIconv
---------
This module finds the ``iconv()`` POSIX.1 functions on the system.
These functions might be provided in the regular C library or externally
in the form of an additional library.
The following variables are provided to indicate iconv support:
.. variable:: Iconv_FOUND
Variable indicating if the iconv support was found.
.. variable:: Iconv_INCLUDE_DIRS
The directories containing the iconv headers.
.. variable:: Iconv_LIBRARIES
The iconv libraries to be linked.
.. variable:: Iconv_IS_BUILT_IN
A variable indicating whether iconv support is stemming from the
C library or not. Even if the C library provides `iconv()`, the presence of
an external `libiconv` implementation might lead to this being false.
Additionally, the following :prop_tgt:`IMPORTED` target is being provided:
.. variable:: Iconv::Iconv
Imported target for using iconv.
The following cache variables may also be set:
.. variable:: Iconv_INCLUDE_DIR
The directory containing the iconv headers.
.. variable:: Iconv_LIBRARY
The iconv library (if not implicitly given in the C library).
.. note::
On POSIX platforms, iconv might be part of the C library and the cache
variables ``Iconv_INCLUDE_DIR`` and ``Iconv_LIBRARY`` might be empty.
#]=======================================================================]
if (WIN32)
# If neither C nor CXX are loaded, implicit iconv makes no sense.
set(Iconv_IS_BUILT_IN FALSE)
endif()
# iconv can only be provided in libc on a POSIX system.
# If any cache variable is already set, we'll skip this test.
if(NOT DEFINED Iconv_IS_BUILT_IN)
if(UNIX AND NOT DEFINED Iconv_INCLUDE_DIR AND NOT DEFINED Iconv_LIBRARY)
include(CheckCSourceCompiles)
# We always suppress the message here: Otherwise on supported systems
# not having iconv in their C library (e.g. those using libiconv)
# would always display a confusing "Looking for iconv - not found" message
set(CMAKE_FIND_QUIETLY TRUE)
# The following code will not work, but it's sufficient to see if it compiles.
# Note: libiconv will define the iconv functions as macros, so CheckSymbolExists
# will not yield correct results.
set(Iconv_IMPLICIT_TEST_CODE
"
#include <stddef.h>
#include <iconv.h>
int main() {
char *a, *b;
size_t i, j;
iconv_t ic;
ic = iconv_open(\"to\", \"from\");
iconv(ic, &a, &i, &b, &j);
iconv_close(ic);
}
"
)
if(CMAKE_C_COMPILER_LOADED)
check_c_source_compiles("${Iconv_IMPLICIT_TEST_CODE}" Iconv_IS_BUILT_IN)
else()
check_cxx_source_compiles("${Iconv_IMPLICIT_TEST_CODE}" Iconv_IS_BUILT_IN)
endif()
else()
set(Iconv_IS_BUILT_IN FALSE)
endif()
endif()
if(NOT Iconv_IS_BUILT_IN)
find_path(Iconv_INCLUDE_DIR
NAMES "iconv.h"
DOC "iconv include directory")
set(Iconv_LIBRARY_NAMES "iconv" "libiconv")
else()
set(Iconv_INCLUDE_DIR "" CACHE FILEPATH "iconv include directory")
set(Iconv_LIBRARY_NAMES "c")
endif()
find_library(Iconv_LIBRARY
NAMES ${Iconv_LIBRARY_NAMES}
DOC "iconv library (potentially the C library)")
mark_as_advanced(Iconv_INCLUDE_DIR)
mark_as_advanced(Iconv_LIBRARY)
include(FindPackageHandleStandardArgs)
if(NOT Iconv_IS_BUILT_IN)
find_package_handle_standard_args(Iconv REQUIRED_VARS Iconv_LIBRARY Iconv_INCLUDE_DIR)
else()
find_package_handle_standard_args(Iconv REQUIRED_VARS Iconv_LIBRARY)
endif()
if(Iconv_FOUND)
set(Iconv_INCLUDE_DIRS "${Iconv_INCLUDE_DIR}")
set(Iconv_LIBRARIES "${Iconv_LIBRARY}")
if(NOT TARGET Iconv::Iconv)
add_library(Iconv::Iconv INTERFACE IMPORTED)
endif()
set_property(TARGET Iconv::Iconv PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${Iconv_INCLUDE_DIRS}")
set_property(TARGET Iconv::Iconv PROPERTY INTERFACE_LINK_LIBRARIES "${Iconv_LIBRARIES}")
endif()
endif()

@ -9,9 +9,6 @@
// Define if you require webready support.
#cmakedefine EXV_ENABLE_WEBREADY
// Define if you have the <libintl.h> header file.
#cmakedefine EXV_HAVE_LIBINTL_H
// Define if you want translation of program messages to the user's native language
#cmakedefine EXV_ENABLE_NLS
@ -44,15 +41,6 @@
// Define if you have the munmap function.
#cmakedefine EXV_HAVE_MUNMAP
/* Define if you have the <libproc.h> header file. */
#cmakedefine EXV_HAVE_LIBPROC_H
/* Define if you have the <unistd.h> header file. */
#cmakedefine EXV_HAVE_UNISTD_H
// Define if you have the <sys/mman.h> header file.
#cmakedefine EXV_HAVE_SYS_MMAN_H
// Define if you have the zlib library.
#cmakedefine EXV_HAVE_LIBZ

@ -7,5 +7,7 @@ Name: exiv2
Description: @PROJECT_DESCRIPTION@
Version: @PROJECT_VERSION@
URL: @PACKAGE_URL@
Requires.private: @requires_private_for_pc_file@
Libs: -L${libdir} -lexiv2
Libs.private: @libs_private_for_pc_file@
Cflags: -I${includedir}

@ -152,5 +152,4 @@ EXIV2API Image::UniquePtr newAsfInstance(BasicIo::UniquePtr io, bool create);
//! Check if the file iIo is a Windows Asf Video.
EXIV2API bool isAsfType(BasicIo& iIo, bool advance);
} // namespace Exiv2
} // namespace Exiv2

@ -116,7 +116,10 @@ class EXIV2API MatroskaVideo : public Image {
method to get a temporary reference.
*/
explicit MatroskaVideo(BasicIo::UniquePtr io);
//@}
//! @name NOT Implemented
//@{
//! Copy constructor
MatroskaVideo(const MatroskaVideo&) = delete;
//! Assignment operator
@ -184,6 +187,10 @@ class EXIV2API MatroskaVideo : public Image {
}; // class MatroskaVideo
// *****************************************************************************
// template, inline and free functions
// These could be static private functions on Image subclasses but then
// ImageFactory needs to be made a friend.
/*!
@brief Create a new MatroskaVideo instance and return an auto-pointer to it.
Caller owns the returned object and the auto-pointer ensures that

@ -17,8 +17,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA.
*/
#ifndef QUICKTIMEVIDEO_HPP
#define QUICKTIMEVIDEO_HPP
#ifndef QUICKTIMEVIDEO_HPP_
#define QUICKTIMEVIDEO_HPP_
// *****************************************************************************
#include "exiv2lib_export.h"
@ -37,7 +37,7 @@ namespace Exiv2 {
/*!
@brief Class to access QuickTime video files.
*/
class QuickTimeVideo : public Image {
class EXIV2API QuickTimeVideo : public Image {
public:
//! @name Creators
//@{
@ -52,7 +52,7 @@ class QuickTimeVideo : public Image {
instance after it is passed to this method. Use the Image::io()
method to get a temporary reference.
*/
QuickTimeVideo(BasicIo::UniquePtr io);
explicit QuickTimeVideo(BasicIo::UniquePtr io);
//@}
//! @name NOT Implemented
@ -71,7 +71,7 @@ class QuickTimeVideo : public Image {
//! @name Accessors
//@{
std::string mimeType() const override;
[[nodiscard]] std::string mimeType() const override;
//@}
protected:
@ -227,11 +227,11 @@ class QuickTimeVideo : public Image {
Caller owns the returned object and the auto-pointer ensures that
it will be deleted.
*/
Image::UniquePtr newQTimeInstance(BasicIo::UniquePtr io, bool create);
EXIV2API Image::UniquePtr newQTimeInstance(BasicIo::UniquePtr io, bool create);
//! Check if the file iIo is a Quick Time Video.
bool isQTimeType(BasicIo& iIo, bool advance);
EXIV2API bool isQTimeType(BasicIo& iIo, bool advance);
} // namespace Exiv2
#endif // QUICKTIMEVIDEO_HPP
#endif // QUICKTIMEVIDEO_HPP_

@ -42,7 +42,6 @@ class EXIV2API RiffVideo : public Image {
//! @name Manipulators
//@{
void printStructure(std::ostream& out, PrintStructureOption option, size_t depth) override;
void readMetadata() override;
void writeMetadata() override;
//@}

@ -488,7 +488,7 @@ template <typename T>
T stringTo(const std::string& s, bool& ok) {
std::istringstream is(s);
T tmp = T();
ok = bool(is >> tmp);
ok = static_cast<bool>(is >> tmp);
std::string rest;
is >> std::skipws >> rest;
if (!rest.empty())

@ -60,7 +60,7 @@ class EXIV2API Xmpdatum : public Metadatum {
@brief Assign a boolean \em value to the %Xmpdatum.
Translates the value to a string "true" or "false".
*/
Xmpdatum& operator=(bool value);
inline Xmpdatum& operator=(bool value);
/*!
@brief Assign a \em value of any type with an output operator
to the %Xmpdatum. Calls operator=(const std::string&).
@ -398,7 +398,7 @@ class EXIV2API XmpParser {
// *****************************************************************************
// free functions, template and inline definitions
inline Xmpdatum& Xmpdatum::operator=(bool value) {
Xmpdatum& Xmpdatum::operator=(bool value) {
return operator=(value ? "True" : "False");
}

@ -26,7 +26,7 @@
// getopt.{cpp|hpp} is not part of libexiv2
#include "getopt.hpp"
#ifdef EXV_HAVE_UNISTD_H
#if __has_include(<unistd.h>)
#include <unistd.h>
#endif
#include <iostream>
@ -79,7 +79,7 @@ int main(int argc, char** const argv) {
int n;
#ifdef EXV_HAVE_UNISTD_H
#if __has_include(<unistd.h>)
std::cout << "standard getopt()" << std::endl;
do {
n = ::getopt(argc, argv, ::optstring);

@ -2,11 +2,16 @@
#include <exiv2/exiv2.hpp>
#include <filesystem>
#include <fstream>
#include <iostream>
#if __has_include(<filesystem>)
#include <filesystem>
namespace fs = std::filesystem;
#else
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#endif
int main(int argc, char* const argv[]) {
Exiv2::XmpParser::initialize();

@ -46,23 +46,23 @@ void mini1(const char* path) {
// Write nothing to a new structure, without a previous binary image
wm = ExifParser::encode(blob, nullptr, 0, bigEndian, exifData);
enforce(wm == wmIntrusive, Exiv2::ErrorCode::kerErrorMessage, "encode returned an unexpected value");
Internal::enforce(wm == wmIntrusive, Exiv2::ErrorCode::kerErrorMessage, "encode returned an unexpected value");
std::cout << "Test 1: Writing empty Exif data without original binary data: ok.\n";
// Write nothing, this time with a previous binary image
DataBuf buf = readFile(path);
wm = ExifParser::encode(blob, buf.c_data(), buf.size(), bigEndian, exifData);
enforce(wm == wmIntrusive, Exiv2::ErrorCode::kerErrorMessage, "encode returned an unexpected value");
Internal::enforce(wm == wmIntrusive, Exiv2::ErrorCode::kerErrorMessage, "encode returned an unexpected value");
std::cout << "Test 2: Writing empty Exif data with original binary data: ok.\n";
// Write something to a new structure, without a previous binary image
exifData["Exif.Photo.DateTimeOriginal"] = "Yesterday at noon";
wm = ExifParser::encode(blob, nullptr, 0, bigEndian, exifData);
enforce(wm == wmIntrusive, Exiv2::ErrorCode::kerErrorMessage, "encode returned an unexpected value");
Internal::enforce(wm == wmIntrusive, Exiv2::ErrorCode::kerErrorMessage, "encode returned an unexpected value");
std::cout << "Test 3: Wrote non-empty Exif data without original binary data:\n";
exifData.clear();
ByteOrder bo = ExifParser::decode(exifData, blob.data(), blob.size());
enforce(bo == bigEndian, Exiv2::ErrorCode::kerErrorMessage, "decode returned an unexpected value");
Internal::enforce(bo == bigEndian, Exiv2::ErrorCode::kerErrorMessage, "decode returned an unexpected value");
print(exifData);
}

@ -158,11 +158,6 @@ endif()
# Other library target properties
# ---------------------------------------------------------
if (${CMAKE_CXX_COMPILER_ID} STREQUAL GNU)
# Do not check format overflows on this file, to skip a false positive warning
set_source_files_properties(value.cpp PROPERTIES COMPILE_FLAGS -Wno-format-overflow)
endif()
set_target_properties( exiv2lib PROPERTIES
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MINOR}
@ -189,10 +184,12 @@ target_include_directories(exiv2lib SYSTEM PRIVATE
if (EXIV2_ENABLE_XMP OR EXIV2_ENABLE_EXTERNAL_XMP)
target_include_directories(exiv2lib PRIVATE ${EXPAT_INCLUDE_DIR})
target_link_libraries(exiv2lib PRIVATE EXPAT::EXPAT)
list(APPEND requires_private_list "expat")
endif()
if (EXIV2_ENABLE_XMP)
target_link_libraries(exiv2lib PRIVATE exiv2-xmp)
list(APPEND libs_private_list "exiv2-xmp")
elseif(EXIV2_ENABLE_EXTERNAL_XMP)
target_link_libraries(exiv2lib PUBLIC ${XMPSDK_LIBRARY})
target_include_directories(exiv2lib PUBLIC ${XMPSDK_INCLUDE_DIR})
@ -211,12 +208,11 @@ target_include_directories(exiv2lib_int PUBLIC
)
if (EXIV2_ENABLE_WEBREADY)
if( EXIV2_ENABLE_CURL )
target_include_directories(exiv2lib SYSTEM PRIVATE ${CURL_INCLUDE_DIR} )
target_link_libraries(exiv2lib PRIVATE ${CURL_LIBRARIES})
list(APPEND requires_private_list "libcurl")
endif()
endif()
if (WIN32)
@ -239,25 +235,31 @@ else()
endif()
if( EXIV2_ENABLE_PNG )
target_link_libraries( exiv2lib PRIVATE ZLIB::ZLIB)
target_link_libraries( exiv2lib PRIVATE ZLIB::ZLIB)
list(APPEND requires_private_list "zlib")
endif()
if( EXIV2_ENABLE_BMFF AND BROTLI_FOUND )
target_link_libraries( exiv2lib PRIVATE ${Brotli_LIBRARIES})
target_include_directories(exiv2lib PRIVATE ${Brotli_INCLUDE_DIRS})
list(APPEND requires_private_list "libbrotlidec")
endif()
if( EXIV2_ENABLE_NLS )
target_link_libraries(exiv2lib PRIVATE ${Intl_LIBRARIES})
target_include_directories(exiv2lib PRIVATE ${Intl_INCLUDE_DIRS})
target_include_directories(exiv2lib_int PRIVATE ${Intl_INCLUDE_DIRS})
if( Intl_LIBRARIES )
list(APPEND libs_private_list "intl")
endif()
# Definition needed for translations
join_paths(EXV_LOCALEDIR ".." "${CMAKE_INSTALL_LOCALEDIR}")
target_compile_definitions(exiv2lib PUBLIC EXV_LOCALEDIR="${EXV_LOCALEDIR}")
endif()
if( ICONV_FOUND )
if( Iconv_FOUND AND Iconv_LIBRARIES )
target_link_libraries( exiv2lib PRIVATE Iconv::Iconv )
list(APPEND libs_private_list "iconv")
endif()
if( EXIV2_ENABLE_INIH )
@ -265,7 +267,20 @@ if( EXIV2_ENABLE_INIH )
target_link_libraries( exiv2lib_int PRIVATE inih::inireader )
target_link_libraries( exiv2lib PRIVATE inih::libinih )
target_link_libraries( exiv2lib PRIVATE inih::inireader )
list(APPEND requires_private_list "INIReader")
endif()
# Convert private lists to delimited strings
list(SORT libs_private_list)
string(REPLACE ";" " -l" libs_private_string "${libs_private_list}")
if(libs_private_string)
string(PREPEND libs_private_string "-l")
endif()
list(SORT requires_private_list)
string(REPLACE ";" ", " requires_private_string "${requires_private_list}")
set(libs_private_for_pc_file "${libs_private_string}" PARENT_SCOPE)
set(requires_private_for_pc_file "${requires_private_string}" PARENT_SCOPE)
write_basic_package_version_file(exiv2ConfigVersion.cmake COMPATIBILITY ExactVersion)

@ -118,6 +118,7 @@ const std::map<std::string, std::string> GUIDReferenceTags = {
parsed into a character array GUID.
https://fr.wikipedia.org/wiki/Globally_unique_identifier
*/
std::string getGUID(DataBuf& buf) {
std::string GUID(36, '-');
if (buf.size() >= 16) {

@ -11,26 +11,25 @@
#include "image_int.hpp"
#include "types.hpp"
// + standard includes
#include <fcntl.h> // _O_BINARY in FileIo::FileIo
#include <sys/stat.h> // for stat, chmod
#include <cstdio> // for remove, rename
#include <cstdlib> // for alloc, realloc, free
#include <cstring> // std::memcpy
#include <ctime> // timestamp for the name of temporary file
#include <filesystem>
#include <fstream> // write the temporary file
#include <iostream>
#ifdef EXV_HAVE_SYS_MMAN_H
// + standard includes
#include <fcntl.h> // _O_BINARY in FileIo::FileIo
#include <sys/stat.h> // for stat, chmod
#if __has_include(<sys/mman.h>)
#include <sys/mman.h> // for mmap and munmap
#endif
#ifdef EXV_HAVE_PROCESS_H
#if __has_include(<process.h>)
#include <process.h>
#endif
#ifdef EXV_HAVE_UNISTD_H
#include <unistd.h> // for getpid, stat
#if __has_include(<unistd.h>)
#include <unistd.h>
#endif
#ifdef EXV_USE_CURL
@ -43,7 +42,13 @@
#include <windows.h>
#endif
#if __has_include(<filesystem>)
#include <filesystem>
namespace fs = std::filesystem;
#else
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#endif
// *****************************************************************************
// class member definitions
@ -61,13 +66,13 @@ void ReplaceStringInPlace(std::string& subject, std::string_view search, std::st
namespace Exiv2 {
void BasicIo::readOrThrow(byte* buf, size_t rcount, ErrorCode err) {
const size_t nread = read(buf, rcount);
enforce(nread == rcount, err);
enforce(!error(), err);
Internal::enforce(nread == rcount, err);
Internal::enforce(!error(), err);
}
void BasicIo::seekOrThrow(int64_t offset, Position pos, ErrorCode err) {
const int r = seek(offset, pos);
enforce(r == 0, err);
Internal::enforce(r == 0, err);
}
//! Internal Pimpl structure of class FileIo.
@ -465,7 +470,7 @@ int FileIo::seek(int64_t offset, Position pos) {
size_t FileIo::tell() const {
const long pos = std::ftell(p_->fp_);
enforce(pos >= 0, ErrorCode::kerInputDataReadFailed);
Internal::enforce(pos >= 0, ErrorCode::kerInputDataReadFailed);
return static_cast<size_t>(pos);
}

@ -249,7 +249,7 @@ uint64_t BmffImage::boxHandler(std::ostream& out /* = std::cout*/, Exiv2::PrintS
byte hdrbuf[2 * sizeof(uint32_t)];
size_t hdrsize = sizeof(hdrbuf);
enforce(hdrsize <= static_cast<size_t>(pbox_end - address), Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(hdrsize <= static_cast<size_t>(pbox_end - address), Exiv2::ErrorCode::kerCorruptedMetadata);
if (io_->read(reinterpret_cast<byte*>(&hdrbuf), sizeof(hdrbuf)) != sizeof(hdrbuf))
return pbox_end;
@ -268,7 +268,7 @@ uint64_t BmffImage::boxHandler(std::ostream& out /* = std::cout*/, Exiv2::PrintS
if (box_length == 1) {
// The box size is encoded as a uint64_t, so we need to read another 8 bytes.
hdrsize += 8;
enforce(hdrsize <= static_cast<size_t>(pbox_end - address), Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(hdrsize <= static_cast<size_t>(pbox_end - address), Exiv2::ErrorCode::kerCorruptedMetadata);
DataBuf data(8);
io_->read(data.data(), data.size());
box_length = data.read_uint64(0, endian_);
@ -276,8 +276,8 @@ uint64_t BmffImage::boxHandler(std::ostream& out /* = std::cout*/, Exiv2::PrintS
// read data in box and restore file position
const size_t restore = io_->tell();
enforce(box_length >= hdrsize, Exiv2::ErrorCode::kerCorruptedMetadata);
enforce(box_length - hdrsize <= pbox_end - restore, Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(box_length >= hdrsize, Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(box_length - hdrsize <= pbox_end - restore, Exiv2::ErrorCode::kerCorruptedMetadata);
const auto buffer_size = box_length - hdrsize;
if (skipBox(box_type)) {
@ -299,7 +299,7 @@ uint64_t BmffImage::boxHandler(std::ostream& out /* = std::cout*/, Exiv2::PrintS
uint32_t flags = 0;
if (fullBox(box_type)) {
enforce(data.size() - skip >= 4, Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(data.size() - skip >= 4, Exiv2::ErrorCode::kerCorruptedMetadata);
flags = data.read_uint32(skip, endian_); // version/flags
version = static_cast<uint8_t>(flags >> 24);
flags &= 0x00ffffff;
@ -309,7 +309,7 @@ uint64_t BmffImage::boxHandler(std::ostream& out /* = std::cout*/, Exiv2::PrintS
switch (box_type) {
// See notes in skipBox()
case TAG_ftyp: {
enforce(data.size() >= 4, Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(data.size() >= 4, Exiv2::ErrorCode::kerCorruptedMetadata);
fileType_ = data.read_uint32(0, endian_);
if (bTrace) {
out << "brand: " << toAscii(fileType_);
@ -323,7 +323,7 @@ uint64_t BmffImage::boxHandler(std::ostream& out /* = std::cout*/, Exiv2::PrintS
bLF = false;
}
enforce(data.size() - skip >= 2, Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(data.size() - skip >= 2, Exiv2::ErrorCode::kerCorruptedMetadata);
uint16_t n = data.read_uint16(skip, endian_);
skip += 2;
@ -335,7 +335,7 @@ uint64_t BmffImage::boxHandler(std::ostream& out /* = std::cout*/, Exiv2::PrintS
// 8.11.6.2
case TAG_infe: { // .__._.__hvc1_ 2 0 0 1 0 1 0 0 104 118 99 49 0
enforce(data.size() - skip >= 8, Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(data.size() - skip >= 8, Exiv2::ErrorCode::kerCorruptedMetadata);
/* getULong (data.pData_+skip,endian_) ; */ skip += 4;
uint16_t ID = data.read_uint16(skip, endian_);
skip += 2;
@ -344,7 +344,7 @@ uint64_t BmffImage::boxHandler(std::ostream& out /* = std::cout*/, Exiv2::PrintS
// Check that the string has a '\0' terminator.
const char* str = data.c_str(skip);
const size_t maxlen = data.size() - skip;
enforce(maxlen > 0 && strnlen(str, maxlen) < maxlen, Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(maxlen > 0 && strnlen(str, maxlen) < maxlen, Exiv2::ErrorCode::kerCorruptedMetadata);
std::string name(str);
if (name.find("Exif") != std::string::npos) { // "Exif" or "ExifExif"
exifID_ = ID;
@ -393,7 +393,7 @@ uint64_t BmffImage::boxHandler(std::ostream& out /* = std::cout*/, Exiv2::PrintS
// 8.11.3.1
case TAG_iloc: {
enforce(data.size() - skip >= 2, Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(data.size() - skip >= 2, Exiv2::ErrorCode::kerCorruptedMetadata);
uint8_t u = data.read_uint8(skip++);
uint16_t offsetSize = u >> 4;
uint16_t lengthSize = u & 0xF;
@ -406,7 +406,7 @@ uint64_t BmffImage::boxHandler(std::ostream& out /* = std::cout*/, Exiv2::PrintS
#else
skip++;
#endif
enforce(data.size() - skip >= (version < 2u ? 2u : 4u), Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(data.size() - skip >= (version < 2u ? 2u : 4u), Exiv2::ErrorCode::kerCorruptedMetadata);
uint32_t itemCount = version < 2 ? data.read_uint16(skip, endian_) : data.read_uint32(skip, endian_);
skip += version < 2 ? 2 : 4;
if (itemCount && itemCount < box_length / 14 && offsetSize == 4 && lengthSize == 4 &&
@ -419,10 +419,10 @@ uint64_t BmffImage::boxHandler(std::ostream& out /* = std::cout*/, Exiv2::PrintS
size_t base = skip;
for (uint32_t i = 0; i < itemCount; i++) {
skip = base + i * step; // move in 14, 16 or 18 byte steps
enforce(data.size() - skip >= (version > 2u ? 4u : 2u), Exiv2::ErrorCode::kerCorruptedMetadata);
enforce(data.size() - skip >= step, Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(data.size() - skip >= (version > 2u ? 4u : 2u), Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(data.size() - skip >= step, Exiv2::ErrorCode::kerCorruptedMetadata);
uint32_t ID = version > 2 ? data.read_uint32(skip, endian_) : data.read_uint16(skip, endian_);
auto offset = [=] {
auto offset = [this, &data, skip, step] {
if (step == 14 || step == 16)
return data.read_uint32(skip + step - 8, endian_);
if (step == 18)
@ -445,7 +445,7 @@ uint64_t BmffImage::boxHandler(std::ostream& out /* = std::cout*/, Exiv2::PrintS
} break;
case TAG_ispe: {
enforce(data.size() - skip >= 12, Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(data.size() - skip >= 12, Exiv2::ErrorCode::kerCorruptedMetadata);
skip += 4;
uint32_t width = data.read_uint32(skip, endian_);
skip += 4;
@ -524,7 +524,7 @@ uint64_t BmffImage::boxHandler(std::ostream& out /* = std::cout*/, Exiv2::PrintS
parseXmp(buffer_size, io_->tell());
break;
case TAG_brob: {
enforce(data.size() >= 4, Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(data.size() >= 4, Exiv2::ErrorCode::kerCorruptedMetadata);
uint32_t realType = data.read_uint32(0, endian_);
if (bTrace) {
out << "type: " << toAscii(realType);
@ -534,7 +534,7 @@ uint64_t BmffImage::boxHandler(std::ostream& out /* = std::cout*/, Exiv2::PrintS
brotliUncompress(data.c_data(4), data.size() - 4, arr);
if (realType == TAG_exif) {
uint32_t offset = Safe::add(arr.read_uint32(0, endian_), 4u);
enforce(Safe::add(offset, 4u) < arr.size(), Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(Safe::add(offset, 4u) < arr.size(), Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::TiffParserWorker::decode(exifData(), iptcData(), xmpData(), arr.c_data(offset), arr.size() - offset,
Internal::Tag::root, Internal::TiffMapping::findDecoder);
} else if (realType == TAG_xml) {
@ -580,10 +580,11 @@ uint64_t BmffImage::boxHandler(std::ostream& out /* = std::cout*/, Exiv2::PrintS
}
void BmffImage::parseTiff(uint32_t root_tag, uint64_t length, uint64_t start) {
enforce(start <= io_->size(), ErrorCode::kerCorruptedMetadata);
enforce(length <= io_->size() - start, ErrorCode::kerCorruptedMetadata);
enforce(start <= static_cast<uint64_t>(std::numeric_limits<int64_t>::max()), ErrorCode::kerCorruptedMetadata);
enforce(length <= std::numeric_limits<size_t>::max(), ErrorCode::kerCorruptedMetadata);
Internal::enforce(start <= io_->size(), ErrorCode::kerCorruptedMetadata);
Internal::enforce(length <= io_->size() - start, ErrorCode::kerCorruptedMetadata);
Internal::enforce(start <= static_cast<uint64_t>(std::numeric_limits<int64_t>::max()),
ErrorCode::kerCorruptedMetadata);
Internal::enforce(length <= std::numeric_limits<size_t>::max(), ErrorCode::kerCorruptedMetadata);
// read and parse exif data
const size_t restore = io_->tell();
@ -608,8 +609,8 @@ void BmffImage::parseTiff(uint32_t root_tag, uint64_t length, uint64_t start) {
void BmffImage::parseTiff(uint32_t root_tag, uint64_t length) {
if (length > 8) {
enforce(length - 8 <= io_->size() - io_->tell(), ErrorCode::kerCorruptedMetadata);
enforce(length - 8 <= std::numeric_limits<size_t>::max(), ErrorCode::kerCorruptedMetadata);
Internal::enforce(length - 8 <= io_->size() - io_->tell(), ErrorCode::kerCorruptedMetadata);
Internal::enforce(length - 8 <= std::numeric_limits<size_t>::max(), ErrorCode::kerCorruptedMetadata);
DataBuf data(static_cast<size_t>(length - 8u));
const size_t bufRead = io_->read(data.data(), data.size());
@ -624,8 +625,8 @@ void BmffImage::parseTiff(uint32_t root_tag, uint64_t length) {
}
void BmffImage::parseXmp(uint64_t length, uint64_t start) {
enforce(start <= io_->size(), ErrorCode::kerCorruptedMetadata);
enforce(length <= io_->size() - start, ErrorCode::kerCorruptedMetadata);
Internal::enforce(start <= io_->size(), ErrorCode::kerCorruptedMetadata);
Internal::enforce(length <= io_->size() - start, ErrorCode::kerCorruptedMetadata);
const size_t restore = io_->tell();
io_->seek(static_cast<int64_t>(start), BasicIo::beg);
@ -651,7 +652,7 @@ void BmffImage::parseCr3Preview(DataBuf& data, std::ostream& out, bool bTrace, u
size_t height_offset, size_t size_offset, size_t relative_position) {
// Derived from https://github.com/lclevy/canon_cr3
const size_t here = io_->tell();
enforce(here <= std::numeric_limits<size_t>::max() - relative_position, ErrorCode::kerCorruptedMetadata);
Internal::enforce(here <= std::numeric_limits<size_t>::max() - relative_position, ErrorCode::kerCorruptedMetadata);
NativePreview nativePreview;
nativePreview.position_ = here + relative_position;
nativePreview.width_ = data.read_uint16(width_offset, endian_);

@ -740,7 +740,7 @@ void Converter::cnvExifDate(const char* from, const char* to) {
}
if (subsec.size() > 10)
subsec = subsec.substr(0, 10);
subsec.resize(10);
snprintf(buf, sizeof(buf), "%4d-%02d-%02dT%02d:%02d:%02d%s", year, month, day, hour, min, sec, subsec.c_str());
buf[sizeof(buf) - 1] = 0;
@ -1141,7 +1141,7 @@ void Converter::cnvXmpGPSCoord(const char* from, const char* to) {
double deg = 0.0;
double min = 0.0;
double sec = 0.0;
char ref = value[value.length() - 1];
char ref = value.back();
char sep1 = '\0';
char sep2 = '\0';
@ -1553,8 +1553,8 @@ const ConvFctList convFctList[] = {
[[maybe_unused]] bool convertStringCharsetWindows(std::string& str, const char* from, const char* to) {
bool ret = false;
const ConvFctList* p = find(convFctList, std::pair(from, to));
std::string tmpstr = str;
auto p = Exiv2::find(convFctList, std::pair(from, to));
if (p)
ret = p->convFct_(tmpstr);
#ifndef SUPPRESS_WARNINGS

@ -22,6 +22,7 @@
#include "error.hpp"
namespace Exiv2::Internal {
/*!
* @brief Ensure that condition is true, otherwise throw an exception of the
* type exception_t
@ -81,3 +82,4 @@ inline void enforce(bool condition, Exiv2::ErrorCode err_code, const T& arg1, co
throw Exiv2::Error(err_code, arg1, arg2, arg3);
}
}
} // namespace Exiv2::Internal

@ -36,7 +36,7 @@ using namespace Exiv2::Internal;
constexpr auto dosEpsSignature = std::string_view("\xC5\xD0\xD3\xC6");
// first line of EPS
constexpr auto epsFirstLine = std::array<std::string_view, 3>{
constexpr std::string_view epsFirstLine[] = {
"%!PS-Adobe-3.0 EPSF-3.0",
"%!PS-Adobe-3.0 EPSF-3.0 ", // OpenOffice
"%!PS-Adobe-3.1 EPSF-3.0", // Illustrator
@ -317,7 +317,7 @@ void readWriteEpsMetadata(BasicIo& io, std::string& xmpPacket, NativePreviewList
#ifdef DEBUG
EXV_DEBUG << "readWriteEpsMetadata: First line: " << firstLine << "\n";
#endif
bool matched = std::find(epsFirstLine.begin(), epsFirstLine.end(), firstLine) != epsFirstLine.end();
auto matched = Exiv2::find(epsFirstLine, firstLine);
if (!matched) {
throw Error(ErrorCode::kerNotAnImage, "EPS");
}

@ -241,7 +241,7 @@ std::ostream& printFujiDriveSetting(std::ostream& os, const Value& value, const
auto byte3 = (value.toInt64() >> 16) & 0xff;
auto fps = value.toInt64() >> 24;
auto setting = find(fujiDriveSettingByte1, byte1);
auto setting = Exiv2::find(fujiDriveSettingByte1, byte1);
if (setting) {
os << exvGettext(setting->label_);
} else {
@ -347,7 +347,7 @@ std::ostream& printFujiFaceElementTypes(std::ostream& os, const Value& value, co
longValue -= '0';
}
auto td = find(fujiFaceElementType, longValue);
auto td = Exiv2::find(fujiFaceElementType, longValue);
if (n != 0) {
os << " ";
}

@ -12,15 +12,16 @@
#include <algorithm>
#include <array>
#include <cstring>
#include <filesystem>
#include <sstream>
#include <stdexcept>
#ifdef EXV_HAVE_UNISTD_H
#include <unistd.h> // for stat()
#endif
#if __has_include(<filesystem>)
#include <filesystem>
namespace fs = std::filesystem;
#else
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#endif
#if defined(_WIN32)
// clang-format off
@ -29,10 +30,14 @@ namespace fs = std::filesystem;
// clang-format on
#endif
#if defined(__APPLE__) && defined(EXV_HAVE_LIBPROC_H)
#if __has_include(<libproc.h>)
#include <libproc.h>
#endif
#if __has_include(<unistd.h>)
#include <unistd.h> // for stat()
#endif
#if defined(__FreeBSD__)
#include <libprocstat.h>
#include <sys/mount.h>
@ -42,7 +47,6 @@ namespace fs = std::filesystem;
#include <sys/sysctl.h>
#include <sys/types.h>
#include <sys/un.h>
#include <unistd.h>
#endif
#ifndef _MAX_PATH
@ -195,7 +199,7 @@ size_t base64decode(const char* in, char* out, size_t out_size) {
Protocol fileProtocol(const std::string& path) {
Protocol result = pFile;
struct {
const struct {
std::string name;
Protocol prot;
bool isUrl; // path.size() > name.size()
@ -234,7 +238,7 @@ std::string strError() {
#else
char buf[n] = {};
const int ret = strerror_r(error, buf, n);
enforce(ret != ERANGE, Exiv2::ErrorCode::kerCallFailed);
Internal::enforce(ret != ERANGE, Exiv2::ErrorCode::kerCallFailed);
#endif
os << buf;
// Issue# 908.
@ -342,14 +346,12 @@ std::string getProcessPath() {
}
CloseHandle(processHandle);
}
#elif defined(__APPLE__)
#ifdef EXV_HAVE_LIBPROC_H
#elif __has_include(<libproc.h>)
const int pid = getpid();
char pathbuf[PROC_PIDPATHINFO_MAXSIZE];
if (proc_pidpath(pid, pathbuf, sizeof(pathbuf)) > 0) {
ret = pathbuf;
}
#endif
#elif defined(__FreeBSD__)
unsigned int n;
char buffer[PATH_MAX] = {};
@ -374,7 +376,7 @@ std::string getProcessPath() {
ret = path;
}
#elif defined(__unix__)
ret = std::filesystem::read_symlink("/proc/self/exe");
ret = fs::read_symlink("/proc/self/exe");
#endif
const size_t idxLastSeparator = ret.find_last_of(EXV_SEPARATOR_CHR);

@ -38,31 +38,31 @@ std::string toString16(Exiv2::DataBuf& buf) {
}
uint64_t readQWORDTag(BasicIo::UniquePtr& io) {
enforce(QWORD <= io->size() - io->tell(), Exiv2::ErrorCode::kerCorruptedMetadata);
DataBuf FieldBuf = io->read(QWORD);
Internal::enforce(QWORD <= io->size() - io->tell(), Exiv2::ErrorCode::kerCorruptedMetadata);
DataBuf FieldBuf = io->read(QWORD);
return FieldBuf.read_uint64(0, littleEndian);
}
uint32_t readDWORDTag(BasicIo::UniquePtr& io) {
enforce(DWORD <= io->size() - io->tell(), Exiv2::ErrorCode::kerCorruptedMetadata);
DataBuf FieldBuf = io->read(DWORD);
Internal::enforce(DWORD <= io->size() - io->tell(), Exiv2::ErrorCode::kerCorruptedMetadata);
DataBuf FieldBuf = io->read(DWORD);
return FieldBuf.read_uint32(0, littleEndian);
}
uint16_t readWORDTag(BasicIo::UniquePtr& io) {
enforce(WORD <= io->size() - io->tell(), Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(WORD <= io->size() - io->tell(), Exiv2::ErrorCode::kerCorruptedMetadata);
DataBuf FieldBuf = io->read(WORD);
return FieldBuf.read_uint16(0, littleEndian);
}
std::string readStringWcharTag(BasicIo::UniquePtr& io, uint16_t length) {
enforce(length <= io->size() - io->tell(), Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(length <= io->size() - io->tell(), Exiv2::ErrorCode::kerCorruptedMetadata);
DataBuf FieldBuf = io->read(length);
return toString16(FieldBuf);
}
std::string readStringTag(BasicIo::UniquePtr& io, uint16_t length) {
enforce(length <= io->size() - io->tell(), Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(length <= io->size() - io->tell(), Exiv2::ErrorCode::kerCorruptedMetadata);
DataBuf FieldBuf = io->read(length);
return Exiv2::toString(FieldBuf.data());
}

@ -131,13 +131,13 @@ static int makeNonBlocking(int sockfd) {
}
int Exiv2::http(Exiv2::Dictionary& request, Exiv2::Dictionary& response, std::string& errors) {
if (!request.count("verb"))
if (request.find("verb") == request.end())
request["verb"] = "GET";
if (!request.count("header"))
if (request.find("header") == request.end())
request["header"] = "";
if (!request.count("version"))
if (request.find("version") == request.end())
request["version"] = "1.0";
if (!request.count("port"))
if (request.find("port") == request.end())
request["port"] = "";
std::string file;
@ -305,8 +305,8 @@ int Exiv2::http(Exiv2::Dictionary& request, Exiv2::Dictionary& response, std::st
while (c && first_newline && c < first_newline && h < buffer + body) {
std::string key(h);
std::string value(c + 1);
key = key.substr(0, c - h);
value = value.substr(0, first_newline - c - 1);
key.resize(c - h);
value.resize(first_newline - c - 1);
response[key] = value;
h = first_newline + 1;
c = strchr(h, C);

@ -308,7 +308,7 @@ void Image::printIFDStructure(BasicIo& io, std::ostream& out, Exiv2::PrintStruct
io.readOrThrow(dir.data(), 2, ErrorCode::kerCorruptedMetadata);
uint16_t dirLength = byteSwap2(dir, 0, bSwap);
// Prevent infinite loops. (GHSA-m479-7frc-gqqg)
enforce(dirLength > 0, ErrorCode::kerCorruptedMetadata);
Internal::enforce(dirLength > 0, ErrorCode::kerCorruptedMetadata);
if (dirLength > 500) // tooBig
throw Error(ErrorCode::kerTiffDirectoryTooLarge);
@ -384,7 +384,7 @@ void Image::printIFDStructure(BasicIo& io, std::ostream& out, Exiv2::PrintStruct
throw Error(ErrorCode::kerInvalidMalloc);
}
// Overflow check
enforce(allocate64 <= std::numeric_limits<size_t>::max(), ErrorCode::kerCorruptedMetadata);
Internal::enforce(allocate64 <= std::numeric_limits<size_t>::max(), ErrorCode::kerCorruptedMetadata);
DataBuf buf(allocate64); // allocate a buffer
std::copy_n(dir.c_data(8), 4, buf.begin()); // copy dir[8:11] into buffer (short strings)

@ -12,7 +12,9 @@
#include <ostream> // for ostream, basic_ostream::put
#include <string>
#if (defined(__GNUG__) || defined(__GNUC__)) || defined(__clang__)
#if defined(__MINGW32__)
#define ATTRIBUTE_FORMAT_PRINTF __attribute__((format(__MINGW_PRINTF_FORMAT, 1, 0)))
#elif defined(__GNUC__)
#define ATTRIBUTE_FORMAT_PRINTF __attribute__((format(printf, 1, 0)))
#else
#define ATTRIBUTE_FORMAT_PRINTF

@ -290,12 +290,12 @@ void IptcData::printStructure(std::ostream& out, const Slice<byte*>& bytes, size
char buff[100];
uint16_t record = bytes.at(i + 1);
uint16_t dataset = bytes.at(i + 2);
enforce(bytes.size() - i >= 5, ErrorCode::kerCorruptedMetadata);
Internal::enforce(bytes.size() - i >= 5, ErrorCode::kerCorruptedMetadata);
uint16_t len = getUShort(bytes.subSlice(i + 3, bytes.size()), bigEndian);
snprintf(buff, sizeof(buff), " %6d | %7d | %-24s | %6d | ", record, dataset,
Exiv2::IptcDataSets::dataSetName(dataset, record).c_str(), len);
enforce(bytes.size() - i >= 5 + static_cast<size_t>(len), ErrorCode::kerCorruptedMetadata);
Internal::enforce(bytes.size() - i >= 5 + static_cast<size_t>(len), ErrorCode::kerCorruptedMetadata);
out << buff << Internal::binaryToString(makeSlice(bytes, i + 5, i + 5 + (len > 40 ? 40 : len)))
<< (len > 40 ? "..." : "") << std::endl;
i += 5 + len;

@ -157,7 +157,7 @@ void Jp2Image::readMetadata() {
<< "Position: " << position << " box type: " << toAscii(box.type) << " length: " << box.length
<< std::endl;
#endif
enforce(box.length <= boxHSize + io_->size() - io_->tell(), ErrorCode::kerCorruptedMetadata);
Internal::enforce(box.length <= boxHSize + io_->size() - io_->tell(), ErrorCode::kerCorruptedMetadata);
if (box.length == 0)
return;
@ -245,7 +245,7 @@ void Jp2Image::readMetadata() {
ihdr.imageHeight = getULong(reinterpret_cast<byte*>(&ihdr.imageHeight), bigEndian);
ihdr.imageWidth = getULong(reinterpret_cast<byte*>(&ihdr.imageWidth), bigEndian);
ihdr.componentCount = getShort(reinterpret_cast<byte*>(&ihdr.componentCount), bigEndian);
enforce(ihdr.c == 7, ErrorCode::kerCorruptedMetadata);
Internal::enforce(ihdr.c == 7, ErrorCode::kerCorruptedMetadata);
pixelWidth_ = ihdr.imageWidth;
pixelHeight_ = ihdr.imageHeight;
@ -276,7 +276,7 @@ void Jp2Image::readMetadata() {
#ifdef EXIV2_DEBUG_MESSAGES
std::cout << "Exiv2::Jp2Image::readMetadata: Exif data found" << std::endl;
#endif
enforce(box.length >= boxHSize + sizeof(uuid), ErrorCode::kerCorruptedMetadata);
Internal::enforce(box.length >= boxHSize + sizeof(uuid), ErrorCode::kerCorruptedMetadata);
rawData.alloc(box.length - (boxHSize + sizeof(uuid)));
bufRead = io_->read(rawData.data(), rawData.size());
if (io_->error())
@ -324,7 +324,7 @@ void Jp2Image::readMetadata() {
#ifdef EXIV2_DEBUG_MESSAGES
std::cout << "Exiv2::Jp2Image::readMetadata: Iptc data found" << std::endl;
#endif
enforce(box.length >= boxHSize + sizeof(uuid), ErrorCode::kerCorruptedMetadata);
Internal::enforce(box.length >= boxHSize + sizeof(uuid), ErrorCode::kerCorruptedMetadata);
rawData.alloc(box.length - (boxHSize + sizeof(uuid)));
bufRead = io_->read(rawData.data(), rawData.size());
if (io_->error())
@ -344,7 +344,7 @@ void Jp2Image::readMetadata() {
#ifdef EXIV2_DEBUG_MESSAGES
std::cout << "Exiv2::Jp2Image::readMetadata: Xmp data found" << std::endl;
#endif
enforce(box.length >= boxHSize + sizeof(uuid), ErrorCode::kerCorruptedMetadata);
Internal::enforce(box.length >= boxHSize + sizeof(uuid), ErrorCode::kerCorruptedMetadata);
rawData.alloc(box.length - (boxHSize + sizeof(uuid)));
bufRead = io_->read(rawData.data(), rawData.size());
if (io_->error())
@ -420,7 +420,7 @@ void Jp2Image::printStructure(std::ostream& out, PrintStructureOption option, si
const size_t position = io_->tell();
box.length = getULong(reinterpret_cast<byte*>(&box.length), bigEndian);
box.type = getULong(reinterpret_cast<byte*>(&box.type), bigEndian);
enforce(box.length <= boxHSize + io_->size() - io_->tell(), ErrorCode::kerCorruptedMetadata);
Internal::enforce(box.length <= boxHSize + io_->size() - io_->tell(), ErrorCode::kerCorruptedMetadata);
if (bPrint) {
out << Internal::stringFormat("%8ld | %8ld | ", position - boxHSize, static_cast<size_t>(box.length))
@ -473,7 +473,7 @@ void Jp2Image::printStructure(std::ostream& out, PrintStructureOption option, si
}
if (subBox.type == kJp2BoxTypeImageHeader) {
enforce(subBox.length == 22, ErrorCode::kerCorruptedMetadata);
Internal::enforce(subBox.length == 22, ErrorCode::kerCorruptedMetadata);
// height (4), width (4), componentsCount (2), bpc (1)
auto compressionType = data.read_uint8(11);
auto unkC = data.read_uint8(12);
@ -485,7 +485,7 @@ void Jp2Image::printStructure(std::ostream& out, PrintStructureOption option, si
const size_t pad = 3; // don't know why there are 3 padding bytes
// Bounds-check for the `getULong()` below, which reads 4 bytes, starting at `pad`.
enforce(data.size() >= pad + 4, ErrorCode::kerCorruptedMetadata);
Internal::enforce(data.size() >= pad + 4, ErrorCode::kerCorruptedMetadata);
/// \todo A conforming JP2 reader shall ignore all Colour Specification boxes after the first.
auto METH = data.read_uint8(0);
@ -502,7 +502,7 @@ void Jp2Image::printStructure(std::ostream& out, PrintStructureOption option, si
if (bPrint) {
out << " | iccLength:" << iccLength;
}
enforce(iccLength <= data.size() - pad, ErrorCode::kerCorruptedMetadata);
Internal::enforce(iccLength <= data.size() - pad, ErrorCode::kerCorruptedMetadata);
if (bICC) {
out.write(data.c_str(pad), iccLength);
}
@ -532,7 +532,7 @@ void Jp2Image::printStructure(std::ostream& out, PrintStructureOption option, si
}
DataBuf rawData;
enforce(box.length >= sizeof(uuid) + boxHSize, ErrorCode::kerCorruptedMetadata);
Internal::enforce(box.length >= sizeof(uuid) + boxHSize, ErrorCode::kerCorruptedMetadata);
rawData.alloc(box.length - sizeof(uuid) - boxHSize);
const size_t bufRead = io_->read(rawData.data(), rawData.size());
if (io_->error())
@ -602,14 +602,14 @@ void Jp2Image::encodeJp2Header(const DataBuf& boxBuf, DataBuf& outBuf) {
DataBuf output(boxBuf.size() + iccProfile_.size() + 100); // allocate sufficient space
size_t outlen = boxHSize; // now many bytes have we written to output?
size_t inlen = boxHSize; // how many bytes have we read from boxBuf?
enforce(boxHSize <= output.size(), ErrorCode::kerCorruptedMetadata);
Internal::enforce(boxHSize <= output.size(), ErrorCode::kerCorruptedMetadata);
uint32_t length = getULong(boxBuf.c_data(0), bigEndian);
enforce(length <= output.size(), ErrorCode::kerCorruptedMetadata);
Internal::enforce(length <= output.size(), ErrorCode::kerCorruptedMetadata);
uint32_t count = boxHSize;
bool bWroteColor = false;
while (count < length && !bWroteColor) {
enforce(boxHSize <= length - count, ErrorCode::kerCorruptedMetadata);
Internal::enforce(boxHSize <= length - count, ErrorCode::kerCorruptedMetadata);
Internal::Jp2BoxHeader subBox;
memcpy(&subBox, boxBuf.c_data(count), boxHSize);
Internal::Jp2BoxHeader newBox = subBox;
@ -621,8 +621,8 @@ void Jp2Image::encodeJp2Header(const DataBuf& boxBuf, DataBuf& outBuf) {
std::cout << "Jp2Image::encodeJp2Header subbox: " << toAscii(subBox.type) << " length = " << subBox.length
<< std::endl;
#endif
enforce(subBox.length > 0, ErrorCode::kerCorruptedMetadata);
enforce(subBox.length <= length - count, ErrorCode::kerCorruptedMetadata);
Internal::enforce(subBox.length > 0, ErrorCode::kerCorruptedMetadata);
Internal::enforce(subBox.length <= length - count, ErrorCode::kerCorruptedMetadata);
count += subBox.length;
newBox.type = subBox.type;
} else {
@ -637,7 +637,7 @@ void Jp2Image::encodeJp2Header(const DataBuf& boxBuf, DataBuf& outBuf) {
if (!iccProfileDefined()) {
const char* pad = "\x01\x00\x00\x00\x00\x00\x10\x00\x00\x05\x1cuuid";
uint32_t psize = 15;
enforce(newlen <= output.size() - outlen, ErrorCode::kerCorruptedMetadata);
Internal::enforce(newlen <= output.size() - outlen, ErrorCode::kerCorruptedMetadata);
ul2Data(reinterpret_cast<byte*>(&newBox.length), psize, bigEndian);
ul2Data(reinterpret_cast<byte*>(&newBox.type), newBox.type, bigEndian);
std::copy_n(reinterpret_cast<char*>(&newBox), sizeof(newBox), output.begin() + outlen);
@ -646,7 +646,7 @@ void Jp2Image::encodeJp2Header(const DataBuf& boxBuf, DataBuf& outBuf) {
const char* pad = "\x02\x00\x00";
uint32_t psize = 3;
newlen = sizeof(newBox) + psize + iccProfile_.size();
enforce(newlen <= output.size() - outlen, ErrorCode::kerCorruptedMetadata);
Internal::enforce(newlen <= output.size() - outlen, ErrorCode::kerCorruptedMetadata);
ul2Data(reinterpret_cast<byte*>(&newBox.length), static_cast<uint32_t>(newlen), bigEndian);
ul2Data(reinterpret_cast<byte*>(&newBox.type), newBox.type, bigEndian);
std::copy_n(reinterpret_cast<char*>(&newBox), sizeof(newBox), output.begin() + outlen);
@ -654,7 +654,7 @@ void Jp2Image::encodeJp2Header(const DataBuf& boxBuf, DataBuf& outBuf) {
std::copy(iccProfile_.begin(), iccProfile_.end(), output.begin() + outlen + sizeof(newBox) + psize);
}
} else {
enforce(newlen <= output.size() - outlen, ErrorCode::kerCorruptedMetadata);
Internal::enforce(newlen <= output.size() - outlen, ErrorCode::kerCorruptedMetadata);
std::copy_n(boxBuf.c_data(inlen), subBox.length, output.begin() + outlen);
}
@ -734,7 +734,8 @@ void Jp2Image::doWriteMetadata(BasicIo& outIo) {
}
// Prevent a malicious file from causing a large memory allocation.
enforce(box.length - 8 <= static_cast<size_t>(io_->size() - io_->tell()), ErrorCode::kerCorruptedMetadata);
Internal::enforce(box.length - 8 <= static_cast<size_t>(io_->size() - io_->tell()),
ErrorCode::kerCorruptedMetadata);
// Read whole box : Box header + Box data (not fixed size - can be null).
DataBuf boxBuf(box.length); // Box header (8 bytes) + box data.
@ -831,7 +832,7 @@ void Jp2Image::doWriteMetadata(BasicIo& outIo) {
}
case kJp2BoxTypeUuid: {
enforce(boxBuf.size() >= 24, ErrorCode::kerCorruptedMetadata);
Internal::enforce(boxBuf.size() >= 24, ErrorCode::kerCorruptedMetadata);
if (boxBuf.cmpBytes(8, kJp2UuidExif, 16) == 0) {
#ifdef EXIV2_DEBUG_MESSAGES
std::cout << "Exiv2::Jp2Image::doWriteMetadata: strip Exif Uuid box" << std::endl;

@ -31,6 +31,7 @@
namespace Exiv2 {
using Exiv2::Internal::enforce;
using Exiv2::Internal::startsWith;
namespace {
// JPEG Segment markers (The first byte is always 0xFF, the value of these constants correspond to the 2nd byte)
@ -61,11 +62,11 @@ constexpr auto exifId_ = "Exif\0\0"; //!< Exif identifier
constexpr auto xmpId_ = "http://ns.adobe.com/xap/1.0/\0"; //!< XMP packet identifier
constexpr auto iccId_ = "ICC_PROFILE\0"; //!< ICC profile identifier
inline bool inRange(int lo, int value, int hi) {
constexpr bool inRange(int lo, int value, int hi) {
return lo <= value && value <= hi;
}
inline bool inRange2(int value, int lo1, int hi1, int lo2, int hi2) {
constexpr bool inRange2(int value, int lo1, int hi1, int lo2, int hi2) {
return inRange(lo1, value, hi1) || inRange(lo2, value, hi2);
}

@ -15,14 +15,16 @@
#include "utils.hpp"
// + standard includes
#ifdef EXV_ENABLE_INIH
#include <INIReader.h>
#endif
#include <array>
#include <filesystem>
#include <iostream>
#if __has_include(<filesystem>)
#include <filesystem>
namespace fs = std::filesystem;
#else
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#endif
#if !defined(_WIN32)
#include <pwd.h>
@ -33,7 +35,10 @@ namespace fs = std::filesystem;
#define CSIDL_PROFILE 40
#endif
#include <process.h>
#endif
#ifdef EXV_ENABLE_INIH
#include <INIReader.h>
#endif
// *****************************************************************************
@ -137,16 +142,16 @@ bool TiffMnRegistry::operator==(IfdId key) const {
TiffComponent* TiffMnCreator::create(uint16_t tag, IfdId group, const std::string& make, const byte* pData, size_t size,
ByteOrder byteOrder) {
auto tmr = std::find(std::begin(registry_), std::end(registry_), make);
if (tmr != std::end(registry_)) {
return tmr->newMnFct_(tag, group, tmr->mnGroup_, pData, size, byteOrder);
auto tmr = Exiv2::find(registry_, make);
if (!tmr) {
return nullptr;
}
return nullptr;
return tmr->newMnFct_(tag, group, tmr->mnGroup_, pData, size, byteOrder);
} // TiffMnCreator::create
TiffComponent* TiffMnCreator::create(uint16_t tag, IfdId group, IfdId mnGroup) {
auto tmr = std::find(std::begin(registry_), std::end(registry_), mnGroup);
if (tmr != std::end(registry_)) {
auto tmr = Exiv2::find(registry_, mnGroup);
if (tmr) {
if (tmr->newMnFct2_) {
return tmr->newMnFct2_(tag, group, mnGroup);
}
@ -859,35 +864,46 @@ struct NikonArrayIdx {
#define NA ((uint32_t)-1)
//! Nikon binary array version lookup table
constexpr auto nikonArrayIdx = std::array{
constexpr NikonArrayIdx nikonArrayIdx[] = {
// NikonSi
NikonArrayIdx{0x0091, "0208", 0, 0, 4}, // D80
NikonArrayIdx{0x0091, "0209", 0, 1, 4}, // D40
NikonArrayIdx{0x0091, "0210", 5291, 2, 4}, // D300
NikonArrayIdx{0x0091, "0210", 5303, 3, 4}, // D300, firmware version 1.10
NikonArrayIdx{0x0091, "02", 0, 4, 4}, // Other v2.* (encrypted)
NikonArrayIdx{0x0091, "01", 0, 5, NA}, // Other v1.* (not encrypted)
{0x0091, "0208", 0, 0, 4}, // D80
{0x0091, "0209", 0, 1, 4}, // D40
{0x0091, "0210", 5291, 2, 4}, // D300
{0x0091, "0210", 5303, 3, 4}, // D300, firmware version 1.10
{0x0091, "02", 0, 4, 4}, // Other v2.* (encrypted)
{0x0091, "01", 0, 5, NA}, // Other v1.* (not encrypted)
// NikonCb
NikonArrayIdx{0x0097, "0100", 0, 0, NA}, NikonArrayIdx{0x0097, "0102", 0, 1, NA},
NikonArrayIdx{0x0097, "0103", 0, 4, NA}, NikonArrayIdx{0x0097, "0205", 0, 2, 4},
NikonArrayIdx{0x0097, "0209", 0, 5, 284}, NikonArrayIdx{0x0097, "0212", 0, 5, 284},
NikonArrayIdx{0x0097, "0214", 0, 5, 284}, NikonArrayIdx{0x0097, "02", 0, 3, 284},
{0x0097, "0100", 0, 0, NA},
{0x0097, "0102", 0, 1, NA},
{0x0097, "0103", 0, 4, NA},
{0x0097, "0205", 0, 2, 4},
{0x0097, "0209", 0, 5, 284},
{0x0097, "0212", 0, 5, 284},
{0x0097, "0214", 0, 5, 284},
{0x0097, "02", 0, 3, 284},
// NikonLd
NikonArrayIdx{0x0098, "0100", 0, 0, NA}, NikonArrayIdx{0x0098, "0101", 0, 1, NA},
NikonArrayIdx{0x0098, "0201", 0, 1, 4}, NikonArrayIdx{0x0098, "0202", 0, 1, 4},
NikonArrayIdx{0x0098, "0203", 0, 1, 4}, NikonArrayIdx{0x0098, "0204", 0, 2, 4},
NikonArrayIdx{0x0098, "0800", 0, 3, 4}, // for e.g. Z6/7
NikonArrayIdx{0x0098, "0801", 0, 3, 4}, // for e.g. Z6/7
NikonArrayIdx{0x0098, "0802", 0, 3, 4}, // for e.g. Z9
{0x0098, "0100", 0, 0, NA},
{0x0098, "0101", 0, 1, NA},
{0x0098, "0201", 0, 1, 4},
{0x0098, "0202", 0, 1, 4},
{0x0098, "0203", 0, 1, 4},
{0x0098, "0204", 0, 2, 4},
{0x0098, "0800", 0, 3, 4}, // for e.g. Z6/7
{0x0098, "0801", 0, 3, 4}, // for e.g. Z6/7
{0x0098, "0802", 0, 3, 4}, // for e.g. Z9
// NikonFl
NikonArrayIdx{0x00a8, "0100", 0, 0, NA}, NikonArrayIdx{0x00a8, "0101", 0, 0, NA},
NikonArrayIdx{0x00a8, "0102", 0, 1, NA}, NikonArrayIdx{0x00a8, "0103", 0, 2, NA},
NikonArrayIdx{0x00a8, "0104", 0, 2, NA}, NikonArrayIdx{0x00a8, "0105", 0, 2, NA},
NikonArrayIdx{0x00a8, "0106", 0, 3, NA}, NikonArrayIdx{0x00a8, "0107", 0, 4, NA},
NikonArrayIdx{0x00a8, "0108", 0, 4, NA},
{0x00a8, "0100", 0, 0, NA},
{0x00a8, "0101", 0, 0, NA},
{0x00a8, "0102", 0, 1, NA},
{0x00a8, "0103", 0, 2, NA},
{0x00a8, "0104", 0, 2, NA},
{0x00a8, "0105", 0, 2, NA},
{0x00a8, "0106", 0, 3, NA},
{0x00a8, "0107", 0, 4, NA},
{0x00a8, "0108", 0, 4, NA},
// NikonAf
NikonArrayIdx{0x00b7, "0100", 30, 0, NA}, // These sizes have been found in tiff headers of MN
NikonArrayIdx{0x00b7, "0101", 84, 1, NA}, // tag 0xb7 in sample image metadata for each version
{0x00b7, "0100", 30, 0, NA}, // These sizes have been found in tiff headers of MN
{0x00b7, "0101", 84, 1, NA}, // tag 0xb7 in sample image metadata for each version
};
int nikonSelector(uint16_t tag, const byte* pData, size_t size, TiffComponent* /*pRoot*/) {
@ -895,8 +911,8 @@ int nikonSelector(uint16_t tag, const byte* pData, size_t size, TiffComponent* /
return -1;
auto ix = NikonArrayIdx::Key(tag, reinterpret_cast<const char*>(pData), size);
auto it = std::find(nikonArrayIdx.begin(), nikonArrayIdx.end(), ix);
if (it == nikonArrayIdx.end())
auto it = Exiv2::find(nikonArrayIdx, ix);
if (!it)
return -1;
return it->idx_;
@ -907,9 +923,8 @@ DataBuf nikonCrypt(uint16_t tag, const byte* pData, size_t size, TiffComponent*
if (size < 4)
return buf;
auto nci = std::find(nikonArrayIdx.begin(), nikonArrayIdx.end(),
NikonArrayIdx::Key(tag, reinterpret_cast<const char*>(pData), size));
if (nci == nikonArrayIdx.end() || nci->start_ == NA || size <= nci->start_)
auto nci = Exiv2::find(nikonArrayIdx, NikonArrayIdx::Key(tag, reinterpret_cast<const char*>(pData), size));
if (!nci || nci->start_ == NA || size <= nci->start_)
return buf;
// Find Exif.Nikon3.ShutterCount
@ -955,12 +970,12 @@ int sonyCsSelector(uint16_t /*tag*/, const byte* /*pData*/, size_t /*size*/, Tif
return idx;
}
int sony2010eSelector(uint16_t /*tag*/, const byte* /*pData*/, size_t /*size*/, TiffComponent* pRoot) {
static constexpr auto models = std::array{
static constexpr const char* models[] = {
"SLT-A58", "SLT-A99", "ILCE-3000", "ILCE-3500", "NEX-3N", "NEX-5R", "NEX-5T",
"NEX-6", "VG30E", "VG900", "DSC-RX100", "DSC-RX1", "DSC-RX1R", "DSC-HX300",
"DSC-HX50V", "DSC-TX30", "DSC-WX60", "DSC-WX200", "DSC-WX300",
};
return std::find(models.begin(), models.end(), getExifModel(pRoot)) != models.end() ? 0 : -1;
return Exiv2::find(models, getExifModel(pRoot)) ? 0 : -1;
}
int sony2FpSelector(uint16_t /*tag*/, const byte* /*pData*/, size_t /*size*/, TiffComponent* pRoot) {

@ -1446,19 +1446,19 @@ static long getKeyLong(const std::string& key, const ExifData* metadata, int whi
/*! http://stackoverflow.com/questions/1798112/removing-leading-and-trailing-spaces-from-a-string
trim from left
*/
inline std::string& ltrim(std::string& s, const char* t = " \t\n\r\f\v") {
static std::string& ltrim(std::string& s, const char* t = " \t\n\r\f\v") {
s.erase(0, s.find_first_not_of(t));
return s;
}
//! trim from right
inline std::string& rtrim(std::string& s, const char* t = " \t\n\r\f\v") {
static std::string& rtrim(std::string& s, const char* t = " \t\n\r\f\v") {
s.erase(s.find_last_not_of(t) + 1);
return s;
}
//! trim from left & right
inline std::string& trim(std::string& s, const char* t = " \t\n\r\f\v") {
static std::string& trim(std::string& s, const char* t = " \t\n\r\f\v") {
return ltrim(rtrim(s, t), t);
}
@ -1483,7 +1483,7 @@ static bool inRange(long value, long min, long max) {
}
static std::ostream& resolvedLens(std::ostream& os, long lensID, long index) {
const TagDetails* td = find(minoltaSonyLensID, lensID);
auto td = Exiv2::find(minoltaSonyLensID, lensID);
std::vector<std::string> tokens = split(td[0].label_, "|");
return os << exvGettext(trim(tokens.at(index - 1)).c_str());
}
@ -1606,7 +1606,7 @@ static std::ostream& resolveLens0xffff(std::ostream& os, const Value& value, con
std::string maxAperture = getKeyString("Exif.Photo.MaxApertureValue", metadata);
std::string F1_8 = "434/256";
static constexpr auto maxApertures = std::array{
static constexpr const char* maxApertures[] = {
"926/256", // F3.5
"1024/256", // F4
"1110/256", // F4.5
@ -1626,7 +1626,7 @@ static std::ostream& resolveLens0xffff(std::ostream& os, const Value& value, con
} catch (...) {
}
if (model == "ILCE-6000" && std::find(maxApertures.begin(), maxApertures.end(), maxAperture) != maxApertures.end())
if (model == "ILCE-6000" && Exiv2::find(maxApertures, maxAperture))
try {
long focalLength = getKeyLong("Exif.Photo.FocalLength", metadata);
if (focalLength > 0) {

@ -77,22 +77,22 @@ void MrwImage::readMetadata() {
uint32_t const end = getULong(tmp + 4, bigEndian);
pos += len;
enforce(pos <= end, ErrorCode::kerFailedToReadImageData);
Internal::enforce(pos <= end, ErrorCode::kerFailedToReadImageData);
io_->read(tmp, len);
if (io_->error() || io_->eof())
throw Error(ErrorCode::kerFailedToReadImageData);
while (memcmp(tmp + 1, "TTW", 3) != 0) {
uint32_t const siz = getULong(tmp + 4, bigEndian);
enforce(siz <= end - pos, ErrorCode::kerFailedToReadImageData);
Internal::enforce(siz <= end - pos, ErrorCode::kerFailedToReadImageData);
pos += siz;
io_->seek(siz, BasicIo::cur);
enforce(!io_->error() && !io_->eof(), ErrorCode::kerFailedToReadImageData);
Internal::enforce(!io_->error() && !io_->eof(), ErrorCode::kerFailedToReadImageData);
enforce(len <= end - pos, ErrorCode::kerFailedToReadImageData);
Internal::enforce(len <= end - pos, ErrorCode::kerFailedToReadImageData);
pos += len;
io_->read(tmp, len);
enforce(!io_->error() && !io_->eof(), ErrorCode::kerFailedToReadImageData);
Internal::enforce(!io_->error() && !io_->eof(), ErrorCode::kerFailedToReadImageData);
}
const uint32_t siz = getULong(tmp + 4, bigEndian);
@ -101,10 +101,10 @@ void MrwImage::readMetadata() {
// greater than io_->size() then it is definitely invalid. But the
// exact bounds checking is done by the call to io_->read, which
// will fail if there are fewer than siz bytes left to read.
enforce(siz <= io_->size(), ErrorCode::kerFailedToReadImageData);
Internal::enforce(siz <= io_->size(), ErrorCode::kerFailedToReadImageData);
DataBuf buf(siz);
io_->read(buf.data(), buf.size());
enforce(!io_->error() && !io_->eof(), ErrorCode::kerFailedToReadImageData);
Internal::enforce(!io_->error() && !io_->eof(), ErrorCode::kerFailedToReadImageData);
ByteOrder bo = TiffParser::decode(exifData_, iptcData_, xmpData_, buf.c_data(), buf.size());
setByteOrder(bo);

@ -3791,7 +3791,7 @@ std::ostream& Nikon3MakerNote::print0x009e(std::ostream& os, const Value& value,
if (l != 0)
trim = false;
std::string d = s.empty() ? "" : "; ";
const TagDetails* td = find(nikonRetouchHistory, l);
auto td = Exiv2::find(nikonRetouchHistory, l);
if (td) {
s = std::string(exvGettext(td->label_)).append(d).append(s);
} else {

@ -1243,7 +1243,7 @@ std::ostream& OlympusMakerNote::print0x0201(std::ostream& os, const Value& value
// 6 numbers: 0. Make, 1. Unknown, 2. Model, 3. Sub-model, 4-5. Unknown.
// Only the Make, Model and Sub-model are used to determine the lens model
static struct {
static const struct {
byte val[3];
const char* label;
} lensTypes[] = {
@ -1397,7 +1397,7 @@ std::ostream& OlympusMakerNote::print0x0209(std::ostream& os, const Value& value
std::ostream& OlympusMakerNote::printEq0x0301(std::ostream& os, const Value& value, const ExifData*) {
// 6 numbers: 0. Make, 1. Unknown, 2. Model, 3. Sub-model, 4-5. Unknown.
// Only the Make and Model are used to determine the extender model
static struct {
static const struct {
byte val[2];
const char* label;
} extenderModels[] = {

@ -1096,7 +1096,7 @@ std::ostream& resolveLens0x32c(std::ostream& os, const Value& value, const ExifD
if (index > 0) {
const unsigned long lensID = 0x32c;
const TagDetails* td = find(pentaxLensType, lensID);
auto td = Exiv2::find(pentaxLensType, lensID);
os << exvGettext(td[index].label_);
return os;
}
@ -1160,7 +1160,7 @@ std::ostream& resolveLens0x3ff(std::ostream& os, const Value& value, const ExifD
if (index > 0) {
const unsigned long lensID = 0x3ff;
const TagDetails* td = find(pentaxLensType, lensID);
auto td = Exiv2::find(pentaxLensType, lensID);
os << exvGettext(td[index].label_);
return os;
}
@ -1187,7 +1187,7 @@ std::ostream& resolveLens0x8ff(std::ostream& os, const Value& value, const ExifD
if (index > 0) {
const unsigned long lensID = 0x8ff;
const TagDetails* td = find(pentaxLensType, lensID);
auto td = Exiv2::find(pentaxLensType, lensID);
os << exvGettext(td[index].label_);
return os;
}
@ -1221,7 +1221,7 @@ std::ostream& resolveLens0x319(std::ostream& os, const Value& value, const ExifD
if (index > 0) {
const unsigned long lensID = 0x319;
const TagDetails* td = find(pentaxLensType, lensID);
auto td = Exiv2::find(pentaxLensType, lensID);
os << exvGettext(td[index].label_);
return os;
}
@ -1245,12 +1245,11 @@ struct LensIdFct {
};
//! List of lens ids which require special treatment using resolveLensType
constexpr auto lensIdFct = std::array{
LensIdFct{0x0317, resolveLensType}, LensIdFct{0x0319, resolveLens0x319}, LensIdFct{0x031b, resolveLensType},
LensIdFct{0x031c, resolveLensType}, LensIdFct{0x031d, resolveLensType}, LensIdFct{0x031f, resolveLensType},
LensIdFct{0x0329, resolveLensType}, LensIdFct{0x032c, resolveLens0x32c}, LensIdFct{0x032e, resolveLensType},
LensIdFct{0x0334, resolveLensType}, LensIdFct{0x03ff, resolveLens0x3ff}, LensIdFct{0x041a, resolveLensType},
LensIdFct{0x042d, resolveLensType}, LensIdFct{0x08ff, resolveLens0x8ff},
constexpr LensIdFct lensIdFct[] = {
{0x0317, resolveLensType}, {0x0319, resolveLens0x319}, {0x031b, resolveLensType}, {0x031c, resolveLensType},
{0x031d, resolveLensType}, {0x031f, resolveLensType}, {0x0329, resolveLensType}, {0x032c, resolveLens0x32c},
{0x032e, resolveLensType}, {0x0334, resolveLensType}, {0x03ff, resolveLens0x3ff}, {0x041a, resolveLensType},
{0x042d, resolveLensType}, {0x08ff, resolveLens0x8ff},
};
//! A lens id and a pretty-print function for special treatment of the id.
@ -1265,8 +1264,8 @@ std::ostream& printLensType(std::ostream& os, const Value& value, const ExifData
const auto index = value.toUint32(0) * 256 + value.toUint32(1);
// std::cout << std::endl << "printLensType value =" << value.toLong() << " index = " << index << std::endl;
auto lif = std::find(lensIdFct.begin(), lensIdFct.end(), index);
if (lif == lensIdFct.end())
auto lif = Exiv2::find(lensIdFct, index);
if (!lif)
return EXV_PRINT_COMBITAG_MULTI(pentaxLensType, 2, 1, 2)(os, value, metadata);
if (metadata && lif->fct_)
return lif->fct_(os, value, metadata);

@ -70,7 +70,7 @@ std::ostream& printCombiTag(std::ostream& os, const Value& value, const ExifData
}
l += (value.toUint32(c) << ((count - c - 1) * 8));
}
const TagDetails* td = find(array, l);
auto td = Exiv2::find(array, l);
if (td) {
os << exvGettext(td->label_);
} else {

@ -87,7 +87,7 @@ void PgfImage::readMetadata() {
// And now, the most interesting, the user data byte array where metadata are stored as small image.
enforce(headerSize <= std::numeric_limits<size_t>::max() - 8, ErrorCode::kerCorruptedMetadata);
Internal::enforce(headerSize <= std::numeric_limits<size_t>::max() - 8, ErrorCode::kerCorruptedMetadata);
size_t size = headerSize + 8 - io_->tell();
#ifdef EXIV2_DEBUG_MESSAGES

@ -154,7 +154,7 @@ DataBuf Photoshop::setIptcIrb(const byte* pPsData, size_t sizePsData, const Iptc
// Write existing stuff after record, skip the current and all remaining IPTC blocks
size_t pos = sizeFront;
auto nextSizeData = Safe::add<long>(static_cast<long>(sizePsData), -static_cast<long>(pos));
enforce(nextSizeData >= 0, ErrorCode::kerCorruptedMetadata);
Internal::enforce(nextSizeData >= 0, ErrorCode::kerCorruptedMetadata);
while (0 == Photoshop::locateIptcIrb(pPsData + pos, nextSizeData, &record, sizeHdr, sizeIptc)) {
const auto newPos = static_cast<size_t>(record - pPsData);
if (newPos > pos) { // Copy data up to the IPTC IRB
@ -162,7 +162,7 @@ DataBuf Photoshop::setIptcIrb(const byte* pPsData, size_t sizePsData, const Iptc
}
pos = newPos + sizeHdr + sizeIptc + (sizeIptc & 1); // Skip the IPTC IRB
nextSizeData = Safe::add<long>(static_cast<long>(sizePsData), -static_cast<long>(pos));
enforce(nextSizeData >= 0, ErrorCode::kerCorruptedMetadata);
Internal::enforce(nextSizeData >= 0, ErrorCode::kerCorruptedMetadata);
}
if (pos < sizePsData) {
append(psBlob, pPsData + pos, sizePsData - pos);

@ -41,7 +41,7 @@ constexpr unsigned char pngBlank[] = {
const auto nullComp = reinterpret_cast<const Exiv2::byte*>("\0\0");
const auto typeExif = reinterpret_cast<const Exiv2::byte*>("eXIf");
const auto typeICCP = reinterpret_cast<const Exiv2::byte*>("iCCP");
inline bool compare(std::string_view str, const Exiv2::DataBuf& buf) {
bool compare(std::string_view str, const Exiv2::DataBuf& buf) {
const auto minlen = std::min(str.size(), buf.size());
return buf.cmpBytes(0, str.data(), minlen) == 0;
}
@ -247,7 +247,7 @@ void PngImage::printStructure(std::ostream& out, PrintStructureOption option, si
}
while (dataString.size() < iMax)
dataString += ' ';
dataString = dataString.substr(0, iMax);
dataString.resize(iMax);
if (bPrint) {
io_->seek(dataOffset, BasicIo::cur); // jump to checksum

@ -731,7 +731,7 @@ DataBuf LoaderTiff::getData() const {
dataValue.setDataArea(base + offset, size);
} else {
// FIXME: the buffer is probably copied twice, it should be optimized
enforce(size_ <= io.size(), ErrorCode::kerCorruptedMetadata);
Internal::enforce(size_ <= io.size(), ErrorCode::kerCorruptedMetadata);
DataBuf buf(size_);
uint32_t idxBuf = 0;
for (size_t i = 0; i < sizes.count(); i++) {
@ -742,7 +742,7 @@ DataBuf LoaderTiff::getData() const {
// see the constructor of LoaderTiff
// But e.g in malicious files some of these values could be negative
// That's why we check again for each step here to really make sure we don't overstep
enforce(Safe::add(idxBuf, size) <= size_, ErrorCode::kerCorruptedMetadata);
Internal::enforce(Safe::add(idxBuf, size) <= size_, ErrorCode::kerCorruptedMetadata);
if (size != 0 && Safe::add(offset, size) <= static_cast<uint32_t>(io.size())) {
std::copy_n(base + offset, size, buf.begin() + idxBuf);
}

@ -4942,8 +4942,8 @@ const XmpNsInfo* XmpProperties::lookupNsRegistryUnsafe(const XmpNsInfo::Prefix&
void XmpProperties::registerNs(const std::string& ns, const std::string& prefix) {
auto scopedWriteLock = std::scoped_lock(mutex_);
std::string ns2 = ns;
if (ns2.substr(ns2.size() - 1, 1) != "/" && ns2.substr(ns2.size() - 1, 1) != "#")
ns2 += "/";
if (ns2.back() != '/' && ns2.back() != '#')
ns2 += '/';
// Check if there is already a registered namespace with this prefix
const XmpNsInfo* xnp = lookupNsRegistryUnsafe(XmpNsInfo::Prefix(prefix));
if (xnp) {
@ -4995,15 +4995,15 @@ void XmpProperties::unregisterNs() {
std::string XmpProperties::prefix(const std::string& ns) {
auto scoped_read_lock = std::scoped_lock(mutex_);
std::string ns2 = ns;
if (ns2.substr(ns2.size() - 1, 1) != "/" && ns2.substr(ns2.size() - 1, 1) != "#")
ns2 += "/";
if (ns2.back() != '/' && ns2.back() != '#')
ns2 += '/';
auto i = nsRegistry_.find(ns2);
std::string p;
if (i != nsRegistry_.end()) {
p = i->second.prefix_;
} else {
const XmpNsInfo* xn = find(xmpNsInfo, XmpNsInfo::Ns(ns2));
auto xn = Exiv2::find(xmpNsInfo, XmpNsInfo::Ns(ns2));
if (xn)
p = std::string(xn->prefix_);
}
@ -5082,7 +5082,7 @@ const XmpNsInfo* XmpProperties::nsInfoUnsafe(const std::string& prefix) {
const XmpNsInfo::Prefix pf(prefix);
const XmpNsInfo* xn = lookupNsRegistryUnsafe(pf);
if (!xn)
xn = find(xmpNsInfo, pf);
xn = Exiv2::find(xmpNsInfo, pf);
if (!xn)
throw Error(ErrorCode::kerNoNamespaceInfoForXmpPrefix, prefix);
return xn;
@ -5108,7 +5108,7 @@ void XmpProperties::printProperties(std::ostream& os, const std::string& prefix)
std::ostream& XmpProperties::printProperty(std::ostream& os, const std::string& key, const Value& value) {
PrintFct fct = printValue;
if (value.count() != 0) {
const XmpPrintInfo* info = find(xmpPrintInfo, key);
auto info = Exiv2::find(xmpPrintInfo, key);
if (info)
fct = info->printFct_;
}

@ -167,10 +167,10 @@ void PsdImage::readMetadata() {
throw Error(ErrorCode::kerNotAnImage, "Photoshop");
}
uint32_t resourcesLength = getULong(buf, bigEndian);
enforce(resourcesLength < io_->size(), Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(resourcesLength < io_->size(), Exiv2::ErrorCode::kerCorruptedMetadata);
while (resourcesLength > 0) {
enforce(resourcesLength >= 8, Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(resourcesLength >= 8, Exiv2::ErrorCode::kerCorruptedMetadata);
resourcesLength -= 8;
if (io_->read(buf, 8) != 8) {
throw Error(ErrorCode::kerNotAnImage, "Photoshop");
@ -183,12 +183,12 @@ void PsdImage::readMetadata() {
uint32_t resourceNameLength = buf[6] & ~1;
// skip the resource name, plus any padding
enforce(resourceNameLength <= resourcesLength, Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(resourceNameLength <= resourcesLength, Exiv2::ErrorCode::kerCorruptedMetadata);
resourcesLength -= resourceNameLength;
io_->seek(resourceNameLength, BasicIo::cur);
// read resource size
enforce(resourcesLength >= 4, Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(resourcesLength >= 4, Exiv2::ErrorCode::kerCorruptedMetadata);
resourcesLength -= 4;
if (io_->read(buf, 4) != 4) {
throw Error(ErrorCode::kerNotAnImage, "Photoshop");
@ -201,10 +201,10 @@ void PsdImage::readMetadata() {
<< "\n";
#endif
enforce(resourceSize <= resourcesLength, Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(resourceSize <= resourcesLength, Exiv2::ErrorCode::kerCorruptedMetadata);
readResourceBlock(resourceId, resourceSize);
resourceSize = (resourceSize + 1) & ~1; // pad to even
enforce(resourceSize <= resourcesLength, Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(resourceSize <= resourcesLength, Exiv2::ErrorCode::kerCorruptedMetadata);
resourcesLength -= resourceSize;
io_->seek(curOffset + resourceSize, BasicIo::beg);
}

@ -775,7 +775,7 @@ void QuickTimeVideo::CameraTagsDecoder(size_t size_external) {
buf.read_uint32(0, littleEndian) / static_cast<double>(buf2.read_uint32(0, littleEndian));
io_->readOrThrow(buf.data(), 10);
io_->readOrThrow(buf.data(), 4);
td = find(whiteBalance, buf.read_uint32(0, littleEndian));
td = Exiv2::find(whiteBalance, buf.read_uint32(0, littleEndian));
if (td)
xmpData_["Xmp.video.WhiteBalance"] = exvGettext(td->label_);
io_->readOrThrow(buf.data(), 4);
@ -814,9 +814,9 @@ void QuickTimeVideo::userDataDecoder(size_t size_external) {
if (buf.data()[0] == 169)
buf.data()[0] = ' ';
td = find(userDatatags, Exiv2::toString(buf.data()));
td = Exiv2::find(userDatatags, Exiv2::toString(buf.data()));
tv = find(userDataReferencetags, Exiv2::toString(buf.data()));
tv = Exiv2::find(userDataReferencetags, Exiv2::toString(buf.data()));
if (size <= 12)
break;
@ -840,7 +840,7 @@ void QuickTimeVideo::userDataDecoder(size_t size_external) {
enforce(tv, Exiv2::ErrorCode::kerCorruptedMetadata);
io_->readOrThrow(buf.data(), 2);
buf.data()[2] = '\0';
tv_internal = find(cameraByteOrderTags, Exiv2::toString(buf.data()));
tv_internal = Exiv2::find(cameraByteOrderTags, Exiv2::toString(buf.data()));
if (tv_internal)
xmpData_[exvGettext(tv->label_)] = exvGettext(tv_internal->label_);
@ -870,7 +870,7 @@ void QuickTimeVideo::NikonTagsDecoder(size_t size_external) {
for (int i = 0; i < 100; i++) {
io_->readOrThrow(buf.data(), 4);
TagID = buf.read_uint32(0, bigEndian);
td = find(NikonNCTGTags, TagID);
td = Exiv2::find(NikonNCTGTags, TagID);
io_->readOrThrow(buf.data(), 2);
dataType = buf.read_uint16(0, bigEndian);
@ -893,40 +893,40 @@ void QuickTimeVideo::NikonTagsDecoder(size_t size_external) {
std::memset(buf.data(), 0x0, buf.size());
io_->readOrThrow(buf.data(), 1);
td2 = find(PictureControlAdjust, static_cast<int>(buf.data()[0]) & 7);
td2 = Exiv2::find(PictureControlAdjust, static_cast<int>(buf.data()[0]) & 7);
if (td2)
xmpData_["Xmp.video.PictureControlAdjust"] = exvGettext(td2->label_);
else
xmpData_["Xmp.video.PictureControlAdjust"] = static_cast<int>(buf.data()[0]) & 7;
io_->readOrThrow(buf.data(), 1);
td2 = find(NormalSoftHard, static_cast<int>(buf.data()[0]) & 7);
td2 = Exiv2::find(NormalSoftHard, static_cast<int>(buf.data()[0]) & 7);
if (td2)
xmpData_["Xmp.video.PictureControlQuickAdjust"] = exvGettext(td2->label_);
io_->readOrThrow(buf.data(), 1);
td2 = find(NormalSoftHard, static_cast<int>(buf.data()[0]) & 7);
td2 = Exiv2::find(NormalSoftHard, static_cast<int>(buf.data()[0]) & 7);
if (td2)
xmpData_["Xmp.video.Sharpness"] = exvGettext(td2->label_);
else
xmpData_["Xmp.video.Sharpness"] = static_cast<int>(buf.data()[0]) & 7;
io_->readOrThrow(buf.data(), 1);
td2 = find(NormalSoftHard, static_cast<int>(buf.data()[0]) & 7);
td2 = Exiv2::find(NormalSoftHard, static_cast<int>(buf.data()[0]) & 7);
if (td2)
xmpData_["Xmp.video.Contrast"] = exvGettext(td2->label_);
else
xmpData_["Xmp.video.Contrast"] = static_cast<int>(buf.data()[0]) & 7;
io_->readOrThrow(buf.data(), 1);
td2 = find(NormalSoftHard, static_cast<int>(buf.data()[0]) & 7);
td2 = Exiv2::find(NormalSoftHard, static_cast<int>(buf.data()[0]) & 7);
if (td2)
xmpData_["Xmp.video.Brightness"] = exvGettext(td2->label_);
else
xmpData_["Xmp.video.Brightness"] = static_cast<int>(buf.data()[0]) & 7;
io_->readOrThrow(buf.data(), 1);
td2 = find(Saturation, static_cast<int>(buf.data()[0]) & 7);
td2 = Exiv2::find(Saturation, static_cast<int>(buf.data()[0]) & 7);
if (td2)
xmpData_["Xmp.video.Saturation"] = exvGettext(td2->label_);
else
@ -936,14 +936,14 @@ void QuickTimeVideo::NikonTagsDecoder(size_t size_external) {
xmpData_["Xmp.video.HueAdjustment"] = static_cast<int>(buf.data()[0]) & 7;
io_->readOrThrow(buf.data(), 1);
td2 = find(FilterEffect, static_cast<int>(buf.data()[0]));
td2 = Exiv2::find(FilterEffect, static_cast<int>(buf.data()[0]));
if (td2)
xmpData_["Xmp.video.FilterEffect"] = exvGettext(td2->label_);
else
xmpData_["Xmp.video.FilterEffect"] = static_cast<int>(buf.data()[0]);
io_->readOrThrow(buf.data(), 1);
td2 = find(ToningEffect, static_cast<int>(buf.data()[0]));
td2 = Exiv2::find(ToningEffect, static_cast<int>(buf.data()[0]));
if (td2)
xmpData_["Xmp.video.ToningEffect"] = exvGettext(td2->label_);
else
@ -963,12 +963,12 @@ void QuickTimeVideo::NikonTagsDecoder(size_t size_external) {
io_->readOrThrow(buf.data(), 2);
xmpData_["Xmp.video.TimeZone"] = Exiv2::getShort(buf.data(), bigEndian);
io_->readOrThrow(buf.data(), 1);
td2 = find(YesNo, static_cast<int>(buf.data()[0]));
td2 = Exiv2::find(YesNo, static_cast<int>(buf.data()[0]));
if (td2)
xmpData_["Xmp.video.DayLightSavings"] = exvGettext(td2->label_);
io_->readOrThrow(buf.data(), 1);
td2 = find(DateDisplayFormat, static_cast<int>(buf.data()[0]));
td2 = Exiv2::find(DateDisplayFormat, static_cast<int>(buf.data()[0]));
if (td2)
xmpData_["Xmp.video.DateDisplayFormat"] = exvGettext(td2->label_);
@ -1143,14 +1143,14 @@ void QuickTimeVideo::audioDescDecoder() {
io_->readOrThrow(buf.data(), 4);
switch (i) {
case AudioFormat:
td = find(qTimeFileType, Exiv2::toString(buf.data()));
td = Exiv2::find(qTimeFileType, Exiv2::toString(buf.data()));
if (td)
xmpData_["Xmp.audio.Compressor"] = exvGettext(td->label_);
else
xmpData_["Xmp.audio.Compressor"] = Exiv2::toString(buf.data());
break;
case AudioVendorID:
td = find(vendorIDTags, Exiv2::toString(buf.data()));
td = Exiv2::find(vendorIDTags, Exiv2::toString(buf.data()));
if (td)
xmpData_["Xmp.audio.VendorID"] = exvGettext(td->label_);
break;
@ -1183,14 +1183,14 @@ void QuickTimeVideo::imageDescDecoder() {
switch (i) {
case codec:
td = find(qTimeFileType, Exiv2::toString(buf.data()));
td = Exiv2::find(qTimeFileType, Exiv2::toString(buf.data()));
if (td)
xmpData_["Xmp.video.Codec"] = exvGettext(td->label_);
else
xmpData_["Xmp.video.Codec"] = Exiv2::toString(buf.data());
break;
case VendorID:
td = find(vendorIDTags, Exiv2::toString(buf.data()));
td = Exiv2::find(vendorIDTags, Exiv2::toString(buf.data()));
if (td)
xmpData_["Xmp.video.VendorID"] = exvGettext(td->label_);
break;
@ -1247,7 +1247,7 @@ void QuickTimeVideo::videoHeaderDecoder(size_t size) {
switch (i) {
case GraphicsMode:
td = find(graphicsModetags, buf.read_uint16(0, bigEndian));
td = Exiv2::find(graphicsModetags, buf.read_uint16(0, bigEndian));
if (td)
xmpData_["Xmp.video.GraphicsMode"] = exvGettext(td->label_);
break;
@ -1274,7 +1274,7 @@ void QuickTimeVideo::handlerDecoder(size_t size) {
switch (i) {
case HandlerClass:
tv = find(handlerClassTags, Exiv2::toString(buf.data()));
tv = Exiv2::find(handlerClassTags, Exiv2::toString(buf.data()));
if (tv) {
if (currentStream_ == Video)
xmpData_["Xmp.video.HandlerClass"] = exvGettext(tv->label_);
@ -1283,7 +1283,7 @@ void QuickTimeVideo::handlerDecoder(size_t size) {
}
break;
case HandlerType:
tv = find(handlerTypeTags, Exiv2::toString(buf.data()));
tv = Exiv2::find(handlerTypeTags, Exiv2::toString(buf.data()));
if (tv) {
if (currentStream_ == Video)
xmpData_["Xmp.video.HandlerType"] = exvGettext(tv->label_);
@ -1292,7 +1292,7 @@ void QuickTimeVideo::handlerDecoder(size_t size) {
}
break;
case HandlerVendorID:
tv = find(vendorIDTags, Exiv2::toString(buf.data()));
tv = Exiv2::find(vendorIDTags, Exiv2::toString(buf.data()));
if (tv) {
if (currentStream_ == Video)
xmpData_["Xmp.video.HandlerVendorID"] = exvGettext(tv->label_);
@ -1314,7 +1314,7 @@ void QuickTimeVideo::fileTypeDecoder(size_t size) {
for (int i = 0; size / 4 != 0; size -= 4, i++) {
io_->readOrThrow(buf.data(), 4);
td = find(qTimeFileType, Exiv2::toString(buf.data()));
td = Exiv2::find(qTimeFileType, Exiv2::toString(buf.data()));
switch (i) {
case 0:
@ -1598,7 +1598,7 @@ bool isQTimeType(BasicIo& iIo, bool advance) {
// we only match if we actually know the video type. This is done
// to avoid matching just on ftyp because bmffimage also has that
// header.
auto td = find(qTimeFileType, std::string{buf.c_str(8), 4});
auto td = Exiv2::find(qTimeFileType, std::string{buf.c_str(8), 4});
if (td) {
matched = true;
}

@ -243,17 +243,17 @@ void RafImage::readMetadata() {
uint32_t jpg_img_off_u32 = Exiv2::getULong(jpg_img_offset, bigEndian);
uint32_t jpg_img_len_u32 = Exiv2::getULong(jpg_img_length, bigEndian);
enforce(Safe::add(jpg_img_off_u32, jpg_img_len_u32) <= io_->size(), ErrorCode::kerCorruptedMetadata);
Internal::enforce(Safe::add(jpg_img_off_u32, jpg_img_len_u32) <= io_->size(), ErrorCode::kerCorruptedMetadata);
#if LONG_MAX < UINT_MAX
enforce(jpg_img_off_u32 <= std::numeric_limits<uint32_t>::max(), ErrorCode::kerCorruptedMetadata);
enforce(jpg_img_len_u32 <= std::numeric_limits<uint32_t>::max(), ErrorCode::kerCorruptedMetadata);
Internal::enforce(jpg_img_off_u32 <= std::numeric_limits<uint32_t>::max(), ErrorCode::kerCorruptedMetadata);
Internal::enforce(jpg_img_len_u32 <= std::numeric_limits<uint32_t>::max(), ErrorCode::kerCorruptedMetadata);
#endif
auto jpg_img_off = static_cast<long>(jpg_img_off_u32);
auto jpg_img_len = static_cast<long>(jpg_img_len_u32);
enforce(jpg_img_len >= 12, ErrorCode::kerCorruptedMetadata);
Internal::enforce(jpg_img_len >= 12, ErrorCode::kerCorruptedMetadata);
DataBuf buf(jpg_img_len - 12);
if (io_->seek(jpg_img_off + 12, BasicIo::beg) != 0)
@ -285,7 +285,7 @@ void RafImage::readMetadata() {
uint32_t tiffLength = Exiv2::getULong(readBuff, bigEndian);
// sanity check. Does tiff lie inside the file?
enforce(Safe::add(tiffOffset, tiffLength) <= io_->size(), ErrorCode::kerCorruptedMetadata);
Internal::enforce(Safe::add(tiffOffset, tiffLength) <= io_->size(), ErrorCode::kerCorruptedMetadata);
if (io_->seek(tiffOffset, BasicIo::beg) != 0)
throw Error(ErrorCode::kerFailedToReadImageData);

@ -359,12 +359,6 @@ std::string RiffVideo::mimeType() const {
return "video/riff";
}
void RiffVideo::printStructure(std::ostream& out, PrintStructureOption option, size_t depth) {
if (io_->open() != 0) {
throw Error(ErrorCode::kerDataSourceOpenFailed, io_->path(), strError());
}
} // RiffVideo::printStructure
void RiffVideo::writeMetadata() {
} // RiffVideo::writeMetadata

@ -56,8 +56,8 @@ namespace Internal {
* https://wiki.sei.cmu.edu/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow
*/
template <typename T>
typename std::enable_if<std::is_signed<T>::value && sizeof(T) >= sizeof(int), bool>::type fallback_add_overflow(
T summand_1, T summand_2, T& result) {
std::enable_if_t<std::is_signed_v<T> && sizeof(T) >= sizeof(int), bool> fallback_add_overflow(T summand_1, T summand_2,
T& result) {
if (((summand_2 >= 0) && (summand_1 > std::numeric_limits<T>::max() - summand_2)) ||
((summand_2 < 0) && (summand_1 < std::numeric_limits<T>::min() - summand_2))) {
return true;
@ -86,8 +86,8 @@ typename std::enable_if<std::is_signed<T>::value && sizeof(T) >= sizeof(int), bo
* https://wiki.sei.cmu.edu/confluence/display/c/INT02-C.+Understand+integer+conversion+rules
*/
template <typename T>
typename std::enable_if<std::is_signed<T>::value && sizeof(T) < sizeof(int), bool>::type fallback_add_overflow(
T summand_1, T summand_2, T& result) {
std::enable_if_t<std::is_signed_v<T> && sizeof(T) < sizeof(int), bool> fallback_add_overflow(T summand_1, T summand_2,
T& result) {
const int res = summand_1 + summand_2;
if ((res > std::numeric_limits<T>::max()) || (res < std::numeric_limits<T>::min())) {
return true;
@ -113,8 +113,7 @@ typename std::enable_if<std::is_signed<T>::value && sizeof(T) < sizeof(int), boo
* https://wiki.sei.cmu.edu/confluence/display/c/INT30-C.+Ensure+that+unsigned+integer+operations+do+not+wrap
*/
template <typename T>
typename std::enable_if<!std::is_signed<T>::value, bool>::type fallback_add_overflow(T summand_1, T summand_2,
T& result) {
std::enable_if_t<!std::is_signed_v<T>, bool> fallback_add_overflow(T summand_1, T summand_2, T& result) {
result = summand_1 + summand_2;
return result < summand_1;
}
@ -224,7 +223,7 @@ T add(T summand_1, T summand_2) {
* when `num == std::numeric_limits<T>::min()`.
*/
template <typename T>
typename std::enable_if<std::is_signed<T>::value, T>::type abs(T num) throw() {
std::enable_if_t<std::is_signed_v<T>, T> abs(T num) throw() {
if (num == std::numeric_limits<T>::min()) {
return std::numeric_limits<T>::max();
}

@ -1864,7 +1864,7 @@ std::ostream& SonyMakerNote::printSony2FpFocusPosition2(std::ostream& os, const
}
// Ranges of models that do not support this tag
for (auto& m : {"DSC-", "Stellar"}) {
for (const auto& m : {"DSC-", "Stellar"}) {
if (startsWith(model, m)) {
os << N_("n/a");
return os;
@ -2077,7 +2077,7 @@ std::ostream& SonyMakerNote::printSonyMisc3cShotNumberSincePowerUp(std::ostream&
// Tag only valid for certain camera models. See
// https://github.com/exiftool/exiftool/blob/7368629751669ba170511419b3d1e05bf0076d0e/lib/Image/ExifTool/Sony.pm#L8170
static constexpr auto models = std::array{
static constexpr const char* models[] = {
"ILCA-68", "ILCA-77M2", "ILCA-99M2", "ILCE-5000", "ILCE-5100", "ILCE-6000", "ILCE-6300",
"ILCE-6500", "ILCE-7", "ILCE-7M2", "ILCE-7R", "ILCE-7RM2", "ILCE-7S", "ILCE-7SM2",
"ILCE-7SM5", "ILCE-QX1", "DSC-HX350", "DSC-HX400V", "DSC-HX60V", "DSC-HX80", "DSC-HX90",
@ -2085,7 +2085,7 @@ std::ostream& SonyMakerNote::printSonyMisc3cShotNumberSincePowerUp(std::ostream&
"DSC-RX100M3", "DSC-RX100M4", "DSC-RX100M5", "DSC-WX220", "DSC-WX350", "DSC-WX500",
};
if (std::find(models.begin(), models.end(), model) != models.end()) {
if (Exiv2::find(models, model)) {
return os << value.toInt64();
}
return os << N_("n/a");
@ -2110,9 +2110,9 @@ std::ostream& SonyMakerNote::printSonyMisc3cQuality2(std::ostream& os, const Val
// Tag only valid for certain camera models. See
// https://github.com/exiftool/exiftool/blob/7368629751669ba170511419b3d1e05bf0076d0e/lib/Image/ExifTool/Sony.pm#L8219
constexpr std::array models{"ILCE-1", "ILCE-7M4", "ILCE-7RM5", "ILCE-7SM3", "ILME-FX3"};
constexpr const char* models[] = {"ILCE-1", "ILCE-7M4", "ILCE-7RM5", "ILCE-7SM3", "ILME-FX3"};
if (std::find(models.begin(), models.end(), model) != models.end()) {
if (Exiv2::find(models, model)) {
EXV_PRINT_TAG(sonyMisc3cQuality2a)(os, val, metadata);
return os;
}
@ -2133,9 +2133,9 @@ std::ostream& SonyMakerNote::printSonyMisc3cSonyImageHeight(std::ostream& os, co
// Tag only valid for certain camera models. See
// https://github.com/exiftool/exiftool/blob/7368629751669ba170511419b3d1e05bf0076d0e/lib/Image/ExifTool/Sony.pm#L8239
constexpr std::array models{"ILCE-1", "ILCE-7M4", "ILCE-7RM5", "ILCE-7SM3", "ILME-FX3"};
constexpr const char* models[] = {"ILCE-1", "ILCE-7M4", "ILCE-7RM5", "ILCE-7SM3", "ILME-FX3"};
if (std::find(models.begin(), models.end(), model) != models.end()) {
if (Exiv2::find(models, model)) {
return os << N_("n/a");
}
const auto val = value.toInt64();
@ -2156,9 +2156,9 @@ std::ostream& SonyMakerNote::printSonyMisc3cModelReleaseYear(std::ostream& os, c
// Tag only valid for certain camera models. See
// https://github.com/exiftool/exiftool/blob/7368629751669ba170511419b3d1e05bf0076d0e/lib/Image/ExifTool/Sony.pm#L8245
constexpr std::array models{"ILCE-1", "ILCE-7M4", "ILCE-7RM5", "ILCE-7SM3", "ILME-FX3"};
constexpr const char* models[] = {"ILCE-1", "ILCE-7M4", "ILCE-7RM5", "ILCE-7SM3", "ILME-FX3"};
if (std::find(models.begin(), models.end(), model) != models.end()) {
if (Exiv2::find(models, model)) {
return os << N_("n/a");
}

@ -2320,7 +2320,7 @@ const TagInfo* mnTagList() {
bool isMakerIfd(IfdId ifdId) {
bool rc = false;
const GroupInfo* ii = find(groupInfo, ifdId);
auto ii = Exiv2::find(groupInfo, ifdId);
if (ii && 0 == strcmp(ii->ifdName_, "Makernote")) {
rc = true;
}
@ -2364,7 +2364,7 @@ void taglist(std::ostream& os, IfdId ifdId) {
} // taglist
const TagInfo* tagList(IfdId ifdId) {
const GroupInfo* ii = find(groupInfo, ifdId);
auto ii = Exiv2::find(groupInfo, ifdId);
if (!ii || !ii->tagList_)
return nullptr;
return ii->tagList_();
@ -2399,21 +2399,21 @@ const TagInfo* tagInfo(const std::string& tagName, IfdId ifdId) {
IfdId groupId(const std::string& groupName) {
IfdId ifdId = IfdId::ifdIdNotSet;
const GroupInfo* ii = find(groupInfo, GroupInfo::GroupName(groupName));
auto ii = Exiv2::find(groupInfo, GroupInfo::GroupName(groupName));
if (ii)
ifdId = static_cast<IfdId>(ii->ifdId_);
return ifdId;
}
const char* ifdName(IfdId ifdId) {
const GroupInfo* ii = find(groupInfo, ifdId);
auto ii = Exiv2::find(groupInfo, ifdId);
if (!ii)
return groupInfo[0].ifdName_;
return ii->ifdName_;
}
const char* groupName(IfdId ifdId) {
const GroupInfo* ii = find(groupInfo, ifdId);
auto ii = Exiv2::find(groupInfo, ifdId);
if (!ii)
return groupInfo[0].groupName_;
return ii->groupName_;
@ -3047,7 +3047,7 @@ const GroupInfo* groupList() {
}
const TagInfo* tagList(const std::string& groupName) {
const GroupInfo* ii = find(groupInfo, GroupInfo::GroupName(groupName));
auto ii = Exiv2::find(groupInfo, GroupInfo::GroupName(groupName));
if (!ii || !ii->tagList_) {
return nullptr;
}

@ -95,7 +95,7 @@ struct TagVocabulary {
*/
template <size_t N, const StringTagDetails (&array)[N]>
std::ostream& printTagString(std::ostream& os, const std::string value, const ExifData*) {
const StringTagDetails* td = find(array, value);
auto td = Exiv2::find(array, value);
if (td) {
os << exvGettext(td->label_);
} else {
@ -152,7 +152,7 @@ std::ostream& printTagString4(std::ostream& os, const Value& value, const ExifDa
*/
template <size_t N, const TagDetails (&array)[N]>
std::ostream& printTagNoError(std::ostream& os, const int64_t value, const ExifData*) {
const TagDetails* td = find(array, value);
auto td = Exiv2::find(array, value);
if (td) {
os << exvGettext(td->label_);
} else {
@ -179,7 +179,7 @@ std::ostream& printTagNoError(std::ostream& os, const Value& value, const ExifDa
*/
template <size_t N, const TagDetails (&array)[N]>
std::ostream& printTag(std::ostream& os, const int64_t value, const ExifData*) {
const TagDetails* td = find(array, value);
auto td = Exiv2::find(array, value);
if (td) {
os << exvGettext(td->label_);
} else {
@ -300,7 +300,7 @@ std::ostream& printTagBitlistAllLE(std::ostream& os, const Value& value, const E
*/
template <size_t N, const TagVocabulary (&array)[N]>
std::ostream& printTagVocabulary(std::ostream& os, const Value& value, const ExifData*) {
const TagVocabulary* td = find(array, value.toString());
auto td = Exiv2::find(array, value.toString());
if (td) {
os << exvGettext(td->label_);
} else {
@ -322,7 +322,7 @@ std::ostream& printTagVocabularyMulti(std::ostream& os, const Value& value, cons
for (size_t i = 0; i < value.count(); i++) {
if (i != 0)
os << ", ";
const TagVocabulary* td = find(array, value.toString(i));
auto td = Exiv2::find(array, value.toString(i));
if (td) {
os << exvGettext(td->label_);
} else {

@ -141,25 +141,6 @@ TiffEntryBase::TiffEntryBase(const TiffEntryBase& rhs) :
storage_(rhs.storage_) {
}
TiffDirectory::TiffDirectory(const TiffDirectory& rhs) : TiffComponent(rhs), hasNext_(rhs.hasNext_) {
}
TiffSubIfd::TiffSubIfd(const TiffSubIfd& rhs) : TiffEntryBase(rhs), newGroup_(rhs.newGroup_) {
}
TiffBinaryArray::TiffBinaryArray(const TiffBinaryArray& rhs) :
TiffEntryBase(rhs),
cfgSelFct_(rhs.cfgSelFct_),
arraySet_(rhs.arraySet_),
arrayCfg_(rhs.arrayCfg_),
arrayDef_(rhs.arrayDef_),
defSize_(rhs.defSize_),
setSize_(rhs.setSize_),
origData_(rhs.origData_),
origSize_(rhs.origSize_),
pRoot_(rhs.pRoot_) {
}
TiffComponent::UniquePtr TiffComponent::clone() const {
return UniquePtr(doClone());
}

@ -864,7 +864,7 @@ class TiffDirectory : public TiffComponent {
//! @name Protected Creators
//@{
//! Copy constructor (used to implement clone()).
TiffDirectory(const TiffDirectory& rhs);
TiffDirectory(const TiffDirectory&) = default;
//@}
//! @name Protected Manipulators
@ -958,7 +958,7 @@ class TiffSubIfd : public TiffEntryBase {
//! @name Protected Creators
//@{
//! Copy constructor (used to implement clone()).
TiffSubIfd(const TiffSubIfd& rhs);
TiffSubIfd(const TiffSubIfd&) = default;
TiffSubIfd& operator=(const TiffSubIfd&) = delete;
//@}
@ -1360,7 +1360,7 @@ class TiffBinaryArray : public TiffEntryBase {
//! @name Protected Creators
//@{
//! Copy constructor (used to implement clone()).
TiffBinaryArray(const TiffBinaryArray& rhs);
TiffBinaryArray(const TiffBinaryArray&) = default;
//@}
//! @name Protected Manipulators

@ -1967,7 +1967,7 @@ const TiffMappingInfo TiffMapping::tiffMappingInfo_[] = {
DecoderFct TiffMapping::findDecoder(const std::string& make, uint32_t extendedTag, IfdId group) {
DecoderFct decoderFct = &TiffDecoder::decodeStdTiffEntry;
const TiffMappingInfo* td = find(tiffMappingInfo_, TiffMappingInfo::Key(make, extendedTag, group));
auto td = Exiv2::find(tiffMappingInfo_, TiffMappingInfo::Key(make, extendedTag, group));
if (td) {
// This may set decoderFct to 0, meaning that the tag should not be decoded
decoderFct = td->decoderFct_;
@ -1977,7 +1977,7 @@ DecoderFct TiffMapping::findDecoder(const std::string& make, uint32_t extendedTa
EncoderFct TiffMapping::findEncoder(const std::string& make, uint32_t extendedTag, IfdId group) {
EncoderFct encoderFct = nullptr;
const TiffMappingInfo* td = find(tiffMappingInfo_, TiffMappingInfo::Key(make, extendedTag, group));
auto td = Exiv2::find(tiffMappingInfo_, TiffMappingInfo::Key(make, extendedTag, group));
if (td) {
// Returns 0 if no special encoder function is found
encoderFct = td->encoderFct_;

@ -22,7 +22,7 @@
// *****************************************************************************
namespace {
//! Information pertaining to the defined %Exiv2 value type identifiers.
struct TypeInfoTable {
constexpr struct TypeInfoTable {
Exiv2::TypeId typeId_; //!< Type id
const char* name_; //!< Name of the type
size_t size_; //!< Bytes per data entry
@ -34,34 +34,32 @@ struct TypeInfoTable {
bool operator==(const std::string& name) const {
return name == name_;
}
}; // struct TypeInfoTable
//! Lookup list with information of Exiv2 types
constexpr auto typeInfoTable = std::array{
TypeInfoTable{Exiv2::invalidTypeId, "Invalid", 0},
TypeInfoTable{Exiv2::unsignedByte, "Byte", 1},
TypeInfoTable{Exiv2::asciiString, "Ascii", 1},
TypeInfoTable{Exiv2::unsignedShort, "Short", 2},
TypeInfoTable{Exiv2::unsignedLong, "Long", 4},
TypeInfoTable{Exiv2::unsignedRational, "Rational", 8},
TypeInfoTable{Exiv2::signedByte, "SByte", 1},
TypeInfoTable{Exiv2::undefined, "Undefined", 1},
TypeInfoTable{Exiv2::signedShort, "SShort", 2},
TypeInfoTable{Exiv2::signedLong, "SLong", 4},
TypeInfoTable{Exiv2::signedRational, "SRational", 8},
TypeInfoTable{Exiv2::tiffFloat, "Float", 4},
TypeInfoTable{Exiv2::tiffDouble, "Double", 8},
TypeInfoTable{Exiv2::tiffIfd, "Ifd", 4},
TypeInfoTable{Exiv2::string, "String", 1},
TypeInfoTable{Exiv2::date, "Date", 8},
TypeInfoTable{Exiv2::time, "Time", 11},
TypeInfoTable{Exiv2::comment, "Comment", 1},
TypeInfoTable{Exiv2::directory, "Directory", 1},
TypeInfoTable{Exiv2::xmpText, "XmpText", 1},
TypeInfoTable{Exiv2::xmpAlt, "XmpAlt", 1},
TypeInfoTable{Exiv2::xmpBag, "XmpBag", 1},
TypeInfoTable{Exiv2::xmpSeq, "XmpSeq", 1},
TypeInfoTable{Exiv2::langAlt, "LangAlt", 1},
} typeInfoTable[] = {
//! Lookup list with information of Exiv2 types
{Exiv2::invalidTypeId, "Invalid", 0},
{Exiv2::unsignedByte, "Byte", 1},
{Exiv2::asciiString, "Ascii", 1},
{Exiv2::unsignedShort, "Short", 2},
{Exiv2::unsignedLong, "Long", 4},
{Exiv2::unsignedRational, "Rational", 8},
{Exiv2::signedByte, "SByte", 1},
{Exiv2::undefined, "Undefined", 1},
{Exiv2::signedShort, "SShort", 2},
{Exiv2::signedLong, "SLong", 4},
{Exiv2::signedRational, "SRational", 8},
{Exiv2::tiffFloat, "Float", 4},
{Exiv2::tiffDouble, "Double", 8},
{Exiv2::tiffIfd, "Ifd", 4},
{Exiv2::string, "String", 1},
{Exiv2::date, "Date", 8},
{Exiv2::time, "Time", 11},
{Exiv2::comment, "Comment", 1},
{Exiv2::directory, "Directory", 1},
{Exiv2::xmpText, "XmpText", 1},
{Exiv2::xmpAlt, "XmpAlt", 1},
{Exiv2::xmpBag, "XmpBag", 1},
{Exiv2::xmpSeq, "XmpSeq", 1},
{Exiv2::langAlt, "LangAlt", 1},
};
} // namespace
@ -70,22 +68,22 @@ constexpr auto typeInfoTable = std::array{
// class member definitions
namespace Exiv2 {
const char* TypeInfo::typeName(TypeId typeId) {
auto tit = std::find(typeInfoTable.begin(), typeInfoTable.end(), typeId);
if (tit == typeInfoTable.end())
auto tit = Exiv2::find(typeInfoTable, typeId);
if (!tit)
return nullptr;
return tit->name_;
}
TypeId TypeInfo::typeId(const std::string& typeName) {
auto tit = std::find(typeInfoTable.begin(), typeInfoTable.end(), typeName);
if (tit == typeInfoTable.end())
auto tit = Exiv2::find(typeInfoTable, typeName);
if (!tit)
return invalidTypeId;
return tit->typeId_;
}
size_t TypeInfo::typeSize(TypeId typeId) {
auto tit = std::find(typeInfoTable.begin(), typeInfoTable.end(), typeId);
if (tit == typeInfoTable.end())
auto tit = Exiv2::find(typeInfoTable, typeId);
if (!tit)
return 0;
return tit->size_;
}
@ -194,9 +192,9 @@ const char* Exiv2::DataBuf::c_str(size_t offset) const {
// free functions
static void checkDataBufBounds(const DataBuf& buf, size_t end) {
enforce<std::invalid_argument>(end <= static_cast<size_t>(std::numeric_limits<long>::max()),
"end of slice too large to be compared with DataBuf bounds.");
enforce<std::out_of_range>(end <= buf.size(), "Invalid slice bounds specified");
Internal::enforce<std::invalid_argument>(end <= static_cast<size_t>(std::numeric_limits<long>::max()),
"end of slice too large to be compared with DataBuf bounds.");
Internal::enforce<std::out_of_range>(end <= buf.size(), "Invalid slice bounds specified");
}
Slice<byte*> makeSlice(DataBuf& buf, size_t begin, size_t end) {

@ -255,7 +255,7 @@ AsciiValue::AsciiValue(const std::string& buf) : StringValueBase(asciiString, bu
int AsciiValue::read(const std::string& buf) {
value_ = buf;
// ensure count>0 and nul terminated # https://github.com/Exiv2/exiv2/issues/1484
if (value_.empty() || value_.at(value_.size() - 1) != '\0') {
if (value_.empty() || value_.back() != '\0') {
value_ += '\0';
}
return 0;
@ -325,8 +325,8 @@ int CommentValue::read(const std::string& comment) {
// Strip quotes (so you can also specify the charset without quotes)
if (!name.empty() && name.front() == '"')
name = name.substr(1);
if (!name.empty() && name[name.length() - 1] == '"')
name = name.substr(0, name.length() - 1);
if (!name.empty() && name.back() == '"')
name.pop_back();
charsetId = CharsetInfo::charsetIdByName(name);
if (charsetId == invalidCharsetId) {
#ifndef SUPPRESS_WARNINGS
@ -391,7 +391,7 @@ std::string CommentValue::comment(const char* encoding) const {
bool bAscii = charsetId() == undefined || charsetId() == ascii;
// # 1266 Remove trailing nulls
if (bAscii && c.find('\0') != std::string::npos) {
c = c.substr(0, c.find('\0'));
c.resize(c.find('\0'));
}
return c;
}
@ -503,8 +503,8 @@ int XmpTextValue::read(const std::string& buf) {
// Strip quotes (so you can also specify the type without quotes)
if (!type.empty() && type.front() == '"')
type = type.substr(1);
if (!type.empty() && type[type.length() - 1] == '"')
type = type.substr(0, type.length() - 1);
if (!type.empty() && type.back() == '"')
type.pop_back();
b.clear();
if (pos != std::string::npos)
b = buf.substr(pos + 1);
@ -670,7 +670,7 @@ int LangAltValue::read(const std::string& buf) {
if (lang.empty() || lang.find('"') != lang.length() - 1)
throw Error(ErrorCode::kerInvalidLangAltValue, buf);
lang = lang.substr(0, lang.length() - 1);
lang.pop_back();
}
if (lang.empty())
@ -954,7 +954,7 @@ size_t TimeValue::copy(byte* buf, ByteOrder /*byteOrder*/) const {
"%02d%02d%02d%1c%02d%02d", time_.hour, time_.minute, time_.second,
plusMinus, abs(time_.tzHour), abs(time_.tzMinute)));
enforce(wrote == 11, Exiv2::ErrorCode::kerUnsupportedTimeFormat);
Internal::enforce(wrote == 11, Exiv2::ErrorCode::kerUnsupportedTimeFormat);
std::memcpy(buf, temp, wrote);
return wrote;
}

@ -312,7 +312,7 @@ void Exiv2::dumpLibraryInfo(std::ostream& os, const std::vector<std::regex>& key
int enable_video = 0;
int use_curl = 0;
#ifdef EXV_HAVE_INTTYPES_H
#if __has_include(<inttypes.h>)
have_inttypes = 1;
#endif
@ -324,21 +324,23 @@ void Exiv2::dumpLibraryInfo(std::ostream& os, const std::vector<std::regex>& key
have_iconv = 1;
#endif
#ifdef EXV_HAVE_LIBINTL_H
#if __has_include(<libintl.h>)
have_libintl = 1;
#endif
#ifdef EXV_HAVE_MEMORY_H
#if __has_include(<memory.h>)
have_memory = 1;
#endif
#ifdef EXV_HAVE_STDBOOL_H
#if __has_include(<stdbool.h>)
have_stdbool = 1;
#endif
#if __has_include(<stdint.h>)
have_stdint = 1;
#endif
#ifdef EXV_HAVE_STDLIB_H
#if __has_include(<stdlib.h>)
have_stdlib = 1;
#endif
@ -346,7 +348,7 @@ void Exiv2::dumpLibraryInfo(std::ostream& os, const std::vector<std::regex>& key
have_strerror_r = 1;
#endif
#ifdef EXV_HAVE_STRINGS_H
#if __has_include(<strings.h>)
have_strings = 1;
#endif
@ -358,19 +360,19 @@ void Exiv2::dumpLibraryInfo(std::ostream& os, const std::vector<std::regex>& key
have_munmap = 1;
#endif
#ifdef EXV_HAVE_SYS_STAT_H
#if __has_include(<sys/stat.h>)
have_sys_stat = 1;
#endif
#ifdef EXV_HAVE_SYS_TYPES_H
#if __has_include(<sys/types.h>)
have_sys_types = 1;
#endif
#ifdef EXV_HAVE_UNISTD_H
#if __has_include(<unistd.h>)
have_unistd = 1;
#endif
#ifdef EXV_HAVE_SYS_MMAN_H
#if __has_include(<sys/mman.h>)
have_sys_mman = 1;
#endif
@ -390,22 +392,6 @@ void Exiv2::dumpLibraryInfo(std::ostream& os, const std::vector<std::regex>& key
adobe_xmpsdk = EXV_ADOBE_XMPSDK;
#endif
#ifdef EXV_HAVE_BOOL
have_bool = 1;
#endif
#ifdef EXV_HAVE_STRINGS
have_strings = 1;
#endif
#ifdef EXV_SYS_TYPES
have_sys_types = 1;
#endif
#ifdef EXV_HAVE_UNISTD
have_unistd = 1;
#endif
#ifdef EXV_ENABLE_BMFF
enable_bmff = 1;
#endif

@ -173,7 +173,7 @@ void WebPImage::doWriteMetadata(BasicIo& outIo) {
has_vp8x = true;
}
if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8X) && !has_size) {
enforce(size_u32 >= 10, Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(size_u32 >= 10, Exiv2::ErrorCode::kerCorruptedMetadata);
has_size = true;
byte size_buf[WEBP_TAG_SIZE];
@ -202,7 +202,7 @@ void WebPImage::doWriteMetadata(BasicIo& outIo) {
}
#endif
if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8) && !has_size) {
enforce(size_u32 >= 10, Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(size_u32 >= 10, Exiv2::ErrorCode::kerCorruptedMetadata);
has_size = true;
byte size_buf[2];
@ -220,13 +220,13 @@ void WebPImage::doWriteMetadata(BasicIo& outIo) {
/* Chunk with lossless image data. */
if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8L) && !has_alpha) {
enforce(size_u32 >= 5, Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(size_u32 >= 5, Exiv2::ErrorCode::kerCorruptedMetadata);
if ((payload.read_uint8(4) & WEBP_VP8X_ALPHA_BIT) == WEBP_VP8X_ALPHA_BIT) {
has_alpha = true;
}
}
if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8L) && !has_size) {
enforce(size_u32 >= 5, Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(size_u32 >= 5, Exiv2::ErrorCode::kerCorruptedMetadata);
has_size = true;
byte size_buf_w[2];
byte size_buf_h[3];
@ -250,13 +250,13 @@ void WebPImage::doWriteMetadata(BasicIo& outIo) {
/* Chunk with animation frame. */
if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_ANMF) && !has_alpha) {
enforce(size_u32 >= 6, Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(size_u32 >= 6, Exiv2::ErrorCode::kerCorruptedMetadata);
if ((payload.read_uint8(5) & 0x2) == 0x2) {
has_alpha = true;
}
}
if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_ANMF) && !has_size) {
enforce(size_u32 >= 12, Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(size_u32 >= 12, Exiv2::ErrorCode::kerCorruptedMetadata);
has_size = true;
byte size_buf[WEBP_TAG_SIZE];
@ -294,7 +294,7 @@ void WebPImage::doWriteMetadata(BasicIo& outIo) {
io_->seek(+1, BasicIo::cur); // skip pad
if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8X)) {
enforce(size_u32 >= 1, Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(size_u32 >= 1, Exiv2::ErrorCode::kerCorruptedMetadata);
if (has_icc) {
const uint8_t x = payload.read_uint8(0);
payload.write_uint8(0, x | WEBP_VP8X_ICC_BIT);
@ -477,7 +477,7 @@ void WebPImage::readMetadata() {
io_->readOrThrow(data, WEBP_TAG_SIZE * 3, Exiv2::ErrorCode::kerCorruptedMetadata);
const uint32_t filesize = Safe::add(Exiv2::getULong(data + WEBP_TAG_SIZE, littleEndian), 8U);
enforce(filesize <= io_->size(), Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(filesize <= io_->size(), Exiv2::ErrorCode::kerCorruptedMetadata);
WebPImage::decodeChunks(filesize);
@ -500,15 +500,15 @@ void WebPImage::decodeChunks(uint32_t filesize) {
const uint32_t size = Exiv2::getULong(size_buff, littleEndian);
// Check that `size` is within bounds.
enforce(io_->tell() <= filesize, Exiv2::ErrorCode::kerCorruptedMetadata);
enforce(size <= (filesize - io_->tell()), Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(io_->tell() <= filesize, Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(size <= (filesize - io_->tell()), Exiv2::ErrorCode::kerCorruptedMetadata);
DataBuf payload(size);
if (payload.empty()) {
io_->seek(size, BasicIo::cur);
} else if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8X) && !has_canvas_data) {
enforce(size >= 10, Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(size >= 10, Exiv2::ErrorCode::kerCorruptedMetadata);
has_canvas_data = true;
byte size_buf[WEBP_TAG_SIZE];
@ -525,7 +525,7 @@ void WebPImage::decodeChunks(uint32_t filesize) {
size_buf[3] = 0;
pixelHeight_ = Exiv2::getULong(size_buf, littleEndian) + 1;
} else if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8) && !has_canvas_data) {
enforce(size >= 10, Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(size >= 10, Exiv2::ErrorCode::kerCorruptedMetadata);
has_canvas_data = true;
io_->readOrThrow(payload.data(), payload.size(), Exiv2::ErrorCode::kerCorruptedMetadata);
@ -543,7 +543,7 @@ void WebPImage::decodeChunks(uint32_t filesize) {
size_buf[3] = 0;
pixelHeight_ = Exiv2::getULong(size_buf, littleEndian) & 0x3fff;
} else if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8L) && !has_canvas_data) {
enforce(size >= 5, Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(size >= 5, Exiv2::ErrorCode::kerCorruptedMetadata);
has_canvas_data = true;
byte size_buf_w[2];
@ -562,7 +562,7 @@ void WebPImage::decodeChunks(uint32_t filesize) {
size_buf_h[1] = ((size_buf_h[1] >> 6) & 0x3) | ((size_buf_h[2] & 0xFU) << 0x2);
pixelHeight_ = Exiv2::getUShort(size_buf_h, littleEndian) + 1;
} else if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_ANMF) && !has_canvas_data) {
enforce(size >= 12, Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(size >= 12, Exiv2::ErrorCode::kerCorruptedMetadata);
has_canvas_data = true;
byte size_buf[WEBP_TAG_SIZE];
@ -752,14 +752,14 @@ void WebPImage::inject_VP8X(BasicIo& iIo, bool has_xmp, bool has_exif, bool has_
}
/* set width - stored in 24bits*/
enforce(width > 0, Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(width > 0, Exiv2::ErrorCode::kerCorruptedMetadata);
uint32_t w = width - 1;
data[4] = w & 0xFF;
data[5] = (w >> 8) & 0xFF;
data[6] = (w >> 16) & 0xFF;
/* set height - stored in 24bits */
enforce(width > 0, Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(width > 0, Exiv2::ErrorCode::kerCorruptedMetadata);
uint32_t h = height - 1;
data[7] = h & 0xFF;
data[8] = (h >> 8) & 0xFF;

@ -585,11 +585,8 @@ static XMP_Status nsDumper(void* refCon, XMP_StringPtr buffer, XMP_StringLen buf
bool bNS = out.find(':') != std::string::npos && !bURI;
// pop trailing ':' on a namespace
if (bNS && !out.empty()) {
std::size_t length = out.length();
if (out[length - 1] == ':')
out = out.substr(0, length - 1);
}
if (bNS && !out.empty() && out.back() == ':')
out.pop_back();
if (bURI || bNS) {
auto p = static_cast<std::map<std::string, std::string>*>(refCon);
@ -706,7 +703,7 @@ int XmpParser::decode(XmpData& xmpData, const std::string& xmpPacket) {
bool ret = SXMPMeta::GetNamespacePrefix(schemaNs.c_str(), &prefix);
if (!ret)
throw Error(ErrorCode::kerSchemaNamespaceNotRegistered, schemaNs);
prefix = prefix.substr(0, prefix.size() - 1);
prefix.pop_back();
XmpProperties::registerNs(schemaNs, prefix);
}
continue;

@ -5,10 +5,16 @@
#include <error.hpp> // Need to include this header for the Exiv2::Error exception
#include <gtest/gtest.h>
#if __has_include(<filesystem>)
#include <filesystem>
namespace fs = std::filesystem;
#else
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#endif
using namespace Exiv2;
namespace fs = std::filesystem;
TEST(TheImageFactory, createsInstancesForFewSupportedTypesInMemory) {
// Note that the constructor of these Image classes take an 'create' argument

@ -9,21 +9,23 @@
TEST(enforce, errMessageCanBeRetrievedFromErrorException) {
try {
enforce(false, Exiv2::ErrorCode::kerErrorMessage, "an error occurred");
Exiv2::Internal::enforce(false, Exiv2::ErrorCode::kerErrorMessage, "an error occurred");
} catch (const Exiv2::Error& e) {
ASSERT_STREQ(e.what(), "an error occurred");
}
}
TEST(enforce, withTrueConditionDoesNotThrow) {
ASSERT_NO_THROW(enforce(true, Exiv2::ErrorCode::kerErrorMessage));
ASSERT_NO_THROW(Exiv2::Internal::enforce(true, Exiv2::ErrorCode::kerErrorMessage));
}
TEST(enforce, withFalseConditionThrows) {
ASSERT_THROW(enforce(false, Exiv2::ErrorCode::kerErrorMessage), Exiv2::Error);
ASSERT_THROW(enforce(false, Exiv2::ErrorCode::kerErrorMessage, "error message"), Exiv2::Error);
ASSERT_THROW(enforce(false, Exiv2::ErrorCode::kerDataSourceOpenFailed, "path", "strerror"), Exiv2::Error);
ASSERT_THROW(enforce(false, Exiv2::ErrorCode::kerCallFailed, "path", "strerror", "function"), Exiv2::Error);
ASSERT_THROW(enforce(false, Exiv2::ErrorCode::kerMallocFailed), Exiv2::Error);
ASSERT_THROW(enforce<std::overflow_error>(false, "error message"), std::overflow_error);
ASSERT_THROW(Exiv2::Internal::enforce(false, Exiv2::ErrorCode::kerErrorMessage), Exiv2::Error);
ASSERT_THROW(Exiv2::Internal::enforce(false, Exiv2::ErrorCode::kerErrorMessage, "error message"), Exiv2::Error);
ASSERT_THROW(Exiv2::Internal::enforce(false, Exiv2::ErrorCode::kerDataSourceOpenFailed, "path", "strerror"),
Exiv2::Error);
ASSERT_THROW(Exiv2::Internal::enforce(false, Exiv2::ErrorCode::kerCallFailed, "path", "strerror", "function"),
Exiv2::Error);
ASSERT_THROW(Exiv2::Internal::enforce(false, Exiv2::ErrorCode::kerMallocFailed), Exiv2::Error);
ASSERT_THROW(Exiv2::Internal::enforce<std::overflow_error>(false, "error message"), std::overflow_error);
}

@ -7,13 +7,18 @@
// Auxiliary headers
#include <cerrno>
#include <cstdio>
#include <filesystem>
#include <fstream>
#include <stdexcept>
#include <gtest/gtest.h>
#if __has_include(<filesystem>)
#include <filesystem>
namespace fs = std::filesystem;
#else
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#endif
using namespace Exiv2;

@ -11,11 +11,8 @@
#include "XMP_Environment.h"
#include <stddef.h>
#if XMP_MacBuild // ! No stdint.h on Windows and some UNIXes.
#include <stdint.h>
#endif
#include <stddef.h>
#include <stdint.h>
#if __cplusplus
extern "C" {
@ -34,31 +31,15 @@ extern "C" {
// case only the declarations of the XMP_... types needs to change, not all of the uses. These
// types are used where fixed sizes are required in order to have a known ABI for a DLL build.
#if XMP_MacBuild
typedef int8_t XMP_Int8;
typedef int16_t XMP_Int16;
typedef int32_t XMP_Int32;
typedef int64_t XMP_Int64;
typedef uint8_t XMP_Uns8;
typedef uint16_t XMP_Uns16;
typedef uint32_t XMP_Uns32;
typedef uint64_t XMP_Uns64;
typedef int8_t XMP_Int8;
typedef int16_t XMP_Int16;
typedef int32_t XMP_Int32;
typedef int64_t XMP_Int64;
#else
typedef signed char XMP_Int8;
typedef signed short XMP_Int16;
typedef signed long XMP_Int32;
typedef signed long long XMP_Int64;
typedef unsigned char XMP_Uns8;
typedef unsigned short XMP_Uns16;
typedef unsigned long XMP_Uns32;
typedef unsigned long long XMP_Uns64;
#endif
typedef uint8_t XMP_Uns8;
typedef uint16_t XMP_Uns16;
typedef uint32_t XMP_Uns32;
typedef uint64_t XMP_Uns64;
typedef XMP_Uns8 XMP_Bool;

@ -38,7 +38,7 @@
# define _WIN64 1
#endif
#if defined WIN32
#if defined _WIN32
# define WIN_ENV 1
/* Todo: How to correctly recognize a Mac platform? */
#elif defined macintosh || defined MACOS_CLASSIC || defined MACOS_X_UNIX || defined MACOS_X || defined MACOS || defined(__APPLE__)

@ -114,7 +114,7 @@ extern WXMP_Result void_wResult;
#define WtoXMPDocOps_Ref(docRef) *((const XMPDocOps *)(docRef))
#define WtoXMPDocOps_Ptr(docRef) (((docRef) == 0) ? 0 : (XMPDocOps *)(docRef))
#define IgnoreParam(p) voidVoidPtr = (void*)&p
#define IgnoreParam(p) (void)p
// =================================================================================================
// Version info

Loading…
Cancel
Save