app->titles = (pnd_localized_string_t *)malloc(sizeof(pnd_localized_string_t) * app->titles_alloc_c);
if (!app->titles) return (0); //errno = NOMEM
- //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))
- {
+ // 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 <titles> block
- if ( ! pElem->GetText() ) {
- continue;
- }
+ pElem = pElem -> FirstChildElement ( PND_PXML_ENAME_TITLE );
+
+ while ( pElem ) {
+
+ // handle <title lang="en_US">Program Title</title>
+ //
+
+ // parse out the text and lang
+ char *text, *lang;
+
+ if ( ! ( text = strdup ( pElem -> GetText() ) ) ) {
+ continue;
+ }
+
+ if ( ! ( lang = pnd_pxml_get_attribute ( pElem, PND_PXML_ATTRNAME_TITLELANG ) ) ) {
+ continue;
+ }
+
+ // increment counter; if we're running out of buffers, grow to handle the new strings
+ app -> titles_c++;
- char *text = strdup(pElem->GetText());
- if (!text) continue;
+ 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
+ }
+
+ // populate the stringbuf
+ pnd_localized_string_t *title = &app->titles[app->titles_c - 1];
+ title->language = lang;
+ title->string = text;
+
+ // next
+ pElem = pElem -> NextSiblingElement ( PND_PXML_ENAME_TITLE );
- char *lang = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_TITLELANG);
- if (!lang) continue;
+ } // foreach
- app->titles_c++;
- if (app->titles_c > app->titles_alloc_c) //we don't have enough strings allocated
+ } else {
+ // older style <title> entry series
+
+ for ( pElem = hRoot.FirstChild(PND_PXML_ENAME_TITLE).Element(); pElem;
+ pElem = pElem->NextSiblingElement(PND_PXML_ENAME_TITLE))
{
- 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;
+ if ( ! pElem->GetText() ) {
+ continue;
+ }
- //pnd_log ( PND_LOG_DEFAULT, (char*)" Title/Lang: %s/%s\n", text, lang );
+ char *text = strdup(pElem->GetText());
+ if (!text) continue;
- }
+ 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 );
}
-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 * sizeof(pnd_localized_string_t) );
- 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;
- }
+ if ( ! ( lang = pnd_pxml_get_attribute ( pElem, PND_PXML_ATTRNAME_DESCRLANG ) ) ) {
+ 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
+ }
- return (1);
+ pnd_localized_string_t *description = &app->descriptions[app->descriptions_c - 1];
+ description->language = lang;
+ description->string = text;
+
+ // next
+ pElem = pElem -> NextSiblingElement ( PND_PXML_ENAME_DESCRIPTION );
+
+ } // foreach
+
+ } else {
+ // fallback to older approach
+
+ for (pElem = hRoot.FirstChild(PND_PXML_ENAME_DESCRIPTION).Element(); pElem;
+ pElem = pElem->NextSiblingElement(PND_PXML_ENAME_DESCRIPTION))
+ {
+
+ if ( ! pElem->GetText() ) {
+ continue;
+ }
+
+ char *text = strdup(pElem->GetText());
+ if (!text) continue;
+
+ 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 ) {
// 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();
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);
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->exec_no_x11 = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_EXECNOX11);
app->execargs = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_EXECARGS);
+ app->exec_dashdash_args = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_DASHDASH);
}
//The app icon:
{
app->previewpic2 = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_PREVPICSRC);
}
- }
+ }
} //previewpic
//The author info:
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;
+ 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.
}
//All file associations:
+#if 1
//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;
+
+ for (pElem = pElem->FirstChildElement(PND_PXML_ENAME_ASSOC); pElem && i < 50;
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;
+ unsigned int maxlen;
- 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;
+ if ( ! ( name && filetype ) ) {
+ if ( name ) free(name);
+ if ( filetype ) free(filetype);
+ continue;
}
+
+ if ( app -> associationitem1_name == NULL ) {
+ // first hit, just dupe
+ app -> associationitem1_name = strdup ( name );
+ app -> associationitem1_filetype = strdup ( filetype );
+ pnd_log ( PND_LOG_DEFAULT, (char*)" File assoc initial: %s -> %s\n", name, filetype );
+ } else {
+ // grow-append buffer
+
+ maxlen = strlen ( app -> associationitem1_name ) + strlen ( name ) + 3;
+ app -> associationitem1_name = (char*) realloc ( app -> associationitem1_name, maxlen );
+ strncat ( app -> associationitem1_name, "; ", maxlen );
+ strncat ( app -> associationitem1_name, name, maxlen );
+
+ maxlen = strlen ( app -> associationitem1_filetype ) + strlen ( filetype ) + 3;
+ app -> associationitem1_filetype = (char*) realloc ( app -> associationitem1_filetype, maxlen );
+ strncat ( app -> associationitem1_filetype, "; ", maxlen );
+ strncat ( app -> associationitem1_filetype, filetype, maxlen );
+
+ pnd_log ( PND_LOG_DEFAULT, (char*)" File assoc growpend: %s -> %s\n", name, filetype );
}
- }
- }
+
+ if ( name ) free(name);
+ if ( filetype ) free(filetype);
+
+ } // for
+ } // assoc
+#endif
//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 ) {
+ 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 ( ( 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
}
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*/ );
app -> mkdir_sp = foo;
} // assuming we got ram, lets cat it all together
+ free(t); // free this attribute
} // got another elem?
} // while
} // 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);
}