| @@ -43,9 +43,9 @@ | ||
| 43 | 43 | $this->app->addFilter('fluent_community/feed/new_feed_data', [$this, 'maybeAddFluentPlayerMedia'], 10, 2); |
| 44 | 44 | $this->app->addFilter('fluent_community/feed/update_feed_data', [$this, 'maybeUpdateFluentPlayerMedia'], 10, 2); |
| 45 | 45 | $this->app->addFilter('fluent_community/feed/uploaded_feed_medias', [$this, 'maybeUpdateUploadedMedia'], 10, 2); |
| 46 | 46 | } |
| 47 | - | |
| 47 | + | |
| 48 | 48 | /** |
| 49 | 49 | * Get FluentPlayer plugin status |
| 50 | 50 | * |
| 51 | 51 | * @return string 'active', 'installed', or 'not_installed' |
| @@ -78,8 +78,10 @@ | ||
| 78 | 78 | 'enable_fluent_player' => 'no', |
| 79 | 79 | 'skin' => 'modern', |
| 80 | 80 | 'brandColor' => '#4a90e2', |
| 81 | 81 | 'controlBarColor' => '', |
| 82 | + 'playButtonColor' => '', | |
| 83 | + 'playButtonBgColor' => '', | |
| 82 | 84 | 'controls' => [ |
| 83 | 85 | 'play' => true, |
| 84 | 86 | 'volume' => true, |
| 85 | 87 | 'progress_bar' => true, |
| @@ -120,8 +122,10 @@ | ||
| 120 | 122 | 'enable_fluent_player' => 'sanitize_text_field', |
| 121 | 123 | 'skin' => 'sanitize_text_field', |
| 122 | 124 | 'brandColor' => 'sanitize_text_field', |
| 123 | 125 | 'controlBarColor' => 'sanitize_text_field', |
| 126 | + 'playButtonColor' => 'sanitize_text_field', | |
| 127 | + 'playButtonBgColor' => 'sanitize_text_field', | |
| 124 | 128 | 'controls.*' => 'rest_sanitize_boolean', |
| 125 | 129 | 'behaviors.*' => 'rest_sanitize_boolean', |
| 126 | 130 | 'video_upload' => 'sanitize_text_field', |
| 127 | 131 | 'video_upload_role' => 'sanitize_text_field', |
| @@ -139,8 +143,10 @@ | ||
| 139 | 143 | $settings['behaviors']['load_strategy'] = in_array($loadStrategy, $allowedStrategies) ? $loadStrategy : 'visible'; |
| 140 | 144 | $settings['enable_audio'] = Arr::get($settings, 'enable_audio') === 'yes' ? 'yes' : 'no'; |
| 141 | 145 | $settings['brandColor'] = self::sanitizeColor(Arr::get($settings, 'brandColor', '')); |
| 142 | 146 | $settings['controlBarColor'] = self::sanitizeColor(Arr::get($settings, 'controlBarColor', '')); |
| 147 | + $settings['playButtonColor'] = self::sanitizeColor(Arr::get($settings, 'playButtonColor', '')); | |
| 148 | + $settings['playButtonBgColor'] = self::sanitizeColor(Arr::get($settings, 'playButtonBgColor', '')); | |
| 143 | 149 | |
| 144 | 150 | Utility::updateOption('_fluent_player_settings', $settings); |
| 145 | 151 | |
| 146 | 152 | return $settings; |
| @@ -373,9 +379,9 @@ | ||
| 373 | 379 | if ($media && is_array($media) && Arr::get($media, 'player') == 'fluent_player') { |
| 374 | 380 | if (!isset($data['meta'])) { |
| 375 | 381 | $data['meta'] = []; |
| 376 | 382 | } |
| 377 | - $data['meta']['media_preview'] = array_filter($media); | |
| 383 | + $data['meta']['media_preview'] = array_filter(self::sanitizeMediaHtml($media)); | |
| 378 | 384 | } |
| 379 | 385 | $audioMedias = $this->sanitizeAudioMedias($requestData); |
| 380 | 386 | if ($audioMedias) { |
| 381 | 387 | if (!isset($data['meta'])) { |
| @@ -391,9 +397,9 @@ | ||
| 391 | 397 | if ($media && is_array($media) && Arr::get($media, 'player') == 'fluent_player') { |
| 392 | 398 | if (!isset($data['meta'])) { |
| 393 | 399 | $data['meta'] = []; |
| 394 | 400 | } |
| 395 | - $data['meta']['media_preview'] = array_filter($media); | |
| 401 | + $data['meta']['media_preview'] = array_filter(self::sanitizeMediaHtml($media)); | |
| 396 | 402 | } |
| 397 | 403 | $audioMedias = $this->sanitizeAudioMedias($requestData); |
| 398 | 404 | if ($audioMedias) { |
| 399 | 405 | if (!isset($data['meta'])) { |
| @@ -403,8 +409,22 @@ | ||
| 403 | 409 | } |
| 404 | 410 | return $data; |
| 405 | 411 | } |
| 406 | 412 | |
| 413 | + /** | |
| 414 | + * media_preview.html is rendered with v-html in _MediaPreview.vue whenever the | |
| 415 | + * player itself cannot handle the media, so request-supplied markup has to go | |
| 416 | + * through the oembed allowlist before it is stored. | |
| 417 | + */ | |
| 418 | + private static function sanitizeMediaHtml($media) | |
| 419 | + { | |
| 420 | + if (!empty($media['html'])) { | |
| 421 | + $media['html'] = \FluentCommunity\App\Services\RemoteUrlParser::sanitizeOembedHtml($media['html']); | |
| 422 | + } | |
| 423 | + | |
| 424 | + return $media; | |
| 425 | + } | |
| 426 | + | |
| 407 | 427 | public function maybeUpdateUploadedMedia($uploadedMedias, $requestData) |
| 408 | 428 | { |
| 409 | 429 | $media = Arr::get($requestData, 'meta.media_preview', []); |
| 410 | 430 | if ($newMedia = Arr::get($requestData, 'media')) { |
| @@ -412,11 +432,17 @@ | ||
| 412 | 432 | } |
| 413 | 433 | if ($media && is_array($media) && Arr::get($media, 'player') == 'fluent_player' && $mediaId = Arr::get($media, 'media_id')) { |
| 414 | 434 | $mediaId = intval($mediaId); |
| 415 | 435 | if ($mediaId) { |
| 416 | - $media = Media::find($mediaId); | |
| 417 | - if ($media) { | |
| 418 | - $uploadedMedias[] = $media; | |
| 436 | + $currentUserId = (int) get_current_user_id(); | |
| 437 | + $mediaModel = Media::find($mediaId); | |
| 438 | + // Owner, or a moderator/admin who can edit the media's feed — never cross-user. | |
| 439 | + $canAttach = $mediaModel && $currentUserId && ( | |
| 440 | + (int) $mediaModel->user_id === $currentUserId | |
| 441 | + || ($mediaModel->feed_id && $mediaModel->feed && $mediaModel->feed->hasEditAccess($currentUserId)) | |
| 442 | + ); | |
| 443 | + if ($canAttach) { | |
| 444 | + $uploadedMedias[] = $mediaModel; | |
| 419 | 445 | } |
| 420 | 446 | } |
| 421 | 447 | } |
| 422 | 448 | $audioMedias = $this->sanitizeAudioMedias($requestData); |