diff --git a/EPUB3.c b/EPUB3.c index 1e99265..274c143 100644 --- a/EPUB3.c +++ b/EPUB3.c @@ -947,11 +947,29 @@ EPUB3Error EPUB3ProcessXMLReaderNodeForMetadataInOPF(EPUB3Ref epub, xmlTextReade } else if(itemId != NULL && xmlStrcmp(itemId, BAD_CAST epub->metadata->_uniqueIdentifierID) != 0) { (*context)->shouldParseTextNode = kEPUB3_NO; - EPUB3_FREE_AND_NULL(itemId); } + EPUB3_XML_FREE_AND_NULL(itemId); + } + break; + } + } + + if(epub->metadata->version == kEPUB3Version_2) { + // There is no standard for cover images in EPUB 2. This is the accepted ad hoc method for defining one + // http://blog.threepress.org/2009/11/20/best-practices-in-epub-cover-images/ + // http://www.mobipocket.com/dev/article.asp?BaseFolder=prcgen&File=cover.htm#IDPF2 + + if(xmlStrcmp(name, BAD_CAST "meta") == 0) { + if(xmlTextReaderHasAttributes(reader)) { + xmlChar * metaName = xmlTextReaderGetAttribute(reader, BAD_CAST "name"); + if(metaName != NULL && xmlStrcmp(metaName, BAD_CAST "cover") == 0) { + xmlChar * coverId = xmlTextReaderGetAttribute(reader, BAD_CAST "content"); + EPUB3MetadataSetCoverImageId(epub->metadata, (const char *)coverId); + EPUB3_XML_FREE_AND_NULL(coverId); + } + EPUB3_XML_FREE_AND_NULL(metaName); } } - } break; } @@ -1064,7 +1082,7 @@ EPUB3Error EPUB3ProcessXMLReaderNodeForSpineInOPF(EPUB3Ref epub, xmlTextReaderPt newItem->isLinear = kEPUB3_YES; epub->spine->linearItemCount++; } - EPUB3_FREE_AND_NULL(linear); + EPUB3_XML_FREE_AND_NULL(linear); newItem->idref = (char *)xmlTextReaderGetAttribute(reader, BAD_CAST "idref"); if(newItem->idref != NULL) { EPUB3ManifestItemListItemPtr manifestPtr = EPUB3ManifestFindItemWithId(epub->manifest, newItem->idref); @@ -1120,7 +1138,7 @@ EPUB3Error EPUB3ParseXMLReaderNodeForOPF(EPUB3Ref epub, xmlTextReaderPtr reader, } else if(*versionString == '3') { epub->metadata->version = kEPUB3Version_3; } - EPUB3_FREE_AND_NULL(versionString); + EPUB3_XML_FREE_AND_NULL(versionString); } } else if(xmlStrcmp(name, BAD_CAST "metadata") == 0) { @@ -1315,8 +1333,10 @@ EPUB3Error EPUB3ProcessXMLReaderNodeForNavMapInNCX(EPUB3Ref epub, xmlTextReaderP const xmlChar *value = xmlTextReaderValue(reader); if(value != NULL) { if(xmlStrcmp((*context)->tagName, BAD_CAST "text") == 0) { - EPUB3TocItemRef tocItem = (*context)->userInfo; - tocItem->title = strdup((const char *)value); + EPUB3TocItemRef tocItem = (EPUB3TocItemRef) (*context)->userInfo; + if(tocItem != NULL) { + tocItem->title = strdup((const char *)value); + } } } } diff --git a/EPUB3_private.h b/EPUB3_private.h index 2b8bcb2..5a26425 100644 --- a/EPUB3_private.h +++ b/EPUB3_private.h @@ -269,6 +269,14 @@ char * EPUB3CopyOfPathByDeletingLastPathComponent(const char * path); } \ } while(0); +#define EPUB3_XML_FREE_AND_NULL(__epub3_xml_ptr_to_null) do { \ + if(__epub3_xml_ptr_to_null != NULL) { \ + xmlFree(__epub3_xml_ptr_to_null); \ + __epub3_xml_ptr_to_null = NULL; \ + } \ +} while(0); + + #pragma mark - Hash function // via: http://www.azillionmonkeys.com/qed/hash.html #undef get16bits diff --git a/TestEPUB3Processor/check_EPUB3_parsing.c b/TestEPUB3Processor/check_EPUB3_parsing.c index a9b201a..7c58258 100644 --- a/TestEPUB3Processor/check_EPUB3_parsing.c +++ b/TestEPUB3Processor/check_EPUB3_parsing.c @@ -353,15 +353,19 @@ START_TEST(test_epub3_parse_data_from_opf_using_broken_medallion_epub) EPUB3Error error = EPUB3InitFromOPF(epub, "9781605428420_epub_opf_r1.opf"); fail_unless(error == kEPUB3Success); fail_if(epub->metadata == NULL); + assert(epub->metadata != NULL); fail_unless(epub->metadata->version == kEPUB3Version_2); fail_if(epub->metadata->title == NULL, "A title is required by the EPUB 3 spec."); + assert(epub->metadata->title != NULL); ck_assert_str_eq(epub->metadata->title, expectedTitle); fail_if(epub->metadata->identifier == NULL, "An identifier is required by the EPUB 3 spec."); + assert(epub->metadata->identifier != NULL); ck_assert_str_eq(epub->metadata->identifier, expectedIdentifier); fail_if(epub->metadata->language == NULL, "A language is required by the EPUB 3 spec."); + assert(epub->metadata->language != NULL); ck_assert_str_eq(epub->metadata->language, expectedLanguage); EPUB3ManifestItemRef item = EPUB3ManifestCopyItemWithId(epub->manifest, expItem1Id); @@ -462,6 +466,9 @@ START_TEST(test_epub3_parse_manifest_from_medallion_opf_data) const char * expItem2Href = "broken_medallion_1.ncx"; const char * expItem2MediaType = "application/x-dtbncx+xml"; + const char * expectedCoverImgId = "my_cover_image"; + const char * expectedCoverImgPath = "OEBPS/images/9781605421490_cvi.jpg"; + TEST_PATH_VAR_FOR_FILENAME(path, "broken_medallion_1.opf"); TEST_DATA_FILE_SIZE_SANITY_CHECK(path, 9265); EPUB3Ref blankEPUB = EPUB3Create(); @@ -508,6 +515,14 @@ START_TEST(test_epub3_parse_manifest_from_medallion_opf_data) ck_assert_str_eq(item->mediaType, expItem2MediaType); EPUB3ManifestItemRelease(item); + fail_if(blankEPUB->metadata->coverImageId == NULL, "Cover image was not found."); + assert(blankEPUB->metadata->coverImageId != NULL); + ck_assert_str_eq(blankEPUB->metadata->coverImageId, expectedCoverImgId); + + char * coverPath = EPUB3CopyCoverImagePath(blankEPUB); + ck_assert_str_eq(coverPath, expectedCoverImgPath); + free(coverPath); + free(newBuf); EPUB3MetadataRelease(blankMetadata); EPUB3ManifestRelease(blankManifest);