Patch from Cloudef to add very basic support for 'package' PXML tags
[pandora-libraries.git] / lib / pnd_discovery.c
index 074513d..7d89475 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,9 +28,10 @@ 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 -> unique_id ) {      free ( p -> unique_id );   }
+  if ( p -> appdata_dirname ) { free ( p -> appdata_dirname );   }
   if ( p -> icon )     {       free ( p -> icon );        }
   if ( p -> exec )     {       free ( p -> exec );        }
   if ( p -> execargs ) {       free ( p -> execargs );    }
@@ -69,7 +71,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
@@ -85,7 +90,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
@@ -113,13 +118,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 );
@@ -128,18 +133,21 @@ static int pnd_disco_callback ( const char *fpath, const struct stat *sb,
 #if 1 // icon
     // for convenience, lets skip along past trailing newlines/CR's in hopes of finding icon data?
     {
-      unsigned int pos = ftell ( f );
       char pngbuffer [ 16 ]; // \211 P N G \r \n \032 \n
       pngbuffer [ 0 ] = 137;      pngbuffer [ 1 ] = 80;      pngbuffer [ 2 ] = 78;      pngbuffer [ 3 ] = 71;
       pngbuffer [ 4 ] = 13;       pngbuffer [ 5 ] = 10;       pngbuffer [ 6 ] = 26;      pngbuffer [ 7 ] = 10;
 
-      unsigned char padtests = 10;
+      unsigned char padtests = 20;
       unsigned int padstart = ftell ( f );
+
+      // seek back 10 (should be back into the /PXML> part) to catch any appending-icon-no-line-endings funny business
+      fseek ( f, -10, SEEK_CUR );
+
       while ( padtests ) {
 
        if ( fread ( pngbuffer + 8, 8, 1, f ) == 1 ) {
          if ( memcmp ( pngbuffer, pngbuffer + 8, 8 ) == 0 ) {
-           pxml_close_pos = pos;
+           pxml_close_pos = ftell ( f ) - 8;
            break;
          } // if
          fseek ( f, -7, SEEK_CUR ); // seek back 7 (so we're 1 further than we started, since PNG header is 8b)
@@ -166,7 +174,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
@@ -216,6 +224,9 @@ static int pnd_disco_callback ( const char *fpath, const struct stat *sb,
       p -> object_type = valid;
 
       // PXML fields
+      if ( pnd_pxml_get_package_id ( pxmlh ) ) {
+       p -> package_id = strdup ( pnd_pxml_get_package_id ( pxmlh ) );
+      }
       if ( pnd_pxml_get_app_name_en ( pxmlh ) ) {
        p -> title_en = strdup ( pnd_pxml_get_app_name_en ( pxmlh ) );
       }
@@ -237,6 +248,9 @@ static int pnd_disco_callback ( const char *fpath, const struct stat *sb,
       if ( pnd_pxml_get_unique_id ( pxmlh ) ) {
        p -> unique_id = strdup ( pnd_pxml_get_unique_id ( pxmlh ) );
       }
+      if ( pnd_pxml_get_appdata_dirname ( pxmlh ) ) {
+       p -> appdata_dirname = strdup ( pnd_pxml_get_appdata_dirname ( pxmlh ) );
+      }
       if ( pnd_pxml_get_clockspeed ( pxmlh ) ) {
        p -> clockspeed = strdup ( pnd_pxml_get_clockspeed ( pxmlh ) ); 
       }
@@ -338,6 +352,15 @@ static int pnd_disco_callback ( const char *fpath, const struct stat *sb,
          p -> clockspeed = strdup ( v );
        }
 
+       // appdata dirname
+       snprintf ( key, 100, "Application-%u.appdata", p -> subapp_number );
+       if ( ( v = pnd_conf_get_as_char ( ovrh, key ) ) ) {
+         if ( p -> appdata_dirname ) {
+           free ( p -> appdata_dirname );
+         }
+         p -> appdata_dirname = strdup ( v );
+       }
+
        // categories
        snprintf ( key, 100, "Application-%u.maincategory", p -> subapp_number );
        if ( ( v = pnd_conf_get_as_char ( ovrh, key ) ) ) {
@@ -350,8 +373,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?
@@ -373,7 +399,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 ) {
@@ -394,7 +420,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
@@ -407,3 +433,34 @@ pnd_box_handle pnd_disco_search ( char *searchpath, char *overridespath ) {
 
   return ( disco_box );
 }
+
+pnd_box_handle pnd_disco_file ( char *path, char *filename ) {
+  struct stat statbuf;
+
+  // set up container
+  disco_overrides = NULL;
+  disco_box = pnd_box_new ( "discovery" );
+
+  // path
+  char fullpath [ PATH_MAX ];
+  sprintf ( fullpath, "%s/%s", path, filename );
+
+  // fake it
+  if ( stat ( fullpath, &statbuf ) < 0 ) {
+    return ( 0 );
+  }
+
+  struct FTW ftw;
+  ftw.base = strlen ( path );
+  ftw.level = 0;
+
+  pnd_disco_callback ( fullpath, &statbuf, FTW_F, &ftw );
+
+  // return whatever we found, or NULL if nada
+  if ( ! pnd_box_get_head ( disco_box ) ) {
+    pnd_box_delete ( disco_box );
+    disco_box = NULL;
+  }
+
+  return ( disco_box );
+}