Skip to content

Commit 0ec0007

Browse files
authored
Merge pull request #152 from DirectoryTree/bug-151
Implement safe token reads when parsing message body parts
2 parents e41dd11 + e5f0d0f commit 0ec0007

File tree

2 files changed

+55
-7
lines changed

2 files changed

+55
-7
lines changed

src/BodyStructurePart.php

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,18 +43,46 @@ protected static function parse(array $tokens, string $partNumber): static
4343
{
4444
return new static(
4545
partNumber: $partNumber,
46-
type: isset($tokens[0]) ? strtolower($tokens[0]->value) : 'text',
47-
subtype: isset($tokens[1]) ? strtolower($tokens[1]->value) : 'plain',
46+
type: strtolower(static::tokenValueAt($tokens, 0) ?? 'text'),
47+
subtype: strtolower(static::tokenValueAt($tokens, 1) ?? 'plain'),
4848
parameters: isset($tokens[2]) && $tokens[2] instanceof ListData ? $tokens[2]->toKeyValuePairs() : [],
49-
id: isset($tokens[3]) && ! $tokens[3] instanceof Nil ? $tokens[3]->value : null,
50-
description: isset($tokens[4]) && ! $tokens[4] instanceof Nil ? $tokens[4]->value : null,
51-
encoding: isset($tokens[5]) && ! $tokens[5] instanceof Nil ? $tokens[5]->value : null,
52-
size: isset($tokens[6]) && ! $tokens[6] instanceof Nil ? (int) $tokens[6]->value : null,
53-
lines: isset($tokens[7]) && ! $tokens[7] instanceof Nil ? (int) $tokens[7]->value : null,
49+
id: static::tokenValueAt($tokens, 3),
50+
description: static::tokenValueAt($tokens, 4),
51+
encoding: static::tokenValueAt($tokens, 5),
52+
size: static::tokenIntValueAt($tokens, 6),
53+
lines: static::tokenIntValueAt($tokens, 7),
5454
disposition: ContentDisposition::parse($tokens),
5555
);
5656
}
5757

58+
/**
59+
* Safely read a scalar token value from the parsed body structure.
60+
*
61+
* @param array<Token|ListData> $tokens
62+
*/
63+
protected static function tokenValueAt(array $tokens, int $index): ?string
64+
{
65+
$token = $tokens[$index] ?? null;
66+
67+
if (! $token instanceof Token || $token instanceof Nil) {
68+
return null;
69+
}
70+
71+
return $token->value;
72+
}
73+
74+
/**
75+
* Safely read an integer token value from the parsed body structure.
76+
*
77+
* @param array<Token|ListData> $tokens
78+
*/
79+
protected static function tokenIntValueAt(array $tokens, int $index): ?int
80+
{
81+
$value = static::tokenValueAt($tokens, $index);
82+
83+
return $value === null ? null : (int) $value;
84+
}
85+
5886
/**
5987
* Get the part number (e.g., "1", "1.2", "2.1.3").
6088
*/

tests/Unit/BodyStructureTest.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,26 @@ function parseBodyStructureResponse(string $response): ListData
152152
expect($imagePart->id())->toBe('<cid123>');
153153
});
154154

155+
test('it does not emit warnings when non-scalar tokens appear in message/rfc822 structure fields', function () {
156+
$listData = parseBodyStructureResponse(
157+
'* 1 FETCH (BODYSTRUCTURE ("MESSAGE" "RFC822" NIL NIL NIL "7BIT" 3456 (NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL) ("TEXT" "PLAIN" ("charset" "utf-8") NIL NIL "7BIT" 100 10 NIL NIL NIL) 42) UID 1)'
158+
);
159+
160+
set_error_handler(static function (int $severity, string $message, string $file, int $line): never {
161+
throw new ErrorException($message, 0, $severity, $file, $line);
162+
});
163+
164+
try {
165+
$part = BodyStructurePart::fromListData($listData);
166+
} finally {
167+
restore_error_handler();
168+
}
169+
170+
expect($part->contentType())->toBe('message/rfc822');
171+
expect($part->size())->toBe(3456);
172+
expect($part->lines())->toBeNull();
173+
});
174+
155175
test('it makes BodyStructureCollection countable', function () {
156176
$listData = parseBodyStructureResponse(
157177
'* 1 FETCH (BODYSTRUCTURE (("text" "plain" ("charset" "utf-8") NIL NIL "7bit" 100 5 NIL NIL NIL) ("text" "html" ("charset" "utf-8") NIL NIL "7bit" 200 10 NIL NIL NIL) "alternative" ("boundary" "abc") NIL NIL) UID 1)'

0 commit comments

Comments
 (0)