Index: libgthumb/bookmarks.c
===================================================================
--- libgthumb/bookmarks.c	(revision 2400)
+++ libgthumb/bookmarks.c	(working copy)
@@ -393,7 +393,7 @@
 	scan = bookmarks->list;
 	while (((bookmarks->max_lines < 0) || (lines < bookmarks->max_lines))
 	       && (scan != NULL)) {
-		gfile_output_stream_write_line (ostream, error, "\"%s\"", scan->data);
+		gfile_output_stream_write_line (ostream, &error, "\"%s\"", scan->data);
 
 	        if (error) {
 	                gfile_warning ("Cannot write line to bookmark file",
Index: libgthumb/gfile-utils.c
===================================================================
--- libgthumb/gfile-utils.c	(revision 2400)
+++ libgthumb/gfile-utils.c	(working copy)
@@ -21,10 +21,14 @@
  */
 
 
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <glib.h>
 
+#include "preferences.h"
+#include "glib-utils.h"
+#include "gconf-utils.h"
 #include "gfile-utils.h"
 
 
@@ -94,11 +98,11 @@
 	uri = gfile_get_uri (file);
 	
 	if (err == NULL)
-		warning = g_strdup_printf ("%s: file %s\n", msg, uri);
+		warning = g_strdup_printf ("%s: file %s", msg, uri);
 	else
-		warning = g_strdup_printf ("%s: file %s: %s\n", msg, uri, err->message);
+		warning = g_strdup_printf ("%s: file %s: %s", msg, uri, err->message);
 	
-	g_warning (warning);
+	g_warning ("%s\n", warning);
 	
         g_free (uri);
         g_free (warning);
@@ -199,6 +203,132 @@
 }
 
 
+/* Be careful: result must be g_free'd  */
+char *
+gfile_get_filename_extension (GFile *file)
+{
+	char *basename;
+	char *last_dot;
+	char *extension;
+
+	basename = g_file_get_basename (file);
+	
+	g_assert (basename != NULL);
+	
+	last_dot = strrchr (basename, '.');
+	if (last_dot == NULL)
+		return NULL;
+
+	extension = g_strdup (last_dot + 1);
+	
+	g_free (basename);
+	
+	return extension;
+}
+
+
+const char*
+gfile_get_file_mime_type (GFile      *file,
+                          gboolean    fast_file_type)
+{
+	const char *value;
+	const char *result = NULL;
+	GFileInfo  *info;
+	GError     *error = NULL;
+ 
+	g_assert (file != NULL);
+	
+	info = g_file_query_info (file,
+				  fast_file_type ?
+				  G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE :
+				  G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
+				  G_FILE_QUERY_INFO_NONE, 
+				  NULL, 
+				  &error);
+        if (info != NULL) {
+        	if (fast_file_type)
+        		value = g_file_info_get_attribute_string (info, 
+        				                          G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE);
+        	else
+        		value = g_file_info_get_content_type (info);
+        	
+		/* 
+		 * If the file content is determined to be binary data (octet-stream), check for 
+		 * HDR file types, which are not well represented in the freedesktop mime database 
+		 * currently. This section can be purged when they are. This is an unpleasant hack. 
+		 * Some file extensions may be missing here; please file a bug if they are. 
+		 */
+		if (strcmp (value, "application/octet-stream") == 0) {
+	
+			char* extension;
+			
+			extension = gfile_get_filename_extension (file);
+			
+			if (extension != NULL) {
+				if (   !strcasecmp (extension, "exr")	/* OpenEXR format */
+				    || !strcasecmp (extension, "hdr")	/* Radiance rgbe */
+				    || !strcasecmp (extension, "pic"))	/* Radiance rgbe */
+					value = "image/x-hdr";
+				
+				g_free (extension);
+			}
+		}
+        	
+
+        	result = get_static_string  (value);
+        }
+        else {
+                gfile_warning ("Could not get content type", file, error);
+                g_clear_error (&error);
+        }
+
+        g_object_unref (info);
+	
+	return result;
+}
+
+
+static gboolean
+_gfile_image_is_type (GFile      *file,
+	              const char *mime_type,
+	              gboolean    fast_file_type)
+{
+	const char *result;
+	
+	result = gfile_get_file_mime_type (file, fast_file_type);
+	
+	if (result == NULL)
+		return FALSE;
+	
+	return (strcmp (result, mime_type) == 0);
+}
+
+
+static gboolean
+_gfile_image_is_type__gconf_file_type (GFile      *file,
+			               const char *mime_type)
+{
+	return _gfile_image_is_type (file, 
+				     mime_type, 
+				     ! gfile_is_local (file) 
+			             || eel_gconf_get_boolean (PREF_FAST_FILE_TYPE, TRUE));
+}
+
+
+gboolean
+gfile_image_is_jpeg (GFile *file)
+{
+	return _gfile_image_is_type__gconf_file_type (file, "image/jpeg");
+}
+
+
+gboolean
+gfile_image_is_gif (GFile *file)
+{
+	return _gfile_image_is_type__gconf_file_type (file, "image/gif");
+}
+
+
 static gboolean
 gfile_is_filetype (GFile      *file,
 		   GFileType   file_type)
@@ -212,7 +342,7 @@
 
 	info = g_file_query_info (file, 
 			          G_FILE_ATTRIBUTE_STANDARD_TYPE, 
-			          0, 
+			          G_FILE_QUERY_INFO_NONE, 
 			          NULL, 
 			          &error);
 	if (error == NULL) {
@@ -250,11 +380,15 @@
 	goffset    size = 0;
 	GError    *err = NULL;
 
-	//FIXME: shouldn't we get rid of this test and fix the callers instead
+	//FIXME: shouldn't we get rid of this test and fix the callers instead?
 	if (file == NULL)
 		return 0;
 	
-        info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_SIZE, 0, NULL, &err);
+        info = g_file_query_info (file, 
+        		          G_FILE_ATTRIBUTE_STANDARD_SIZE, 
+        		          G_FILE_QUERY_INFO_NONE, 
+        		          NULL, 
+        		          &err);
         if (err == NULL) {
                 size = g_file_info_get_size (info);
         }
@@ -272,7 +406,7 @@
 /* Directory utils */
 
 static gboolean
-make_directory_tree (GFile    *dir,
+_gfile_make_directory_tree (GFile    *dir,
 		     mode_t    mode,
 		     GError  **error)
 {
@@ -281,7 +415,7 @@
 
 	parent = g_file_get_parent (dir);
 	if (parent != NULL) {
-		success = make_directory_tree (parent, mode, error);
+		success = _gfile_make_directory_tree (parent, mode, error);
 		g_object_unref (parent);
 		if (! success)
 			return FALSE;
@@ -312,14 +446,14 @@
 {
 	GError *priv_error = NULL;
 
-	//FIXME: shouldn't we get rid of this test and fix the callers instead
+	//FIXME: shouldn't we get rid of this test and fix the callers instead?
 	if (dir == NULL)
 		return FALSE;
 
 	if (error == NULL)
 		error = &priv_error;
 
-	if (! make_directory_tree (dir, mode, error)) {
+	if (! _gfile_make_directory_tree (dir, mode, error)) {
 		
 		gfile_warning ("could not create directory", dir, *error);
 		if (priv_error != NULL)
@@ -384,7 +518,7 @@
 #define MAX_TEMP_FOLDER_TO_TRY  2
 
 static GFile *
-ith_temp_folder_to_try (int n)
+_gfile_ith_temp_folder_to_try (int n)
 {
 	GFile *dir = NULL;
 	
@@ -436,7 +570,7 @@
 		GFile    *folder;
 		guint64   size;
 
-		folder = ith_temp_folder_to_try (i);
+		folder = _gfile_ith_temp_folder_to_try (i);
 		size = gfile_get_destination_free_space (folder);
 		if (max_size < size) {
 			max_size = size;
@@ -464,8 +598,8 @@
 
 
 static gboolean
-delete_directory_recursive (GFile   *dir,
-			    GError **error)
+_gfile_delete_directory_recursive (GFile   *dir,
+			           GError **error)
 {
 	GFileEnumerator *file_enum;
 	GFileInfo       *info;
@@ -486,7 +620,7 @@
 
 		switch (g_file_info_get_file_type (info)) {
 		case G_FILE_TYPE_DIRECTORY:
-			if (! delete_directory_recursive (child, error))
+			if (! _gfile_delete_directory_recursive (child, error))
 				error_occurred = TRUE;
 			break;
 		default:
@@ -514,7 +648,7 @@
 	gboolean   result;
 	GError    *error = NULL;
 
-	result = delete_directory_recursive (dir, &error);
+	result = _gfile_delete_directory_recursive (dir, &error);
 	if (! result) {
 		gfile_warning ("Cannot delete directory", dir, error);
 		g_clear_error (&error);
@@ -526,14 +660,13 @@
 
 /* Xfer */
 
-
-/* empty functions */
 static void _empty_file_progress_cb  (goffset current_num_bytes,
 				      goffset total_num_bytes,
 				      gpointer user_data)
 {
 }
 
+
 gboolean
 gfile_xfer (GFile    *sfile,
 	    GFile    *dfile,
@@ -584,34 +717,59 @@
 }
 
 
-void
-gfile_output_stream_write_line (GFileOutputStream *ostream, 
-				GError            *error,
-				const char        *format,
+gssize
+gfile_output_stream_write (GFileOutputStream  *ostream, 
+			   GError            **error,
+			   const char         *str)
+{
+	GError   *priv_error = NULL;
+	gssize    result;
+
+
+	g_assert (str != NULL);
+	
+	if (error == NULL)
+		error = &priv_error;
+
+	result = g_output_stream_write (G_OUTPUT_STREAM(ostream), 
+			                str,
+			                strlen (str),
+			                NULL,
+			                error);
+	
+	if (*error != NULL)
+		debug (DEBUG_INFO, "could not write string \"%s\": %s\n", str, (*error)->message);
+	
+	if (priv_error != NULL)
+		g_clear_error (&priv_error);
+	
+	return result;
+}
+
+
+gssize
+gfile_output_stream_write_line (GFileOutputStream  *ostream, 
+				GError            **error,
+				const char         *format,
 				...)
 {
 	va_list         args;
 	char           *str;
+	gssize          n1 = -1;
+	gssize          n2 = -1;
 
 	g_assert (format != NULL);
-
+	
 	va_start (args, format);
 	str = g_strdup_vprintf (format, args);
 	va_end (args);
 
-	g_output_stream_write (G_OUTPUT_STREAM(ostream), 
-			       str,
-			       strlen (str),
-			       NULL,
-			       &error);
+	n1 = gfile_output_stream_write (ostream, error, str);
+	
+	if (n1 != -1)
+		n2 = gfile_output_stream_write (ostream, error, "\n");
+	
 	g_free (str);
-
-	if (error != NULL)
-		return;
-
-	g_output_stream_write (G_OUTPUT_STREAM(ostream), 
-                               "\n",
-                               1,
-                               NULL,
-                               &error);	
+	
+	return (n1 == -1 || n2 == -1 ? -1 : n1 + n2);
 }
Index: libgthumb/gfile-utils.h
===================================================================
--- libgthumb/gfile-utils.h	(revision 2400)
+++ libgthumb/gfile-utils.h	(working copy)
@@ -66,6 +66,10 @@
                                                 ...);
 
 gboolean      gfile_is_local                   (GFile      *file);
+const char*   gfile_get_file_mime_type         (GFile      *file,
+                                                gboolean    fast_file_type);
+gboolean      gfile_image_is_jpeg              (GFile      *file);
+gboolean      gfile_image_is_gif               (GFile      *file);
 gboolean      gfile_path_is_file               (GFile      *file);
 gboolean      gfile_path_is_dir                (GFile      *file);
 goffset       gfile_get_file_size              (GFile      *file);
@@ -92,9 +96,12 @@
 		                                GFile      *dfile);
 
 /* line-based read/write */
-void          gfile_output_stream_write_line   (GFileOutputStream *ostream,
-                                		GError            *error,
+gssize        gfile_output_stream_write_line   (GFileOutputStream *ostream,
+                                		GError           **error,
 		                                const char        *format,
                 		                ...);
+gssize        gfile_output_stream_write        (GFileOutputStream  *ostream, 
+                                                GError            **error,
+                                                const char         *str);
 
 #endif /* GFILE_UTILS_H */
Index: libgthumb/catalog.c
===================================================================
--- libgthumb/catalog.c	(revision 2400)
+++ libgthumb/catalog.c	(working copy)
@@ -373,39 +373,39 @@
 
 		/* write search data. */
 		if (!error) gfile_output_stream_write_line (ostream,
-							    error,
+							    &error,
 							    SEARCH_HEADER);
 		if (!error) gfile_output_stream_write_line (ostream,
-                                                            error,
+                                                            &error,
 							    "\"%s\"",
 							    search_data->start_from);
 		if (!error) gfile_output_stream_write_line (ostream,
-                                                            error,
+                                                            &error,
 							    "\"%s\"",
 							   (search_data->recursive ? "TRUE" : "FALSE"));
 		if (!error) gfile_output_stream_write_line (ostream,
-                                                            error,
+                                                            &error,
                                                             "\"%s\"",
                                                             search_data->file_pattern);
 		if (!error) gfile_output_stream_write_line (ostream,
-                                                            error,
+                                                            &error,
                                                             "\"%s\"",
                                                             search_data->comment_pattern);
 		if (!error) gfile_output_stream_write_line (ostream,
-                                                            error,
+                                                            &error,
                                                             "\"%s\"",
                                                             search_data->place_pattern);
 		if (!error) gfile_output_stream_write_line (ostream,
-                                                            error,
+                                                            &error,
 							    "%d\"%s\"",
 							    catalog->search_data->all_keywords,
                                                             search_data->keywords_pattern);
 		if (!error) gfile_output_stream_write_line (ostream,
-                                                            error,
+                                                            &error,
                                                             "%ld",
                                                             search_data->date);
 		if (!error) gfile_output_stream_write_line (ostream,
-                                                            error,
+                                                            &error,
                                                             "%d",
                                                             search_data->date_scope);
 	}
@@ -413,7 +413,7 @@
 	/* sort method */
 
 	if (!error) gfile_output_stream_write_line (ostream,
-						    error,
+						    &error,
 						    "%s%s",
 						    SORT_FIELD,
 						    sort_names[catalog->sort_method]);
@@ -422,7 +422,7 @@
 
 	for (scan = catalog->list; scan; scan = scan->next)
 		if (!error) gfile_output_stream_write_line (ostream,
-							    error,
+							    &error,
 							    "\"%s\"",
 							    (char*) scan->data);
 
Index: libgthumb/file-utils.c
===================================================================
--- libgthumb/file-utils.c	(revision 2400)
+++ libgthumb/file-utils.c	(working copy)
@@ -407,7 +407,16 @@
 gboolean
 dir_remove (const gchar *path)
 {
-	return (gnome_vfs_remove_directory (path) == GNOME_VFS_OK);
+	GFile    *file;
+	gboolean  result;
+	
+	file = gfile_new (path);
+	
+	result = g_file_delete (file, NULL, NULL);
+	
+	g_object_unref (file);
+
+	return result;
 }
 
 
@@ -781,7 +790,18 @@
 gboolean
 file_unlink (const char *path)
 {
-	return (gnome_vfs_unlink (path) == GNOME_VFS_OK);
+	GFile    *file;
+	gboolean  result;
+	
+	g_assert (path != NULL);
+	
+	file = gfile_new (path);
+	
+	result = g_file_delete (file, NULL, NULL);
+	
+	g_object_unref (file);
+
+	return result;
 }
 
 
@@ -807,99 +827,27 @@
 }
 
 
-static char*
-get_sample_name (const char *filename)
-{
-	const char *ext;
-
-	ext = get_extension (filename);
-	if (ext == NULL)
-		return NULL;
-
-	return g_strconcat ("a", get_extension (filename), NULL);
-}
-
-
 const char*
-get_file_mime_type (const char *filename,
+get_file_mime_type (const char *path,
 		    gboolean    fast_file_type)
 {
-	const char *result = NULL;
-	const char *extension;
-
-	if (filename == NULL)
+	GFile      *file;
+	const char *result;
+	
+	if (path == NULL)
 		return NULL;
 
-	if (fast_file_type) {
-		char *sample_name;
-		char *n1;
+	file = gfile_new (path);
 
-		sample_name = get_sample_name (filename);
-		if (sample_name != NULL) {
-			n1 = g_filename_to_utf8 (sample_name, -1, 0, 0, 0);
-			if (n1 != NULL) {
-				char *n2 = g_utf8_strdown (n1, -1);
-				char *n3 = g_filename_from_utf8 (n2, -1, 0, 0, 0);
-				if (n3 != NULL)
-					result = gnome_vfs_mime_type_from_name_or_default (file_name_from_path (n3), NULL);
-				g_free (n3);
-				g_free (n2);
-				g_free (n1);
-			}
+	result = gfile_get_file_mime_type (file, fast_file_type);
 
-			g_free (sample_name);
-		}
-	} 
-	else {
-		if (uri_scheme_is_file (filename))
-			filename = get_file_path_from_uri (filename);
-		result = gnome_vfs_get_file_mime_type (filename, NULL, FALSE);
-	}
-
-	result = get_static_string (result);
-
-	/* Check files with special or problematic extensions */
-	extension = get_filename_extension (filename);
-	if (extension != NULL) {
-
-		/* Raw NEF files are sometimes mis-recognized as tiff files. Fix that. */
-		if (!strcmp_null_tolerant (result, "image/tiff") && 
-		    !strcasecmp (extension, "nef"))
-			return "image/x-nikon-nef";
-
-		/* Raw CR2 files are sometimes mis-recognized as tiff files. Fix that. */
-		if (!strcmp_null_tolerant (result, "image/tiff") && 
-		    !strcasecmp (extension, "cr2"))
-			return "image/x-canon-cr2";
-
-		/* Check unrecognized binary types for special types that are not
-		   handled correctly in the normal mime databases. */
-
-		if ((result == NULL) || 
-		    (strcmp_null_tolerant (result, "application/octet-stream") == 0)) {
-
-			/* If the file extension is not recognized, or the content is
-			   determined to be binary data (octet-stream), check for HDR file
-			   types, which are not well represented in the freedesktop mime
-			   database currently. This section can be purged when they are.
-			   This is an unpleasant hack. Some file extensions
-			   may be missing here; please file a bug if they are. */
-			if (   !strcasecmp (extension, "exr")	/* OpenEXR format */
-			    || !strcasecmp (extension, "hdr")	/* Radiance rgbe */
-			    || !strcasecmp (extension, "pic"))	/* Radiance rgbe */
-				return "image/x-hdr";
-
-			/* Bug 329072: gnome-vfs doesn't recognize pcx files.
-			   This is the work-around until bug 329072 is fixed. */
-			if (strcasecmp (extension, "pcx") == 0)
-				return "image/x-pcx";
-		}
-	}
+	g_object_unref (file);
 
 	return result;
 }
 
 
+
 gboolean
 mime_type_is (const char *mime_type,
 	      const char *value)
@@ -909,27 +857,18 @@
 
 
 gboolean
-image_is_type (const char *uri,
-	       const char *type,
-	       gboolean    fast_file_type)
+image_is_jpeg (const char *path)
 {
-	const char *result = get_file_mime_type (uri, fast_file_type);
-	return (strcmp_null_tolerant (result, type) == 0);
-}
-
-
-static gboolean
-image_is_type__gconf_file_type (const char *uri,
-			        const char *type)
-{
-	return image_is_type (uri, type, ! is_local_file (uri) || eel_gconf_get_boolean (PREF_FAST_FILE_TYPE, TRUE));
-}
-
+	GFile    *file;
+	gboolean  result;
+	
+	file = gfile_new (path);
+	
+	result = gfile_image_is_jpeg (file);
+	
+	g_object_unref (file);
 
-gboolean
-image_is_jpeg (const char *name)
-{
-	return image_is_type__gconf_file_type (name, "image/jpeg");
+	return result;
 }
 
 
@@ -964,9 +903,18 @@
 
 
 gboolean
-image_is_gif (const char *name)
+image_is_gif (const char *path)
 {
-	return image_is_type__gconf_file_type (name, "image/gif");
+	GFile    *file;
+	gboolean  result;
+	
+	file = gfile_new (path);
+	
+	result = gfile_image_is_gif (file);
+	
+	g_object_unref (file);
+
+	return result;
 }
 
 
Index: src/albumtheme.y
===================================================================
--- src/albumtheme.y	(revision 2400)
+++ src/albumtheme.y	(working copy)
@@ -22,6 +22,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <gio/gio.h>
 #include "albumtheme-private.h"
 
 void  yyerror (char *fmt, ...);
Index: src/catalog-web-exporter.c
===================================================================
--- src/catalog-web-exporter.c	(revision 2400)
+++ src/catalog-web-exporter.c	(working copy)
@@ -79,10 +79,10 @@
 };
 
 extern int yyparse (void);
+extern GFileInputStream *yy_istream;
 
 static GObjectClass *parent_class = NULL;
 static guint         catalog_web_exporter_signals[LAST_SIGNAL] = { 0 };
-extern FILE         *yyin;
 
 #define DEFAULT_THUMB_SIZE 100
 #define DEFAULT_INDEX_FILE "index.html"
@@ -1069,36 +1069,49 @@
 }
 
 
+/* write a line when no error is pending */
+
 static void
-_write_line (const char *line, FILE *fout)
+_write_line (GFileOutputStream   *ostream, 
+	     GError             **error,
+	     const char          *line)
 {
-	fwrite (line, sizeof (char), strlen (line), fout);
+	if (error != NULL && *error != NULL)
+		return;
+	
+	gfile_output_stream_write (ostream, error, line);
 }
 
 
 static void
-_write_locale_line (const char *line, FILE *fout)
+_write_locale_line (GFileOutputStream  *ostream, 
+		    GError            **error,
+		    const char         *line)
 {
 	char *utf8_line;
 
 	utf8_line = g_locale_to_utf8 (line, -1, 0, 0, 0);
-	_write_line (utf8_line, fout);
+	_write_line (ostream, error, utf8_line);
 	g_free (utf8_line);
 }
 
 
 static void
-write_line (const char *line, FILE *fout)
+write_line (GFileOutputStream  *ostream, 
+	    GError            **error,
+	    const char         *line)
 {
 	if (line_is_void (line))
 		return;
 
-	_write_line (line, fout);
+	_write_line (ostream, error, line);
 }
 
 
 static void
-write_markup_escape_line (const char *line, FILE *fout)
+write_markup_escape_line (GFileOutputStream  *ostream, 
+                          GError            **error,
+                          const char         *line)
 {
 	char *e_line;
 
@@ -1106,13 +1119,15 @@
 		return;
 	
 	e_line = _g_escape_text_for_html (line, -1);
-	_write_line (e_line, fout);
+	_write_line (ostream, error, e_line);
 	g_free (e_line);
 }
 
 
 static void
-write_markup_escape_locale_line (const char *line, FILE *fout)
+write_markup_escape_locale_line (GFileOutputStream  *ostream, 
+                                 GError            **error,
+                                 const char         *line)
 {
 	char *e_line;
 
@@ -1122,7 +1137,7 @@
 		return;
 	
 	e_line = _g_escape_text_for_html (line, -1);
-	_write_locale_line (e_line, fout);
+	_write_locale_line (ostream, error, e_line);
 	g_free (e_line);
 }
 
@@ -1465,11 +1480,12 @@
 
 
 static void
-gth_parsed_doc_print (GList              *document,
-		      GFile		 *relative_to,
-		      CatalogWebExporter *ce,
-		      FILE               *fout,
-		      gboolean            allow_table)
+gth_parsed_doc_print (GList               *document,
+		      GFile		  *relative_to,
+		      CatalogWebExporter  *ce,
+		      GFileOutputStream   *ostream, 
+		      GError             **error,
+		      gboolean             allow_table)
 {
 	GList *scan;
 
@@ -1499,20 +1515,23 @@
 		GList      *scan;
 
 
+		if (error != NULL && *error != NULL)
+			return;
+		
 		switch (tag->type) {
 		case GTH_TAG_HEADER:
 			line = get_hf_text (ce->header);
-			write_markup_escape_line (line, fout);
+			write_markup_escape_line (ostream, error, line);
 			break;
 
 		case GTH_TAG_FOOTER:
 			line = get_hf_text (ce->footer);
-			write_markup_escape_line (line, fout);
+			write_markup_escape_line (ostream, error, line);
 			break;
 
 		case GTH_TAG_LANGUAGE:
 			line = get_current_language ();
-			write_markup_escape_line (line, fout);
+			write_markup_escape_line (ostream, error, line);
 			break;
 
 		case GTH_TAG_THEME_LINK:
@@ -1525,7 +1544,7 @@
 					       src);
 			line = gfile_get_relative_uri (file, relative_to);
 			
-			write_markup_escape_line (line, fout);
+			write_markup_escape_line (ostream, error, line);
 			
 			g_object_unref (file);
 			break;
@@ -1602,7 +1621,7 @@
 						image_height,
 						id_attr,
 						class_attr);
-			write_line (line, fout);
+			write_line (ostream, error, line);
 
 			g_free (src_attr);
 			g_free (id_attr);
@@ -1619,14 +1638,14 @@
 						    idata, 
 						    ce->target_dir);
 			line = gfile_get_relative_uri (file, relative_to);
-			write_markup_escape_line (line, fout);
+			write_markup_escape_line (ostream, error, line);
 
 			g_object_unref (file);
 			break;
 
 		case GTH_TAG_IMAGE_IDX:
 			line = g_strdup_printf ("%d", get_image_idx (tag, ce) + 1);
-			write_line (line, fout);
+			write_line (ostream, error, line);
 			break;
 
 		case GTH_TAG_IMAGE_DIM:
@@ -1635,12 +1654,12 @@
 			line = g_strdup_printf ("%dx%d",
 						idata->image_width,
 						idata->image_height);
-			write_line (line, fout);
+			write_line (ostream, error, line);
 			break;
 
 		case GTH_TAG_IMAGES:
 			line = g_strdup_printf ("%d", ce->n_images);
-			write_line (line, fout);
+			write_line (ostream, error, line);
 			break;
 
 		case GTH_TAG_FILENAME:
@@ -1685,9 +1704,9 @@
 			}
 
 			if  (gth_tag_get_var (ce, tag, "utf8") != 0)
-				write_markup_escape_locale_line (line, fout);
+				write_markup_escape_locale_line (ostream, error, line);
 			else
-				write_markup_escape_line (line, fout);
+				write_markup_escape_line (ostream, error, line);
 
 			g_object_unref (file);
 			break;
@@ -1728,9 +1747,9 @@
 				line = gfile_get_path (dir);
 
 			if  (gth_tag_get_var (ce, tag, "utf8") != 0)
-				write_markup_escape_locale_line (line, fout);
+				write_markup_escape_locale_line (ostream, error, line);
 			else
-				write_markup_escape_line (line, fout);
+				write_markup_escape_line (ostream, error, line);
 
 			g_object_unref (dir);
 			g_object_unref (file);
@@ -1740,7 +1759,7 @@
 			idx = get_image_idx (tag, ce);
 			idata = g_list_nth (ce->file_list, idx)->data;
 			line = g_format_size_for_display (idata->src_file->size);
-			write_markup_escape_line (line, fout);
+			write_markup_escape_line (ostream, error, line);
 			break;
 
 		case GTH_TAG_COMMENT:
@@ -1765,7 +1784,7 @@
 				g_free (comment);
 			}
 
-			write_markup_escape_line (line, fout);
+			write_markup_escape_line (ostream, error, line);
 			break;
 
 		case GTH_TAG_PLACE:
@@ -1789,7 +1808,7 @@
 				g_free (place);
 			}
 
-			write_markup_escape_line (line, fout);
+			write_markup_escape_line (ostream, error, line);
 			break;
 
 		case GTH_TAG_DATE_TIME:
@@ -1812,7 +1831,7 @@
 				g_free (date_time);
 			}
 
-			write_markup_escape_line (line, fout);
+			write_markup_escape_line (ostream, error, line);
 			break;
 
 		case GTH_TAG_PAGE_LINK:
@@ -1828,29 +1847,29 @@
 						    idx, 
 						    ce->target_dir);
 			line = gfile_get_relative_uri (file, relative_to);
-			write_markup_escape_line (line, fout);
+			write_markup_escape_line (ostream, error, line);
 
 			g_object_unref (file);
 			break;
 
 		case GTH_TAG_PAGE_IDX:
 			line = g_strdup_printf ("%d", get_page_idx (tag, ce) + 1);
-			write_line (line, fout);
+			write_line (ostream, error, line);
 			break;
 
 		case GTH_TAG_PAGE_ROWS:
 			line = g_strdup_printf ("%d", ce->page_rows);
-			write_line (line, fout);
+			write_line (ostream, error, line);
 			break;
 			
 		case GTH_TAG_PAGE_COLS:
 			line = g_strdup_printf ("%d", ce->page_cols);
-			write_line (line, fout);
+			write_line (ostream, error, line);
 			break;
 			
 		case GTH_TAG_PAGES:
 			line = g_strdup_printf ("%d", ce->n_pages);
-			write_line (line, fout);
+			write_line (ostream, error, line);
 			break;
 
 		case GTH_TAG_TABLE:
@@ -1863,27 +1882,28 @@
 			/* this may not work correctly if single_index is set */
 			for (r = 0; r < ce->page_rows; r++) {
 				if (ce->image < ce->n_images)
-					write_line ("  <tr class=\"tr_index\">\n", fout);
+					write_line (ostream, error, "  <tr class=\"tr_index\">\n");
 				else
-					write_line ("  <tr class=\"tr_empty_index\">\n", fout);
+					write_line (ostream, error, "  <tr class=\"tr_empty_index\">\n");
 				for (c = 0; c < ce->page_cols; c++) {
 					if (ce->image < ce->n_images) {
-						write_line ("    <td class=\"td_index\">\n", fout);
+						write_line (ostream, error, "    <td class=\"td_index\">\n");
 						gth_parsed_doc_print (ce->thumbnail_parsed,
 								      relative_to,
 								      ce,
-								      fout,
+								      ostream,
+								      error,
 								      FALSE);
-						write_line ("    </td>\n", fout);
+						write_line (ostream, error, "    </td>\n");
 						ce->image++;
 					} 
 					else {
-						write_line ("    <td class=\"td_empty_index\">\n", fout);
-						write_line ("    &nbsp;\n", fout);
-						write_line ("    </td>\n", fout);
+						write_line (ostream, error, "    <td class=\"td_empty_index\">\n");
+						write_line (ostream, error, "    &nbsp;\n");
+						write_line (ostream, error, "    </td>\n");
 					}
 				}
-				write_line ("  </tr>\n", fout);
+				write_line (ostream, error, "  </tr>\n");
 			}
 			break;
 
@@ -1897,8 +1917,9 @@
 					break;
 				gth_parsed_doc_print (ce->thumbnail_parsed, 
 						      relative_to,
-						      ce, 
-						      fout, 
+						      ce,
+						      ostream,
+						      error,
 						      FALSE);
 				ce->image++;
 			}
@@ -1906,11 +1927,11 @@
 
 		case GTH_TAG_DATE:
 			line = get_current_date ();
-			write_markup_escape_line (line, fout);
+			write_markup_escape_line (ostream, error, line);
 			break;
 
 		case GTH_TAG_HTML:
-			write_line (tag->value.html, fout);
+			write_line (ostream, error, tag->value.html);
 			break;
 
 		case GTH_TAG_EXIF_EXPOSURE_TIME:
@@ -1918,7 +1939,7 @@
 			idata = g_list_nth (ce->file_list, idx)->data;
 			line = get_metadata_tagset_string (idata->src_file, 
 							    TAG_NAME_SETS[EXPTIME_TAG_NAMES]);
-			write_markup_escape_line (line, fout);
+			write_markup_escape_line (ostream, error, line);
 			break;
 
 		case GTH_TAG_EXIF_EXPOSURE_MODE:
@@ -1926,7 +1947,7 @@
 			idata = g_list_nth (ce->file_list, idx)->data;
 			line = get_metadata_tagset_string (idata->src_file,
 							    TAG_NAME_SETS[EXPMODE_TAG_NAMES]);
-			write_markup_escape_line (line, fout);
+			write_markup_escape_line (ostream, error, line);
 			break;
 
 		case GTH_TAG_EXIF_FLASH:
@@ -1934,7 +1955,7 @@
 			idata = g_list_nth (ce->file_list, idx)->data;
 			line = get_metadata_tagset_string (idata->src_file,
 					     		    TAG_NAME_SETS[FLASH_TAG_NAMES]);
-			write_markup_escape_line (line, fout);
+			write_markup_escape_line (ostream, error, line);
 			break;
 
 		case GTH_TAG_EXIF_SHUTTER_SPEED:
@@ -1942,7 +1963,7 @@
 			idata = g_list_nth (ce->file_list, idx)->data;
 			line = get_metadata_tagset_string (idata->src_file,
 							    TAG_NAME_SETS[SHUTTERSPEED_TAG_NAMES]);
-			write_markup_escape_line (line, fout);
+			write_markup_escape_line (ostream, error, line);
 			break;
 
 		case GTH_TAG_EXIF_APERTURE_VALUE:
@@ -1950,7 +1971,7 @@
 			idata = g_list_nth (ce->file_list, idx)->data;
 			line = get_metadata_tagset_string (idata->src_file,
 							    TAG_NAME_SETS[APERTURE_TAG_NAMES]); 
-			write_markup_escape_line (line, fout);
+			write_markup_escape_line (ostream, error, line);
 			break;
 
 		case GTH_TAG_EXIF_FOCAL_LENGTH:
@@ -1958,7 +1979,7 @@
 			idata = g_list_nth (ce->file_list, idx)->data;
 			line = get_metadata_tagset_string (idata->src_file,
 					     		    TAG_NAME_SETS[FOCAL_TAG_NAMES]);
-			write_markup_escape_line (line, fout);
+			write_markup_escape_line (ostream, error, line);
 			break;
 
 		case GTH_TAG_EXIF_DATE_TIME:
@@ -1974,10 +1995,10 @@
 					tp = localtime (&t);
 					strftime (s, 99, DATE_FORMAT, tp);
 					line = g_locale_to_utf8 (s, -1, 0, 0, 0);
-					write_markup_escape_line (line, fout);
+					write_markup_escape_line (ostream, error, line);
 				} 
 				else
-					write_line ("-", fout);
+					write_line (ostream, error, "-");
 
 			}
 			break;
@@ -1987,14 +2008,14 @@
 			idata = g_list_nth (ce->file_list, idx)->data;
 			line = get_metadata_tagset_string (idata->src_file,
 							    TAG_NAME_SETS[MAKE_TAG_NAMES]);
-			write_markup_escape_line (line, fout);
+			write_markup_escape_line (ostream, error, line);
 			g_free (line);
 
-			write_line (" &nbsp; ", fout);
+			write_line (ostream, error, " &nbsp; ");
 
 			line = get_metadata_tagset_string (idata->src_file,
 					    		    TAG_NAME_SETS[MODEL_TAG_NAMES]);
-			write_markup_escape_line (line, fout);
+			write_markup_escape_line (ostream, error, line);
 			break;
 
 		case GTH_TAG_SET_VAR:
@@ -2007,8 +2028,8 @@
 
 			value = gth_tag_get_var (ce, tag, "expr");
 
-			line = g_strdup_printf ("%d",value);
-			write_line (line, fout);
+			line = g_strdup_printf ("%d", value);
+			write_line (ostream, error, line);
 			break;
 
 		case GTH_TAG_IF:
@@ -2022,7 +2043,8 @@
 					gth_parsed_doc_print (cond->document,
 							      relative_to,
 							      ce,
-							      fout,
+							      ostream,
+							      error,
 							      FALSE);
 					break;
 				}
@@ -2036,7 +2058,7 @@
 				if (child->type != GTH_TAG_HTML)
 					break;
 				line = g_strdup (_(child->value.html));
-				write_markup_escape_line (line, fout);
+				write_markup_escape_line (ostream, error, line);
 			}
 			break;
 
@@ -2049,6 +2071,45 @@
 }
 
 
+
+static gboolean
+gfile_parsed_doc_print (CatalogWebExporter *ce,
+                        GList              *document,
+                        GFile              *file,
+			GFile              *relative_to)
+{
+        GFileOutputStream  *ostream;
+        GError             *error = NULL;
+        gboolean            result;
+
+	gfile_debug (DEBUG_INFO, "save html file", file);
+
+        ostream = g_file_replace (file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, &error);
+        
+        if (error) {
+                gfile_warning ("Cannot open html file for writing",
+                               file,
+                               error);
+        }
+        else {
+		gth_parsed_doc_print (document,
+				      relative_to,
+				      ce, 
+				      ostream,
+				      &error,
+				      TRUE);
+	} 
+
+	g_output_stream_close (G_OUTPUT_STREAM(ostream), NULL, &error);
+	g_object_unref (ostream);
+	
+	result = (error == NULL);
+	g_clear_error (&error);
+
+	return result;
+}
+
+
 static void
 exporter_set_info (CatalogWebExporter *ce,
 		   const char         *info)
@@ -2324,14 +2385,14 @@
 }
 
 
+
 static gboolean
 save_html_image_cb (gpointer data)
 {
 	CatalogWebExporter *ce = data;
 	ImageData          *idata;
 	GFile              *file;
-	char               *local_file;
-	FILE               *fout;
+	GFile              *relative_to;
 
 	if (ce->saving_timeout != 0) {
 		g_source_remove (ce->saving_timeout);
@@ -2353,28 +2414,16 @@
 	file = get_html_image_file (ce, 
 				    idata, 
 				    ce->target_tmp_dir);
-	local_file = gfile_get_path (file);
-		
-	debug (DEBUG_INFO, "save html file: %s", local_file);
-
-	fout = fopen (local_file, "w");
-	if (fout != NULL) {
-		GFile *relative_to;
+	
+	
+	relative_to = get_html_image_dir (ce, 
+					  ce->target_dir);
+	
 
-		relative_to = get_html_image_dir (ce, 
-						  ce->target_dir);
-		
-		gth_parsed_doc_print (ce->image_parsed,
-				      relative_to,
-				      ce, 
-				      fout, 
-				      TRUE);
-		g_object_unref (relative_to);
-		fclose (fout);
-	} 
+	gfile_parsed_doc_print (ce, ce->image_parsed, file, relative_to);
 
 	g_object_unref (file);
-	g_free (local_file);
+	g_object_unref (relative_to);
 
 	/**/
 
@@ -2407,8 +2456,6 @@
 	CatalogWebExporter *ce = data;
 	GFile              *file;
 	GFile              *relative_to;
-	char               *local_file;
-	FILE               *fout;
 
 	if (ce->saving_timeout != 0) {
 		g_source_remove (ce->saving_timeout);
@@ -2435,21 +2482,8 @@
 				    ce->page, 
 				    ce->target_tmp_dir);
 
-	local_file = gfile_get_path (file);
-
-	debug (DEBUG_INFO, "save html index: %s", local_file);
+	gfile_parsed_doc_print (ce, ce->index_parsed, file, relative_to);
 
-	fout = fopen (local_file, "w");
-	if (fout != NULL) {
-		gth_parsed_doc_print (ce->index_parsed,
-				      relative_to, 
-				      ce, 
-				      fout,
-				      TRUE);
-		fclose (fout);
-	} 
-
-	g_free (local_file);
 	g_object_unref (file);
 	g_object_unref (relative_to);
 
@@ -2664,10 +2698,10 @@
 	copy_done = gfile_copy (sfile, dfile);
 
 	if (copy_done) {
-		char *uri;
-		uri = gfile_get_uri (dfile);
+		if (gfile_image_is_jpeg (dfile)) {
+			char *uri;
+			uri = gfile_get_uri (dfile);
 		
-		if (image_is_jpeg (uri)) {
 			GthTransform  transform;
 		
 			FileData *fd;
@@ -2682,8 +2716,8 @@
 			}
 
 			file_data_unref (fd);
+			g_free (uri);
 		}
-		g_free (uri);
 	}
 	
 	g_object_unref (sfile);
@@ -2846,12 +2880,41 @@
 }
 
 
+static GList *
+get_parsed_file (GFile *file) 
+{
+	GList            *result = NULL;
+	GError           *error = NULL;
+	
+	yy_parsed_doc = NULL;
+	
+	gfile_debug (DEBUG_INFO, "load template", file);
+	
+	yy_istream = g_file_read (file, NULL, &error);
+	
+	if (error != NULL) {
+		gfile_warning ("Could not open template", file, error);
+		g_object_unref (&error);
+	}
+	else {
+		if (yyparse () == 0)
+			result = yy_parsed_doc;
+		else
+			debug (DEBUG_INFO, "<<syntax error>>");
+		
+		g_input_stream_close (G_INPUT_STREAM(yy_istream), NULL, &error);
+		g_object_unref (yy_istream);
+	}
+	
+	return result;
+}
+
+
 static void
 parse_theme_files (CatalogWebExporter *ce)
 {
-	GFile *template;
-	char  *local_file;
-	GList *scan;
+	GFile            *template;
+	GList            *scan;
 
 	free_parsed_docs (ce);
 
@@ -2859,50 +2922,29 @@
 
 	/* read and parse index.gthtml */
 
-	yy_parsed_doc = NULL;
 	template = gfile_append_path (ce->style_dir, 
 				      "index.gthtml",
 				      NULL);
-	gfile_debug (DEBUG_INFO, "load", template);
-	
-	local_file = gfile_get_path (template);
-	yyin = fopen (local_file, "r");
 	
-	if ((yyin != NULL) && (yyparse () == 0))
-		ce->index_parsed = yy_parsed_doc;
-	else
-		debug (DEBUG_INFO, "<<syntax error>>");
+	ce->index_parsed = get_parsed_file (template);
 
-	if (yyin != NULL)
-		fclose (yyin);
+	g_object_unref (template);
 
 	if (ce->index_parsed == NULL) {
 		GthTag *tag = gth_tag_new (GTH_TAG_TABLE, NULL);
 		ce->index_parsed = g_list_prepend (NULL, tag);
 	}
 
-	g_object_unref (template);
-	g_free (local_file);
-
 	/* read and parse thumbnail.gthtml */
 
-	yy_parsed_doc = NULL;
 	template = gfile_append_path (ce->style_dir, 
 				      "thumbnail.gthtml",
 				      NULL);
-	gfile_debug (DEBUG_INFO, "load", template);
-	
-	local_file = gfile_get_path (template);
-	yyin = fopen (local_file, "r");
 	
-	if ((yyin != NULL) && (yyparse () == 0))
-		ce->thumbnail_parsed = yy_parsed_doc;
-	else
-		debug (DEBUG_INFO, "<<syntax error>>");
+	ce->thumbnail_parsed = get_parsed_file (template);
 
-	if (yyin != NULL)
-		fclose (yyin);
-
+	g_object_unref (template);
+	
 	if (ce->thumbnail_parsed == NULL) {
 		GthExpr *expr;
 		GthVar  *var;
@@ -2923,28 +2965,16 @@
 		ce->thumbnail_parsed = g_list_prepend (NULL, tag);
 	}
 
-	g_object_unref (template);
-	g_free (local_file);
-
 	/* Read and parse image.gthtml */
 
-	yy_parsed_doc = NULL;
 	template = gfile_append_path (ce->style_dir, 
 				      "image.gthtml",
 				      NULL);
-	gfile_debug (DEBUG_INFO, "load", template);
 	
-	local_file = gfile_get_path (template);	
-	yyin = fopen (local_file, "r");
+	ce->image_parsed = get_parsed_file (template);
+
+	g_object_unref (template);
 	
-	if ((yyin != NULL) && (yyparse () == 0))
-		ce->image_parsed = yy_parsed_doc;
-	else
-		debug (DEBUG_INFO, "<<syntax error>>");
-
-	if (yyin != NULL)
-		fclose (yyin);
-
 	if (ce->image_parsed == NULL) {
 		GthExpr *expr;
 		GthVar  *var;
@@ -2965,9 +2995,6 @@
 		ce->image_parsed = g_list_prepend (NULL, tag);
 	}
 
-	g_object_unref (template);
-	g_free (local_file);
-	
 	/* read index.html and set variables. */
 
 	for (scan = ce->index_parsed; scan; scan = scan->next) {
Index: src/albumtheme.l
===================================================================
--- src/albumtheme.l	(revision 2400)
+++ src/albumtheme.l	(working copy)
@@ -20,10 +20,20 @@
  */
 
 #include <glib.h>
+#include <gio/gio.h>
+
+GFileInputStream *yy_istream;
+
+#undef YY_INPUT
+#define YY_INPUT(buf,result,max_size)                                      	                  \
+{                                                                          	                  \
+	gssize n = g_input_stream_read (G_INPUT_STREAM(yy_istream), buf, max_size, NULL, NULL);   \
+	result = (n <= 0 ? YY_NULL : n);                                                          \
+}
 
 %}
 
-%option nounput
+%option noinput nounput
 
 number           [0-9]+
 name             [a-zA-Z_][0-9a-zA-Z_:@]*
