Commit 3b0656ea authored by Dmitry Kazakov's avatar Dmitry Kazakov Committed by Halla Rempt
Browse files

Fixed a crash when opening JPEG files edited in Lightroom

We do not support nested arrays/nested structures in the XMP currently.
This means that all the information about Adjustment masks applied by
the Adobe Lightroom will be lost.

This is not ideal of course, but we can live with it for now.

Here is an example of XMP tag that will be dropped:
GradientBasedCorrections[1]/crs:CorrectionMasks[1]/crs:What

BUG:318724
parent f6520dc1
......@@ -157,6 +157,64 @@ bool KisXMPIO::saveTo(KisMetaData::Store* store, QIODevice* ioDevice, HeaderType
return true;
}
bool parseTagName(const QString &tagString,
QString &structName,
int &arrayIndex,
QString &tagName,
const KisMetaData::TypeInfo* typeInfo,
const KisMetaData::Schema *schema)
{
arrayIndex = -1;
typeInfo = 0;
int numSubNames = tagString.count('/') + 1;
if (numSubNames == 1) {
structName = QString();
tagName = tagString;
typeInfo = schema->propertyType(tagName);
return true;
}
if (numSubNames == 2) {
QRegExp regexp("([A-Za-z]\\w+)/([A-Za-z]\\w+):([A-Za-z]\\w+)");
if (regexp.indexIn(tagString) != -1) {
structName = regexp.capturedTexts()[1];
tagName = regexp.capturedTexts()[3];
typeInfo = schema->propertyType(structName);
if (typeInfo && typeInfo->propertyType() == KisMetaData::TypeInfo::StructureType) {
typeInfo = typeInfo->structureSchema()->propertyType(tagName);
}
return true;
}
QRegExp regexp2("([A-Za-z]\\w+)\\[(\\d+)\\]/([A-Za-z]\\w+):([A-Za-z]\\w+)");
if (regexp2.indexIn(tagString) != -1) {
structName = regexp2.capturedTexts()[1];
arrayIndex = regexp2.capturedTexts()[2].toInt() - 1;
tagName = regexp2.capturedTexts()[4];
if (schema->propertyType(structName)) {
typeInfo = schema->propertyType(structName)->embeddedPropertyType();
Q_ASSERT(typeInfo);
if (typeInfo->propertyType() == KisMetaData::TypeInfo::StructureType) {
typeInfo = typeInfo->structureSchema()->propertyType(tagName);
}
}
return true;
}
}
qWarning() << "WARNING: Unsupported tag. We do not yet support nested tags. The tag will be dropped!";
qWarning() << " Failing tag:" << tagString;
return false;
}
bool KisXMPIO::loadFrom(KisMetaData::Store* store, QIODevice* ioDevice) const
{
ioDevice->open(QIODevice::ReadOnly);
......@@ -171,7 +229,8 @@ bool KisXMPIO::loadFrom(KisMetaData::Store* store, QIODevice* ioDevice) const
QMap< const KisMetaData::Schema*, QMap<QString, QMap<QString, KisMetaData::Value> > > structures;
QMap< const KisMetaData::Schema*, QMap<QString, QVector< QMap<QString, KisMetaData::Value> > > > arraysOfStructures;
for (Exiv2::XmpData::iterator it = xmpData_.begin(); it != xmpData_.end(); ++it) {
dbgFile << it->key().c_str();
dbgFile << "Start iteration" << it->key().c_str();
Exiv2::XmpKey key(it->key());
dbgFile << key.groupName().c_str() << " " << key.tagName().c_str() << " " << key.ns().c_str();
if ((key.groupName() == "exif" || key.groupName() == "tiff") && key.tagName() == "NativeDigest") { // TODO: someone who has time to lose can look in adding support for NativeDigest, it's undocumented use by the XMP SDK to check if exif data has been changed while XMP hasn't been updated
......@@ -186,50 +245,22 @@ bool KisXMPIO::loadFrom(KisMetaData::Store* store, QIODevice* ioDevice) const
}
}
const Exiv2::Value::AutoPtr value = it->getValue();
// Decrypt key
QString structName = "";
QString tagName = key.tagName().c_str();
QString structName;
int arrayIndex = -1;
QString tagName;
const KisMetaData::TypeInfo* typeInfo = 0;
bool isStructureEntry = false;
bool isStructureInArrayEntry = false;
if (tagName.contains("/")) {
QRegExp regexp("([A-Za-z]\\w+)/([A-Za-z]\\w+):([A-Za-z]\\w+)");
if (regexp.indexIn(tagName) != -1) {
structName = regexp.capturedTexts()[1];
tagName = regexp.capturedTexts()[3];
typeInfo = schema->propertyType(structName);
Q_ASSERT(typeInfo == schema->propertyType(structName));
if (typeInfo && typeInfo->propertyType() == KisMetaData::TypeInfo::StructureType) {
typeInfo = typeInfo->structureSchema()->propertyType(tagName);
}
isStructureEntry = true;
} else {
QRegExp regexp2("([A-Za-z]\\w+)\\[(\\d+)\\]/([A-Za-z]\\w+):([A-Za-z]\\w+)");
if (regexp2.indexIn(tagName) != -1) {
dbgFile << ppVar(tagName);
structName = regexp2.capturedTexts()[1];
arrayIndex = regexp2.capturedTexts()[2].toInt() - 1;
tagName = regexp2.capturedTexts()[4];
dbgFile << ppVar(structName) << ppVar(regexp2.capturedTexts()[3]);
//Q_ASSERT(schema->propertyType(structName));
if (schema->propertyType(structName)) {
typeInfo = schema->propertyType(structName)->embeddedPropertyType();
Q_ASSERT(typeInfo);
if (typeInfo && typeInfo->propertyType() == KisMetaData::TypeInfo::StructureType) {
typeInfo = typeInfo->structureSchema()->propertyType(tagName);
}
}
isStructureInArrayEntry = true;
} else {
dbgFile << "Decoding structure name/entry failed: " << tagName;
}
}
} else {
typeInfo = schema->propertyType(tagName);
}
KisMetaData::Value v;
if (!parseTagName(key.tagName().c_str(),
structName, arrayIndex, tagName,
typeInfo, schema)) continue;
bool isStructureEntry = !structName.isEmpty() && arrayIndex == -1;
bool isStructureInArrayEntry = !structName.isEmpty() && arrayIndex != -1;
Q_ASSERT(isStructureEntry != isStructureInArrayEntry || !isStructureEntry);
KisMetaData::Value v;
bool ignoreValue = false;
// Compute the value
if (value->typeId() == Exiv2::xmpBag
......@@ -298,14 +329,18 @@ bool KisXMPIO::loadFrom(KisMetaData::Store* store, QIODevice* ioDevice) const
}
// set the value
dbgFile << ppVar(tagName);
if (isStructureEntry) {
structures[schema][structName][tagName] = v;
} else if (isStructureInArrayEntry) {
if (arraysOfStructures[schema][structName].size() <= arrayIndex) {
arraysOfStructures[schema][structName].resize(arrayIndex + 1);
}
arraysOfStructures[schema][structName][arrayIndex][tagName] = v;
if (!arraysOfStructures[schema][structName][arrayIndex].contains(tagName)) {
arraysOfStructures[schema][structName][arrayIndex][tagName] = v;
} else {
qWarning() << "WARNING: trying to overwrite tag" << tagName << "in" << structName << arrayIndex;
}
} else {
if (!ignoreValue) {
store->addEntry(KisMetaData::Entry(schema, tagName, v));
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment