2 #include <stdio.h> /* for FILE */
3 #include <stdlib.h> /* for malloc */
4 #include <string.h> /* for string ops */
6 #include <sys/types.h> /* for stat */
7 #include <sys/stat.h> /* for stat */
8 #include <unistd.h> /* for stat */
11 #include "pnd_pathiter.h"
12 #include "pnd_tinyxml.h"
14 pnd_pxml_handle pnd_pxml_fetch ( char *fullpath ) {
16 pnd_pxml_t *p = malloc ( sizeof(pnd_pxml_t) );
18 memset ( p, '\0', sizeof(pnd_pxml_t) );
20 if ( ! pnd_pxml_load ( fullpath, p ) ) {
27 pnd_pxml_handle pnd_pxml_fetch_buffer ( char *filename, char *buffer ) {
29 pnd_pxml_t *p = malloc ( sizeof(pnd_pxml_t) );
31 memset ( p, '\0', sizeof(pnd_pxml_t) );
33 if ( ! pnd_pxml_parse ( filename, buffer, strlen ( buffer ), p ) ) {
40 void pnd_pxml_delete ( pnd_pxml_handle h ) {
41 pnd_pxml_t *p = (pnd_pxml_t*) h;
45 for (i = 0; i < p->titles_c; i++)
47 free(p->titles[i].language);
48 free(p->titles[i].string);
53 if (p->descriptions) {
54 for (i = 0; i < p->descriptions_c; i++)
56 free(p->descriptions[i].language);
57 free(p->descriptions[i].string);
59 free(p->descriptions);
62 if ( p -> standalone ) {
63 free ( p -> standalone );
68 if ( p -> previewpic1 ) {
69 free ( p -> previewpic1 );
71 if ( p -> previewpic2 ) {
72 free ( p -> previewpic2 );
74 if ( p -> author_name ) {
75 free ( p -> author_name );
77 if ( p -> author_website ) {
78 free ( p -> author_website );
80 if ( p -> version_major ) {
81 free ( p -> version_major );
83 if ( p -> version_minor ) {
84 free ( p -> version_minor );
86 if ( p -> version_release ) {
87 free ( p -> version_release );
89 if ( p -> version_build ) {
90 free ( p -> version_build );
95 if ( p -> main_category ) {
96 free ( p -> main_category );
98 if ( p -> subcategory1 ) {
99 free ( p -> subcategory1 );
101 if ( p -> subcategory2 ) {
102 free ( p -> subcategory2 );
104 if ( p -> altcategory ) {
105 free ( p -> altcategory );
107 if ( p -> altsubcategory1 ) {
108 free ( p -> altsubcategory1 );
110 if ( p -> altsubcategory2 ) {
111 free ( p -> altsubcategory2 );
113 if ( p -> osversion_major ) {
114 free ( p -> osversion_major );
116 if ( p -> osversion_minor ) {
117 free ( p -> osversion_minor );
119 if ( p -> osversion_release ) {
120 free ( p -> osversion_release );
122 if ( p -> osversion_build ) {
123 free ( p -> osversion_build );
125 if ( p -> associationitem1_name ) {
126 free ( p -> associationitem1_name );
128 if ( p -> associationitem1_filetype ) {
129 free ( p -> associationitem1_filetype );
131 if ( p -> associationitem1_parameter ) {
132 free ( p -> associationitem1_parameter );
134 if ( p -> associationitem2_name ) {
135 free ( p -> associationitem2_name );
137 if ( p -> associationitem2_filetype ) {
138 free ( p -> associationitem2_filetype );
140 if ( p -> associationitem2_parameter ) {
141 free ( p -> associationitem2_parameter );
143 if ( p -> associationitem3_name ) {
144 free ( p -> associationitem3_name );
146 if ( p -> associationitem1_filetype ) {
147 free ( p -> associationitem3_filetype );
149 if ( p -> associationitem1_parameter ) {
150 free ( p -> associationitem3_parameter );
152 if ( p -> clockspeed ) {
153 free ( p -> clockspeed );
155 if ( p -> background ) {
156 free ( p -> background );
158 if ( p -> startdir ) {
159 free ( p -> startdir );
162 free(p); /*very important!*/
167 void pnd_pxml_set_app_name ( pnd_pxml_handle h, char *v ) {
169 * Please do not use this function if it can be avoided; it is only here for compatibility.
170 * The function might fail on low memory, and there's no way for the user to know when this happens.
172 pnd_pxml_t *p = (pnd_pxml_t*) h;
173 char has_en_field = 0;
176 if (!v) return; /*TODO: add error information? Make it possible to set the string to NULL?*/
178 for (i = 0; i < p->titles_c; i++)
180 if (strncmp("en", p->titles[i].language, 2) == 0) /*strict comparison; match "en_US", "en_GB" etc... All these are set.*/
182 free(p->titles[i].string);
183 p->titles[i].string = strdup(v);
191 if (p->titles_c > p->titles_alloc_c) //we don't have enough strings allocated
193 p->titles_alloc_c <<= 1;
194 p->titles = (pnd_localized_string_t *)realloc((void*)p->titles, p->titles_alloc_c);
195 if (!p->titles) return; //errno = ENOMEM
197 p->titles[p->titles_c - 1].language = "en_US";
198 p->titles[p->titles_c - 1].string = strdup(v);
204 unsigned char pnd_is_pxml_valid_app ( pnd_pxml_handle h ) {
205 //pnd_pxml_t *p = (pnd_pxml_t*) h; //unused atm
207 // for now, lets just verify the exec-path is valid
209 //printf ( "exec is '%s'\n", p -> exec );
213 // even this is complicated by pnd_run.sh semantics .. can't check if it exists
214 // during discovery, since it is not mounted yet..
217 if ( stat ( p -> exec, &buf ) == 0 ) {
218 return ( 1 ); // path is present
225 signed char pnd_pxml_merge_override ( pnd_pxml_handle h, char *searchpath ) {
226 // the pxml includes a unique-id; use this value to attempt to find an
227 // override in the given searchpath
228 signed char retval = 0;
229 pnd_pxml_handle mergeh;
231 if ( ! pnd_pxml_get_unique_id ( h ) ) {
232 return ( -1 ); // no unique-id present, so can't use it to name potential override files
239 strncat ( buffer, "/", FILENAME_MAX );
240 strncat ( buffer, pnd_pxml_get_unique_id ( h ), FILENAME_MAX );
241 strncat ( buffer, ".xml", FILENAME_MAX );
242 //printf ( " Path to seek merges: '%s'\n", buffer );
244 mergeh = pnd_pxml_fetch ( buffer );
248 if ( pnd_pxml_get_app_name_en ( mergeh ) ) {
249 pnd_pxml_set_app_name ( h, pnd_pxml_get_app_name_en ( mergeh ) );
252 pnd_pxml_delete ( mergeh );
261 char *pnd_pxml_get_best_localized_string(pnd_localized_string_t strings[], int strings_c, char *iso_lang)
264 int similarity_weight = 0xff; /*Set to something Really Bad in the beginning*/
265 char *best_match = NULL;
267 for(i = 0; i < strings_c; i++)
269 int new_weight = abs(strcmp(strings[i].language, iso_lang));
270 if (new_weight < similarity_weight)
272 similarity_weight = new_weight;
273 best_match = strings[i].string;
278 return strdup(best_match);
284 char *pnd_pxml_get_app_name ( pnd_pxml_handle h, char *iso_lang ) {
285 pnd_pxml_t *p = (pnd_pxml_t *) h;
286 return pnd_pxml_get_best_localized_string(p->titles, p->titles_c, iso_lang);
289 char *pnd_pxml_get_app_name_en ( pnd_pxml_handle h ) {
290 return pnd_pxml_get_app_name(h, "en");
293 char *pnd_pxml_get_app_name_de ( pnd_pxml_handle h ) {
294 return pnd_pxml_get_app_name(h, "de");
297 char *pnd_pxml_get_app_name_it ( pnd_pxml_handle h ) {
298 return pnd_pxml_get_app_name(h, "it");
301 char *pnd_pxml_get_app_name_fr ( pnd_pxml_handle h ) {
302 return pnd_pxml_get_app_name(h, "fr");
305 char *pnd_pxml_get_unique_id ( pnd_pxml_handle h ) {
306 pnd_pxml_t *p = (pnd_pxml_t*) h;
307 return ( p -> unique_id );
310 char *pnd_pxml_get_standalone ( pnd_pxml_handle h ) {
311 pnd_pxml_t *p = (pnd_pxml_t*) h;
312 return ( p -> standalone );
315 char *pnd_pxml_get_icon ( pnd_pxml_handle h ) {
316 pnd_pxml_t *p = (pnd_pxml_t*) h;
317 return ( p -> icon );
320 char *pnd_pxml_get_app_description ( pnd_pxml_handle h, char *iso_lang ) {
321 pnd_pxml_t *p = (pnd_pxml_t *) h;
322 return pnd_pxml_get_best_localized_string(p->descriptions, p->descriptions_c, iso_lang);
325 char *pnd_pxml_get_description_en ( pnd_pxml_handle h ) {
326 return pnd_pxml_get_app_description(h, "en");
329 char *pnd_pxml_get_description_de ( pnd_pxml_handle h ) {
330 return pnd_pxml_get_app_description(h, "de");
333 char *pnd_pxml_get_description_it ( pnd_pxml_handle h ) {
334 return pnd_pxml_get_app_description(h, "it");
337 char *pnd_pxml_get_description_fr ( pnd_pxml_handle h ) {
338 return pnd_pxml_get_app_description(h, "fr");
341 char *pnd_pxml_get_previewpic1 ( pnd_pxml_handle h ) {
342 pnd_pxml_t *p = (pnd_pxml_t*) h;
343 return ( p -> previewpic1 );
346 char *pnd_pxml_get_previewpic2 ( pnd_pxml_handle h ) {
347 pnd_pxml_t *p = (pnd_pxml_t*) h;
348 return ( p -> previewpic2 );
351 char *pnd_pxml_get_author_name ( pnd_pxml_handle h ) {
352 pnd_pxml_t *p = (pnd_pxml_t*) h;
353 return ( p -> author_name );
356 char *pnd_pxml_get_author_website ( pnd_pxml_handle h ) {
357 pnd_pxml_t *p = (pnd_pxml_t*) h;
358 return ( p -> author_website );
361 char *pnd_pxml_get_version_major ( pnd_pxml_handle h ) {
362 pnd_pxml_t *p = (pnd_pxml_t*) h;
363 return ( p -> version_major );
366 char *pnd_pxml_get_version_minor ( pnd_pxml_handle h ) {
367 pnd_pxml_t *p = (pnd_pxml_t*) h;
368 return ( p -> version_minor );
371 char *pnd_pxml_get_version_release ( pnd_pxml_handle h ) {
372 pnd_pxml_t *p = (pnd_pxml_t*) h;
373 return ( p -> version_release );
376 char *pnd_pxml_get_version_build ( pnd_pxml_handle h ) {
377 pnd_pxml_t *p = (pnd_pxml_t*) h;
378 return ( p -> version_build );
381 char *pnd_pxml_get_exec ( pnd_pxml_handle h ) {
382 pnd_pxml_t *p = (pnd_pxml_t*) h;
383 return ( p -> exec );
386 char *pnd_pxml_get_exec_option_no_x11 ( pnd_pxml_handle h ) {
387 pnd_pxml_t *p = (pnd_pxml_t*) h;
388 return ( p -> exec_no_x11 );
391 char *pnd_pxml_get_main_category ( pnd_pxml_handle h ) {
392 pnd_pxml_t *p = (pnd_pxml_t*) h;
393 return ( p -> main_category );
396 char *pnd_pxml_get_subcategory1 ( pnd_pxml_handle h ) {
397 pnd_pxml_t *p = (pnd_pxml_t*) h;
398 return ( p -> subcategory1 );
401 char *pnd_pxml_get_subcategory2 ( pnd_pxml_handle h ) {
402 pnd_pxml_t *p = (pnd_pxml_t*) h;
403 return ( p -> subcategory2 );
406 char *pnd_pxml_get_altcategory ( pnd_pxml_handle h ) {
407 pnd_pxml_t *p = (pnd_pxml_t*) h;
408 return ( p -> altcategory );
411 char *pnd_pxml_get_altsubcategory1 ( pnd_pxml_handle h ) {
412 pnd_pxml_t *p = (pnd_pxml_t*) h;
413 return ( p -> altsubcategory1 );
416 char *pnd_pxml_get_altsubcategory2 ( pnd_pxml_handle h ) {
417 pnd_pxml_t *p = (pnd_pxml_t*) h;
418 return ( p -> altsubcategory2 );
421 char *pnd_pxml_get_osversion_major ( pnd_pxml_handle h ) {
422 pnd_pxml_t *p = (pnd_pxml_t*) h;
423 return ( p -> osversion_major );
426 char *pnd_pxml_get_osversion_minor ( pnd_pxml_handle h ) {
427 pnd_pxml_t *p = (pnd_pxml_t*) h;
428 return ( p -> osversion_minor );
431 char *pnd_pxml_get_osversion_release ( pnd_pxml_handle h ) {
432 pnd_pxml_t *p = (pnd_pxml_t*) h;
433 return ( p -> osversion_release );
436 char *pnd_pxml_get_osversion_build ( pnd_pxml_handle h ) {
437 pnd_pxml_t *p = (pnd_pxml_t*) h;
438 return ( p -> osversion_build );
441 char *pnd_pxml_get_associationitem1_name ( pnd_pxml_handle h ) {
442 pnd_pxml_t *p = (pnd_pxml_t*) h;
443 return ( p -> associationitem1_name );
446 char *pnd_pxml_get_associationitem1_filetype ( pnd_pxml_handle h ) {
447 pnd_pxml_t *p = (pnd_pxml_t*) h;
448 return ( p -> associationitem1_filetype );
451 char *pnd_pxml_get_associationitem1_parameter ( pnd_pxml_handle h ) {
452 pnd_pxml_t *p = (pnd_pxml_t*) h;
453 return ( p -> associationitem1_parameter );
456 char *pnd_pxml_get_associationitem2_name ( pnd_pxml_handle h ) {
457 pnd_pxml_t *p = (pnd_pxml_t*) h;
458 return ( p -> associationitem2_name );
461 char *pnd_pxml_get_associationitem2_filetype ( pnd_pxml_handle h ) {
462 pnd_pxml_t *p = (pnd_pxml_t*) h;
463 return ( p -> associationitem2_filetype );
466 char *pnd_pxml_get_associationitem2_parameter ( pnd_pxml_handle h ) {
467 pnd_pxml_t *p = (pnd_pxml_t*) h;
468 return ( p -> associationitem2_parameter );
471 char *pnd_pxml_get_associationitem3_name ( pnd_pxml_handle h ) {
472 pnd_pxml_t *p = (pnd_pxml_t*) h;
473 return ( p -> associationitem3_name );
476 char *pnd_pxml_get_associationitem3_filetype ( pnd_pxml_handle h ) {
477 pnd_pxml_t *p = (pnd_pxml_t*) h;
478 return ( p -> associationitem3_filetype );
481 char *pnd_pxml_get_associationitem3_parameter ( pnd_pxml_handle h ) {
482 pnd_pxml_t *p = (pnd_pxml_t*) h;
483 return ( p -> associationitem3_parameter );
486 char *pnd_pxml_get_clockspeed ( pnd_pxml_handle h ) {
487 pnd_pxml_t *p = (pnd_pxml_t*) h;
488 return ( p -> clockspeed );
491 char *pnd_pxml_get_background ( pnd_pxml_handle h ) {
492 pnd_pxml_t *p = (pnd_pxml_t*) h;
493 return ( p -> background );
496 char *pnd_pxml_get_startdir ( pnd_pxml_handle h ) {
497 pnd_pxml_t *p = (pnd_pxml_t*) h;
498 return ( p -> startdir );
501 char *pnd_pxml_get_mkdir ( pnd_pxml_handle h ) {
502 pnd_pxml_t *p = (pnd_pxml_t*) h;
503 return ( p -> mkdir_sp );