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 ) {
19 f = fopen ( fullpath, "r" );
25 fseek ( f, 0, SEEK_END );
29 fseek ( f, 0, SEEK_SET );
31 b = (char*) malloc ( len );
38 fread ( b, 1, len, f );
42 return ( pnd_pxml_fetch_buffer ( fullpath, b ) );
45 pnd_pxml_handle *pnd_pxml_fetch_buffer ( char *filename, char *buffer ) {
47 pnd_pxml_t **p = malloc ( sizeof(pnd_pxml_t*) * PXML_MAXAPPS );
48 memset ( p, '\0', sizeof(pnd_pxml_t*) * PXML_MAXAPPS );
50 if ( ! pnd_pxml_parse ( filename, buffer, strlen ( buffer ), p ) ) {
54 return ( (pnd_pxml_handle*) p );
57 void pnd_pxml_delete ( pnd_pxml_handle h ) {
58 pnd_pxml_t *p = (pnd_pxml_t*) h;
62 for (i = 0; i < p->titles_c; i++)
64 free(p->titles[i].language);
65 free(p->titles[i].string);
70 if (p->descriptions) {
71 for (i = 0; i < p->descriptions_c; i++)
73 free(p->descriptions[i].language);
74 free(p->descriptions[i].string);
76 free(p->descriptions);
79 if ( p -> standalone ) {
80 free ( p -> standalone );
85 if ( p -> previewpic1 ) {
86 free ( p -> previewpic1 );
88 if ( p -> previewpic2 ) {
89 free ( p -> previewpic2 );
91 if ( p -> author_name ) {
92 free ( p -> author_name );
94 if ( p -> author_website ) {
95 free ( p -> author_website );
97 if ( p -> version_major ) {
98 free ( p -> version_major );
100 if ( p -> version_minor ) {
101 free ( p -> version_minor );
103 if ( p -> version_release ) {
104 free ( p -> version_release );
106 if ( p -> version_build ) {
107 free ( p -> version_build );
112 if ( p -> main_category ) {
113 free ( p -> main_category );
115 if ( p -> subcategory1 ) {
116 free ( p -> subcategory1 );
118 if ( p -> subcategory2 ) {
119 free ( p -> subcategory2 );
121 if ( p -> altcategory ) {
122 free ( p -> altcategory );
124 if ( p -> altsubcategory1 ) {
125 free ( p -> altsubcategory1 );
127 if ( p -> altsubcategory2 ) {
128 free ( p -> altsubcategory2 );
130 if ( p -> osversion_major ) {
131 free ( p -> osversion_major );
133 if ( p -> osversion_minor ) {
134 free ( p -> osversion_minor );
136 if ( p -> osversion_release ) {
137 free ( p -> osversion_release );
139 if ( p -> osversion_build ) {
140 free ( p -> osversion_build );
142 if ( p -> associationitem1_name ) {
143 free ( p -> associationitem1_name );
145 if ( p -> associationitem1_filetype ) {
146 free ( p -> associationitem1_filetype );
148 if ( p -> associationitem1_parameter ) {
149 free ( p -> associationitem1_parameter );
151 if ( p -> associationitem2_name ) {
152 free ( p -> associationitem2_name );
154 if ( p -> associationitem2_filetype ) {
155 free ( p -> associationitem2_filetype );
157 if ( p -> associationitem2_parameter ) {
158 free ( p -> associationitem2_parameter );
160 if ( p -> associationitem3_name ) {
161 free ( p -> associationitem3_name );
163 if ( p -> associationitem1_filetype ) {
164 free ( p -> associationitem3_filetype );
166 if ( p -> associationitem1_parameter ) {
167 free ( p -> associationitem3_parameter );
169 if ( p -> clockspeed ) {
170 free ( p -> clockspeed );
172 if ( p -> background ) {
173 free ( p -> background );
175 if ( p -> startdir ) {
176 free ( p -> startdir );
179 free(p); /*very important!*/
184 void pnd_pxml_set_app_name ( pnd_pxml_handle h, char *v ) {
186 * Please do not use this function if it can be avoided; it is only here for compatibility.
187 * The function might fail on low memory, and there's no way for the user to know when this happens.
189 pnd_pxml_t *p = (pnd_pxml_t*) h;
190 char has_en_field = 0;
193 if (!v) return; /*TODO: add error information? Make it possible to set the string to NULL?*/
195 for (i = 0; i < p->titles_c; i++)
197 if (strncmp("en", p->titles[i].language, 2) == 0) /*strict comparison; match "en_US", "en_GB" etc... All these are set.*/
199 free(p->titles[i].string);
200 p->titles[i].string = strdup(v);
208 if (p->titles_c > p->titles_alloc_c) //we don't have enough strings allocated
210 p->titles_alloc_c <<= 1;
211 p->titles = (pnd_localized_string_t *)realloc((void*)p->titles, p->titles_alloc_c);
212 if (!p->titles) return; //errno = ENOMEM
214 p->titles[p->titles_c - 1].language = "en_US";
215 p->titles[p->titles_c - 1].string = strdup(v);
221 unsigned char pnd_is_pxml_valid_app ( pnd_pxml_handle h ) {
222 //pnd_pxml_t *p = (pnd_pxml_t*) h; //unused atm
224 // for now, lets just verify the exec-path is valid
226 //printf ( "exec is '%s'\n", p -> exec );
230 // even this is complicated by pnd_run.sh semantics .. can't check if it exists
231 // during discovery, since it is not mounted yet..
234 if ( stat ( p -> exec, &buf ) == 0 ) {
235 return ( 1 ); // path is present
242 signed char pnd_pxml_merge_override ( pnd_pxml_handle h, char *searchpath ) {
243 // the pxml includes a unique-id; use this value to attempt to find an
244 // override in the given searchpath
245 signed char retval = 0;
247 #if 0 // TODO: Unfinished entirely now
248 pnd_pxml_handle mergeh;
250 if ( ! pnd_pxml_get_unique_id ( h ) ) {
251 return ( -1 ); // no unique-id present, so can't use it to name potential override files
258 strncat ( buffer, "/", FILENAME_MAX );
259 strncat ( buffer, pnd_pxml_get_unique_id ( h ), FILENAME_MAX );
260 strncat ( buffer, ".xml", FILENAME_MAX );
261 //printf ( " Path to seek merges: '%s'\n", buffer );
263 // TODO: handle multiple subapps!
264 mergeh = pnd_pxml_fetch ( buffer );
268 // TODO: handle all the various data bits
269 if ( pnd_pxml_get_app_name_en ( mergeh ) ) {
270 pnd_pxml_set_app_name ( h, pnd_pxml_get_app_name_en ( mergeh ) );
273 pnd_pxml_delete ( mergeh );
283 char *pnd_pxml_get_best_localized_string(pnd_localized_string_t strings[], int strings_c, char *iso_lang)
286 int similarity_weight = 0xff; /*Set to something Really Bad in the beginning*/
287 char *best_match = NULL;
289 for(i = 0; i < strings_c; i++)
291 int new_weight = abs(strcmp(strings[i].language, iso_lang));
292 if (new_weight < similarity_weight)
294 similarity_weight = new_weight;
295 best_match = strings[i].string;
300 return strdup(best_match);
306 char *pnd_pxml_get_app_name ( pnd_pxml_handle h, char *iso_lang ) {
307 pnd_pxml_t *p = (pnd_pxml_t *) h;
308 return pnd_pxml_get_best_localized_string(p->titles, p->titles_c, iso_lang);
311 char *pnd_pxml_get_app_name_en ( pnd_pxml_handle h ) {
312 return pnd_pxml_get_app_name(h, "en");
315 char *pnd_pxml_get_app_name_de ( pnd_pxml_handle h ) {
316 return pnd_pxml_get_app_name(h, "de");
319 char *pnd_pxml_get_app_name_it ( pnd_pxml_handle h ) {
320 return pnd_pxml_get_app_name(h, "it");
323 char *pnd_pxml_get_app_name_fr ( pnd_pxml_handle h ) {
324 return pnd_pxml_get_app_name(h, "fr");
327 char *pnd_pxml_get_unique_id ( pnd_pxml_handle h ) {
328 pnd_pxml_t *p = (pnd_pxml_t*) h;
329 return ( p -> unique_id );
332 char *pnd_pxml_get_standalone ( pnd_pxml_handle h ) {
333 pnd_pxml_t *p = (pnd_pxml_t*) h;
334 return ( p -> standalone );
337 char *pnd_pxml_get_icon ( pnd_pxml_handle h ) {
338 pnd_pxml_t *p = (pnd_pxml_t*) h;
339 return ( p -> icon );
342 char *pnd_pxml_get_app_description ( pnd_pxml_handle h, char *iso_lang ) {
343 pnd_pxml_t *p = (pnd_pxml_t *) h;
344 return pnd_pxml_get_best_localized_string(p->descriptions, p->descriptions_c, iso_lang);
347 char *pnd_pxml_get_description_en ( pnd_pxml_handle h ) {
348 return pnd_pxml_get_app_description(h, "en");
351 char *pnd_pxml_get_description_de ( pnd_pxml_handle h ) {
352 return pnd_pxml_get_app_description(h, "de");
355 char *pnd_pxml_get_description_it ( pnd_pxml_handle h ) {
356 return pnd_pxml_get_app_description(h, "it");
359 char *pnd_pxml_get_description_fr ( pnd_pxml_handle h ) {
360 return pnd_pxml_get_app_description(h, "fr");
363 char *pnd_pxml_get_previewpic1 ( pnd_pxml_handle h ) {
364 pnd_pxml_t *p = (pnd_pxml_t*) h;
365 return ( p -> previewpic1 );
368 char *pnd_pxml_get_previewpic2 ( pnd_pxml_handle h ) {
369 pnd_pxml_t *p = (pnd_pxml_t*) h;
370 return ( p -> previewpic2 );
373 char *pnd_pxml_get_author_name ( pnd_pxml_handle h ) {
374 pnd_pxml_t *p = (pnd_pxml_t*) h;
375 return ( p -> author_name );
378 char *pnd_pxml_get_author_website ( pnd_pxml_handle h ) {
379 pnd_pxml_t *p = (pnd_pxml_t*) h;
380 return ( p -> author_website );
383 char *pnd_pxml_get_version_major ( pnd_pxml_handle h ) {
384 pnd_pxml_t *p = (pnd_pxml_t*) h;
385 return ( p -> version_major );
388 char *pnd_pxml_get_version_minor ( pnd_pxml_handle h ) {
389 pnd_pxml_t *p = (pnd_pxml_t*) h;
390 return ( p -> version_minor );
393 char *pnd_pxml_get_version_release ( pnd_pxml_handle h ) {
394 pnd_pxml_t *p = (pnd_pxml_t*) h;
395 return ( p -> version_release );
398 char *pnd_pxml_get_version_build ( pnd_pxml_handle h ) {
399 pnd_pxml_t *p = (pnd_pxml_t*) h;
400 return ( p -> version_build );
403 char *pnd_pxml_get_exec ( pnd_pxml_handle h ) {
404 pnd_pxml_t *p = (pnd_pxml_t*) h;
405 return ( p -> exec );
408 char *pnd_pxml_get_execargs ( pnd_pxml_handle h ) {
409 pnd_pxml_t *p = (pnd_pxml_t*) h;
410 return ( p -> execargs );
413 char *pnd_pxml_get_exec_option_no_x11 ( pnd_pxml_handle h ) {
414 pnd_pxml_t *p = (pnd_pxml_t*) h;
415 return ( p -> exec_no_x11 );
418 char *pnd_pxml_get_main_category ( pnd_pxml_handle h ) {
419 pnd_pxml_t *p = (pnd_pxml_t*) h;
420 return ( p -> main_category );
423 char *pnd_pxml_get_subcategory1 ( pnd_pxml_handle h ) {
424 pnd_pxml_t *p = (pnd_pxml_t*) h;
425 return ( p -> subcategory1 );
428 char *pnd_pxml_get_subcategory2 ( pnd_pxml_handle h ) {
429 pnd_pxml_t *p = (pnd_pxml_t*) h;
430 return ( p -> subcategory2 );
433 char *pnd_pxml_get_altcategory ( pnd_pxml_handle h ) {
434 pnd_pxml_t *p = (pnd_pxml_t*) h;
435 return ( p -> altcategory );
438 char *pnd_pxml_get_altsubcategory1 ( pnd_pxml_handle h ) {
439 pnd_pxml_t *p = (pnd_pxml_t*) h;
440 return ( p -> altsubcategory1 );
443 char *pnd_pxml_get_altsubcategory2 ( pnd_pxml_handle h ) {
444 pnd_pxml_t *p = (pnd_pxml_t*) h;
445 return ( p -> altsubcategory2 );
448 char *pnd_pxml_get_osversion_major ( pnd_pxml_handle h ) {
449 pnd_pxml_t *p = (pnd_pxml_t*) h;
450 return ( p -> osversion_major );
453 char *pnd_pxml_get_osversion_minor ( pnd_pxml_handle h ) {
454 pnd_pxml_t *p = (pnd_pxml_t*) h;
455 return ( p -> osversion_minor );
458 char *pnd_pxml_get_osversion_release ( pnd_pxml_handle h ) {
459 pnd_pxml_t *p = (pnd_pxml_t*) h;
460 return ( p -> osversion_release );
463 char *pnd_pxml_get_osversion_build ( pnd_pxml_handle h ) {
464 pnd_pxml_t *p = (pnd_pxml_t*) h;
465 return ( p -> osversion_build );
468 char *pnd_pxml_get_associationitem1_name ( pnd_pxml_handle h ) {
469 pnd_pxml_t *p = (pnd_pxml_t*) h;
470 return ( p -> associationitem1_name );
473 char *pnd_pxml_get_associationitem1_filetype ( pnd_pxml_handle h ) {
474 pnd_pxml_t *p = (pnd_pxml_t*) h;
475 return ( p -> associationitem1_filetype );
478 char *pnd_pxml_get_associationitem1_parameter ( pnd_pxml_handle h ) {
479 pnd_pxml_t *p = (pnd_pxml_t*) h;
480 return ( p -> associationitem1_parameter );
483 char *pnd_pxml_get_associationitem2_name ( pnd_pxml_handle h ) {
484 pnd_pxml_t *p = (pnd_pxml_t*) h;
485 return ( p -> associationitem2_name );
488 char *pnd_pxml_get_associationitem2_filetype ( pnd_pxml_handle h ) {
489 pnd_pxml_t *p = (pnd_pxml_t*) h;
490 return ( p -> associationitem2_filetype );
493 char *pnd_pxml_get_associationitem2_parameter ( pnd_pxml_handle h ) {
494 pnd_pxml_t *p = (pnd_pxml_t*) h;
495 return ( p -> associationitem2_parameter );
498 char *pnd_pxml_get_associationitem3_name ( pnd_pxml_handle h ) {
499 pnd_pxml_t *p = (pnd_pxml_t*) h;
500 return ( p -> associationitem3_name );
503 char *pnd_pxml_get_associationitem3_filetype ( pnd_pxml_handle h ) {
504 pnd_pxml_t *p = (pnd_pxml_t*) h;
505 return ( p -> associationitem3_filetype );
508 char *pnd_pxml_get_associationitem3_parameter ( pnd_pxml_handle h ) {
509 pnd_pxml_t *p = (pnd_pxml_t*) h;
510 return ( p -> associationitem3_parameter );
513 char *pnd_pxml_get_clockspeed ( pnd_pxml_handle h ) {
514 pnd_pxml_t *p = (pnd_pxml_t*) h;
515 return ( p -> clockspeed );
518 char *pnd_pxml_get_background ( pnd_pxml_handle h ) {
519 pnd_pxml_t *p = (pnd_pxml_t*) h;
520 return ( p -> background );
523 char *pnd_pxml_get_startdir ( pnd_pxml_handle h ) {
524 pnd_pxml_t *p = (pnd_pxml_t*) h;
525 return ( p -> startdir );
528 char *pnd_pxml_get_mkdir ( pnd_pxml_handle h ) {
529 pnd_pxml_t *p = (pnd_pxml_t*) h;
530 return ( p -> mkdir_sp );
533 unsigned char pnd_pxml_is_affirmative ( char *v ) {
539 if ( ( v [ 0 ] == 'Y' ) ||
540 ( v [ 0 ] == 'y' ) ||