static gboolean ensure_valid_group (FmFilePropData *data)
{
    gboolean ret = TRUE;
    const char *tmp = gtk_entry_get_text (GTK_ENTRY (data->group));

    data->gid = -1;
    if (tmp && *tmp)
    {
        if (data->all_native && !isdigit (tmp[0])) // entering names instead of numbers is only allowed for local files.
        {
            struct group *gr;
            if (!tmp || !*tmp || ! (gr = getgrnam (tmp)))
                ret = FALSE;
            else
                data->gid = gr->gr_gid;
        }
    }
    else
        ret = FALSE;

    if (!ret)
    {
        fm_show_error (GTK_WINDOW (data->dlg), NULL, _("Please enter a valid group name or numeric id."));
        gtk_widget_grab_focus (data->group);
    }
    if (data->gid == -1)
        data->gid = atoi (tmp);

    return ret;
}
Exemple #2
0
FmJobErrorAction on_folder_err(FmFolder* folder, GError* err, FmJobErrorSeverity severity, FmFolderView* fv)
{
    GtkWindow* parent = (GtkWindow*)gtk_widget_get_toplevel((GtkWidget*)fv);
    if( err->domain == G_IO_ERROR )
    {
        if( err->code == G_IO_ERROR_NOT_MOUNTED && severity < FM_JOB_ERROR_CRITICAL )
            if(fm_mount_path(parent, folder->dir_path, TRUE))
                return FM_JOB_RETRY;
        else if(err->code == G_IO_ERROR_FAILED_HANDLED)
            return FM_JOB_CONTINUE;
    }
    fm_show_error(parent, NULL, err->message);
    return FM_JOB_CONTINUE;
}
Exemple #3
0
static FmJobErrorAction on_folder_error(FmFolder* folder, GError* err, FmJobErrorSeverity severity, FmTabPage* page)
{
    GtkWindow* win = GTK_WINDOW(GET_MAIN_WIN(page));
    if(err->domain == G_IO_ERROR)
    {
        if( err->code == G_IO_ERROR_NOT_MOUNTED && severity < FM_JOB_ERROR_CRITICAL )
        {
            FmPath* path = fm_folder_get_path(folder);
            if(fm_mount_path(win, path, TRUE))
                return FM_JOB_RETRY;
        }
    }
    if(severity >= FM_JOB_ERROR_MODERATE)
    {
        /* Only show more severe errors to the users and
         * ignore milder errors. Otherwise too many error
         * message boxes can be annoying.
         * This fixes bug #3411298- Show "Permission denied" when switching to super user mode.
         * https://sourceforge.net/tracker/?func=detail&aid=3411298&group_id=156956&atid=801864
         * */
        fm_show_error(win, NULL, err->message);
    }
    return FM_JOB_CONTINUE;
}
Exemple #4
0
void on_create_new(GtkAction* action, FmMainWin* win)
{
    FmFolderView* fv = FM_FOLDER_VIEW(win->folder_view);
    const char* name = gtk_action_get_name(action);
    GError* err = NULL;
    FmPath* cwd = fm_folder_view_get_cwd(fv);
    FmPath* dest;
    char* basename;
_retry:
    basename = fm_get_user_input(GTK_WINDOW(win), _("Create New..."), _("Enter a name for the newly created file:"), _("New"));
    if(!basename)
        return;

    dest = fm_path_new_child(cwd, basename);
    g_free(basename);

    if( strcmp(name, "NewFolder") == 0 )
    {
        GFile* gf = fm_path_to_gfile(dest);
        if(!g_file_make_directory(gf, NULL, &err))
        {
            if(err->domain = G_IO_ERROR && err->code == G_IO_ERROR_EXISTS)
            {
                fm_path_unref(dest);
                g_error_free(err);
                g_object_unref(gf);
                err = NULL;
                goto _retry;
            }
            fm_show_error(GTK_WINDOW(win), err->message);
            g_error_free(err);
        }

        if(!err) /* select the newly created file */
        {
            /*FIXME: this doesn't work since the newly created file will
             * only be shown after file-created event was fired on its
             * folder's monitor and after FmFolder handles it in idle
             * handler. So, we cannot select it since it's not yet in
             * the folder model now. */
            /* fm_folder_view_select_file_path(fv, dest); */
        }
        g_object_unref(gf);
    }
    else if( strcmp(name, "NewBlank") == 0 )
    {
        GFile* gf = fm_path_to_gfile(dest);
        GFileOutputStream* f = g_file_create(gf, G_FILE_CREATE_NONE, NULL, &err);
        if(f)
        {
            g_output_stream_close(G_OUTPUT_STREAM(f), NULL, NULL);
            g_object_unref(f);
        }
        else
        {
            if(err->domain = G_IO_ERROR && err->code == G_IO_ERROR_EXISTS)
            {
                fm_path_unref(dest);
                g_error_free(err);
                g_object_unref(gf);
                err = NULL;
                goto _retry;
            }
            fm_show_error(GTK_WINDOW(win), err->message);
            g_error_free(err);
        }

        if(!err) /* select the newly created file */
        {
            /*FIXME: this doesn't work since the newly created file will
             * only be shown after file-created event was fired on its
             * folder's monitor and after FmFolder handles it in idle
             * handler. So, we cannot select it since it's not yet in
             * the folder model now. */
            /* fm_folder_view_select_file_path(fv, dest); */
        }
        g_object_unref(gf);
    }
    else /* templates */
    {

    }
    fm_path_unref(dest);
}
Exemple #5
0
gboolean fm_dnd_dest_drag_drop(FmDndDest* dd, GdkDragContext *drag_context,
                               GdkAtom target, guint time)
{
    gboolean ret = FALSE;
    GtkWidget* dest_widget = dd->widget;
    int i;
    for(i = 0; i < G_N_ELEMENTS(fm_default_dnd_dest_targets); ++i)
    {
        if(gdk_atom_intern_static_string(fm_default_dnd_dest_targets[i].target) == target)
        {
            ret = TRUE;
            break;
        }
    }
    if(ret) /* we support this kind of target */
    {
        if(i == FM_DND_DEST_TARGET_XDS) /* if this is XDS */
        {
            guchar *data = NULL;
            gint len = 0;
            GdkAtom text_atom = gdk_atom_intern_static_string("text/plain");
            /* get filename from the source window */
            if(gdk_property_get(drag_context->source_window, xds_target_atom, text_atom,
                                0, 1024, FALSE, NULL, NULL,
                                &len, &data) && data)
            {
                FmFileInfo* dest = fm_dnd_dest_get_dest_file(dd);
                if( dest && fm_file_info_is_dir(dest) )
                {
                    FmPath* path = fm_path_new_child(dest->path, data);
                    char* uri = fm_path_to_uri(path);
                    /* setup the property */
                    gdk_property_change(GDK_DRAWABLE(drag_context->source_window), xds_target_atom,
                                       text_atom, 8, GDK_PROP_MODE_REPLACE, (const guchar *)uri,
                                       strlen(uri) + 1);
                    fm_path_unref(path);
                    g_free(uri);
                }
            }
            else
            {
                fm_show_error(gtk_widget_get_toplevel(dest_widget),
                              _("XDirectSave failed."));
                gdk_property_change(GDK_DRAWABLE(drag_context->source_window), xds_target_atom,
                                   text_atom, 8, GDK_PROP_MODE_REPLACE, (const guchar *)"", 0);
            }
            g_free(data);
            gtk_drag_get_data(dest_widget, drag_context, target, time);
            /* we should call gtk_drag_finish later in data-received callback. */
            return TRUE;
        }

        /* see if the drag files are cached */
        if(dd->src_files)
        {
            /* emit files-dropped signal */
            g_signal_emit(dd, signals[FILES_DROPPED], 0, drag_context->action, dd->info_type, dd->src_files, &ret);
        }
        else /* we don't have the data */
        {
            if(dd->waiting_data) /* if we're still waiting for the data */
            {
                /* FIXME: how to handle this? */
                ret = FALSE;
            }
            else
                ret = FALSE;
        }
        gtk_drag_finish(drag_context, ret, FALSE, time);
    }
    return ret;
}
static gboolean on_error(FmFileOpsJob* job, GError* err, gboolean recoverable, FmProgressDisplay* data)
{
    ensure_dlg(data);
    fm_show_error(GTK_WINDOW(data->dlg), err->message);
    return FALSE;
}
static void on_response (GtkDialog *dlg, int response, FmFilePropData *data)
{
    if ( response == GTK_RESPONSE_OK )
    {
        int sel;
        const char *new_owner = gtk_entry_get_text (GTK_ENTRY (data->owner));
        const char *new_group = gtk_entry_get_text (GTK_ENTRY (data->group));
        guint32 uid = -1, gid = -1;
        mode_t new_mode = 0, new_mode_mask = 0;

        if (!ensure_valid_owner (data) || !ensure_valid_group (data))
        {
            g_signal_stop_emission_by_name (dlg, "response");
            return;
        }

        /* FIXME_pcm: if all files are native, it's possible to check
         * if the names are legal user and group names on the local
         * machine prior to chown. */
        if (new_owner && *new_owner && g_strcmp0 (data->orig_owner, new_owner))
        {
            // change owner
            g_debug ("change owner to: %d", data->uid);
        }
        else
            data->uid = -1;

        if (new_group && *new_group && g_strcmp0 (data->orig_group, new_group))
        {
            // change group
            g_debug ("change group to: %d", data->gid);
        }
        else
            data->gid = -1;

        // check if chmod is needed here.
        sel = gtk_combo_box_get_active (GTK_COMBO_BOX (data->owner_perm));
        if ( sel != NO_CHANGE ) // need to change owner permission
        {
            if (data->owner_perm_sel != sel) // new value is different from original
            {
                new_mode_mask |= S_IRUSR|S_IWUSR;
                data->owner_perm_sel = sel;
                switch (sel)
                {
                case READ_WRITE:
                    new_mode |= S_IRUSR|S_IWUSR;
                    break;
                case READ_ONLY:
                    new_mode |= S_IRUSR;
                    break;
                case WRITE_ONLY:
                    new_mode |= S_IWUSR;
                    break;
                }
            }
            else // otherwise, no change
                data->owner_perm_sel = NO_CHANGE;
        }
        else
            data->owner_perm_sel = NO_CHANGE;

        sel = gtk_combo_box_get_active (GTK_COMBO_BOX (data->group_perm));
        if ( sel != NO_CHANGE ) // need to change group permission
        {
            if (data->group_perm_sel != sel) // new value is different from original
            {
                new_mode_mask |= S_IRGRP|S_IWGRP;
                data->group_perm_sel = sel;
                switch (sel)
                {
                case READ_WRITE:
                    new_mode |= S_IRGRP|S_IWGRP;
                    break;
                case READ_ONLY:
                    new_mode |= S_IRGRP;
                    break;
                case WRITE_ONLY:
                    new_mode |= S_IWGRP;
                    break;
                }
            }
            else // otherwise, no change
                data->group_perm_sel = NO_CHANGE;
        }
        else
            data->group_perm_sel = NO_CHANGE;

#if 0
        sel = gtk_combo_box_get_active (GTK_COMBO_BOX (data->other_perm));
        if ( sel != NO_CHANGE ) // need to change other permission
        {
            if (data->other_perm_sel != sel) // new value is different from original
            {
                new_mode_mask |= S_IROTH|S_IWOTH;
                switch (sel)
                {
                case READ_WRITE:
                    new_mode |= S_IROTH|S_IWOTH;
                    break;
                case READ_ONLY:
                    new_mode |= S_IROTH;
                    break;
                case WRITE_ONLY:
                    new_mode |= S_IWOTH;
                    break;
                }
                data->other_perm_sel = sel;
            }
            else // otherwise, no change
                data->other_perm_sel = NO_CHANGE;
        }
        else
            data->other_perm_sel = NO_CHANGE;

        if (!data->has_dir
                && !gtk_toggle_button_get_inconsistent (GTK_TOGGLE_BUTTON (data->exec))
                && gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->exec)) != data->exec_state)
        {
            new_mode_mask |=  (S_IXUSR|S_IXGRP|S_IXOTH);
            if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->exec)))
                new_mode |=  (S_IXUSR|S_IXGRP|S_IXOTH);
        }

        if (new_mode_mask || data->uid != -1 || data->gid != -1)
        {
            FmPathList *paths = fm_path_list_new_from_file_info_list (data->files);
            FmFileOpsJob *job = (FmFileOpsJob*) fm_file_ops_job_new (FM_FILE_OP_CHANGE_ATTR, paths);

            // need to chown
            if (data->uid != -1 || data->gid != -1)
                fm_file_ops_job_set_chown (job, data->uid, data->gid);

            // need to do chmod
            if (new_mode_mask)
                fm_file_ops_job_set_chmod (job, new_mode, new_mode_mask);

            if (data->has_dir)
            {
                if (fm_yes_no (GTK_WINDOW (data->dlg), NULL, _( "Do you want to recursively apply these changes to all files and sub-folders?" ), TRUE))
                    fm_file_ops_job_set_recursive (job, TRUE);
            }

            // show progress dialog
            fm_file_ops_job_run_with_progress (GTK_WINDOW (data->dlg), job);
            fm_list_unref (paths);
        }

        // change default application for the mime-type if needed
        if (data->mime_type && fm_mime_type_get_type (data->mime_type) && data->open_with)
        {
            GAppInfo *app;
            gboolean default_app_changed = FALSE;
            GError *err = NULL;
            app = fm_app_chooser_combo_box_get_selected (GTK_COMBO_BOX (data->open_with), &default_app_changed);
            if (app)
            {
                if (default_app_changed)
                {
                    g_app_info_set_as_default_for_type (app, fm_mime_type_get_type (data->mime_type), &err);
                    if (err)
                    {
                        fm_show_error (GTK_WINDOW (dlg), NULL, err->message);
                        g_error_free (err);
                    }
                }
                g_object_unref (app);
            }
        }

        if (data->single_file) // when only one file is shown
        {
            // if the user has changed its name
            if ( g_strcmp0 (data->file_info->disp_name, gtk_entry_get_text (GTK_ENTRY (data->name))) )
            {
                // FIXME_pcm: rename the file or set display name for it.
            }
        }
#endif
    }
    gtk_widget_destroy (GTK_WIDGET (dlg));
}
Exemple #8
0
static gboolean fm_do_mount(GtkWindow* parent, GObject* obj, MountAction action, gboolean interactive)
{
    gboolean ret;
    struct MountData* data = g_new0(struct MountData, 1);
    /* bug #3615234: it seems GtkMountOperations is buggy and sometimes leaves
       parent window reference intact while destroys itself so it leads to
       severe memory corruption, therefore we pass here NULL as parent window
       to gtk_mount_operation_new() to not bind it to anything as a workaround */
    GMountOperation* op = interactive ? gtk_mount_operation_new(NULL) : NULL;
    GCancellable* cancellable = g_cancellable_new();

    data->loop = g_main_loop_new (NULL, TRUE);
    data->action = action;

    switch(data->action)
    {
    case MOUNT_VOLUME:
        g_volume_mount(G_VOLUME(obj), 0, op, cancellable, on_mount_action_finished, data);
        break;
    case MOUNT_GFILE:
        g_file_mount_enclosing_volume(G_FILE(obj), 0, op, cancellable, on_mount_action_finished, data);
        break;
    case UMOUNT_MOUNT:
        prepare_unmount(G_MOUNT(obj));
        g_mount_unmount_with_operation(G_MOUNT(obj), G_MOUNT_UNMOUNT_NONE, op, cancellable, on_mount_action_finished, data);
        break;
    case EJECT_MOUNT:
        prepare_unmount(G_MOUNT(obj));
        g_mount_eject_with_operation(G_MOUNT(obj), G_MOUNT_UNMOUNT_NONE, op, cancellable, on_mount_action_finished, data);
        break;
    case EJECT_VOLUME:
        {
            GMount* mnt = g_volume_get_mount(G_VOLUME(obj));
            if (mnt) /* it might be unmounted already */
            {
                prepare_unmount(mnt);
                g_object_unref(mnt);
            }
            g_volume_eject_with_operation(G_VOLUME(obj), G_MOUNT_UNMOUNT_NONE, op, cancellable, on_mount_action_finished, data);
        }
        break;
    }

    /* FIXME: create progress window with busy cursor */
    if (g_main_loop_is_running(data->loop))
    {
        GDK_THREADS_LEAVE();
        g_main_loop_run(data->loop);
        GDK_THREADS_ENTER();
    }

    g_main_loop_unref(data->loop);

    ret = data->ret;
    if(data->err)
    {
        if(interactive)
        {
            if(data->err->domain == G_IO_ERROR)
            {
                if(data->err->code == G_IO_ERROR_FAILED)
                {
                    /* Generate a more human-readable error message instead of using a gvfs one. */

                    /* The original error message is something like:
                     * Error unmounting: umount exited with exit code 1:
                     * helper failed with: umount: only root can unmount
                     * UUID=18cbf00c-e65f-445a-bccc-11964bdea05d from /media/sda4 */

                    /* Why they pass this back to us?
                     * This is not human-readable for the users at all. */

                    if(strstr(data->err->message, "only root can "))
                    {
                        g_debug("%s", data->err->message);
                        g_free(data->err->message);
                        data->err->message = g_strdup(_("Only system administrators have the permission to do this."));
                    }
                }
                else if(data->err->code == G_IO_ERROR_FAILED_HANDLED)
                    interactive = FALSE;
            }
            if(interactive)
                fm_show_error(parent, NULL, data->err->message);
        }
        g_error_free(data->err);
    }

    g_free(data);
    g_object_unref(cancellable);
    if(op)
        g_object_unref(op);
    return ret;
}