[SCM] exiv2 packaging branch, master, updated. debian/0.25-3.1-3734-gdcbc29a
Maximiliano Curia
maxy at moszumanska.debian.org
Thu Jul 13 17:42:27 UTC 2017
Gitweb-URL: http://git.debian.org/?p=pkg-kde/kde-extras/exiv2.git;a=commitdiff;h=3b13ab8
The following commit has been merged in the master branch:
commit 3b13ab8717c2597be3ee6ff2521d4290f7a632b4
Author: vog <vog at notjusthosting.com>
Date: Fri Jun 24 17:33:17 2011 +0000
#689: Make private implementation pf EpsImage really private
---
src/epsimage.cpp | 769 ++++++++++++++++++++++++++++---------------------------
src/epsimage.hpp | 25 --
2 files changed, 395 insertions(+), 399 deletions(-)
diff --git a/src/epsimage.cpp b/src/epsimage.cpp
index a67e3b7..6698875 100644
--- a/src/epsimage.cpp
+++ b/src/epsimage.cpp
@@ -55,134 +55,352 @@ EXIV2_RCSID("@(#) $Id: epsimage.cpp $")
#include <sstream>
#include <string>
-// signature of DOS EPS
-static const std::string epsDosSignature = "\xc5\xd0\xd3\xc6";
-
-// first line of EPS
-static const std::string epsFirstLine[] = {
- "%!PS-Adobe-3.0 EPSF-3.0",
- "%!PS-Adobe-3.0 EPSF-3.0 ", // OpenOffice
- "%!PS-Adobe-3.1 EPSF-3.0", // Illustrator
-};
-
-// blank EPS file
-static const std::string epsBlank = "%!PS-Adobe-3.0 EPSF-3.0
"
- "%%BoundingBox: 0 0 0 0
";
-
-// list of all valid XMP headers
-static const struct { std::string header; std::string charset; } xmpHeadersDef[] = {
-
- // We do not enforce the trailing "?>" here, because the XMP specification
- // permits additional attributes after begin="..." and id="...".
-
- // normal headers
- {"<?xpacket begin=\"\xef\xbb\xbf\" id=\"W5M0MpCehiHzreSzNTczkc9d\"", "UTF-8"},
- {"<?xpacket begin=\"\xef\xbb\xbf\" id='W5M0MpCehiHzreSzNTczkc9d'", "UTF-8"},
- {"<?xpacket begin='\xef\xbb\xbf' id=\"W5M0MpCehiHzreSzNTczkc9d\"", "UTF-8"},
- {"<?xpacket begin='\xef\xbb\xbf' id='W5M0MpCehiHzreSzNTczkc9d'", "UTF-8"},
- {"<?xpacket begin=\"\xef\xbb\xbf\" id=\"W5M0MpCehiHzreSzNTczkc9d\"", "UTF-16BE"},
- {"<?xpacket begin=\"\xef\xbb\xbf\" id='W5M0MpCehiHzreSzNTczkc9d'", "UTF-16BE"},
- {"<?xpacket begin='\xef\xbb\xbf' id=\"W5M0MpCehiHzreSzNTczkc9d\"", "UTF-16BE"},
- {"<?xpacket begin='\xef\xbb\xbf' id='W5M0MpCehiHzreSzNTczkc9d'", "UTF-16BE"},
- {"<?xpacket begin=\"\xef\xbb\xbf\" id=\"W5M0MpCehiHzreSzNTczkc9d\"", "UTF-16LE"},
- {"<?xpacket begin=\"\xef\xbb\xbf\" id='W5M0MpCehiHzreSzNTczkc9d'", "UTF-16LE"},
- {"<?xpacket begin='\xef\xbb\xbf' id=\"W5M0MpCehiHzreSzNTczkc9d\"", "UTF-16LE"},
- {"<?xpacket begin='\xef\xbb\xbf' id='W5M0MpCehiHzreSzNTczkc9d'", "UTF-16LE"},
- {"<?xpacket begin=\"\xef\xbb\xbf\" id=\"W5M0MpCehiHzreSzNTczkc9d\"", "UTF-32BE"},
- {"<?xpacket begin=\"\xef\xbb\xbf\" id='W5M0MpCehiHzreSzNTczkc9d'", "UTF-32BE"},
- {"<?xpacket begin='\xef\xbb\xbf' id=\"W5M0MpCehiHzreSzNTczkc9d\"", "UTF-32BE"},
- {"<?xpacket begin='\xef\xbb\xbf' id='W5M0MpCehiHzreSzNTczkc9d'", "UTF-32BE"},
- {"<?xpacket begin=\"\xef\xbb\xbf\" id=\"W5M0MpCehiHzreSzNTczkc9d\"", "UTF-32LE"},
- {"<?xpacket begin=\"\xef\xbb\xbf\" id='W5M0MpCehiHzreSzNTczkc9d'", "UTF-32LE"},
- {"<?xpacket begin='\xef\xbb\xbf' id=\"W5M0MpCehiHzreSzNTczkc9d\"", "UTF-32LE"},
- {"<?xpacket begin='\xef\xbb\xbf' id='W5M0MpCehiHzreSzNTczkc9d'", "UTF-32LE"},
-
- // deprecated headers (empty begin attribute, UTF-8 only)
- {"<?xpacket begin=\"\" id=\"W5M0MpCehiHzreSzNTczkc9d\"", "UTF-8"},
- {"<?xpacket begin=\"\" id='W5M0MpCehiHzreSzNTczkc9d'", "UTF-8"},
- {"<?xpacket begin='' id=\"W5M0MpCehiHzreSzNTczkc9d\"", "UTF-8"},
- {"<?xpacket begin='' id='W5M0MpCehiHzreSzNTczkc9d'", "UTF-8"},
-};
-
-// list of all valid XMP trailers
-static const struct { std::string trailer; bool readOnly; } xmpTrailersDef[] = {
-
- // We do not enforce the trailing "?>" here, because the XMP specification
- // permits additional attributes after end="...".
-
- {"<?xpacket end=\"r\"", true},
- {"<?xpacket end='r'", true},
- {"<?xpacket end=\"w\"", false},
- {"<?xpacket end='w'", false},
-};
-
-// closing part of all valid XMP trailers
-static const std::string xmpTrailerEndDef = "?>";
-
// *****************************************************************************
-// class member definitions
-namespace Exiv2
-{
-
- EpsImage::EpsImage(BasicIo::AutoPtr io, bool create)
- : Image(ImageType::eps, mdXmp, io)
+namespace {
+
+ using namespace Exiv2;
+
+ // signature of DOS EPS
+ static const std::string epsDosSignature = "\xc5\xd0\xd3\xc6";
+
+ // first line of EPS
+ static const std::string epsFirstLine[] = {
+ "%!PS-Adobe-3.0 EPSF-3.0",
+ "%!PS-Adobe-3.0 EPSF-3.0 ", // OpenOffice
+ "%!PS-Adobe-3.1 EPSF-3.0", // Illustrator
+ };
+
+ // blank EPS file
+ static const std::string epsBlank = "%!PS-Adobe-3.0 EPSF-3.0
"
+ "%%BoundingBox: 0 0 0 0
";
+
+ // list of all valid XMP headers
+ static const struct { std::string header; std::string charset; } xmpHeadersDef[] = {
+
+ // We do not enforce the trailing "?>" here, because the XMP specification
+ // permits additional attributes after begin="..." and id="...".
+
+ // normal headers
+ {"<?xpacket begin=\"\xef\xbb\xbf\" id=\"W5M0MpCehiHzreSzNTczkc9d\"", "UTF-8"},
+ {"<?xpacket begin=\"\xef\xbb\xbf\" id='W5M0MpCehiHzreSzNTczkc9d'", "UTF-8"},
+ {"<?xpacket begin='\xef\xbb\xbf' id=\"W5M0MpCehiHzreSzNTczkc9d\"", "UTF-8"},
+ {"<?xpacket begin='\xef\xbb\xbf' id='W5M0MpCehiHzreSzNTczkc9d'", "UTF-8"},
+ {"<?xpacket begin=\"\xef\xbb\xbf\" id=\"W5M0MpCehiHzreSzNTczkc9d\"", "UTF-16BE"},
+ {"<?xpacket begin=\"\xef\xbb\xbf\" id='W5M0MpCehiHzreSzNTczkc9d'", "UTF-16BE"},
+ {"<?xpacket begin='\xef\xbb\xbf' id=\"W5M0MpCehiHzreSzNTczkc9d\"", "UTF-16BE"},
+ {"<?xpacket begin='\xef\xbb\xbf' id='W5M0MpCehiHzreSzNTczkc9d'", "UTF-16BE"},
+ {"<?xpacket begin=\"\xef\xbb\xbf\" id=\"W5M0MpCehiHzreSzNTczkc9d\"", "UTF-16LE"},
+ {"<?xpacket begin=\"\xef\xbb\xbf\" id='W5M0MpCehiHzreSzNTczkc9d'", "UTF-16LE"},
+ {"<?xpacket begin='\xef\xbb\xbf' id=\"W5M0MpCehiHzreSzNTczkc9d\"", "UTF-16LE"},
+ {"<?xpacket begin='\xef\xbb\xbf' id='W5M0MpCehiHzreSzNTczkc9d'", "UTF-16LE"},
+ {"<?xpacket begin=\"\xef\xbb\xbf\" id=\"W5M0MpCehiHzreSzNTczkc9d\"", "UTF-32BE"},
+ {"<?xpacket begin=\"\xef\xbb\xbf\" id='W5M0MpCehiHzreSzNTczkc9d'", "UTF-32BE"},
+ {"<?xpacket begin='\xef\xbb\xbf' id=\"W5M0MpCehiHzreSzNTczkc9d\"", "UTF-32BE"},
+ {"<?xpacket begin='\xef\xbb\xbf' id='W5M0MpCehiHzreSzNTczkc9d'", "UTF-32BE"},
+ {"<?xpacket begin=\"\xef\xbb\xbf\" id=\"W5M0MpCehiHzreSzNTczkc9d\"", "UTF-32LE"},
+ {"<?xpacket begin=\"\xef\xbb\xbf\" id='W5M0MpCehiHzreSzNTczkc9d'", "UTF-32LE"},
+ {"<?xpacket begin='\xef\xbb\xbf' id=\"W5M0MpCehiHzreSzNTczkc9d\"", "UTF-32LE"},
+ {"<?xpacket begin='\xef\xbb\xbf' id='W5M0MpCehiHzreSzNTczkc9d'", "UTF-32LE"},
+
+ // deprecated headers (empty begin attribute, UTF-8 only)
+ {"<?xpacket begin=\"\" id=\"W5M0MpCehiHzreSzNTczkc9d\"", "UTF-8"},
+ {"<?xpacket begin=\"\" id='W5M0MpCehiHzreSzNTczkc9d'", "UTF-8"},
+ {"<?xpacket begin='' id=\"W5M0MpCehiHzreSzNTczkc9d\"", "UTF-8"},
+ {"<?xpacket begin='' id='W5M0MpCehiHzreSzNTczkc9d'", "UTF-8"},
+ };
+
+ // list of all valid XMP trailers
+ static const struct { std::string trailer; bool readOnly; } xmpTrailersDef[] = {
+
+ // We do not enforce the trailing "?>" here, because the XMP specification
+ // permits additional attributes after end="...".
+
+ {"<?xpacket end=\"r\"", true},
+ {"<?xpacket end='r'", true},
+ {"<?xpacket end=\"w\"", false},
+ {"<?xpacket end='w'", false},
+ };
+
+ // closing part of all valid XMP trailers
+ static const std::string xmpTrailerEndDef = "?>";
+
+ //! Write data into temp file, taking care of errors
+ static void writeTemp(BasicIo& tempIo, const char* data, size_t size)
{
- //LogMsg::setLevel(LogMsg::debug);
- if (create) {
- if (io_->open() == 0) {
- #ifdef DEBUG
- EXV_DEBUG << "Exiv2::EpsImage:: Creating blank EPS image
";
- #endif
- IoCloser closer(*io_);
- if (io_->write(reinterpret_cast<const byte*>(epsBlank.data()), static_cast<long>(epsBlank.size())) != static_cast<long>(epsBlank.size())) {
- #ifndef SUPPRESS_WARNINGS
- EXV_WARNING << "Failed to write blank EPS image.
";
- #endif
- throw Error(21);
- }
- }
+ if (size == 0) return;
+ if (tempIo.write(reinterpret_cast<const byte*>(data), static_cast<long>(size)) != static_cast<long>(size)) {
+ #ifndef SUPPRESS_WARNINGS
+ EXV_WARNING << "Failed to write to temporary file.
";
+ #endif
+ throw Error(21);
}
}
- std::string EpsImage::mimeType() const
+ //! Write data into temp file, taking care of errors
+ static void writeTemp(BasicIo& tempIo, const std::string &data)
{
- return "application/postscript";
+ writeTemp(tempIo, data.data(), data.size());
}
- void EpsImage::setComment(const std::string& /*comment*/)
+ //! Check whether a string has a certain beginning
+ static bool startsWith(const std::string& s, const std::string& start)
{
- throw Error(32, "Image comment", "EPS");
+ return s.size() >= start.size() && memcmp(s.data(), start.data(), start.size()) == 0;
}
- void EpsImage::readMetadata()
+ //! Check whether a string contains only white space characters
+ static bool onlyWhitespaces(const std::string& s)
{
- doReadWriteMetadata(/* write = */ false);
+ // According to the DSC 3.0 specification, 4.4 Parsing Rules,
+ // only spaces and tabs are considered to be white space characters.
+ return s.find_first_not_of(" ") == std::string::npos;
}
- void EpsImage::writeMetadata()
+ //! Convert an integer of type size_t to a decimal string
+ static std::string toString(size_t size)
+ {
+ std::ostringstream stream;
+ stream << size;
+ return stream.str();
+ }
+
+ //! Read the next line of a buffer, allow for changing line ending style
+ static size_t readLine(std::string& line, const char* data, size_t startPos, size_t size)
+ {
+ line.clear();
+ size_t pos = startPos;
+ // step through line
+ while (pos < size && data[pos] != '
' && data[pos] != '
') {
+ line += data[pos];
+ pos++;
+ }
+ // skip line ending, if present
+ if (pos >= size) return pos;
+ pos++;
+ if (pos >= size) return pos;
+ if (data[pos - 1] == '
' && data[pos] == '
') pos++;
+ return pos;
+ }
+
+ //! Read the previous line of a buffer, allow for changing line ending style
+ static size_t readPrevLine(std::string& line, const char* data, size_t startPos, size_t size)
+ {
+ line.clear();
+ size_t pos = startPos;
+ if (pos > size) return pos;
+ // skip line ending of previous line, if present
+ if (pos <= 0) return pos;
+ if (data[pos - 1] == '
' || data[pos - 1] == '
') {
+ pos--;
+ if (pos <= 0) return pos;
+ if (data[pos - 1] == '
' && data[pos] == '
') {
+ pos--;
+ if (pos <= 0) return pos;
+ }
+ }
+ // step through previous line
+ while (pos >= 1 && data[pos - 1] != '
' && data[pos - 1] != '
') {
+ pos--;
+ line += data[pos];
+ }
+ std::reverse(line.begin(), line.end());
+ return pos;
+ }
+
+ //! Find an XMP block
+ static void findXmp(size_t& xmpPos, size_t& xmpSize, const char* data, size_t size, bool write)
{
- doReadWriteMetadata(/* write = */ true);
+ // prepare list of valid XMP headers
+ std::vector<std::pair<std::string, std::string> > xmpHeaders;
+ for (size_t i = 0; i < (sizeof xmpHeadersDef) / (sizeof *xmpHeadersDef); i++) {
+ const std::string &charset = xmpHeadersDef[i].charset;
+ std::string header(xmpHeadersDef[i].header);
+ if (!convertStringCharset(header, "UTF-8", charset.c_str())) {
+ throw Error(28, charset);
+ }
+ xmpHeaders.push_back(make_pair(header, charset));
+ }
+
+ // search for valid XMP header
+ xmpSize = 0;
+ for (xmpPos = 0; xmpPos < size; xmpPos++) {
+ if (data[xmpPos] != '\x00' && data[xmpPos] != '<') continue;
+ for (size_t i = 0; i < xmpHeaders.size(); i++) {
+ const std::string &header = xmpHeaders[i].first;
+ if (xmpPos + header.size() > size) continue;
+ if (memcmp(data + xmpPos, header.data(), header.size()) != 0) continue;
+ #ifdef DEBUG
+ EXV_DEBUG << "findXmp: Found XMP header at position: " << xmpPos << "
";
+ #endif
+
+ // prepare list of valid XMP trailers in the charset of the header
+ const std::string &charset = xmpHeaders[i].second;
+ std::vector<std::pair<std::string, bool> > xmpTrailers;
+ for (size_t j = 0; j < (sizeof xmpTrailersDef) / (sizeof *xmpTrailersDef); j++) {
+ std::string trailer(xmpTrailersDef[j].trailer);
+ if (!convertStringCharset(trailer, "UTF-8", charset.c_str())) {
+ throw Error(28, charset);
+ }
+ xmpTrailers.push_back(make_pair(trailer, xmpTrailersDef[j].readOnly));
+ }
+ std::string xmpTrailerEnd(xmpTrailerEndDef);
+ if (!convertStringCharset(xmpTrailerEnd, "UTF-8", charset.c_str())) {
+ throw Error(28, charset);
+ }
+
+ // search for valid XMP trailer
+ for (size_t trailerPos = xmpPos + header.size(); trailerPos < size; trailerPos++) {
+ if (data[xmpPos] != '\x00' && data[xmpPos] != '<') continue;
+ for (size_t j = 0; j < xmpTrailers.size(); j++) {
+ const std::string &trailer = xmpTrailers[j].first;
+ if (trailerPos + trailer.size() > size) continue;
+ if (memcmp(data + trailerPos, trailer.data(), trailer.size()) != 0) continue;
+ #ifdef DEBUG
+ EXV_DEBUG << "findXmp: Found XMP trailer at position: " << trailerPos << "
";
+ #endif
+
+ const bool readOnly = xmpTrailers[j].second;
+ if (readOnly) {
+ #ifndef SUPPRESS_WARNINGS
+ EXV_WARNING << "Unable to handle read-only XMP metadata yet. Please provide your"
+ " sample EPS file to the Exiv2 project: http://dev.exiv2.org/projects/exiv2
";
+ #endif
+ throw Error(write ? 21 : 14);
+ }
+
+ // search for end of XMP trailer
+ for (size_t trailerEndPos = trailerPos + trailer.size(); trailerEndPos + xmpTrailerEnd.size() <= size; trailerEndPos++) {
+ if (memcmp(data + trailerEndPos, xmpTrailerEnd.data(), xmpTrailerEnd.size()) == 0) {
+ xmpSize = (trailerEndPos + xmpTrailerEnd.size()) - xmpPos;
+ return;
+ }
+ }
+ #ifndef SUPPRESS_WARNINGS
+ EXV_WARNING << "Found XMP header but incomplete XMP trailer.
";
+ #endif
+ throw Error(write ? 21 : 14);
+ }
+ }
+ #ifndef SUPPRESS_WARNINGS
+ EXV_WARNING << "Found XMP header but no XMP trailer.
";
+ #endif
+ throw Error(write ? 21 : 14);
+ }
+ }
}
- void EpsImage::doReadWriteMetadata(bool write)
+ //! Find removable XMP embeddings
+ static std::vector<std::pair<size_t, size_t> > findRemovableEmbeddings(const char* data, size_t posEof, size_t posEndPageSetup,
+ size_t xmpPos, size_t xmpSize, bool write)
{
+ std::vector<std::pair<size_t, size_t> > removableEmbeddings;
+ std::string line;
+ size_t pos;
+
+ // check after XMP
+ pos = xmpPos + xmpSize;
+ pos = readLine(line, data, pos, posEof);
+ if (line != "") return removableEmbeddings;
+ #ifdef DEBUG
+ EXV_DEBUG << "findRemovableEmbeddings: Found empty line after XMP
";
+ #endif
+ pos = readLine(line, data, pos, posEof);
+ if (line != "%end_xml_packet") return removableEmbeddings;
+ #ifdef DEBUG
+ EXV_DEBUG << "findRemovableEmbeddings: Found %end_xml_packet
";
+ #endif
+ size_t posEmbeddingEnd = 0;
+ for (int i = 0; i < 32; i++) {
+ pos = readLine(line, data, pos, posEof);
+ if (line == "%end_xml_code") {
+ posEmbeddingEnd = pos;
+ break;
+ }
+ }
+ if (posEmbeddingEnd == 0) return removableEmbeddings;
+ #ifdef DEBUG
+ EXV_DEBUG << "findRemovableEmbeddings: Found %end_xml_code
";
+ #endif
+
+ // check before XMP
+ pos = xmpPos;
+ pos = readPrevLine(line, data, pos, posEof);
+ if (!startsWith(line, "%begin_xml_packet: ")) return removableEmbeddings;
+ #ifdef DEBUG
+ EXV_DEBUG << "findRemovableEmbeddings: Found %begin_xml_packet: ...
";
+ #endif
+ size_t posEmbeddingStart = posEof;
+ for (int i = 0; i < 32; i++) {
+ pos = readPrevLine(line, data, pos, posEof);
+ if (line == "%begin_xml_code") {
+ posEmbeddingStart = pos;
+ break;
+ }
+ }
+ if (posEmbeddingStart == posEof) return removableEmbeddings;
#ifdef DEBUG
- if (write) {
- EXV_DEBUG << "Exiv2::EpsImage::doReadWriteMetadata: Writing EPS file " << io_->path() << "
";
+ EXV_DEBUG << "findRemovableEmbeddings: Found %begin_xml_code
";
+ #endif
+
+ // check at EOF
+ pos = posEof;
+ pos = readPrevLine(line, data, pos, posEof);
+ if (line == "[/EMC pdfmark") {
+ // Exiftool style
+ #ifdef DEBUG
+ EXV_DEBUG << "findRemovableEmbeddings: Found [/EMC pdfmark
";
+ #endif
+ } else if (line == "[/NamespacePop pdfmark") {
+ // Photoshop style
+ #ifdef DEBUG
+ EXV_DEBUG << "findRemovableEmbeddings: Found /NamespacePop pdfmark
";
+ #endif
+ pos = readPrevLine(line, data, pos, posEof);
+ if (line != "[{nextImage} 1 dict begin /Metadata {photoshop_metadata_stream} def currentdict end /PUT pdfmark") return removableEmbeddings;
+ #ifdef DEBUG
+ EXV_DEBUG << "findRemovableEmbeddings: Found /PUT pdfmark
";
+ #endif
} else {
- EXV_DEBUG << "Exiv2::EpsImage::doReadWriteMetadata: Reading EPS file " << io_->path() << "
";
+ return removableEmbeddings;
}
+
+ // check whether another XMP metadata block would take precedence if this one was removed
+ {
+ size_t xmpPos, xmpSize;
+ findXmp(xmpPos, xmpSize, data, posEndPageSetup, write);
+ if (xmpSize != 0) {
+ #ifndef SUPPRESS_WARNINGS
+ EXV_WARNING << "Second XMP metadata block interferes at position: " << xmpPos << "
";
+ #endif
+ if (write) throw Error(21);
+ }
+ }
+
+ removableEmbeddings.push_back(std::make_pair(posEmbeddingStart, posEmbeddingEnd));
+ removableEmbeddings.push_back(std::make_pair(pos, posEof));
+ #ifdef DEBUG
+ const size_t n = removableEmbeddings.size();
+ EXV_DEBUG << "findRemovableEmbeddings: Recognized Photoshop-style XMP embedding at "
+ "[" << removableEmbeddings[n-2].first << "," << removableEmbeddings[n-2].second << ")"
+ " with trailer "
+ "[" << removableEmbeddings[n-1].first << "," << removableEmbeddings[n-1].second << ")"
+ "
";
#endif
+ return removableEmbeddings;
+ }
+ //! Unified implementation of reading and writing EPS metadata
+ static void readWriteEpsMetadata(BasicIo& io, std::string& xmpPacket, bool write)
+ {
// open input file
- if (io_->open() != 0) {
- throw Error(9, io_->path(), strError());
+ if (io.open() != 0) {
+ throw Error(9, io.path(), strError());
}
- IoCloser closer(*io_);
+ IoCloser closer(io);
// read from input file via memory map
- const char *data = reinterpret_cast<const char*>(io_->mmap());
- const size_t size = io_->size();
+ const char *data = reinterpret_cast<const char*>(io.mmap());
+ const size_t size = io.size();
size_t pos = 0;
std::string line;
@@ -193,7 +411,7 @@ namespace Exiv2
pos = readLine(line, data, firstLinePos, size);
const std::string firstLine = line;
#ifdef DEBUG
- EXV_DEBUG << "Exiv2::EpsImage::doReadWriteMetadata: First line: " << firstLine << "
";
+ EXV_DEBUG << "readWriteEpsMetadata: First line: " << firstLine << "
";
#endif
bool matched = false;
for (size_t i = 0; !matched && i < (sizeof epsFirstLine) / (sizeof *epsFirstLine); i++) {
@@ -213,13 +431,13 @@ namespace Exiv2
const std::string lineEnding(data + firstLinePos + firstLine.size(), pos - (firstLinePos + firstLine.size()));
#ifdef DEBUG
if (lineEnding == "
") {
- EXV_DEBUG << "Exiv2::EpsImage::doReadWriteMetadata: Line ending style: Unix (LF)
";
+ EXV_DEBUG << "readWriteEpsMetadata: Line ending style: Unix (LF)
";
} else if (lineEnding == "
") {
- EXV_DEBUG << "Exiv2::EpsImage::doReadWriteMetadata: Line ending style: Mac (CR)
";
+ EXV_DEBUG << "readWriteEpsMetadata: Line ending style: Mac (CR)
";
} else if (lineEnding == "
") {
- EXV_DEBUG << "Exiv2::EpsImage::doReadWriteMetadata: Line ending style: DOS (CR LF)
";
+ EXV_DEBUG << "readWriteEpsMetadata: Line ending style: DOS (CR LF)
";
} else {
- EXV_DEBUG << "Exiv2::EpsImage::doReadWriteMetadata: Line ending style: (unknown)
";
+ EXV_DEBUG << "readWriteEpsMetadata: Line ending style: (unknown)
";
}
#endif
@@ -246,7 +464,7 @@ namespace Exiv2
if (posEndComments == size) {
posEndComments = startPos;
#ifdef DEBUG
- EXV_DEBUG << "Exiv2::EpsImage::doReadWriteMetadata: Found implicit EndComments at position: " << startPos << "
";
+ EXV_DEBUG << "readWriteEpsMetadata: Found implicit EndComments at position: " << startPos << "
";
#endif
}
}
@@ -255,13 +473,13 @@ namespace Exiv2
posPage = startPos;
implicitPage = true;
#ifdef DEBUG
- EXV_DEBUG << "Exiv2::EpsImage::doReadWriteMetadata: Found implicit Page at position: " << startPos << "
";
+ EXV_DEBUG << "readWriteEpsMetadata: Found implicit Page at position: " << startPos << "
";
#endif
}
if (posEndPageSetup == size && posPage != size && !inPageSetup) {
posEndPageSetup = startPos;
#ifdef DEBUG
- EXV_DEBUG << "Exiv2::EpsImage::doReadWriteMetadata: Found implicit EndPageSetup at position: " << startPos << "
";
+ EXV_DEBUG << "readWriteEpsMetadata: Found implicit EndPageSetup at position: " << startPos << "
";
#endif
}
}
@@ -269,7 +487,7 @@ namespace Exiv2
if (line == "%%EOF" && posPageTrailer == size) {
posPageTrailer = startPos;
#ifdef DEBUG
- EXV_DEBUG << "Exiv2::EpsImage::doReadWriteMetadata: Found implicit PageTrailer at position: " << startPos << "
";
+ EXV_DEBUG << "readWriteEpsMetadata: Found implicit PageTrailer at position: " << startPos << "
";
#endif
}
// explicit comments
@@ -349,7 +567,7 @@ namespace Exiv2
}
#ifdef DEBUG
if (significantLine) {
- EXV_DEBUG << "Exiv2::EpsImage::doReadWriteMetadata: Found significant line \"" << line << "\" at position: " << startPos << "
";
+ EXV_DEBUG << "readWriteEpsMetadata: Found significant line \"" << line << "\" at position: " << startPos << "
";
}
#endif
}
@@ -392,12 +610,12 @@ namespace Exiv2
readLine(line, data, posLineAfterXmp, size);
if (line == "% &&end XMP packet marker&&" || line == "% &&end XMP packet marker&&") {
#ifdef DEBUG
- EXV_DEBUG << "Exiv2::EpsImage::doReadWriteMetadata: Recognized flexible XMP embedding
";
+ EXV_DEBUG << "readWriteEpsMetadata: Recognized flexible XMP embedding
";
#endif
const size_t posBeginXmlPacket = readPrevLine(line, data, xmpPos, size);
if (startsWith(line, "%begin_xml_packet:")) {
#ifdef DEBUG
- EXV_DEBUG << "Exiv2::EpsImage::doReadWriteMetadata: Found %begin_xml_packet before flexible XMP embedding
";
+ EXV_DEBUG << "readWriteEpsMetadata: Found %begin_xml_packet before flexible XMP embedding
";
#endif
if (write) {
fixBeginXmlPacket = true;
@@ -422,28 +640,14 @@ namespace Exiv2
}
if (!write) {
- // copy and decode XMP metadata
- xmpPacket_.assign(data + xmpPos, xmpSize);
- if (xmpPacket_.size() > 0 && XmpParser::decode(xmpData_, xmpPacket_) > 1) {
- #ifndef SUPPRESS_WARNINGS
- EXV_WARNING << "Failed to decode XMP metadata.
";
- #endif
- throw Error(14);
- }
+ // copy
+ xmpPacket.assign(data + xmpPos, xmpSize);
} else {
const bool useExistingEmbedding = (xmpPos != size && removableEmbeddings.empty());
- // encode XMP metadata if necessary
- if (!writeXmpFromPacket() && XmpParser::encode(xmpPacket_, xmpData_) > 1) {
- #ifndef SUPPRESS_WARNINGS
- EXV_WARNING << "Failed to encode XMP metadata.
";
- #endif
- throw Error(21);
- }
-
// TODO: Add support for deleting XMP metadata. Note that this is not
// as simple as it may seem, and requires special attention!
- if (xmpPacket_.size() == 0) {
+ if (xmpPacket.size() == 0) {
#ifndef SUPPRESS_WARNINGS
EXV_WARNING << "Deleting XMP metadata is currently not supported.
";
#endif
@@ -451,7 +655,7 @@ namespace Exiv2
}
// create temporary output file
- BasicIo::AutoPtr tempIo(io_->temporary());
+ BasicIo::AutoPtr tempIo(io.temporary());
assert (tempIo.get() != 0);
if (!tempIo->isopen()) {
#ifndef SUPPRESS_WARNINGS
@@ -460,7 +664,7 @@ namespace Exiv2
throw Error(21);
}
#ifdef DEBUG
- EXV_DEBUG << "Exiv2::EpsImage::doReadWriteMetadata: Created temporary file " << tempIo->path() << "
";
+ EXV_DEBUG << "readWriteEpsMetadata: Created temporary file " << tempIo->path() << "
";
#endif
// sort all positions
@@ -504,7 +708,7 @@ namespace Exiv2
if (pos == size && pos >= 1 && data[pos - 1] != '
' && data[pos - 1] != '
') {
writeTemp(*tempIo, lineEnding);
#ifdef DEBUG
- EXV_DEBUG << "Exiv2::EpsImage::doReadWriteMetadata: Added missing line ending of last line
";
+ EXV_DEBUG << "readWriteEpsMetadata: Added missing line ending of last line
";
#endif
}
// update and complement DSC comments
@@ -566,9 +770,9 @@ namespace Exiv2
// insert XMP metadata into existing flexible embedding
if (pos == xmpPos) {
if (fixBeginXmlPacket) {
- writeTemp(*tempIo, "%begin_xml_packet: " + toString(xmpPacket_.size()) + lineEnding);
+ writeTemp(*tempIo, "%begin_xml_packet: " + toString(xmpPacket.size()) + lineEnding);
}
- writeTemp(*tempIo, xmpPacket_.data(), xmpPacket_.size());
+ writeTemp(*tempIo, xmpPacket.data(), xmpPacket.size());
skipPos += xmpSize;
}
} else {
@@ -598,9 +802,9 @@ namespace Exiv2
if (photoshop) {
writeTemp(*tempIo, "%Exiv2Notice: The following line is needed by Photoshop. "
"Parameter must be exact size of XMP metadata." + lineEnding);
- writeTemp(*tempIo, "%begin_xml_packet: " + toString(xmpPacket_.size()) + lineEnding);
+ writeTemp(*tempIo, "%begin_xml_packet: " + toString(xmpPacket.size()) + lineEnding);
}
- writeTemp(*tempIo, xmpPacket_.data(), xmpPacket_.size());
+ writeTemp(*tempIo, xmpPacket.data(), xmpPacket.size());
writeTemp(*tempIo, lineEnding);
writeTemp(*tempIo, "% &&end XMP packet marker&&" + lineEnding);
writeTemp(*tempIo, "[/Document 1 dict begin" + lineEnding);
@@ -635,273 +839,90 @@ namespace Exiv2
}
// copy temporary file to real output file
- io_->close();
- io_->transfer(*tempIo);
- }
-
- #ifdef DEBUG
- if (write) {
- EXV_DEBUG << "Exiv2::EpsImage::doReadWriteMetadata: Finished writing EPS file " << io_->path() << "
";
- } else {
- EXV_DEBUG << "Exiv2::EpsImage::doReadWriteMetadata: Finished reading EPS file " << io_->path() << "
";
+ io.close();
+ io.transfer(*tempIo);
}
- #endif
}
- std::vector<std::pair<size_t, size_t> > EpsImage::findRemovableEmbeddings(const char* data, size_t posEof, size_t posEndPageSetup,
- size_t xmpPos, size_t xmpSize, bool write)
- {
- std::vector<std::pair<size_t, size_t> > removableEmbeddings;
- std::string line;
- size_t pos;
-
- // check after XMP
- pos = xmpPos + xmpSize;
- pos = readLine(line, data, pos, posEof);
- if (line != "") return removableEmbeddings;
- #ifdef DEBUG
- EXV_DEBUG << "Exiv2::EpsImage::findRemovableEmbeddings: Found empty line after XMP
";
- #endif
- pos = readLine(line, data, pos, posEof);
- if (line != "%end_xml_packet") return removableEmbeddings;
- #ifdef DEBUG
- EXV_DEBUG << "Exiv2::EpsImage::findRemovableEmbeddings: Found %end_xml_packet
";
- #endif
- size_t posEmbeddingEnd = 0;
- for (int i = 0; i < 32; i++) {
- pos = readLine(line, data, pos, posEof);
- if (line == "%end_xml_code") {
- posEmbeddingEnd = pos;
- break;
- }
- }
- if (posEmbeddingEnd == 0) return removableEmbeddings;
- #ifdef DEBUG
- EXV_DEBUG << "Exiv2::EpsImage::findRemovableEmbeddings: Found %end_xml_code
";
- #endif
-
- // check before XMP
- pos = xmpPos;
- pos = readPrevLine(line, data, pos, posEof);
- if (!startsWith(line, "%begin_xml_packet: ")) return removableEmbeddings;
- #ifdef DEBUG
- EXV_DEBUG << "Exiv2::EpsImage::findRemovableEmbeddings: Found %begin_xml_packet: ...
";
- #endif
- size_t posEmbeddingStart = posEof;
- for (int i = 0; i < 32; i++) {
- pos = readPrevLine(line, data, pos, posEof);
- if (line == "%begin_xml_code") {
- posEmbeddingStart = pos;
- break;
- }
- }
- if (posEmbeddingStart == posEof) return removableEmbeddings;
- #ifdef DEBUG
- EXV_DEBUG << "Exiv2::EpsImage::findRemovableEmbeddings: Found %begin_xml_code
";
- #endif
-
- // check at EOF
- pos = posEof;
- pos = readPrevLine(line, data, pos, posEof);
- if (line == "[/EMC pdfmark") {
- // Exiftool style
- #ifdef DEBUG
- EXV_DEBUG << "Exiv2::EpsImage::findRemovableEmbeddings: Found [/EMC pdfmark
";
- #endif
- } else if (line == "[/NamespacePop pdfmark") {
- // Photoshop style
- #ifdef DEBUG
- EXV_DEBUG << "Exiv2::EpsImage::findRemovableEmbeddings: Found /NamespacePop pdfmark
";
- #endif
- pos = readPrevLine(line, data, pos, posEof);
- if (line != "[{nextImage} 1 dict begin /Metadata {photoshop_metadata_stream} def currentdict end /PUT pdfmark") return removableEmbeddings;
- #ifdef DEBUG
- EXV_DEBUG << "Exiv2::EpsImage::findRemovableEmbeddings: Found /PUT pdfmark
";
- #endif
- } else {
- return removableEmbeddings;
- }
-
- // check whether another XMP metadata block would take precedence if this one was removed
- {
- size_t xmpPos, xmpSize;
- findXmp(xmpPos, xmpSize, data, posEndPageSetup, write);
- if (xmpSize != 0) {
- #ifndef SUPPRESS_WARNINGS
- EXV_WARNING << "Second XMP metadata block interferes at position: " << xmpPos << "
";
- #endif
- if (write) throw Error(21);
- }
- }
+} // namespace
- removableEmbeddings.push_back(std::make_pair(posEmbeddingStart, posEmbeddingEnd));
- removableEmbeddings.push_back(std::make_pair(pos, posEof));
- #ifdef DEBUG
- const size_t n = removableEmbeddings.size();
- EXV_DEBUG << "Exiv2::EpsImage::findRemovableEmbeddings: Recognized Photoshop-style XMP embedding at "
- "[" << removableEmbeddings[n-2].first << "," << removableEmbeddings[n-2].second << ")"
- " with trailer "
- "[" << removableEmbeddings[n-1].first << "," << removableEmbeddings[n-1].second << ")"
- "
";
- #endif
- return removableEmbeddings;
- }
+// *****************************************************************************
+// class member definitions
+namespace Exiv2
+{
- void EpsImage::findXmp(size_t& xmpPos, size_t& xmpSize, const char* data, size_t size, bool write)
+ EpsImage::EpsImage(BasicIo::AutoPtr io, bool create)
+ : Image(ImageType::eps, mdXmp, io)
{
- // prepare list of valid XMP headers
- std::vector<std::pair<std::string, std::string> > xmpHeaders;
- for (size_t i = 0; i < (sizeof xmpHeadersDef) / (sizeof *xmpHeadersDef); i++) {
- const std::string &charset = xmpHeadersDef[i].charset;
- std::string header(xmpHeadersDef[i].header);
- if (!convertStringCharset(header, "UTF-8", charset.c_str())) {
- throw Error(28, charset);
- }
- xmpHeaders.push_back(make_pair(header, charset));
- }
-
- // search for valid XMP header
- xmpSize = 0;
- for (xmpPos = 0; xmpPos < size; xmpPos++) {
- if (data[xmpPos] != '\x00' && data[xmpPos] != '<') continue;
- for (size_t i = 0; i < xmpHeaders.size(); i++) {
- const std::string &header = xmpHeaders[i].first;
- if (xmpPos + header.size() > size) continue;
- if (memcmp(data + xmpPos, header.data(), header.size()) != 0) continue;
+ //LogMsg::setLevel(LogMsg::debug);
+ if (create) {
+ if (io_->open() == 0) {
#ifdef DEBUG
- EXV_DEBUG << "Exiv2::EpsImage::findXmp: Found XMP header at position: " << xmpPos << "
";
+ EXV_DEBUG << "Exiv2::EpsImage:: Creating blank EPS image
";
#endif
-
- // prepare list of valid XMP trailers in the charset of the header
- const std::string &charset = xmpHeaders[i].second;
- std::vector<std::pair<std::string, bool> > xmpTrailers;
- for (size_t j = 0; j < (sizeof xmpTrailersDef) / (sizeof *xmpTrailersDef); j++) {
- std::string trailer(xmpTrailersDef[j].trailer);
- if (!convertStringCharset(trailer, "UTF-8", charset.c_str())) {
- throw Error(28, charset);
- }
- xmpTrailers.push_back(make_pair(trailer, xmpTrailersDef[j].readOnly));
- }
- std::string xmpTrailerEnd(xmpTrailerEndDef);
- if (!convertStringCharset(xmpTrailerEnd, "UTF-8", charset.c_str())) {
- throw Error(28, charset);
- }
-
- // search for valid XMP trailer
- for (size_t trailerPos = xmpPos + header.size(); trailerPos < size; trailerPos++) {
- if (data[xmpPos] != '\x00' && data[xmpPos] != '<') continue;
- for (size_t j = 0; j < xmpTrailers.size(); j++) {
- const std::string &trailer = xmpTrailers[j].first;
- if (trailerPos + trailer.size() > size) continue;
- if (memcmp(data + trailerPos, trailer.data(), trailer.size()) != 0) continue;
- #ifdef DEBUG
- EXV_DEBUG << "Exiv2::EpsImage::findXmp: Found XMP trailer at position: " << trailerPos << "
";
- #endif
-
- const bool readOnly = xmpTrailers[j].second;
- if (readOnly) {
- #ifndef SUPPRESS_WARNINGS
- EXV_WARNING << "Unable to handle read-only XMP metadata yet. Please provide your"
- " sample EPS file to the Exiv2 project: http://dev.exiv2.org/projects/exiv2
";
- #endif
- throw Error(write ? 21 : 14);
- }
-
- // search for end of XMP trailer
- for (size_t trailerEndPos = trailerPos + trailer.size(); trailerEndPos + xmpTrailerEnd.size() <= size; trailerEndPos++) {
- if (memcmp(data + trailerEndPos, xmpTrailerEnd.data(), xmpTrailerEnd.size()) == 0) {
- xmpSize = (trailerEndPos + xmpTrailerEnd.size()) - xmpPos;
- return;
- }
- }
- #ifndef SUPPRESS_WARNINGS
- EXV_WARNING << "Found XMP header but incomplete XMP trailer.
";
- #endif
- throw Error(write ? 21 : 14);
- }
+ IoCloser closer(*io_);
+ if (io_->write(reinterpret_cast<const byte*>(epsBlank.data()), static_cast<long>(epsBlank.size())) != static_cast<long>(epsBlank.size())) {
+ #ifndef SUPPRESS_WARNINGS
+ EXV_WARNING << "Failed to write blank EPS image.
";
+ #endif
+ throw Error(21);
}
- #ifndef SUPPRESS_WARNINGS
- EXV_WARNING << "Found XMP header but no XMP trailer.
";
- #endif
- throw Error(write ? 21 : 14);
}
}
}
- size_t EpsImage::readLine(std::string& line, const char* data, size_t startPos, size_t size)
+ std::string EpsImage::mimeType() const
{
- line.clear();
- size_t pos = startPos;
- // step through line
- while (pos < size && data[pos] != '
' && data[pos] != '
') {
- line += data[pos];
- pos++;
- }
- // skip line ending, if present
- if (pos >= size) return pos;
- pos++;
- if (pos >= size) return pos;
- if (data[pos - 1] == '
' && data[pos] == '
') pos++;
- return pos;
+ return "application/postscript";
}
- size_t EpsImage::readPrevLine(std::string& line, const char* data, size_t startPos, size_t size)
+ void EpsImage::setComment(const std::string& /*comment*/)
{
- line.clear();
- size_t pos = startPos;
- if (pos > size) return pos;
- // skip line ending of previous line, if present
- if (pos <= 0) return pos;
- if (data[pos - 1] == '
' || data[pos - 1] == '
') {
- pos--;
- if (pos <= 0) return pos;
- if (data[pos - 1] == '
' && data[pos] == '
') {
- pos--;
- if (pos <= 0) return pos;
- }
- }
- // step through previous line
- while (pos >= 1 && data[pos - 1] != '
' && data[pos - 1] != '
') {
- pos--;
- line += data[pos];
- }
- std::reverse(line.begin(), line.end());
- return pos;
+ throw Error(32, "Image comment", "EPS");
}
- bool EpsImage::startsWith(const std::string& s, const std::string& start)
+ void EpsImage::readMetadata()
{
- return s.size() >= start.size() && memcmp(s.data(), start.data(), start.size()) == 0;
- }
+ #ifdef DEBUG
+ EXV_DEBUG << "Exiv2::EpsImage::readMetadata: Reading EPS file " << io_->path() << "
";
+ #endif
- bool EpsImage::onlyWhitespaces(const std::string& s)
- {
- // According to the DSC 3.0 specification, 4.4 Parsing Rules,
- // only spaces and tabs are considered to be white space characters.
- return s.find_first_not_of(" ") == std::string::npos;
- }
+ // read metadata
+ readWriteEpsMetadata(*io_, xmpPacket_, /* write = */ false);
- std::string EpsImage::toString(size_t size)
- {
- std::ostringstream stream;
- stream << size;
- return stream.str();
+ // decode XMP metadata
+ if (xmpPacket_.size() > 0 && XmpParser::decode(xmpData_, xmpPacket_) > 1) {
+ #ifndef SUPPRESS_WARNINGS
+ EXV_WARNING << "Failed to decode XMP metadata.
";
+ #endif
+ throw Error(14);
+ }
+
+ #ifdef DEBUG
+ EXV_DEBUG << "Exiv2::EpsImage::readMetadata: Finished reading EPS file " << io_->path() << "
";
+ #endif
}
- void EpsImage::writeTemp(BasicIo& tempIo, const char* data, size_t size)
+ void EpsImage::writeMetadata()
{
- if (size == 0) return;
- if (tempIo.write(reinterpret_cast<const byte*>(data), static_cast<long>(size)) != static_cast<long>(size)) {
+ #ifdef DEBUG
+ EXV_DEBUG << "Exiv2::EpsImage::writeMetadata: Writing EPS file " << io_->path() << "
";
+ #endif
+
+ // encode XMP metadata if necessary
+ if (!writeXmpFromPacket() && XmpParser::encode(xmpPacket_, xmpData_) > 1) {
#ifndef SUPPRESS_WARNINGS
- EXV_WARNING << "Failed to write to temporary file.
";
+ EXV_WARNING << "Failed to encode XMP metadata.
";
#endif
throw Error(21);
}
- }
- void EpsImage::writeTemp(BasicIo& tempIo, const std::string &data)
- {
- writeTemp(tempIo, data.data(), data.size());
+ // write metadata
+ readWriteEpsMetadata(*io_, xmpPacket_, /* write = */ true);
+
+ #ifdef DEBUG
+ EXV_DEBUG << "Exiv2::EpsImage::writeMetadata: Finished writing EPS file " << io_->path() << "
";
+ #endif
}
// *************************************************************************
diff --git a/src/epsimage.hpp b/src/epsimage.hpp
index e82366e..b067387 100644
--- a/src/epsimage.hpp
+++ b/src/epsimage.hpp
@@ -105,31 +105,6 @@ namespace Exiv2
EpsImage& operator=(const EpsImage& rhs);
//@}
- //! @name Internal implementation
- //@{
- //! Unified implementation of reading and writing metadata
- EXV_DLLLOCAL void doReadWriteMetadata(bool write);
- //! Find removable XMP embeddings
- EXV_DLLLOCAL static std::vector<std::pair<size_t, size_t> > findRemovableEmbeddings(const char* data, size_t posEof, size_t posEndPageSetup,
- size_t xmpPos, size_t xmpSize, bool write);
- //! Find an XMP block
- EXV_DLLLOCAL static void findXmp(size_t& xmpPos, size_t& xmpSize, const char* data, size_t size, bool write);
- //! Read the next line of a buffer, allow for changing line ending style
- EXV_DLLLOCAL static size_t readLine(std::string& line, const char* data, size_t startPos, size_t size);
- //! Read the previous line of a buffer, allow for changing line ending style
- EXV_DLLLOCAL static size_t readPrevLine(std::string& line, const char* data, size_t startPos, size_t size);
- //! Check whether a string has a certain beginning
- EXV_DLLLOCAL static bool startsWith(const std::string& s, const std::string& start);
- //! Check whether a string contains only white space characters
- EXV_DLLLOCAL static bool onlyWhitespaces(const std::string& s);
- //! Convert an integer of type size_t to a decimal string
- EXV_DLLLOCAL static std::string toString(size_t size);
- //! Write data into temp file, taking care of errors
- EXV_DLLLOCAL static void writeTemp(BasicIo& tempIo, const char* data, size_t size);
- //! Write data into temp file, taking care of errors
- EXV_DLLLOCAL static void writeTemp(BasicIo& tempIo, const std::string &data);
- //@}
-
}; // class EpsImage
// *****************************************************************************
--
exiv2 packaging
More information about the pkg-kde-commits
mailing list