|
27 | 27 | use Symfony\Component\HttpFoundation\Response; |
28 | 28 | use Symfony\Contracts\Translation\TranslatorInterface; |
29 | 29 |
|
| 30 | +use function file_put_contents; |
30 | 31 | use function json_encode; |
| 32 | +use function sys_get_temp_dir; |
| 33 | +use function tempnam; |
| 34 | +use function unlink; |
31 | 35 |
|
32 | 36 | #[CoversClass(UploadController::class)] |
33 | 37 | #[CoversClass(AbstractController::class)] |
@@ -78,7 +82,7 @@ public function testUpload(): void |
78 | 82 | ->willReturn('sample_image'); |
79 | 83 |
|
80 | 84 | $uploadedFileMock |
81 | | - ->expects(self::exactly(2)) |
| 85 | + ->expects(self::exactly(3)) |
82 | 86 | ->method('getClientOriginalExtension') |
83 | 87 | ->willReturn('jpg'); |
84 | 88 |
|
@@ -179,6 +183,265 @@ public function testUpload(): void |
179 | 183 | ); |
180 | 184 | } |
181 | 185 |
|
| 186 | + public function testUploadEncryptedPdfIsRaw(): void |
| 187 | + { |
| 188 | + $tmpPdfPath = (string) tempnam(sys_get_temp_dir(), 'ngrm_encrypted_pdf_'); |
| 189 | + file_put_contents($tmpPdfPath, "%PDF-1.7\n1 0 obj\n<< /Encrypt 2 0 R >>\nendobj\n"); |
| 190 | + |
| 191 | + $request = new Request(); |
| 192 | + $request->request->add([ |
| 193 | + 'folder' => 'media/document', |
| 194 | + ]); |
| 195 | + |
| 196 | + $uploadedFileMock = $this->createMock(UploadedFile::class); |
| 197 | + |
| 198 | + $uploadedFileMock |
| 199 | + ->expects(self::once()) |
| 200 | + ->method('isFile') |
| 201 | + ->willReturn(true); |
| 202 | + |
| 203 | + // getRealPath is used for md5 hash + FileStruct + encryption detector |
| 204 | + $uploadedFileMock |
| 205 | + ->expects(self::exactly(4)) |
| 206 | + ->method('getRealPath') |
| 207 | + ->willReturn($tmpPdfPath); |
| 208 | + |
| 209 | + $uploadedFileMock |
| 210 | + ->expects(self::exactly(2)) |
| 211 | + ->method('getClientOriginalName') |
| 212 | + ->willReturn('protected.pdf'); |
| 213 | + |
| 214 | + // getClientOriginalExtension is used for FileStruct + encryption detector |
| 215 | + $uploadedFileMock |
| 216 | + ->expects(self::exactly(3)) |
| 217 | + ->method('getClientOriginalExtension') |
| 218 | + ->willReturn('pdf'); |
| 219 | + |
| 220 | + $request->files->add([ |
| 221 | + 'file' => $uploadedFileMock, |
| 222 | + ]); |
| 223 | + |
| 224 | + $this->fileHashFactoryMock |
| 225 | + ->expects(self::once()) |
| 226 | + ->method('createHash') |
| 227 | + ->with($tmpPdfPath) |
| 228 | + ->willReturn('md5hash'); |
| 229 | + |
| 230 | + $fileStruct = FileStruct::fromUploadedFile($uploadedFileMock); |
| 231 | + |
| 232 | + $resourceStruct = new ResourceStruct( |
| 233 | + $fileStruct, |
| 234 | + 'raw', |
| 235 | + Folder::fromPath('media/document'), |
| 236 | + 'public', |
| 237 | + $request->request->get('filename'), |
| 238 | + ); |
| 239 | + |
| 240 | + $resource = new RemoteResource( |
| 241 | + remoteId: 'upload|raw|media/document/protected.pdf', |
| 242 | + type: 'raw', |
| 243 | + url: 'https://cloudinary.com/test/upload/raw/media/document/protected.pdf', |
| 244 | + md5: 'md5hash', |
| 245 | + name: 'protected.pdf', |
| 246 | + folder: Folder::fromPath('media/document'), |
| 247 | + size: 123, |
| 248 | + ); |
| 249 | + |
| 250 | + $this->providerMock |
| 251 | + ->expects(self::once()) |
| 252 | + ->method('upload') |
| 253 | + ->with($resourceStruct) |
| 254 | + ->willReturn($resource); |
| 255 | + |
| 256 | + $this->providerMock |
| 257 | + ->expects(self::exactly(0)) |
| 258 | + ->method('buildVariation') |
| 259 | + ->willReturnCallback( |
| 260 | + static fn () => new RemoteResourceVariation( |
| 261 | + $resource, |
| 262 | + 'https://cloudinary.com/test/variation/url', |
| 263 | + ), |
| 264 | + ); |
| 265 | + |
| 266 | + $response = $this->controller->__invoke($request); |
| 267 | + |
| 268 | + self::assertInstanceOf(JsonResponse::class, $response); |
| 269 | + |
| 270 | + unlink($tmpPdfPath); |
| 271 | + } |
| 272 | + |
| 273 | + public function testUploadPdfWithEncryptInMetadataIsAuto(): void |
| 274 | + { |
| 275 | + $tmpPdfPath = (string) tempnam(sys_get_temp_dir(), 'ngrm_unencrypted_pdf_metadata_'); |
| 276 | + file_put_contents( |
| 277 | + $tmpPdfPath, |
| 278 | + "%PDF-1.7\n1 0 obj\n<< /Type /Catalog >>\nendobj\n" |
| 279 | + . "/Title (/Encrypt)\n" |
| 280 | + . "%%EOF\n", |
| 281 | + ); |
| 282 | + |
| 283 | + $request = new Request(); |
| 284 | + $request->request->add([ |
| 285 | + 'folder' => 'media/document', |
| 286 | + ]); |
| 287 | + |
| 288 | + $uploadedFileMock = $this->createMock(UploadedFile::class); |
| 289 | + |
| 290 | + $uploadedFileMock |
| 291 | + ->expects(self::once()) |
| 292 | + ->method('isFile') |
| 293 | + ->willReturn(true); |
| 294 | + |
| 295 | + // getRealPath is used for md5 hash + FileStruct + encryption detector |
| 296 | + $uploadedFileMock |
| 297 | + ->expects(self::exactly(4)) |
| 298 | + ->method('getRealPath') |
| 299 | + ->willReturn($tmpPdfPath); |
| 300 | + |
| 301 | + $uploadedFileMock |
| 302 | + ->expects(self::exactly(2)) |
| 303 | + ->method('getClientOriginalName') |
| 304 | + ->willReturn('unencrypted.pdf'); |
| 305 | + |
| 306 | + // getClientOriginalExtension is used for FileStruct + encryption detector |
| 307 | + $uploadedFileMock |
| 308 | + ->expects(self::exactly(3)) |
| 309 | + ->method('getClientOriginalExtension') |
| 310 | + ->willReturn('pdf'); |
| 311 | + |
| 312 | + $request->files->add([ |
| 313 | + 'file' => $uploadedFileMock, |
| 314 | + ]); |
| 315 | + |
| 316 | + $this->fileHashFactoryMock |
| 317 | + ->expects(self::once()) |
| 318 | + ->method('createHash') |
| 319 | + ->with($tmpPdfPath) |
| 320 | + ->willReturn('md5hash'); |
| 321 | + |
| 322 | + $fileStruct = FileStruct::fromUploadedFile($uploadedFileMock); |
| 323 | + |
| 324 | + $resourceStruct = new ResourceStruct( |
| 325 | + $fileStruct, |
| 326 | + 'auto', |
| 327 | + Folder::fromPath('media/document'), |
| 328 | + 'public', |
| 329 | + $request->request->get('filename'), |
| 330 | + ); |
| 331 | + |
| 332 | + $resource = new RemoteResource( |
| 333 | + remoteId: 'upload|auto|media/document/unencrypted.pdf', |
| 334 | + type: 'auto', |
| 335 | + url: 'https://cloudinary.com/test/upload/auto/media/document/unencrypted.pdf', |
| 336 | + md5: 'md5hash', |
| 337 | + name: 'unencrypted.pdf', |
| 338 | + folder: Folder::fromPath('media/document'), |
| 339 | + size: 123, |
| 340 | + ); |
| 341 | + |
| 342 | + $this->providerMock |
| 343 | + ->expects(self::once()) |
| 344 | + ->method('upload') |
| 345 | + ->with($resourceStruct) |
| 346 | + ->willReturn($resource); |
| 347 | + |
| 348 | + $this->providerMock |
| 349 | + ->expects(self::exactly(0)) |
| 350 | + ->method('buildVariation'); |
| 351 | + |
| 352 | + $response = $this->controller->__invoke($request); |
| 353 | + |
| 354 | + self::assertInstanceOf(JsonResponse::class, $response); |
| 355 | + |
| 356 | + unlink($tmpPdfPath); |
| 357 | + } |
| 358 | + |
| 359 | + public function testUploadPdfWithEncryptInTrailingCommentAfterEofIsAuto(): void |
| 360 | + { |
| 361 | + $tmpPdfPath = (string) tempnam(sys_get_temp_dir(), 'ngrm_unencrypted_pdf_comment_'); |
| 362 | + file_put_contents( |
| 363 | + $tmpPdfPath, |
| 364 | + "%PDF-1.7\n1 0 obj\n<< /Type /Catalog >>\nendobj\n" |
| 365 | + . "%%EOF\n" |
| 366 | + . "% /Encrypt 2 0 R\n", |
| 367 | + ); |
| 368 | + |
| 369 | + $request = new Request(); |
| 370 | + $request->request->add([ |
| 371 | + 'folder' => 'media/document', |
| 372 | + ]); |
| 373 | + |
| 374 | + $uploadedFileMock = $this->createMock(UploadedFile::class); |
| 375 | + |
| 376 | + $uploadedFileMock |
| 377 | + ->expects(self::once()) |
| 378 | + ->method('isFile') |
| 379 | + ->willReturn(true); |
| 380 | + |
| 381 | + // getRealPath is used for md5 hash + FileStruct + encryption detector |
| 382 | + $uploadedFileMock |
| 383 | + ->expects(self::exactly(4)) |
| 384 | + ->method('getRealPath') |
| 385 | + ->willReturn($tmpPdfPath); |
| 386 | + |
| 387 | + $uploadedFileMock |
| 388 | + ->expects(self::exactly(2)) |
| 389 | + ->method('getClientOriginalName') |
| 390 | + ->willReturn('unencrypted.pdf'); |
| 391 | + |
| 392 | + // getClientOriginalExtension is used for FileStruct + encryption detector |
| 393 | + $uploadedFileMock |
| 394 | + ->expects(self::exactly(3)) |
| 395 | + ->method('getClientOriginalExtension') |
| 396 | + ->willReturn('pdf'); |
| 397 | + |
| 398 | + $request->files->add([ |
| 399 | + 'file' => $uploadedFileMock, |
| 400 | + ]); |
| 401 | + |
| 402 | + $this->fileHashFactoryMock |
| 403 | + ->expects(self::once()) |
| 404 | + ->method('createHash') |
| 405 | + ->with($tmpPdfPath) |
| 406 | + ->willReturn('md5hash'); |
| 407 | + |
| 408 | + $fileStruct = FileStruct::fromUploadedFile($uploadedFileMock); |
| 409 | + |
| 410 | + $resourceStruct = new ResourceStruct( |
| 411 | + $fileStruct, |
| 412 | + 'auto', |
| 413 | + Folder::fromPath('media/document'), |
| 414 | + 'public', |
| 415 | + $request->request->get('filename'), |
| 416 | + ); |
| 417 | + |
| 418 | + $resource = new RemoteResource( |
| 419 | + remoteId: 'upload|auto|media/document/unencrypted.pdf', |
| 420 | + type: 'auto', |
| 421 | + url: 'https://cloudinary.com/test/upload/auto/media/document/unencrypted.pdf', |
| 422 | + md5: 'md5hash', |
| 423 | + name: 'unencrypted.pdf', |
| 424 | + folder: Folder::fromPath('media/document'), |
| 425 | + size: 123, |
| 426 | + ); |
| 427 | + |
| 428 | + $this->providerMock |
| 429 | + ->expects(self::once()) |
| 430 | + ->method('upload') |
| 431 | + ->with($resourceStruct) |
| 432 | + ->willReturn($resource); |
| 433 | + |
| 434 | + $this->providerMock |
| 435 | + ->expects(self::exactly(0)) |
| 436 | + ->method('buildVariation'); |
| 437 | + |
| 438 | + $response = $this->controller->__invoke($request); |
| 439 | + |
| 440 | + self::assertInstanceOf(JsonResponse::class, $response); |
| 441 | + |
| 442 | + unlink($tmpPdfPath); |
| 443 | + } |
| 444 | + |
182 | 445 | public function testUploadProtectedWithContext(): void |
183 | 446 | { |
184 | 447 | $uploadContext = [ |
@@ -211,7 +474,7 @@ public function testUploadProtectedWithContext(): void |
211 | 474 | ->willReturn('sample_image'); |
212 | 475 |
|
213 | 476 | $uploadedFileMock |
214 | | - ->expects(self::exactly(2)) |
| 477 | + ->expects(self::exactly(3)) |
215 | 478 | ->method('getClientOriginalExtension') |
216 | 479 | ->willReturn('jpg'); |
217 | 480 |
|
@@ -396,7 +659,7 @@ public function testUploadExistingFile(): void |
396 | 659 | ->willReturn('sample_image'); |
397 | 660 |
|
398 | 661 | $uploadedFileMock |
399 | | - ->expects(self::exactly(2)) |
| 662 | + ->expects(self::exactly(3)) |
400 | 663 | ->method('getClientOriginalExtension') |
401 | 664 | ->willReturn('jpg'); |
402 | 665 |
|
@@ -555,7 +818,7 @@ public function testUploadExistingFileName(): void |
555 | 818 | ->willReturn('sample_image'); |
556 | 819 |
|
557 | 820 | $uploadedFileMock |
558 | | - ->expects(self::exactly(2)) |
| 821 | + ->expects(self::exactly(3)) |
559 | 822 | ->method('getClientOriginalExtension') |
560 | 823 | ->willReturn('jpg'); |
561 | 824 |
|
|
0 commit comments