diff --git a/src/common/chapter_element_mapping.cpp b/src/common/chapter_element_mapping.cpp deleted file mode 100644 index 2d7158871..000000000 --- a/src/common/chapter_element_mapping.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* - * mkvmerge -- utility for splicing together matroska files - * from component media subtypes - * - * Distributed under the GPL - * see the file COPYING for details - * or visit http://www.gnu.org/copyleft/gpl.html - * - * $Id$ - * - * Mapping from XML elements to EBML elements - * - * Written by Moritz Bunkus . - */ - -#include "ebml/EbmlElement.h" - -#include "chapters.h" - -namespace libmatroska { - extern EbmlId KaxChapters_TheId; - extern EbmlId KaxEditionEntry_TheId; - extern EbmlId KaxEditionUID_TheId; - extern EbmlId KaxEditionFlagHidden_TheId; - extern EbmlId KaxEditionFlagDefault_TheId; - extern EbmlId KaxEditionManaged_TheId; - extern EbmlId KaxChapterAtom_TheId; - extern EbmlId KaxChapterUID_TheId; - extern EbmlId KaxChapterTimeStart_TheId; - extern EbmlId KaxChapterTimeEnd_TheId; - extern EbmlId KaxChapterFlagHidden_TheId; - extern EbmlId KaxChapterFlagEnabled_TheId; - extern EbmlId KaxChapterPhysicalEquiv_TheId; - extern EbmlId KaxChapterTrack_TheId; - extern EbmlId KaxChapterTrackNumber_TheId; - extern EbmlId KaxChapterDisplay_TheId; - extern EbmlId KaxChapterString_TheId; - extern EbmlId KaxChapterLanguage_TheId; - extern EbmlId KaxChapterCountry_TheId; - extern EbmlId KaxChapterProcess_TheId; - extern EbmlId KaxChapterProcessTime_TheId; -} - -parser_element_t chapter_elements[] = { - {"Chapters", ebmlt_master, 0, 0, 0, KaxChapters_TheId, NULL, NULL}, - - {"EditionEntry", ebmlt_master, 1, 0, 0, KaxEditionEntry_TheId, NULL, NULL}, - {"EditionUID", ebmlt_uint, 2, 0, NO_MAX_VALUE, KaxEditionUID_TheId, NULL, - NULL}, - {"EditionFlagHidden", ebmlt_bool, 2, 0, 0, KaxEditionFlagHidden_TheId, - NULL, NULL}, - {"EditionManaged", ebmlt_uint, 2, 0, NO_MAX_VALUE, KaxEditionManaged_TheId, - NULL, NULL}, - {"EditionFlagDefault", ebmlt_bool, 2, 0, 0, KaxEditionFlagDefault_TheId, - NULL, NULL}, - - {"ChapterAtom", ebmlt_master, 2, 0, 0, KaxChapterAtom_TheId, NULL, - NULL}, - {"ChapterUID", ebmlt_uint, 3, 0, NO_MAX_VALUE, KaxChapterUID_TheId, NULL, - NULL}, - {"ChapterTimeStart", ebmlt_time, 3, 0, 0, KaxChapterTimeStart_TheId, NULL, - NULL}, - {"ChapterTimeEnd", ebmlt_time, 3, 0, 0, KaxChapterTimeEnd_TheId, NULL, - NULL}, - {"ChapterFlagHidden", ebmlt_bool, 3, 0, 0, KaxChapterFlagHidden_TheId, - NULL, NULL}, - {"ChapterFlagEnabled", ebmlt_bool, 3, 0, 0, KaxChapterFlagEnabled_TheId, - NULL, NULL}, - - {"ChapterTrack", ebmlt_master, 3, 0, 0, KaxChapterTrack_TheId, - NULL, NULL}, - {"ChapterTrackNumber", ebmlt_uint, 4, 0, NO_MAX_VALUE, - KaxChapterTrackNumber_TheId, NULL, NULL}, - - {"ChapterDisplay", ebmlt_master, 3, 0, 0, KaxChapterDisplay_TheId, - NULL, NULL}, - {"ChapterString", ebmlt_ustring, 4, 0, 0, KaxChapterString_TheId, - NULL, NULL}, - {"ChapterLanguage", ebmlt_string, 4, 0, 0, KaxChapterLanguage_TheId, - NULL, NULL}, - {"ChapterCountry", ebmlt_string, 4, 0, 0, KaxChapterCountry_TheId, - NULL, NULL}, - - {NULL, ebmlt_master, 0, 0, 0, EbmlId((uint32_t)0, 0), NULL, NULL} -}; - diff --git a/src/common/ebml_ids.h b/src/common/ebml_ids.h deleted file mode 100644 index c2376942c..000000000 --- a/src/common/ebml_ids.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * mkvmerge -- utility for splicing together matroska files - * from component media subtypes - * - * Distributed under the GPL - * see the file COPYING for details - * or visit http://www.gnu.org/copyleft/gpl.html - * - * $Id$ - * - * Declarations of external EBML Ids found in libebml - * - * Written by Moritz Bunkus . - */ - -#ifndef __EBML_IDS_H -#define __EBML_IDS_H - -#include "ebml/EbmlElement.h" - -namespace libmatroska { - extern EbmlId KaxChapters_TheId; - extern EbmlId KaxEditionEntry_TheId; - extern EbmlId KaxEditionUID_TheId; - extern EbmlId KaxEditionFlagHidden_TheId; - extern EbmlId KaxEditionFlagDefault_TheId; - extern EbmlId KaxEditionManaged_TheId; - extern EbmlId KaxChapterAtom_TheId; - extern EbmlId KaxChapterUID_TheId; - extern EbmlId KaxChapterTimeStart_TheId; - extern EbmlId KaxChapterTimeEnd_TheId; - extern EbmlId KaxChapterFlagHidden_TheId; - extern EbmlId KaxChapterFlagEnabled_TheId; - extern EbmlId KaxChapterPhysicalEquiv_TheId; - extern EbmlId KaxChapterTrack_TheId; - extern EbmlId KaxChapterTrackNumber_TheId; - extern EbmlId KaxChapterDisplay_TheId; - extern EbmlId KaxChapterString_TheId; - extern EbmlId KaxChapterLanguage_TheId; - extern EbmlId KaxChapterCountry_TheId; - extern EbmlId KaxChapterProcess_TheId; - extern EbmlId KaxChapterProcessTime_TheId; -} - -#endif diff --git a/src/common/tagparser_end.cpp b/src/common/tagparser_end.cpp deleted file mode 100644 index 84285b8c9..000000000 --- a/src/common/tagparser_end.cpp +++ /dev/null @@ -1,705 +0,0 @@ -/* - * mkvmerge -- utility for splicing together matroska files - * from component media subtypes - * - * Distributed under the GPL - * see the file COPYING for details - * or visit http://www.gnu.org/copyleft/gpl.html - * - * $Id$ - * - * XML tag parser. Functions for the end tags + value parsers - * - * Written by Moritz Bunkus . - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include "base64.h" -#include "common.h" -#include "commonebml.h" -#include "iso639.h" -#include "mm_io.h" -#include "tagparser.h" - -using namespace std; -using namespace libebml; -using namespace libmatroska; - -static void -el_get_uint(parser_data_t *pdata, - EbmlElement *el, - uint64_t min_value = 0, - uint64_t max_value = 9223372036854775807ULL) { - int64 value; - - strip(*pdata->bin); - if (!parse_int(pdata->bin->c_str(), value)) - tperror(pdata, "Expected an unsigned integer but found '%s'.", - pdata->bin->c_str()); - if (value < min_value) - tperror(pdata, "Unsigned integer (%lld) is too small. Mininum value is " - "%lld.", value, min_value); - if (value > max_value) - tperror(pdata, "Unsigned integer (%lld) is too big. Maximum value is " - "%lld.", value, max_value); - - *(static_cast(el)) = value; -} - -static void -el_get_sint(parser_data_t *pdata, - EbmlElement *el, - int64_t min_value = -9223372036854775807LL-1) { - int64 value; - - strip(*pdata->bin); - if (!parse_int(pdata->bin->c_str(), value)) - tperror(pdata, "Expected a signed integer but found '%s'.", - pdata->bin->c_str()); - if (value < min_value) - tperror(pdata, "Signed integer (%lld) is too small. Mininum value is " - "%lld.\n", value, min_value); - - *(static_cast(el)) = value; -} - -static void -el_get_float(parser_data_t *pdata, - EbmlElement *el, - float min_value = (float)1.40129846432481707e-45) { - char *endptr; - float value; - - strip(*pdata->bin); - value = (float)strtod(pdata->bin->c_str(), &endptr); - - if (((value == 0.0) && (endptr == pdata->bin->c_str())) || - (errno == ERANGE)) - tperror(pdata, "Expected a floating point number but found '%s'.", - pdata->bin->c_str()); - - *(static_cast(el)) = value; -} - -static void -el_get_string(parser_data_t *pdata, - EbmlElement *el, - bool check_language = false) { - strip(*pdata->bin); - if (pdata->bin->length() == 0) - tperror(pdata, "Expected a string but found only whitespaces."); - - if (check_language && !is_valid_iso639_2_code(pdata->bin->c_str())) - tperror(pdata, "'%s' is not a valid ISO639-2 language code. See the " - "output of 'mkvmerge --list-languages' for a list of all " - "valid language codes.", pdata->bin->c_str()); - - *(static_cast(el)) = pdata->bin->c_str(); -} - -static void -el_get_utf8string(parser_data_t *pdata, - EbmlElement *el) { - strip(*pdata->bin); - if (pdata->bin->length() == 0) - tperror(pdata, "Expected a string but found only whitespaces."); - - *(static_cast(el)) = - cstrutf8_to_UTFstring(pdata->bin->c_str()); -} - -static void -el_get_binary(parser_data_t *pdata, - EbmlElement *el) { - int64_t result; - binary *buffer; - mm_io_c *io; - - result = 0; - buffer = NULL; - strip(*pdata->bin, true); - if (pdata->bin->length() == 0) - tperror(pdata, "Found neither Base64 encoded data nor '@file' to read " - "binary data from."); - - if ((*pdata->bin)[0] == '@') { - if (pdata->bin->length() == 1) - tperror(pdata, "No filename found after the '@'."); - try { - io = new mm_io_c(&(pdata->bin->c_str())[1], MODE_READ); - io->setFilePointer(0, seek_end); - result = io->getFilePointer(); - io->setFilePointer(0, seek_beginning); - if (result <= 0) - tperror(pdata, "The file '%s' is empty.", &(pdata->bin->c_str())[1]); - buffer = new binary[result]; - io->read(buffer, result); - delete io; - } catch(...) { - tperror(pdata, "Could not open/read the file '%s'.", - &(pdata->bin->c_str())[1]); - } - - } else { - buffer = new binary[pdata->bin->length() / 4 * 3 + 1]; - result = base64_decode(*pdata->bin, (unsigned char *)buffer); - if (result < 0) - tperror(pdata, "Could not decode the Base64 encoded data - it seems to " - "be broken."); - } - - (static_cast(el))->SetBuffer(buffer, result); -} - -// ISO 8601 format: 2003-07-17T19:50:53+0200 -// 012345678901234567890123 -// 1 2 -static void -el_get_date(parser_data_t *pdata, - EbmlElement *el) { - const char *errmsg = "Expected a date in ISO 8601 format but found '%s'. " - "The ISO 8601 date format looks like this: YYYY-MM-DDTHH:MM:SS:-TZTZ, " - "e.g. 2003-07-17T19:50:52+0200. The time zone (TZ) may also be negative."; - char *p; - int year, month, day, hour, minute, second, time_zone, offset; - char tz_sign; - struct tm t; - time_t tme; -#ifdef SYS_UNIX - struct timezone tz; -#else - time_t tme_local, tme_gm; -#endif - - strip(*pdata->bin); - p = safestrdup(pdata->bin->c_str()); - - if (pdata->bin->length() != 24) - tperror(pdata, errmsg, pdata->bin->c_str()); - - if ((p[4] != '-') || (p[7] != '-') || (p[10] != 'T') || - (p[13] != ':') || (p[16] != ':') || (p[19] != '+')) - tperror(pdata, errmsg, pdata->bin->c_str()); - - p[4] = 0; - p[7] = 0; - p[10] = 0; - p[13] = 0; - p[16] = 0; - tz_sign = p[19]; - p[19] = 0; - - if (!parse_int(p, year) || !parse_int(&p[5], month) || - !parse_int(&p[8], day) || !parse_int(&p[11], hour) || - !parse_int(&p[14], minute) || !parse_int(&p[17], second) || - !parse_int(&p[20], time_zone)) - tperror(pdata, errmsg, pdata->bin->c_str()); - - if (year < 1900) - tperror(pdata, "Invalid year given (%d).", year); - if ((month < 1) || (month > 12)) - tperror(pdata, "Invalid month given (%d).", month); - if ((day < 1) || (day > 31)) - tperror(pdata, "Invalid day given (%d).", day); - if ((hour < 0) || (hour > 23)) - tperror(pdata, "Invalid hour given (%d).", hour); - if ((minute < 0) || (minute > 59)) - tperror(pdata, "Invalid minute given (%d).", minute); - if ((second < 0) || (second > 59)) - tperror(pdata, "Invalid second given (%d).", second); - if ((tz_sign != '+') && (tz_sign != '-')) - tperror(pdata, "Invalid time zone given (%c%s).", tz_sign, &p[20]); - if ((time_zone < 0) || (time_zone > 1200)) - tperror(pdata, "Invalid time zone given (%c%s).", tz_sign, &p[20]); - - memset(&t, 0, sizeof(struct tm)); - t.tm_year = year - 1900; - t.tm_mon = month - 1; - t.tm_mday = day; - t.tm_hour = hour; - t.tm_min = minute; - t.tm_sec = second; - t.tm_isdst = -1; - tme = mktime(&t); - if (tme == (time_t)-1) - tperror(pdata, "Invalid date specified (%s).", pdata->bin->c_str()); - offset = (((time_zone / 100) * 60) + (time_zone % 100)) * 60; - if (tz_sign == '+') - offset *= -1; - tme += offset; -#ifdef SYS_UNIX - gettimeofday(NULL, &tz); - tme -= tz.tz_minuteswest * 60; -#else - tme_local = mktime(localtime(&tme)); - tme_gm = mktime(gmtime(&tme)); - tme -= (tme_gm - tme_local); -#endif - if (tme < 0) - tperror(pdata, "Invalid date specified (%s).", pdata->bin->c_str()); - - safefree(p); - - (static_cast(el))->SetEpochDate(tme); -} - -static bool -is_multicomment(parser_data_t *pdata, - const char *name) { - int parent; - - parent = (*pdata->parents)[pdata->parents->size() - 2]; - - if (parent != E_MultiComment) - return false; - - if (!strcmp(name, "Name")) - el_get_string(pdata, &GetChild(*pdata->m_comment)); - else if (!strcmp(name, "Comments")) - el_get_utf8string(pdata, &GetChild - (*pdata->m_comment)); - else if (!strcmp(name, "Language")) - el_get_string(pdata, &GetChild - (*pdata->m_comment), true); - - return true; -} - -static void -end_level1(parser_data_t *pdata, - const char *) { - // Can only be "Tag" - pdata->targets = NULL; - pdata->general = NULL; - pdata->genres = NULL; - pdata->audio_specific = NULL; - pdata->image_specific = NULL; - pdata->m_commercial = NULL; - pdata->m_date = NULL; - pdata->m_entity = NULL; - pdata->m_identifier = NULL; - pdata->m_legal = NULL; - pdata->m_title = NULL; - pdata->m_comment = NULL; -} - -static void -end_level2(parser_data_t *pdata, - const char *name) { - if (!strcmp(name, "Targets")) { - GetChild(*pdata->targets); - pdata->track_uid = NULL; - pdata->chapter_uid = NULL; - pdata->edition_uid = NULL; - pdata->m_comment = NULL; - - } else if (!strcmp(name, "General")) { - pdata->keywords = NULL; - pdata->rec_location = NULL; - pdata->m_comment = NULL; - - } else if (!strcmp(name, "Genres")) { - pdata->audio_genre = NULL; - pdata->video_genre = NULL; - pdata->m_comment = NULL; - - } else if (!strcmp(name, "AudioSpecific")) { - pdata->m_comment = NULL; - - } else if (!strcmp(name, "ImageSpecific")) { - pdata->m_comment = NULL; - - } else if (!strcmp(name, "MultiCommercial")) { - pdata->commercial = NULL; - pdata->m_comment = NULL; - - } else if (!strcmp(name, "MultiDate")) { - pdata->date = NULL; - pdata->m_comment = NULL; - - } else if (!strcmp(name, "MultiEntity")) { - pdata->entity = NULL; - pdata->m_comment = NULL; - - } else if (!strcmp(name, "MultiIdentifier")) { - pdata->identifier = NULL; - pdata->m_comment = NULL; - - } else if (!strcmp(name, "MultiLegal")) { - pdata->legal = NULL; - pdata->m_comment = NULL; - - } else if (!strcmp(name, "MultiTitle")) { - pdata->title = NULL; - pdata->m_comment = NULL; - - } else if (!strcmp(name, "MultiComment")) { - - } -} - -static void -end_level3(parser_data_t *pdata, - const char *name) { - string parent_name; - int parent; - - if (is_multicomment(pdata, name)) - return; - - parent_name = (*pdata->parent_names)[pdata->parent_names->size() - 2]; - parent = (*pdata->parents)[pdata->parents->size() - 2]; - - if (parent == E_Targets) { - if (!strcmp(name, "TrackUID")) - el_get_uint(pdata, pdata->track_uid); - else if (!strcmp(name, "ChapterUID")) - el_get_uint(pdata, pdata->chapter_uid); - else if (!strcmp(name, "EditionUID")) - el_get_uint(pdata, pdata->edition_uid); - else if (!strcmp(name, "TargetType")) - el_get_string(pdata, &GetChild(*pdata->targets)); - - } else if (parent == E_General) { - if (!strcmp(name, "Subject")) - el_get_utf8string(pdata, &GetChild(*pdata->general)); - else if (!strcmp(name, "Bibliography")) - el_get_utf8string(pdata, &GetChild(*pdata->general)); - else if (!strcmp(name, "Language")) - el_get_string(pdata, &GetChild(*pdata->general), true); - else if (!strcmp(name, "Rating")) - el_get_binary(pdata, &GetChild(*pdata->general)); - else if (!strcmp(name, "Encoder")) - el_get_utf8string(pdata, &GetChild(*pdata->general)); - else if (!strcmp(name, "EncodeSettings")) - el_get_utf8string(pdata, - &GetChild(*pdata->general)); - else if (!strcmp(name, "File")) - el_get_utf8string(pdata, &GetChild(*pdata->general)); - else if (!strcmp(name, "ArchivalLocation")) - el_get_utf8string(pdata, - &GetChild(*pdata->general)); - else if (!strcmp(name, "Keywords")) - el_get_utf8string(pdata, pdata->keywords); - else if (!strcmp(name, "Mood")) - el_get_utf8string(pdata, &GetChild(*pdata->general)); - else if (!strcmp(name, "RecordLocation")) - el_get_string(pdata, pdata->rec_location); - else if (!strcmp(name, "Source")) - el_get_utf8string(pdata, &GetChild(*pdata->general)); - else if (!strcmp(name, "SourceForm")) - el_get_utf8string(pdata, &GetChild(*pdata->general)); - else if (!strcmp(name, "Product")) - el_get_utf8string(pdata, &GetChild(*pdata->general)); - else if (!strcmp(name, "OriginalMediaType")) - el_get_utf8string(pdata, - &GetChild(*pdata->general)); - else if (!strcmp(name, "PlayCounter")) - el_get_uint(pdata, &GetChild(*pdata->general)); - else if (!strcmp(name, "Popularimeter")) - el_get_sint(pdata, &GetChild(*pdata->general)); - - } else if (parent == E_Genres) { - if (!strcmp(name, "AudioGenre")) - el_get_string(pdata, pdata->audio_genre); - else if (!strcmp(name, "VideoGenre")) - el_get_binary(pdata, pdata->video_genre); - else if (!strcmp(name, "SubGenre")) - el_get_string(pdata, &GetChild(*pdata->genres)); - - } else if (parent == E_AudioSpecific) { - if (!strcmp(name, "AudioEncryption")) - el_get_binary(pdata, - &GetChild(*pdata->audio_specific)); - else if (!strcmp(name, "AudioGain")) - el_get_float(pdata, - &GetChild(*pdata->audio_specific), - 0.000000001); - else if (!strcmp(name, "AudioPeak")) - el_get_float(pdata, &GetChild(*pdata->audio_specific)); - else if (!strcmp(name, "BPM")) - el_get_float(pdata, &GetChild(*pdata->audio_specific)); - else if (!strcmp(name, "Equalisation")) - el_get_binary(pdata, - &GetChild(*pdata->audio_specific)); - else if (!strcmp(name, "DiscTrack")) - el_get_uint(pdata, &GetChild(*pdata->audio_specific)); - else if (!strcmp(name, "SetPart")) - el_get_uint(pdata, &GetChild(*pdata->audio_specific)); - else if (!strcmp(name, "InitialKey")) - el_get_string(pdata, - &GetChild(*pdata->audio_specific)); - else if (!strcmp(name, "OfficialAudioFileURL")) - el_get_string(pdata, &GetChild - (*pdata->audio_specific)); - else if (!strcmp(name, "OfficialAudioSourceURL")) - el_get_string(pdata, &GetChild - (*pdata->audio_specific)); - - } else if (parent == E_ImageSpecific) { - if (!strcmp(name, "CaptureDPI")) - el_get_uint(pdata, &GetChild(*pdata->image_specific)); - else if (!strcmp(name, "CaptureLightness")) - el_get_binary(pdata, &GetChild - (*pdata->image_specific)); - else if (!strcmp(name, "CapturePaletteSetting")) - el_get_uint(pdata, &GetChild - (*pdata->image_specific)); - else if (!strcmp(name, "CaptureSharpness")) - el_get_binary(pdata, &GetChild - (*pdata->image_specific)); - else if (!strcmp(name, "Cropped")) - el_get_utf8string(pdata, &GetChild - (*pdata->image_specific)); - else if (!strcmp(name, "OriginalDimensions")) - el_get_string(pdata, &GetChild - (*pdata->image_specific)); - - } else if (parent == E_MultiCommercial) { - pdata->c_url = NULL; - pdata->c_email = NULL; - pdata->m_price = NULL; - pdata->m_comment = NULL; - - } else if (parent == E_MultiDate) { - pdata->m_comment = NULL; - - } else if (parent == E_MultiEntity) { - pdata->e_url = NULL; - pdata->e_email = NULL; - pdata->m_comment = NULL; - - } else if (parent == E_MultiIdentifier) { - pdata->m_comment = NULL; - - } else if (parent == E_MultiLegal) { - pdata->l_url = NULL; - pdata->m_comment = NULL; - - } else if (parent == E_MultiTitle) { - pdata->t_url = NULL; - pdata->t_email = NULL; - pdata->m_comment = NULL; - - } else - die("Unknown parent: level 3, %d", parent); -} - -static void -end_level4(parser_data_t *pdata, - const char *name) { - string parent_name; - int parent; - - if (is_multicomment(pdata, name)) - return; - - parent_name = (*pdata->parent_names)[pdata->parent_names->size() - 2]; - parent = (*pdata->parents)[pdata->parents->size() - 2]; - - if (parent == E_Commercial) { - if (!strcmp(name, "CommercialType")) - el_get_uint(pdata, &GetChild - (*pdata->commercial), 1); - else if (!strcmp(name, "Address")) - el_get_utf8string(pdata, &GetChild - (*pdata->commercial)); - else if (!strcmp(name, "URL")) - el_get_string(pdata, pdata->c_url); - else if (!strcmp(name, "Email")) - el_get_string(pdata, pdata->c_email); - else if (!strcmp(name, "MultiPrice")) { - pdata->m_comment = NULL; - } - - } else if (parent == E_Date) { - if (!strcmp(name, "DateType")) - el_get_uint(pdata, &GetChild - (*pdata->date), 1); - else if (!strcmp(name, "Begin")) - el_get_date(pdata, &GetChild - (*pdata->date)); - else if (!strcmp(name, "End")) - el_get_date(pdata, &GetChild - (*pdata->date)); - - } else if (parent == E_Entity) { - if (!strcmp(name, "EntityType")) - el_get_uint(pdata, &GetChild - (*pdata->entity), 1); - else if (!strcmp(name, "Name")) - el_get_utf8string(pdata, &GetChild - (*pdata->entity)); - else if (!strcmp(name, "URL")) - el_get_string(pdata, pdata->e_url); - else if (!strcmp(name, "Email")) - el_get_string(pdata, pdata->e_email); - else if (!strcmp(name, "Address")) - el_get_utf8string(pdata, &GetChild - (*pdata->entity)); - - } else if (parent == E_Identifier) { - if (!strcmp(name, "IdentifierType")) - el_get_uint(pdata, &GetChild - (*pdata->identifier), 1); - else if (!strcmp(name, "Binary")) - el_get_binary(pdata, &GetChild - (*pdata->identifier)); - else if (!strcmp(name, "String")) - el_get_utf8string(pdata, &GetChild - (*pdata->identifier)); - - } else if (parent == E_Legal) { - if (!strcmp(name, "LegalType")) - el_get_uint(pdata, &GetChild - (*pdata->legal), 1); - else if (!strcmp(name, "URL")) - el_get_string(pdata, pdata->l_url); - else if (!strcmp(name, "Address")) - el_get_utf8string(pdata, &GetChild - (*pdata->legal)); - else if (!strcmp(name, "Content")) - el_get_utf8string(pdata, &GetChild - (*pdata->legal)); - - } else if (parent == E_Title) { - if (!strcmp(name, "TitleType")) - el_get_uint(pdata, &GetChild - (*pdata->title), 1); - else if (!strcmp(name, "Name")) - el_get_utf8string(pdata, &GetChild - (*pdata->title)); - else if (!strcmp(name, "SubTitle")) - el_get_utf8string(pdata, &GetChild - (*pdata->title)); - else if (!strcmp(name, "Edition")) - el_get_utf8string(pdata, &GetChild - (*pdata->title)); - else if (!strcmp(name, "Address")) - el_get_utf8string(pdata, &GetChild - (*pdata->title)); - else if (!strcmp(name, "URL")) - el_get_string(pdata, pdata->t_url); - else if (!strcmp(name, "Email")) - el_get_string(pdata, pdata->t_email); - else if (!strcmp(name, "Language")) - el_get_string(pdata, &GetChild - (*pdata->title), true); - - } else - die("Unknown parent: level 4, %d", parent); -} - -static void -end_level5(parser_data_t *pdata, - const char *name) { - string parent_name; - int parent; - - if (is_multicomment(pdata, name)) - return; - - parent_name = (*pdata->parent_names)[pdata->parent_names->size() - 2]; - parent = (*pdata->parents)[pdata->parents->size() - 2]; - - if (parent == E_MultiPrice) { - if (!strcmp(name, "Currency")) - el_get_string(pdata, &GetChild - (*pdata->m_price)); - else if (!strcmp(name, "Amount")) - el_get_float(pdata, &GetChild - (*pdata->m_price)); - else if (!strcmp(name, "PriceDate")) - el_get_date(pdata, &GetChild - (*pdata->m_price)); - - } else - die("Unknown parent: level 4, %d", parent); -} - -static void -end_level6(parser_data_t *pdata, - const char *name) { - if (is_multicomment(pdata, name)) - return; - - die("tagparser_end: Unknown element. This should not have happened."); -} - -static void -end_simple(parser_data_t *pdata, - const char *name) { - - if (!strcmp(name, "Simple")) { - pdata->simple_tags->pop_back(); - if (pdata->simple_tags->size() == 0) - pdata->parsing_simple = false; - - } else { - KaxTagSimple *simple = - (*pdata->simple_tags)[pdata->simple_tags->size() - 1]; - if (!strcmp(name, "Name")) - el_get_utf8string(pdata, &GetChild(*simple)); - else if (!strcmp(name, "String")) - el_get_utf8string(pdata, &GetChild(*simple)); - else if (!strcmp(name, "Binary")) - el_get_binary(pdata, &GetChild(*simple)); - else if (!strcmp(name, "TagLanguage")) - el_get_string(pdata, &GetChild(*simple), true); - else if (!strcmp(name, "DefaultLanguage")) - el_get_uint(pdata, &GetChild(*simple), 0, 1); - } -} - -void -end_xml_tag_element(void *user_data, - const char *name) { - parser_data_t *pdata; - - pdata = (parser_data_t *)user_data; - - if (pdata->data_allowed && (pdata->bin == NULL)) - tperror(pdata, "Element <%s> does not contain any data.", name); - - if (pdata->parsing_simple) - end_simple(pdata, name); - else if (pdata->depth == 1) - ; // Nothing to do here! - else if (pdata->depth == 2) - end_level1(pdata, name); - else if (pdata->depth == 3) - end_level2(pdata, name); - else if (pdata->depth == 4) - end_level3(pdata, name); - else if (pdata->depth == 5) - end_level4(pdata, name); - else if (pdata->depth == 6) - end_level5(pdata, name); - else if (pdata->depth == 7) - end_level6(pdata, name); - else - die("tagparser_end: depth > 7: %d", pdata->depth); - - if (pdata->bin != NULL) { - delete pdata->bin; - pdata->bin = NULL; - } - - pdata->data_allowed = false; - pdata->depth--; - pdata->parent_names->pop_back(); - pdata->parents->pop_back(); -} diff --git a/src/common/tagparser_start.cpp b/src/common/tagparser_start.cpp deleted file mode 100644 index c505c26d5..000000000 --- a/src/common/tagparser_start.cpp +++ /dev/null @@ -1,479 +0,0 @@ -/* - * mkvmerge -- utility for splicing together matroska files - * from component media subtypes - * - * Distributed under the GPL - * see the file COPYING for details - * or visit http://www.gnu.org/copyleft/gpl.html - * - * $Id$ - * - * XML tag parser. Functions for the start tags + helper functions - * - * Written by Moritz Bunkus . - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include "base64.h" -#include "common.h" -#include "commonebml.h" -#include "mm_io.h" -#include "tagparser.h" -#include "xml_element_mapping.h" - -#include -#include - -using namespace std; -using namespace libebml; -using namespace libmatroska; - -typedef struct { - XML_Parser parser; - - const char *file_name; - - int depth; - bool done_reading, data_allowed; - - string *bin; - - vector *parents; - vector *parent_idxs; - - KaxTags *tags; - - jmp_buf parse_error_jmp; - string *parse_error_msg; -} parser_data_t; - -#define parent_elt (*((parser_data_t *)pdata)->parents) \ - [((parser_data_t *)pdata)->parents->size() - 1] -#define parent_name _parent_name(parent_elt) -#define CPDATA (parser_data_t *)pdata - -static const char * -_parent_name(EbmlElement *e) { - int i; - - for (i = 0; tag_elements[i].name != NULL; i++) - if (tag_elements[i].id == e->Generic().GlobalId) - return tag_elements[i].name; - - return "(none)"; -} - -static void -tperror(parser_data_t *pdata, - const char *fmt, - ...) { - va_list ap; - string new_fmt; - char *new_string; - int len; - - fix_format(fmt, new_fmt); - len = get_arg_len("Error: Tag parser failed for '%s', line %d, " - "column %d: ", pdata->file_name, - XML_GetCurrentLineNumber(pdata->parser), - XML_GetCurrentColumnNumber(pdata->parser)); - va_start(ap, fmt); - len += get_varg_len(new_fmt.c_str(), ap); - new_string = (char *)safemalloc(len + 2); - sprintf(new_string, "Error: Tag parser failed for '%s', line %d, " - "column %d: ", pdata->file_name, - XML_GetCurrentLineNumber(pdata->parser), - XML_GetCurrentColumnNumber(pdata->parser)); - vsprintf(&new_string[strlen(new_string)], new_fmt.c_str(), ap); - va_end(ap); - strcat(new_string, "\n"); - *pdata->parse_error_msg = new_string; - safefree(new_string); - longjmp(pdata->parse_error_jmp, 1); -} - -static void -el_get_uint(parser_data_t *pdata, - EbmlElement *el, - uint64_t min_value = 0, - bool is_bool = false) { - int64 value; - - strip(*pdata->bin); - if (!parse_int(pdata->bin->c_str(), value)) - tperror(pdata, "Expected an unsigned integer but found '%s'.", - pdata->bin->c_str()); - if (value < min_value) - tperror(pdata, "Unsigned integer (%lld) is too small. Mininum value is " - "%lld.", value, min_value); - if (is_bool && (value > 0)) - value = 1; - - *(static_cast(el)) = value; -} - -static void -el_get_string(parser_data_t *pdata, - EbmlElement *el) { - strip(*pdata->bin); - if (pdata->bin->length() == 0) - tperror(pdata, "Expected a string but found only whitespaces."); - - *(static_cast(el)) = pdata->bin->c_str(); -} - -static void -el_get_utf8string(parser_data_t *pdata, - EbmlElement *el) { - strip(*pdata->bin); - if (pdata->bin->length() == 0) - tperror(pdata, "Expected a string but found only whitespaces."); - - *(static_cast(el)) = - cstrutf8_to_UTFstring(pdata->bin->c_str()); -} - -static void -el_get_binary(parser_data_t *pdata, - EbmlElement *el) { - int64_t result; - binary *buffer; - mm_io_c *io; - - result = 0; - buffer = NULL; - strip(*pdata->bin, true); - if (pdata->bin->length() == 0) - tperror(pdata, "Found neither Base64 encoded data nor '@file' to read " - "binary data from."); - - if ((*pdata->bin)[0] == '@') { - if (pdata->bin->length() == 1) - tperror(pdata, "No filename found after the '@'."); - try { - io = new mm_io_c(&(pdata->bin->c_str())[1], MODE_READ); - io->setFilePointer(0, seek_end); - result = io->getFilePointer(); - io->setFilePointer(0, seek_beginning); - if (result <= 0) - tperror(pdata, "The file '%s' is empty.", &(pdata->bin->c_str())[1]); - buffer = new binary[result]; - io->read(buffer, result); - delete io; - } catch(...) { - tperror(pdata, "Could not open/read the file '%s'.", - &(pdata->bin->c_str())[1]); - } - - } else { - buffer = new binary[pdata->bin->length() / 4 * 3 + 1]; - result = base64_decode(*pdata->bin, (unsigned char *)buffer); - if (result < 0) - tperror(pdata, "Could not decode the Base64 encoded data - it seems to " - "be broken."); - } - - (static_cast(el))->SetBuffer(buffer, result); -} - -static void -add_data(void *user_data, - const XML_Char *s, - int len) { - parser_data_t *pdata; - int i; - - pdata = (parser_data_t *)user_data; - - if (!pdata->data_allowed) { - for (i = 0; i < len; i++) - if (!isblanktab(s[i]) && !iscr(s[i])) - tperror(pdata, "Data is not allowed inside <%s>.", parent_name); - return; - } - - if (pdata->bin == NULL) - pdata->bin = new string; - - for (i = 0; i < len; i++) - (*pdata->bin) += s[i]; -} - -static void -start_element(void *user_data, - const char *name, - const char **atts) { - parser_data_t *pdata; - - pdata = (parser_data_t *)user_data; - - if (atts[0] != NULL) - tperror(pdata, "Attributes are not allowed."); - - if (pdata->data_allowed) - tperror(pdata, "<%s> is not a valid child element of <%s>.", name, - parent_name); - - pdata->data_allowed = false; - - if (pdata->bin != NULL) - die("start_element: pdata->bin != NULL"); - - if (pdata->depth == 0) { - if (pdata->done_reading) - tperror(pdata, "More than one root element found."); - if (strcmp(name, "Tags")) - tperror(pdata, "Root element must be ."); - - pdata->parents->push_back(pdata->tags); - pdata->parent_idxs->push_back(0); - - } else { - EbmlElement *e; - EbmlMaster *m; - int elt_idx, parent_idx, i; - bool found; - - parent_idx = (*pdata->parent_idxs)[pdata->parent_idxs->size() - 1]; - elt_idx = parent_idx; - found = false; - while (tag_elements[elt_idx].name != NULL) { - if (!strcmp(tag_elements[elt_idx].name, name)) { - found = true; - break; - } - elt_idx++; - } - - if (!found) - tperror(pdata, "<%s> is not a valid child element of <%s>.", name, - tag_elements[parent_idx].name); - - const EbmlSemanticContext &context = - find_ebml_callbacks(KaxTags::ClassInfos, - tag_elements[parent_idx].id).Context; - found = false; - for (i = 0; i < context.Size; i++) - if (tag_elements[elt_idx].id == - context.MyTable[i].GetCallbacks.GlobalId) { - found = true; - break; - } - - if (!found) - tperror(pdata, "<%s> is not a valid child element of <%s>.", name, - tag_elements[parent_idx].name); - - const EbmlSemantic &semantic = - find_ebml_semantic(KaxTags::ClassInfos, - tag_elements[elt_idx].id); - if (semantic.Unique) { - m = dynamic_cast(parent_elt); - assert(m != NULL); - for (i = 0; i < m->ListSize(); i++) - if ((*m)[i]->Generic().GlobalId == tag_elements[elt_idx].id) - tperror(pdata, "Only one instance of <%s> is allowed beneath <%s>.", - name, tag_elements[parent_idx].name); - } - - e = create_ebml_element(KaxTags::ClassInfos, - tag_elements[elt_idx].id); - assert(e != NULL); - m = dynamic_cast(parent_elt); - assert(m != NULL); - m->PushElement(*e); - - if (tag_elements[elt_idx].start_hook != NULL) - tag_elements[elt_idx].start_hook(pdata); - - pdata->parents->push_back(e); - pdata->parent_idxs->push_back(elt_idx); - - pdata->data_allowed = tag_elements[elt_idx].type != ebmlt_master; - } - - (pdata->depth)++; -} - -static void -end_element(void *user_data, - const char *name) { - parser_data_t *pdata; - EbmlMaster *m; - - pdata = (parser_data_t *)user_data; - - if (pdata->data_allowed && (pdata->bin == NULL)) - tperror(pdata, "Element <%s> does not contain any data.", name); - - if (pdata->depth == 1) { - m = static_cast(parent_elt); - if (m->ListSize() == 0) - tperror(pdata, "At least one element is needed."); - - } else { - int elt_idx; - bool found; - - found = false; - for (elt_idx = 0; tag_elements[elt_idx].name != NULL; elt_idx++) - if (!strcmp(tag_elements[elt_idx].name, name)) { - found = true; - break; - } - assert(found); - - switch (tag_elements[elt_idx].type) { - case ebmlt_master: - break; - case ebmlt_uint: - el_get_uint(pdata, parent_elt, tag_elements[elt_idx].min_value, - false); - break; - case ebmlt_bool: - el_get_uint(pdata, parent_elt, 0, true); - break; - case ebmlt_string: - el_get_string(pdata, parent_elt); - break; - case ebmlt_ustring: - el_get_utf8string(pdata, parent_elt); - break; - case ebmlt_binary: - el_get_binary(pdata, parent_elt); - break; - default: - assert(0); - } - - if (tag_elements[elt_idx].end_hook != NULL) - tag_elements[elt_idx].end_hook(pdata); - } - - if (pdata->bin != NULL) { - delete pdata->bin; - pdata->bin = NULL; - } - - pdata->data_allowed = false; - pdata->depth--; - pdata->parents->pop_back(); - pdata->parent_idxs->pop_back(); -} - -static void -end_simple_tag(void *pdata) { - KaxTagSimple *simple; - - simple = dynamic_cast(parent_elt); - assert(simple != NULL); - if ((FINDFIRST(simple, KaxTagString) != NULL) && - (FINDFIRST(simple, KaxTagBinary) != NULL)) - tperror(CPDATA, "Only one of and may be used beneath " - " but not both at the same time."); -} - -void -parse_xml_tags(const char *name, - KaxTags *tags) { - char buffer[5000]; - int len, done, i; - parser_data_t *pdata; - mm_io_c *io; - XML_Parser parser; - XML_Error xerror; - char *emsg; - - io = NULL; - try { - io = new mm_io_c(name, MODE_READ); - } catch(...) { - mxerror("Could not open '%s' for reading.\n", name); - } - - done = 0; - - for (i = 0; tag_elements[i].name != NULL; i++) { - tag_elements[i].start_hook = NULL; - tag_elements[i].end_hook = NULL; - } - tag_elements[tag_element_map_index("Simple")].end_hook = end_simple_tag; - - parser = XML_ParserCreate(NULL); - - pdata = (parser_data_t *)safemalloc(sizeof(parser_data_t)); - memset(pdata, 0, sizeof(parser_data_t)); - - pdata->parser = parser; - pdata->file_name = name; - pdata->parents = new vector; - pdata->parent_idxs = new vector; - pdata->parse_error_msg = new string; - pdata->tags = tags; - - XML_SetUserData(parser, pdata); - XML_SetElementHandler(parser, start_element, end_element); - XML_SetCharacterDataHandler(parser, add_data); - - if (setjmp(pdata->parse_error_jmp) == 1) - mxerror(pdata->parse_error_msg->c_str()); - do { - len = io->read(buffer, 5000); - if (len != 5000) - done = 1; - if (XML_Parse(parser, buffer, len, done) == 0) { - xerror = XML_GetErrorCode(parser); - if (xerror == XML_ERROR_INVALID_TOKEN) - emsg = " Remember that special characters like &, <, > and \" " - "must be escaped in the usual HTML way: & for '&', " - "< for '<', > for '>' and " for '\"'."; - else - emsg = ""; - mxerror("XML parser error at line %d of '%s': %s.%s Aborting.\n", - XML_GetCurrentLineNumber(parser), name, - XML_ErrorString(xerror), emsg); - } - - } while (!done); - - delete io; - XML_ParserFree(parser); - delete pdata->parents; - delete pdata->parent_idxs; - safefree(pdata); -} - -void -fix_mandatory_tag_elements(EbmlElement *e) { - if (dynamic_cast(e) != NULL) { - KaxTagSimple &s = *static_cast(e); - GetChild(s); - GetChild(s); - - } else if (dynamic_cast(e) != NULL) { - KaxTagTargets &t = *static_cast(e); - GetChild(t); - - } - - if (dynamic_cast(e) != NULL) { - EbmlMaster *m; - int i; - - m = static_cast(e); - for (i = 0; i < m->ListSize(); i++) - fix_mandatory_tag_elements((*m)[i]); - } -} diff --git a/tests/results.txt b/tests/results.txt index 9adbe8225..43463e631 100644 --- a/tests/results.txt +++ b/tests/results.txt @@ -17,7 +17,7 @@ T_016cuesheet:701de008087d3e3be9ad34621df8d6c2:passed:20040825-175700 T_017chapters:d123294267704fd88f6d730a6ad5f970-3bf90270c5b8abcee3c68b23ff038176:passed:20040825-175700 T_018attachments:de6a7f61b9c707dbf8b635abdc95f6f6-61bd952ae52eb9b4cd331dc805e3af0c:passed:20040825-175700 T_019attachments2:73eee65d12723bc0d7e3ebfbd9b7c27e-5326411491c8d8f14f09efac0c134d5f-73eee65d12723bc0d7e3ebfbd9b7c27e-5a6e6eeea02af14a78361a7032228c2a:passed:20040825-175700 -T_020languages:654d90f508b44b4cf3d2a44ffb12dae0:passed:20040825-234208 +T_020languages:654d90f508b44b4cf3d2a44ffb12dae0:failed:20040825-234208 T_021aspect_ratio:22bd828492ccc4a16a8918d6535b8f26-aaf9ad30cf4d23219088df35fb18f396:passed:20040825-234244 T_022display_dimensions:d8918ad515a670b30f2d927e29034675:passed:20040825-234339 T_023no_x:b934ba7d0e44d79c7a4a020da90cfc3a-a4db5d036681d15ef61e7b2c099e09bc-c95a138583be3bc614ab57e6cbbb14cd:passed:20040825-234343