/*
* Copyright © 2016 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see .
*
* Authors:
* Alexander Larsson
* Matthias Clasen
*/
#include "config.h"
#include
#include
#include
#include
#include
#include
#include "xdp-dbus.h"
#include "xdp-utils.h"
#include "documents.h"
#include "document-enums.h"
static XdpDbusDocuments *documents = NULL;
static char *documents_mountpoint = NULL;
void
init_document_proxy (GDBusConnection *connection)
{
documents = xdp_dbus_documents_proxy_new_sync (connection, 0,
"org.freedesktop.portal.Documents",
"/org/freedesktop/portal/documents",
NULL, NULL);
xdp_dbus_documents_call_get_mount_point_sync (documents,
&documents_mountpoint,
NULL, NULL);
xdp_set_documents_mountpoint (documents_mountpoint);
}
char *
register_document (const char *uri,
const char *app_id,
DocumentFlags flags,
GError **error)
{
g_autofree char *doc_id = NULL;
g_auto(GStrv) doc_ids = NULL;
g_autofree char *path = NULL;
g_autofree char *basename = NULL;
g_autofree char *dirname = NULL;
GUnixFDList *fd_list = NULL;
int fd, fd_in;
g_autoptr(GFile) file = NULL;
gboolean ret = FALSE;
const char *permissions[5];
g_autofree char *doc_path = NULL;
int i;
int version;
gboolean handled_permissions = FALSE;
DocumentAddFullFlags full_flags;
g_return_val_if_fail (app_id != NULL && *app_id != '\0', NULL);
file = g_file_new_for_uri (uri);
path = g_file_get_path (file);
basename = g_path_get_basename (path);
dirname = g_path_get_dirname (path);
if (flags & DOCUMENT_FLAG_FOR_SAVE)
fd = open (dirname, O_PATH | O_CLOEXEC);
else
fd = open (path, O_PATH | O_CLOEXEC);
if (fd == -1)
{
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno),
"Failed to open %s", uri);
return NULL;
}
fd_list = g_unix_fd_list_new ();
fd_in = g_unix_fd_list_append (fd_list, fd, error);
close (fd);
if (fd_in == -1)
return NULL;
i = 0;
permissions[i++] = "read";
if ((flags & DOCUMENT_FLAG_WRITABLE) || (flags & DOCUMENT_FLAG_FOR_SAVE))
permissions[i++] = "write";
permissions[i++] = "grant-permissions";
if (flags & DOCUMENT_FLAG_DELETABLE)
permissions[i++] = "delete";
permissions[i++] = NULL;
version = xdp_dbus_documents_get_version (documents);
full_flags = DOCUMENT_ADD_FLAGS_REUSE_EXISTING | DOCUMENT_ADD_FLAGS_PERSISTENT | DOCUMENT_ADD_FLAGS_AS_NEEDED_BY_APP;
if (flags & DOCUMENT_FLAG_DIRECTORY)
full_flags |= DOCUMENT_ADD_FLAGS_DIRECTORY;
if (flags & DOCUMENT_FLAG_FOR_SAVE)
{
if (version >= 3)
{
ret = xdp_dbus_documents_call_add_named_full_sync (documents,
g_variant_new_handle (fd_in),
basename,
full_flags,
app_id,
permissions,
fd_list,
&doc_id,
NULL,
NULL,
NULL,
error);
handled_permissions = TRUE;
}
else
ret = xdp_dbus_documents_call_add_named_sync (documents,
g_variant_new_handle (fd_in),
basename,
TRUE,
TRUE,
fd_list,
&doc_id,
NULL,
NULL,
error);
}
else
{
if (version >= 2)
{
ret = xdp_dbus_documents_call_add_full_sync (documents,
g_variant_new_fixed_array (G_VARIANT_TYPE_HANDLE, &fd_in, 1, sizeof (gint32)),
full_flags,
app_id,
permissions,
fd_list,
&doc_ids,
NULL,
NULL,
NULL,
error);
handled_permissions = TRUE;
}
else
ret = xdp_dbus_documents_call_add_sync (documents,
g_variant_new_handle (fd_in),
TRUE,
TRUE,
fd_list,
&doc_id,
NULL,
NULL,
error);
}
g_object_unref (fd_list);
if (!ret)
return NULL;
if (doc_ids && doc_ids[0]) {
doc_id = g_strdup (doc_ids[0]);
}
if (!handled_permissions)
{
if (!xdp_dbus_documents_call_grant_permissions_sync (documents,
doc_id,
app_id,
permissions,
NULL,
error))
return NULL;
}
if (!g_strcmp0 (doc_id, ""))
{
doc_path = g_build_filename (path, NULL);
return g_filename_to_uri (doc_path, NULL, NULL);
}
doc_path = g_build_filename (documents_mountpoint, doc_id, basename, NULL);
return g_filename_to_uri (doc_path, NULL, NULL);
}
char *
get_real_path_for_doc_path (const char *path,
XdpAppInfo *app_info)
{
g_autofree char *doc_id = NULL;
gboolean ret = FALSE;
g_autoptr(GError) error = NULL;
if (xdp_app_info_is_host (app_info))
return g_strdup (path);
ret = xdp_dbus_documents_call_lookup_sync (documents, path, &doc_id, NULL, &error);
if (!ret)
{
g_debug ("document portal error for path '%s': %s", path, error->message);
return g_strdup (path);
}
if (!g_strcmp0 (doc_id, ""))
{
g_debug ("document portal returned empty doc id for path '%s'", path);
return g_strdup (path);
}
return get_real_path_for_doc_id (doc_id);
}
char *
get_real_path_for_doc_id (const char *doc_id)
{
gboolean ret = FALSE;
char *real_path = NULL;
g_autoptr (GError) error = NULL;
ret = xdp_dbus_documents_call_info_sync (documents, doc_id, &real_path, NULL, NULL, &error);
if (!ret)
{
g_debug ("document portal error for doc id '%s': %s", doc_id, error->message);
return NULL;
}
return real_path;
}