diff --git a/genericfileelement.h b/genericfileelement.h index 261f82d..8b9f473 100644 --- a/genericfileelement.h +++ b/genericfileelement.h @@ -767,17 +767,26 @@ template void GenericFileElement::validateSubsequentElementStructure(NotificationList &gatheredNotifications, uint64 *paddingSize) { try { + // validate element itself by just parsing it parse(); gatheredNotifications.insert(gatheredNotifications.end(), notifications().begin(), notifications().end()); - if(firstChild()) { // element is parent - firstChild()->validateSubsequentElementStructure(gatheredNotifications, paddingSize); + // validate children + if(firstChild()) { + try { + firstChild()->validateSubsequentElementStructure(gatheredNotifications, paddingSize); + } catch(const Failure &) { + // - ignore critical errors in child structure to continue validating siblings + // - critical notifications about the errors should have already been added to + // gatheredNotifications + } } else if(paddingSize && isPadding()) { // element is padding *paddingSize += totalSize(); } + // validate siblings if(nextSibling()) { nextSibling()->validateSubsequentElementStructure(gatheredNotifications, paddingSize); } - } catch(Failure &) { + } catch(const Failure &) { gatheredNotifications.insert(gatheredNotifications.end(), notifications().begin(), notifications().end()); throw; } diff --git a/mediafileinfo.cpp b/mediafileinfo.cpp index 5c98c0d..8cb17d4 100644 --- a/mediafileinfo.cpp +++ b/mediafileinfo.cpp @@ -643,7 +643,7 @@ bool MediaFileInfo::createAppropriateTags(bool treatUnknownFilesAsMp3Files, TagU */ void MediaFileInfo::applyChanges() { - const string context("making file"); + static const string context("making file"); addNotification(NotificationType::Information, "Changes are about to be applied.", context); bool previousParsingSuccessful = true; switch(tagsParsingStatus()) { @@ -678,9 +678,8 @@ void MediaFileInfo::applyChanges() m_tagsParsingStatus = ParsingStatus::NotParsedYet; try { m_container->makeFile(); - addNotifications(*m_container); } catch(...) { - addNotifications(*m_container); + // since the file might be messed up, invalidate the parsing results clearParsingResults(); throw; } @@ -689,6 +688,7 @@ void MediaFileInfo::applyChanges() try { makeMp3File(); } catch(...) { + // since the file might be messed up, invalidate the parsing results clearParsingResults(); throw; } @@ -1182,7 +1182,7 @@ vector MediaFileInfo::chapters() const { vector res; if(m_container) { - size_t count = m_container->chapterCount(); + const size_t count = m_container->chapterCount(); res.reserve(count); for(size_t i = 0; i != count; ++i) { res.push_back(m_container->chapter(i)); @@ -1200,9 +1200,9 @@ vector MediaFileInfo::attachments() const { vector res; if(m_container) { - size_t count = m_container->attachmentCount(); + const size_t count = m_container->attachmentCount(); res.reserve(count); - for(size_t i = 0; i < count; ++i) { + for(size_t i = 0; i != count; ++i) { res.push_back(m_container->attachment(i)); } } @@ -1284,7 +1284,27 @@ void MediaFileInfo::gatherRelatedNotifications(NotificationList ¬ifications) { notifications.insert(notifications.end(), this->notifications().cbegin(), this->notifications().cend()); if(m_container) { - notifications.insert(notifications.end(), m_container->notifications().cbegin(), m_container->notifications().cend()); + // prevent duplicates which might be present when validating element structure + switch(m_containerFormat) { + case ContainerFormat::Ebml: + case ContainerFormat::Matroska: + // those files are only validated when a full parse is forced + if(!m_forceFullParse) { + break; + } + FALLTHROUGH; + case ContainerFormat::Mp4: + case ContainerFormat::QuickTime: + // those files are always validated + for(const Notification ¬ification : m_container->notifications()) { + if(find(notifications.cbegin(), notifications.cend(), notification) == notifications.cend()) { + notifications.emplace_back(notification); + } + } + break; + default: + notifications.insert(notifications.end(), m_container->notifications().cbegin(), m_container->notifications().cend());; + } } for(const auto *track : tracks()) { notifications.insert(notifications.end(), track->notifications().cbegin(), track->notifications().cend());