From e60d97ae5e2386dd5c645eb19e81c52bd0f77549 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Fri, 2 Dec 2022 22:23:43 -0800 Subject: [PATCH] video: allow transcoding everywhere --- lib/Controller/PublicController.php | 3 +++ lib/Controller/VideoController.php | 24 +++++++++++--------- scripts/get-exiftool.sh | 2 +- src/components/Metadata.vue | 8 ++++--- src/components/PsVideo.ts | 34 ++++++++++++++++------------- src/components/Timeline.vue | 6 +---- src/services/FileUtils.ts | 5 ++--- src/services/Utils.ts | 34 ++++++++++++++++++++++++----- 8 files changed, 74 insertions(+), 42 deletions(-) diff --git a/lib/Controller/PublicController.php b/lib/Controller/PublicController.php index a4355458..f2dd9b14 100644 --- a/lib/Controller/PublicController.php +++ b/lib/Controller/PublicController.php @@ -121,6 +121,9 @@ class PublicController extends AuthPublicShareController $policy->addAllowedScriptDomain('blob:'); $policy->addAllowedMediaDomain('blob:'); + // Image editor + $policy->addAllowedConnectDomain('data:'); + // Allow nominatim for metadata $policy->addAllowedConnectDomain('nominatim.openstreetmap.org'); $policy->addAllowedFrameDomain('www.openstreetmap.org'); diff --git a/lib/Controller/VideoController.php b/lib/Controller/VideoController.php index 854e4faf..fb38b6f5 100644 --- a/lib/Controller/VideoController.php +++ b/lib/Controller/VideoController.php @@ -34,17 +34,14 @@ class VideoController extends ApiBase /** * @NoAdminRequired * + * @PublicPage + * * @NoCSRFRequired * * Transcode a video to HLS by proxy */ - public function transcode(string $client, string $fileid, string $profile): Http\Response + public function transcode(string $client, int $fileid, string $profile): Http\Response { - $user = $this->userSession->getUser(); - if (null === $user) { - return new JSONResponse([], Http::STATUS_PRECONDITION_FAILED); - } - // Make sure not running in read-only mode if (false !== $this->config->getSystemValue('memories.no_transcode', 'UNSET')) { return new JSONResponse(['message' => 'Transcoding disabled'], Http::STATUS_FORBIDDEN); @@ -56,11 +53,10 @@ class VideoController extends ApiBase } // Get file - $files = $this->rootFolder->getUserFolder($user->getUID())->getById($fileid); - if (0 === \count($files)) { + $file = $this->getUserFile($fileid); + if (!$file) { return new JSONResponse(['message' => 'File not found'], Http::STATUS_NOT_FOUND); } - $file = $files[0]; if (!($file->getPermissions() & \OCP\Constants::PERMISSION_READ)) { return new JSONResponse(['message' => 'File not readable'], Http::STATUS_FORBIDDEN); @@ -250,7 +246,15 @@ class VideoController extends ApiBase private function getUpstreamInternal($client, $path, $profile) { $path = rawurlencode($path); - $ch = curl_init("http://127.0.0.1:47788/{$client}{$path}/{$profile}"); + + // Make sure query params are repeated + // For example, in folder sharing, we need the params on every request + $url = "http://127.0.0.1:47788/{$client}{$path}/{$profile}"; + if ($params = $_SERVER['QUERY_STRING']) { + $url .= "?{$params}"; + } + + $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); curl_setopt($ch, CURLOPT_HEADER, 0); diff --git a/scripts/get-exiftool.sh b/scripts/get-exiftool.sh index b7bd29d8..137b53bd 100755 --- a/scripts/get-exiftool.sh +++ b/scripts/get-exiftool.sh @@ -20,7 +20,7 @@ mv "exiftool-$exifver" exiftool rm -rf *.zip exiftool/t exiftool/html chmod 755 exiftool/exiftool -govod="0.0.22" +govod="0.0.23" echo "Getting go-vod $govod" wget -q "https://github.com/pulsejet/go-vod/releases/download/$govod/go-vod-amd64" wget -q "https://github.com/pulsejet/go-vod/releases/download/$govod/go-vod-aarch64" diff --git a/src/components/Metadata.vue b/src/components/Metadata.vue index f0f5a29d..abb87a1e 100644 --- a/src/components/Metadata.vue +++ b/src/components/Metadata.vue @@ -88,9 +88,11 @@ export default class Metadata extends Mixins(GlobalMixin) { this.nominatim = null; let state = this.state; - const res = await axios.get( - generateUrl("/apps/memories/api/image/info/{id}", { id: fileInfo.id }) - ); + let url = generateUrl("/apps/memories/api/image/info/{id}", { + id: fileInfo.id, + }); + url = utils.addQueryTokensToUrl(url); + const res = await axios.get(url); if (state !== this.state) return; this.baseInfo = res.data; diff --git a/src/components/PsVideo.ts b/src/components/PsVideo.ts index 90120137..be28a3ea 100644 --- a/src/components/PsVideo.ts +++ b/src/components/PsVideo.ts @@ -5,6 +5,7 @@ import axios from "@nextcloud/axios"; import { showError } from "@nextcloud/dialogs"; import { translate as t } from "@nextcloud/l10n"; import { getCurrentUser } from "@nextcloud/auth"; +import { addQueryTokensToUrl } from "../services/Utils"; const config_noTranscode = loadState( "memories", @@ -115,12 +116,16 @@ class VideoContentSetup { } getHLSsrc(content: any) { + // Get base URL const fileid = content.data.photo.fileid; - const baseUrl = generateUrl( - `/apps/memories/api/video/transcode/${videoClientId}/${fileid}` + let url = generateUrl( + `/apps/memories/api/video/transcode/${videoClientId}/${fileid}/index.m3u8` ); + + url = addQueryTokensToUrl(url); + return { - src: `${baseUrl}/index.m3u8`, + src: url, type: "application/x-mpegURL", }; } @@ -227,19 +232,18 @@ class VideoContentSetup { }); // Get correct orientation - axios - .get( - generateUrl("/apps/memories/api/image/info/{id}", { - id: content.data.photo.fileid, - }) - ) - .then((response) => { - content.data.exif = response.data?.exif; + let url = generateUrl("/apps/memories/api/image/info/{id}", { + id: content.data.photo.fileid, + }); + url = addQueryTokensToUrl(url); - // Update only after video is ready - // Otherwise the poster image is rotated - if (canPlay) this.updateRotation(content); - }); + axios.get(url).then((response) => { + content.data.exif = response.data?.exif; + + // Update only after video is ready + // Otherwise the poster image is rotated + if (canPlay) this.updateRotation(content); + }); } destroyVideo(content: any) { diff --git a/src/components/Timeline.vue b/src/components/Timeline.vue index 206702f7..b035a165 100644 --- a/src/components/Timeline.vue +++ b/src/components/Timeline.vue @@ -602,11 +602,6 @@ export default class Timeline extends Mixins(GlobalMixin, UserConfig) { ); } - // Favorites - if (this.$route.name === "folder-share") { - query.set("folder_share", this.$route.params.token); - } - // Month view if (this.isMonthView) { query.set("monthView", "1"); @@ -614,6 +609,7 @@ export default class Timeline extends Mixins(GlobalMixin, UserConfig) { } // Create query string and append to URL + utils.addQueryTokens(query); const queryStr = query.toString(); if (queryStr) { url += "?" + queryStr; diff --git a/src/services/FileUtils.ts b/src/services/FileUtils.ts index de4ab203..21fecf87 100644 --- a/src/services/FileUtils.ts +++ b/src/services/FileUtils.ts @@ -23,6 +23,7 @@ import { generateUrl } from "@nextcloud/router"; import camelcase from "camelcase"; import { IFileInfo, IPhoto } from "../types"; import { isNumber } from "./NumberUtils"; +import { addQueryTokens } from "./Utils"; /** * Get an url encoded path @@ -153,9 +154,7 @@ const getPreviewUrl = function ( query.set("a", square ? "0" : "1"); // Public preview - if (vuerouter.currentRoute.name === "folder-share") { - query.set("folder_share", vuerouter.currentRoute.params.token); - } + addQueryTokens(query); return url + "?" + query.toString(); }; diff --git a/src/services/Utils.ts b/src/services/Utils.ts index 51c2b694..085ce6dd 100644 --- a/src/services/Utils.ts +++ b/src/services/Utils.ts @@ -237,6 +237,34 @@ export function getFolderRoutePath(basePath: string) { return path; } +/** + * Add any access tokens to query param if required + * @param query Query string + */ +export function addQueryTokens(query: URLSearchParams) { + if (vuerouter.currentRoute.name === "folder-share") { + query.set("folder_share", vuerouter.currentRoute.params.token); + } +} + +/** + * Add query tokens to a string URL + * @param url URL to add tokens to + */ +export function addQueryTokensToUrl(url: string) { + const query = new URLSearchParams(); + addQueryTokens(query); + if (query.toString()) { + if (url.indexOf("?") === -1) { + url += "?"; + } else { + url += "&"; + } + url += query.toString(); + } + return url; +} + /** * Get URL to live photo video part */ @@ -254,11 +282,7 @@ export function getLivePhotoVideoUrl(p: IPhoto, transcode: boolean) { query.set("transcode", videoClientIdPersistent); } - // Add auth token for public share - if (vuerouter.currentRoute.name === "folder-share") { - query.set("folder_share", vuerouter.currentRoute.params.token); - } - + addQueryTokens(query); return url + "?" + query.toString(); }