PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 16.2-a.1
Jetpack – WP Security, Backup, Speed, & Growth v16.2-a.1
16.2-a.3 16.1.2 16.2-a.1 16.1.1 16.1 16.1-beta 16.1-beta.2 16.1-beta.3 16.1-a.5 16.1-a.3 16.0.1 16.1-a.1 16.0 16.0-beta 16.0-a.7 16.0-a.5 15.9.1 16.0-a.3 16.0-a.1 15.9 15.9-beta 15.9-a.7 15.9-a.5 15.9-a.3 15.9-a.1 15.8 15.8-beta 15.8-a.7 15.8-a.5 5.2.5 5.3.4 5.4.4 5.5.5 5.6.5 5.7.5 5.8.4 5.9.4 6.0.4 6.1 6.1.1 6.1.2 6.1.3 6.1.4 6.1.5 6.2 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.3 6.3.1 6.3.2 6.3.3 6.3.4 6.3.5 6.3.6 6.3.7 6.4 6.4.1 6.4.2 6.4.3 6.4.4 6.4.5 6.4.6 6.5 6.5.1 6.5.2 6.5.3 6.5.4 6.6 6.6.1 6.6.2 6.6.3 6.6.4 6.6.5 6.7 6.7.1 6.7.2 6.7.3 6.7.4 6.8 6.8.1 6.8.2 6.8.3 6.8.4 6.8.5 6.9 6.9.1 6.9.2 6.9.3 6.9.4 7.0 7.0.1 7.0.2 7.0.3 7.0.4 7.0.5 7.1 7.1.1 7.1.2 7.1.3 7.1.4 7.1.5 7.2 7.2.1 7.2.1.1 7.2.2 7.2.3 7.2.4 7.2.5 7.3 7.3.0.1 7.3.1 7.3.1.1 7.3.2 7.3.3 7.3.4 7.3.5 7.4 7.4.1 7.4.2 7.4.3 7.4.4 7.4.5 7.5 7.5.0.1 7.5.1 7.5.2 7.5.3 7.5.4 7.5.5 7.5.6 7.5.7 7.6 7.6.1 7.6.2 7.6.3 7.6.4 7.7 7.7.1 7.7.2 7.7.3 7.7.4 7.7.5 7.7.6 7.8 7.8.1 7.8.2 7.8.3 7.8.4 7.9 7.9.1 7.9.2 7.9.3 7.9.4 8.0 8.0.1 8.0.2 8.0.3 8.1 8.1.1 8.1.2 8.1.3 8.1.4 8.2 8.2.0.1 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.2.6 8.3 8.3.1 8.3.2 8.3.3 8.4 8.4.1 8.4.2 8.4.3 8.4.4 8.4.5 8.5 8.5.1 8.5.2 8.5.3 8.6 8.6.1 8.6.2 8.6.3 8.6.4 8.7 8.7.0.1 8.7.1 8.7.2 8.7.3 8.7.4 8.8 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.9 8.9.1 8.9.2 8.9.3 8.9.4 9.0 9.0.1 9.0.2 9.0.3 9.0.4 9.0.5 9.1 9.1.1 9.1.2 9.1.3 9.2 9.2.1 9.2.2 9.2.3 9.2.4 9.3 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.4 9.4.1 9.4.2 9.4.3 9.4.4 9.5 9.5.1 9.5.2 9.5.3 9.5.4 9.5.5 9.6 9.6.1 9.6.2 9.6.3 9.6.4 9.7 9.7.1 9.7.2 15.7-beta.2 9.7.3 15.7.1 9.8 15.8-a.1 9.8.1 15.8-a.3 9.8.2 2.0.9 9.8.3 2.1.7 9.9 2.2.10 9.9.1 2.3.10 9.9.2 2.4.7 9.9.3 2.5.5 2.6.6 2.7.5 2.8.5 2.9.6 3.0.6 3.1.5 3.2.5 3.3.6 3.4.6 3.5.6 3.6.4 3.7.5 3.8.5 3.9.10 4.0.7 4.1.4 4.2.5 4.3.5 4.4.5 4.5.3 4.6.3 4.7.4 4.8.5 4.9.3 5.0.3 5.1.4 trunk 10.0 10.0.1 10.0.2 10.1 10.1.1 10.1.2 10.2 10.2.1 10.2.2 10.2.3 10.3 10.3.1 10.3.2 10.4 10.4.1 10.4.2 10.5 10.5.1 10.5.2 10.5.3 10.6 10.6.1 10.6.2 10.7 10.7.1 10.7.2 10.8 10.8.1 10.8.2 10.9 10.9.1 10.9.2 10.9.3 11.0 11.0.1 11.0.2 11.1 11.1.1 11.1.2 11.1.3 11.1.4 11.2 11.2.1 11.2.2 11.3 11.3.1 11.3.2 11.3.3 11.3.4 11.4 11.4.1 11.4.2 11.5 11.5.1 11.5.2 11.5.3 11.6 11.6.1 11.6.2 11.7 11.7.1 11.7.2 11.7.3 11.8 11.8.3 11.8.4 11.8.5 11.8.6 11.9 11.9.1 11.9.2 11.9.3 12.0 12.0.1 12.0.2 12.1 12.1.1 12.1.2 12.2 12.2.1 12.2.2 12.3 12.3.1 12.4 12.4.1 12.5 12.5.1 12.6 12.6.1 12.6.2 12.6.3 12.7 12.7.1 12.7.2 12.8 12.8.1 12.8.2 12.9 12.9.1 12.9.2 12.9.3 12.9.4 13.0 13.0.1 13.1 13.1.1 13.1.2 13.1.3 13.1.4 13.2 13.2.1 13.2.2 13.2.3 13.3 13.3.1 13.3.2 13.4 13.4.1 13.4.2 13.4.3 13.4.4 13.5 13.5.1 13.6 13.6.1 13.7 13.7.1 13.8 13.8.1 13.8.2 13.9 13.9.1 14.0 14.1 14.2 14.2.1 14.3 14.4 14.4.1 14.5 14.6 14.7 14.8 14.9 14.9.1 15.0 15.0.1 15.0.2 15.1 15.1.1 15.2 15.3 15.3.1 15.4 15.5 15.6 15.7 15.7-a.1 15.7-a.3 15.7-a.5 15.7-a.7 15.7-beta
jetpack / jetpack_vendor / automattic / jetpack-videopress / src / class-ajax.php
jetpack / jetpack_vendor / automattic / jetpack-videopress / src Last commit date
js 2 months ago tus 1 month ago videopress-divi 2 months ago videopress-divi-5 2 months ago class-access-control.php 5 days ago class-admin-ui.php 2 weeks ago class-ajax.php 1 month ago class-attachment-handler.php 1 month ago class-block-editor-content.php 1 month ago class-block-editor-extensions.php 2 weeks ago class-block-replacement.php 9 months ago class-caption-tracks.php 1 month ago class-data.php 1 month ago class-divi.php 2 months ago class-initial-state.php 2 weeks ago class-initializer.php 5 days ago class-jwt-token-bridge.php 2 years ago class-module-control.php 3 years ago class-options.php 2 years ago class-package-version.php 5 days ago class-plan.php 2 years ago class-rest-controller.php 1 month ago class-site.php 3 years ago class-stats.php 1 year ago class-status.php 9 months ago class-upload-exception.php 3 years ago class-uploader-rest-endpoints.php 2 weeks ago class-uploader.php 1 month ago class-utils.php 3 months ago class-video-block-email-renderer.php 2 months ago class-videopress-rest-api-v1-features.php 6 months ago class-videopress-rest-api-v1-settings.php 1 month ago class-videopress-rest-api-v1-site.php 2 weeks ago class-videopress-rest-api-v1-stats.php 3 years ago class-videopresstoken.php 1 month ago class-wpcom-rest-api-v2-attachment-field-videopress.php 9 months ago class-wpcom-rest-api-v2-attachment-videopress-data.php 1 month ago class-wpcom-rest-api-v2-endpoint-videopress-caption-tracks.php 1 month ago class-wpcom-rest-api-v2-endpoint-videopress.php 2 weeks ago class-xmlrpc.php 1 month ago utility-functions.php 4 weeks ago
class-ajax.php
324 lines
1 <?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
2
3 namespace Automattic\Jetpack\VideoPress;
4
5 use Automattic\Jetpack\Connection\Client;
6
7 /**
8 * VideoPress AJAX action handlers and utilities.
9 *
10 * Note: this is also being used on WordPress.com.
11 * Use IS_WPCOM checks for functionality that is specific to WPCOM/Jetpack.
12 */
13 class AJAX {
14
15 /**
16 * Singleton AJAX instance.
17 *
18 * @var AJAX
19 **/
20 private static $instance = null;
21
22 /**
23 * Private AJAX constructor.
24 *
25 * Use the AJAX::init() method to get an instance.
26 */
27 private function __construct() {
28 add_action( 'wp_ajax_videopress-get-upload-token', array( $this, 'wp_ajax_videopress_get_upload_token' ) );
29 add_action( 'wp_ajax_videopress-get-upload-jwt', array( $this, 'wp_ajax_videopress_get_upload_jwt' ) );
30 add_action( 'wp_ajax_nopriv_videopress-get-playback-jwt', array( $this, 'wp_ajax_videopress_get_playback_jwt' ) );
31 add_action( 'wp_ajax_videopress-get-playback-jwt', array( $this, 'wp_ajax_videopress_get_playback_jwt' ) );
32
33 add_action(
34 'wp_ajax_videopress-update-transcoding-status',
35 array(
36 $this,
37 'wp_ajax_update_transcoding_status',
38 ),
39 -1
40 );
41 }
42
43 /**
44 * Initialize the AJAX and get back a singleton instance.
45 *
46 * @return AJAX
47 */
48 public static function init() {
49 if ( self::$instance === null ) {
50 self::$instance = new AJAX();
51 }
52
53 return self::$instance;
54 }
55
56 /**
57 * Validate a guid.
58 *
59 * @param string $guid The guid to validate.
60 *
61 * @return bool
62 **/
63 private function is_valid_guid( $guid ) {
64 if ( empty( $guid ) ) {
65 return false;
66 }
67
68 preg_match( '/^[a-z0-9]{8}$/i', $guid, $matches );
69
70 if ( empty( $matches ) ) {
71 return false;
72 }
73
74 return true;
75 }
76
77 /**
78 * Ajax method that is used by the VideoPress player to get a token to play a video.
79 *
80 * This is used for both logged in and logged out users.
81 *
82 * @return void
83 */
84 public function wp_ajax_videopress_get_playback_jwt() {
85 $guid = filter_input( INPUT_POST, 'guid' );
86 $embedded_post_id = filter_input( INPUT_POST, 'post_id', FILTER_VALIDATE_INT );
87 $selected_plan_id = filter_input( INPUT_POST, 'subscription_plan_id' );
88
89 if ( empty( $embedded_post_id ) ) {
90 $embedded_post_id = 0;
91 }
92
93 if ( empty( $guid ) || ! $this->is_valid_guid( $guid ) ) {
94 // @phan-suppress-next-line PhanTypeMismatchArgumentProbablyReal -- It takes null, but its phpdoc only says int.
95 wp_send_json_error( array( 'message' => __( 'need a guid', 'jetpack-videopress-pkg' ) ), null, JSON_UNESCAPED_SLASHES );
96 return;
97 }
98
99 if ( ! $this->is_current_user_authed_for_video( $guid, $embedded_post_id, $selected_plan_id ) ) {
100 // @phan-suppress-next-line PhanTypeMismatchArgumentProbablyReal -- It takes null, but its phpdoc only says int.
101 wp_send_json_error( array( 'message' => __( 'You cannot view this video.', 'jetpack-videopress-pkg' ) ), null, JSON_UNESCAPED_SLASHES );
102 return;
103 }
104
105 $token = $this->request_jwt_from_wpcom( $guid );
106
107 if ( empty( $token ) ) {
108 // @phan-suppress-next-line PhanTypeMismatchArgumentProbablyReal -- It takes null, but its phpdoc only says int.
109 wp_send_json_error( array( 'message' => __( 'Could not obtain a VideoPress playback JWT. Please try again later. (empty upload token)', 'jetpack-videopress-pkg' ) ), null, JSON_UNESCAPED_SLASHES );
110 return;
111 }
112
113 if ( is_wp_error( $token ) ) {
114 // @phan-suppress-next-line PhanTypeMismatchArgumentProbablyReal -- It takes null, but its phpdoc only says int.
115 wp_send_json_error( array( 'message' => __( 'Could not obtain a VideoPress upload JWT. Please try again later.', 'jetpack-videopress-pkg' ) ), null, JSON_UNESCAPED_SLASHES );
116 return;
117 }
118
119 // @phan-suppress-next-line PhanTypeMismatchArgumentProbablyReal -- It takes null, but its phpdoc only says int.
120 wp_send_json_success( array( 'jwt' => $token ), null, JSON_UNESCAPED_SLASHES );
121 }
122
123 /**
124 * Determines if the current user can view the provided video. Only ever gets fired if site-wide private videos are enabled.
125 *
126 * Filterable for 3rd party plugins.
127 *
128 * @param string $guid The video id being checked.
129 * @param int $embedded_post_id The post id the video is embedded in or 0.
130 * @param int $selected_plan_id The plan id the earn block this video is embedded in has.
131 */
132 private function is_current_user_authed_for_video( $guid, $embedded_post_id, $selected_plan_id = 0 ) {
133 return Access_Control::instance()->is_current_user_authed_for_video( $guid, $embedded_post_id, $selected_plan_id );
134 }
135
136 /**
137 * Requests JWT from wpcom.
138 *
139 * @param string $guid The video id being checked.
140 */
141 private function request_jwt_from_wpcom( $guid ) {
142 if ( defined( 'IS_WPCOM' ) && IS_WPCOM && function_exists( 'video_wpcom_get_playback_jwt_for_guid' ) ) {
143 $jwt_data = video_wpcom_get_playback_jwt_for_guid( $guid );
144 if ( is_wp_error( $jwt_data ) ) {
145 return false;
146 }
147 return $jwt_data->metadata_token;
148 }
149
150 $video_blog_id = $this->get_videopress_blog_id();
151 $args = array(
152 'method' => 'POST',
153 );
154
155 $endpoint = "sites/{$video_blog_id}/media/videopress-playback-jwt/{$guid}";
156 $result = Client::wpcom_json_api_request_as_blog( $endpoint, 'v2', $args, null, 'wpcom' );
157 if ( is_wp_error( $result ) ) {
158 return $result;
159 }
160
161 $response = json_decode( $result['body'], true );
162
163 if ( empty( $response['metadata_token'] ) ) {
164 return false;
165 }
166
167 return $response['metadata_token'];
168 }
169
170 /**
171 * Ajax method that is used by the VideoPress uploader to get a token to upload a file to the wpcom api.
172 *
173 * @return void
174 */
175 public function wp_ajax_videopress_get_upload_jwt() {
176 if ( ! current_user_can( 'upload_files' ) ) {
177 // @phan-suppress-next-line PhanTypeMismatchArgumentProbablyReal -- It takes null, but its phpdoc only says int.
178 wp_send_json_error( array( 'message' => __( 'You do not have permission to upload files.', 'jetpack-videopress-pkg' ) ), null, JSON_UNESCAPED_SLASHES );
179 return;
180 }
181
182 $video_blog_id = $this->get_videopress_blog_id();
183 $args = array(
184 'method' => 'POST',
185 );
186
187 $endpoint = "sites/{$video_blog_id}/media/videopress-upload-jwt";
188 $result = Client::wpcom_json_api_request_as_blog( $endpoint, 'v2', $args, null, 'wpcom' );
189 if ( is_wp_error( $result ) ) {
190 // @phan-suppress-next-line PhanTypeMismatchArgumentProbablyReal -- It takes null, but its phpdoc only says int.
191 wp_send_json_error( array( 'message' => __( 'Could not obtain a VideoPress upload JWT. Please try again later.', 'jetpack-videopress-pkg' ) ), null, JSON_UNESCAPED_SLASHES );
192 return;
193 }
194
195 $response = json_decode( $result['body'], true );
196
197 if ( empty( $response['upload_token'] ) ) {
198 // @phan-suppress-next-line PhanTypeMismatchArgumentProbablyReal -- It takes null, but its phpdoc only says int.
199 wp_send_json_error( array( 'message' => __( 'Could not obtain a VideoPress upload JWT. Please try again later. (empty upload token)', 'jetpack-videopress-pkg' ) ), null, JSON_UNESCAPED_SLASHES );
200 return;
201 }
202
203 $response['upload_action_url'] = videopress_make_resumable_upload_path( $video_blog_id );
204
205 // @phan-suppress-next-line PhanTypeMismatchArgumentProbablyReal -- It takes null, but its phpdoc only says int.
206 wp_send_json_success( $response, null, JSON_UNESCAPED_SLASHES );
207 }
208
209 /**
210 * Ajax method that is used by the VideoPress uploader to get a token to upload a file to the wpcom api.
211 *
212 * @return void
213 */
214 public function wp_ajax_videopress_get_upload_token() {
215 if ( ! current_user_can( 'upload_files' ) ) {
216 // @phan-suppress-next-line PhanTypeMismatchArgumentProbablyReal -- It takes null, but its phpdoc only says int.
217 wp_send_json_error( array( 'message' => __( 'You do not have permission to upload files.', 'jetpack-videopress-pkg' ) ), null, JSON_UNESCAPED_SLASHES );
218 return;
219 }
220
221 $video_blog_id = $this->get_videopress_blog_id();
222
223 // On WordPress.com the classic `sites/{id}/media/token` (rest/v1.1) endpoint
224 // isn't reachable in-process (WPCOM_API_Direct only dispatches WP-REST routes),
225 // so mint the token via VideoPressToken, which has its own IS_WPCOM branch that
226 // mints locally. `get_videopress_blog_id()` is the current blog on Simple, matching
227 // the minted token. The self-hosted remote path below is left unchanged.
228 if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
229 try {
230 $upload_token = VideoPressToken::videopress_onetime_upload_token();
231 } catch ( Upload_Exception $e ) {
232 // Explicit 200: identical to the null default (admin-ajax errors
233 // ride the success:false envelope), but typed as the phpdoc wants.
234 wp_send_json_error( array( 'message' => $e->getMessage() ), 200, JSON_UNESCAPED_SLASHES );
235 return;
236 }
237
238 // `upload_action_url` (from `videopress_make_media_upload_path()`) is omitted:
239 // that helper isn't loaded in the Simple admin-ajax context, and only the
240 // legacy upload-form flow reads it — the track/poster consumers use the token
241 // and blog id, not the URL.
242 wp_send_json_success(
243 array(
244 'upload_token' => $upload_token,
245 'upload_blog_id' => $video_blog_id,
246 ),
247 200,
248 JSON_UNESCAPED_SLASHES
249 );
250 return;
251 }
252
253 $args = array(
254 'method' => 'POST',
255 );
256
257 $endpoint = "sites/{$video_blog_id}/media/token";
258 $result = Client::wpcom_json_api_request_as_blog( $endpoint, Client::WPCOM_JSON_API_VERSION, $args );
259
260 if ( is_wp_error( $result ) ) {
261 // @phan-suppress-next-line PhanTypeMismatchArgumentProbablyReal -- It takes null, but its phpdoc only says int.
262 wp_send_json_error( array( 'message' => __( 'Could not obtain a VideoPress upload token. Please try again later.', 'jetpack-videopress-pkg' ) ), null, JSON_UNESCAPED_SLASHES );
263 return;
264 }
265
266 $response = json_decode( $result['body'], true );
267
268 if ( empty( $response['upload_token'] ) ) {
269 // @phan-suppress-next-line PhanTypeMismatchArgumentProbablyReal -- It takes null, but its phpdoc only says int.
270 wp_send_json_error( array( 'message' => __( 'Could not obtain a VideoPress upload token. Please try again later.', 'jetpack-videopress-pkg' ) ), null, JSON_UNESCAPED_SLASHES );
271 return;
272 }
273
274 $response['upload_action_url'] = videopress_make_media_upload_path( $video_blog_id );
275
276 // @phan-suppress-next-line PhanTypeMismatchArgumentProbablyReal -- It takes null, but its phpdoc only says int.
277 wp_send_json_success( $response, null, JSON_UNESCAPED_SLASHES );
278 }
279
280 /**
281 * Ajax action to update the video transcoding status from the WPCOM API.
282 *
283 * @return void
284 */
285 public function wp_ajax_update_transcoding_status() {
286 if ( ! isset( $_POST['post_id'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Informational AJAX response.
287 // @phan-suppress-next-line PhanTypeMismatchArgumentProbablyReal -- It takes null, but its phpdoc only says int.
288 wp_send_json_error( array( 'message' => __( 'A valid post_id is required.', 'jetpack-videopress-pkg' ) ), null, JSON_UNESCAPED_SLASHES );
289 return;
290 }
291
292 $post_id = (int) $_POST['post_id']; // phpcs:ignore WordPress.Security.NonceVerification.Missing
293
294 if ( ! videopress_update_meta_data( $post_id ) ) {
295 // @phan-suppress-next-line PhanTypeMismatchArgumentProbablyReal -- It takes null, but its phpdoc only says int.
296 wp_send_json_error( array( 'message' => __( 'That post does not have a VideoPress video associated to it.', 'jetpack-videopress-pkg' ) ), null, JSON_UNESCAPED_SLASHES );
297 return;
298 }
299
300 wp_send_json_success(
301 array(
302 'message' => __( 'Status updated', 'jetpack-videopress-pkg' ),
303 'status' => videopress_get_transcoding_status( $post_id ),
304 ),
305 null, // @phan-suppress-current-line PhanTypeMismatchArgumentProbablyReal -- It takes null, but its phpdoc only says int.
306 JSON_UNESCAPED_SLASHES
307 );
308 }
309
310 /**
311 * Returns the proper blog id depending on Jetpack or WP.com
312 *
313 * @return int the blog id
314 */
315 public function get_videopress_blog_id() {
316 if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
317 return get_current_blog_id();
318 }
319
320 $options = Options::get_options();
321 return $options['shadow_blog_id'];
322 }
323 }
324