recognize ar and tar archives by magic number

This commit is contained in:
Martchus 2016-01-20 22:41:10 +01:00
parent 73ff80c46a
commit fa129cf487
4 changed files with 40 additions and 15 deletions

View File

@ -21,7 +21,7 @@ or appending the tag. Usage of padding can be configured:
However, it is also possible to force rewriting the entire file.
Taking advantage of padding is currently not supported when dealing with Ogg stream.
Taking advantage of padding is currently not supported when dealing with Ogg streams.
## Additional features
The library can also display technical information such as the ID, format, language, bitrate,

View File

@ -181,7 +181,7 @@ startParsingSignature:
goto startParsingSignature;
}
if(m_paddingSize) {
addNotification(NotificationType::Warning, ConversionUtilities::numberToString(m_paddingSize) + " zero-bytes skipped at the beginning of the file.", context);
addNotification(NotificationType::Warning, numberToString(m_paddingSize) + " zero-bytes skipped at the beginning of the file.", context);
}
// parse signature
@ -198,7 +198,7 @@ startParsingSignature:
stream().read(buff, 5);
// set the container offset to skip ID3v2 header
m_containerOffset += ConversionUtilities::toNormalInt(ConversionUtilities::BE::toUInt32(buff + 1)) + 10;
m_containerOffset += toNormalInt(BE::toUInt32(buff + 1)) + 10;
if((*buff) & 0x10) {
// footer present
m_containerOffset += 10;
@ -208,17 +208,19 @@ startParsingSignature:
goto startParsingSignature;
case ContainerFormat::Mp4: {
// EBML/Matroska is handled using Mp4Container instance
m_container = make_unique<Mp4Container>(*this, m_containerOffset);
NotificationList notifications;
try {
static_cast<Mp4Container *>(m_container.get())->validateElementStructure(notifications, &m_paddingSize);
} catch (Failure &) {
} catch(const Failure &) {
m_containerParsingStatus = ParsingStatus::CriticalFailure;
}
addNotifications(notifications);
break;
} case ContainerFormat::Ebml: {
// EBML/Matroska is handled using MatroskaContainer instance
auto container = make_unique<MatroskaContainer>(*this, m_containerOffset);
NotificationList notifications;
try {
@ -234,16 +236,28 @@ startParsingSignature:
container->validateElementStructure(notifications, &m_paddingSize);
container->validateIndex();
}
} catch(Failure &) {
} catch(const Failure &) {
m_containerParsingStatus = ParsingStatus::CriticalFailure;
}
m_container = move(container);
addNotifications(notifications);
break;
} case ContainerFormat::Ogg:
// Ogg is handled using OggContainer instance
m_container = make_unique<OggContainer>(*this, m_containerOffset);
static_cast<OggContainer *>(m_container.get())->setChecksumValidationEnabled(m_forceFullParse);
break;
case ContainerFormat::Unknown:
// container format is still unknown -> check for magic numbers at odd offsets
// -> check for tar (magic number at offset 0x101)
if(size() > 0x107) {
stream().seekg(0x101);
stream().read(buff, 6);
if(buff[0] == 0x75 && buff[1] == 0x73 && buff[2] == 0x74 && buff[3] == 0x61 && buff[4] == 0x72 && buff[5] == 0x00) {
m_containerFormat = ContainerFormat::Tar;
break;
}
}
default:
;
}
@ -306,10 +320,10 @@ void MediaFileInfo::parseTracks()
m_singleTrack->parseHeader();
}
m_tracksParsingStatus = ParsingStatus::Ok;
} catch (NotImplementedException &) {
} catch(const NotImplementedException &) {
addNotification(NotificationType::Information, "Parsing tracks is not implemented for the container format of the file.", context);
m_tracksParsingStatus = ParsingStatus::NotSupported;
} catch (Failure &) {
} catch(const Failure &) {
addNotification(NotificationType::Critical, "Unable to parse tracks.", context);
m_tracksParsingStatus = ParsingStatus::CriticalFailure;
}
@ -349,9 +363,9 @@ void MediaFileInfo::parseTags()
try {
m_id3v1Tag->parse(stream(), true);
m_actualExistingId3v1Tag = true;
} catch(NoDataFoundException &) {
} catch(const NoDataFoundException &) {
m_id3v1Tag.reset(); // no ID3v1 tag found
} catch(Failure &) {
} catch(const Failure &) {
m_tagsParsingStatus = ParsingStatus::CriticalFailure;
addNotification(NotificationType::Critical, "Unable to parse ID3v1 tag.", context);
}
@ -364,9 +378,9 @@ void MediaFileInfo::parseTags()
try {
id3v2Tag->parse(stream(), size() - offset);
m_paddingSize += id3v2Tag->paddingSize();
} catch(NoDataFoundException &) {
} catch(const NoDataFoundException &) {
continue;
} catch(Failure &) {
} catch(const Failure &) {
m_tagsParsingStatus = ParsingStatus::CriticalFailure;
addNotification(NotificationType::Critical, "Unable to parse ID3v2 tag.", context);
}
@ -375,13 +389,13 @@ void MediaFileInfo::parseTags()
if(m_container) {
try {
m_container->parseTags();
} catch (NotImplementedException &) {
} catch(const NotImplementedException &) {
if(m_tagsParsingStatus == ParsingStatus::NotParsedYet) {
// do not override parsing status from ID3 tags here
m_tagsParsingStatus = ParsingStatus::NotSupported;
}
addNotification(NotificationType::Information, "Parsing tags is not implemented for the container format of the file.", context);
} catch (Failure &) {
} catch(const Failure &) {
m_tagsParsingStatus = ParsingStatus::CriticalFailure;
addNotification(NotificationType::Critical, "Unable to parse tag.", context);
}

View File

@ -11,6 +11,7 @@ namespace Media {
*/
enum Sig64 : uint64
{
Ar = 0x213C617263683E0A,
Asf1 = 0x3026B2758E66CF11ul,
Asf2 = 0xA6D900AA0062CE6Cul,
Png = 0x89504E470D0A1A0Aul,
@ -109,6 +110,8 @@ ContainerFormat parseSignature(const char *buffer, int bufferSize)
}
// return corresponding container format
switch(sig) { // check 64-bit signatures
case Ar:
return ContainerFormat::Ar;
case Asf1:
return ContainerFormat::Asf;
case Asf2:
@ -223,6 +226,7 @@ ContainerFormat parseSignature(const char *buffer, int bufferSize)
const char *containerFormatAbbreviation(ContainerFormat containerFormat, MediaType mediaType, unsigned int version)
{
switch(containerFormat) {
case ContainerFormat::Ar: return "a";
case ContainerFormat::Asf: return "asf";
case ContainerFormat::Elf: return "elf";
case ContainerFormat::Gif87a:
@ -273,6 +277,7 @@ const char *containerFormatAbbreviation(ContainerFormat containerFormat, MediaTy
case ContainerFormat::Riff: return "riff";
case ContainerFormat::RiffWave: return "wav";
case ContainerFormat::RiffAvi: return "avi";
case ContainerFormat::Tar: return "tar";
case ContainerFormat::TiffBigEndian:
case ContainerFormat::TiffLittleEndian: return "tiff";
case ContainerFormat::WindowsBitmap: return "bmp";
@ -296,6 +301,8 @@ const char *containerFormatName(ContainerFormat containerFormat)
switch(containerFormat) {
case ContainerFormat::Adts:
return "Audio Data Transport Stream";
case ContainerFormat::Ar:
return "Archive (GNU ar)";
case ContainerFormat::Asf:
return "Advanced Systems Format";
case ContainerFormat::Elf:
@ -337,6 +344,8 @@ const char *containerFormatName(ContainerFormat containerFormat)
return "RIFF/WAVE";
case ContainerFormat::RiffAvi:
return "RIFF/Audio Video Interleave";
case ContainerFormat::Tar:
return "TAR archive";
case ContainerFormat::TiffBigEndian:
case ContainerFormat::TiffLittleEndian:
return "Tagged Image File Format";
@ -356,10 +365,10 @@ const char *containerFormatName(ContainerFormat containerFormat)
return "gzip compressed file";
case ContainerFormat::Lzip:
return "lzip compressed file";
case ContainerFormat::Zip:
return "ZIP archive";
case ContainerFormat::SevenZ:
return "7z archive";
case ContainerFormat::Zip:
return "ZIP archive";
default:
return "unknown";
}

View File

@ -15,6 +15,7 @@ enum class ContainerFormat
{
Unknown, /**< unknown container format */
Adts, /** < Audio Data Transport Stream */
Ar, /** < "GNU ar" archive */
Asf, /**< Advanced Systems Format */
Bzip2, /** bzip2 compressed file */
Elf, /**< Executable and Linkable Format */
@ -39,6 +40,7 @@ enum class ContainerFormat
Riff, /**< Resource Interchange File Format */
RiffWave, /**< WAVE (subset of RIFF) */
RiffAvi, /**< Audio Video Interleave (subset of RIFF) */
Tar, /** < Tar archive */
TiffBigEndian, /**< Tagged Image File Format (big endian) */
TiffLittleEndian, /**< Tagged Image File Format (little endian) */
Utf16Text, /**< UTF-16 text */