--- ./daemon/gvfsftpfile.h.orig 2021-04-30 06:19:33.184706000 -0500 +++ ./daemon/gvfsftpfile.h 2026-02-28 15:20:38.488741716 -0600 @@ -31,7 +31,8 @@ typedef struct _GVfsFtpFile GVfsFtpFile; GVfsFtpFile * g_vfs_ftp_file_new_from_gvfs (GVfsBackendFtp * ftp, - const char * gvfs_path); + const char * gvfs_path, + GError ** error); GVfsFtpFile * g_vfs_ftp_file_new_from_ftp (GVfsBackendFtp * ftp, const char * ftp_path); GVfsFtpFile * g_vfs_ftp_file_new_parent (const GVfsFtpFile * file); --- ./daemon/gvfsbackendftp.c.orig 2021-04-30 06:19:33.176705800 -0500 +++ ./daemon/gvfsbackendftp.c 2026-02-28 15:24:10.950729964 -0600 @@ -867,9 +867,14 @@ error_550_permission_or_not_found, NULL }; - g_vfs_ftp_task_setup_data_connection (&task); - file = g_vfs_ftp_file_new_from_gvfs (ftp, filename); + file = g_vfs_ftp_file_new_from_gvfs (ftp, filename, &task.error); + if (file == NULL) + { + g_vfs_ftp_task_done (&task); + return; + } + g_vfs_ftp_task_setup_data_connection (&task); g_vfs_ftp_task_send_and_check (&task, G_VFS_FTP_PASS_100 | G_VFS_FTP_FAIL_200, open_read_handlers, @@ -988,7 +993,13 @@ GFileInfo *info; GVfsFtpFile *file; - file = g_vfs_ftp_file_new_from_gvfs (ftp, filename); + file = g_vfs_ftp_file_new_from_gvfs (ftp, filename, &task.error); + if (file == NULL) + { + g_vfs_ftp_task_done (&task); + return; + } + info = g_vfs_ftp_dir_cache_lookup_file (ftp->dir_cache, &task, file, FALSE); if (info) { @@ -1018,7 +1029,13 @@ GVfsFtpTask task = G_VFS_FTP_TASK_INIT (ftp, G_VFS_JOB (job)); GVfsFtpFile *file; - file = g_vfs_ftp_file_new_from_gvfs (ftp, filename); + file = g_vfs_ftp_file_new_from_gvfs (ftp, filename, &task.error); + if (file == NULL) + { + g_vfs_ftp_task_done (&task); + return; + } + do_start_write (&task, flags, "APPE %s", g_vfs_ftp_file_get_ftp_path (file)); g_vfs_ftp_dir_cache_purge_file (ftp->dir_cache, file); g_vfs_ftp_file_free (file); @@ -1040,14 +1057,25 @@ static const GVfsFtpErrorFunc rnfr_handlers[] = { error_550_permission_or_not_found, NULL }; - file = g_vfs_ftp_file_new_from_gvfs (ftp, filename); + file = g_vfs_ftp_file_new_from_gvfs (ftp, filename, &task.error); + if (file == NULL) + { + g_vfs_ftp_task_done (&task); + return; + } if (make_backup) { GFileInfo *info; char *backup_path = g_strconcat (filename, "~", NULL); - backupfile = g_vfs_ftp_file_new_from_gvfs (ftp, backup_path); + backupfile = g_vfs_ftp_file_new_from_gvfs (ftp, backup_path, &task.error); g_free (backup_path); + if (backupfile == NULL) + { + g_vfs_ftp_file_free (file); + g_vfs_ftp_task_done (&task); + return; + } info = g_vfs_ftp_dir_cache_lookup_file (ftp->dir_cache, &task, file, FALSE); @@ -1117,7 +1145,7 @@ stream = g_vfs_ftp_connection_get_data_stream (conn); filename = g_object_get_data (G_OBJECT (stream), "g-vfs-backend-ftp-filename"); - file = g_vfs_ftp_file_new_from_gvfs (ftp, filename); + file = g_vfs_ftp_file_new_from_gvfs (ftp, filename, NULL); g_vfs_ftp_task_give_connection (&task, handle); g_vfs_ftp_task_close_data_connection (&task); @@ -1169,8 +1197,14 @@ GVfsFtpTask task = G_VFS_FTP_TASK_INIT (ftp, G_VFS_JOB (job)); GVfsFtpFile *file; GFileInfo *real; - - file = g_vfs_ftp_file_new_from_gvfs (ftp, filename); + + file = g_vfs_ftp_file_new_from_gvfs (ftp, filename, &task.error); + if (file == NULL) + { + g_vfs_ftp_task_done (&task); + return; + } + real = g_vfs_ftp_dir_cache_lookup_file (ftp->dir_cache, &task, file, @@ -1238,7 +1272,12 @@ GVfsFtpTask task = G_VFS_FTP_TASK_INIT (ftp, G_VFS_JOB (job)); GVfsFtpFile *file; - file = g_vfs_ftp_file_new_from_gvfs (ftp, filename); + file = g_vfs_ftp_file_new_from_gvfs (ftp, filename, &task.error); + if (file == NULL) + { + g_vfs_ftp_task_done (&task); + return; + } if (strcmp (attribute, G_FILE_ATTRIBUTE_UNIX_MODE) == 0) { @@ -1294,7 +1333,13 @@ GVfsFtpFile *dir; GList *list, *walk; - dir = g_vfs_ftp_file_new_from_gvfs (ftp, dirname); + dir = g_vfs_ftp_file_new_from_gvfs (ftp, dirname, &task.error); + if (dir == NULL) + { + g_vfs_ftp_task_done (&task); + return; + } + list = g_vfs_ftp_dir_cache_lookup_dir (ftp->dir_cache, &task, dir, @@ -1336,9 +1381,23 @@ GVfsFtpTask task = G_VFS_FTP_TASK_INIT (ftp, G_VFS_JOB (job)); GVfsFtpFile *original, *dir, *now; - original = g_vfs_ftp_file_new_from_gvfs (ftp, filename); + original = g_vfs_ftp_file_new_from_gvfs (ftp, filename, &task.error); + if (original == NULL) + { + g_vfs_ftp_task_done (&task); + return; + } + dir = g_vfs_ftp_file_new_parent (original); now = g_vfs_ftp_file_new_child (dir, display_name, &task.error); + if (now == NULL) + { + g_vfs_ftp_file_free (original); + g_vfs_ftp_file_free (dir); + g_vfs_ftp_task_done (&task); + return; + } + g_vfs_ftp_task_send (&task, G_VFS_FTP_PASS_300 | G_VFS_FTP_FAIL_200, "RNFR %s", g_vfs_ftp_file_get_ftp_path (original)); @@ -1368,7 +1427,13 @@ /* We try file deletion first. If that fails, we try directory deletion. * The file-first-then-directory order has been decided by coin-toss. */ - file = g_vfs_ftp_file_new_from_gvfs (ftp, filename); + file = g_vfs_ftp_file_new_from_gvfs (ftp, filename, &task.error); + if (file == NULL) + { + g_vfs_ftp_task_done (&task); + return; + } + response = g_vfs_ftp_task_send (&task, G_VFS_FTP_PASS_500, "DELE %s", g_vfs_ftp_file_get_ftp_path (file)); @@ -1416,7 +1481,13 @@ GVfsFtpFile *file; static const GVfsFtpErrorFunc make_directory_handlers[] = { error_550_exists, error_550_parent_not_found, NULL }; - file = g_vfs_ftp_file_new_from_gvfs (ftp, filename); + file = g_vfs_ftp_file_new_from_gvfs (ftp, filename, &task.error); + if (file == NULL) + { + g_vfs_ftp_task_done (&task); + return; + } + g_vfs_ftp_task_send_and_check (&task, 0, make_directory_handlers, @@ -1447,6 +1518,21 @@ static const GVfsFtpErrorFunc rnfr_handlers[] = { error_550_permission_or_not_found, NULL }; + srcfile = g_vfs_ftp_file_new_from_gvfs (ftp, source, &task.error); + if (srcfile == NULL) + { + g_vfs_ftp_task_done (&task); + return; + } + + destfile = g_vfs_ftp_file_new_from_gvfs (ftp, destination, &task.error); + if (destfile == NULL) + { + g_vfs_ftp_file_free (srcfile); + g_vfs_ftp_task_done (&task); + return; + } + /* FIXME: what about G_FILE_COPY_NOFOLLOW_SYMLINKS and G_FILE_COPY_ALL_METADATA? */ if (flags & G_FILE_COPY_BACKUP) @@ -1474,8 +1560,6 @@ return; } - srcfile = g_vfs_ftp_file_new_from_gvfs (ftp, source); - destfile = g_vfs_ftp_file_new_from_gvfs (ftp, destination); if (g_vfs_ftp_task_try_cd (&task, destfile)) { char *basename = g_path_get_basename (source); @@ -1613,7 +1697,13 @@ GOutputStream *output; goffset total_size = 0; - src = g_vfs_ftp_file_new_from_gvfs (ftp, source); + src = g_vfs_ftp_file_new_from_gvfs (ftp, source, &task.error); + if (src == NULL) + { + g_vfs_ftp_task_done (&task); + return; + } + dest = g_file_new_for_path (local_path); if (remove_source && (flags & G_FILE_COPY_NO_FALLBACK_FOR_MOVE)) --- ./daemon/gvfsftpfile.c.orig 2021-04-30 06:19:33.184706000 -0500 +++ ./daemon/gvfsftpfile.c 2026-02-28 15:18:59.574293336 -0600 @@ -68,19 +68,29 @@ * g_vfs_ftp_file_new_from_gvfs: * @ftp: the ftp backend this file is to be used on * @gvfs_path: gvfs path to create the file from + * @error: location to take an eventual error or %NULL * - * Constructs a new #GVfsFtpFile representing the given gvfs path. + * Constructs a new #GVfsFtpFile representing the given gvfs path. If the + * display name is invalid, @error is set and %NULL is returned. * - * Returns: a new file + * Returns: a new file or %NULL on error **/ GVfsFtpFile * -g_vfs_ftp_file_new_from_gvfs (GVfsBackendFtp *ftp, const char *gvfs_path) +g_vfs_ftp_file_new_from_gvfs (GVfsBackendFtp *ftp, const char *gvfs_path, GError **error) { GVfsFtpFile *file; g_return_val_if_fail (G_VFS_IS_BACKEND_FTP (ftp), NULL); g_return_val_if_fail (gvfs_path != NULL, NULL); + if (strpbrk (gvfs_path, "\r\n") != NULL) + { + g_set_error_literal (error, + G_IO_ERROR, G_IO_ERROR_INVALID_FILENAME, + _("Filename contains invalid characters.")); + return NULL; + } + file = g_slice_new (GVfsFtpFile); file->backend = g_object_ref (ftp); file->gvfs_path = g_strdup (gvfs_path); @@ -136,7 +146,7 @@ return g_vfs_ftp_file_copy (file); dirname = g_path_get_dirname (file->gvfs_path); - dir = g_vfs_ftp_file_new_from_gvfs (file->backend, dirname); + dir = g_vfs_ftp_file_new_from_gvfs (file->backend, dirname, NULL); g_free (dirname); return dir; @@ -163,7 +173,7 @@ g_return_val_if_fail (parent != NULL, NULL); g_return_val_if_fail (display_name != NULL, NULL); - if (strpbrk (display_name, "/\r\n")) + if (strchr (display_name, '/') != NULL) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_INVALID_FILENAME, @@ -172,7 +182,7 @@ } new_path = g_strconcat (parent->gvfs_path, parent->gvfs_path[1] == 0 ? "" : "/", display_name, NULL); - child = g_vfs_ftp_file_new_from_gvfs (parent->backend, new_path); + child = g_vfs_ftp_file_new_from_gvfs (parent->backend, new_path, error); g_free (new_path); return child; }