PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 15.2.1
Jetpack – WP Security, Backup, Speed, & Growth v15.2.1
12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 13.8.3 13.9.2 14.0.1 14.1.1 14.2.2 14.3.1 14.4.2 14.5.1 14.6.1 14.7.1 14.8.1 14.9.2 15.0.3 15.1.2 15.2.1 15.3.2 15.4.1 15.5.1 15.6.1 15.7.2 15.8.1 15.9.2 16.0.2 16.1.3 16.2-a.5 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 / unauth-file-upload.php
jetpack Last commit date
3rd-party 9 months ago _inc 1 day ago css 10 months ago extensions 9 months ago images 1 year ago jetpack_vendor 1 day ago json-endpoints 9 months ago modules 9 months ago sal 9 months ago src 9 months ago vendor 9 months ago views 11 months ago CHANGELOG.md 9 months ago LICENSE.txt 5 years ago SECURITY.md 2 years ago class-jetpack-connection-status.php 2 years ago class-jetpack-gallery-settings.php 1 year ago class-jetpack-newsletter-dashboard-widget.php 1 year ago class-jetpack-pre-connection-jitms.php 2 years ago class-jetpack-stats-dashboard-widget.php 1 year ago class-jetpack-xmlrpc-methods.php 9 months ago class.frame-nonce-preview.php 1 year ago class.jetpack-admin.php 11 months ago class.jetpack-autoupdate.php 1 year ago class.jetpack-cli.php 10 months ago class.jetpack-client-server.php 2 years ago class.jetpack-gutenberg.php 11 months ago class.jetpack-heartbeat.php 2 years ago class.jetpack-modules-list-table.php 1 year ago class.jetpack-network-sites-list-table.php 1 year ago class.jetpack-network.php 1 year ago class.jetpack-plan.php 3 years ago class.jetpack-post-images.php 10 months ago class.jetpack-twitter-cards.php 9 months ago class.jetpack-user-agent.php 2 years ago class.jetpack.php 9 months ago class.json-api-endpoints.php 9 months ago class.json-api.php 9 months ago class.photon.php 3 years ago composer.json 9 months ago enhanced-open-graph.php 1 year ago functions.compat.php 1 year ago functions.cookies.php 2 years ago functions.global.php 9 months ago functions.is-mobile.php 2 years ago functions.opengraph.php 1 year ago functions.photon.php 2 years ago jetpack.php 1 day ago json-api-config.php 3 years ago json-endpoints.php 2 years ago load-jetpack.php 1 year ago locales.php 1 year ago readme.txt 1 day ago unauth-file-upload.php 10 months ago uninstall.php 1 year ago wpml-config.xml 4 years ago
unauth-file-upload.php
168 lines
1 <?php
2 /**
3 * Unauthenticated File Upload Helper Functions.
4 *
5 * @package automattic/jetpack
6 */
7
8 namespace Automattic\Jetpack\UnauthFileUpload;
9
10 if ( ! defined( 'ABSPATH' ) ) {
11 exit( 0 );
12 }
13
14 add_action( 'wp_ajax_jetpack_unauth_file_download', __NAMESPACE__ . '\handle_file_download' );
15 add_filter( 'jetpack_unauth_file_upload_get_file', __NAMESPACE__ . '\get_file_content', 10, 2 );
16 add_filter( 'jetpack_unauth_file_download_url', __NAMESPACE__ . '\filter_get_download_url', 10, 2 );
17
18 /**
19 * Get the file download URL filter callback.
20 *
21 * @param string $url The file download URL.
22 * @param int $file_id The file ID.
23 *
24 * @return string The file download URL.
25 */
26 function filter_get_download_url( $url, $file_id ) {
27 $nonce = wp_create_nonce( 'jetpack_unauth_file_download_nonce_' . $file_id );
28 return add_query_arg(
29 array(
30 'action' => 'jetpack_unauth_file_download',
31 'file_id' => $file_id,
32 '_wpnonce' => $nonce,
33 ),
34 admin_url( 'admin-ajax.php' )
35 );
36 }
37
38 /**
39 * Handle file download requests from the admin page.
40 *
41 * @return never This method never returns as it exits directly
42 */
43 function handle_file_download() {
44 if ( ! current_user_can( 'edit_pages' ) ) {
45 wp_die( esc_html__( 'Sorry, you are not allowed to access this page.', 'jetpack' ) );
46 }
47
48 $file_id = isset( $_GET['file_id'] ) ? absint( wp_unslash( $_GET['file_id'] ) ) : 0;
49
50 if ( ! $file_id ) {
51 wp_die( esc_html__( 'Invalid file request.', 'jetpack' ) );
52 }
53
54 if (
55 ! isset( $_GET['_wpnonce'] ) ||
56 ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ), 'jetpack_unauth_file_download_nonce_' . $file_id ) ) {
57 wp_die( esc_html__( 'Invalid nonce.', 'jetpack' ) );
58 }
59
60 /**
61 * Get the file content that we send to the user to download.
62 *
63 * @since 14.6
64 *
65 * @param array $file_content The file content.
66 * @param string $file_id The file ID.
67 *
68 * @return array|\WP_Error The file array, containing the content, name and type.
69 */
70 $file = apply_filters( 'jetpack_unauth_file_upload_get_file', array(), $file_id );
71
72 if ( is_wp_error( $file ) || empty( $file ) || ! is_array( $file ) ) {
73 wp_die( esc_html__( 'Error retrieving file content.', 'jetpack' ) );
74 }
75
76 // Given $file can be manipulated by a filter, make sure everything is as it should be.
77 $file['content'] = $file['content'] ?? '';
78 $file['type'] = $file['type'] ?? 'application/octet-stream';
79 $file['name'] = $file['name'] ?? '';
80
81 $is_preview = isset( $_GET['preview'] ) && 'true' === $_GET['preview'];
82
83 // Clean output buffer
84 if ( ob_get_length() ) {
85 ob_clean();
86 }
87 // Set headers for download
88 header( 'Content-Type: ' . $file['type'] );
89
90 if ( ! $is_preview ) {
91 // Forcing the file to be downloaded is important to prevent XSS attacks.
92 header( 'Content-Disposition: attachment; filename="' . sanitize_file_name( $file['name'] ) . '"' );
93 } else {
94 // For preview mode, use inline disposition
95 header( 'Content-Disposition: inline; filename="' . sanitize_file_name( $file['name'] ) . '"' );
96 }
97 header( 'Content-Length: ' . strlen( $file['content'] ) );
98 header( 'Content-Transfer-Encoding: binary' );
99 header( 'Cache-Control: no-cache, must-revalidate, max-age=0' );
100 header( 'Pragma: no-cache' );
101 header( 'Expires: 0' );
102
103 // Output file content and exit
104 echo $file['content']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Binary file data
105 exit( 0 );
106 }
107
108 /**
109 * Get the file content.
110 *
111 * @param array $file_content The file content, name and type.
112 * @param integer $file_id The file ID.
113 * @return array|\WP_Error The file content, name and type
114 */
115 function get_file_content( $file_content, $file_id ) {
116 if ( ( new \Automattic\Jetpack\Status\Host() )->is_wpcom_simple() ) {
117 return $file_content;
118 }
119
120 $blog_id = \Jetpack_Options::get_option( 'id' );
121 $request_url = sprintf( '/sites/%d/unauth-file-upload/%s', $blog_id, $file_id );
122
123 $response = \Automattic\Jetpack\Connection\Client::wpcom_json_api_request_as_blog(
124 $request_url,
125 'v2',
126 array(
127 'method' => 'GET',
128 ),
129 null,
130 'wpcom'
131 );
132
133 $file_content = wp_remote_retrieve_body( $response );
134
135 if ( is_wp_error( $response ) || empty( $file_content ) ) {
136 return new \WP_Error( 'jetpack_unauth_file_upload_error', esc_html__( 'Error retrieving file content.', 'jetpack' ) );
137 }
138
139 try {
140 $content = json_decode( $file_content, true, 3, defined( 'JSON_THROW_ON_ERROR' ) ? \JSON_THROW_ON_ERROR : 0 ); // phpcs:ignore PHPCompatibility.Constants.NewConstants.json_throw_on_errorFound
141 if ( isset( $content['message'] ) ) {
142 return new \WP_Error( 'jetpack_unauth_file_upload_error', esc_html__( 'Error retrieving file content.', 'jetpack' ) );
143 }
144 } catch ( \Exception $e ) { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch
145 // If the file is not JSON, we assume it's a binary file.
146 }
147
148 $content_disposition = wp_remote_retrieve_header( $response, 'content-disposition' );
149 $filename = '';
150 if ( $content_disposition ) {
151 // Match the filename using a regular expression
152 if ( preg_match( '/filename="([^"]+)"/', $content_disposition, $matches ) ) {
153 $filename = $matches[1]; // Extract the filename
154 }
155 }
156
157 $type = wp_remote_retrieve_header( $response, 'content-type' );
158 if ( empty( $type ) ) {
159 $type = 'application/octet-stream'; // Default to binary if no content type is found
160 }
161
162 return array(
163 'content' => $file_content,
164 'type' => $type,
165 'name' => $filename,
166 );
167 }
168