From d6d3ba79afe6278ab72ae7d37cf5df7d508b8419 Mon Sep 17 00:00:00 2001 From: Nate Weller Date: Fri, 4 Oct 2024 15:53:11 -0600 Subject: [PATCH 1/9] WAF: Allow rules to specify body parser type (#39516) * WAF: Add support for rules file to manually specify body parsing method * Add public $version property to Waf_Runtime --- .../waf/changelog/add-waf-body-processor | 4 ++ .../packages/waf/src/class-waf-request.php | 57 +++++++++++++----- .../packages/waf/src/class-waf-runtime.php | 38 +++++++++++- .../waf/tests/php/unit/test-waf-request.php | 58 +++++++++++++++++++ 4 files changed, 143 insertions(+), 14 deletions(-) create mode 100644 projects/packages/waf/changelog/add-waf-body-processor diff --git a/projects/packages/waf/changelog/add-waf-body-processor b/projects/packages/waf/changelog/add-waf-body-processor new file mode 100644 index 0000000000000..df675355a4f53 --- /dev/null +++ b/projects/packages/waf/changelog/add-waf-body-processor @@ -0,0 +1,4 @@ +Significance: minor +Type: added + +Firewall Runtime: Added support for rule files to specify body parser type. diff --git a/projects/packages/waf/src/class-waf-request.php b/projects/packages/waf/src/class-waf-request.php index 5017a2e25f46c..bbb8bcf3e17f9 100644 --- a/projects/packages/waf/src/class-waf-request.php +++ b/projects/packages/waf/src/class-waf-request.php @@ -328,28 +328,59 @@ public function get_get_vars() { return flatten_array( $_GET ); } + /** + * Returns the POST variables from a JSON body + * + * @return array{string, scalar}[] + */ + private function get_json_post_vars() { + $decoded_json = json_decode( $this->get_body(), true ) ?? array(); + return flatten_array( $decoded_json, 'json', true ); + } + + /** + * Returns the POST variables from a urlencoded body + * + * @return array{string, scalar}[] + */ + private function get_urlencoded_post_vars() { + parse_str( $this->get_body(), $params ); + return flatten_array( $params ); + } + /** * Returns the POST variables * + * @param string $body_processor Manually specifiy the method to use to process the body. Options are 'URLENCODED' and 'JSON'. + * * @return array{string, scalar}[] */ - public function get_post_vars() { + public function get_post_vars( string $body_processor = '' ) { $content_type = $this->get_header( 'content-type' ); + + // If the body processor is specified by the rules file, trust it. + if ( 'URLENCODED' === $body_processor ) { + return $this->get_urlencoded_post_vars(); + } + if ( 'JSON' === $body_processor ) { + return $this->get_json_post_vars(); + } + + // Otherwise, use $_POST if it's not empty. if ( ! empty( $_POST ) ) { - // If $_POST is populated, use it. return flatten_array( $_POST ); - } elseif ( strpos( $content_type, 'application/json' ) !== false ) { - // Attempt to decode JSON requests. - $decoded_json = json_decode( $this->get_body(), true ) ?? array(); - return flatten_array( $decoded_json, 'json', true ); - } elseif ( strpos( $content_type, 'application/x-www-form-urlencoded' ) !== false ) { - // Attempt to decode url-encoded data - parse_str( $this->get_body(), $params ); - return flatten_array( $params ); - } else { - // Don't try to parse any other content types - return array(); } + + // Lastly, try to parse the body based on the content type. + if ( strpos( $content_type, 'application/json' ) !== false ) { + return $this->get_json_post_vars(); + } + if ( strpos( $content_type, 'application/x-www-form-urlencoded' ) !== false ) { + return $this->get_urlencoded_post_vars(); + } + + // Don't try to parse any other content types. + return array(); } /** diff --git a/projects/packages/waf/src/class-waf-runtime.php b/projects/packages/waf/src/class-waf-runtime.php index 394d46aa5a6f1..19300ea804582 100644 --- a/projects/packages/waf/src/class-waf-runtime.php +++ b/projects/packages/waf/src/class-waf-runtime.php @@ -38,6 +38,14 @@ class Waf_Runtime { */ const NORMALIZE_ARRAY_MATCH_VALUES = 2; + /** + * The version of this runtime class. Used by rule files to ensure compatibility. + * + * @since $$next-version$$ + * + * @var int + */ + public $version = 1; /** * Last rule. * @@ -68,6 +76,12 @@ class Waf_Runtime { * @var string */ public $matched_var_name = ''; + /** + * Body Processor. + * + * @var string 'URLENCODED' | 'JSON' | '' + */ + private $body_processor = ''; /** * State. @@ -438,7 +452,7 @@ public function meta( $key ) { $value = $this->args_names( $this->meta( 'args_get' ) ); break; case 'args_post': - $value = $this->request->get_post_vars(); + $value = $this->request->get_post_vars( $this->get_body_processor() ); break; case 'args_post_names': $value = $this->args_names( $this->meta( 'args_post' ) ); @@ -488,6 +502,28 @@ private function state_values( $prefix ) { return $output; } + /** + * Get the body processor. + * + * @return string + */ + private function get_body_processor() { + return $this->body_processor; + } + + /** + * Set the body processor. + * + * @param string $processor Processor to set. Either 'URLENCODED' or 'JSON'. + * + * @return void + */ + public function set_body_processor( $processor ) { + if ( $processor === 'URLENCODED' || $processor === 'JSON' ) { + $this->body_processor = $processor; + } + } + /** * Change a string to all lowercase and replace spaces and underscores with dashes. * diff --git a/projects/packages/waf/tests/php/unit/test-waf-request.php b/projects/packages/waf/tests/php/unit/test-waf-request.php index ce409a4b9e5ac..01c68e5aa5bea 100644 --- a/projects/packages/waf/tests/php/unit/test-waf-request.php +++ b/projects/packages/waf/tests/php/unit/test-waf-request.php @@ -301,6 +301,64 @@ public function testGetVarsPost() { $_POST = array(); } + /** + * Test that the Waf_Request class returns POST-ed data correctly decoded from JSON via Waf_Request::get_post_vars(). + */ + public function testGetVarsPostWithJsonBodyProcessor() { + $_SERVER['CONTENT_TYPE'] = 'irrelevant'; + + $request = $this->mock_request( + array( + 'body' => json_encode( + array( + 'str' => 'value', + 'arr' => array( 'a', 'b', 'c' ), + 'obj' => (object) array( 'foo' => 'bar' ), + ) + ), + ) + ); + $value = $request->get_post_vars( 'JSON' ); + $this->assertIsArray( $value ); + $this->assertContains( array( 'json.str', 'value' ), $value ); + $this->assertContains( array( 'json.arr.0', 'a' ), $value ); + $this->assertContains( array( 'json.arr.1', 'b' ), $value ); + $this->assertContains( array( 'json.arr.2', 'c' ), $value ); + $this->assertContains( array( 'json.obj.foo', 'bar' ), $value ); + + unset( $_SERVER['CONTENT_TYPE'] ); + } + + /** + * Test that the Waf_Request class returns POST-ed data correctly decoded from URLENCODED body via Waf_Request::get_post_vars(). + */ + public function testGetVarsPostWithUrlencodedBodyProcessor() { + $_SERVER['CONTENT_TYPE'] = 'irrelevant'; + + $request = $this->mock_request( + array( + 'body' => ( + http_build_query( + array( + 'str' => 'value', + 'arr' => array( 'a', 'b', 'c' ), + 'obj' => (object) array( 'foo' => 'bar' ), + ) + ) + ), + ) + ); + $value = $request->get_post_vars( 'URLENCODED' ); + $this->assertIsArray( $value ); + $this->assertContains( array( 'str', 'value' ), $value ); + $this->assertContains( array( 'arr[0]', 'a' ), $value ); + $this->assertContains( array( 'arr[1]', 'b' ), $value ); + $this->assertContains( array( 'arr[2]', 'c' ), $value ); + $this->assertContains( array( 'obj[foo]', 'bar' ), $value ); + + unset( $_SERVER['CONTENT_TYPE'] ); + } + /** * Test that the Waf_Request class returns POST-ed data correctly decoded from JSON via Waf_Request::get_post_vars(). */ From 8a5b2e774932ece77e29f89ac67c0911b4068ea5 Mon Sep 17 00:00:00 2001 From: Brandon Kraft Date: Fri, 4 Oct 2024 19:18:06 -0500 Subject: [PATCH 2/9] Blocks: provide nice error message for workaround in dev env (#39602) * Provide nice error message for workaround * typos will be the dealth of me --- projects/plugins/jetpack/changelog/add-nice-fatal-message | 5 +++++ projects/plugins/jetpack/class.jetpack-gutenberg.php | 4 ++++ 2 files changed, 9 insertions(+) create mode 100644 projects/plugins/jetpack/changelog/add-nice-fatal-message diff --git a/projects/plugins/jetpack/changelog/add-nice-fatal-message b/projects/plugins/jetpack/changelog/add-nice-fatal-message new file mode 100644 index 0000000000000..70f2483520a3d --- /dev/null +++ b/projects/plugins/jetpack/changelog/add-nice-fatal-message @@ -0,0 +1,5 @@ +Significance: patch +Type: other +Comment: Just adding a nicer error message that would only display in dev environments. + + diff --git a/projects/plugins/jetpack/class.jetpack-gutenberg.php b/projects/plugins/jetpack/class.jetpack-gutenberg.php index 7968f0452f7df..6fa4dd4ed04cf 100644 --- a/projects/plugins/jetpack/class.jetpack-gutenberg.php +++ b/projects/plugins/jetpack/class.jetpack-gutenberg.php @@ -674,6 +674,10 @@ public static function enqueue_block_editor_assets() { // wp-edit-post but wp-edit-post's styles break the Widget Editor and // Site Editor) until a real fix gets unblocked. // @todo Remove this once #20357 is properly fixed. + $wp_styles_fix = wp_styles()->query( 'jetpack-blocks-editor', 'registered' ); + if ( empty( $wp_styles_fix ) ) { + wp_die( 'Your installation of Jetpack is incomplete. Please run "jetpack build plugins/jetpack" in your dev env.' ); + } wp_styles()->query( 'jetpack-blocks-editor', 'registered' )->deps = array(); Assets::enqueue_script( 'jetpack-blocks-editor' ); From 6b41b2a138ec358e76bc21eac59b5687837383a9 Mon Sep 17 00:00:00 2001 From: Grzegorz Chudzinski-Pawlowski <112354940+grzegorz-cp@users.noreply.github.com> Date: Mon, 7 Oct 2024 12:56:43 +1300 Subject: [PATCH 3/9] Settings - Newsletter, Sharing: Disabling options for sites missing user connection (#39520) * Newsletters: Disabling controls that need user connection * changelog * Settings: Fixing disabled label when not saving * Settings: Improving isLinked check * Settings: Removing disabled CSS from active controls * Settings: Disabling sharing without a connected user * Settings: Disabling newsletter settings for sites without a single connected user * Settings: Disabling also whole groups * Settings: Updating the description of the task * Settings: Updating the description of the task --- .../settings-disable-inactive-elements | 5 ++++ .../client/components/settings-card/index.jsx | 13 ++++++++-- .../_inc/client/newsletter/email-settings.jsx | 24 +++++++++---------- .../client/newsletter/messages-setting.jsx | 22 +++++++---------- .../newsletter/newsletter-categories.jsx | 23 +++++++++--------- .../_inc/client/newsletter/newsletter.jsx | 14 ++++++++--- .../client/newsletter/paid-newsletter.jsx | 11 +++++---- .../newsletter/subscriptions-settings.jsx | 18 +++++++++++--- .../jetpack/_inc/client/sharing/publicize.jsx | 6 +++-- .../settings-disable-inactive-elements | 5 ++++ 10 files changed, 89 insertions(+), 52 deletions(-) create mode 100644 projects/packages/my-jetpack/changelog/settings-disable-inactive-elements create mode 100644 projects/plugins/jetpack/changelog/settings-disable-inactive-elements diff --git a/projects/packages/my-jetpack/changelog/settings-disable-inactive-elements b/projects/packages/my-jetpack/changelog/settings-disable-inactive-elements new file mode 100644 index 0000000000000..cd89bbb31e2bb --- /dev/null +++ b/projects/packages/my-jetpack/changelog/settings-disable-inactive-elements @@ -0,0 +1,5 @@ +Significance: patch +Type: fixed +Comment: Disable controls that require user connection. + + diff --git a/projects/plugins/jetpack/_inc/client/components/settings-card/index.jsx b/projects/plugins/jetpack/_inc/client/components/settings-card/index.jsx index f388ffbb37235..4bc2a10179aa8 100644 --- a/projects/plugins/jetpack/_inc/client/components/settings-card/index.jsx +++ b/projects/plugins/jetpack/_inc/client/components/settings-card/index.jsx @@ -51,6 +51,7 @@ export const SettingsCard = inprops => { const props = { action: '', saveDisabled: false, + isDisabled: false, ...inprops, }; @@ -94,6 +95,7 @@ export const SettingsCard = inprops => { return ; } + const isDisabled = props.isDisabled; const isSaving = props.saveDisabled, feature = props.feature ? props.feature : false; let header = props.header ? props.header : ''; @@ -545,11 +547,17 @@ export const SettingsCard = inprops => {
{ ! props.hideButton && ( -