diff --git a/config/config.h.in b/config/config.h.in index f71f5556..1a918e98 100644 --- a/config/config.h.in +++ b/config/config.h.in @@ -37,6 +37,15 @@ /* Define to 1 if you have the header file. */ #undef HAVE_LIBINTL_H +/* Define to 1 if you have the `iconv' function. */ +#undef HAVE_ICONV + +/* Define to `const' or to empty, depending on the second argument of `iconv'. */ +#undef ICONV_CONST + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIBINTL_H + /* Define to 1 if your system has a GNU libc compatible `malloc' function, and to 0 otherwise. */ #undef HAVE_MALLOC diff --git a/config/config.mk.in b/config/config.mk.in index f7d5a57b..fdf8b98b 100644 --- a/config/config.mk.in +++ b/config/config.mk.in @@ -55,7 +55,7 @@ CPPFLAGS = -I. @CPPFLAGS@ -DEXV_LOCALEDIR=\"$(localedir)\" # Linker flags and libraries LDFLAGS = @LDFLAGS@ -LIBS = @LTLIBINTL@ @LIBS@ +LIBS = @LTLIBINTL@ @LTLIBICONV@ @LIBS@ # Suffix of executables EXEEXT := @EXEEXT@ diff --git a/config/configure.ac b/config/configure.ac index bb6b279c..4a553a72 100644 --- a/config/configure.ac +++ b/config/configure.ac @@ -30,14 +30,6 @@ AC_PROG_RANLIB # --------------------------------------------------------------------------- AM_GNU_GETTEXT([external]) -#dnl We cannot use AC_DEFINE_UNQUOTED() for these definitions, as -#dnl we require make to do insert the proper $(datadir) value -#localedir="\$(datadir)/locale" -#AC_SUBST(localedir) -#AM_CPPFLAGS="$CPPFLAGS" -#AM_CPPFLAGS="$AM_CPPFLAGS -DLOCALEDIR=\\\"${localedir}\\\"" -#AC_SUBST(AM_CPPFLAGS) - # --------------------------------------------------------------------------- # Libtool support # --------------------------------------------------------------------------- @@ -50,12 +42,13 @@ AC_CHECK_LIBM() LIBS="$LIBS $LIBM" CHECK_ZLIB() AC_SUBST(HAVE_LIBZ,$HAVE_LIBZ) +AM_ICONV # --------------------------------------------------------------------------- # Checks for header files. # --------------------------------------------------------------------------- AC_HEADER_STDC -AC_CHECK_HEADERS([libintl.h malloc.h stdint.h stdlib.h string.h unistd.h wchar.h sys/mman.h]) +AC_CHECK_HEADERS([libintl.h locale.h malloc.h stdint.h stdlib.h string.h unistd.h sys/mman.h utime.h]) # --------------------------------------------------------------------------- # Checks for typedefs, structures, and compiler characteristics. @@ -66,6 +59,11 @@ AC_C_INLINE AC_TYPE_PID_T AC_TYPE_SIZE_T AC_STRUCT_TM +AC_TYPE_UINT8_T +AC_TYPE_UINT16_T +AC_TYPE_UINT32_T +AC_TYPE_INT16_T +AC_TYPE_INT32_T # --------------------------------------------------------------------------- # Checks for library functions. @@ -74,6 +72,7 @@ AC_FUNC_ALLOCA AC_FUNC_MALLOC AC_FUNC_MEMCMP AC_FUNC_MKTIME +AC_FUNC_MMAP AC_FUNC_REALLOC AC_FUNC_STAT AC_FUNC_STRERROR_R diff --git a/src/tags.cpp b/src/tags.cpp index f1d3b4a7..d133b2a6 100644 --- a/src/tags.cpp +++ b/src/tags.cpp @@ -32,9 +32,10 @@ EXIV2_RCSID("@(#) $Id$") // ***************************************************************************** // included header files +#include "types.hpp" #include "tags.hpp" #include "error.hpp" -#include "types.hpp" +#include "futils.hpp" #include "ifd.hpp" #include "value.hpp" #include "makernote.hpp" @@ -49,6 +50,10 @@ EXIV2_RCSID("@(#) $Id$") #include #include +#ifdef EXV_HAVE_ICONV +# include +#endif + // ***************************************************************************** // class member definitions namespace Exiv2 { @@ -459,6 +464,21 @@ namespace Exiv2 { N_("Contains four ASCII characters representing the TIFF/EP standard " "version of a TIFF/EP file, eg '1', '0', '0', '0'"), ifd0Id, otherTags, unsignedByte, printValue), // TIFF/EP Tag + TagInfo(0x9c9b, "XPTitle", N_("Windows Title"), + N_("Title tag used by Windows, encoded in UCS2"), + ifd0Id, otherTags, unsignedByte, printUcs2), // Windows Tag + TagInfo(0x9c9c, "XPComment", N_("Windows Comment"), + N_("Comment tag used by Windows, encoded in UCS2"), + ifd0Id, otherTags, unsignedByte, printUcs2), // Windows Tag + TagInfo(0x9c9d, "XPAuthor", N_("Windows Author"), + N_("Author tag used by Windows, encoded in UCS2"), + ifd0Id, otherTags, unsignedByte, printUcs2), // Windows Tag + TagInfo(0x9c9e, "XPKeywords", N_("Windows Keywords"), + N_("Keywords tag used by Windows, encoded in UCS2"), + ifd0Id, otherTags, unsignedByte, printUcs2), // Windows Tag + TagInfo(0x9c9f, "XPSubject", N_("Windows Subject"), + N_("Subject tag used by Windows, encoded in UCS2"), + ifd0Id, otherTags, unsignedByte, printUcs2), // Windows Tag // End of list marker TagInfo(0xffff, "(UnknownIfdTag)", N_("Unknown IFD tag"), N_("Unknown IFD tag"), @@ -1645,6 +1665,64 @@ namespace Exiv2 { return os; } // printDegrees + std::ostream& printUcs2(std::ostream& os, const Value& value) + { +#ifdef EXV_HAVE_ICONV + bool go = true; + iconv_t cd = (iconv_t)(-1); + if (value.typeId() != unsignedByte) { + go = false; + } + if (go) { + cd = iconv_open("UTF-8", "UCS-2LE"); + if (cd == (iconv_t)(-1)) { +#ifndef SUPPRESS_WARNINGS + std::cerr << "Warning: iconv_open: " << strError() << "\n"; +#endif + go = false; + } + } + if (go) { + DataBuf ib(value.size()); + value.copy(ib.pData_, invalidByteOrder); + DataBuf ob(value.size()); + char* outptr = reinterpret_cast(ob.pData_); + const char* outbuf = outptr; + size_t outbytesleft = ob.size_; + EXV_ICONV_CONST char* inbuf + = reinterpret_cast(ib.pData_); + size_t inbytesleft = ib.size_; + size_t rc = iconv(cd, + &inbuf, + &inbytesleft, + &outptr, + &outbytesleft); + if (rc == size_t(-1)) { +#ifndef SUPPRESS_WARNINGS + std::cerr << "Warning: iconv: " + << strError() + << " inbytesleft = " << inbytesleft << "\n"; +#endif + go = false; + } + if (go) { + // Todo: What if outbytesleft == 0 + os << std::string(outbuf, outptr-outbuf); + } + } + if (cd != (iconv_t)(-1)) { + iconv_close(cd); + } + if (!go) { + os << value; + } +#else // !EXV_HAVE_ICONV + os << value; +#endif // EXV_HAVE_ICONV + return os; + + } // printUcs2 + std::ostream& print0x0006(std::ostream& os, const Value& value) { std::ostringstream oss; diff --git a/src/tags.hpp b/src/tags.hpp index a1df4b37..b7c1ee56 100644 --- a/src/tags.hpp +++ b/src/tags.hpp @@ -442,6 +442,8 @@ namespace Exiv2 { std::ostream& printFloat(std::ostream& os, const Value& value); //! Print a longitude or latitude value std::ostream& printDegrees(std::ostream& os, const Value& value); + //! Print function converting from UCS-2LE to UTF-8 + std::ostream& printUcs2(std::ostream& os, const Value& value); //! Print GPS altitude std::ostream& print0x0006(std::ostream& os, const Value& value); diff --git a/test/bugfixes-test.sh b/test/bugfixes-test.sh index b47b11ef..05bcfc1b 100755 --- a/test/bugfixes-test.sh +++ b/test/bugfixes-test.sh @@ -54,6 +54,10 @@ num=447 # Problem only visible in Valgrind filename=`prep_file $num` $binpath/exiv2 -pi $filename +num=460 +filename=`prep_file $num` +$binpath/exiv2 -pt $filename + num=479 filename=`prep_file $num` $binpath/exiv2 -pt $filename diff --git a/test/data/bugfixes-test.out b/test/data/bugfixes-test.out index f1b3286f..3e9451f2 100644 --- a/test/data/bugfixes-test.out +++ b/test/data/bugfixes-test.out @@ -210,6 +210,12 @@ Warning: Exif tag 0x9286 has invalid Exif type 14; using 7 (undefined). Iptc.Application2.Caption String 0 Iptc.Application2.DateCreated Date 8 2005-08-09 Iptc.Application2.TimeCreated Time 11 01:28:31-07:00 +------> Bug 460 <------- +Exif.Image.XPTitle Byte 40 Titel und ähnliches +Exif.Image.XPComment Byte 46 And a standard comment +Exif.Image.XPAuthor Byte 44 Українська (Russian?) +Exif.Image.XPKeywords Byte 30 עברית (Hebrew) +Exif.Image.XPSubject Byte 32 తెలుగు (Telugu) ------> Bug 479 <------- Warning: IFD0: Pointer to next IFD is out of bounds; ignored. Exif.Image.ImageWidth Short 1 3173 diff --git a/test/data/exiv2-bug460.jpg b/test/data/exiv2-bug460.jpg new file mode 100644 index 00000000..d205de80 Binary files /dev/null and b/test/data/exiv2-bug460.jpg differ