|
| 1 | +--TEST-- |
| 2 | +CURLOPT_SEEKFUNCTION callback error handling and option validation |
| 3 | +--EXTENSIONS-- |
| 4 | +curl |
| 5 | +--FILE-- |
| 6 | +<?php |
| 7 | +include 'server.inc'; |
| 8 | +$host = curl_cli_server_start(); |
| 9 | + |
| 10 | +// Drive a 307-redirect upload so libcurl invokes the seek callback to rewind |
| 11 | +// the body; $seek is the callback under test. |
| 12 | +function run_upload(string $host, callable $seek): void |
| 13 | +{ |
| 14 | + $offset = 0; |
| 15 | + $body = 'Hello cURL seek!'; |
| 16 | + $ch = curl_init("{$host}/get.inc?test=redirect"); |
| 17 | + curl_setopt($ch, CURLOPT_UPLOAD, true); |
| 18 | + curl_setopt($ch, CURLOPT_INFILESIZE, strlen($body)); |
| 19 | + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); |
| 20 | + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); |
| 21 | + curl_setopt($ch, CURLOPT_READFUNCTION, function ($ch, $fd, int $length) use ($body, &$offset) { |
| 22 | + $chunk = substr($body, $offset, $length); |
| 23 | + $offset += strlen($chunk); |
| 24 | + return $chunk; |
| 25 | + }); |
| 26 | + curl_setopt($ch, CURLOPT_SEEKFUNCTION, $seek); |
| 27 | + curl_exec($ch); |
| 28 | +} |
| 29 | + |
| 30 | +echo "Returning a non-int:\n"; |
| 31 | +try { |
| 32 | + run_upload($host, fn($ch, $offset, $origin) => 'not an int'); |
| 33 | +} catch (\TypeError $e) { |
| 34 | + echo $e->getMessage(), "\n"; |
| 35 | +} |
| 36 | + |
| 37 | +echo "\nReturning an out-of-range int:\n"; |
| 38 | +try { |
| 39 | + run_upload($host, fn($ch, $offset, $origin) => 42); |
| 40 | +} catch (\ValueError $e) { |
| 41 | + echo $e->getMessage(), "\n"; |
| 42 | +} |
| 43 | + |
| 44 | +echo "\nThrowing from the callback:\n"; |
| 45 | +try { |
| 46 | + run_upload($host, function ($ch, $offset, $origin) { |
| 47 | + throw new \RuntimeException('boom from seek'); |
| 48 | + }); |
| 49 | +} catch (\RuntimeException $e) { |
| 50 | + echo $e->getMessage(), "\n"; |
| 51 | +} |
| 52 | + |
| 53 | +echo "\nSetting the callback to null:\n"; |
| 54 | +var_dump(curl_setopt(curl_init(), CURLOPT_SEEKFUNCTION, null)); |
| 55 | + |
| 56 | +echo "\nSetting a non-callable scalar:\n"; |
| 57 | +try { |
| 58 | + curl_setopt(curl_init(), CURLOPT_SEEKFUNCTION, 42); |
| 59 | +} catch (\TypeError $e) { |
| 60 | + echo $e->getMessage(), "\n"; |
| 61 | +} |
| 62 | +?> |
| 63 | +--EXPECT-- |
| 64 | +Returning a non-int: |
| 65 | +The CURLOPT_SEEKFUNCTION callback must return one of CURL_SEEKFUNC_OK, CURL_SEEKFUNC_FAIL or CURL_SEEKFUNC_CANTSEEK |
| 66 | + |
| 67 | +Returning an out-of-range int: |
| 68 | +The CURLOPT_SEEKFUNCTION callback must return one of CURL_SEEKFUNC_OK, CURL_SEEKFUNC_FAIL or CURL_SEEKFUNC_CANTSEEK |
| 69 | + |
| 70 | +Throwing from the callback: |
| 71 | +boom from seek |
| 72 | + |
| 73 | +Setting the callback to null: |
| 74 | +bool(true) |
| 75 | + |
| 76 | +Setting a non-callable scalar: |
| 77 | +curl_setopt(): Argument #3 ($value) must be a valid callback for option CURLOPT_SEEKFUNCTION, no array or string given |
0 commit comments