/** * @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; }