コード例 #1
0
ファイル: fm-path.c プロジェクト: afilmore/libfmcore
// FIXME_pcm: maybe we can support different encoding for different mount points?
char *fm_path_display_basename (FmPath *path)
{
    if (G_UNLIKELY (!path->parent)) // root_path element
    {
        if (!fm_path_is_native (path) && fm_path_is_virtual (path))
        {
            if (fm_path_is_root (path) && fm_path_is_trash (path))
                return g_strdup (_("Trash Can"));
            
            //~ if (g_str_has_prefix (path->name, "computer:/"))
                //~ return g_strdup (_("My Computer"));
            
            if (fm_path_is_computer (path))
                return g_strdup (_("My Computer"));
            
            if (g_str_has_prefix (path->name, "menu:/"))
            {
                // FIXME_pcm: this should be more flexible
                const char *p = path->name + 5;
                
                while (p[0] == '/')
                    ++p;
                
                if (g_str_has_prefix (p, "applications.menu"))
                    return g_strdup (_("Applications"));
            }
            
            if (g_str_has_prefix (path->name, "network:/"))
                return g_strdup (_("Network"));
        }
    }
    return g_filename_display_name (path->name);
}
コード例 #2
0
static gboolean fm_dir_list_job_run(FmJob* fmjob)
{
    gboolean ret;
    FmDirListJob* job = FM_DIR_LIST_JOB(fmjob);
    g_return_val_if_fail(job->dir_path != NULL, FALSE);
    if(fm_path_is_native(job->dir_path)) /* if this is a native file on real file system */
        ret = fm_dir_list_job_run_posix(job);
    else /* this is a virtual path or remote file system path */
        ret = fm_dir_list_job_run_gio(job);
    return ret;
}
コード例 #3
0
ファイル: fm-path.c プロジェクト: juergenhoetzel/libfm
GFile* fm_path_to_gfile(FmPath* path)
{
	GFile* gf;
	char* str;
	str = fm_path_to_str(path);
	if(fm_path_is_native(path))
		gf = g_file_new_for_path(str);
	else
		gf = g_file_new_for_uri(str);
	g_free(str);
	return gf;
}
コード例 #4
0
ファイル: fm-dnd-dest.c プロジェクト: engla/libfm
inline static
gboolean cache_src_file_infos(FmDndDest* dd, GtkWidget *dest_widget,
                        gint x, gint y, GdkDragContext *drag_context)
{
    GdkAtom target;
    target = gtk_drag_dest_find_target( dest_widget, drag_context, NULL );
    if( target != GDK_NONE )
    {
        GdkDragAction action;
        gboolean ret;
        /* treat X direct save as a special case. */
        if( target == gdk_atom_intern_static_string("XdndDirectSave0") )
        {
            /* FIXME: need a better way to handle this. */
            action = drag_context->suggested_action;
            g_signal_emit(dd, signals[QUERY_INFO], 0, x, y, &action, &ret);

            gdk_drag_status(drag_context, action, time);
            return TRUE;
        }

        /* g_debug("try to cache src_files"); */
        dd->mainloop = g_main_loop_new(NULL, TRUE);
        gtk_drag_get_data(dest_widget, drag_context, target, time);
        /* run the main loop to block here waiting for
         * 'drag-data-received' signal being handled first. */
        /* it's possible that g_main_loop_quit is called before we really run the loop. */
        if(g_main_loop_is_running(dd->mainloop))
            g_main_loop_run(dd->mainloop);
        g_main_loop_unref(dd->mainloop);
        dd->mainloop = NULL;
        /* g_debug("src_files cached: %p", dd->src_files); */

        /* dd->src_files should be set now */
        if( dd->src_files && fm_list_is_file_info_list(dd->src_files) )
        {
            /* cache file system id of source files */
            if( fm_file_info_list_is_same_fs(dd->src_files) )
            {
                FmFileInfo* fi = (FmFileInfo*)fm_list_peek_head(dd->src_files);
                if(fm_path_is_native(fi->path))
                    dd->src_dev = fi->dev;
                else
                    dd->src_fs_id = fi->fs_id;
            }
        }
    }
    return FALSE;
}
コード例 #5
0
ファイル: fm-places-model.c プロジェクト: geekless/libfm
static void add_bookmarks(FmPlacesModel* model, FmFileInfoJob* job)
{
    FmPlaceItem* item;
    GList *bms, *l;
    FmIcon* icon = fm_icon_from_name("folder");
    FmIcon* remote_icon = NULL;
    GdkPixbuf* folder_pix = fm_icon_get_pixbuf(icon, fm_config->pane_icon_size);
    GdkPixbuf* remote_pix = NULL;
    bms = fm_bookmarks_list_all(model->bookmarks);
    for(l=bms;l;l=l->next)
    {
        FmBookmarkItem* bm = (FmBookmarkItem*)l->data;
        GtkTreeIter it;
        GdkPixbuf* pix;
        item = g_slice_new0(FmPlaceItem);
        item->type = FM_PLACES_ITEM_PATH;
        item->fi = fm_file_info_new();
        item->fi->path = fm_path_ref(bm->path);
        fm_file_info_job_add(job, item->fi->path);

        if(fm_path_is_native(item->fi->path))
        {
            item->fi->icon = fm_icon_ref(icon);
            pix = folder_pix;
        }
        else
        {
            if(G_UNLIKELY(!remote_icon))
            {
                remote_icon = fm_icon_from_name("folder-remote");
                remote_pix = fm_icon_get_pixbuf(remote_icon, fm_config->pane_icon_size);
            }
            item->fi->icon = fm_icon_ref(remote_icon);
            pix = remote_pix;
        }
        item->bm_item = bm;
        gtk_list_store_append(GTK_LIST_STORE(model), &it);
        gtk_list_store_set(GTK_LIST_STORE(model), &it, FM_PLACES_MODEL_COL_ICON, pix, FM_PLACES_MODEL_COL_LABEL, bm->name, FM_PLACES_MODEL_COL_INFO, item, -1);
    }
    g_object_unref(folder_pix);
    fm_icon_unref(icon);
    if(remote_icon)
    {
        fm_icon_unref(remote_icon);
        if(remote_pix)
            g_object_unref(remote_pix);
    }
}
コード例 #6
0
ファイル: fm-path.c プロジェクト: juergenhoetzel/libfm
/* FIXME: maybe we can support different encoding for different mount points? */
char* fm_path_display_basename(FmPath* path)
{
    if(G_UNLIKELY(!path->parent)) /* root element */
    {
        if( !fm_path_is_native(path) && fm_path_is_virtual(path) )
        {
            if(fm_path_is_trash_root(path))
                return g_strdup(_("Trash Can"));
            if(g_str_has_prefix(path->name, "computer:/"))
                return g_strdup(_("My Computer"));
            if(g_str_has_prefix(path->name, "applications:/"))
                return g_strdup(_("Applications"));
            if(g_str_has_prefix(path->name, "network:/"))
                return g_strdup(_("Network"));
        }
    }
    return g_filename_display_name(path->name);
}
コード例 #7
0
gboolean fm_deep_count_job_run(FmJob* job)
{
    FmDeepCountJob* dc = (FmDeepCountJob*)job;
    GList* l;

    l = fm_list_peek_head_link(dc->paths);
    for(; !fm_job_is_cancelled(job) && l; l=l->next)
    {
        FmPath* path = FM_PATH(l->data);
        if(fm_path_is_native(path)) /* if it's a native file, use posix APIs */
            deep_count_posix( dc, path );
        else
        {
            GFile* gf = fm_path_to_gfile(path);
            deep_count_gio( dc, NULL, gf );
            g_object_unref(gf);
        }
    }
    return TRUE;
}
コード例 #8
0
ファイル: fm-path.c プロジェクト: afilmore/libfmcore
GFile *fm_path_to_gfile (FmPath *path)
{
    GFile *gf;
    
    char *str = fm_path_to_str (path);
    
    if (fm_path_is_native (path))
    {
        gf = g_file_new_for_path (str);
    }
    else
    {
        // Escape the path so that it supports spaces and special characters like accentuated ones...
        char *tmp_str = g_uri_escape_string (str, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH, TRUE);
        
        gf = g_file_new_for_uri (tmp_str);
        g_free (tmp_str);
    }
    
    g_free (str);
    
    return gf;
}
コード例 #9
0
ファイル: fm-path.c プロジェクト: afilmore/libfmcore
/**
 * fm_path_new_child_len
 * @parent: a parent path
 * @basename: basename of a direct child of @parent directory in glib
 * filename encoding.  (can be non-UTF-8).
 * @len: length of basename
 *
 * Returns: a newly created FmPath for the path. You have to call
 * fm_path_unref () when it's no longer needed.
 */
FmPath *fm_path_new_child_len (FmPath *parent, const char *basename, int name_len)
{
    FmPath *path;
    gboolean append_slash = FALSE;
    int flags;

    // skip empty basename
    if (G_UNLIKELY (!basename || name_len == 0))
        return parent ? fm_path_ref (path) : NULL;

    if (G_LIKELY (parent)) // remove slashes if needed.
    {
        #if 0 // This saves some memory, but it's too inefficient.
        // Optimization: reuse existing FmPaths
        if (fm_path_is_native (parent))
        {
            path = _fm_path_reuse_existing_paths (parent, basename, name_len);
            if (G_UNLIKELY (path))
                return path;
        }
        #endif

        // Inherit of parent flags without the root flag...
        flags = parent->flags & (~FM_PATH_IS_ROOT);
        
        while (basename[0] == '/')
        {
            ++basename;
            --name_len;
        }
        
        while (name_len > 0 && basename[name_len-1] == '/')
            --name_len;

        // special case for . and ..
        if (basename[0] == '.' &&  (name_len == 1 ||  (name_len == 2 && basename[1] == '.')))
        {
            if (name_len == 1) // .
                return parent ? fm_path_ref (parent) : NULL;
            else // ..
            {
                if (parent)
                    return parent->parent ? fm_path_ref (parent->parent) : fm_path_ref (parent);
                else
                    return NULL;
            }
        }
    }
    else // this basename is root of the fs  (no parent), it can be "/" or something like "ftp://user@host/"
    {
        // remove duplicated leading slashes and treat them as one /
        if (G_UNLIKELY (basename[0] == '/')) // this is a posix path
            return fm_path_ref (root_path);
        else // This is something like: trash:///, computer:/// sftp://user@host/
            return _fm_path_new_uri_root (basename, name_len, NULL, FALSE);
    }

    // remove tailing slashes
    while (name_len > 0 && basename[name_len-1] == '/')
        --name_len;

    if (name_len == 0)
        return parent ? fm_path_ref (parent) : NULL;

    path = _fm_path_alloc (parent, (G_UNLIKELY (append_slash) ? name_len + 1 : name_len), flags);
    
    memcpy (path->name, basename, name_len);
    if (G_UNLIKELY (append_slash))
    {
        path->name [name_len] = '/';
        path->name [name_len + 1] = '\0';
    }
    else
        path->name [name_len] = '\0';
    
    return path;
}
コード例 #10
0
ファイル: fm-file-info-job.c プロジェクト: YustasSwamp/libfm
static gboolean fm_file_info_job_run(FmJob* fmjob)
{
    GList* l;
    FmFileInfoJob* job = (FmFileInfoJob*)fmjob;
    GError* err = NULL;

    if(job->file_infos == NULL)
        return FALSE;

    for(l = fm_file_info_list_peek_head_link(job->file_infos); !fm_job_is_cancelled(fmjob) && l;)
    {
        FmFileInfo* fi = (FmFileInfo*)l->data;
        GList* next = l->next;
        FmPath* path = fm_file_info_get_path(fi);

        if(job->current)
            fm_path_unref(job->current);
        job->current = fm_path_ref(path);

        if(fm_path_is_native(path))
        {
            char* path_str = fm_path_to_str(path);
            if(!_fm_file_info_job_get_info_for_native_file(fmjob, fi, path_str, &err))
            {
                FmJobErrorAction act = fm_job_emit_error(fmjob, err, FM_JOB_ERROR_MILD);
                g_error_free(err);
                err = NULL;
                if(act == FM_JOB_RETRY)
                {
                    g_free(path_str);
                    continue; /* retry */
                }

                fm_file_info_list_delete_link(job->file_infos, l); /* also calls unref */
            }
            else if(G_UNLIKELY(job->flags & FM_FILE_INFO_JOB_EMIT_FOR_EACH_FILE))
                fm_job_call_main_thread(fmjob, _emit_current_file, fi);
            g_free(path_str);
            /* recursively set display names for path parents */
            _check_native_display_names(fm_path_get_parent(path));
        }
        else
        {
            GFile* gf;

            gf = fm_path_to_gfile(path);
            if(!_fm_file_info_job_get_info_for_gfile(fmjob, fi, gf, &err))
            {
              if(err->domain == G_IO_ERROR && err->code == G_IO_ERROR_NOT_MOUNTED)
              {
                GFileInfo *inf;
                /* location by link isn't mounted; unfortunately we cannot
                   launch a target if we don't know what kind of target we
                   have; lets make a simplest directory-kind GFIleInfo */
                /* FIXME: this may be dirty a bit */
                g_error_free(err);
                err = NULL;
                inf = g_file_info_new();
                g_file_info_set_file_type(inf, G_FILE_TYPE_DIRECTORY);
                g_file_info_set_name(inf, fm_path_get_basename(path));
                g_file_info_set_display_name(inf, fm_path_get_basename(path));
                fm_file_info_set_from_g_file_data(fi, gf, inf);
                g_object_unref(inf);
              }
              else
              {
                FmJobErrorAction act = fm_job_emit_error(fmjob, err, FM_JOB_ERROR_MILD);
                g_error_free(err);
                err = NULL;
                if(act == FM_JOB_RETRY)
                {
                    g_object_unref(gf);
                    continue; /* retry */
                }

                fm_file_info_list_delete_link(job->file_infos, l); /* also calls unref */
                goto _next;
              }
            }
            else if(G_UNLIKELY(job->flags & FM_FILE_INFO_JOB_EMIT_FOR_EACH_FILE))
                    fm_job_call_main_thread(fmjob, _emit_current_file, fi);
            /* recursively set display names for path parents */
            _check_gfile_display_names(fm_path_get_parent(path), gf);
_next:
            g_object_unref(gf);
        }
        l = next;
    }
    return TRUE;
}
コード例 #11
0
ファイル: fm-utils.c プロジェクト: gilir/libfm-debian
gboolean fm_launch_files(GAppLaunchContext* ctx, GList* file_infos, FmFileLauncher* launcher, gpointer user_data)
{
    GList* l;
    GHashTable* hash = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
    GList* folders = NULL;
    FmFileInfo* fi;
    GError* err = NULL;
    GAppInfo* app;

    for(l = file_infos; l; l=l->next)
    {
        GList* fis;
        fi = (FmFileInfo*)l->data;
        if(fm_file_info_is_dir(fi))
            folders = g_list_prepend(folders, fi);
        else
        {
            /* FIXME: handle shortcuts, such as the items in menu:// */
            if(fm_path_is_native(fi->path))
            {
                char* filename;
                if(fm_file_info_is_desktop_entry(fi))
                {
                    /* if it's a desktop entry file, directly launch it. */
                    filename = fm_path_to_str(fi->path);
                    if(!fm_launch_desktop_entry(ctx, filename, NULL, &err))
                    {
                        if(launcher->error)
                            launcher->error(ctx, err, user_data);
                        g_error_free(err);
                        err = NULL;
                    }
                    continue;
                }
                else if(fm_file_info_is_executable_type(fi))
                {
                    /* if it's an executable file, directly execute it. */
                    filename = fm_path_to_str(fi->path);
                    /* FIXME: we need to use eaccess/euidaccess here. */
                    if(g_file_test(filename, G_FILE_TEST_IS_EXECUTABLE))
                    {
                        app = g_app_info_create_from_commandline(filename, NULL, 0, NULL);
                        if(app)
                        {
                            if(!g_app_info_launch(app, NULL, ctx, &err))
                            {
                                if(launcher->error)
                                    launcher->error(ctx, err, user_data);
                                g_error_free(err);
                                err = NULL;
                            }
                            g_object_unref(app);
                            continue;
                        }
                    }
                    g_free(filename);
                }
            }
            else /* not a native path */
            {
                if(fm_file_info_is_shortcut(fi) && !fm_file_info_is_dir(fi))
                {
                    /* FIXME: special handling for shortcuts */
                    if(fm_path_is_xdg_menu(fi->path) && fi->target)
                    {
                        if(!fm_launch_desktop_entry(ctx, fi->target, NULL, &err))
                        {
                            if(launcher->error)
                                launcher->error(ctx, err, user_data);
                            g_error_free(err);
                            err = NULL;
                        }
                        continue;
                    }
                }
            }
            if(fi->type && fi->type->type)
            {
                fis = g_hash_table_lookup(hash, fi->type->type);
                fis = g_list_prepend(fis, fi);
                g_hash_table_insert(hash, fi->type->type, fis);
            }
        }
    }

    if(g_hash_table_size(hash) > 0)
    {
        GHashTableIter it;
        const char* type;
        GList* fis;
        g_hash_table_iter_init(&it, hash);
        while(g_hash_table_iter_next(&it, &type, &fis))
        {
            GAppInfo* app = g_app_info_get_default_for_type(type, FALSE);
            if(!app)
            {
                if(launcher->get_app)
                {
                    FmMimeType* mime_type = ((FmFileInfo*)fis->data)->type;
                    app = launcher->get_app(fis, mime_type, user_data, NULL);
                }
            }
            if(app)
            {
                for(l=fis; l; l=l->next)
                {
                    char* uri;
                    fi = (FmFileInfo*)l->data;
                    uri = fm_path_to_uri(fi->path);
                    l->data = uri;
                }
                fis = g_list_reverse(fis);
                g_app_info_launch_uris(app, fis, ctx, err);
                /* free URI strings */
                g_list_foreach(fis, (GFunc)g_free, NULL);
                g_object_unref(app);
            }
            g_list_free(fis);
        }
    }
    g_hash_table_destroy(hash);

    if(folders)
    {
        folders = g_list_reverse(folders);
        if(launcher->open_folder)
        {
            launcher->open_folder(ctx, folders, user_data, &err);
            if(err)
            {
                if(launcher->error)
                    launcher->error(ctx, err, user_data);
                g_error_free(err);
                err = NULL;
            }
        }
        g_list_free(folders);
    }
    return TRUE;
}
コード例 #12
0
ファイル: fm-dnd-dest.c プロジェクト: engla/libfm
/**
 * fm_dnd_dest_get_default_action
 * @dd FmDndDest object
 * @target GdkTarget of the target data type
 * @dest FmFileInfo of the destination file at drop site.
 *
 * Returns the default action to take for the dragged files.
 */
GdkDragAction fm_dnd_dest_get_default_action(FmDndDest* dd,
                                             GdkDragContext* drag_context,
                                             GdkTarget target)
{
    GdkDragAction action;
    FmFileInfo* dest = dd->dest_file;

    if(!dest || !dest->path)
        return FALSE;

    /* this is XDirectSave */
    if(target == xds_target_atom)
        return GDK_ACTION_COPY;

    if(dd->src_files) /* we have got drag source files */
    {
        FmPath* dest_path = dest->path;
        if(fm_path_is_trash(dest_path))
        {
            if(fm_path_is_trash_root(dest_path)) /* we can only move files to trash can */
                action = GDK_ACTION_MOVE;
            else /* files inside trash are read only */
                action = 0;
        }
        else if(fm_path_is_virtual(dest_path))
        {
            /* computer:/// and network:/// shouldn't received dropped files. */
            /* FIXME: some special handling can be done with menu:// */
            action = 0;
        }
        else if(list_contains_path(dd->src_files, dest_path)) {
            /* don't allow dropping files into themselves */
            action = 0;
        }
        else /* dest is a ordinary path */
        {
            /* determine if the dragged files are on the same device as destination file */
            /* Here we only check the first dragged file since checking all of them can
             * make the operation very slow. */
            gboolean same_fs;
            if(dd->src_dev || dd->src_fs_id) /* we know the device of dragged source files */
            {
                /* compare the device/filesystem id against that of destination file */
                if(fm_path_is_native(dest_path))
                    same_fs = dd->src_dev && (dd->src_dev == dest->dev);
                else /* FIXME: can we use direct comparison here? */
                    same_fs = dd->src_fs_id && (0 == g_strcmp0(dd->src_fs_id, dest->fs_id));
                action = same_fs ? GDK_ACTION_MOVE : GDK_ACTION_COPY;
            }
            else /* we don't know on which device the dragged source files are. */
                action = 0;
        }
    }
    else /* we didn't have any data */
    {
        action = 0;
        if(!dd->waiting_data) /* we're still waiting for "drag-data-received" signal */
        {
            /* retrieve the source files */
            gtk_drag_get_data(dd->widget, drag_context, target, time);
            dd->waiting_data = TRUE;
        }
    }

    if( action && 0 == (drag_context->actions & action) )
        action = drag_context->suggested_action;

    return action;
}
コード例 #13
0
ファイル: fm-dnd-dest.c プロジェクト: engla/libfm
gboolean fm_dnd_dest_drag_data_received(FmDndDest* dd, GdkDragContext *drag_context,
             gint x, gint y, GtkSelectionData *sel_data, guint info, guint time)
{
    FmList* files = NULL;
    GtkWidget *dest_widget = dd->widget;

    if(info ==  FM_DND_DEST_TARGET_FM_LIST)
    {
        if((sel_data->length >= 0) && (sel_data->format==8))
        {
            /* get the pointer */
            memcpy(&files, sel_data->data, sel_data->length);
            if(files)
                fm_list_ref(files);
            if(files)
            {
                FmFileInfo* fi = FM_FILE_INFO(fm_list_peek_head(files));
                /* get the device of the first dragged source file */
                if(fm_path_is_native(fi->path))
                    dd->src_dev = fi->dev;
                else
                    dd->src_fs_id = fi->fs_id;
            }
        }
    }
    else if(info == FM_DND_DEST_TARGET_URI_LIST)
    {
        if((sel_data->length >= 0) && (sel_data->format==8))
        {
            gchar **uris;
            uris = gtk_selection_data_get_uris( sel_data );
            files = fm_path_list_new_from_uris((const char **)uris);
            g_free(uris);
            if(files)
            {
                GFileInfo* inf;
                FmPath* path = FM_PATH(fm_list_peek_head(files));
                GFile* gf = fm_path_to_gfile(path);
                const char* attr = fm_path_is_native(path) ? G_FILE_ATTRIBUTE_UNIX_DEVICE : G_FILE_ATTRIBUTE_ID_FILESYSTEM;
                inf = g_file_query_info(gf, attr, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, NULL);
                g_object_unref(gf);

                if(fm_path_is_native(path))
                    dd->src_dev = g_file_info_get_attribute_uint32(inf, G_FILE_ATTRIBUTE_UNIX_DEVICE);
                else
                    dd->src_fs_id = g_intern_string(g_file_info_get_attribute_string(inf, G_FILE_ATTRIBUTE_ID_FILESYSTEM));
                g_object_unref(inf);
            }
        }
    }
    else if(info == FM_DND_DEST_TARGET_XDS) /* X direct save */
    {
        if( sel_data->format == 8 && sel_data->length == 1 && sel_data->data[0] == 'F')
        {
            gdk_property_change(GDK_DRAWABLE(drag_context->source_window),
                               xds_target_atom,
                               gdk_atom_intern_static_string("text/plain"), 8,
                               GDK_PROP_MODE_REPLACE, (const guchar *)"", 0);
        }
        else if(sel_data->format == 8 && sel_data->length == 1 && sel_data->data[0] == 'S')
        {
            /* XDS succeeds */
        }
        gtk_drag_finish(drag_context, TRUE, FALSE, time);
        return TRUE;
    }
    else
        return FALSE;

    /* remove previously cached source files. */
    if(G_UNLIKELY(dd->src_files))
    {
        fm_list_unref(dd->src_files);
        dd->src_files = NULL;
    }
    dd->src_files = files;
    dd->waiting_data = FALSE;
    dd->info_type = info;
    return TRUE;
}
コード例 #14
0
ファイル: fm-file-launcher.c プロジェクト: Gontxal0/libfm
/**
 * fm_launch_files
 * @ctx: (allow-none): a launch context
 * @file_infos: (element-type FmFileInfo): files to launch
 * @launcher: #FmFileLauncher with callbacks
 * @user_data: data supplied for callbacks
 *
 * Launches files using callbacks in @launcher.
 *
 * Returns: %TRUE in case of success.
 *
 * Since: 0.1.0
 */
gboolean fm_launch_files(GAppLaunchContext* ctx, GList* file_infos, FmFileLauncher* launcher, gpointer user_data)
{
    GList* l;
    GHashTable* hash = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
    GList *folders = NULL;
    FmFileInfo* fi;
    GList *targets = NULL;
    GError* err = NULL;
    GAppInfo* app;
    const char* type;

    for(l = file_infos; l; l=l->next)
    {
        GList* fis;
        char *filename, *scheme;
        const char *target = NULL;

        fi = (FmFileInfo*)l->data;
        /* special handling for shortcuts */
        if (!fm_file_info_is_symlink(fi))
            /* symlinks also has fi->target, but we only handle shortcuts here. */
            target = fm_file_info_get_target(fi);
        if (launcher->open_folder && fm_file_info_is_dir(fi))
        {
            /* special handling for shortcuts */
            if(target)
            {
                fi = _fetch_file_info_for_shortcut(fm_file_info_get_target(fi),
                                                   ctx, launcher, user_data);
                if (fi == NULL)
                    /* error was shown by job already */
                    continue;
                targets = g_list_prepend(targets, fi);
            }
            folders = g_list_prepend(folders, fi);
        }
        else if (fm_file_info_is_desktop_entry(fi))
        {
_launch_desktop_entry:
            if (!target)
                filename = fm_path_to_str(fm_file_info_get_path(fi));
            fm_launch_desktop_entry(ctx, target ? target : filename, NULL,
                                    launcher, user_data);
            if (!target)
                g_free(filename);
            continue;
        }
        else
        {
            FmPath* path = fm_file_info_get_path(fi);
            FmMimeType* mime_type = NULL;
            if(fm_path_is_native(path))
            {
                /* special handling for shortcuts */
                if (target)
                {
                    if (fm_file_info_get_mime_type(fi) == _fm_mime_type_get_inode_x_shortcut())
                    /* if we already know MIME type then use it instead */
                    {
                      scheme = g_uri_parse_scheme(target);
                      if (scheme)
                      {
                        /* FIXME: this is rough! */
                        if (strcmp(scheme, "file") != 0 &&
                            strcmp(scheme, "trash") != 0 &&
                            strcmp(scheme, "network") != 0 &&
                            strcmp(scheme, "computer") != 0 &&
                            strcmp(scheme, "menu") != 0)
                        {
                            /* we don't support this URI internally, try GIO */
                            app = g_app_info_get_default_for_uri_scheme(scheme);
                            if (app)
                            {
                                fis = g_list_prepend(NULL, (char *)target);
                                fm_app_info_launch_uris(app, fis, ctx, &err);
                                g_list_free(fis);
                                g_object_unref(app);
                            }
                            else if (launcher->error)
                                g_set_error(&err, G_IO_ERROR, G_IO_ERROR_FAILED,
                                            _("No default application is set to launch URIs %s://"),
                                            scheme);
                            if (err)
                            {
                                launcher->error(ctx, err, NULL, user_data);
                                g_clear_error(&err);
                            }
                            g_free(scheme);
                            continue;
                        }
                        g_free(scheme);
                      }
                    }
                    else
                        mime_type = fm_file_info_get_mime_type(fi);
                    /* retrieve file info for target otherwise and handle it */
                    fi = _fetch_file_info_for_shortcut(target, ctx, launcher, user_data);
                    if (fi == NULL)
                        /* error was shown by job already */
                        continue;
                    targets = g_list_prepend(targets, fi);
                    path = fm_file_info_get_path(fi);
                    /* special handling for desktop entries */
                    if (fm_file_info_is_desktop_entry(fi))
                        goto _launch_desktop_entry;
                }
                if(fm_file_info_is_executable_type(fi))
                {
                    /* if it's an executable file, directly execute it. */
                    filename = fm_path_to_str(path);

                    /* FIXME: we need to use eaccess/euidaccess here. */
                    if(g_file_test(filename, G_FILE_TEST_IS_EXECUTABLE))
                    {
                        if(launcher->exec_file)
                        {
                            FmFileLauncherExecAction act = launcher->exec_file(fi, user_data);
                            GAppInfoCreateFlags flags = 0;
                            switch(act)
                            {
                            case FM_FILE_LAUNCHER_EXEC_IN_TERMINAL:
                                flags |= G_APP_INFO_CREATE_NEEDS_TERMINAL;
                                /* NOTE: no break here */
                            case FM_FILE_LAUNCHER_EXEC:
                            {
                                /* filename may contain spaces. Fix #3143296 */
                                char* quoted = g_shell_quote(filename);
                                app = fm_app_info_create_from_commandline(quoted, NULL, flags, NULL);
                                g_free(quoted);
                                if(app)
                                {
                                    char* run_path = g_path_get_dirname(filename);
                                    char* cwd = NULL;
                                    /* bug #3589641: scripts are ran from $HOME.
                                       since GIO launcher is kinda ugly - it has
                                       no means to set running directory so we
                                       do workaround - change directory to it */
                                    if(run_path && strcmp(run_path, "."))
                                    {
                                        cwd = g_get_current_dir();
                                        if(chdir(run_path) != 0)
                                        {
                                            g_free(cwd);
                                            cwd = NULL;
                                            if (launcher->error)
                                            {
                                                g_set_error(&err, G_IO_ERROR,
                                                            g_io_error_from_errno(errno),
                                                            _("Cannot set working directory to '%s': %s"),
                                                            run_path, g_strerror(errno));
                                                launcher->error(ctx, err, NULL, user_data);
                                                g_clear_error(&err);
                                            }
                                        }
                                    }
                                    g_free(run_path);
                                    if(!fm_app_info_launch(app, NULL, ctx, &err))
                                    {
                                        if(launcher->error)
                                            launcher->error(ctx, err, NULL, user_data);
                                        g_error_free(err);
                                        err = NULL;
                                    }
                                    if(cwd) /* return back */
                                    {
                                        if(chdir(cwd) != 0)
                                            g_warning("fm_launch_files(): chdir() failed");
                                        g_free(cwd);
                                    }
                                    g_object_unref(app);
                                    continue;
                                }
                                break;
                            }
                            case FM_FILE_LAUNCHER_EXEC_OPEN:
                                break;
                            case FM_FILE_LAUNCHER_EXEC_CANCEL:
                                continue;
                            }
                        }
                    }
                    g_free(filename);
                }
            }
            if (mime_type == NULL)
                mime_type = fm_file_info_get_mime_type(fi);
            if(mime_type && (type = fm_mime_type_get_type(mime_type)))
            {
                fis = g_hash_table_lookup(hash, type);
                fis = g_list_prepend(fis, fi);
                g_hash_table_insert(hash, (gpointer)type, fis);
            }
            else if (launcher->error)
            {
                g_set_error(&err, G_IO_ERROR, G_IO_ERROR_FAILED,
                            _("Could not determine content type of file '%s' to launch it"),
                            fm_file_info_get_disp_name(fi));
                launcher->error(ctx, err, NULL, user_data);
                g_clear_error(&err);
            }
        }
    }

    if(g_hash_table_size(hash) > 0)
    {
        GHashTableIter it;
        GList* fis;
        g_hash_table_iter_init(&it, hash);
        while(g_hash_table_iter_next(&it, (void**)&type, (void**)&fis))
        {
            GAppInfo* app = g_app_info_get_default_for_type(type, FALSE);
            if(!app)
            {
                if(launcher->get_app)
                {
                    FmMimeType* mime_type = fm_file_info_get_mime_type((FmFileInfo*)fis->data);
                    app = launcher->get_app(fis, mime_type, user_data, NULL);
                }
            }
            if(app)
            {
                for(l=fis; l; l=l->next)
                {
                    char* uri;
                    fi = (FmFileInfo*)l->data;
                    /* special handling for shortcuts */
                    if (fm_file_info_is_shortcut(fi))
                        uri = g_strdup(fm_file_info_get_target(fi));
                    else
                        uri = fm_path_to_uri(fm_file_info_get_path(fi));
                    l->data = uri;
                }
                fis = g_list_reverse(fis);
                fm_app_info_launch_uris(app, fis, ctx, &err);
                /* free URI strings */
                g_list_foreach(fis, (GFunc)g_free, NULL);
                g_object_unref(app);
            }
            else if (launcher->error)
                g_set_error(&err, G_IO_ERROR, G_IO_ERROR_FAILED,
                            _("No default application is set for MIME type %s"),
                            type);
            if (err)
            {
                launcher->error(ctx, err, NULL, user_data);
                g_clear_error(&err);
            }
            g_list_free(fis);
        }
    }
    g_hash_table_destroy(hash);

    if(folders)
    {
        folders = g_list_reverse(folders);
        if(launcher->open_folder)
        {
            launcher->open_folder(ctx, folders, user_data, &err);
            if(err)
            {
                if(launcher->error)
                    launcher->error(ctx, err, NULL, user_data);
                g_error_free(err);
                err = NULL;
            }
        }
        g_list_free(folders);
    }
    g_list_free_full(targets, (GDestroyNotify)fm_file_info_unref);
    return TRUE;
}
コード例 #15
0
ファイル: fm-file-info-job.c プロジェクト: afilmore/libfmcore
/*********************************************************************
 * ...
 * 
 * 
 ********************************************************************/
gboolean fm_file_info_job_run (FmJob *fmjob)
{
	FmFileInfoJob *job = (FmFileInfoJob*) fmjob;
    GError *err = NULL;

	GList *l;
	for (l = fm_list_peek_head_link (job->file_infos); !fm_job_is_cancelled (fmjob) && l; )
	{
		FmFileInfo *file_info = (FmFileInfo*) l->data;
        GList *next = l->next;

        job->current = file_info->path;

		if (fm_path_is_native (file_info->path))
		{
			char *path_str = fm_path_to_str (file_info->path);
			
            
            // FileInfo rework: new function for testing...
            // this one is not cancellable and doesn't handle errors...
            // if (!fm_file_info_job_get_info_for_native_file (FM_JOB (job), file_info, path_str, &err))
            if (!fm_file_info_set_for_native_file (file_info, path_str))
            {
                //~ FmJobErrorAction act = fm_job_emit_error (FM_JOB(job), err, FM_JOB_ERROR_MILD);
                //~ 
                //~ g_error_free (err);
                //~ err = NULL;
                //~ 
                //~ if (act == FM_JOB_RETRY)
                    //~ continue;

                DEBUG ("fm_file_info_set_for_native_file: error reading %s\n", path_str);
                
                next = l->next;
                fm_list_delete_link (job->file_infos, l); // Also calls unref...
            }
			
            g_free (path_str);
		}
		else
		{
            GFile *gf;
            
            if (fm_path_is_virtual (file_info->path))
            {
                // This is a xdg menu
                if (fm_path_is_xdg_menu (file_info->path))
                {
                    MenuCache *mc;
                    MenuCacheDir *dir;
                    
                    char *path_str = fm_path_to_str (file_info->path);
                    char *menu_name = path_str + 5, ch;
                    char *dir_name;
                    
                    while (*menu_name == '/')
                        ++menu_name;
                    
                    dir_name = menu_name;
                    
                    while (*dir_name && *dir_name != '/')
                        ++dir_name;
                    
                    ch = *dir_name;
                    *dir_name = '\0';
                    
                    menu_name = g_strconcat (menu_name, ".menu", NULL);
                    mc = menu_cache_lookup_sync (menu_name);
                    g_free (menu_name);

                    if (*dir_name && !(*dir_name == '/' && dir_name[1] == '\0'))
                    {
                        char *tmp = g_strconcat ("/",
                                                 menu_cache_item_get_id (MENU_CACHE_ITEM(menu_cache_get_root_dir (mc))),
                                                 dir_name, NULL);
                        
                        dir = menu_cache_get_dir_from_path (mc, tmp);
                        
                        g_free (tmp);
                    }
                    else
                    {
                        dir = menu_cache_get_root_dir (mc);
                    }
                    
                    if (dir)
                    {
                        fm_file_info_set_from_menu_cache_item (file_info, (MenuCacheItem*) dir);
                    }
                    else
                    {
                        next = l->next;
                        fm_list_delete_link (job->file_infos, l); // Also calls unref...
                    }
                    
                    g_free (path_str);
                    menu_cache_unref (mc);
                    
                    l = l->next;
                    continue;
                }
            }

			gf = fm_path_to_gfile (file_info->path);
			
            if (!fm_file_info_job_get_info_for_gfile (FM_JOB (job), file_info, gf, &err))
            {
                FmJobErrorAction act = fm_job_emit_error (FM_JOB (job), err, FM_JOB_ERROR_MILD);
                
                g_error_free (err);
                err = NULL;
                
                if (act == FM_JOB_RETRY)
                    continue;

                next = l->next;
                
                fm_list_delete_link (job->file_infos, l);   // Also calls unref...
            }
			
            g_object_unref (gf);
		}
        
        l = next;
	}
	
    return TRUE;
}
コード例 #16
0
// FIXME_pcm: this is too dirty. Need some refactor later.
static void update_permissions (FmFilePropData *data)
{
    FmFileInfo *file_info =  (FmFileInfo*)fm_list_peek_head (data->files);
    GList *l;
    int sel;
    char *tmp;
    mode_t owner_perm =  (file_info->mode & S_IRWXU);
    mode_t group_perm =  (file_info->mode & S_IRWXG);
    mode_t other_perm =  (file_info->mode & S_IRWXO);
    mode_t exec_perm =  (file_info->mode &  (S_IXUSR|S_IXGRP|S_IXOTH));
    uid_t uid = file_info->uid;
    gid_t gid = file_info->gid;
    struct group *grp = NULL;
    struct passwd *pw = NULL;

    data->all_native = fm_path_is_native (fm_file_info_get_path (file_info));
    data->has_dir = S_ISDIR (file_info->mode) != FALSE;

    for (l=fm_list_peek_head_link (data->files)->next; l; l=l->next)
    {
        FmFileInfo *file_info =  (FmFileInfo*)l->data;

        if ( !fm_path_is_native (fm_file_info_get_path (file_info)) )
            data->all_native = FALSE;

        if (S_ISDIR (file_info->mode))
            data->has_dir = TRUE;

        if ( uid != file_info->uid )
            uid = -1;
        if ( gid != file_info->gid )
            gid = -1;

        if ( owner_perm != -1 && owner_perm !=  (file_info->mode & S_IRWXU) )
            owner_perm = -1;
        if ( group_perm != -1 && group_perm !=  (file_info->mode & S_IRWXG) )
            group_perm = -1;
        if ( other_perm != -1 && other_perm !=  (file_info->mode & S_IRWXO) )
            other_perm = -1;

        if ( exec_perm !=  (file_info->mode &  (S_IXUSR|S_IXGRP|S_IXOTH)) )
            exec_perm = -1;
    }

    if ( data->all_native )
    {
        if ( uid >= 0 )
        {
            pw = getpwuid (uid);
            if (pw)
                gtk_entry_set_text (GTK_ENTRY (data->owner), pw->pw_name);
        }
        if ( gid >= 0 )
        {
            grp = getgrgid (gid);
            if (grp)
                gtk_entry_set_text (GTK_ENTRY (data->group), grp->gr_name);
        }
    }

    if ( uid >=0 && !pw )
    {
        tmp = g_strdup_printf ("%u", uid);
        gtk_entry_set_text (GTK_ENTRY (data->owner), tmp);
        g_free (tmp);
    }

    if ( gid >=0 && !grp )
    {
        tmp = g_strdup_printf ("%u", gid);
        gtk_entry_set_text (GTK_ENTRY (data->group), tmp);
        g_free (tmp);
    }

    data->orig_owner = g_strdup (gtk_entry_get_text (GTK_ENTRY (data->owner)));
    data->orig_group = g_strdup (gtk_entry_get_text (GTK_ENTRY (data->group)));

    // on local filesystems, only root can do chown.
    if ( data->all_native && geteuid () != 0 )
    {
        gtk_editable_set_editable (GTK_EDITABLE (data->owner), FALSE);
        gtk_editable_set_editable (GTK_EDITABLE (data->group), FALSE);
    }

    sel = NO_CHANGE;
    if (owner_perm != -1)
    {
        if (  (owner_perm &  (S_IRUSR|S_IWUSR)) ==  (S_IRUSR|S_IWUSR) )
            sel = READ_WRITE;
        else if (  (owner_perm &  (S_IRUSR|S_IWUSR)) == S_IRUSR )
            sel = READ_ONLY;
        else if (  (owner_perm &  (S_IRUSR|S_IWUSR)) == S_IWUSR )
            sel = WRITE_ONLY;
        else
            sel = NONE;
    }
    gtk_combo_box_set_active (GTK_COMBO_BOX (data->owner_perm), sel);
    data->owner_perm_sel = sel;

    sel = NO_CHANGE;
    if (group_perm != -1)
    {
        if (  (group_perm &  (S_IRGRP|S_IWGRP)) ==  (S_IRGRP|S_IWGRP) )
            sel = READ_WRITE;
        else if (  (group_perm &  (S_IRGRP|S_IWGRP)) == S_IRGRP )
            sel = READ_ONLY;
        else if (  (group_perm &  (S_IRGRP|S_IWGRP)) == S_IWGRP )
            sel = WRITE_ONLY;
        else
            sel = NONE;
    }
    gtk_combo_box_set_active (GTK_COMBO_BOX (data->group_perm), sel);
    data->group_perm_sel = sel;

    sel = NO_CHANGE;
    if (other_perm != -1)
    {
        if (  (other_perm &  (S_IROTH|S_IWOTH)) ==  (S_IROTH|S_IWOTH) )
            sel = READ_WRITE;
        else if (  (other_perm &  (S_IROTH|S_IWOTH)) == S_IROTH )
            sel = READ_ONLY;
        else if (  (other_perm &  (S_IROTH|S_IWOTH)) == S_IWOTH )
            sel = WRITE_ONLY;
        else
            sel = NONE;
    }
    gtk_combo_box_set_active (GTK_COMBO_BOX (data->other_perm), sel);
    data->other_perm_sel = sel;

    if (data->has_dir)
        gtk_widget_hide ( data->exec );

    if ( exec_perm != -1 )
    {
        gboolean xusr =  (exec_perm & S_IXUSR) != 0;
        gboolean xgrp =  (exec_perm & S_IXGRP) != 0;
        gboolean xoth =  (exec_perm & S_IXOTH) != 0;
        if ( xusr == xgrp && xusr == xoth ) // executable
        {
            gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (data->exec), xusr);
            data->exec_state = xusr;
        }
        else // inconsistent
        {
            gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (data->exec), TRUE);
            g_signal_connect (data->exec, "toggled", G_CALLBACK (on_exec_toggled), data);
            data->exec_state = -1;
        }
    }
    else // inconsistent
    {
        gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (data->exec), TRUE);
        g_signal_connect (data->exec, "toggled", G_CALLBACK (on_exec_toggled), data);
        data->exec_state = -1;
    }
}