Skip to content

Commit 4134899

Browse files
committed
WIP Bundle path validation
1 parent f12933a commit 4134899

1 file changed

Lines changed: 43 additions & 3 deletions

File tree

components/Blueprints/BlueprintParser.php

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ private function createExecutionPlan( array $blueprint ): array {
274274
if ( isset( $blueprint['activeTheme'] ) ) {
275275
$themeRef = $blueprint['activeTheme'];
276276
if ( is_string( $themeRef ) ) {
277-
$plan[] = [
277+
$step = [
278278
'name' => 'installTheme',
279279
'args' => [
280280
'source' => $themeRef,
@@ -283,9 +283,9 @@ private function createExecutionPlan( array $blueprint ): array {
283283
]
284284
];
285285
} elseif ( is_array( $themeRef ) && isset( $themeRef['source'] ) && is_string( $themeRef['source'] ) ) {
286-
$plan[] = [
286+
$step = [
287287
'name' => 'installTheme',
288-
'args' => [
288+
'args' => [
289289
'source' => $themeRef['source'],
290290
'active' => true,
291291
'importStarterContent' => $themeRef['importStarterContent'] ?? false,
@@ -295,6 +295,12 @@ private function createExecutionPlan( array $blueprint ): array {
295295
} else {
296296
throw new InvalidArgumentException( 'Invalid theme reference format for "activeTheme".' );
297297
}
298+
299+
$plan[] = $step;
300+
$error = $this->validateDataSource( $step['args']['source'], 'wp-content/themes/' );
301+
if ( $error ) {
302+
$errors['themes'] = [$error];
303+
}
298304
}
299305

300306
// 6. plugins
@@ -309,6 +315,11 @@ private function createExecutionPlan( array $blueprint ): array {
309315
'name' => 'installPlugin',
310316
'args' => $pluginDef
311317
];
318+
319+
$error = $this->validateDataSource( $pluginDef['source'], 'wp-content/plugins/' );
320+
if ( $error ) {
321+
$errors['plugins'] = [$error];
322+
}
312323
}
313324
}
314325

@@ -410,4 +421,33 @@ private function createExecutionPlan( array $blueprint ): array {
410421

411422
return [ $plan, $errors ];
412423
}
424+
425+
private function validateDataSource( string $source, string $bundle_prefix ): ?string {
426+
427+
if ( strlen( $source ) === 0 ) {
428+
return 'Source must be a non-empty string.';
429+
}
430+
431+
// 1. Absolute URL.
432+
if ( str_contains( $source, '://' ) ) {
433+
return null;
434+
}
435+
436+
// 2. Bundle-relative path.
437+
$byte_1 = $source[0];
438+
$byte_2 = $source[1] ?? null;
439+
if ( str_contains( $source, '/' ) ) {
440+
if ( $byte_1 === '/' ) {
441+
$source = substr( $source, 1 );
442+
} elseif ( $byte_1 === '.' && $byte_2 === '/' ) {
443+
$source = substr( $source, 2 );
444+
}
445+
446+
if ( ! str_starts_with( $source, $bundle_prefix ) ) {
447+
return 'Source must be a relative path starting with "' . $bundle_prefix . '".';
448+
}
449+
}
450+
451+
return null;
452+
}
413453
}

0 commit comments

Comments
 (0)