X-Git-Url: http://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-libraries.git;a=blobdiff_plain;f=lib%2Fpnd_tinyxml.cpp;h=1aa8f9b03c5f80ec7f3a0e4bb5b12d0becb08c6b;hp=6a7e2e3b7fd41140aff5e974ec9928abf35b3ab0;hb=4b7531ad98d318b8071d595ce3e0d4113ee06f93;hpb=0258a5f326ad753a47bfc8189249c71748bed7fc diff --git a/lib/pnd_tinyxml.cpp b/lib/pnd_tinyxml.cpp index 6a7e2e3..1aa8f9b 100644 --- a/lib/pnd_tinyxml.cpp +++ b/lib/pnd_tinyxml.cpp @@ -1,321 +1,554 @@ +#include #include "tinyxml/tinyxml.h" #include "../include/pnd_pxml.h" #include "pnd_tinyxml.h" +#include "pnd_logger.h" //Easily change the tag names if required (globally in this file): #include "pnd_pxml_names.h" extern "C" { -unsigned char pnd_pxml_load ( const char* pFilename, pnd_pxml_t *app ) { - FILE *f; - char *b; - unsigned int len; +char *pnd_pxml_get_attribute(TiXmlElement *elem, const char *name) +{ + const char *value = elem->Attribute(name); + if (value) + return strdup(value); + else + return NULL; +} - f = fopen ( pFilename, "r" ); +unsigned char pnd_pxml_parse_titles(const TiXmlHandle hRoot, pnd_pxml_t *app) { + TiXmlElement *pElem; + app->titles_alloc_c = 4; //TODO: adjust this based on how many titles a PXML usually has. Power of 2. - if ( ! f ) { - return ( 0 ); - } + app->titles = (pnd_localized_string_t *)malloc(sizeof(pnd_localized_string_t) * app->titles_alloc_c); + if (!app->titles) return (0); //errno = NOMEM - fseek ( f, 0, SEEK_END ); + // Go through all title tags and load them. + // - Check if newer style titles sub-block exists; if so, use that. + // - if not, fall back to old style + // - failing that, crash earth into sun + if ( (pElem = hRoot.FirstChild(PND_PXML_NODENAME_TITLES).Element()) ) { + // newer block - len = ftell ( f ); + pElem = pElem -> FirstChildElement ( PND_PXML_ENAME_TITLE ); - fseek ( f, 0, SEEK_SET ); + while ( pElem ) { - b = (char*) malloc ( len ); + // handle Program Title + // - if ( ! b ) { - fclose ( f ); - return ( 0 ); - } + // parse out the text and lang + char *text, *lang; - fread ( b, 1, len, f ); + if ( ! ( text = strdup ( pElem -> GetText() ) ) ) { + continue; + } - fclose ( f ); + if ( ! ( lang = pnd_pxml_get_attribute ( pElem, PND_PXML_ATTRNAME_TITLELANG ) ) ) { + continue; + } - return ( pnd_pxml_parse ( pFilename, b, len, app ) ); -} + // increment counter; if we're running out of buffers, grow to handle the new strings + app -> titles_c++; -char *pnd_pxml_get_attribute(TiXmlElement *elem, const char *name) -{ - const char *value = elem->Attribute(name); - if (value) - return strdup(value); - else - return NULL; -} + if ( app -> titles_c > app -> titles_alloc_c ) { + // we don't have enough strings allocated + app -> titles_alloc_c <<= 1; + app -> titles = (pnd_localized_string_t *)realloc((void*)app->titles, app->titles_alloc_c); + if (!app->titles) return (0); //errno = ENOMEM + } -unsigned char pnd_pxml_parse_titles(const TiXmlHandle hRoot, pnd_pxml_t *app) -{ - TiXmlElement *pElem; - app->titles_alloc_c = 4; //TODO: adjust this based on how many titles a PXML usually has. Power of 2. + // populate the stringbuf + pnd_localized_string_t *title = &app->titles[app->titles_c - 1]; + title->language = lang; + title->string = text; - app->titles = (pnd_localized_string_t *)malloc(sizeof(pnd_localized_string_t) * app->titles_alloc_c); - if (!app->titles) return (0); //errno = NOMEM + // next + pElem = pElem -> NextSiblingElement ( PND_PXML_ENAME_TITLE ); - //Go through all title tags and load them. - for (pElem = hRoot.FirstChild(PND_PXML_ENAME_TITLE).Element(); pElem; - pElem = pElem->NextSiblingElement(PND_PXML_ENAME_TITLE)) - { + } // foreach - if ( ! pElem->GetText() ) { - continue; - } + } else { + // older style entry series - char *text = strdup(pElem->GetText()); - if (!text) continue; + for ( pElem = hRoot.FirstChild(PND_PXML_ENAME_TITLE).Element(); pElem; + pElem = pElem->NextSiblingElement(PND_PXML_ENAME_TITLE)) + { - char *lang = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_TITLELANG); - if (!lang) continue; + if ( ! pElem->GetText() ) { + continue; + } - app->titles_c++; - if (app->titles_c > app->titles_alloc_c) //we don't have enough strings allocated - { - app->titles_alloc_c <<= 1; - app->titles = (pnd_localized_string_t *)realloc((void*)app->titles, app->titles_alloc_c); - if (!app->titles) return (0); //errno = ENOMEM - } + char *text = strdup(pElem->GetText()); + if (!text) continue; - pnd_localized_string_t *title = &app->titles[app->titles_c - 1]; - title->language = lang; - title->string = text; - } + char *lang = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_TITLELANG); + if (!lang) continue; + + app->titles_c++; + if (app->titles_c > app->titles_alloc_c) //we don't have enough strings allocated + { + app->titles_alloc_c <<= 1; + app->titles = (pnd_localized_string_t *)realloc((void*)app->titles, app->titles_alloc_c); + if (!app->titles) return (0); //errno = ENOMEM + } + + pnd_localized_string_t *title = &app->titles[app->titles_c - 1]; + title->language = lang; + title->string = text; + + //pnd_log ( PND_LOG_DEFAULT, (char*)" Title/Lang: %s/%s\n", text, lang ); + + } // for + + } // new or old style <title(s)> - return (1); + return ( 1 ); } -unsigned char pnd_pxml_parse_descriptions(const TiXmlHandle hRoot, pnd_pxml_t *app) -{ - TiXmlElement *pElem; - app->descriptions_alloc_c = 4; //TODO: adjust this based on how many descriptions a PXML usually has. Power of 2. +unsigned char pnd_pxml_parse_descriptions(const TiXmlHandle hRoot, pnd_pxml_t *app) { + TiXmlElement *pElem; + app->descriptions_alloc_c = 4; //TODO: adjust this based on how many descriptions a PXML usually has. Power of 2. - app->descriptions = (pnd_localized_string_t *)malloc(sizeof(pnd_localized_string_t) * app->descriptions_alloc_c); - if (!app->descriptions) - { - app->descriptions_alloc_c = 0; - return (0); //errno = NOMEM - } + app->descriptions = (pnd_localized_string_t *)malloc(sizeof(pnd_localized_string_t) * app->descriptions_alloc_c); + if (!app->descriptions) + { + app->descriptions_alloc_c = 0; + return (0); //errno = NOMEM + } - for (pElem = hRoot.FirstChild(PND_PXML_ENAME_DESCRIPTION).Element(); pElem; - pElem = pElem->NextSiblingElement(PND_PXML_ENAME_DESCRIPTION)) - { + // similar logic to how <titles> or <title> is parsed + // - if <titles> block is found, use that; otherwise fall back to <title> deprecated form + if ( (pElem = hRoot.FirstChild ( PND_PXML_NODENAME_DESCRIPTIONS).Element() ) ) { + // newer style <descriptions> block - if ( ! pElem->GetText() ) { - continue; - } + pElem = pElem -> FirstChildElement ( PND_PXML_ENAME_DESCRIPTION ); - char *text = strdup(pElem->GetText()); - if (!text) continue; + while ( pElem ) { - char *lang = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_DESCRLANG); - if (!lang) continue; + char *text, *lang; - app->descriptions_c++; - if (app->descriptions_c > app->descriptions_alloc_c) //we don't have enough strings allocated - { - app->descriptions_alloc_c <<= 1; - app->descriptions = (pnd_localized_string_t*)realloc((void*)app->descriptions, app->descriptions_alloc_c); - if (!app->descriptions) return (0); //errno = ENOMEM - } + if ( ! ( text = strdup ( pElem -> GetText() ) ) ) { + continue; + } - pnd_localized_string_t *description = &app->descriptions[app->descriptions_c - 1]; - description->language = lang; - description->string = text; - } - return (1); -} + if ( ! ( lang = pnd_pxml_get_attribute ( pElem, PND_PXML_ATTRNAME_DESCRLANG ) ) ) { + if(text) free(text); text = NULL; + continue; + } -unsigned char pnd_pxml_parse ( const char *pFilename, char *buffer, unsigned int length, pnd_pxml_t *app ) { - //Load the XML document - TiXmlDocument doc; - doc.Parse(buffer); + app->descriptions_c++; + if (app->descriptions_c > app->descriptions_alloc_c) //we don't have enough strings allocated + { + app->descriptions_alloc_c <<= 1; + app->descriptions = (pnd_localized_string_t*)realloc((void*)app->descriptions, app->descriptions_alloc_c * sizeof(pnd_localized_string_t) ); + if (!app->descriptions) { if(text) free(text); if(lang) free(lang); return (0); } //errno = ENOMEM + } - TiXmlElement *pElem = NULL; + pnd_localized_string_t *description = &app->descriptions[app->descriptions_c - 1]; + description->language = lang; + description->string = text; - //Find the root element - TiXmlHandle hDoc(&doc); - TiXmlHandle hRoot(0); + // next + pElem = pElem -> NextSiblingElement ( PND_PXML_ENAME_DESCRIPTION ); - pElem = hDoc.FirstChild("PXML").Element(); - if (!pElem) return (0); - hRoot = TiXmlHandle(pElem); + } // foreach - //Get unique ID first. - app->unique_id = pnd_pxml_get_attribute(hRoot.Element(), PND_PXML_ATTRNAME_UID); + } else { + // fallback to older approach - //Everything related to the title: - pnd_pxml_parse_titles(hRoot, app); + for (pElem = hRoot.FirstChild(PND_PXML_ENAME_DESCRIPTION).Element(); pElem; + pElem = pElem->NextSiblingElement(PND_PXML_ENAME_DESCRIPTION)) + { - //Everything description-related: - pnd_pxml_parse_descriptions(hRoot, app); + if ( ! pElem->GetText() ) { + continue; + } - //Everything launcher-related in one tag: - if ( (pElem = hRoot.FirstChild(PND_PXML_ENAME_EXEC).Element()) ) - { - app->background = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_EXECBG); //if this returns NULL, the struct is filled with NULL. No need to check. - app->standalone = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_EXECSTAL); - app->exec = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_EXECCMD); - app->startdir = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_EXECWD); - app->exec_no_x11 = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_EXECNOX11); - } + char *text = strdup(pElem->GetText()); + if (!text) continue; - //The app icon: - if ( (pElem = hRoot.FirstChild(PND_PXML_ENAME_ICON).Element()) ) - { - app->icon = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_ICONSRC); - } + char *lang = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_DESCRLANG); + if (!lang) { if(text) free(text); text = NULL; continue; } + + app->descriptions_c++; + if (app->descriptions_c > app->descriptions_alloc_c) //we don't have enough strings allocated + { + app->descriptions_alloc_c <<= 1; + app->descriptions = (pnd_localized_string_t*)realloc((void*)app->descriptions, app->descriptions_alloc_c * sizeof(pnd_localized_string_t) ); + if (!app->descriptions) { if(text) free(text); if(lang) free(lang); return (0); } //errno = ENOMEM + } + + pnd_localized_string_t *description = &app->descriptions[app->descriptions_c - 1]; + description->language = lang; + description->string = text; + } // for + + } // new form or old form? + + return ( 1 ); +} + +unsigned char pnd_pxml_parse ( const char *pFilename, char *buffer, unsigned int length, pnd_pxml_t **apps ) { + + //Load the XML document + TiXmlDocument doc; + doc.Parse(buffer); + + unsigned char appwrappermode = 0; // >=1 -> using <application>...</application> wrapper + unsigned char appcount = 0; + pnd_pxml_t *app = NULL; + + TiXmlElement *pElem = NULL; + TiXmlElement *appElem = NULL; + + //Find the root element + TiXmlHandle hDoc(&doc); + TiXmlHandle hRoot(0); + + pElem = hDoc.FirstChild("PXML").Element(); + if (!pElem) return (0); + + // new Strategy; really, we want multiple app support within a PXML, without the lameness of + // multiple <PXML>..</PXML> within a single PXML.xml file. As such, we should have an app within + // an <application>..</application> wrapper level, with the ID on that. Further, the icon and + // .desktop filenames can have a # appended which is the application-count-# within the PXML, + // so that they can have their own .desktop and icon without collisions, but still use the + // same unique-id if they want to. + // To avoid breaking existing PXML's (even though we're pre-launch), can detect if ID + // is present in PXML line or not; if not, assume application mode? + hRoot = TiXmlHandle(pElem); + + // workaround for package ID's used by some package managers + // get the package ID and store it for each application + char* package_id = NULL; + char* package_version_major = NULL; + char* package_version_minor = NULL; + char* package_version_release = NULL; + char* package_version_build = NULL; + pElem = hRoot.FirstChild ( PND_PXML_ENAME_PACKAGE ).Element(); + if ( pElem ) { + package_id = pnd_pxml_get_attribute ( pElem, PND_PXML_ATTRNAME_PACKAGE_ID ); + TiXmlHandle pRoot = TiXmlHandle( pElem ); + if ( (pElem = pRoot.FirstChild(PND_PXML_ENAME_VERSION).Element()) ) + { + package_version_major = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_VERMAJOR); + package_version_minor = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_VERMINOR); + package_version_release = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_VERREL); + package_version_build = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_VERBUILD); + } + } + + // move to applications element then + if ( hRoot.FirstChild(PND_PXML_APP).Element() != NULL ) { + appwrappermode = 1; + appElem = hRoot.FirstChild(PND_PXML_APP).Element(); + hRoot = TiXmlHandle ( appElem ); + } - //The preview pics: - if ( (pElem = hRoot.FirstChild(PND_PXML_NODENAME_PREVPICS).Element()) ) + // until we run out of applications in the PXML.. + while ( 1 ) { + + //pnd_log ( PND_LOG_DEFAULT, (char*)" App #%u inside of PXML %s\n", appcount, pFilename ); + + // create the buffer to hold the pxml + apps [ appcount ] = (pnd_pxml_t*) malloc ( sizeof(pnd_pxml_t) ); + memset ( apps [ appcount ], '\0', sizeof(pnd_pxml_t) ); + + // due to old code, just make life easier a minute.. + app = apps [ appcount ]; + if ( appwrappermode ) { + app -> subapp_number = appcount; + } else { + app -> subapp_number = 0; + } + + // give application the package id, if there is one + if( package_id ) + app -> package_id = strdup(package_id); + if( package_version_major ) + app -> package_version_major = strdup(package_version_major); + if( package_version_minor ) + app -> package_version_minor = strdup(package_version_minor); + if( package_version_release ) + app -> package_version_release = strdup(package_version_release); + if( package_version_build ) + app -> package_version_build = strdup(package_version_build); + + //Get unique ID first. + if ( appwrappermode ) { + app->unique_id = pnd_pxml_get_attribute(appElem, PND_PXML_ATTRNAME_UID); + //pnd_log ( PND_LOG_DEFAULT, (char*)" Subapp #%u has unique_id %s\n", appcount, app -> unique_id ); + app->appdata_dirname = pnd_pxml_get_attribute(appElem, PND_PXML_ATTRNAME_APPDATANAME); + } else { + app->unique_id = pnd_pxml_get_attribute(hRoot.Element(), PND_PXML_ATTRNAME_UID); + //pnd_log ( PND_LOG_DEFAULT, (char*)" Only-app #%u has unique_id %s\n", appcount, app -> unique_id ); + } + + //Everything related to the title: + pnd_pxml_parse_titles(hRoot, app); + + //Everything description-related: + pnd_pxml_parse_descriptions(hRoot, app); + + //Everything launcher-related in one tag: + if ( (pElem = hRoot.FirstChild(PND_PXML_ENAME_EXEC).Element()) ) + { + app->background = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_EXECBG); //if this returns NULL, the struct is filled with NULL. No need to check. + app->standalone = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_EXECSTAL); + app->exec = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_EXECCMD); + app->startdir = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_EXECWD); + app->exec_no_x11 = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_EXECNOX11); + app->execargs = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_EXECARGS); + } + + //The app icon: + if ( (pElem = hRoot.FirstChild(PND_PXML_ENAME_ICON).Element()) ) { + app->icon = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_ICONSRC); + } + + // <info> + if ( (pElem = hRoot.FirstChild(PND_PXML_ENAME_INFO).Element()) ) + { + app-> info_name = pnd_pxml_get_attribute ( pElem, PND_PXML_ATTRNAME_INFONAME ); + app-> info_filename = pnd_pxml_get_attribute ( pElem, PND_PXML_ATTRNAME_INFOSRC ); + app-> info_type = pnd_pxml_get_attribute ( pElem, PND_PXML_ATTRNAME_INFOTYPE ); + } + + //The preview pics: + if ( (pElem = hRoot.FirstChild(PND_PXML_NODENAME_PREVPICS).Element()) ) + { + //TODO: Change this if pnd_pxml_t gains the feature of more pics than 2. + if ( (pElem = pElem->FirstChildElement(PND_PXML_ENAME_PREVPIC)) ) + { + app->previewpic1 = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_PREVPICSRC); + + if ( (pElem = pElem->NextSiblingElement(PND_PXML_ENAME_PREVPIC)) ) { - //TODO: Change this if pnd_pxml_t gains the feature of more pics than 2. - if ( (pElem = pElem->FirstChildElement(PND_PXML_ENAME_PREVPIC)) ) - { - app->previewpic1 = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_PREVPICSRC); - - if ( (pElem = pElem->NextSiblingElement(PND_PXML_ENAME_PREVPIC)) ) - { - app->previewpic2 = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_PREVPICSRC); - } - } - } //previewpic - - //The author info: - if ( (pElem = hRoot.FirstChild(PND_PXML_ENAME_AUTHOR).Element()) ) + app->previewpic2 = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_PREVPICSRC); + } + } + } //previewpic + + //The author info: + if ( (pElem = hRoot.FirstChild(PND_PXML_ENAME_AUTHOR).Element()) ) + { + app->author_name = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_AUTHORNAME); + app->author_website = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_AUTHORWWW); + //TODO: Uncomment this if the author gets email support. + //app->author_email = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_AUTHOREMAIL)); + } + + //The version info: + if ( (pElem = hRoot.FirstChild(PND_PXML_ENAME_VERSION).Element()) ) + { + app->version_major = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_VERMAJOR); + app->version_minor = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_VERMINOR); + app->version_release = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_VERREL); + app->version_build = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_VERBUILD); + } + + //The OS version info: + if ( (pElem = hRoot.FirstChild(PND_PXML_ENAME_OSVERSION).Element()) ) + { + app->osversion_major = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_OSVERMAJOR); + app->osversion_minor = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_OSVERMINOR); + app->osversion_release = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_OSVERREL); + app->osversion_build = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_OSVERBUILD); + } + + int i; //For now, we need to keep track of the index of categories. + //Categories: + if ( (pElem = hRoot.FirstChildElement(PND_PXML_NODENAME_CATS).Element()) ) //First, enter the "categories" node. + { + i = 0; + + //Goes through all the top-level categories and their sub-categories. i helps limit these to 2. + for (pElem = pElem->FirstChildElement(PND_PXML_ENAME_CAT); pElem && i < 2; + pElem = pElem->NextSiblingElement(PND_PXML_ENAME_CAT), i++) + { + //TODO: Fix pnd_pxml_t so that there can be more than 2 category 'trees' and more than 2 subcategories. Then this can be removed. + switch (i) { - app->author_name = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_AUTHORNAME); - app->author_website = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_AUTHORWWW); - //TODO: Uncomment this if the author gets email support. - //app->author_email = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_AUTHOREMAIL)); + case 0: //first category counts as the main cat for now + app->main_category = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_CATNAME); + break; + + case 1: //...second as the alternative + app->altcategory = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_CATNAME); } - //The version info: - if ( (pElem = hRoot.FirstChild(PND_PXML_ENAME_VERSION).Element()) ) + TiXmlElement *pSubCatElem; //the sub-elements for a main category. + int j = 0; //the subcategory index within this category + + //Goes through all the subcategories within this category. j helps limit these to 2. + for (pSubCatElem = pElem->FirstChildElement(PND_PXML_ENAME_SUBCAT); pSubCatElem && j < 2; + pSubCatElem = pSubCatElem->NextSiblingElement(PND_PXML_ENAME_SUBCAT), j++) { - app->version_major = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_VERMAJOR); - app->version_minor = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_VERMINOR); - app->version_release = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_VERREL); - app->version_build = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_VERBUILD); + char *subcat = pnd_pxml_get_attribute(pSubCatElem, PND_PXML_ATTRNAME_SUBCATNAME); + if (!(subcat)) continue; + + //TODO: This is ugly. Fix pnd_pxml_t so that there can be more than 2 category 'trees' and more than 2 subcategories. Then this can be removed. + switch (j | (i << 1)) + { + case 0: + app->subcategory1 = subcat; + break; + case 1: + app->subcategory2 = subcat; + break; + case 2: + app->altsubcategory1 = subcat; + break; + case 3: + app->altsubcategory2 = subcat; + } } - - //The OS version info: - if ( (pElem = hRoot.FirstChild(PND_PXML_ENAME_OSVERSION).Element()) ) + } + } + + //All file associations: + //Step into the associations node + if ( (pElem = hRoot.FirstChild(PND_PXML_NODENAME_ASSOCS).Element()) ) + { + i = 0; + //Go through all associations. i serves as index; since the format only supports 3 associations we need to keep track of the number. + for (pElem = pElem->FirstChildElement(PND_PXML_ENAME_ASSOC); pElem && i < 3; + pElem = pElem->NextSiblingElement(PND_PXML_ENAME_ASSOC), i++) + { + char *name = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_ASSOCNAME); + char *filetype = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_ASSOCFTYPE); + char *paramter = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_ASSOCARGS); + + if (!(name && filetype && paramter)) + { + if(name) free(name); + if(filetype) free(filetype); + if(paramter) free(paramter); + continue; + } + + switch(i) //TODO: same problem here: only 3 associations supported + { + case 0: { - app->osversion_major = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_OSVERMAJOR); - app->osversion_minor = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_OSVERMINOR); - app->osversion_release = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_OSVERREL); - app->osversion_build = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_OSVERBUILD); + app->associationitem1_name = name; + app->associationitem1_filetype = filetype; + app->associationitem1_parameter = paramter; + break; } - - int i; //For now, we need to keep track of the index of categories. - //Categories: - if ( (pElem = hRoot.FirstChildElement(PND_PXML_NODENAME_CATS).Element()) ) //First, enter the "categories" node. + case 1: { - i = 0; - - //Goes through all the top-level categories and their sub-categories. i helps limit these to 2. - for (pElem = pElem->FirstChildElement(PND_PXML_ENAME_CAT); pElem && i < 2; - pElem = pElem->NextSiblingElement(PND_PXML_ENAME_CAT), i++) - { - //TODO: Fix pnd_pxml_t so that there can be more than 2 category 'trees' and more than 2 subcategories. Then this can be removed. - switch (i) - { - case 0: //first category counts as the main cat for now - app->main_category = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_CATNAME); - break; - - case 1: //...second as the alternative - app->altcategory = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_CATNAME); - } - - TiXmlElement *pSubCatElem; //the sub-elements for a main category. - int j = 0; //the subcategory index within this category - - //Goes through all the subcategories within this category. j helps limit these to 2. - for (pSubCatElem = pElem->FirstChildElement(PND_PXML_ENAME_SUBCAT); pSubCatElem && j < 2; - pSubCatElem = pSubCatElem->NextSiblingElement(PND_PXML_ENAME_SUBCAT), j++) - { - char *subcat = pnd_pxml_get_attribute(pSubCatElem, PND_PXML_ATTRNAME_SUBCATNAME); - if (!(subcat)) continue; - - //TODO: This is ugly. Fix pnd_pxml_t so that there can be more than 2 category 'trees' and more than 2 subcategories. Then this can be removed. - switch (j | (i << 1)) - { - case 0: - app->subcategory1 = subcat; - break; - case 1: - app->subcategory2 = subcat; - break; - case 2: - app->altsubcategory1 = subcat; - break; - case 3: - app->altsubcategory2 = subcat; - } - } - } + app->associationitem2_name = name; + app->associationitem2_filetype = filetype; + app->associationitem2_parameter = paramter; + break; } - - //All file associations: - //Step into the associations node - if ( (pElem = hRoot.FirstChild(PND_PXML_NODENAME_ASSOCS).Element()) ) + case 2: { - i = 0; - //Go through all associations. i serves as index; since the format only supports 3 associations we need to keep track of the number. - for (pElem = pElem->FirstChildElement(PND_PXML_ENAME_ASSOC); pElem && i < 3; - pElem = pElem->NextSiblingElement(PND_PXML_ENAME_ASSOC), i++) - { - char *name = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_ASSOCNAME); - char *filetype = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_ASSOCFTYPE); - char *paramter = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_ASSOCARGS); - - if (!(name && filetype && paramter)) continue; - - switch(i) //TODO: same problem here: only 3 associations supported - { - case 0: - { - app->associationitem1_name = name; - app->associationitem1_filetype = filetype; - app->associationitem1_parameter = paramter; - break; - } - case 1: - { - app->associationitem2_name = name; - app->associationitem2_filetype = filetype; - app->associationitem2_parameter = paramter; - break; - } - case 2: - { - app->associationitem3_name = name; - app->associationitem3_filetype = filetype; - app->associationitem3_parameter = paramter; - } - } - } + app->associationitem3_name = name; + app->associationitem3_filetype = filetype; + app->associationitem3_parameter = paramter; } - - //Performance related things (aka: Clockspeed XD): - pElem = hRoot.FirstChild(PND_PXML_ENAME_CLOCK).Element(); - if (pElem) - { - app->clockspeed = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_CLOCKFREQ); } - - // Package - pElem = hRoot.FirstChild ( PND_PXML_ENAME_PACKAGE ).Element(); - if ( pElem ) { - app -> package_name = pnd_pxml_get_attribute ( pElem, PND_PXML_ATTRNAME_PACKAGE_NAME ); - app -> package_release_date = pnd_pxml_get_attribute ( pElem, PND_PXML_ATTRNAME_PACKAGE_DATE ); + if(name) free(name); + if(filetype) free(filetype); + if(paramter) free(paramter); + } + } + + //Performance related things (aka: Clockspeed XD): + pElem = hRoot.FirstChild(PND_PXML_ENAME_CLOCK).Element(); + if (pElem) + { + app->clockspeed = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_CLOCKFREQ); + } + + // Package + pElem = hRoot.FirstChild ( PND_PXML_ENAME_PACKAGE ).Element(); + if ( pElem ) { + app -> package_name = pnd_pxml_get_attribute ( pElem, PND_PXML_ATTRNAME_PACKAGE_NAME ); + app -> package_release_date = pnd_pxml_get_attribute ( pElem, PND_PXML_ATTRNAME_PACKAGE_DATE ); + } + + // mkdir request + if ( (pElem = hRoot.FirstChild(PND_PXML_NODENAME_MKDIR).Element()) ) { + + // seek <dir> + if ( (pElem = pElem->FirstChildElement(PND_PXML_ENAME_MKDIR)) ) { + char *t; + + if ( ( t = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_MKDIRPATH) ) ) { + // first <dir>, so just replace it wholesale; we use strdup so we can free() easily later, consistently. Mmm, leak seems imminent. + app -> mkdir_sp = strdup ( t ); + free(t); // free this attribute } - return (1); + while ( ( pElem = pElem -> NextSiblingElement ( PND_PXML_ENAME_MKDIR ) ) ) { + + if ( ( t = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_MKDIRPATH) ) ) { + char *foo = (char*) malloc ( strlen ( app -> mkdir_sp ) + strlen ( t ) + 1 /*:*/ + 1 /*\0*/ ); + + if ( foo ) { + sprintf ( foo, "%s:%s", app -> mkdir_sp, t ); + free ( app -> mkdir_sp ); + app -> mkdir_sp = foo; + } // assuming we got ram, lets cat it all together + + free(t); // free this attribute + } // got another elem? + + } // while + + } // found a <dir> + +#if 0 + if ( app -> mkdir_sp ) { + printf ( "mkdir: %s\n", app -> mkdir_sp ); + } +#endif + + } // mkdir + + // if in <application> mode, do we find another app? + if ( appwrappermode ) { + appElem = appElem -> NextSiblingElement ( PND_PXML_APP ); + if ( ! appElem ) { + //pnd_log ( PND_LOG_DEFAULT, (char*)" No more applications within PXML\n" ); + break; // no more applications + } + // got another application.. + //pnd_log ( PND_LOG_DEFAULT, " Found another applications within PXML\n" ); + appwrappermode++; + hRoot = TiXmlHandle ( appElem ); + + appcount++; + + if ( appcount == PXML_MAXAPPS ) { + return ( 1 ); // thats all we can handle; we're not going to auto-extend this + } + + } else { + break; // single-app old PXML + } + + } // while finding apps + + if( package_id ) + free(package_id); + if( package_version_major ) + free(package_version_major); + if( package_version_minor ) + free(package_version_minor); + if( package_version_release ) + free(package_version_release); + if( package_version_build ) + free(package_version_build); + + return (1); } } // extern C