| <?php | |
| /** | |
| * Copyright 2007 Google Inc. | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| /** | |
| * SPL (Standard PHP Library) function definitions to replace originals. | |
| * | |
| * In order to allow unit testing on an unmodified PHP runtime the function | |
| * implementation definition is contained by this class. The actual function | |
| * name is mapped in Setup.php which simply calls the implementation. | |
| */ | |
| namespace google\appengine\runtime; | |
| use google\appengine\api\modules\ModulesService; | |
| final class SplOverride { | |
| const DEFAULT_CONTENT_TYPE = 'binary/octet-stream'; | |
| /** | |
| * Gets the standard host name for the local machine. | |
| * | |
| * @return bool|string | |
| * a string with the hostname on success, otherwise FALSE is returned. | |
| * | |
| * @see http://php.net/gethostname | |
| */ | |
| public static function gethostname() { | |
| // In order to be consistent with PHP core implementation, wrap any | |
| // exception and return false. | |
| try { | |
| return ModulesService::getHostname(); | |
| } | |
| catch (\Exception $e) { | |
| return false; | |
| } | |
| } | |
| /** | |
| * Moves an uploaded file to a new location. | |
| * | |
| * @param string $filename | |
| * The filename of the uploaded file. | |
| * @param string $destination | |
| * The destination of the moved file. | |
| * @param array $context_options | |
| * An associative array of stream context options. The options will be | |
| * merged with defaults and passed to stream_context_create(). | |
| * | |
| * @see http://php.net/move_uploaded_file | |
| */ | |
| public static function move_uploaded_file($filename, $destination, | |
| array $context_options = null) { | |
| // move_uploaded_file() does not support moving a file between two different | |
| // stream wrappers. Other file handling functions like rename() have the | |
| // same problem, but copy() works since it explicitly sends the contents to | |
| // the new source. As such move_uploaded_file() is replaced by | |
| // is_uploaded_file(), copy(), and unlink() the old file. | |
| // | |
| // This also supports upload proxying during which the file may be remotely | |
| // located and referenced by a stream wrapper. In that case $filename may be | |
| // something like gs://... and $destination public://... which may end up on | |
| // the same remote filesystem, but PHP does not make the distinction. Of | |
| // course, this also means the file can be moved between two different file | |
| // systems. | |
| // | |
| // In the simple case gs:// to gs:// rename() will be called first and | |
| // invoke the more performant operation. | |
| if (is_uploaded_file($filename)) { | |
| // Either use the user provided context options, otherwise use the default | |
| // context with the Content-Type overridden. | |
| if ($context_options !== null) { | |
| $context = stream_context_create($context_options); | |
| } else { | |
| // Default to content type provided in $_FILES array. | |
| $context = stream_context_get_default([ | |
| 'gs' => ['Content-Type' => static::lookupContentType($filename)], | |
| ]); | |
| } | |
| // Attempt rename() which is less expensive if the origin and destination | |
| // use the same stream wrapper, otherwise perform copy() and unlink(). | |
| if (@rename($filename, $destination, $context)) { | |
| static::removeUploadedFile($filename); | |
| return true; | |
| } | |
| if (copy($filename, $destination, $context) && | |
| unlink($filename, $context)) { | |
| static::removeUploadedFile($filename); | |
| return true; | |
| } | |
| } | |
| return false; | |
| } | |
| /** | |
| * Lookup the content type associated with an uploaded file. | |
| * | |
| * @param string $filename | |
| * The filename of the uploaded file. | |
| * @return | |
| * Content type associated with filename, otherwise DEFAULT_CONTENT_TYPE. | |
| */ | |
| private static function lookupContentType($filename) { | |
| foreach ($_FILES as $file) { | |
| if ($file['tmp_name'] == $filename) { | |
| return $file['type'] ?: static::DEFAULT_CONTENT_TYPE; | |
| } | |
| } | |
| return static::DEFAULT_CONTENT_TYPE; | |
| } | |
| /** | |
| * Remove file from uploaded files list. | |
| * | |
| * Provided by the GAE extension, otherwise ignore if not present. | |
| * | |
| * @param string $filename | |
| * The filename of the uploaded file. | |
| */ | |
| private static function removeUploadedFile($filename) { | |
| if (function_exists('__remove_uploaded_file')) { | |
| __remove_uploaded_file($filename); | |
| } | |
| } | |
| } |