tracker r2185 - in branches/indexer-split: . src/tracker-thumbnailer
- From: ifrade svn gnome org
- To: svn-commits-list gnome org
- Subject: tracker r2185 - in branches/indexer-split: . src/tracker-thumbnailer
- Date: Fri, 29 Aug 2008 12:02:23 +0000 (UTC)
Author: ifrade
Date: Fri Aug 29 12:02:23 2008
New Revision: 2185
URL: http://svn.gnome.org/viewvc/tracker?rev=2185&view=rev
Log:
Fixed crash with incorrect parameters, memory leaks and structure of code in thumbnailer
Modified:
branches/indexer-split/ChangeLog
branches/indexer-split/src/tracker-thumbnailer/tracker-thumbnailer.c
Modified: branches/indexer-split/src/tracker-thumbnailer/tracker-thumbnailer.c
==============================================================================
--- branches/indexer-split/src/tracker-thumbnailer/tracker-thumbnailer.c (original)
+++ branches/indexer-split/src/tracker-thumbnailer/tracker-thumbnailer.c Fri Aug 29 12:02:23 2008
@@ -42,111 +42,52 @@
#define LIBDIR "/usr/lib"
#endif
-static guint
+static gboolean
create_thumbnails_dir (const gchar * const subdir)
{
+
gchar *thumbnails_dir = NULL;
- thumbnails_dir = g_build_filename (g_get_home_dir(), ".thumbnails", NULL);
+ const gchar *home_dir;
+
+ home_dir = g_get_home_dir ();
+
+ thumbnails_dir = g_build_filename (home_dir, ".thumbnails", NULL);
/* Ensure that ~/.thumbnails is not a file if it exists */
if (g_file_test (thumbnails_dir, G_FILE_TEST_EXISTS) &&
!g_file_test (thumbnails_dir, G_FILE_TEST_IS_DIR)) {
g_printerr ("%s exists but is not a directory.\n", thumbnails_dir);
- goto error;
+ g_free (thumbnails_dir);
+ return FALSE;
}
g_free (thumbnails_dir);
- thumbnails_dir = g_build_filename (g_get_home_dir(), ".thumbnails", subdir, NULL);
+
+ thumbnails_dir = g_build_filename (home_dir, ".thumbnails", subdir, NULL);
+
if (g_mkdir_with_parents (thumbnails_dir, 00775) == -1) {
g_printerr ("failed: g_mkdir_with_parents (%s)\n", thumbnails_dir);
- goto error;
+ g_free (thumbnails_dir);
+ return FALSE;
}
g_free (thumbnails_dir);
- return 0;
+ return TRUE;
-error:
- g_free (thumbnails_dir);
- return -1;
}
-/* argv[1] == full path of file to be nailed
- * argv[2] == mime type of said file
- * argv[3] == requested size: "normal", "large", "preview"
- */
-
-int main (int argc, char *argv[])
+static gboolean
+valid_thumbnail_exists (const gchar *thumbnail_filename, const gchar *uri, const gchar *mtime)
{
- gchar *uri;
- gchar realname[MAXPATHLEN];
- struct stat stat_info;
- gchar *mtime;
- const gchar *md5_hash;
- int i;
- guint32 j;
- gchar *filename, *thumbnail_filename;
- FILE *fp;
- png_structp png_ptr;
- png_infop info_ptr;
- png_textp pngtext;
- int count, tests_passed;
- gchar *thumbnailer;
- gchar *args[5];
- png_uint_32 width, height;
- int bit_depth, color_type, interlace_method;
- int compression_method, filter_method;
- png_colorp palette;
- int num_palette;
- png_bytepp row_pointers;
- GChecksum *checksum;
-
- /* only make normal size thumbnails for now */
- if (strcmp (argv[3], "normal") != 0) {
- g_printerr ("Only normal sized thumbnails are supported\n");
- return EXIT_FAILURE;
- }
-
- if (create_thumbnails_dir (argv[3]) != 0)
- return EXIT_FAILURE;
-
- /* make sure the actual file exists */
- if (!g_file_test (argv[1], G_FILE_TEST_EXISTS)) {
- g_printerr ("%s does not exist\n", argv[1]);
- return EXIT_FAILURE;
- }
-
- /* g_filename_to_uri needs an absolute filename */
- if (!realpath (argv[1], realname)) {
- g_printerr("could not resolve absolute pathname for %s\n", argv[1]);
- return EXIT_FAILURE;
- }
-
- /* convert file name to URI */
- uri = g_filename_to_uri (realname, NULL, NULL);
+ FILE *fp;
+ png_structp png_ptr;
+ png_infop info_ptr;
+ gint i, count, tests_passed;
+ png_textp pngtext;
- /* get stat information on the file */
- if (g_stat (argv[1], &stat_info) == -1) {
- g_printerr ("stat () failed for %s\n", argv[1]);
- return EXIT_FAILURE;
- }
- mtime = g_strdup_printf ("%lu", stat_info.st_mtime);
-
- /* create path to thumbnail */
- checksum = g_checksum_new (G_CHECKSUM_MD5);
- g_checksum_update (checksum, (guchar *) uri, -1);
- md5_hash = g_checksum_get_string (checksum);
-
- filename = g_strdup_printf ("%s.png", md5_hash);
- g_checksum_free (checksum);
-
- thumbnail_filename = g_build_filename (
- g_get_home_dir (), ".thumbnails", argv[3], filename, NULL);
-
- g_free (filename);
-
- /* check to see if the thumbnail already exists */
if (g_file_test (thumbnail_filename, G_FILE_TEST_EXISTS)) {
- g_printerr ("%s exists\n", thumbnail_filename);
+
+ g_printerr ("%s exists ", thumbnail_filename);
/* thumbnail exists; but is it valid? */
g_assert ((fp = g_fopen (thumbnail_filename, "r")));
@@ -165,30 +106,45 @@
}
}
fclose (fp);
+
+ png_destroy_info_struct (png_ptr, &info_ptr);
+ png_destroy_read_struct (&png_ptr, NULL, NULL);
+
+
if (tests_passed == 2) {
- g_printerr ("Thumbnail valid\n");
- g_print ("%s\n", thumbnail_filename);
- return EXIT_SUCCESS;
+ g_printerr ("and it is valid\n");
+ return TRUE;
}
- g_printerr ("Not all tests passed. Recreating thumbnail...\n");
+ g_printerr ("but it is not valid. Recreating thumbnail...\n");
}
- /* thumbnail either doesn't exist or is invalid; contiue... */
+
+ return FALSE;
+}
+
+static gboolean
+generate_thumbnail (const gchar *filename, const gchar *thumbnail_filename, const gchar *mime, gint size)
+{
+
+ gchar *thumbnailer;
+ gchar *args[5];
+ gint i;
+ gboolean error = FALSE;
/* do we have a thumbnailer for this mime type? */
thumbnailer = g_strconcat (LIBDIR "/tracker/thumbnailers/",
- argv[2], "_thumbnailer", NULL);
+ mime, "_thumbnailer", NULL);
if (!g_file_test (thumbnailer, G_FILE_TEST_EXISTS)) {
- g_printerr ("%s not found\n", thumbnailer);
- return EXIT_FAILURE;
+ g_printerr ("Thumbnailer '%s' for mime %s not found\n", thumbnailer, mime);
+ g_free (thumbnailer);
+ return FALSE;
}
/* execute the thumbnailer */
- args[0] = thumbnailer;
- args[1] = g_filename_from_utf8 (argv[1], -1, NULL, NULL, NULL);
- args[2] = thumbnail_filename;
- if (strcmp (argv[3], "normal") == 0)
- args[3] = g_strdup ("128");
+ args[0] = g_strdup (thumbnailer);
+ args[1] = g_filename_from_utf8 (filename, -1, NULL, NULL, NULL);
+ args[2] = g_strdup (thumbnail_filename);
+ args[3] = g_strdup_printf ("%d", size);
args[4] = NULL;
if (!g_spawn_sync (NULL, args, NULL,
@@ -197,30 +153,49 @@
g_printerr ("%s failed to create %s\n", thumbnailer, thumbnail_filename);
g_remove (thumbnail_filename);
- return EXIT_FAILURE;
+ error = TRUE;
}
+ for (i = 0; i < 4; i++) {
+ g_free (args[i]);
+ }
+ g_free (thumbnailer);
+
+ return !error;
+}
+
+
+static gboolean
+ensure_correct_thumbnail (const gchar *uri, const gchar *thumbnail_filename, const gchar *mtime) {
+
+ FILE *fp;
+ png_structp png_ptr;
+ png_infop info_ptr;
+ png_textp pngtext;
+ png_uint_32 width, height;
+ gint bit_depth, color_type, interlace_method;
+ gint compression_method, filter_method;
+ png_colorp palette = NULL;
+ gint num_palette;
+ png_bytepp row_pointers;
+ guint i;
+
/* the fd.o spec requires us to set certain PNG keys. As far as I can
* see, libpng doesn't allow you to just set metadata, you have to do
* that when you create the file. Therefore, we need to copy the newly
* created thumbnail into a new one while setting the required attributes
- */
-
- /* read in the thumbnail into a buffer */
-
- if (!g_file_test (thumbnail_filename, G_FILE_TEST_EXISTS)) {
- return EXIT_FAILURE;
- }
-
- g_assert ((fp = g_fopen (thumbnail_filename, "r")));
+ */
+ g_assert ((fp = g_fopen (thumbnail_filename, "r")));
g_assert ((png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)));
g_assert ((info_ptr = png_create_info_struct (png_ptr)));
if (setjmp (png_jmpbuf (png_ptr))) {
g_printerr ("Error reading thumbnail\n");
- fclose (fp);
+ png_destroy_info_struct (png_ptr, &info_ptr);
+ png_destroy_read_struct (&png_ptr, NULL, NULL);
+ fclose (fp);
g_remove (thumbnail_filename);
- return EXIT_FAILURE;
+ return FALSE;
}
png_init_io (png_ptr, fp);
@@ -231,11 +206,14 @@
png_get_PLTE (png_ptr, info_ptr, &palette, &num_palette);
row_pointers = g_new (png_bytep, height);
- for (j = 0; j < height; j++) {
- row_pointers[j] = (png_bytep) malloc (png_get_rowbytes (png_ptr, info_ptr));
+ for (i = 0; i < height; i++) {
+ row_pointers[i] = (png_bytep) g_malloc0 (png_get_rowbytes (png_ptr, info_ptr));
}
png_read_image (png_ptr, row_pointers);
png_read_end (png_ptr, NULL);
+
+ png_destroy_info_struct (png_ptr, &info_ptr);
+ png_destroy_read_struct (&png_ptr, NULL, NULL);
fclose (fp);
/* write the new thumbnail (overwrites the old) */
@@ -245,40 +223,165 @@
if (setjmp (png_jmpbuf (png_ptr))) {
g_printerr ("Error creating thumbnail\n");
- fclose (fp);
- g_remove (thumbnail_filename);
+ } else {
+
+ png_init_io (png_ptr, fp);
+
+ png_set_IHDR (png_ptr, info_ptr, width, height, bit_depth,
+ color_type, interlace_method, compression_method, filter_method);
+
+ if (palette && num_palette > 0)
+ png_set_PLTE (png_ptr, info_ptr, palette, num_palette);
+
+ /* set the required fields */
+ pngtext = g_new0 (png_text, 3);
+ pngtext[0].key = "Thumb::URI";
+ pngtext[0].text = g_strdup (uri);
+ pngtext[0].text_length = strlen (uri);
+ pngtext[0].compression = PNG_TEXT_COMPRESSION_NONE;
+ pngtext[1].key = "Thumb::MTime";
+ pngtext[1].text = g_strdup (mtime);
+ pngtext[1].text_length = strlen (mtime);
+ pngtext[1].compression = PNG_TEXT_COMPRESSION_NONE;
+ /* set some optional fields */
+ pngtext[2].key = "Software";
+ pngtext[2].text = "Tracker thumbnail factory";
+ pngtext[2].compression = PNG_TEXT_COMPRESSION_NONE;
+ png_set_text(png_ptr, info_ptr, pngtext, 3);
+
+ png_write_info (png_ptr, info_ptr);
+ png_write_image (png_ptr, row_pointers);
+ png_write_end (png_ptr, info_ptr);
+
+ g_free (pngtext[0].text);
+ g_free (pngtext[1].text);
+ g_free (pngtext);
+ }
+ fclose (fp);
+
+ for (i = 0; i < height; i++) {
+ g_free (row_pointers[i]);
+ }
+
+ g_free (row_pointers);
+
+ png_destroy_info_struct (png_ptr, &info_ptr);
+ png_destroy_write_struct (&png_ptr, NULL);
+
+ return TRUE;
+}
+
+static gboolean
+validate_args (gint argc, gchar **argv)
+{
+ if (argc < 4) {
+ return FALSE;
+ }
+
+ if (!strcmp (argv[3], "normal")
+ || !strcmp (argv[3], "large")
+ || !strcmp (argv[3], "preview")) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/* argv[1] == full path of file to be nailed
+ * argv[2] == mime type of said file
+ * argv[3] == requested size: "normal", "large", "preview"
+ */
+
+gint
+main (gint argc, gchar *argv[])
+{
+ gchar *uri;
+ gchar realname[MAXPATHLEN];
+ struct stat stat_info;
+ gchar *mtime;
+ gchar *uri_hash;
+ GChecksum *checksum;
+ gchar *thumbnail_filename;
+
+ if (!validate_args (argc, argv)) {
+ g_printerr ("Usage: ./tracker-thumbnailer filename mimetype [normal|large|preview]\n");
+ return EXIT_FAILURE;
+ }
+
+ /* only make normal size thumbnails for now */
+ if (strcmp (argv[3], "normal") != 0) {
+ g_printerr ("Only normal sized thumbnails are supported\n");
return EXIT_FAILURE;
}
- png_init_io (png_ptr, fp);
+ if (!create_thumbnails_dir (argv[3]))
+ return EXIT_FAILURE;
- png_set_IHDR (png_ptr, info_ptr, width, height, bit_depth, color_type, interlace_method, compression_method, filter_method);
+ /* make sure the actual file exists */
+ if (!g_file_test (argv[1], G_FILE_TEST_EXISTS)) {
+ g_printerr ("File '%s' does not exist\n", argv[1]);
+ return EXIT_FAILURE;
+ }
- if (palette && num_palette > 0)
- png_set_PLTE (png_ptr, info_ptr, palette, num_palette);
+ /* g_filename_to_uri needs an absolute filename */
+ if (!realpath (argv[1], realname)) {
+ g_printerr("could not resolve absolute pathname for %s\n", argv[1]);
+ return EXIT_FAILURE;
+ }
- /* set the required fields */
- pngtext = g_new0 (png_text, 3);
- pngtext[0].key = "Thumb::URI";
- pngtext[0].text = uri;
- pngtext[0].text_length = strlen (uri);
- pngtext[0].compression = PNG_TEXT_COMPRESSION_NONE;
- pngtext[1].key = "Thumb::MTime";
- pngtext[1].text = mtime;
- pngtext[1].text_length = strlen (mtime);
- pngtext[1].compression = PNG_TEXT_COMPRESSION_NONE;
- /* set some optional fields */
- pngtext[2].key = "Software";
- pngtext[2].text = "Tracker thumbnail factory";
- pngtext[2].compression = PNG_TEXT_COMPRESSION_NONE;
- png_set_text(png_ptr, info_ptr, pngtext, 3);
-
- png_write_info (png_ptr, info_ptr);
- png_write_image (png_ptr, row_pointers);
- png_write_end (png_ptr, info_ptr);
- fclose (fp);
+ /* convert file name to URI */
+ uri = g_filename_to_uri (realname, NULL, NULL);
+
+
+ /* create path to thumbnail */
+ checksum = g_checksum_new (G_CHECKSUM_MD5);
+ g_checksum_update (checksum, (guchar *)uri, strlen (uri));
+ uri_hash = g_strconcat (g_checksum_get_string (checksum), ".png", NULL);
+ g_checksum_free (checksum);
+
+
+ thumbnail_filename = g_build_filename (g_get_home_dir (), ".thumbnails", argv[3], uri_hash, NULL);
+ g_free (uri_hash);
+
+ /* get stat information on the file */
+ if (g_stat (argv[1], &stat_info) == -1) {
+ g_printerr ("stat () failed for %s\n", argv[1]);
+ g_free (thumbnail_filename);
+ g_free (uri);
+ return EXIT_FAILURE;
+ }
+ mtime = g_strdup_printf ("%lu", stat_info.st_mtime);
+
+ /* check to see if the thumbnail already exists */
+ if (valid_thumbnail_exists (thumbnail_filename, uri, mtime)) {
+ g_print ("%s\n", thumbnail_filename);
+ g_free (mtime);
+ g_free (thumbnail_filename);
+ g_free (uri);
+ return EXIT_SUCCESS;
+ }
+
+ if (!generate_thumbnail (uri, thumbnail_filename, argv[2], 128)) {
+ g_free (mtime);
+ g_free (thumbnail_filename);
+ g_free (uri);
+ return EXIT_FAILURE;
+ }
+
+ if (g_file_test (thumbnail_filename, G_FILE_TEST_EXISTS)) {
+ ensure_correct_thumbnail (uri, thumbnail_filename, mtime);
+ } else {
+ g_free (mtime);
+ g_free (thumbnail_filename);
+ g_free (uri);
+ return EXIT_FAILURE;
+ }
/* if we get here, everything must have succeeded */
g_print ("%s\n", thumbnail_filename);
+ g_free (thumbnail_filename);
+ g_free (uri);
+ g_free (mtime);
return EXIT_SUCCESS;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]