Quick change so back to single .desktop/info, no assoc .desktops, and no alternative...
[pandora-libraries.git] / lib / pnd_discovery.c
index 4c2feba..2fd1882 100644 (file)
@@ -11,6 +11,7 @@
 
 #define _XOPEN_SOURCE 500
 #define __USE_XOPEN_EXTENDED
+#define _GNU_SOURCE
 #include <ftw.h> /* for nftw, tree walker */
 
 #include "pnd_container.h"
@@ -27,8 +28,9 @@ static pnd_box_handle disco_box;
 static char *disco_overrides = NULL;
 
 void pnd_disco_destroy ( pnd_disco_t *p ) {
-
+  if ( p -> package_id ) {     free ( p -> package_id);   }
   if ( p -> title_en ) {       free ( p -> title_en );    }
+  if ( p -> desc_en ) {        free ( p -> desc_en );    }
   if ( p -> unique_id ) {      free ( p -> unique_id );   }
   if ( p -> appdata_dirname ) { free ( p -> appdata_dirname );   }
   if ( p -> icon )     {       free ( p -> icon );        }
@@ -43,10 +45,25 @@ void pnd_disco_destroy ( pnd_disco_t *p ) {
   if ( p -> alt_category ) {   free ( p -> alt_category );   }
   if ( p -> alt_category1 ) {  free ( p -> alt_category1 );  }
   if ( p -> alt_category2 ) {  free ( p -> alt_category2 );  }
+  if ( p -> object_filename ) { free ( p -> object_filename ); }
+  if ( p -> object_path )     { free ( p -> object_path ); }
   if ( p -> mkdir_sp )      {  free ( p -> mkdir_sp );       }
   if ( p -> info_name )     {  free ( p -> info_name );       }
   if ( p -> info_type )     {  free ( p -> info_type );       }
   if ( p -> info_filename ) {  free ( p -> info_filename );       }
+  if ( p -> preview_pic1 )  {  free ( p -> preview_pic1 );     }
+  if ( p -> preview_pic2 )  {  free ( p -> preview_pic2 );     }
+  if ( p -> version_major ) {  free ( p -> version_major );    }
+  if ( p -> version_minor ) {  free ( p -> version_minor );    }
+  if ( p -> version_release ) {free ( p -> version_release );  }
+  if ( p -> version_build ) {  free ( p -> version_build );    }
+  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 ); }
+  if ( p -> associationitem1_name ) { free ( p -> associationitem1_name ); }
+  if ( p -> associationitem1_filetype ) { free ( p -> associationitem1_filetype ); }
+  if ( p -> exec_dashdash_args ) { free ( p -> exec_dashdash_args ); }
 
   return;
 }
@@ -70,7 +87,10 @@ static int pnd_disco_callback ( const char *fpath, const struct stat *sb,
     if ( logit ) {
       pnd_log ( PND_LOG_DEFAULT, " .. is dir, skipping\n" );
     }
-    return ( 0 ); // skip directories and other non-regular files
+    if ( ftwbuf -> level >= pathiter_depthlimit ) {
+      return ( FTW_SKIP_SUBTREE );
+    }
+    return ( FTW_CONTINUE ); // skip directories and other non-regular files
   }
 
   // PND/PNZ file and others may be valid as well .. but lets leave that for now
@@ -86,7 +106,7 @@ static int pnd_disco_callback ( const char *fpath, const struct stat *sb,
     if ( logit ) {
       pnd_log ( PND_LOG_DEFAULT, " .. bad filename, skipping\n" );
     }
-    return ( 0 );
+    return ( FTW_CONTINUE );
   }
 
   // potentially a valid application
@@ -114,13 +134,13 @@ static int pnd_disco_callback ( const char *fpath, const struct stat *sb,
     // try to locate the PXML portion
     if ( ! pnd_pnd_seek_pxml ( f ) ) {
       fclose ( f );
-      return ( 0 ); // pnd or not, but not to spec. Pwn'd the pnd?
+      return ( FTW_CONTINUE ); // pnd or not, but not to spec. Pwn'd the pnd?
     }
 
     // accrue it into a buffer
     if ( ! pnd_pnd_accrue_pxml ( f, pxmlbuf, 32 * 1024 ) ) {
       fclose ( f );
-      return ( 0 );
+      return ( FTW_CONTINUE );
     }
 
     //printf ( "buffer is %s\n", pxmlbuf );
@@ -170,7 +190,7 @@ static int pnd_disco_callback ( const char *fpath, const struct stat *sb,
 
   // pxmlh is useful?
   if ( ! pxmlapps ) {
-    return ( 0 ); // continue tree walk
+    return ( FTW_CONTINUE ); // continue tree walk
   }
 
   // for ovr-file
@@ -220,11 +240,16 @@ static int pnd_disco_callback ( const char *fpath, const struct stat *sb,
       p -> object_type = valid;
 
       // PXML fields
-      if ( pnd_pxml_get_app_name_en ( pxmlh ) ) {
-       p -> title_en = strdup ( pnd_pxml_get_app_name_en ( pxmlh ) );
+      if ( pnd_pxml_get_package_id ( pxmlh ) ) {
+       p -> package_id = strdup ( pnd_pxml_get_package_id ( pxmlh ) );
+      }
+      char *name_en = pnd_pxml_get_app_name_en ( pxmlh );
+      if (name_en) {
+       p -> title_en = name_en; /* already strdupped */
       }
-      if ( pnd_pxml_get_description_en ( pxmlh ) ) {
-       p -> desc_en = strdup ( pnd_pxml_get_description_en ( pxmlh ) );
+      char *desc_en = pnd_pxml_get_description_en ( pxmlh );
+      if ( desc_en ) {
+       p -> desc_en = desc_en; /* already strdupped */
       }
       if ( pnd_pxml_get_icon ( pxmlh ) ) {
        p -> icon = strdup ( pnd_pxml_get_icon ( pxmlh ) );
@@ -245,10 +270,10 @@ static int pnd_disco_callback ( const char *fpath, const struct stat *sb,
        p -> appdata_dirname = strdup ( pnd_pxml_get_appdata_dirname ( pxmlh ) );
       }
       if ( pnd_pxml_get_clockspeed ( pxmlh ) ) {
-       p -> clockspeed = strdup ( pnd_pxml_get_clockspeed ( pxmlh ) ); 
+       p -> clockspeed = strdup ( pnd_pxml_get_clockspeed ( pxmlh ) );
       }
       if ( pnd_pxml_get_startdir ( pxmlh ) ) {
-       p -> startdir = strdup ( pnd_pxml_get_startdir ( pxmlh ) ); 
+       p -> startdir = strdup ( pnd_pxml_get_startdir ( pxmlh ) );
       }
       // category kruft
       if ( pnd_pxml_get_main_category ( pxmlh ) ) {
@@ -290,6 +315,41 @@ static int pnd_disco_callback ( const char *fpath, const struct stat *sb,
       if ( pnd_pxml_get_info_type ( pxmlh ) ) {
        p -> info_type = strdup ( pnd_pxml_get_info_type ( pxmlh ) );
       }
+      if ( pnd_pxml_get_version_major ( pxmlh ) ) {
+   p -> version_major = strdup ( pnd_pxml_get_version_major ( pxmlh ) );
+      }
+      if ( pnd_pxml_get_version_minor ( pxmlh ) ) {
+   p -> version_minor = strdup ( pnd_pxml_get_version_minor ( pxmlh ) );
+      }
+      if ( pnd_pxml_get_version_release ( pxmlh ) ) {
+   p -> version_release = strdup ( pnd_pxml_get_version_release ( pxmlh ) );
+      }
+      if ( pnd_pxml_get_version_build ( pxmlh ) ) {
+   p -> version_build = strdup ( pnd_pxml_get_version_build ( pxmlh ) );
+      }
+      if ( pnd_pxml_get_package_version_major ( pxmlh ) ) {
+       p -> package_version_major = strdup ( pnd_pxml_get_package_version_major ( pxmlh ) );
+      }
+      if ( pnd_pxml_get_package_version_minor ( pxmlh ) ) {
+   p -> package_version_minor = strdup ( pnd_pxml_get_package_version_minor ( pxmlh ) );
+      }
+      if ( pnd_pxml_get_package_version_release ( pxmlh ) ) {
+   p -> package_version_release = strdup ( pnd_pxml_get_package_version_release ( pxmlh ) );
+      }
+      if ( pnd_pxml_get_package_version_build ( pxmlh ) ) {
+   p -> package_version_build = strdup ( pnd_pxml_get_package_version_build ( pxmlh ) );
+      }
+#if 1
+      // file associations
+      if ( pnd_pxml_get_associationitem1_name ( pxmlh ) ) {
+       p -> associationitem1_name = strdup ( pnd_pxml_get_associationitem1_name ( pxmlh ) );
+       p -> associationitem1_filetype = strdup ( pnd_pxml_get_associationitem1_filetype ( pxmlh ) );
+       //pnd_log ( PND_LOG_DEFAULT, "  Disco: Found file association request in PXML (%s)\n", p -> title_en );
+      }
+#endif
+      if ( pnd_pxml_get_execdashdashargs ( pxmlh ) ) {
+       p -> exec_dashdash_args = strdup ( pnd_pxml_get_execdashdashargs ( pxmlh ) );
+      }
 
       // look for any PXML overrides, if requested
       if ( disco_overrides ) {
@@ -366,8 +426,11 @@ static int pnd_disco_callback ( const char *fpath, const struct stat *sb,
        if ( ( v = pnd_conf_get_as_char ( ovrh, key ) ) ) {
          if ( p -> main_category1 ) {
            free ( p -> main_category1 );
+           p -> main_category1 = NULL;
+         }
+         if ( strcasecmp ( v, "NoSubcategory" ) != 0 ) {
+           p -> main_category1 = strdup ( v );
          }
-         p -> main_category1 = strdup ( v );
        }
 
       } // got ovr conf loaded?
@@ -389,7 +452,7 @@ static int pnd_disco_callback ( const char *fpath, const struct stat *sb,
   // free up the applist
   free ( pxmlapps );
 
-  return ( 0 ); // continue the tree walk
+  return ( FTW_CONTINUE ); // continue the tree walk
 }
 
 pnd_box_handle pnd_disco_search ( char *searchpath, char *overridespath ) {
@@ -410,7 +473,7 @@ pnd_box_handle pnd_disco_search ( char *searchpath, char *overridespath ) {
     nftw ( buffer,               // path to descend
           pnd_disco_callback,   // callback to do processing
           10,                   // no more than X open fd's at once
-          FTW_PHYS );           // do not follow symlinks
+          FTW_PHYS | FTW_ACTIONRETVAL );   // do not follow symlinks
 
   }
   SEARCHPATH_POST