Skip to content

Commit d7a58e9

Browse files
authored
Merge pull request #1351 from abraham/file-path
Consistent file validation
2 parents 3af0fde + b673ddf commit d7a58e9

2 files changed

Lines changed: 63 additions & 4 deletions

File tree

src/TwitterOAuth.php

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -359,10 +359,8 @@ public function mediaStatus(string $media_id)
359359
*/
360360
private function uploadMediaNotChunked(string $path, array $parameters)
361361
{
362-
if (
363-
!is_readable($parameters['media']) ||
364-
($file = file_get_contents($parameters['media'])) === false
365-
) {
362+
$this->validateMediaPath($parameters['media']);
363+
if (($file = file_get_contents($parameters['media'])) === false) {
366364
throw new \InvalidArgumentException(
367365
'You must supply a readable file',
368366
);
@@ -383,6 +381,7 @@ private function uploadMediaNotChunked(string $path, array $parameters)
383381
*/
384382
private function uploadMediaChunked(string $path, array $parameters)
385383
{
384+
$this->validateMediaPath($parameters['media']);
386385
/** @var object $init */
387386
$init = $this->http(
388387
'POST',
@@ -430,6 +429,26 @@ private function uploadMediaChunked(string $path, array $parameters)
430429
return $finalize;
431430
}
432431

432+
/**
433+
* Validate upload media path before reading from disk.
434+
*
435+
* @param string $mediaPath
436+
*/
437+
private function validateMediaPath(string $mediaPath): void
438+
{
439+
if (
440+
!stream_is_local($mediaPath) ||
441+
!file_exists($mediaPath) ||
442+
!is_file($mediaPath) ||
443+
is_link($mediaPath) ||
444+
!is_readable($mediaPath)
445+
) {
446+
throw new \InvalidArgumentException(
447+
'You must supply a readable file',
448+
);
449+
}
450+
}
451+
433452
/**
434453
* Private method to get params for upload media chunked init.
435454
* Twitter docs: https://dev.x.com/rest/reference/post/media/upload-init.html

tests/TwitterOAuthMediaTest.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,4 +113,44 @@ public function testPostStatusesUpdateWithMediaChunkedException()
113113
}
114114
assert($caught);
115115
}
116+
117+
public function testUploadRejectsSymlinkForNotChunked()
118+
{
119+
$target = __DIR__ . '/kitten.jpg';
120+
$link = __DIR__ . '/kitten-symlink.jpg';
121+
122+
@unlink($link);
123+
if (!symlink($target, $link)) {
124+
$this->markTestSkipped('Unable to create symlink on this system.');
125+
}
126+
127+
try {
128+
$this->expectException(\InvalidArgumentException::class);
129+
$this->twitter->upload('media/upload', ['media' => $link]);
130+
} finally {
131+
@unlink($link);
132+
}
133+
}
134+
135+
public function testUploadRejectsSymlinkForChunked()
136+
{
137+
$target = __DIR__ . '/video.mp4';
138+
$link = __DIR__ . '/video-symlink.mp4';
139+
140+
@unlink($link);
141+
if (!symlink($target, $link)) {
142+
$this->markTestSkipped('Unable to create symlink on this system.');
143+
}
144+
145+
try {
146+
$this->expectException(\InvalidArgumentException::class);
147+
$this->twitter->upload(
148+
'media/upload',
149+
['media' => $link, 'media_type' => 'video/mp4'],
150+
['chunkedUpload' => true],
151+
);
152+
} finally {
153+
@unlink($link);
154+
}
155+
}
116156
}

0 commit comments

Comments
 (0)