document-portals: Support unique documents

These document id will not be shared for multiple users. The main
difference is this this makes it safe for the creating app to delete
the document if he wants to (i.e. for temporary docs), and thus we can
grant this additional permission for the calling app.
tingping/wmclass
Alexander Larsson 2015-09-04 14:46:02 +02:00
parent 83201bd7e4
commit 7ad47c74ea
5 changed files with 45 additions and 16 deletions

View File

@ -36,7 +36,10 @@
#include "xdg-app-utils.h"
#include "xdg-app-run.h"
gboolean opt_unique = FALSE;
static GOptionEntry options[] = {
{ "unique", 'u', 0, G_OPTION_ARG_NONE, &opt_unique, "Create a unique document reference", NULL },
{ NULL }
};
@ -99,7 +102,7 @@ xdg_app_builtin_export_file (int argc, char **argv,
"/org/freedesktop/portal/documents",
"org.freedesktop.portal.Documents",
"Add",
g_variant_new ("(h)", fd_id),
g_variant_new ("(hb)", fd_id, !opt_unique),
G_VARIANT_TYPE ("(s)"),
G_DBUS_CALL_FLAGS_NONE,
30000,

View File

@ -30,6 +30,7 @@
</method>
<method name="Add">
<arg type='h' name='o_path_fd' direction='in'/>
<arg type='b' name='reuse_existing' direction='in'/>
<arg type='s' name='doc_id' direction='out'/>
</method>
<method name="GrantPermissions">

View File

@ -228,23 +228,30 @@ portal_delete (GDBusMethodInvocation *invocation,
}
char *
do_create_doc (struct stat *parent_st_buf, const char *path)
do_create_doc (struct stat *parent_st_buf, const char *path, gboolean reuse_existing)
{
g_autoptr(GVariant) data = NULL;
g_autoptr (XdgAppDbEntry) entry = NULL;
g_auto(GStrv) ids = NULL;
char *id = NULL;
guint32 flags = 0;
if (!reuse_existing)
flags |= XDP_ENTRY_FLAG_UNIQUE;
data =
g_variant_ref_sink (g_variant_new ("(^aytt)",
g_variant_ref_sink (g_variant_new ("(^ayttu)",
path,
(guint64)parent_st_buf->st_dev,
(guint64)parent_st_buf->st_ino));
(guint64)parent_st_buf->st_ino,
flags));
ids = xdg_app_db_list_ids_by_value (db, data);
if (reuse_existing)
{
ids = xdg_app_db_list_ids_by_value (db, data);
if (ids[0] != NULL)
return g_strdup (ids[0]); /* Reuse pre-existing entry with same path */
if (ids[0] != NULL)
return g_strdup (ids[0]); /* Reuse pre-existing entry with same path */
}
while (TRUE)
{
@ -288,8 +295,9 @@ portal_add (GDBusMethodInvocation *invocation,
struct stat st_buf, real_st_buf, real_parent_st_buf;
g_autofree char *dirname = NULL;
g_autofree char *name = NULL;
gboolean reuse_existing;
g_variant_get (parameters, "(h)", &fd_id);
g_variant_get (parameters, "(hb)", &fd_id, &reuse_existing);
message = g_dbus_method_invocation_get_message (invocation);
fd_list = g_dbus_message_get_unix_fd_list (message);
@ -346,17 +354,23 @@ portal_add (GDBusMethodInvocation *invocation,
return;
}
id = do_create_doc (&real_parent_st_buf, path_buffer);
id = do_create_doc (&real_parent_st_buf, path_buffer, reuse_existing);
if (app_id[0] != '\0')
{
g_autoptr(XdgAppDbEntry) entry = NULL;
XdpPermissionFlags perms =
XDP_PERMISSION_FLAGS_GRANT_PERMISSIONS |
XDP_PERMISSION_FLAGS_READ |
XDP_PERMISSION_FLAGS_WRITE;
entry = xdg_app_db_lookup (db, id);
do_set_permissions (entry, id, app_id,
XDP_PERMISSION_FLAGS_GRANT_PERMISSIONS |
XDP_PERMISSION_FLAGS_READ |
XDP_PERMISSION_FLAGS_WRITE);
/* If its a unique one its safe for the creator to
delete it at will */
if (!reuse_existing)
perms |= XDP_PERMISSION_FLAGS_DELETE;
do_set_permissions (entry, id, app_id, perms);
}
g_dbus_method_invocation_return_value (invocation,

View File

@ -51,7 +51,7 @@ xdp_parse_permissions (const char **permissions)
XdpPermissionFlags
xdp_entry_get_permissions (XdgAppDbEntry *entry,
const char *app_id)
const char *app_id)
{
g_autofree const char **permissions = NULL;
@ -64,8 +64,8 @@ xdp_entry_get_permissions (XdgAppDbEntry *entry,
gboolean
xdp_entry_has_permissions (XdgAppDbEntry *entry,
const char *app_id,
XdpPermissionFlags perms)
const char *app_id,
XdpPermissionFlags perms)
{
XdpPermissionFlags current_perms;
@ -126,6 +126,14 @@ xdp_entry_get_inode (XdgAppDbEntry *entry)
return g_variant_get_uint64 (c);
}
guint32
xdp_entry_get_flags (XdgAppDbEntry *entry)
{
g_autoptr(GVariant) v = xdg_app_db_entry_get_data (entry);
g_autoptr(GVariant) c = g_variant_get_child_value (v, 3);
return g_variant_get_uint32 (c);
}
int
xdp_entry_open_dir (XdgAppDbEntry *entry)
{

View File

@ -7,6 +7,8 @@
G_BEGIN_DECLS
#define XDP_ENTRY_FLAG_UNIQUE (1<<0)
const char ** xdg_unparse_permissions (XdpPermissionFlags permissions);
XdpPermissionFlags xdp_parse_permissions (const char **permissions);
@ -20,6 +22,7 @@ char * xdp_entry_dup_basename (XdgAppDbEntry *entry);
char * xdp_entry_dup_dirname (XdgAppDbEntry *entry);
guint64 xdp_entry_get_device (XdgAppDbEntry *entry);
guint64 xdp_entry_get_inode (XdgAppDbEntry *entry);
guint32 xdp_entry_get_flags (XdgAppDbEntry *entry);
int xdp_entry_open_dir (XdgAppDbEntry *entry);
int xdp_entry_stat (XdgAppDbEntry *entry,
struct stat *buf,