Beispiel #1
0
guint64
utils_timestamp_file(const gchar* filename, GError** error)
{
    RETURN_VAL_IF_FAIL(!utils_str_empty(filename), 0);

    GError* err = NULL; /* NOTE: Doesn't need to be freed because we propagate it */

    if (g_file_test(filename, G_FILE_TEST_EXISTS))
    {
        GTimeVal time;

        g_autoptr(GFile) file = g_file_new_for_path(filename);

        g_autoptr(GFileInfo) info = g_file_query_info(file,
            G_FILE_ATTRIBUTE_TIME_MODIFIED, G_FILE_QUERY_INFO_NONE,
            NULL, &err);

        if (err)
        {
            WARNING("Could not timestamp file because: %s", err->message);

            g_propagate_prefixed_error(error, err, "Could not timestamp file because: ");

            return 0;
        }

        g_file_info_get_modification_time(info, &time);

        return time.tv_sec;
    }

    RETURN_VAL_IF_REACHED(0);
}
GTimeVal*
codeslayer_utils_get_modification_time (const gchar *file_path)
{
  GFile *file;
  GFileInfo *info;
  GTimeVal time;
  GTimeVal *result;
  
  file = g_file_new_for_path (file_path);
  
  info = g_file_query_info (file, "*", 
                            G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, NULL);
                            
  g_file_info_get_modification_time (info, &time);
  
  result = g_malloc (sizeof (GTimeVal));
  
  result->tv_sec = time.tv_sec;
  result->tv_usec = time.tv_usec;
  
  g_object_unref (file);
  g_object_unref (info);
  
  return result;
}
static void
ft_handler_gfile_ready_cb (GObject *source,
    GAsyncResult *res,
    CallbacksData *cb_data)
{
  GFileInfo *info;
  GError *error = NULL;
  GTimeVal mtime;
  EmpathyFTHandlerPriv *priv = GET_PRIV (cb_data->handler);

  DEBUG ("Got GFileInfo.");

  info = g_file_query_info_finish (priv->gfile, res, &error);

  if (error != NULL)
    goto out;

  if (g_file_info_get_file_type (info) != G_FILE_TYPE_REGULAR)
    {
      error = g_error_new_literal (EMPATHY_FT_ERROR_QUARK,
          EMPATHY_FT_ERROR_INVALID_SOURCE_FILE,
          _("The selected file is not a regular file"));
      goto out;
    }

  priv->total_bytes = g_file_info_get_size (info);
  if (priv->total_bytes == 0)
    {
      error = g_error_new_literal (EMPATHY_FT_ERROR_QUARK,
          EMPATHY_FT_ERROR_EMPTY_SOURCE_FILE,
          _("The selected file is empty"));
      goto out;
    }

  priv->content_type = g_strdup (g_file_info_get_content_type (info));
  priv->filename = g_strdup (g_file_info_get_display_name (info));
  g_file_info_get_modification_time (info, &mtime);
  priv->mtime = mtime.tv_sec;
  priv->transferred_bytes = 0;
  priv->description = NULL;

  g_object_unref (info);

out:
  if (error != NULL)
    {
      if (!g_cancellable_is_cancelled (priv->cancellable))
        g_cancellable_cancel (priv->cancellable);

      cb_data->callback (cb_data->handler, error, cb_data->user_data);
      g_error_free (error);

      callbacks_data_free (cb_data);
    }
  else
    {
      /* see if FT/hashing are allowed */
      check_hashing (cb_data);
    }
}
Beispiel #4
0
static void
saved_query_info_cb (GFile         *location,
		     GAsyncResult  *result,
		     GeditDocument *doc)
{
	GFileInfo *info;
	const gchar *content_type = NULL;
	GError *error = NULL;

	info = g_file_query_info_finish (location, result, &error);

	if (error != NULL)
	{
		g_warning ("Document saving: query info error: %s", error->message);
		g_error_free (error);
		error = NULL;
	}

	doc->priv->mtime_set = FALSE;

	if (info != NULL)
	{
		if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE))
		{
			content_type = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE);
		}

		if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_TIME_MODIFIED))
		{
			g_file_info_get_modification_time (info, &doc->priv->mtime);
			doc->priv->mtime_set = TRUE;
		}
	}

	gedit_document_set_content_type (doc, content_type);

	if (info != NULL)
	{
		/* content_type (owned by info) is no longer needed. */
		g_object_unref (info);
	}

	g_get_current_time (&doc->priv->time_of_last_save_or_load);

	doc->priv->externally_modified = FALSE;
	doc->priv->deleted = FALSE;
	doc->priv->create = FALSE;

	set_readonly (doc, FALSE);

	gtk_text_buffer_set_modified (GTK_TEXT_BUFFER (doc), FALSE);

	save_encoding_metadata (doc);

	/* Async operation finished. */
	g_object_unref (doc);
}
Beispiel #5
0
static void
loaded_query_info_cb (GFile         *location,
		      GAsyncResult  *result,
		      GeditDocument *doc)
{
	GFileInfo *info;
	GError *error = NULL;

	info = g_file_query_info_finish (location, result, &error);

	if (error != NULL)
	{
		/* Ignore not found error as it can happen when opening a
		 * non-existent file from the command line.
		 */
		if (error->domain != G_IO_ERROR ||
		    error->code != G_IO_ERROR_NOT_FOUND)
		{
			g_warning ("Document loading: query info error: %s", error->message);
		}

		g_error_free (error);
		error = NULL;
	}

	if (info != NULL)
	{
		if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE))
		{
			const gchar *content_type;

			content_type = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE);

			gedit_document_set_content_type (doc, content_type);
		}

		if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE))
		{
			gboolean read_only;

			read_only = !g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE);

			set_readonly (doc, read_only);
		}

		if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_TIME_MODIFIED))
		{
			g_file_info_get_modification_time (info, &doc->priv->mtime);
			doc->priv->mtime_set = TRUE;
		}

		g_object_unref (info);
	}

	/* Async operation finished. */
	g_object_unref (doc);
}
Beispiel #6
0
static void
check_file_on_disk (GeditDocument *doc)
{
	GFile *location;
	GFileInfo *info;

	location = gtk_source_file_get_location (doc->priv->file);

	if (location == NULL)
	{
		return;
	}

	info = g_file_query_info (location,
				  G_FILE_ATTRIBUTE_TIME_MODIFIED "," \
				  G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE,
				  G_FILE_QUERY_INFO_NONE,
				  NULL, NULL);

	if (info != NULL)
	{
		/* While at it also check if permissions changed */
		if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE))
		{
			gboolean read_only;

			read_only = !g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE);

			set_readonly (doc, read_only);
		}

		if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_TIME_MODIFIED) &&
		    doc->priv->mtime_set)
		{
			GTimeVal timeval;

			g_file_info_get_modification_time (info, &timeval);

			/* Note that mtime can even go backwards if the
			 * user is copying over a file with an old mtime
			 */
			if (timeval.tv_sec != doc->priv->mtime.tv_sec ||
			    timeval.tv_usec != doc->priv->mtime.tv_usec)
			{
				doc->priv->externally_modified = TRUE;
			}
		}

		g_object_unref (info);
	}
	else
	{
		doc->priv->deleted = TRUE;
	}
}
Beispiel #7
0
/**
 * shell_get_thumbnail:
 *
 * @uri: URI of the file to thumbnail
 *
 * @mime_type: Mime-Type of the file to thumbnail
 *
 * Return value: #GdkPixbuf containing a thumbnail for file @uri
 *               if the thumbnail exists or can be generated, %NULL otherwise
 */
GdkPixbuf *
shell_get_thumbnail(const gchar *uri,
                    const gchar *mime_type)
{
    char *existing_thumbnail;
    GdkPixbuf *pixbuf = NULL;
    GError *error = NULL;
    GFile *file = NULL;
    GFileInfo *file_info = NULL;
    GTimeVal mtime_g;
    time_t mtime = 0;

    file = g_file_new_for_uri (uri);
    file_info = g_file_query_info (file, G_FILE_ATTRIBUTE_TIME_MODIFIED, G_FILE_QUERY_INFO_NONE, NULL, NULL);
    g_object_unref (file);
    if (file_info) {
        g_file_info_get_modification_time (file_info, &mtime_g);
        g_object_unref (file_info);
        mtime = (time_t) mtime_g.tv_sec;
    }

    if (thumbnail_factory == NULL)
      thumbnail_factory = gnome_thumbnail_factory_new (GNOME_THUMBNAIL_SIZE_NORMAL);

    existing_thumbnail = gnome_thumbnail_factory_lookup (thumbnail_factory, uri, mtime);

    if (existing_thumbnail != NULL)
      {
        pixbuf = gdk_pixbuf_new_from_file(existing_thumbnail, &error);
        if (error != NULL) 
          {
            g_warning("Could not generate a pixbuf from file %s: %s", existing_thumbnail, error->message);
            g_clear_error (&error);
          }
      }
    else if (gnome_thumbnail_factory_has_valid_failed_thumbnail (thumbnail_factory, uri, mtime))
      return NULL;
    else if (gnome_thumbnail_factory_can_thumbnail (thumbnail_factory, uri, mime_type, mtime)) 
      {
        pixbuf = gnome_thumbnail_factory_generate_thumbnail (thumbnail_factory, uri, mime_type);
        if (pixbuf)
          {
            // we need to save the thumbnail so that we don't need to generate it again in the future
            gnome_thumbnail_factory_save_thumbnail (thumbnail_factory, pixbuf, uri, mtime);
          }          
        else 
          {
            g_warning ("Could not generate thumbnail for %s", uri);
            gnome_thumbnail_factory_create_failed_thumbnail (thumbnail_factory, uri, mtime);
          }
      }

    return pixbuf;   
}
static gboolean
gimp_test_get_file_state_verbose (const gchar       *filename,
                                  GimpTestFileState *filestate)
{
  gboolean success = TRUE;

  filestate->filename = g_strdup (filename);

  /* Get checksum */
  if (success)
    {
      gchar *contents = NULL;
      gsize  length   = 0;

      success = g_file_get_contents (filename,
                                     &contents,
                                     &length,
                                     NULL);
      if (success)
        {
          filestate->md5 = g_compute_checksum_for_string (G_CHECKSUM_MD5,
                                                          contents,
                                                          length);
        }

      g_free (contents);
    }

  /* Get modification time */
  if (success)
    {
      GFile     *file = g_file_new_for_path (filename);
      GFileInfo *info = g_file_query_info (file,
                                           G_FILE_ATTRIBUTE_TIME_MODIFIED, 0,
                                           NULL, NULL);
      if (info)
        {
          g_file_info_get_modification_time (info, &filestate->modtime);
          success = TRUE;
          g_object_unref (info);
        }
      else
        {
          success = FALSE;
        }

      g_object_unref (file);
    }

  if (! success)
    g_printerr ("Failed to get initial file info for '%s'\n", filename);

  return success;
}
static GdkPixbuf *
impl_load_thumbnail (StTextureCache    *cache,
                     const char        *uri,
                     const char        *mime_type,
                     guint              size,
                     GError           **error)
{
  GnomeDesktopThumbnailFactory *thumbnail_factory;
  GdkPixbuf *pixbuf = NULL;
  GFile *file;
  GFileInfo *file_info;
  GTimeVal mtime_g;
  time_t mtime = 0;
  char *existing_thumbnail;

  file = g_file_new_for_uri (uri);
  file_info = g_file_query_info (file, G_FILE_ATTRIBUTE_TIME_MODIFIED, G_FILE_QUERY_INFO_NONE, NULL, NULL);
  g_object_unref (file);
  if (file_info)
    {
      g_file_info_get_modification_time (file_info, &mtime_g);
      g_object_unref (file_info);
      mtime = (time_t) mtime_g.tv_sec;
    }

  thumbnail_factory = cache->priv->thumbnails;

  existing_thumbnail = gnome_desktop_thumbnail_factory_lookup (thumbnail_factory, uri, mtime);

  if (existing_thumbnail != NULL)
    {
      pixbuf = gdk_pixbuf_new_from_file_at_size (existing_thumbnail, size, size, error);
      g_free (existing_thumbnail);
    }
  else if (gnome_desktop_thumbnail_factory_has_valid_failed_thumbnail (thumbnail_factory, uri, mtime))
    g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Has failed thumbnail");
  else if (gnome_desktop_thumbnail_factory_can_thumbnail (thumbnail_factory, uri, mime_type, mtime))
    {
      pixbuf = gnome_desktop_thumbnail_factory_generate_thumbnail (thumbnail_factory, uri, mime_type);
      if (pixbuf)
        {
          // we need to save the thumbnail so that we don't need to generate it again in the future
          gnome_desktop_thumbnail_factory_save_thumbnail (thumbnail_factory, pixbuf, uri, mtime);
        }
      else
        {
          g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Failed to generate thumbnail");
          gnome_desktop_thumbnail_factory_create_failed_thumbnail (thumbnail_factory, uri, mtime);
        }
     }
   return pixbuf;
}
Beispiel #10
0
/**
 * gtk_source_file_check_file_on_disk:
 * @file: a #GtkSourceFile.
 *
 * Checks synchronously the file on disk, to know whether the file is externally
 * modified, or has been deleted, and whether the file is read-only.
 *
 * #GtkSourceFile doesn't create a #GFileMonitor to track those properties, so
 * this function needs to be called instead. Creating lots of #GFileMonitor's
 * would take lots of resources.
 *
 * Since this function is synchronous, it is advised to call it only on local
 * files. See gtk_source_file_is_local().
 *
 * Since: 3.18
 */
void
gtk_source_file_check_file_on_disk (GtkSourceFile *file)
{
	GFileInfo *info;

	if (file->priv->location == NULL)
	{
		return;
	}

	info = g_file_query_info (file->priv->location,
				  G_FILE_ATTRIBUTE_TIME_MODIFIED ","
				  G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE,
				  G_FILE_QUERY_INFO_NONE,
				  NULL,
				  NULL);

	if (info == NULL)
	{
		file->priv->deleted = TRUE;
		return;
	}

	if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_TIME_MODIFIED) &&
	    file->priv->modification_time_set)
	{
		GTimeVal timeval;

		g_file_info_get_modification_time (info, &timeval);

		/* Note that the modification time can even go backwards if the
		 * user is copying over an old file.
		 */
		if (timeval.tv_sec != file->priv->modification_time.tv_sec ||
		    timeval.tv_usec != file->priv->modification_time.tv_usec)
		{
			file->priv->externally_modified = TRUE;
		}
	}

	if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE))
	{
		gboolean readonly;

		readonly = !g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE);

		_gtk_source_file_set_readonly (file, readonly);
	}

	g_object_unref (info);
}
static void
gs_screenshot_soup_msg_set_modified_request (SoupMessage *msg, GFile *file)
{
	GTimeVal time_val;
	g_autoptr(GDateTime) date_time = NULL;
	g_autoptr(GFileInfo) info = NULL;
	g_autofree gchar *mod_date = NULL;

	info = g_file_query_info (file,
				  G_FILE_ATTRIBUTE_TIME_MODIFIED,
				  G_FILE_QUERY_INFO_NONE,
				  NULL,
				  NULL);
	if (info == NULL)
		return;
	g_file_info_get_modification_time (info, &time_val);
	date_time = g_date_time_new_from_timeval_local (&time_val);
	mod_date = g_date_time_format (date_time, "%a, %d %b %Y %H:%M:%S %Z");
	soup_message_headers_append (msg->request_headers,
				     "If-Modified-Since",
				     mod_date);
}
Beispiel #12
0
G_GNUC_INTERNAL gboolean
gcab_file_update_info (GCabFile *self, GFileInfo *info)
{
    GTimeVal tv;
    time_t time;
    struct tm *m; // Use GDateTime when 2.26 in RHEL6

    g_return_val_if_fail (GCAB_IS_FILE (self), FALSE);
    g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);

    g_file_info_get_modification_time (info, &tv);
    time = tv.tv_sec;
    m = localtime (&time);

    self->cfile.name = self->name;
    self->cfile.usize = g_file_info_get_size (info);
    self->cfile.fattr = GCAB_FILE_ATTRIBUTE_ARCH;
    self->cfile.date = ((m->tm_year + 1900 - 1980 ) << 9 ) +
        ((m->tm_mon+1) << 5 ) + (m->tm_mday);
    self->cfile.time = (m->tm_hour << 11) + (m->tm_min << 5) + (m->tm_sec / 2);

    return TRUE;
}
gboolean
e_reap_trash_directory_sync (GFile *trash_directory,
                             gint expiry_in_days,
                             GCancellable *cancellable,
                             GError **error)
{
	GFileEnumerator *file_enumerator;
	GQueue directories = G_QUEUE_INIT;
	GFile *reaping_directory;
	GFileInfo *file_info;
	const gchar *attributes;
	gboolean success = TRUE;
	GError *local_error = NULL;

	g_return_val_if_fail (G_IS_FILE (trash_directory), FALSE);
	g_return_val_if_fail (expiry_in_days > 0, FALSE);

	reaping_directory = g_file_get_child (
		trash_directory, REAPING_DIRECTORY_NAME);

	attributes =
		G_FILE_ATTRIBUTE_STANDARD_NAME ","
		G_FILE_ATTRIBUTE_STANDARD_TYPE ","
		G_FILE_ATTRIBUTE_TIME_MODIFIED;

	file_enumerator = g_file_enumerate_children (
		trash_directory, attributes,
		G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
		cancellable, error);

	if (file_enumerator == NULL)
		return FALSE;

	file_info = g_file_enumerator_next_file (
		file_enumerator, cancellable, &local_error);

	while (file_info != NULL) {
		GFileType file_type;
		GTimeVal mtime;
		GDate *date_now;
		GDate *date_mtime;
		const gchar *name;
		gboolean reap_it;
		gint days_old;

		name = g_file_info_get_name (file_info);
		file_type = g_file_info_get_file_type (file_info);
		g_file_info_get_modification_time (file_info, &mtime);

		/* Calculate how many days ago the file was modified. */
		date_now = g_date_new ();
		g_date_set_time_t (date_now, time (NULL));
		date_mtime = g_date_new ();
		g_date_set_time_val (date_mtime, &mtime);
		days_old = g_date_days_between (date_mtime, date_now);
		g_date_free (date_mtime);
		g_date_free (date_now);

		reap_it =
			(file_type == G_FILE_TYPE_DIRECTORY) &&
			(days_old >= expiry_in_days);

		if (reap_it) {
			GFile *child;

			child = g_file_get_child (trash_directory, name);

			/* If we find an unfinished reaping directory, put
			 * it on the head of the queue so we reap it first. */
			if (g_file_equal (child, reaping_directory))
				g_queue_push_head (&directories, child);
			else
				g_queue_push_tail (&directories, child);
		}

		g_object_unref (file_info);

		file_info = g_file_enumerator_next_file (
			file_enumerator, cancellable, &local_error);
	}

	if (local_error != NULL) {
		g_propagate_error (error, local_error);
		success = FALSE;
	}

	g_object_unref (file_enumerator);

	/* Now delete the directories we've queued up. */
	while (success && !g_queue_is_empty (&directories)) {
		GFile *directory;

		directory = g_queue_pop_head (&directories);

		/* First we rename the directory to prevent it
		 * from being recovered while being deleted. */
		if (!g_file_equal (directory, reaping_directory))
			success = g_file_move (
				directory, reaping_directory,
				G_FILE_COPY_NONE, cancellable,
				NULL, NULL, error);

		if (success)
			success = e_file_recursive_delete_sync (
				reaping_directory, cancellable, error);

		g_object_unref (directory);
	}

	/* Flush the queue in case we aborted on an error. */
	while (!g_queue_is_empty (&directories))
		g_object_unref (g_queue_pop_head (&directories));

	g_object_unref (reaping_directory);

	return success;
}
/**
 * Read content of file or create file list from directory
 * @param aBuf read destination buffer
 * @param aCount length of destination buffer
 * @param aCountRead number of read characters
 * @return NS_OK when read successfully, NS_BASE_STREAM_CLOSED when end of file,
 *         error code otherwise
 */
nsresult
nsGIOInputStream::DoRead(char *aBuf, uint32_t aCount, uint32_t *aCountRead)
{
  nsresult rv = NS_ERROR_NOT_AVAILABLE;
  if (mStream) {
    // file read
    GError *error = nullptr;    
    uint32_t bytes_read = g_input_stream_read(G_INPUT_STREAM(mStream),
                                              aBuf,
                                              aCount,
                                              nullptr,
                                              &error);
    if (error) {
      rv = MapGIOResult(error);
      *aCountRead = 0;
      g_warning("Cannot read from file: %s", error->message);
      g_error_free(error);
      return rv;
    }
    *aCountRead = bytes_read;
    mBytesRemaining -= *aCountRead;
    return NS_OK;
  }
  else if (mDirOpen) {
    // directory read
    while (aCount && rv != NS_BASE_STREAM_CLOSED)
    {
      // Copy data out of our buffer
      uint32_t bufLen = mDirBuf.Length() - mDirBufCursor;
      if (bufLen)
      {
        uint32_t n = std::min(bufLen, aCount);
        memcpy(aBuf, mDirBuf.get() + mDirBufCursor, n);
        *aCountRead += n;
        aBuf += n;
        aCount -= n;
        mDirBufCursor += n;
      }

      if (!mDirListPtr)    // Are we at the end of the directory list?
      {
        rv = NS_BASE_STREAM_CLOSED;
      }
      else if (aCount)     // Do we need more data?
      {
        GFileInfo *info = (GFileInfo *) mDirListPtr->data;

        // Prune '.' and '..' from directory listing.
        const char * fname = g_file_info_get_name(info);
        if (fname && fname[0] == '.' && 
            (fname[1] == '\0' || (fname[1] == '.' && fname[2] == '\0')))
        {
          mDirListPtr = mDirListPtr->next;
          continue;
        }

        mDirBuf.AssignLiteral("201: ");

        // The "filename" field
        nsCString escName;
        nsCOMPtr<nsINetUtil> nu = do_GetService(NS_NETUTIL_CONTRACTID);
        if (nu && fname) {
          nu->EscapeString(nsDependentCString(fname),
                           nsINetUtil::ESCAPE_URL_PATH, escName);

          mDirBuf.Append(escName);
          mDirBuf.Append(' ');
        }

        // The "content-length" field
        // XXX truncates size from 64-bit to 32-bit
        mDirBuf.AppendInt(int32_t(g_file_info_get_size(info)));
        mDirBuf.Append(' ');

        // The "last-modified" field
        //
        // NSPR promises: PRTime is compatible with time_t
        // we just need to convert from seconds to microseconds
        GTimeVal gtime;
        g_file_info_get_modification_time(info, &gtime);

        PRExplodedTime tm;
        PRTime pt = ((PRTime) gtime.tv_sec) * 1000000;
        PR_ExplodeTime(pt, PR_GMTParameters, &tm);
        {
          char buf[64];
          PR_FormatTimeUSEnglish(buf, sizeof(buf),
              "%a,%%20%d%%20%b%%20%Y%%20%H:%M:%S%%20GMT ", &tm);
          mDirBuf.Append(buf);
        }

        // The "file-type" field
        switch (g_file_info_get_file_type(info))
        {
          case G_FILE_TYPE_REGULAR:
            mDirBuf.AppendLiteral("FILE ");
            break;
          case G_FILE_TYPE_DIRECTORY:
            mDirBuf.AppendLiteral("DIRECTORY ");
            break;
          case G_FILE_TYPE_SYMBOLIC_LINK:
            mDirBuf.AppendLiteral("SYMBOLIC-LINK ");
            break;
          default:
            break;
        }
        mDirBuf.Append('\n');

        mDirBufCursor = 0;
        mDirListPtr = mDirListPtr->next;
      }
    }
  }
  return rv;
}
static void
get_folder_content_done_cb (GError   *error,
		            gpointer  user_data)
{
	LoadData             *load_data = user_data;
	FrFileSelectorDialog *self = load_data->dialog;
	GtkListStore         *list_store;
	GList                *scan;
	GtkTreeIter           iter;
	GDateTime            *today;
	int                   sort_column_id;
	GtkSortType           sort_order;
	GHashTable           *selected_files;

	if (error != NULL) {
		if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_MOUNTED)) {
			GMountOperation *operation;

			operation = gtk_mount_operation_new (GTK_WINDOW (self));
			g_file_mount_enclosing_volume (load_data->folder,
						       G_MOUNT_MOUNT_NONE,
						       operation,
						       load_data->cancellable,
						       folder_mount_enclosing_volume_ready_cb,
						       load_data);

			g_object_unref (operation);

			return;
		}

		if (! g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
			_gtk_error_dialog_run (GTK_WINDOW (self), _("Could not load the location"), "%s", error->message);

		if (load_data->dialog->priv->current_operation == load_data)
			load_data->dialog->priv->current_operation = NULL;
		load_data_free (load_data);

		return;
	}

	load_data->files = g_list_reverse (load_data->files);

	today = g_date_time_new_now_local ();

	gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (GET_WIDGET ("files_liststore")), &sort_column_id, &sort_order);
	gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (GET_WIDGET ("files_liststore")), GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID, 0);

	selected_files = g_hash_table_new (g_file_hash, (GEqualFunc) g_file_equal);
	for (scan = load_data->files_to_select; scan; scan = scan->next)
		g_hash_table_insert(selected_files, scan->data, GINT_TO_POINTER (1));

	list_store = GTK_LIST_STORE (GET_WIDGET ("files_liststore"));
	gtk_list_store_clear (list_store);
	for (scan = load_data->files; scan; scan = scan->next) {
		FileInfo  *file_info = scan->data;
		GdkPixbuf *icon_pixbuf;
		char      *size;
		GTimeVal   timeval;
		GDateTime *datetime;
		char      *modified;
		char      *collate_key;
		gboolean   is_folder;

		if (! self->priv->show_hidden && g_file_info_get_is_hidden (file_info->info))
			continue;

		gtk_list_store_append (list_store, &iter);

		icon_pixbuf = gth_icon_cache_get_pixbuf (self->priv->icon_cache, g_file_info_get_icon (file_info->info));
		size = g_format_size (g_file_info_get_size (file_info->info));
		g_file_info_get_modification_time (file_info->info, &timeval);
		datetime = g_date_time_new_from_timeval_local (&timeval);
		modified = g_date_time_format (datetime, _g_date_time_same_day (datetime, today) ? "%X" : "%x");
		collate_key = g_utf8_collate_key_for_filename (g_file_info_get_display_name (file_info->info), -1);
		is_folder = (g_file_info_get_file_type (file_info->info) == G_FILE_TYPE_DIRECTORY);

		gtk_list_store_set (list_store, &iter,
				    FILE_LIST_COLUMN_ICON, icon_pixbuf,
				    FILE_LIST_COLUMN_NAME, g_file_info_get_display_name (file_info->info),
				    FILE_LIST_COLUMN_SIZE, (is_folder ? "" : size),
				    FILE_LIST_COLUMN_MODIFIED, modified,
				    FILE_LIST_COLUMN_FILE, file_info->file,
				    FILE_LIST_COLUMN_NAME_ORDER, collate_key,
				    FILE_LIST_COLUMN_SIZE_ORDER, g_file_info_get_size (file_info->info),
				    FILE_LIST_COLUMN_MODIFIED_ORDER, timeval.tv_sec,
				    FILE_LIST_COLUMN_IS_FOLDER, is_folder,
				    FILE_LIST_COLUMN_IS_SELECTED, (g_hash_table_lookup (selected_files, file_info->file) != NULL),
				    -1);

		g_free (collate_key);
		g_free (modified);
		g_date_time_unref (datetime);
		g_free (size);
		_g_object_unref (icon_pixbuf);
	}

	gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (GET_WIDGET ("files_liststore")), sort_column_id, sort_order);
	set_current_folder (self, load_data->folder);

	if (load_data->dialog->priv->current_operation == load_data)
		load_data->dialog->priv->current_operation = NULL;

	g_hash_table_unref (selected_files);
	g_date_time_unref (today);
	load_data_free (load_data);
}
Beispiel #16
0
static gboolean
cheese_thumb_view_idle_append_item (gpointer data)
{
  CheeseThumbViewIdleData *item = g_queue_peek_head (data);
  CheeseThumbView         *thumb_view;
  CheeseThumbViewPrivate  *priv;

  /* Disconnect the idle handler when the queue is empty. */
  if (item == NULL) return FALSE;

  thumb_view = item->thumb_view;
  priv = cheese_thumb_view_get_instance_private (thumb_view);


  GnomeDesktopThumbnailFactory *factory = priv->factory;
  GFile                        *file    = item->file;
  GtkTreeIter                   iter    = item->iter;
  GdkPixbuf                    *pixbuf  = NULL;
  GFileInfo                    *info;
  char                         *thumb_loc;
  GTimeVal                      mtime;
  char                         *mime_type;
  char                         *uri;
  char                         *filename;

  info = g_file_query_info (file, "standard::content-type,time::modified", 0, NULL, NULL);

  if (!info)
  {
    g_warning ("Invalid filename\n");
    return TRUE;
  }
  g_file_info_get_modification_time (info, &mtime);
  mime_type = g_strdup (g_file_info_get_content_type (info));

  uri      = g_file_get_uri (file);
  filename = g_file_get_path (file);

  thumb_loc = gnome_desktop_thumbnail_factory_lookup (factory, uri, mtime.tv_sec);

  if (!thumb_loc)
  {
    pixbuf = gnome_desktop_thumbnail_factory_generate_thumbnail (factory, uri, mime_type);
    if (!pixbuf)
    {
      g_warning ("could not generate thumbnail for %s (%s)\n", filename, mime_type);
    }
    else
    {
      gnome_desktop_thumbnail_factory_save_thumbnail (factory, pixbuf, uri, mtime.tv_sec);
    }
  }
  else
  {
    pixbuf = gdk_pixbuf_new_from_file (thumb_loc, NULL);
    if (!pixbuf)
    {
      g_warning ("could not load thumbnail %s (%s)\n", filename, mime_type);
    }
  }
  g_object_unref (info);
  g_free (thumb_loc);
  g_free (uri);

  if (!pixbuf)
  {
    gchar  *escape = NULL;
    GError *error  = NULL;
    escape = g_strrstr (mime_type, "/");
    if (escape != NULL) *escape = '-';
    pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
                                       mime_type,
                                       96,
                                       GTK_ICON_LOOKUP_GENERIC_FALLBACK,
                                       &error);
    if (error)
    {
      g_warning ("%s", error->message);
      return TRUE;
    }
  }
  else
  {
    cheese_thumbnail_add_frame (&pixbuf);
  }

  gtk_list_store_set (priv->store, &iter,
                      THUMBNAIL_PIXBUF_COLUMN, pixbuf, -1);

  g_free (mime_type);
  g_free (filename);
  g_object_unref (pixbuf);
  g_object_unref (file);
  g_slice_free (CheeseThumbViewIdleData, item);
  g_queue_pop_head (data);

  return TRUE;
}
void vfs_backend_get_file_info (const gchar *cBaseURI, gchar **cName, gchar **cURI, gchar **cIconName, gboolean *bIsDirectory, int *iVolumeID, double *fOrder, CairoDockFMSortType iSortType)
{
	g_return_if_fail (cBaseURI != NULL);
	GError *erreur = NULL;
	cd_message ("%s (%s)", __func__, cBaseURI);
	
	gchar *cFullURI;
	if (strncmp (cBaseURI, "x-nautilus-desktop://", 21) == 0)
	{
		gchar *cNautilusFile = g_strdup (cBaseURI+14);
		memcpy (cNautilusFile, "file", 4);
		if (g_str_has_suffix (cBaseURI, ".volume"))
		{
			cNautilusFile[strlen(cNautilusFile)-7] = '\0';
		}
		else if (g_str_has_suffix (cBaseURI, ".drive"))
		{
			cNautilusFile[strlen(cNautilusFile)-6] = '\0';
		}
		cFullURI = g_filename_from_uri (cNautilusFile, NULL, &erreur);
		if (erreur != NULL)
		{
			cd_warning ("gnome_integration : %s", erreur->message);
			g_error_free (erreur);
			return ;
		}
		gchar *cVolumeName = cFullURI + 1;  // on saute le '/'.
		cd_message ("cVolumeName : %s", cVolumeName);
		
		GMount *pMount = NULL;
		_cd_find_mount_from_volume_name (cVolumeName, &pMount, cURI, cIconName);
		g_return_if_fail (pMount != NULL);
		
		*cName = g_strdup (cVolumeName);
		*bIsDirectory = TRUE;
		*iVolumeID = 1;
		*fOrder = 0;
		//g_object_unref (pMount);
		
		g_free (cFullURI);
		//g_free (cNautilusFile);
		return;
	}
	else
	{
		if (*cBaseURI == '/')
			cFullURI = g_filename_to_uri (cBaseURI, NULL, NULL);
		else
			cFullURI = g_strdup (cBaseURI);
	}
	cd_message (" -> cFullURI : %s", cFullURI);
	
	GFile *pFile = g_file_new_for_uri (cFullURI);
	
	const gchar *cQuery = G_FILE_ATTRIBUTE_STANDARD_TYPE","
		G_FILE_ATTRIBUTE_STANDARD_SIZE","
		G_FILE_ATTRIBUTE_TIME_MODIFIED","
		G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE","
		G_FILE_ATTRIBUTE_STANDARD_NAME","
		G_FILE_ATTRIBUTE_STANDARD_ICON","
		G_FILE_ATTRIBUTE_STANDARD_TARGET_URI","
		G_FILE_ATTRIBUTE_MOUNTABLE_UNIX_DEVICE;
	GFileInfo *pFileInfo = g_file_query_info (pFile,
		cQuery,
		G_FILE_QUERY_INFO_NONE,  /// G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS
		NULL,
		&erreur);
	//g_object_unref (pFile);
	if (erreur != NULL)
	{
		cd_warning ("gnome_integration : %s", erreur->message);
		g_error_free (erreur);
		return ;
	}
	
	*cURI = cFullURI;
	const gchar *cFileName = g_file_info_get_name (pFileInfo);
	const gchar *cMimeType = g_file_info_get_content_type (pFileInfo);
	GFileType iFileType = g_file_info_get_file_type (pFileInfo);
	
	if (iSortType == CAIRO_DOCK_FM_SORT_BY_DATE)
	{
		GTimeVal t;
		g_file_info_get_modification_time (pFileInfo, &t);
		*fOrder = t.tv_sec;
	}
	else if (iSortType == CAIRO_DOCK_FM_SORT_BY_SIZE)
		*fOrder = g_file_info_get_size (pFileInfo);
	else if (iSortType == CAIRO_DOCK_FM_SORT_BY_TYPE)
		*fOrder = (cMimeType != NULL ? *((int *) cMimeType) : 0);
	else
		*fOrder = 0;
	
	*bIsDirectory = (iFileType == G_FILE_TYPE_DIRECTORY);
	cd_message (" => '%s' (mime:%s ; bIsDirectory:%d)", cFileName, cMimeType, *bIsDirectory);
	
	if (iFileType == G_FILE_TYPE_MOUNTABLE)
	{
		*cName = NULL;
		*iVolumeID = 1;
		
		const gchar *cTargetURI = g_file_info_get_attribute_string (pFileInfo, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI);
		cd_message ("  cTargetURI:%s", cTargetURI);
		GMount *pMount = NULL;
		if (cTargetURI != NULL)
		{
			GFile *file = g_file_new_for_uri (cTargetURI);
			pMount = g_file_find_enclosing_mount (file, NULL, NULL);
			//g_object_unref (file);
		}
		if (pMount != NULL)
		{
			*cName = g_mount_get_name (pMount);
			cd_message ("un GMount existe (%s)",* cName);
		}
		else
		{
			gchar *cMountName = g_strdup (cFileName);
			gchar *str = strrchr (cMountName, '.');  // on vire l'extension ".volume" ou ".drive".
			if (str != NULL)
			{
				*str = '\0';
				if (strcmp (str+1, "link") == 0)  // pour les liens, on prend le nom du lien.
				{
					if (strcmp (cMountName, "root") == 0)  // on remplace 'root' par un nom plus parlant, sinon on prendra le nom du lien.
					{
						*cName = g_strdup ("/");
					}
				}
				else if (strcmp (str+1, "drive") == 0)  // on cherche un nom plus parlant si possible.
				{
					gchar *cVolumeName = _cd_find_volume_name_from_drive_name (cMountName);
					if (cVolumeName != NULL)
					{
						*cName = cVolumeName;
					}
				}
			}
			if (*cName == NULL)
				*cName = cMountName;
			//else
				//g_free (cMountName);
		}
		if (*cName ==  NULL)
			*cName = g_strdup (cFileName);
	}
	else
	{
		*iVolumeID = 0;
		*cName = g_strdup (cFileName);
	}
	
	*cIconName = NULL;
	if (cMimeType != NULL && strncmp (cMimeType, "image", 5) == 0)
	{
		gchar *cHostname = NULL;
		GError *erreur = NULL;
		gchar *cFilePath = g_filename_from_uri (cBaseURI, &cHostname, &erreur);
		if (erreur != NULL)
		{
			g_error_free (erreur);
		}
		else if (cHostname == NULL || strcmp (cHostname, "localhost") == 0)  // on ne recupere la vignette que sur les fichiers locaux.
		{
			*cIconName = g_strdup (cFilePath);
			cairo_dock_remove_html_spaces (*cIconName);
		}
		//g_free (cHostname);
	}
	if (*cIconName == NULL)
	{
		GIcon *pSystemIcon = g_file_info_get_icon (pFileInfo);
		if (pSystemIcon != NULL)
		{
			*cIconName = _cd_get_icon_path (pSystemIcon);
		}
	}
	cd_message ("cIconName : %s", *cIconName);
	
	//*iVolumeID = g_file_info_get_attribute_uint32 (pFileInfo, G_FILE_ATTRIBUTE_MOUNTABLE_UNIX_DEVICE);
	//cd_message ("ID : %d\n", *iVolumeID);
	//g_object_unref (pFileInfo);
}
GList *vfs_backend_list_directory (const gchar *cBaseURI, CairoDockFMSortType iSortType, int iNewIconsType, gboolean bListHiddenFiles, gchar **cFullURI)
{
	g_return_val_if_fail (cBaseURI != NULL, NULL);
	cd_message ("%s (%s)", __func__, cBaseURI);
	
	gchar *cURI;
	gboolean bAddHome = FALSE;
	if (strcmp (cBaseURI, CAIRO_DOCK_FM_VFS_ROOT) == 0)
	{
		cURI = g_strdup ("computer://");
		bAddHome = TRUE;
		///*cFullURI = cURI;
		///return vfs_backend_list_volumes ();
		//vfs_backend_list_volumes ();
	}
	else if (strcmp (cBaseURI, CAIRO_DOCK_FM_NETWORK) == 0)
		cURI = g_strdup ("network://");
	else
		cURI = (*cBaseURI == '/' ? g_strconcat ("file://", cBaseURI, NULL) : g_strdup (cBaseURI));
	*cFullURI = cURI;
	
	GFile *pFile = g_file_new_for_uri (cURI);
	GError *erreur = NULL;
	const gchar *cAttributes = G_FILE_ATTRIBUTE_STANDARD_TYPE","
		G_FILE_ATTRIBUTE_STANDARD_SIZE","
		G_FILE_ATTRIBUTE_TIME_MODIFIED","
		G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE","
		G_FILE_ATTRIBUTE_STANDARD_NAME","
		G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN","
		G_FILE_ATTRIBUTE_STANDARD_ICON","
		G_FILE_ATTRIBUTE_STANDARD_TARGET_URI","
		G_FILE_ATTRIBUTE_MOUNTABLE_UNIX_DEVICE;
	GFileEnumerator *pFileEnum = g_file_enumerate_children (pFile,
		cAttributes,
		G_FILE_QUERY_INFO_NONE,  /// G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS
		NULL,
		&erreur);
	//g_object_unref (pFile);
	if (erreur != NULL)
	{
		cd_warning ("gnome_integration : %s", erreur->message);
		g_error_free (erreur);
		return NULL;
	}
	
	int iOrder = 0;
	GList *pIconList = NULL;
	Icon *icon;
	GFileInfo *pFileInfo;
	do
	{
		pFileInfo = g_file_enumerator_next_file (pFileEnum, NULL, &erreur);
		if (erreur != NULL)
		{
			cd_warning ("gnome_integration : %s", erreur->message);
			g_error_free (erreur);
			erreur = NULL;
			continue;
		}
		if (pFileInfo == NULL)
			break ;
		
		gboolean bIsHidden = g_file_info_get_is_hidden (pFileInfo);
		if (bListHiddenFiles || ! bIsHidden)
		{
			GFileType iFileType = g_file_info_get_file_type (pFileInfo);
			GIcon *pFileIcon = g_file_info_get_icon (pFileInfo);
			if (pFileIcon == NULL)
			{
				cd_message ("AUCUNE ICONE");
				continue;
			}
			const gchar *cFileName = g_file_info_get_name (pFileInfo);
			const gchar *cMimeType = g_file_info_get_content_type (pFileInfo);
			gchar *cName = NULL;
			
			icon = g_new0 (Icon, 1);
			icon->iType = iNewIconsType;
			icon->cBaseURI = g_strconcat (*cFullURI, "/", cFileName, NULL);
			cd_message ("+ %s (mime:%s)", icon->cBaseURI, cMimeType);
			
			if (iFileType == G_FILE_TYPE_MOUNTABLE)
			{
				const gchar *cTargetURI = g_file_info_get_attribute_string (pFileInfo, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI);
				cd_message ("  c'est un point de montage correspondant a %s", cTargetURI);
				
				GMount *pMount = NULL;
				if (cTargetURI != NULL)
				{
					icon->acCommand = g_strdup (cTargetURI);
					GFile *file = g_file_new_for_uri (cTargetURI);
					pMount = g_file_find_enclosing_mount (file, NULL, NULL);
					//g_object_unref (file);
				}
				if (pMount != NULL)
				{
					cName = g_mount_get_name (pMount);
					cd_message ("un GMount existe (%s)", cName);
					
					GVolume *volume = g_mount_get_volume (pMount);
					if (volume)
						cd_message ("  volume associe : %s", g_volume_get_name (volume));
					GDrive *drive = g_mount_get_drive (pMount);
					if (drive)
						cd_message ("  disque associe : %s", g_drive_get_name (drive));
					
					///pFileIcon = g_mount_get_icon (pMount);
				}
				else
				{
					cName = g_strdup (cFileName);
					gchar *str = strrchr (cName, '.');  // on vire l'extension ".volume" ou ".drive".
					if (str != NULL)
					{
						*str = '\0';
						if (strcmp (str+1, "link") == 0)
						{
							if (strcmp (cName, "root") == 0)
							{
								g_free (cName);
								cName = g_strdup ("/");
							}
						}
						else if (strcmp (str+1, "drive") == 0)  // on cherche un nom plus parlant si possible.
						{
							gchar *cVolumeName = _cd_find_volume_name_from_drive_name (cName);
							if (cVolumeName != NULL)
							{
								g_free (cName);
								g_free (cVolumeName);
								continue;  /// apparemment il n'est plus necessaire d'afficher les .drives qui ont 1 (ou plusieurs ?) volumes, car ces derniers sont dans la liste, donc ca fait redondant.
								/**if (strcmp (cVolumeName, "discard") == 0)
									continue;
								g_free (cName);
								cName = cVolumeName;*/
							}
						}
					}
				}
				icon->iVolumeID = 1;
				cd_message ("le nom de ce volume est : %s", cName);
			}
			else
				cName = g_strdup (cFileName);
			
			if (icon->acCommand == NULL)
				icon->acCommand = g_strdup (icon->cBaseURI);
			icon->acName = cName;
			icon->acFileName = NULL;
			if (cMimeType != NULL && strncmp (cMimeType, "image", 5) == 0)
			{
				gchar *cHostname = NULL;
				gchar *cFilePath = g_filename_from_uri (icon->cBaseURI, &cHostname, &erreur);
				if (erreur != NULL)
				{
					g_error_free (erreur);
					erreur = NULL;
				}
				else if (cHostname == NULL || strcmp (cHostname, "localhost") == 0)  // on ne recupere la vignette que sur les fichiers locaux.
				{
					icon->acFileName = g_strdup (cFilePath);
					cairo_dock_remove_html_spaces (icon->acFileName);
				}
				g_free (cHostname);
				g_free (cFilePath);
			}
			if (icon->acFileName == NULL)
			{
				icon->acFileName = _cd_get_icon_path (pFileIcon);
				cd_message ("icon->acFileName : %s", icon->acFileName);
			}
			
			if (iSortType == CAIRO_DOCK_FM_SORT_BY_SIZE)
				icon->fOrder = g_file_info_get_size (pFileInfo);
			else if (iSortType == CAIRO_DOCK_FM_SORT_BY_DATE)
			{
				GTimeVal t;
				g_file_info_get_modification_time (pFileInfo, &t);
				icon->fOrder = t.tv_sec;
			}
			else if (iSortType == CAIRO_DOCK_FM_SORT_BY_TYPE)
				icon->fOrder = (cMimeType != NULL ? *((int *) cMimeType) : 0);
			if (icon->fOrder == 0)  // un peu moyen mais mieux que rien non ?
				icon->fOrder = iOrder;
			pIconList = g_list_insert_sorted (pIconList,
				icon,
				(GCompareFunc) cairo_dock_compare_icons_order);
			//g_list_prepend (pIconList, icon);
			iOrder ++;
		}
	} while (TRUE);  // 'g_file_enumerator_close' est appelee lors du dernier 'g_file_enumerator_next_file'.
	
	if (bAddHome && pIconList != NULL)
	{
		icon = g_new0 (Icon, 1);
		icon->iType = iNewIconsType;
		icon->cBaseURI = g_strdup_printf ("file://%s", "/home");
		icon->acCommand = g_strdup ("/home");
		//icon->acCommand = g_strdup (icon->cBaseURI);
		icon->iVolumeID = 0;
		icon->acName = g_strdup ("home");
		Icon *pRootIcon = cairo_dock_get_icon_with_name (pIconList, "/");
		if (pRootIcon == NULL)
		{
			pRootIcon = cairo_dock_get_first_icon (pIconList);
			g_print ("domage ! (%s:%s)\n", pRootIcon->acCommand, pRootIcon->acName);
		}
		icon->acFileName = g_strdup (pRootIcon->acFileName);
		icon->fOrder = iOrder++;
		pIconList = g_list_insert_sorted (pIconList,
			icon,
			(GCompareFunc) cairo_dock_compare_icons_order);
	}
	
	if (iSortType == CAIRO_DOCK_FM_SORT_BY_NAME)
		pIconList = cairo_dock_sort_icons_by_name (pIconList);
	else
		pIconList = cairo_dock_sort_icons_by_order (pIconList);
	
	return pIconList;
}
static void queryInfoCallback(GObject* source, GAsyncResult* res, gpointer data)
{
    ResourceHandle* handle = static_cast<ResourceHandle*>(data);
    ResourceHandleInternal* d = handle->getInternal();
    ResourceHandleClient* client = handle->client();

    if (d->m_cancelled) {
        cleanupGioOperation(handle);
        return;
    }

    ResourceResponse response;

    char* uri = g_file_get_uri(d->m_gfile);
    response.setUrl(KURL(uri));
    g_free(uri);

    GError *error = NULL;
    GFileInfo* info = g_file_query_info_finish(d->m_gfile, res, &error);

    if (error) {
        // FIXME: to be able to handle ftp URIs properly, we must
        // check if the error is G_IO_ERROR_NOT_MOUNTED, and if so,
        // call g_file_mount_enclosing_volume() to mount the ftp
        // server (and then keep track of the fact that we mounted it,
        // and set a timeout to unmount it later after it's been idle
        // for a while).

        cleanupGioOperation(handle);

        if (error->domain == G_IO_ERROR &&
                error->code == G_IO_ERROR_NOT_FOUND)
            response.setHTTPStatusCode(SOUP_STATUS_NOT_FOUND);
        else if (error->domain == G_IO_ERROR &&
                 error->code == G_IO_ERROR_PERMISSION_DENIED)
            response.setHTTPStatusCode(SOUP_STATUS_FORBIDDEN);
        else
            response.setHTTPStatusCode(SOUP_STATUS_BAD_REQUEST); // ?
        g_error_free(error);

        // FIXME: do we need to fake up a response body containing the
        // error message?

        client->didReceiveResponse(handle, response);
        client->didFinishLoading(handle);
        return;
    }

    if (g_file_info_get_file_type(info) != G_FILE_TYPE_REGULAR) {
        // FIXME: what if the URI points to a directory? Should we
        // generate a listing? How? What do other backends do here?

        cleanupGioOperation(handle);
        response.setHTTPStatusCode(SOUP_STATUS_FORBIDDEN); // ?
        client->didReceiveResponse(handle, response);
        client->didFinishLoading(handle);
        return;
    }

    response.setMimeType(g_file_info_get_content_type(info));
    response.setExpectedContentLength(g_file_info_get_size(info));
    response.setHTTPStatusCode(SOUP_STATUS_OK);

    GTimeVal tv;
    g_file_info_get_modification_time(info, &tv);
    response.setLastModifiedDate(tv.tv_sec);

    client->didReceiveResponse(handle, response);

    g_file_read_async(d->m_gfile, G_PRIORITY_DEFAULT, d->m_cancellable,
                      openCallback, handle);
}
static gboolean
log_load (GIOSchedulerJob *io_job,
          GCancellable *cancellable,
          gpointer user_data)
{
  /* this runs in a separate i/o thread */
  LoadJob *job = user_data;
  LogviewLog *log = job->log;
  GFile *f = log->priv->file;
  GFileInfo *info;
  GInputStream *is;
  const char *peeked_buffer;
  const char * parse_data[2];
  GSList *days;
  const char *content_type;
  GFileType type;
  GError *err = NULL;
  GTimeVal timeval;
  gboolean is_archive, can_read;

  info = g_file_query_info (f,
                            G_FILE_ATTRIBUTE_ACCESS_CAN_READ ","
                            G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE ","
                            G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME ","
                            G_FILE_ATTRIBUTE_STANDARD_TYPE ","
                            G_FILE_ATTRIBUTE_STANDARD_SIZE ","
                            G_FILE_ATTRIBUTE_TIME_MODIFIED ",",
                            0, NULL, &err);
  if (err) {
    if (err->code == G_IO_ERROR_PERMISSION_DENIED) {
      /* TODO: PolicyKit integration */
    }
    goto out;
  }

  can_read = g_file_info_get_attribute_boolean (info,
                                                G_FILE_ATTRIBUTE_ACCESS_CAN_READ);
  if (!can_read) {
    /* TODO: PolicyKit integration */
    err = g_error_new_literal (LOGVIEW_ERROR_QUARK, LOGVIEW_ERROR_PERMISSION_DENIED,
                               _("You don't have enough permissions to read the file."));
    g_object_unref (info);

    goto out;
  }

  type = g_file_info_get_file_type (info);
  content_type = g_file_info_get_content_type (info);

  is_archive = g_content_type_equals (content_type, "application/x-gzip");

  if (type != (G_FILE_TYPE_REGULAR || G_FILE_TYPE_SYMBOLIC_LINK) ||
      (!g_content_type_is_a (content_type, "text/plain") && !is_archive))
  {
    err = g_error_new_literal (LOGVIEW_ERROR_QUARK, LOGVIEW_ERROR_NOT_A_LOG,
                               _("The file is not a regular file or is not a text file."));
    g_object_unref (info);

    goto out;
  }

  log->priv->file_size = g_file_info_get_size (info);
  g_file_info_get_modification_time (info, &timeval);
  log->priv->file_time = timeval.tv_sec;
  log->priv->display_name = g_strdup (g_file_info_get_display_name (info));

  g_object_unref (info);

  /* initialize the stream */
  is = G_INPUT_STREAM (g_file_read (f, NULL, &err));

  if (err) {
    if (err->code == G_IO_ERROR_PERMISSION_DENIED) {
      /* TODO: PolicyKit integration */
    }

    goto out;
  }

  if (is_archive) {
#ifdef HAVE_ZLIB
    GZHandle *gz;
    gboolean res;
    guchar * buffer;
    gsize bytes_read;
    GInputStream *real_is;
    time_t mtime; /* seconds */

    /* this also skips the header from |is| */
    res = read_gzip_header (is, &mtime);

    if (!res) {
      g_object_unref (is);

      err = create_zlib_error ();
      goto out;
    }

    log->priv->file_time = mtime;

    gz = gz_handle_new (f, is);
    res = gz_handle_init (gz);

    if (!res) {
      g_object_unref (is);
      gz_handle_free (gz);

      err = create_zlib_error ();
      goto out;
    }

    real_is = g_memory_input_stream_new ();

    do {
      buffer = g_malloc (1024);
      res = gz_handle_read (gz, buffer, 1024, &bytes_read);
      g_memory_input_stream_add_data (G_MEMORY_INPUT_STREAM (real_is),
                                      buffer, bytes_read, g_free);
    } while (res == TRUE && bytes_read > 0);

    if (!res) {
      gz_handle_free (gz);
      g_object_unref (real_is);
      g_object_unref (is);

      err = create_zlib_error ();
      goto out;
    }
 
    g_object_unref (is);
    is = real_is;

    gz_handle_free (gz);
#else /* HAVE_ZLIB */
    g_object_unref (is);

    err = g_error_new_literal (LOGVIEW_ERROR_QUARK, LOGVIEW_ERROR_NOT_SUPPORTED,
                               _("This version of System Log does not support GZipped logs."));
    goto out;
#endif /* HAVE_ZLIB */
  }

  log->priv->stream = g_data_input_stream_new (is);

  /* sniff into the stream for a timestamped line */
  g_buffered_input_stream_fill (G_BUFFERED_INPUT_STREAM (log->priv->stream),
                                (gssize) g_buffered_input_stream_get_buffer_size (G_BUFFERED_INPUT_STREAM (log->priv->stream)),
                                NULL, &err);
  if (err == NULL) {
    peeked_buffer = g_buffered_input_stream_peek_buffer
        (G_BUFFERED_INPUT_STREAM (log->priv->stream), NULL);
    parse_data[0] = peeked_buffer;
    parse_data[1] = NULL;

    if ((days = log_read_dates (parse_data, time (NULL))) != NULL) {
      log->priv->has_days = TRUE;
      g_slist_foreach (days, (GFunc) logview_utils_day_free, NULL);
      g_slist_free (days);
    } else {
      log->priv->has_days = FALSE;
    }
  } else {
    log->priv->has_days = FALSE;
    g_clear_error (&err);
  }

  g_object_unref (is);

out:
  if (err) {
    job->err = err;
  }

  g_io_scheduler_job_send_to_mainloop_async (io_job,
                                             log_load_done,
                                             job, NULL);
  return FALSE;
}