*/
public function __construct( array $config ) {
parent::__construct( $config );
- if ( !MWInit::classExists( 'CF_Constants' ) ) {
+ if ( !class_exists( 'CF_Constants' ) ) {
throw new MWException( 'SwiftCloudFiles extension not installed.' );
}
// Required settings
: false;
$this->swiftCDNExpiry = isset( $config['swiftCDNExpiry'] )
? $config['swiftCDNExpiry']
- : 12*3600; // 12 hours is safe (tokens last 24 hours per http://docs.openstack.org)
+ : 12 * 3600; // 12 hours is safe (tokens last 24 hours per http://docs.openstack.org)
$this->swiftCDNPurgable = isset( $config['swiftCDNPurgable'] )
? $config['swiftCDNPurgable']
: true;
}
/**
- * @param string $disposition Content-Disposition header value
+ * @param $headers array
+ * @return array
+ */
+ protected function sanitizeHdrs( array $headers ) {
+ // By default, Swift has annoyingly low maximum header value limits
+ if ( isset( $headers['Content-Disposition'] ) ) {
+ $headers['Content-Disposition'] = $this->truncDisp( $headers['Content-Disposition'] );
+ }
+ return $headers;
+ }
+
+ /**
+ * @param $disposition string Content-Disposition header value
* @return string Truncated Content-Disposition header value to meet Swift limits
*/
protected function truncDisp( $disposition ) {
if ( !strlen( $obj->content_type ) ) { // special case
$obj->content_type = 'unknown/unknown';
}
- // Set the Content-Disposition header if requested
- if ( isset( $params['disposition'] ) ) {
- $obj->headers['Content-Disposition'] = $this->truncDisp( $params['disposition'] );
- }
// Set any other custom headers if requested
if ( isset( $params['headers'] ) ) {
- $obj->headers += $params['headers'];
+ $obj->headers += $this->sanitizeHdrs( $params['headers'] );
}
if ( !empty( $params['async'] ) ) { // deferred
$op = $obj->write_async( $params['content'] );
if ( !strlen( $obj->content_type ) ) { // special case
$obj->content_type = 'unknown/unknown';
}
- // Set the Content-Disposition header if requested
- if ( isset( $params['disposition'] ) ) {
- $obj->headers['Content-Disposition'] = $this->truncDisp( $params['disposition'] );
- }
// Set any other custom headers if requested
if ( isset( $params['headers'] ) ) {
- $obj->headers += $params['headers'];
+ $obj->headers += $this->sanitizeHdrs( $params['headers'] );
}
if ( !empty( $params['async'] ) ) { // deferred
wfSuppressWarnings();
$sContObj = $this->getContainer( $srcCont );
$dContObj = $this->getContainer( $dstCont );
} catch ( NoSuchContainerException $e ) {
- $status->fatal( 'backend-fail-copy', $params['src'], $params['dst'] );
+ if ( empty( $params['ignoreMissingSource'] ) || isset( $sContObj ) ) {
+ $status->fatal( 'backend-fail-copy', $params['src'], $params['dst'] );
+ }
return $status;
} catch ( CloudFilesException $e ) { // some other exception?
$this->handleException( $e, $status, __METHOD__, $params );
try {
$dstObj = new CF_Object( $dContObj, $dstRel, false, false ); // skip HEAD
$hdrs = array(); // source file headers to override with new values
- if ( isset( $params['disposition'] ) ) {
- $hdrs['Content-Disposition'] = $this->truncDisp( $params['disposition'] );
+ // Set any other custom headers if requested
+ if ( isset( $params['headers'] ) ) {
+ $hdrs += $this->sanitizeHdrs( $params['headers'] );
}
if ( !empty( $params['async'] ) ) { // deferred
$op = $sContObj->copy_object_to_async( $srcRel, $dContObj, $dstRel, null, $hdrs );
$sContObj = $this->getContainer( $srcCont );
$dContObj = $this->getContainer( $dstCont );
} catch ( NoSuchContainerException $e ) {
- $status->fatal( 'backend-fail-move', $params['src'], $params['dst'] );
+ if ( empty( $params['ignoreMissingSource'] ) || isset( $sContObj ) ) {
+ $status->fatal( 'backend-fail-move', $params['src'], $params['dst'] );
+ }
return $status;
} catch ( CloudFilesException $e ) { // some other exception?
$this->handleException( $e, $status, __METHOD__, $params );
$srcObj = new CF_Object( $sContObj, $srcRel, false, false ); // skip HEAD
$dstObj = new CF_Object( $dContObj, $dstRel, false, false ); // skip HEAD
$hdrs = array(); // source file headers to override with new values
- if ( isset( $params['disposition'] ) ) {
- $hdrs['Content-Disposition'] = $this->truncDisp( $params['disposition'] );
+ // Set any other custom headers if requested
+ if ( isset( $params['headers'] ) ) {
+ $hdrs += $this->sanitizeHdrs( $params['headers'] );
}
if ( !empty( $params['async'] ) ) { // deferred
$op = $sContObj->move_object_to_async( $srcRel, $dContObj, $dstRel, null, $hdrs );
} catch ( CDNNotEnabledException $e ) {
// CDN not enabled; nothing to see here
} catch ( NoSuchContainerException $e ) {
- $status->fatal( 'backend-fail-delete', $params['src'] );
+ if ( empty( $params['ignoreMissingSource'] ) ) {
+ $status->fatal( 'backend-fail-delete', $params['src'] );
+ }
} catch ( NoSuchObjectException $e ) {
if ( empty( $params['ignoreMissingSource'] ) ) {
$status->fatal( 'backend-fail-delete', $params['src'] );
return $status;
}
- $hdrs = isset( $params['headers'] ) ? $params['headers'] : array();
- // Set the Content-Disposition header if requested
- if ( isset( $params['disposition'] ) ) {
- $hdrs['Content-Disposition'] = $this->truncDisp( $params['disposition'] );
- }
-
try {
$sContObj = $this->getContainer( $srcCont );
// Get the latest version of the current metadata
$srcObj = $sContObj->get_object( $srcRel,
$this->headersFromParams( array( 'latest' => true ) ) );
// Merge in the metadata updates...
- $srcObj->headers = $hdrs + $srcObj->headers;
+ if ( isset( $params['headers'] ) ) {
+ $srcObj->headers = $this->sanitizeHdrs( $params['headers'] ) + $srcObj->headers;
+ }
$srcObj->sync_metadata(); // save to Swift
$this->purgeCDNCache( array( $srcObj ) );
} catch ( CDNNotEnabledException $e ) {
$stat = array(
// Convert dates like "Tue, 03 Jan 2012 22:01:04 GMT" to TS_MW
'mtime' => wfTimestamp( TS_MW, $srcObj->last_modified ),
- 'size' => (int)$srcObj->content_length,
- 'sha1' => $srcObj->getMetadataValue( 'Sha1base36' )
+ 'size' => (int)$srcObj->content_length,
+ 'sha1' => $srcObj->getMetadataValue( 'Sha1base36' )
);
} catch ( NoSuchContainerException $e ) {
} catch ( NoSuchObjectException $e ) {
str_replace( '/swift/v1', '', // S3 API is the rgw default
$sContObj->cfs_http->getStorageUrl() . $spath ),
array(
- 'Signature' => $signature,
- 'Expires' => $expires,
+ 'Signature' => $signature,
+ 'Expires' => $expires,
'AWSAccessKeyId' => $this->rgwS3AccessKey )
);
}
* on a FileBackend params array, e.g. that of getLocalCopy().
* $params is currently only checked for a 'latest' flag.
*
- * @param $params Array
+ * @param array $params
* @return Array
*/
protected function headersFromParams( array $params ) {
* matches the expression and the request is not for a listing.
* Setting this to '*' effectively makes a container public.
* -".rlistings:<regex>" : Grants access if the request is from a referrer host that
- * matches the expression and the request for a listing.
+ * matches the expression and the request is for a listing.
*
* $writeGrps is a list of the possible criteria for a request to have
* access to write to a container. Each item is of the following format:
if ( is_array( $creds ) ) { // cache hit
$this->auth->load_cached_credentials(
$creds['auth_token'], $creds['storage_url'], $creds['cdnm_url'] );
- $this->sessionStarted = time() - ceil( $this->authTTL/2 ); // skew for worst case
+ $this->sessionStarted = time() - ceil( $this->authTTL / 2 ); // skew for worst case
} else { // cache miss
try {
$this->auth->authenticate();
$creds = $this->auth->export_credentials();
- $this->srvCache->add( $cacheKey, $creds, ceil( $this->authTTL/2 ) ); // cache
+ $this->srvCache->add( $cacheKey, $creds, ceil( $this->authTTL / 2 ) ); // cache
$this->sessionStarted = time();
} catch ( CloudFilesException $e ) {
$this->connException = $e; // don't keep re-trying
* @param $e Exception
* @param $status Status|null
* @param $func string
- * @param $params Array
+ * @param array $params
* @return void
*/
protected function handleException( Exception $e, $status, $func, array $params ) {
* @param $backend SwiftFileBackend
* @param string $fullCont Resolved container name
* @param string $dir Resolved directory relative to container
- * @param $params Array
+ * @param array $params
*/
public function __construct( SwiftFileBackend $backend, $fullCont, $dir, array $params ) {
$this->backend = $backend;
* @param string $dir Resolved path relative to container
* @param $after string|null
* @param $limit integer
- * @param $params Array
+ * @param array $params
* @return Traversable|Array|null Returns null on failure
*/
abstract protected function pageFromList( $container, $dir, &$after, $limit, array $params );