diff --git a/Sourcecode/private/extern/ezxml/src/private/private/PugiDoc.cpp b/Sourcecode/private/extern/ezxml/src/private/private/PugiDoc.cpp index 95522fdc5..de22ba2d2 100755 --- a/Sourcecode/private/extern/ezxml/src/private/private/PugiDoc.cpp +++ b/Sourcecode/private/extern/ezxml/src/private/private/PugiDoc.cpp @@ -38,54 +38,69 @@ namespace ezxml ss << "pugixml parsing failed - '"; switch( parseResult.status ) { - case pugi::status_file_not_found:ss << "status_file_not_found'"; + case pugi::status_file_not_found: + ss << "status_file_not_found'"; break; - case pugi::status_io_error:ss << "status_io_error'"; + case pugi::status_io_error: + ss << "status_io_error'"; break; - case pugi::status_out_of_memory:ss << "status_out_of_memory'"; + case pugi::status_out_of_memory: + ss << "status_out_of_memory'"; break; - case pugi::status_internal_error:ss << "status_internal_error'"; + case pugi::status_internal_error: + ss << "status_internal_error'"; break; - case pugi::status_unrecognized_tag:ss << "status_unrecognized_tag'"; + case pugi::status_unrecognized_tag: + ss << "status_unrecognized_tag'"; break; - case pugi::status_bad_pi:ss << "status_bad_pi'"; + case pugi::status_bad_pi: + ss << "status_bad_pi'"; break; - case pugi::status_bad_comment:ss << "status_bad_comment'"; + case pugi::status_bad_comment: + ss << "status_bad_comment'"; break; - case pugi::status_bad_cdata:ss << "status_bad_cdata'"; + case pugi::status_bad_cdata: + ss << "status_bad_cdata'"; break; - case pugi::status_bad_doctype:ss << "status_bad_doctype'"; + case pugi::status_bad_doctype: + ss << "status_bad_doctype'"; break; - case pugi::status_bad_pcdata:ss << "status_bad_pcdata'"; + case pugi::status_bad_pcdata: + ss << "status_bad_pcdata'"; break; - case pugi::status_bad_start_element:ss << "status_bad_start_element'"; + case pugi::status_bad_start_element: + ss << "status_bad_start_element'"; break; - case pugi::status_bad_attribute:ss << "status_bad_attribute'"; + case pugi::status_bad_attribute: + ss << "status_bad_attribute'"; break; - case pugi::status_end_element_mismatch:ss << "status_end_element_mismatch'"; + case pugi::status_end_element_mismatch: + ss << "status_end_element_mismatch'"; break; - case pugi::status_append_invalid_root:ss << "status_append_invalid_root'"; + case pugi::status_append_invalid_root: + ss << "status_append_invalid_root'"; break; - case pugi::status_no_document_element:ss << "status_no_document_element'"; + case pugi::status_no_document_element: + ss << "status_no_document_element'"; break; default:break; } - ss << " - " << parseResult.description(); + EZXML_THROW( ss.str() ); } else if( myDoc.begin() == myDoc.end() ) diff --git a/Sourcecode/private/mx/api/DocumentManager.cpp b/Sourcecode/private/mx/api/DocumentManager.cpp index 46435e417..331e7c16c 100755 --- a/Sourcecode/private/mx/api/DocumentManager.cpp +++ b/Sourcecode/private/mx/api/DocumentManager.cpp @@ -57,7 +57,37 @@ namespace mx int DocumentManager::createFromFile( const std::string& filePath ) { auto xdoc = ::ezxml::XFactory::makeXDoc(); - xdoc->loadFile( filePath ); + + try + { + xdoc->loadFile( filePath ); + } + catch ( std::exception& e ) + { + const std::string originalMessage = e.what(); + + const auto fileExtension = []( const std::string& filePath ) + { + const auto dotPos = filePath.find_last_of( '.' ); + if( dotPos == std::string::npos || dotPos == filePath.size() - 1 ) + { + return std::string{ "" }; + } + + return filePath.substr( dotPos + 1 ); + }; + + if ( ( originalMessage.find( "status_no_document_element" ) != std::string::npos) && + fileExtension( filePath ) == "mxl" ) + { + std::stringstream ss; + ss << "it looks like you are trying to parse a compressed musicxml file, which is currently " + << "unsupported. https://github.com/webern/mx/issues/66 (" + << originalMessage << ")"; + MX_THROW( ss.str() ); + } + } + auto mxdoc = mx::core::makeDocument(); std::stringstream messages; auto isSuccess = mxdoc->fromXDoc( messages, *xdoc ); diff --git a/Sourcecode/private/mxtest/api/MxlTest.cpp b/Sourcecode/private/mxtest/api/MxlTest.cpp new file mode 100644 index 000000000..d292bbe28 --- /dev/null +++ b/Sourcecode/private/mxtest/api/MxlTest.cpp @@ -0,0 +1,49 @@ +// MusicXML Class Library +// Copyright (c) by Matthew James Briggs +// Distributed under the MIT License + +#include "cpul/cpulTestHarness.h" +#include "mx/api/DocumentManager.h" +#include "mxtest/file/MxFileRepository.h" +#include + +namespace mxtest +{ + static constexpr const char* const EXPECTED_MXL_ERROR_MESSAGE = + "it looks like you are trying to parse a compressed musicxml file, which is currently unsupported."; +} + + +TEST( Mxl, TemporaryNoCrashTest ) +{ + const auto filepath = mxtest::MxFileRepository::getFullPath( "Dichterliebe01.mxl" ); + auto& docMgr = mx::api::DocumentManager::getInstance(); + std::string actualMessage; + const std::string expectedMessage = mxtest::EXPECTED_MXL_ERROR_MESSAGE; + bool isExceptionThrown = false; + + try + { + docMgr.createFromFile( filepath ); + } + catch ( std::exception& e ) + { + isExceptionThrown = true; + actualMessage = e.what(); + } + + if( !isExceptionThrown ) + { + FAIL( "an exception was expected during docMgr.createFromFile( filepath ); but none was thrown" ); + } + + const auto isFound = actualMessage.find( expectedMessage ) != std::string::npos; + + if( !isFound ) + { + std::stringstream failure; + failure << "expected to find the string '" << expectedMessage << "' in the error message '" + << actualMessage << "' but did not."; + FAIL( failure.str() ); + } +} diff --git a/Sourcecode/private/mxtest/import/ExpectedFiles.cpp b/Sourcecode/private/mxtest/import/ExpectedFiles.cpp index fc3860afd..00f1b749d 100755 --- a/Sourcecode/private/mxtest/import/ExpectedFiles.cpp +++ b/Sourcecode/private/mxtest/import/ExpectedFiles.cpp @@ -143,10 +143,6 @@ namespace mxtest openInputFile( inputFile, fullPath ); auto xdoc = ::ezxml::XFactory::makeXDoc(); xdoc->loadStream( inputFile ); -// std::stringstream ss; -// xdoc->saveStream( ss ); -// std::cout << ss.str() << std::endl; -// inputFile.close(); return xdoc; } @@ -315,7 +311,7 @@ namespace mxtest q.push_front( std::move( fut ) ); } - while( q.size() > 0 ) + while( q.empty() ) { for( auto qIter = q.begin(); qIter != q.end(); ++qIter ) {