summaryrefslogtreecommitdiff
path: root/src/librygel-server/rygel-item-updater.vala
diff options
context:
space:
mode:
Diffstat (limited to 'src/librygel-server/rygel-item-updater.vala')
-rw-r--r--src/librygel-server/rygel-item-updater.vala178
1 files changed, 178 insertions, 0 deletions
diff --git a/src/librygel-server/rygel-item-updater.vala b/src/librygel-server/rygel-item-updater.vala
new file mode 100644
index 00000000..600ba70e
--- /dev/null
+++ b/src/librygel-server/rygel-item-updater.vala
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * Author: Krzesimir Nowak <krnowak@openismus.com>
+ *
+ * This file is part of Rygel.
+ *
+ * Rygel 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.
+ *
+ * Rygel 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 program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+using GUPnP;
+using Gee;
+
+/**
+ * UpdateObject action implementation.
+ */
+internal class Rygel.ItemUpdater: GLib.Object, Rygel.StateMachine {
+ private string object_id;
+ private string current_tag_value;
+ private string new_tag_value;
+
+ private ContentDirectory content_dir;
+ private ServiceAction action;
+
+ public Cancellable cancellable { get; set; }
+
+ public ItemUpdater (ContentDirectory content_dir,
+ owned ServiceAction action) {
+ this.content_dir = content_dir;
+ this.cancellable = content_dir.cancellable;
+ this.action = (owned) action;
+ }
+
+ public async void run () {
+ try {
+ this.action.get ("ObjectID",
+ typeof (string),
+ out this.object_id,
+ "CurrentTagValue",
+ typeof (string),
+ out this.current_tag_value,
+ "NewTagValue",
+ typeof (string),
+ out this.new_tag_value);
+ if (this.object_id == null) {
+ // Sorry we can't do anything without the ID
+ throw new ContentDirectoryError.NO_SUCH_OBJECT
+ (_("No such object"));
+ }
+
+ yield this.update_object ();
+
+ this.action.return ();
+
+ debug (_("Successfully updated object '%s'"), this.object_id);
+ } catch (Error error) {
+ if (error is ContentDirectoryError) {
+ this.action.return_error (error.code, error.message);
+ } else {
+ this.action.return_error (701, error.message);
+ }
+
+ warning (_("Failed to update object '%s': %s"),
+ this.object_id,
+ error.message);
+ }
+
+ this.completed ();
+ }
+
+ private static LinkedList<string> csv_split (string? tag_values) {
+ var list = new LinkedList<string> ();
+ var escape = false;
+ var token_start = 0;
+ var token_length = 0;
+ var len = (tag_values != null ? tag_values.length : 0);
+
+ for (int iter = 0; iter < len; ++iter) {
+ var c = tag_values[iter];
+
+ if (escape) {
+ escape = false;
+ } else {
+ switch (c) {
+ case '\\':
+ escape = true;
+
+ break;
+ case ',':
+ list.add (tag_values.substring (token_start, token_length));
+ token_start += token_length + 1;
+ token_length = 0;
+
+ break;
+ }
+ }
+ ++token_length;
+ }
+
+ // Single tag value only
+ if (len > 0 && list.is_empty) {
+ list.add (tag_values);
+ }
+
+ return list;
+ }
+
+ private async void update_object () throws Error {
+ var media_object = yield this.fetch_object ();
+ var current_list = csv_split (this.current_tag_value);
+ var new_list = csv_split (this.new_tag_value);
+
+
+ switch (media_object.apply_fragments (current_list,
+ new_list,
+ this.content_dir.http_server)) {
+ case DIDLLiteFragmentResult.OK:
+ break;
+ case DIDLLiteFragmentResult.CURRENT_BAD_XML:
+ case DIDLLiteFragmentResult.CURRENT_INVALID:
+ throw new ContentDirectoryError.INVALID_CURRENT_TAG_VALUE
+ ("Bad current tag value.");
+ case DIDLLiteFragmentResult.NEW_BAD_XML:
+ case DIDLLiteFragmentResult.NEW_INVALID:
+ throw new ContentDirectoryError.INVALID_NEW_TAG_VALUE
+ ("Bad current tag value.");
+ case DIDLLiteFragmentResult.REQUIRED_TAG:
+ throw new ContentDirectoryError.REQUIRED_TAG
+ ("Tried to delete required tag.");
+ case DIDLLiteFragmentResult.READONLY_TAG:
+ throw new ContentDirectoryError.READ_ONLY_TAG
+ ("Tried to change read-only property.");
+ case DIDLLiteFragmentResult.MISMATCH:
+ throw new ContentDirectoryError.PARAMETER_MISMATCH
+ ("Parameter count mismatch.");
+ default:
+ throw new ContentDirectoryError.NO_SUCH_OBJECT ("Unknown error.");
+ }
+ }
+
+ private async MediaObject fetch_object () throws Error {
+ var media_object = yield this.content_dir.root_container.find_object
+ (this.object_id,
+ this.cancellable);
+
+ if (media_object == null) {
+ throw new ContentDirectoryError.NO_SUCH_OBJECT
+ (_("No such object"));
+ } else if (!(OCMFlags.CHANGE_METADATA in media_object.ocm_flags)) {
+ var msg = _("Metadata modification of object %s not allowed");
+
+ throw new ContentDirectoryError.RESTRICTED_OBJECT (msg,
+ media_object.id);
+ } else if (media_object.parent.restricted) {
+ var msg = _("Metadata modification of object %s being a child " +
+ "of restricted object %s not allowed");
+
+ throw new ContentDirectoryError.RESTRICTED_PARENT
+ (msg,
+ media_object.id,
+ media_object.parent.id);
+ }
+
+ return media_object;
+ }
+}