Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 45 additions & 6 deletions packages/desktop_drop/linux/desktop_drop_plugin.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,50 @@ G_DEFINE_TYPE(DesktopDropPlugin, desktop_drop_plugin, g_object_get_type())
void on_drag_data_received(GtkWidget *widget, GdkDragContext *drag_context,
gint x, gint y, GtkSelectionData *sdata, guint info,
guint time, gpointer user_data) {
// When dragging from different file managers we may receive a plain string
// (e.g. "dde-fileManager") instead of real URIs. Use gtk_selection_data_get_uris
// which understands the "text/uri-list" format and returns an array of
// URI strings. Convert those to local filenames and join with newlines.
Comment on lines +24 to +27
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description mentions updates to CHANGELOG.md (an “Unreleased” entry) and the example app’s printFiles for defensive path handling, but those changes aren’t present in this PR branch (CHANGELOG has no “Unreleased” section; example printFiles still calls lastModified/length without guards). Either include those commits or adjust the PR description so it matches what’s being merged.

Copilot uses AI. Check for mistakes.
auto *channel = static_cast<FlMethodChannel *>(user_data);
auto *data = gtk_selection_data_get_data(sdata);
double point[] = {double(x), double(y)};

gchar *text = nullptr;
gchar **uris = gtk_selection_data_get_uris(sdata);
if (uris) {
// build newline-separated list of file paths
GString *builder = g_string_new(NULL);
for (gchar **uri = uris; *uri; uri++) {
gchar *filename = g_filename_from_uri(*uri, nullptr, nullptr);
if (!filename) {
// if conversion failed, fall back to raw URI
filename = g_strdup(*uri);
}
if (builder->len > 0) {
g_string_append(builder, "\n");
}
g_string_append(builder, filename);
g_free(filename);
Comment on lines +34 to +46
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Linux Dart handler currently does Uri.tryParse(line)?.toFilePath(), which expects each line to be a valid URI string. Converting URIs to decoded local filenames here (via g_filename_from_uri) can produce paths containing spaces or other characters that are invalid in a URI, causing Uri.tryParse to return null and the dropped file to be silently ignored. Prefer joining and sending the original URIs from gtk_selection_data_get_uris() as-is (or re-encoding filenames back into file:// URIs) so Dart parsing remains robust.

Suggested change
// build newline-separated list of file paths
GString *builder = g_string_new(NULL);
for (gchar **uri = uris; *uri; uri++) {
gchar *filename = g_filename_from_uri(*uri, nullptr, nullptr);
if (!filename) {
// if conversion failed, fall back to raw URI
filename = g_strdup(*uri);
}
if (builder->len > 0) {
g_string_append(builder, "\n");
}
g_string_append(builder, filename);
g_free(filename);
// build newline-separated list of URIs (keep them as URIs for Dart)
GString *builder = g_string_new(NULL);
for (gchar **uri = uris; *uri; uri++) {
if (builder->len > 0) {
g_string_append(builder, "\n");
}
g_string_append(builder, *uri);

Copilot uses AI. Check for mistakes.
}
text = g_string_free(builder, FALSE);
g_strfreev(uris);
} else {
// fallback to the raw data as before
auto *data = gtk_selection_data_get_data(sdata);
if (data) {
text = g_strdup((gchar *)data);
Comment on lines +51 to +54
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fallback path uses gtk_selection_data_get_data() and then g_strdup((gchar*)data), but gtk_selection_data_get_data() returns a byte buffer that is not guaranteed to be NUL-terminated. This can lead to reading past the buffer or truncation if embedded NULs exist. Use gtk_selection_data_get_text() for text targets, or use gtk_selection_data_get_length() and g_strndup() to duplicate a bounded buffer safely.

Suggested change
// fallback to the raw data as before
auto *data = gtk_selection_data_get_data(sdata);
if (data) {
text = g_strdup((gchar *)data);
// fallback to the raw data as before, but respect the buffer length
gint length = gtk_selection_data_get_length(sdata);
const guchar *data = gtk_selection_data_get_data(sdata);
if (data != nullptr && length > 0) {
text = g_strndup((const gchar *)data, (gsize)length);

Copilot uses AI. Check for mistakes.
}
}

if (!text) {
text = g_strdup("");
}

auto args = fl_value_new_list();
fl_value_append(args, fl_value_new_string((gchar *) data));
fl_value_append(args, fl_value_new_string(text));
fl_value_append(args, fl_value_new_float_list(point, 2));
fl_method_channel_invoke_method(channel, "performOperation_linux", args,
nullptr, nullptr, nullptr);
g_free(text);
}

void on_drag_motion(GtkWidget *widget, GdkDragContext *drag_context,
Expand Down Expand Up @@ -95,11 +131,14 @@ void desktop_drop_plugin_register_with_registrar(FlPluginRegistrar *registrar) {
g_object_new(desktop_drop_plugin_get_type(), nullptr));

auto *fl_view = fl_plugin_registrar_get_view(registrar);
static GtkTargetEntry entries[] = {
{strdup("STRING"), GTK_TARGET_OTHER_APP, 0}
};
gtk_drag_dest_set(GTK_WIDGET(fl_view), GTK_DEST_DEFAULT_ALL, entries, 1, GDK_ACTION_COPY);
// Use URI targets for file drops and avoid forcing the generic STRING
// target first. Prioritize text/uri-list so we receive actual file
// URIs instead of application names like "dde-fileManager".
gtk_drag_dest_set(GTK_WIDGET(fl_view), GTK_DEST_DEFAULT_ALL, nullptr, 0, GDK_ACTION_COPY);
gtk_drag_dest_add_uri_targets(GTK_WIDGET(fl_view));
// In case a source doesn't provide URI targets we still accept generic
// text, but it is added _after_ the URI targets so it has lower priority.
gtk_drag_dest_add_text_targets(GTK_WIDGET(fl_view));

g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
FlMethodChannel *channel =
Expand Down
Loading