Added basic icon support
authorskeezix <skeezix@flotsam-vm.(none)>
Tue, 24 Feb 2009 02:25:52 +0000 (21:25 -0500)
committerskeezix <skeezix@flotsam-vm.(none)>
Tue, 24 Feb 2009 02:25:52 +0000 (21:25 -0500)
discotest has it, not yet pndnotifyd
discotest can extract icon from pnd to /tmp
Almost there!

Makefile
include/pnd_discovery.h
lib/pnd_discovery.c
test/discotest.c
testdata/pndsample/x86_echo.pnd
testdata/pndsample/x86_ls.pnd

index f1b169e..e883136 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -65,6 +65,7 @@ deploy:
        cp bin/pndnotifyd deployment/usr/bin
        cp testdata/scripts/* deployment/usr/pandora/scripts
        # copy in freebee .pnd apps to /usr/pandora/apps
+       # add pndnotify to etc/rc/startup-whatever
 
 # test tool targets
 #
index 59029dd..b92215e 100644 (file)
@@ -31,12 +31,21 @@ pnd_box_handle pnd_disco_search ( char *searchpath, char *overridespath );
  * confusion.. it is not displayed. So no big deal.
  */
 
+typedef enum {
+  pnd_object_type_unknown = 0,
+  pnd_object_type_directory,
+  pnd_object_type_pnd,
+  pnd_object_type_max
+} pnd_object_type_t;
+
 // another struct? Have always intended discovery_t to have minimal members.. just enough to lead to an
 // application (PXML, xecutable, name); if the apps want more details, they can use the pnd_pxml code to
 // fetch the full PXML and get all the details. But I think we got out of control here :)
 typedef struct {
   // base
-  char *path_to_object; // full path to the PXML.xml or awesomeapp.pnd file
+  unsigned char object_type;   // see enum above
+  char *path_to_object;        // full path to the PXML.xml or awesomeapp.pnd file
+  unsigned int pnd_icon_pos;   // offset to the byte after end of PXML in a pnd file (should be icon if present)
   // strdup'd from PXML
   char *title_en;
   char *unique_id;
@@ -53,6 +62,10 @@ void pnd_disco_destroy ( pnd_disco_t *p ); // a function name that simply could
 // TODO: Copy the icon into this directory as well, if its source is a .pnd or info is in the dico struct
 unsigned char pnd_emit_dotdesktop ( char *targetpath, char *pndrun, pnd_disco_t *p );
 
+// emit_icon() will attempt to copy the icon from a PXML directory, or from a pnd file if appended,
+// to the given directory; returns 1 on sucess, otherwise is a fail.
+unsigned char pnd_emit_icon ( char *targetpath, pnd_disco_t *p );
+
 // TODO: A way to release the disco-lists and reclaim RAM :)
 
 #ifdef __cplusplus
index 84de948..3ddecb4 100644 (file)
@@ -52,8 +52,9 @@ void pnd_disco_destroy ( pnd_disco_t *p ) {
 static int pnd_disco_callback ( const char *fpath, const struct stat *sb,
                                int typeflag, struct FTW *ftwbuf )
 {
-  unsigned char valid = 0; // 1 for plaintext PXML, 2 for PND...
+  unsigned char valid = pnd_object_type_unknown;
   pnd_pxml_handle pxmlh = 0;
+  unsigned int pxml_close_pos = 0;
 
   //printf ( "disco root callback encountered '%s'\n", fpath );
 
@@ -66,9 +67,9 @@ static int pnd_disco_callback ( const char *fpath, const struct stat *sb,
   // PND/PNZ file and others may be valid as well .. but lets leave that for now
   //   printf ( "%s %s\n", fpath + ftwbuf -> base, PND_PACKAGE_FILEEXT );
   if ( strcasecmp ( fpath + ftwbuf -> base, PXML_FILENAME ) == 0 ) {
-    valid = 1;
+    valid = pnd_object_type_directory;
   } else if ( strcasestr ( fpath + ftwbuf -> base, PND_PACKAGE_FILEEXT "\0" ) ) {
-    valid = 2;
+    valid = pnd_object_type_pnd;
   }
 
   // if not a file of interest, just keep looking until we run out
@@ -78,14 +79,14 @@ static int pnd_disco_callback ( const char *fpath, const struct stat *sb,
   }
 
   // potentially a valid application
-  if ( valid == 1 ) {
+  if ( valid == pnd_object_type_directory ) {
     // Plaintext PXML file
     //printf ( "PXML: disco callback encountered '%s'\n", fpath );
 
     // pick up the PXML if we can
     pxmlh = pnd_pxml_fetch ( (char*) fpath );
 
-  } else if ( valid == 2 ) {
+  } else if ( valid == pnd_object_type_pnd ) {
     // PND ... ??
     FILE *f;
     char pxmlbuf [ 32 * 1024 ]; // TBD: assuming 32k pxml accrual buffer is a little lame
@@ -114,9 +115,27 @@ static int pnd_disco_callback ( const char *fpath, const struct stat *sb,
     //printf ( "buffer is %s\n", pxmlbuf );
     //fflush ( stdout );
 
+#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;
+      if ( fread ( pngbuffer + 8, 8, 1, f ) == 1 ) {
+       if ( memcmp ( pngbuffer, pngbuffer + 8, 8 ) == 0 ) {
+         pxml_close_pos = pos;
+       }
+      }
+    } // icon
+#endif
+
     // by now, we have <PXML> .. </PXML>, try to parse..
     pxmlh = pnd_pxml_fetch_buffer ( (char*) fpath, pxmlbuf );
 
+    // done with file
+    fclose ( f );
+
   }
 
   // pxmlh is useful?
@@ -134,11 +153,16 @@ static int pnd_disco_callback ( const char *fpath, const struct stat *sb,
 
       // base path
       p -> path_to_object = strdup ( fpath );
-
       if ( ( fixpxml = strcasestr ( p -> path_to_object, PXML_FILENAME ) ) ) {
        *fixpxml = '\0'; // if this is not a .pnd, lop off the PXML.xml at the end
       }
 
+      // png icon path
+      p -> pnd_icon_pos = pxml_close_pos;
+
+      // type
+      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 ) );
@@ -278,3 +302,79 @@ unsigned char pnd_emit_dotdesktop ( char *targetpath, char *pndrun, pnd_disco_t
 
   return ( 1 );
 }
+
+unsigned char pnd_emit_icon ( char *targetpath, pnd_disco_t *p ) {
+  char buffer [ FILENAME_MAX ];
+  char bits [ 8 * 1024 ];
+  unsigned int bitlen;
+
+  // filename
+  sprintf ( buffer, "%s/%u.png", targetpath, p -> unique_id );
+
+  // first.. are we looking through a pnd file or a dir?
+  if ( p -> object_type == pnd_object_type_directory ) {
+    // if we can find icon, copy it in from directory to destination
+
+  } else if ( p -> object_type == pnd_object_type_pnd ) {
+    // if we can get it from pnd file, copy it into destination
+
+    if ( ! p -> pnd_icon_pos ) {
+      return ( 0 ); // discover code didn't find it, so FAIL
+    }
+
+    FILE *pnd, *target;
+    unsigned int len;
+
+    pnd = fopen ( p -> path_to_object, "r" );
+
+    if ( ! pnd ) {
+      return ( 0 );
+    }
+
+    target = fopen ( buffer, "wb" );
+
+    if ( ! target ) {
+      fclose ( pnd );
+      return ( 0 );
+    }
+
+    fseek ( pnd, 0, SEEK_END );
+    len = ftell ( pnd );
+    //fseek ( pnd, 0, SEEK_SET );
+
+    fseek ( pnd, p -> pnd_icon_pos, SEEK_SET );
+
+    len -= p -> pnd_icon_pos;
+
+    while ( len ) {
+
+      if ( len > (8*1024) ) {
+       bitlen = (8*1024);
+      } else {
+       bitlen = len;
+      }
+
+      if ( fread ( bits, bitlen, 1, pnd ) != 1 ) {
+       fclose ( pnd );
+       fclose ( target );
+       unlink ( buffer );
+       return ( 0 );
+      }
+
+      if ( fwrite ( bits, bitlen, 1, target ) != 1 ) {
+       fclose ( pnd );
+       fclose ( target );
+       unlink ( buffer );
+       return ( 0 );
+      }
+
+      len -= bitlen;
+    } // while
+
+    fclose ( pnd );
+    fclose ( target );
+
+  }
+
+  return ( 1 );
+}
index a299e7d..b374f36 100644 (file)
@@ -9,10 +9,35 @@
 #include "pnd_discovery.h"
 #include "pnd_locate.h"
 
-int main ( void) {
+int main ( int argc, char *argv[] ) {
   char *configpath;
   char *appspath;
   char *overridespath;
+  unsigned char i;
+  unsigned char do_exec = 0;
+  unsigned char do_icon = 0;
+  unsigned char do_dotdesktop = 0;
+
+  for ( i = 1; i < argc; i++ ) {
+
+    if ( argv [ i ][ 0 ] == '-' && argv [ i ][ 1 ] == 'e' ) {
+      printf ( "Will attempt a random exec.\n" );
+      do_exec = 1;
+    } else if ( argv [ i ][ 0 ] == '-' && argv [ i ][ 1 ] == 'i' ) {
+      printf ( "Will attempt to extract icons.\n" );
+      do_icon = 1;
+    } else if ( argv [ i ][ 0 ] == '-' && argv [ i ][ 1 ] == 'd' ) {
+      printf ( "Will attempt to extract dotdesktop.\n" );
+      do_dotdesktop = 1;
+    } else {
+      printf ( "%s [-e] [-i] [-d]\n", argv [ 0 ] );
+      printf ( "-e\tOptional. Attempt to exec a random app.\n" );
+      printf ( "-i\tOptional. Attempt to dump icon files from the end of pnd's to /tmp.\n" );
+      printf ( "-d\tOptional. Attempt to dump dotdesktop files from the end of pnd's to /tmp.\n" );
+      exit ( 0 );
+    }
+
+  }
 
   /* attempt to sort out the config file madness
    */
@@ -47,6 +72,36 @@ int main ( void) {
   printf ( "Apps searchpath is '%s'\n", appspath );
   printf ( "Apps overrides searchpath is '%s'\n", overridespath );
 
+  /* find pnd runscript
+   */
+  char *run_searchpath;
+  char *run_script;
+  char *pndrun;
+
+  if ( apph ) {
+    run_searchpath = pnd_conf_get_as_char ( apph, PND_PNDRUN_SEARCHPATH_KEY );
+    run_script = pnd_conf_get_as_char ( apph, PND_PNDRUN_KEY );
+    pndrun = NULL;
+
+    if ( ! run_searchpath ) {
+      run_searchpath = PND_APPS_SEARCHPATH;
+      run_script = PND_PNDRUN_FILENAME;
+    }
+
+  } else {
+    run_searchpath = NULL;
+    run_script = NULL;
+    pndrun = PND_PNDRUN_DEFAULT;
+  }
+
+  if ( ! pndrun ) {
+    pndrun = pnd_locate_filename ( run_searchpath, run_script );
+  }
+
+  if ( run_searchpath ) printf ( "Locating pnd run in %s\n", run_searchpath );
+  if ( run_script ) printf ( "Locating pnd runscript as %s\n", run_script );
+  if ( pndrun ) printf ( "Default pndrun is %s\n", pndrun );
+
   /* attempt to discover apps in the path
    */
   pnd_box_handle applist;
@@ -62,7 +117,7 @@ int main ( void) {
 
       // display the app 'as is'
 
-      printf ( "App: %s\n", pnd_box_get_key ( d ) );
+      printf ( "App: %s (type %u)\n", pnd_box_get_key ( d ), d -> object_type );
 
       printf ( "  Base path: %s\n", d -> path_to_object );
 
@@ -72,6 +127,9 @@ int main ( void) {
       if ( d -> icon ) {
        printf ( "  Icon: %s\n", d -> icon );
       }
+      if ( d -> pnd_icon_pos ) {
+       printf ( "  Icon in pnd might be at: %u\n", d -> pnd_icon_pos );
+      }
       if ( d -> unique_id ) {
        printf ( "  Unique ID: %s\n", d -> unique_id );
       }
@@ -88,7 +146,13 @@ int main ( void) {
        printf ( "  Clockspeed: %s\n", d -> clockspeed );
       }
 
-      //pnd_emit_dotdesktop ( "/tmp", d );
+      if ( do_dotdesktop ) {
+       pnd_emit_dotdesktop ( "/tmp", pndrun, d );
+      }
+
+      if ( do_icon ) {
+       pnd_emit_icon ( "/tmp", d );
+      }
 
       // next!
       d = pnd_box_get_next ( d );
@@ -100,49 +164,25 @@ int main ( void) {
   }
 
   // lets toy with executing an application
-  char *run_searchpath;
-  char *run_script;
-  char *pndrun;
-
-  if ( apph ) {
-    run_searchpath = pnd_conf_get_as_char ( apph, PND_PNDRUN_SEARCHPATH_KEY );
-    run_script = pnd_conf_get_as_char ( apph, PND_PNDRUN_KEY );
-    pndrun = NULL;
-
-    if ( ! run_searchpath ) {
-      run_searchpath = PND_APPS_SEARCHPATH;
-      run_script = PND_PNDRUN_FILENAME;
-    }
+  if ( do_exec ) {
 
-  } else {
-    run_searchpath = NULL;
-    run_script = NULL;
-    pndrun = PND_PNDRUN_DEFAULT;
-  }
-
-  if ( ! pndrun ) {
-    pndrun = pnd_locate_filename ( run_searchpath, run_script );
-  }
-
-  if ( run_searchpath ) printf ( "Locating pnd run in %s\n", run_searchpath );
-  if ( run_script ) printf ( "Locating pnd runscript as %s\n", run_script );
-  if ( pndrun ) printf ( "Default pndrun is %s\n", pndrun );
-
-  if ( ! pndrun ) {
-    printf ( "*** Couldn't locate a pnd runscript.\n" );
-  } else {
-    printf ( "Found a pnd runscript of %s\n", pndrun );
-
-    pnd_disco_t *d = pnd_box_get_head ( applist );
-    if ( d ) {
-      d = pnd_box_get_next ( d );
+    if ( ! pndrun ) {
+      printf ( "*** Couldn't locate a pnd runscript.\n" );
+    } else {
+      printf ( "Found a pnd runscript of %s\n", pndrun );
 
+      pnd_disco_t *d = pnd_box_get_head ( applist );
       if ( d ) {
-       pnd_apps_exec ( pndrun, d -> path_to_object, d -> unique_id, d -> exec, d -> startdir, atoi ( d -> clockspeed ) );
+       d = pnd_box_get_next ( d );
+
+       if ( d ) {
+         pnd_apps_exec ( pndrun, d -> path_to_object, d -> unique_id, d -> exec, d -> startdir, atoi ( d -> clockspeed ) );
+       }
       }
+
     }
 
-  }
+  } // do_exec?
 
   // exeunt with alarums
   free ( configpath );
index a5ff2db..00d9ead 100644 (file)
Binary files a/testdata/pndsample/x86_echo.pnd and b/testdata/pndsample/x86_echo.pnd differ
index dfea9e6..9e36a1d 100644 (file)
Binary files a/testdata/pndsample/x86_ls.pnd and b/testdata/pndsample/x86_ls.pnd differ