From 20fd9872965a65121c4497fb166eda15b1a9f360 Mon Sep 17 00:00:00 2001 From: Bharat Mediratta Date: Sat, 7 Aug 2010 22:33:01 -0700 Subject: A new REST resource that allows access to view and modify the actual contents of the file, which enables REST viewers to see the actual data which is useful when the files are privileged. Currently it returns the contents of the file in JSON encoded form, which may not be the best. Multipart/mime might be much better. Fixes ticket #1224. --- modules/gallery/helpers/data_rest.php | 84 +++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 modules/gallery/helpers/data_rest.php (limited to 'modules/gallery/helpers/data_rest.php') diff --git a/modules/gallery/helpers/data_rest.php b/modules/gallery/helpers/data_rest.php new file mode 100644 index 00000000..ca5acb4a --- /dev/null +++ b/modules/gallery/helpers/data_rest.php @@ -0,0 +1,84 @@ +url); + access::required("view", $item); + + $p = $request->params; + switch (isset($p->size) ? $p->size : "full") { + case "thumb": + $entity = array( + "width" => $item->thumb_width, + "height" => $item->thumb_height, + "path" => $item->thumb_path()); + break; + + case "resize": + $entity = array( + "width" => $item->resize_width, + "height" => $item->resize_height, + "path" => $item->resize_path()); + break; + + default: + case "full": + $entity = array( + "width" => $item->width, + "height" => $item->height, + "path" => $item->file_path()); + break; + } + + $entity["size"] = filesize($entity["path"]); + $entity["contents"] = file_get_contents($entity["path"]); + unset($entity["path"]); + + $result = array( + "url" => $request->url, + "entity" => $entity, + "relationships" => rest::relationships("data", $item)); + return $result; + } + + static function put($request) { + $item = rest::resolve($request->url); + access::required("edit", $item); + + if ($item->is_album()) { + throw new Rest_Exception("Bad Request", 400, array("errors" => array("type" => "invalid"))); + } + + $item->set_data_file($request->file); + $item->save(); + } + + static function resolve($id) { + $item = ORM::factory("item", $id); + if (!access::can("view", $item)) { + throw new Kohana_404_Exception(); + } + return $item; + } + + static function url($item) { + return url::abs_site("rest/data/{$item->id}"); + } +} -- cgit v1.2.3 From 4e95ec843a2bef45e044e2aa3a36fcb590d85464 Mon Sep 17 00:00:00 2001 From: Bharat Mediratta Date: Sun, 8 Aug 2010 01:12:43 -0700 Subject: Allow item_rest::put() to replace the current data file. Remove data_rest::put() altogether; it's no longer necessary. --- modules/gallery/helpers/data_rest.php | 12 ------------ modules/gallery/helpers/item_rest.php | 6 ++++++ 2 files changed, 6 insertions(+), 12 deletions(-) (limited to 'modules/gallery/helpers/data_rest.php') diff --git a/modules/gallery/helpers/data_rest.php b/modules/gallery/helpers/data_rest.php index ca5acb4a..e45a4645 100644 --- a/modules/gallery/helpers/data_rest.php +++ b/modules/gallery/helpers/data_rest.php @@ -58,18 +58,6 @@ class data_rest_Core { return $result; } - static function put($request) { - $item = rest::resolve($request->url); - access::required("edit", $item); - - if ($item->is_album()) { - throw new Rest_Exception("Bad Request", 400, array("errors" => array("type" => "invalid"))); - } - - $item->set_data_file($request->file); - $item->save(); - } - static function resolve($id) { $item = ORM::factory("item", $id); if (!access::can("view", $item)) { diff --git a/modules/gallery/helpers/item_rest.php b/modules/gallery/helpers/item_rest.php index 6869181d..10f9e16a 100644 --- a/modules/gallery/helpers/item_rest.php +++ b/modules/gallery/helpers/item_rest.php @@ -126,6 +126,12 @@ class item_rest_Core { } } } + + // Replace the data file, if required + if (($item->is_photo() || $item->is_movie()) && isset($request->file)) { + $item->set_data_file($request->file); + } + $item->save(); if (isset($request->params->members) && $item->sort_column == "weight") { -- cgit v1.2.3 From b7700d1eec02caa794629adcc0555d7c9f0c1414 Mon Sep 17 00:00:00 2001 From: Bharat Mediratta Date: Sun, 8 Aug 2010 09:57:13 -0700 Subject: Require the size parameter. Optional params are confusing. And be robust in the face of a missing data file (movies and albums lack resize, albums lack full size, some albums don't have a thumb if they have no contents, etc) --- modules/gallery/helpers/data_rest.php | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'modules/gallery/helpers/data_rest.php') diff --git a/modules/gallery/helpers/data_rest.php b/modules/gallery/helpers/data_rest.php index e45a4645..48de2a3a 100644 --- a/modules/gallery/helpers/data_rest.php +++ b/modules/gallery/helpers/data_rest.php @@ -23,7 +23,11 @@ class data_rest_Core { access::required("view", $item); $p = $request->params; - switch (isset($p->size) ? $p->size : "full") { + if (!isset($p->size) || !in_array($p->size, array("thumb", "resize", "full"))) { + throw new Rest_Exception("Bad Request", 400, array("errors" => array("size" => "invalid"))); + } + + switch ($p->size) { case "thumb": $entity = array( "width" => $item->thumb_width, @@ -38,7 +42,6 @@ class data_rest_Core { "path" => $item->resize_path()); break; - default: case "full": $entity = array( "width" => $item->width, @@ -47,8 +50,13 @@ class data_rest_Core { break; } - $entity["size"] = filesize($entity["path"]); - $entity["contents"] = file_get_contents($entity["path"]); + if (file_exists($entity["path"]) && is_file($entity["path"])) { + $entity["size"] = filesize($entity["path"]); + $entity["contents"] = file_get_contents($entity["path"]); + } else { + $entity["size"] = null; + $entity["contents"] = null; + } unset($entity["path"]); $result = array( -- cgit v1.2.3 From 3c18762fda9a91717b5defc300ace6bda61eb233 Mon Sep 17 00:00:00 2001 From: Bharat Mediratta Date: Mon, 9 Aug 2010 22:54:57 -0700 Subject: Change the way that this works. Now instead of sending back the image metadata and the data itself JSON encoded, we just send back the raw data with the right Content-Type. This, combined with code in Item_Model::as_restful_array() that swaps in /rest/data urls as appropriate, means that the RESTful payload has consistent urls when permissions are in play. --- modules/gallery/helpers/data_rest.php | 55 +++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 25 deletions(-) (limited to 'modules/gallery/helpers/data_rest.php') diff --git a/modules/gallery/helpers/data_rest.php b/modules/gallery/helpers/data_rest.php index 48de2a3a..3cd2f59a 100644 --- a/modules/gallery/helpers/data_rest.php +++ b/modules/gallery/helpers/data_rest.php @@ -17,6 +17,11 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ + +/** + * This resource returns the raw contents of Item_Model data files. It's analogous to the + * file_proxy controller, but it uses the REST authentication model. + */ class data_rest_Core { static function get($request) { $item = rest::resolve($request->url); @@ -29,41 +34,41 @@ class data_rest_Core { switch ($p->size) { case "thumb": - $entity = array( - "width" => $item->thumb_width, - "height" => $item->thumb_height, - "path" => $item->thumb_path()); + $file = $item->thumb_path(); break; case "resize": - $entity = array( - "width" => $item->resize_width, - "height" => $item->resize_height, - "path" => $item->resize_path()); + $file = $item->resize_path(); break; case "full": - $entity = array( - "width" => $item->width, - "height" => $item->height, - "path" => $item->file_path()); + $file = $item->file_path(); break; } - if (file_exists($entity["path"]) && is_file($entity["path"])) { - $entity["size"] = filesize($entity["path"]); - $entity["contents"] = file_get_contents($entity["path"]); + if (!file_exists($file)) { + throw new Kohana_404_Exception(); + } + + // Note: this code is roughly duplicated in data_rest, so if you modify this, please look to + // see if you should make the same change there as well. + // + // We don't have a cache buster in the url, so don't set cache headers here. + // We don't need to save the session for this request + Session::instance()->abort_save(); + + // Dump out the image. If the item is a movie, then its thumbnail will be a JPG. + if ($item->is_movie() && $p->size == "thumb") { + header("Content-Type: image/jpeg"); } else { - $entity["size"] = null; - $entity["contents"] = null; + header("Content-Type: {$item->mime_type}"); } - unset($entity["path"]); + Kohana::close_buffers(false); + readfile($file); - $result = array( - "url" => $request->url, - "entity" => $entity, - "relationships" => rest::relationships("data", $item)); - return $result; + // We must exit here to keep the regular REST framework reply code from adding more bytes on + // at the end or tinkering with headers. + exit; } static function resolve($id) { @@ -74,7 +79,7 @@ class data_rest_Core { return $item; } - static function url($item) { - return url::abs_site("rest/data/{$item->id}"); + static function url($item, $size) { + return url::abs_site("rest/data/{$item->id}?size=$size"); } } -- cgit v1.2.3 From 6563ad1393b6d9a9cde44a127355359edae54843 Mon Sep 17 00:00:00 2001 From: Bharat Mediratta Date: Sat, 14 Aug 2010 22:00:53 -0700 Subject: Return the right content type for album thumbnails (based on the album cover's mime type) --- modules/gallery/helpers/data_rest.php | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'modules/gallery/helpers/data_rest.php') diff --git a/modules/gallery/helpers/data_rest.php b/modules/gallery/helpers/data_rest.php index 3cd2f59a..98c98894 100644 --- a/modules/gallery/helpers/data_rest.php +++ b/modules/gallery/helpers/data_rest.php @@ -57,9 +57,17 @@ class data_rest_Core { // We don't need to save the session for this request Session::instance()->abort_save(); + if ($item->is_album() && !$item->album_cover_item_id) { + // No thumbnail. Return nothing. + // @todo: what should we do here? + return; + } + // Dump out the image. If the item is a movie, then its thumbnail will be a JPG. if ($item->is_movie() && $p->size == "thumb") { header("Content-Type: image/jpeg"); + } else if ($item->is_album()) { + header("Content-Type: " . $item->album_cover()->mime_type); } else { header("Content-Type: {$item->mime_type}"); } -- cgit v1.2.3