예제 #1
0
 /**
  * @see FileBackend::__construct()
  * Additional $config params include:
  *   - wanCache     : WANOBjectCache object to use for persistent caching.
  *   - mimeCallback : Callback that takes (storage path, content, file system path) and
  *                    returns the MIME type of the file or 'unknown/unknown'. The file
  *                    system path parameter should be used if the content one is null.
  *
  * @param array $config
  */
 public function __construct(array $config)
 {
     parent::__construct($config);
     $this->mimeCallback = isset($config['mimeCallback']) ? $config['mimeCallback'] : function ($storagePath, $content, $fsPath) {
         // @todo handle the case of extension-less files using the contents
         return StreamFile::contentTypeFromPath($storagePath) ?: 'unknown/unknown';
     };
     $this->memCache = WANObjectCache::newEmpty();
     // disabled by default
     $this->cheapCache = new ProcessCacheLRU(self::CACHE_CHEAP_SIZE);
     $this->expensiveCache = new ProcessCacheLRU(self::CACHE_EXPENSIVE_SIZE);
 }
예제 #2
0
 /**
  * @see FileBackendStore::doStoreInternal()
  * @return Status
  */
 protected function doStoreInternal(array $params)
 {
     $status = Status::newGood();
     list($dstCont, $dstRel) = $this->resolveStoragePathReal($params['dst']);
     if ($dstRel === null) {
         $status->fatal('backend-fail-invalidpath', $params['dst']);
         return $status;
     }
     // (a) Check the destination container and object
     try {
         $dContObj = $this->getContainer($dstCont);
     } catch (NoSuchContainerException $e) {
         $status->fatal('backend-fail-copy', $params['src'], $params['dst']);
         return $status;
     } catch (CloudFilesException $e) {
         // some other exception?
         $this->handleException($e, $status, __METHOD__, $params);
         return $status;
     }
     // (b) Get a SHA-1 hash of the object
     wfSuppressWarnings();
     $sha1Hash = sha1_file($params['src']);
     wfRestoreWarnings();
     if ($sha1Hash === false) {
         // source doesn't exist?
         $status->fatal('backend-fail-copy', $params['src'], $params['dst']);
         return $status;
     }
     $sha1Hash = wfBaseConvert($sha1Hash, 16, 36, 31);
     // (c) Actually store the object
     try {
         // Create a fresh CF_Object with no fields preloaded.
         // We don't want to preserve headers, metadata, and such.
         $obj = new CF_Object($dContObj, $dstRel, false, false);
         // skip HEAD
         $obj->setMetadataValues(array('Sha1base36' => $sha1Hash));
         // The MD5 here will be checked within Swift against its own MD5.
         $obj->set_etag(md5_file($params['src']));
         // Use the same content type as StreamFile for security
         $obj->content_type = StreamFile::contentTypeFromPath($params['dst']);
         if (!strlen($obj->content_type)) {
             // special case
             $obj->content_type = 'unknown/unknown';
         }
         // Set any other custom headers if requested
         if (isset($params['headers'])) {
             $obj->headers += $this->sanitizeHdrs($params['headers']);
         }
         if (!empty($params['async'])) {
             // deferred
             wfSuppressWarnings();
             $fp = fopen($params['src'], 'rb');
             wfRestoreWarnings();
             if (!$fp) {
                 $status->fatal('backend-fail-copy', $params['src'], $params['dst']);
             } else {
                 $op = $obj->write_async($fp, filesize($params['src']), true);
                 $status->value = new SwiftFileOpHandle($this, $params, 'Store', $op);
                 $status->value->resourcesToClose[] = $fp;
                 $status->value->affectedObjects[] = $obj;
             }
         } else {
             // actually write the object in Swift
             $obj->load_from_filename($params['src'], true);
             // calls $obj->write()
             $this->purgeCDNCache(array($obj));
         }
     } catch (CDNNotEnabledException $e) {
         // CDN not enabled; nothing to see here
     } catch (BadContentTypeException $e) {
         $status->fatal('backend-fail-contenttype', $params['dst']);
     } catch (IOException $e) {
         $status->fatal('backend-fail-copy', $params['src'], $params['dst']);
     } catch (CloudFilesException $e) {
         // some other exception?
         $this->handleException($e, $status, __METHOD__, $params);
     }
     return $status;
 }
예제 #3
0
 /**
  * @see FileBackendStore::doCreateInternal()
  */
 protected function doCreateInternal(array $params)
 {
     $status = Status::newGood();
     list($dstCont, $dstRel) = $this->resolveStoragePathReal($params['dst']);
     if ($dstRel === null) {
         $status->fatal('backend-fail-invalidpath', $params['dst']);
         return $status;
     }
     // (a) Check the destination container and object
     try {
         unset($this->objCache[$params['dst']]);
         $dContObj = $this->getContainer($dstCont);
         if (empty($params['overwrite']) && $this->fileExists(array('src' => $params['dst'], 'latest' => 1))) {
             $status->fatal('backend-fail-alreadyexists', $params['dst']);
             return $status;
         }
     } catch (NoSuchContainerException $e) {
         $status->fatal('backend-fail-create', $params['dst']);
         $this->logException($e, __METHOD__, $params);
         return $status;
     } catch (InvalidResponseException $e) {
         $status->fatal('backend-fail-connect', $this->name);
         $this->logException($e, __METHOD__, $params);
         return $status;
     } catch (Exception $e) {
         // some other exception?
         $status->fatal('backend-fail-internal', $this->name);
         $this->logException($e, __METHOD__, $params);
         return $status;
     }
     // (b) Get a SHA-1 hash of the object
     $sha1Hash = wfBaseConvert(sha1($params['content']), 16, 36, 31);
     // (c) Actually create the object
     try {
         // Create a fresh CF_Object with no fields preloaded.
         // We don't want to preserve headers, metadata, and such.
         $obj = new CF_Object($dContObj, $dstRel, false, false);
         // skip HEAD
         // Note: metadata keys stored as [Upper case char][[Lower case char]...]
         $obj->metadata = array('Sha1base36' => $sha1Hash);
         // Manually set the ETag (https://github.com/rackspace/php-cloudfiles/issues/59).
         // The MD5 here will be checked within Swift against its own MD5.
         $obj->set_etag(md5($params['content']));
         // Use the same content type as StreamFile for security
         $obj->content_type = StreamFile::contentTypeFromPath($params['dst']);
         // Actually write the object in Swift
         $obj->write($params['content']);
     } catch (BadContentTypeException $e) {
         $status->fatal('backend-fail-contenttype', $params['dst']);
         $this->logException($e, __METHOD__, $params);
     } catch (InvalidResponseException $e) {
         $status->fatal('backend-fail-connect', $this->name);
         $this->logException($e, __METHOD__, $params);
     } catch (Exception $e) {
         // some other exception?
         $status->fatal('backend-fail-internal', $this->name);
         $this->logException($e, __METHOD__, $params);
     }
     return $status;
 }
 public function streamFile(array $params)
 {
     // The stream methods use the file extension to determine the
     // Content-Type (as MediaWiki should already validate it on upload).
     // The translated SHA1 path has no extension, so this needs to use
     // the untranslated path extension.
     $type = StreamFile::contentTypeFromPath($params['src']);
     if ($type && $type != 'unknown/unknown') {
         $params['headers'][] = "Content-type: {$type}";
     }
     return $this->translateSrcParams(__FUNCTION__, $params);
 }