views:

31

answers:

1

I am using PHP S3.PHP class to manage files on Amazon S3. I use the copyObject() function to copy files in my S3 bucket. All works great until I meet filenames that need to be urlencoded (I urlencode everything anyway). When a filename ends up with % characters in it the copyObject() function spits the dummy.

for example - the filename 63037_Copy%287%29ofDSC_1337.JPG throws the following error when passed to copyObject() -

Warning:  sprintf() [<a href='function.sprintf'>function.sprintf</a>]: Too few arguments in ..... S3.php on line 477

Here's the copyObject function line 477

public static function copyObject($srcBucket, $srcUri, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $requestHeaders = array()) {
    $rest = new S3Request('PUT', $bucket, $uri);
    $rest->setHeader('Content-Length', 0);
    foreach ($requestHeaders as $h => $v) $rest->setHeader($h, $v);
    foreach ($metaHeaders as $h => $v) $rest->setAmzHeader('x-amz-meta-'.$h, $v);
    $rest->setAmzHeader('x-amz-acl', $acl);
    $rest->setAmzHeader('x-amz-copy-source', sprintf('/%s/%s', $srcBucket, $srcUri));
    if (sizeof($requestHeaders) > 0 || sizeof($metaHeaders) > 0)
        $rest->setAmzHeader('x-amz-metadata-directive', 'REPLACE');
    $rest = $rest->getResponse();
    if ($rest->error === false && $rest->code !== 200)
        $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
    if ($rest->error !== false) {
-------------------------------------------- LINE 477 ----------------------------


        **trigger_error(sprintf("S3::copyObject({$srcBucket}, {$srcUri}, {$bucket}, {$uri}): [%s] %s",
        $rest->error['code'], $rest->error['message']), E_USER_WARNING);**


-------------------------------------------- LINE 477 ----------------------------

        return false;
    }
    return isset($rest->body->LastModified, $rest->body->ETag) ? array(
        'time' => strtotime((string)$rest->body->LastModified),
        'hash' => substr((string)$rest->body->ETag, 1, -1)
    ) : false;
}

Has anyone come across this before? There is absolutely no problem when using filenames which don't change when urlencoded, and Ive already tried removing all whitespace from filenames but wont be able to catch all characters, like brackets which is the problem in the example here. And I dont want to go down that road anyway as I want to keep the filenames as close to the original as possible.

thanks guys

+1  A: 

Redo the line this way:

trigger_error("S3::copyObject({$srcBucket}, {$srcUri}, {$bucket}, {$uri}): ". sprintf("[%s] %s",
        $rest->error['code'], $rest->error['message']), E_USER_WARNING);

%'s in the first parameter to sprintf are identified as the placeholders for values. Because your filenames are first inserted in the string and that string is then passed to sprintf(), sprintf() mistakenly interprets the %'s in the file names as placeholders.

m1tk4
Thanks, that may have been the correct answer but I ended up just doing a str_replace on the filename when it was uploaded to avoid this problem all together. Thanks for your response, regards.
undefined