Skip to content

Commit 45ea455

Browse files
committed
wip
1 parent a53c87d commit 45ea455

1 file changed

Lines changed: 45 additions & 1 deletion

File tree

components/Blueprints/BlueprintParser.php

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,14 @@ private function buildPluginStep( $plugin ): array {
417417
$plugin = [ 'source' => $plugin ];
418418
}
419419

420-
$error = $this->validateDataSource( $plugin['source'], 'wp-content/plugins/*' );
420+
$source = $plugin['source'];
421+
$error = $this->validateDataSource( $source, 'wp-content/plugins/*' );
422+
if ( null === $error ) {
423+
if ( str_ends_with( $source, '.php' ) ) {
424+
$error = $this->validatePluginFile( $source );
425+
}
426+
}
427+
421428
return [
422429
'key' => 'plugins',
423430
'name' => 'installPlugin',
@@ -554,6 +561,43 @@ private function validateDataSource( string $source, string $allowed_pattern ):
554561
return null;
555562
}
556563

564+
/**
565+
* Validate a plugin file as per WordPress plugin requirements.
566+
*
567+
* The implementation mirrors "get_file_data()" from WordPress core.
568+
*
569+
* @param string $source The path to the plugin file.
570+
* @return string|null An error message if the plugin file is invalid, or null if it is valid.
571+
*/
572+
private function validatePluginFile( string $source ): ?string {
573+
$root = $this->configuration->getTargetSiteRoot();
574+
$file = rtrim( $root, '/' ) . ltrim( $source, '.' );
575+
576+
// Pull only the first 8 KB of the file in.
577+
$file_data = file_get_contents( $file, false, null, 0, 8 * 1024 );
578+
if ( false === $file_data ) {
579+
$file_data = '';
580+
}
581+
582+
// Make sure we catch CR-only line endings.
583+
$file_data = str_replace( "\r", "\n", $file_data );
584+
585+
// We only need to check for the plugin name header.
586+
$all_headers = array( 'Name' => 'Plugin Name' );
587+
foreach ( $all_headers as $field => $regex ) {
588+
if ( preg_match( '/^(?:[ \t]*<\?php)?[ \t\/*#@]*' . preg_quote( $regex, '/' ) . ':(.*)$/mi', $file_data, $match ) && $match[1] ) {
589+
$all_headers[ $field ] = $match[1];
590+
} else {
591+
$all_headers[ $field ] = '';
592+
}
593+
}
594+
595+
if ( empty( $all_headers['Name'] ) ) {
596+
return 'Invalid plugin file. Missing "Plugin Name" header.';
597+
}
598+
return null;
599+
}
600+
557601
/**
558602
* Detect on which line a top-level JSON key is defined in the input string.
559603
* This is a simple helper that only supports top-level keys in a top-level

0 commit comments

Comments
 (0)