X-Git-Url: http://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-libraries.git;a=blobdiff_plain;f=lib%2Fpnd_pxml.c;h=77fc0117f4d061af8680fd9c8d9c25895c5d5897;hp=35b21b35fe1f4adfdba0be49078c4a6bf8bbaee0;hb=4b7531ad98d318b8071d595ce3e0d4113ee06f93;hpb=020f0555fd57745e14c1e388884c4f63272d8562 diff --git a/lib/pnd_pxml.c b/lib/pnd_pxml.c index 35b21b3..77fc011 100644 --- a/lib/pnd_pxml.c +++ b/lib/pnd_pxml.c @@ -10,50 +10,86 @@ #include "pnd_pxml.h" #include "pnd_pathiter.h" #include "pnd_tinyxml.h" +#include "pnd_logger.h" -pnd_pxml_handle pnd_pxml_fetch ( char *fullpath ) { +pnd_pxml_handle *pnd_pxml_fetch ( char *fullpath ) { + FILE *f; + char *b; + unsigned int len; + pnd_pxml_handle *h; - pnd_pxml_t *p = malloc ( sizeof(pnd_pxml_t) ); + f = fopen ( fullpath, "r" ); - memset ( p, '\0', sizeof(pnd_pxml_t) ); + if ( ! f ) { + return ( 0 ); + } + + fseek ( f, 0, SEEK_END ); + + len = ftell ( f ); + + fseek ( f, 0, SEEK_SET ); + + if ( ! len ) { + return ( NULL ); + } + + b = (char*) malloc ( len + 1 ); - if ( ! pnd_pxml_load ( fullpath, p ) ) { + if ( ! b ) { + fclose ( f ); return ( 0 ); } - return ( p ); -} + fread ( b, 1, len, f ); + + fclose ( f ); -pnd_pxml_handle pnd_pxml_fetch_buffer ( char *filename, char *buffer ) { + h = pnd_pxml_fetch_buffer ( fullpath, b ); + free ( b ); + + return ( h ); +} - pnd_pxml_t *p = malloc ( sizeof(pnd_pxml_t) ); +pnd_pxml_handle *pnd_pxml_fetch_buffer ( char *filename, char *buffer ) { - memset ( p, '\0', sizeof(pnd_pxml_t) ); + pnd_pxml_t **p = malloc ( sizeof(pnd_pxml_t*) * PXML_MAXAPPS ); + memset ( p, '\0', sizeof(pnd_pxml_t*) * PXML_MAXAPPS ); if ( ! pnd_pxml_parse ( filename, buffer, strlen ( buffer ), p ) ) { return ( 0 ); } - return ( p ); + return ( (pnd_pxml_handle*) p ); } void pnd_pxml_delete ( pnd_pxml_handle h ) { pnd_pxml_t *p = (pnd_pxml_t*) h; - if ( p -> title_en ) { - free ( p -> title_en ); - } - if ( p -> title_de ) { - free ( p -> title_de ); - } - if ( p -> title_it ) { - free ( p -> title_it ); + int i; + if (p->titles) { + for (i = 0; i < p->titles_c; i++) + { + free(p->titles[i].language); + free(p->titles[i].string); + } + free(p->titles); } - if ( p -> title_fr ) { - free ( p -> title_fr ); + + if (p->descriptions) { + for (i = 0; i < p->descriptions_c; i++) + { + free(p->descriptions[i].language); + free(p->descriptions[i].string); + } + free(p->descriptions); } + if ( p -> unique_id ) { - free ( p -> unique_id ); + free ( p -> unique_id ); + } + if ( p -> package_id ) { + free ( p -> package_id ); } if ( p -> standalone ) { free ( p -> standalone ); @@ -61,18 +97,6 @@ void pnd_pxml_delete ( pnd_pxml_handle h ) { if ( p -> icon ) { free ( p -> icon ); } - if ( p -> description_en ) { - free ( p -> description_en ); - } - if ( p -> description_de ) { - free ( p -> description_de ); - } - if ( p -> description_it ) { - free ( p -> description_it ); - } - if ( p -> description_fr ) { - free ( p -> description_fr ); - } if ( p -> previewpic1 ) { free ( p -> previewpic1 ); } @@ -166,26 +190,84 @@ void pnd_pxml_delete ( pnd_pxml_handle h ) { if ( p -> startdir ) { free ( p -> startdir ); } + if ( p -> appdata_dirname ) { + free ( p -> appdata_dirname ); + } + if ( p -> info_name ) { + free ( p -> info_name ); + } + if ( p -> info_filename ) { + free ( p -> info_filename ); + } + if ( p -> info_type ) { + free ( p -> info_type ); + } + if ( p -> exec_no_x11 ) { + free ( p -> exec_no_x11 ); + } + if ( p -> execargs ) { + free ( p -> execargs ); + } + if ( p -> mkdir_sp ) { + free ( p -> mkdir_sp ); + } + if ( p -> package_version_major ) { + free ( p -> package_version_major ); + } + if ( p -> package_version_minor ) { + free ( p -> package_version_minor ); + } + if ( p -> package_version_release ) { + free ( p -> package_version_release ); + } + if ( p -> package_version_build ) { + free ( p -> package_version_build ); + } + + free(p); /*very important!*/ return; } void pnd_pxml_set_app_name ( pnd_pxml_handle h, char *v ) { + /* + * Please do not use this function if it can be avoided; it is only here for compatibility. + * The function might fail on low memory, and there's no way for the user to know when this happens. + */ pnd_pxml_t *p = (pnd_pxml_t*) h; - if ( p -> title_en ) { - free ( p -> title_en ); - p -> title_en = NULL; + char has_en_field = 0; + int i; + + if (!v) return; /*TODO: add error information? Make it possible to set the string to NULL?*/ + + for (i = 0; i < p->titles_c; i++) + { + if (strncmp("en", p->titles[i].language, 2) == 0) /*strict comparison; match "en_US", "en_GB" etc... All these are set.*/ + { + free(p->titles[i].string); + p->titles[i].string = strdup(v); + has_en_field = 1; + } } - if ( v ) { - p -> title_en = strdup ( v ); + if (!has_en_field) + { + p->titles_c++; + if (p->titles_c > p->titles_alloc_c) //we don't have enough strings allocated + { + p->titles_alloc_c <<= 1; + p->titles = (pnd_localized_string_t *)realloc((void*)p->titles, p->titles_alloc_c); + if (!p->titles) return; //errno = ENOMEM + } + p->titles[p->titles_c - 1].language = "en_US"; + p->titles[p->titles_c - 1].string = strdup(v); } return; } unsigned char pnd_is_pxml_valid_app ( pnd_pxml_handle h ) { - pnd_pxml_t *p = (pnd_pxml_t*) h; + //pnd_pxml_t *p = (pnd_pxml_t*) h; //unused atm // for now, lets just verify the exec-path is valid @@ -209,8 +291,14 @@ signed char pnd_pxml_merge_override ( pnd_pxml_handle h, char *searchpath ) { // the pxml includes a unique-id; use this value to attempt to find an // override in the given searchpath signed char retval = 0; + +#if 0 // TODO: Unfinished entirely now pnd_pxml_handle mergeh; + if ( ! pnd_pxml_get_unique_id ( h ) ) { + return ( -1 ); // no unique-id present, so can't use it to name potential override files + } + SEARCHPATH_PRE { @@ -220,10 +308,12 @@ signed char pnd_pxml_merge_override ( pnd_pxml_handle h, char *searchpath ) { strncat ( buffer, ".xml", FILENAME_MAX ); //printf ( " Path to seek merges: '%s'\n", buffer ); + // TODO: handle multiple subapps! mergeh = pnd_pxml_fetch ( buffer ); if ( mergeh ) { + // TODO: handle all the various data bits if ( pnd_pxml_get_app_name_en ( mergeh ) ) { pnd_pxml_set_app_name ( h, pnd_pxml_get_app_name_en ( mergeh ) ); } @@ -233,35 +323,77 @@ signed char pnd_pxml_merge_override ( pnd_pxml_handle h, char *searchpath ) { } SEARCHPATH_POST +#endif return ( retval ); } -char *pnd_pxml_get_app_name_en ( pnd_pxml_handle h ) { +char *pnd_pxml_get_best_localized_string(pnd_localized_string_t strings[], int strings_c, char *iso_lang) +{ + int i; + int similarity_weight = 0xffff; /*Set to something Really Bad in the beginning*/ + char *best_match = NULL; + + for(i = 0; i < strings_c; i++) + { + // factor in the length -- if we're given 'en' and have a string 'en_US', thats better than 'de_something'; if we don't + // use length, then en_US and de_FO are same to 'en'. + int maxcount = strlen ( strings[i].language ) < strlen ( iso_lang ) ? strlen ( strings[i].language ) : strlen ( iso_lang ); + int new_weight = abs(strncmp(strings[i].language, iso_lang, maxcount)); + //pnd_log ( PND_LOG_DEFAULT, "looking for lang %s, looking at lang %s (weight %d, old %d): %s\n", + // iso_lang, strings [ i ].language, new_weight, similarity_weight, strings [ i ].string ); + if (new_weight < similarity_weight) + { + similarity_weight = new_weight; + best_match = strings[i].string; + } + } + + if ( best_match ) { + //pnd_log ( PND_LOG_DEFAULT, "best match: %s\n", best_match ); + return strdup(best_match); + } + + //pnd_log ( PND_LOG_DEFAULT, "best match: FAIL\n" ); + + return ( NULL ); +} + +char *pnd_pxml_get_package_id ( pnd_pxml_handle h ) { pnd_pxml_t *p = (pnd_pxml_t*) h; - return ( p -> title_en ); + return ( p -> package_id ); +} + +char *pnd_pxml_get_app_name ( pnd_pxml_handle h, char *iso_lang ) { + pnd_pxml_t *p = (pnd_pxml_t *) h; + return pnd_pxml_get_best_localized_string(p->titles, p->titles_c, iso_lang); +} + +char *pnd_pxml_get_app_name_en ( pnd_pxml_handle h ) { + return pnd_pxml_get_app_name(h, "en"); } char *pnd_pxml_get_app_name_de ( pnd_pxml_handle h ) { - pnd_pxml_t *p = (pnd_pxml_t*) h; - return ( p -> title_de ); + return pnd_pxml_get_app_name(h, "de"); } char *pnd_pxml_get_app_name_it ( pnd_pxml_handle h ) { - pnd_pxml_t *p = (pnd_pxml_t*) h; - return ( p -> title_it ); + return pnd_pxml_get_app_name(h, "it"); } char *pnd_pxml_get_app_name_fr ( pnd_pxml_handle h ) { - pnd_pxml_t *p = (pnd_pxml_t*) h; - return ( p -> title_fr ); + return pnd_pxml_get_app_name(h, "fr"); } - char *pnd_pxml_get_unique_id ( pnd_pxml_handle h ) { pnd_pxml_t *p = (pnd_pxml_t*) h; return ( p -> unique_id ); } +char *pnd_pxml_get_appdata_dirname ( pnd_pxml_handle h ) { + pnd_pxml_t *p = (pnd_pxml_t*) h; + return ( p -> appdata_dirname ); +} + char *pnd_pxml_get_standalone ( pnd_pxml_handle h ) { pnd_pxml_t *p = (pnd_pxml_t*) h; return ( p -> standalone ); @@ -272,24 +404,34 @@ char *pnd_pxml_get_icon ( pnd_pxml_handle h ) { return ( p -> icon ); } +// this guy's func name is 'out of sync' with the family of functions below; but since it +// exists, rather than just remove it and break someones code, will add in the appropriate +// function wrapper; the header only specifies the other guy (always did), so the header +// was already on the right path. +char *pnd_pxml_get_app_description ( pnd_pxml_handle h, char *iso_lang ) { + pnd_pxml_t *p = (pnd_pxml_t *) h; + return pnd_pxml_get_best_localized_string(p->descriptions, p->descriptions_c, iso_lang); +} + char *pnd_pxml_get_description_en ( pnd_pxml_handle h ) { - pnd_pxml_t *p = (pnd_pxml_t*) h; - return ( p -> description_en ); + return pnd_pxml_get_app_description(h, "en"); } char *pnd_pxml_get_description_de ( pnd_pxml_handle h ) { - pnd_pxml_t *p = (pnd_pxml_t*) h; - return ( p -> description_de ); + return pnd_pxml_get_app_description(h, "de"); } char *pnd_pxml_get_description_it ( pnd_pxml_handle h ) { - pnd_pxml_t *p = (pnd_pxml_t*) h; - return ( p -> description_it ); + return pnd_pxml_get_app_description(h, "it"); } char *pnd_pxml_get_description_fr ( pnd_pxml_handle h ) { - pnd_pxml_t *p = (pnd_pxml_t*) h; - return ( p -> description_fr ); + return pnd_pxml_get_app_description(h, "fr"); +} + +// wrapper added so family of function names is consistent; see comment for pnd_pxml_get_app_description() above +char *pnd_pxml_get_description ( pnd_pxml_handle h, char *iso_lang) { + return ( pnd_pxml_get_app_description ( h, iso_lang ) ); } char *pnd_pxml_get_previewpic1 ( pnd_pxml_handle h ) { @@ -337,6 +479,16 @@ char *pnd_pxml_get_exec ( pnd_pxml_handle h ) { return ( p -> exec ); } +char *pnd_pxml_get_execargs ( pnd_pxml_handle h ) { + pnd_pxml_t *p = (pnd_pxml_t*) h; + return ( p -> execargs ); +} + +char *pnd_pxml_get_exec_option_no_x11 ( pnd_pxml_handle h ) { + pnd_pxml_t *p = (pnd_pxml_t*) h; + return ( p -> exec_no_x11 ); +} + char *pnd_pxml_get_main_category ( pnd_pxml_handle h ) { pnd_pxml_t *p = (pnd_pxml_t*) h; return ( p -> main_category ); @@ -446,3 +598,74 @@ char *pnd_pxml_get_startdir ( pnd_pxml_handle h ) { pnd_pxml_t *p = (pnd_pxml_t*) h; return ( p -> startdir ); } + +char *pnd_pxml_get_mkdir ( pnd_pxml_handle h ) { + pnd_pxml_t *p = (pnd_pxml_t*) h; + return ( p -> mkdir_sp ); +} + +char *pnd_pxml_get_package_version_major ( pnd_pxml_handle h ) { + pnd_pxml_t *p = (pnd_pxml_t*) h; + return ( p -> package_version_major ); +} + +char *pnd_pxml_get_package_version_minor ( pnd_pxml_handle h ) { + pnd_pxml_t *p = (pnd_pxml_t*) h; + return ( p -> package_version_minor ); +} + +char *pnd_pxml_get_package_version_release ( pnd_pxml_handle h ) { + pnd_pxml_t *p = (pnd_pxml_t*) h; + return ( p -> package_version_release ); +} + +char *pnd_pxml_get_package_version_build ( pnd_pxml_handle h ) { + pnd_pxml_t *p = (pnd_pxml_t*) h; + return ( p -> package_version_build ); +} + +unsigned char pnd_pxml_is_affirmative ( char *v ) { + + if ( ! v ) { + return ( 0 ); + } + + if ( ( v [ 0 ] == 'Y' ) || + ( v [ 0 ] == 'y' ) || + ( v [ 0 ] == '1' ) ) + { + return ( 0 ); + } + + return ( 0 ); +} + +pnd_pxml_x11_req_e pnd_pxml_get_x11 ( char *pxmlvalue ) { + + if ( ! pxmlvalue ) { + return ( pnd_pxml_x11_ignored ); + } else if ( strcasecmp ( pxmlvalue, "req" ) == 0 ) { + return ( pnd_pxml_x11_required ); + } else if ( strcasecmp ( pxmlvalue, "stop" ) == 0 ) { + return ( pnd_pxml_x11_stop ); + } else if ( strcasecmp ( pxmlvalue, "ignore" ) == 0 ) { + return ( pnd_pxml_x11_ignored ); + } + + return ( pnd_pxml_x11_ignored ); // default +} + +char *pnd_pxml_get_info_name ( pnd_pxml_handle h ) { + pnd_pxml_t *p = (pnd_pxml_t*) h; + return ( p -> info_name ); +} + +char *pnd_pxml_get_info_type ( pnd_pxml_handle h ) { + pnd_pxml_t *p = (pnd_pxml_t*) h; + return ( p -> info_type ); +} + +char *pnd_pxml_get_info_src ( pnd_pxml_handle h ) { + pnd_pxml_t *p = (pnd_pxml_t*) h; + return ( p -> info_filename ); +}