| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982 | <?php/** * @file * Drupal stream wrapper interface. * * Provides a Drupal interface and classes to implement PHP stream wrappers for * public, private, and temporary files. * * A stream wrapper is an abstraction of a file system that allows Drupal to * use the same set of methods to access both local files and remote resources. * * Note that PHP 5.2 fopen() only supports URIs of the form "scheme://target" * despite the fact that according to RFC 3986 a URI's scheme component * delimiter is in general just ":", not "://".  Because of this PHP limitation * and for consistency Drupal will only accept URIs of form "scheme://target". * * @see http://www.faqs.org/rfcs/rfc3986.html * @see http://bugs.php.net/bug.php?id=47070 *//** * Stream wrapper bit flags that are the basis for composite types. * * Note that 0x0002 is skipped, because it was the value of a constant that has * since been removed. *//** * Stream wrapper bit flag -- a filter that matches all wrappers. */define('STREAM_WRAPPERS_ALL', 0x0000);/** * Stream wrapper bit flag -- refers to a local file system location. */define('STREAM_WRAPPERS_LOCAL', 0x0001);/** * Stream wrapper bit flag -- wrapper is readable (almost always true). */define('STREAM_WRAPPERS_READ', 0x0004);/** * Stream wrapper bit flag -- wrapper is writeable. */define('STREAM_WRAPPERS_WRITE', 0x0008);/** * Stream wrapper bit flag -- exposed in the UI and potentially web accessible. */define('STREAM_WRAPPERS_VISIBLE', 0x0010);/** * Composite stream wrapper bit flags that are usually used as the types. *//** * Stream wrapper type flag -- not visible in the UI or accessible via web, * but readable and writable. E.g. the temporary directory for uploads. */define('STREAM_WRAPPERS_HIDDEN', STREAM_WRAPPERS_READ | STREAM_WRAPPERS_WRITE);/** * Stream wrapper type flag -- hidden, readable and writeable using local files. */define('STREAM_WRAPPERS_LOCAL_HIDDEN', STREAM_WRAPPERS_LOCAL | STREAM_WRAPPERS_HIDDEN);/** * Stream wrapper type flag -- visible, readable and writeable. */define('STREAM_WRAPPERS_WRITE_VISIBLE', STREAM_WRAPPERS_READ | STREAM_WRAPPERS_WRITE | STREAM_WRAPPERS_VISIBLE);/** * Stream wrapper type flag -- visible and read-only. */define('STREAM_WRAPPERS_READ_VISIBLE', STREAM_WRAPPERS_READ | STREAM_WRAPPERS_VISIBLE);/** * Stream wrapper type flag -- the default when 'type' is omitted from * hook_stream_wrappers(). This does not include STREAM_WRAPPERS_LOCAL, * because PHP grants a greater trust level to local files (for example, they * can be used in an "include" statement, regardless of the "allow_url_include" * setting), so stream wrappers need to explicitly opt-in to this. */define('STREAM_WRAPPERS_NORMAL', STREAM_WRAPPERS_WRITE_VISIBLE);/** * Stream wrapper type flag -- visible, readable and writeable using local files. */define('STREAM_WRAPPERS_LOCAL_NORMAL', STREAM_WRAPPERS_LOCAL | STREAM_WRAPPERS_NORMAL);/** * Generic PHP stream wrapper interface. * * @see http://www.php.net/manual/class.streamwrapper.php */interface StreamWrapperInterface {  public function stream_open($uri, $mode, $options, &$opened_url);  public function stream_close();  public function stream_lock($operation);  public function stream_read($count);  public function stream_write($data);  public function stream_eof();  public function stream_seek($offset, $whence);  public function stream_flush();  public function stream_tell();  public function stream_stat();  public function unlink($uri);  public function rename($from_uri, $to_uri);  public function mkdir($uri, $mode, $options);  public function rmdir($uri, $options);  public function url_stat($uri, $flags);  public function dir_opendir($uri, $options);  public function dir_readdir();  public function dir_rewinddir();  public function dir_closedir();}/** * Drupal stream wrapper extension. * * Extend the StreamWrapperInterface with methods expected by Drupal stream * wrapper classes. */interface DrupalStreamWrapperInterface extends StreamWrapperInterface {  /**   * Set the absolute stream resource URI.   *   * This allows you to set the URI. Generally is only called by the factory   * method.   *   * @param $uri   *   A string containing the URI that should be used for this instance.   */  public function setUri($uri);  /**   * Returns the stream resource URI.   *   * @return   *   Returns the current URI of the instance.   */  public function getUri();  /**   * Returns a web accessible URL for the resource.   *   * This function should return a URL that can be embedded in a web page   * and accessed from a browser. For example, the external URL of   * "youtube://xIpLd0WQKCY" might be   * "http://www.youtube.com/watch?v=xIpLd0WQKCY".   *   * @return   *   Returns a string containing a web accessible URL for the resource.   */  public function getExternalUrl();  /**   * Returns the MIME type of the resource.   *   * @param $uri   *   The URI, path, or filename.   * @param $mapping   *   An optional map of extensions to their mimetypes, in the form:   *    - 'mimetypes': a list of mimetypes, keyed by an identifier,   *    - 'extensions': the mapping itself, an associative array in which   *      the key is the extension and the value is the mimetype identifier.   *   * @return   *   Returns a string containing the MIME type of the resource.   */  public static function getMimeType($uri, $mapping = NULL);  /**   * Changes permissions of the resource.   *   * PHP lacks this functionality and it is not part of the official stream   * wrapper interface. This is a custom implementation for Drupal.   *   * @param $mode   *   Integer value for the permissions. Consult PHP chmod() documentation   *   for more information.   *   * @return   *   Returns TRUE on success or FALSE on failure.   */  public function chmod($mode);  /**   * Returns canonical, absolute path of the resource.   *   * Implementation placeholder. PHP's realpath() does not support stream   * wrappers. We provide this as a default so that individual wrappers may   * implement their own solutions.   *   * @return   *   Returns a string with absolute pathname on success (implemented   *   by core wrappers), or FALSE on failure or if the registered   *   wrapper does not provide an implementation.   */  public function realpath();  /**   * Gets the name of the directory from a given path.   *   * This method is usually accessed through drupal_dirname(), which wraps   * around the normal PHP dirname() function, which does not support stream   * wrappers.   *   * @param $uri   *   An optional URI.   *   * @return   *   A string containing the directory name, or FALSE if not applicable.   *   * @see drupal_dirname()   */  public function dirname($uri = NULL);}/** * Drupal stream wrapper base class for local files. * * This class provides a complete stream wrapper implementation. URIs such as * "public://example.txt" are expanded to a normal filesystem path such as * "sites/default/files/example.txt" and then PHP filesystem functions are * invoked. * * DrupalLocalStreamWrapper implementations need to implement at least the * getDirectoryPath() and getExternalUrl() methods. */abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface {  /**   * Stream context resource.   *   * @var Resource   */  public $context;  /**   * A generic resource handle.   *   * @var Resource   */  public $handle = NULL;  /**   * Instance URI (stream).   *   * A stream is referenced as "scheme://target".   *   * @var String   */  protected $uri;  /**   * Gets the path that the wrapper is responsible for.   * @TODO: Review this method name in D8 per http://drupal.org/node/701358   *   * @return   *   String specifying the path.   */  abstract function getDirectoryPath();  /**   * Base implementation of setUri().   */  function setUri($uri) {    $this->uri = $uri;  }  /**   * Base implementation of getUri().   */  function getUri() {    return $this->uri;  }  /**   * Returns the local writable target of the resource within the stream.   *   * This function should be used in place of calls to realpath() or similar   * functions when attempting to determine the location of a file. While   * functions like realpath() may return the location of a read-only file, this   * method may return a URI or path suitable for writing that is completely   * separate from the URI used for reading.   *   * @param $uri   *   Optional URI.   *   * @return   *   Returns a string representing a location suitable for writing of a file,   *   or FALSE if unable to write to the file such as with read-only streams.   */  protected function getTarget($uri = NULL) {    if (!isset($uri)) {      $uri = $this->uri;    }    list($scheme, $target) = explode('://', $uri, 2);    // Remove erroneous leading or trailing, forward-slashes and backslashes.    return trim($target, '\/');  }  /**   * Base implementation of getMimeType().   */  static function getMimeType($uri, $mapping = NULL) {    if (!isset($mapping)) {      // The default file map, defined in file.mimetypes.inc is quite big.      // We only load it when necessary.      include_once DRUPAL_ROOT . '/includes/file.mimetypes.inc';      $mapping = file_mimetype_mapping();    }    $extension = '';    $file_parts = explode('.', drupal_basename($uri));    // Remove the first part: a full filename should not match an extension.    array_shift($file_parts);    // Iterate over the file parts, trying to find a match.    // For my.awesome.image.jpeg, we try:    //   - jpeg    //   - image.jpeg, and    //   - awesome.image.jpeg    while ($additional_part = array_pop($file_parts)) {      $extension = strtolower($additional_part . ($extension ? '.' . $extension : ''));      if (isset($mapping['extensions'][$extension])) {        return $mapping['mimetypes'][$mapping['extensions'][$extension]];      }    }    return 'application/octet-stream';  }  /**   * Base implementation of chmod().   */  function chmod($mode) {    $output = @chmod($this->getLocalPath(), $mode);    // We are modifying the underlying file here, so we have to clear the stat    // cache so that PHP understands that URI has changed too.    clearstatcache();    return $output;  }  /**   * Base implementation of realpath().   */  function realpath() {    return $this->getLocalPath();  }  /**   * Returns the canonical absolute path of the URI, if possible.   *   * @param string $uri   *   (optional) The stream wrapper URI to be converted to a canonical   *   absolute path. This may point to a directory or another type of file.   *   * @return string|false   *   If $uri is not set, returns the canonical absolute path of the URI   *   previously set by the DrupalStreamWrapperInterface::setUri() function.   *   If $uri is set and valid for this class, returns its canonical absolute   *   path, as determined by the realpath() function. If $uri is set but not   *   valid, returns FALSE.   */  protected function getLocalPath($uri = NULL) {    if (!isset($uri)) {      $uri = $this->uri;    }    $path = $this->getDirectoryPath() . '/' . $this->getTarget($uri);    $realpath = realpath($path);    if (!$realpath) {      // This file does not yet exist.      $realpath = realpath(dirname($path)) . '/' . drupal_basename($path);    }    $directory = realpath($this->getDirectoryPath());    if (!$realpath || !$directory || strpos($realpath, $directory) !== 0) {      return FALSE;    }    return $realpath;  }  /**   * Support for fopen(), file_get_contents(), file_put_contents() etc.   *   * @param $uri   *   A string containing the URI to the file to open.   * @param $mode   *   The file mode ("r", "wb" etc.).   * @param $options   *   A bit mask of STREAM_USE_PATH and STREAM_REPORT_ERRORS.   * @param $opened_path   *   A string containing the path actually opened.   *   * @return   *   Returns TRUE if file was opened successfully.   *   * @see http://php.net/manual/streamwrapper.stream-open.php   */  public function stream_open($uri, $mode, $options, &$opened_path) {    $this->uri = $uri;    $path = $this->getLocalPath();    $this->handle = ($options & STREAM_REPORT_ERRORS) ? fopen($path, $mode) : @fopen($path, $mode);    if ((bool) $this->handle && $options & STREAM_USE_PATH) {      $opened_path = $path;    }    return (bool) $this->handle;  }  /**   * Support for flock().   *   * @param $operation   *   One of the following:   *   - LOCK_SH to acquire a shared lock (reader).   *   - LOCK_EX to acquire an exclusive lock (writer).   *   - LOCK_UN to release a lock (shared or exclusive).   *   - LOCK_NB if you don't want flock() to block while locking (not   *     supported on Windows).   *   * @return   *   Always returns TRUE at the present time.   *   * @see http://php.net/manual/streamwrapper.stream-lock.php   */  public function stream_lock($operation) {    if (in_array($operation, array(LOCK_SH, LOCK_EX, LOCK_UN, LOCK_NB))) {      return flock($this->handle, $operation);    }    return TRUE;  }  /**   * Support for fread(), file_get_contents() etc.   *   * @param $count   *   Maximum number of bytes to be read.   *   * @return   *   The string that was read, or FALSE in case of an error.   *   * @see http://php.net/manual/streamwrapper.stream-read.php   */  public function stream_read($count) {    return fread($this->handle, $count);  }  /**   * Support for fwrite(), file_put_contents() etc.   *   * @param $data   *   The string to be written.   *   * @return   *   The number of bytes written (integer).   *   * @see http://php.net/manual/streamwrapper.stream-write.php   */  public function stream_write($data) {    return fwrite($this->handle, $data);  }  /**   * Support for feof().   *   * @return   *   TRUE if end-of-file has been reached.   *   * @see http://php.net/manual/streamwrapper.stream-eof.php   */  public function stream_eof() {    return feof($this->handle);  }  /**   * Support for fseek().   *   * @param $offset   *   The byte offset to got to.   * @param $whence   *   SEEK_SET, SEEK_CUR, or SEEK_END.   *   * @return   *   TRUE on success.   *   * @see http://php.net/manual/streamwrapper.stream-seek.php   */  public function stream_seek($offset, $whence) {    // fseek returns 0 on success and -1 on a failure.    // stream_seek   1 on success and  0 on a failure.    return !fseek($this->handle, $offset, $whence);  }  /**   * Support for fflush().   *   * @return   *   TRUE if data was successfully stored (or there was no data to store).   *   * @see http://php.net/manual/streamwrapper.stream-flush.php   */  public function stream_flush() {    return fflush($this->handle);  }  /**   * Support for ftell().   *   * @return   *   The current offset in bytes from the beginning of file.   *   * @see http://php.net/manual/streamwrapper.stream-tell.php   */  public function stream_tell() {    return ftell($this->handle);  }  /**   * Support for fstat().   *   * @return   *   An array with file status, or FALSE in case of an error - see fstat()   *   for a description of this array.   *   * @see http://php.net/manual/streamwrapper.stream-stat.php   */  public function stream_stat() {    return fstat($this->handle);  }  /**   * Support for fclose().   *   * @return   *   TRUE if stream was successfully closed.   *   * @see http://php.net/manual/streamwrapper.stream-close.php   */  public function stream_close() {    return fclose($this->handle);  }  /**   * Sets metadata on the stream.   *   * WARNING: Do not call this method directly! It will be called internally by   * PHP itself when one of the following functions is called on a stream URL:   *   * @param string $uri   *   A string containing the URI to the file to set metadata on.   * @param int $option   *   One of:   *   - STREAM_META_TOUCH: The method was called in response to touch().   *   - STREAM_META_OWNER_NAME: The method was called in response to chown()   *     with string parameter.   *   - STREAM_META_OWNER: The method was called in response to chown().   *   - STREAM_META_GROUP_NAME: The method was called in response to chgrp().   *   - STREAM_META_GROUP: The method was called in response to chgrp().   *   - STREAM_META_ACCESS: The method was called in response to chmod().   * @param mixed $value   *   If option is:   *   - STREAM_META_TOUCH: Array consisting of two arguments of the touch()   *     function.   *   - STREAM_META_OWNER_NAME or STREAM_META_GROUP_NAME: The name of the owner   *     user/group as string.   *   - STREAM_META_OWNER or STREAM_META_GROUP: The value of the owner   *     user/group as integer.   *   - STREAM_META_ACCESS: The argument of the chmod() as integer.   *   * @return bool   *   Returns TRUE on success or FALSE on failure. If $option is not   *   implemented, FALSE should be returned.   *   * @see touch()   * @see chmod()   * @see chown()   * @see chgrp()   * @link http://php.net/manual/streamwrapper.stream-metadata.php   */  public function stream_metadata($uri, $option, $value) {    $target = $this->getLocalPath($uri);    $return = FALSE;    switch ($option) {      case STREAM_META_TOUCH:        if (!empty($value)) {          $return = touch($target, $value[0], $value[1]);        }        else {          $return = touch($target);        }        break;      case STREAM_META_OWNER_NAME:      case STREAM_META_OWNER:        $return = chown($target, $value);        break;      case STREAM_META_GROUP_NAME:      case STREAM_META_GROUP:        $return = chgrp($target, $value);        break;      case STREAM_META_ACCESS:        $return = chmod($target, $value);        break;    }    if ($return) {      // For convenience clear the file status cache of the underlying file,      // since metadata operations are often followed by file status checks.      clearstatcache(TRUE, $target);    }    return $return;  }  /**   * Truncate stream.   *   * Will respond to truncation; e.g., through ftruncate().   *   * @param int $new_size   *   The new size.   *   * @return bool   *   TRUE on success, FALSE otherwise.   */  public function stream_truncate($new_size) {    return ftruncate($this->handle, $new_size);  }  /**   * Retrieve the underlying stream resource.   *   * This method is called in response to stream_select().   *   * @param int $cast_as   *   Can be STREAM_CAST_FOR_SELECT when stream_select() is calling   *   stream_cast() or STREAM_CAST_AS_STREAM when stream_cast() is called for   *   other uses.   *   * @return resource|false   *   The underlying stream resource or FALSE if stream_select() is not   *   supported.   *   * @see stream_select()   * @link http://php.net/manual/streamwrapper.stream-cast.php   */  public function stream_cast($cast_as) {    return $this->handle ? $this->handle : FALSE;  }  /**   * Change stream options.   *   * This method is called to set options on the stream.   *   * Since Windows systems do not allow it and it is not needed for most use   * cases anyway, this method is not supported on local files and will trigger   * an error and return false. If needed, custom subclasses can provide   * OS-specific implementations for advanced use cases.   *   * @param int $option   *   One of:   *   - STREAM_OPTION_BLOCKING: The method was called in response to   *     stream_set_blocking().   *   - STREAM_OPTION_READ_TIMEOUT: The method was called in response to   *     stream_set_timeout().   *   - STREAM_OPTION_WRITE_BUFFER: The method was called in response to   *     stream_set_write_buffer().   * @param int $arg1   *   If option is:   *   - STREAM_OPTION_BLOCKING: The requested blocking mode:   *     - 1 means blocking.   *     - 0 means not blocking.   *   - STREAM_OPTION_READ_TIMEOUT: The timeout in seconds.   *   - STREAM_OPTION_WRITE_BUFFER: The buffer mode, STREAM_BUFFER_NONE or   *     STREAM_BUFFER_FULL.   * @param int $arg2   *   If option is:   *   - STREAM_OPTION_BLOCKING: This option is not set.   *   - STREAM_OPTION_READ_TIMEOUT: The timeout in microseconds.   *   - STREAM_OPTION_WRITE_BUFFER: The requested buffer size.   *   * @return bool   *   TRUE on success, FALSE otherwise. If $option is not implemented, FALSE   *   should be returned.   */  public function stream_set_option($option, $arg1, $arg2) {    trigger_error('stream_set_option() not supported for local file based stream wrappers', E_USER_WARNING);    return FALSE;  }  /**   * Support for unlink().   *   * @param $uri   *   A string containing the URI to the resource to delete.   *   * @return   *   TRUE if resource was successfully deleted.   *   * @see http://php.net/manual/streamwrapper.unlink.php   */  public function unlink($uri) {    $this->uri = $uri;    return drupal_unlink($this->getLocalPath());  }  /**   * Support for rename().   *   * @param $from_uri,   *   The URI to the file to rename.   * @param $to_uri   *   The new URI for file.   *   * @return   *   TRUE if file was successfully renamed.   *   * @see http://php.net/manual/streamwrapper.rename.php   */  public function rename($from_uri, $to_uri) {    return rename($this->getLocalPath($from_uri), $this->getLocalPath($to_uri));  }  /**   * Gets the name of the directory from a given path.   *   * This method is usually accessed through drupal_dirname(), which wraps   * around the PHP dirname() function because it does not support stream   * wrappers.   *   * @param $uri   *   A URI or path.   *   * @return   *   A string containing the directory name.   *   * @see drupal_dirname()   */  public function dirname($uri = NULL) {    list($scheme, $target) = explode('://', $uri, 2);    $target  = $this->getTarget($uri);    $dirname = dirname($target);    if ($dirname == '.') {      $dirname = '';    }    return $scheme . '://' . $dirname;  }  /**   * Support for mkdir().   *   * @param $uri   *   A string containing the URI to the directory to create.   * @param $mode   *   Permission flags - see mkdir().   * @param $options   *   A bit mask of STREAM_REPORT_ERRORS and STREAM_MKDIR_RECURSIVE.   *   * @return   *   TRUE if directory was successfully created.   *   * @see http://php.net/manual/streamwrapper.mkdir.php   */  public function mkdir($uri, $mode, $options) {    $this->uri = $uri;    $recursive = (bool) ($options & STREAM_MKDIR_RECURSIVE);    if ($recursive) {      // $this->getLocalPath() fails if $uri has multiple levels of directories      // that do not yet exist.      $localpath = $this->getDirectoryPath() . '/' . $this->getTarget($uri);    }    else {      $localpath = $this->getLocalPath($uri);    }    if ($options & STREAM_REPORT_ERRORS) {      return mkdir($localpath, $mode, $recursive);    }    else {      return @mkdir($localpath, $mode, $recursive);    }  }  /**   * Support for rmdir().   *   * @param $uri   *   A string containing the URI to the directory to delete.   * @param $options   *   A bit mask of STREAM_REPORT_ERRORS.   *   * @return   *   TRUE if directory was successfully removed.   *   * @see http://php.net/manual/streamwrapper.rmdir.php   */  public function rmdir($uri, $options) {    $this->uri = $uri;    if ($options & STREAM_REPORT_ERRORS) {      return drupal_rmdir($this->getLocalPath());    }    else {      return @drupal_rmdir($this->getLocalPath());    }  }  /**   * Support for stat().   *   * @param $uri   *   A string containing the URI to get information about.   * @param $flags   *   A bit mask of STREAM_URL_STAT_LINK and STREAM_URL_STAT_QUIET.   *   * @return   *   An array with file status, or FALSE in case of an error - see fstat()   *   for a description of this array.   *   * @see http://php.net/manual/streamwrapper.url-stat.php   */  public function url_stat($uri, $flags) {    $this->uri = $uri;    $path = $this->getLocalPath();    // Suppress warnings if requested or if the file or directory does not    // exist. This is consistent with PHP's plain filesystem stream wrapper.    if ($flags & STREAM_URL_STAT_QUIET || !file_exists($path)) {      return @stat($path);    }    else {      return stat($path);    }  }  /**   * Support for opendir().   *   * @param $uri   *   A string containing the URI to the directory to open.   * @param $options   *   Unknown (parameter is not documented in PHP Manual).   *   * @return   *   TRUE on success.   *   * @see http://php.net/manual/streamwrapper.dir-opendir.php   */  public function dir_opendir($uri, $options) {    $this->uri = $uri;    $this->handle = opendir($this->getLocalPath());    return (bool) $this->handle;  }  /**   * Support for readdir().   *   * @return   *   The next filename, or FALSE if there are no more files in the directory.   *   * @see http://php.net/manual/streamwrapper.dir-readdir.php   */  public function dir_readdir() {    return readdir($this->handle);  }  /**   * Support for rewinddir().   *   * @return   *   TRUE on success.   *   * @see http://php.net/manual/streamwrapper.dir-rewinddir.php   */  public function dir_rewinddir() {    rewinddir($this->handle);    // We do not really have a way to signal a failure as rewinddir() does not    // have a return value and there is no way to read a directory handler    // without advancing to the next file.    return TRUE;  }  /**   * Support for closedir().   *   * @return   *   TRUE on success.   *   * @see http://php.net/manual/streamwrapper.dir-closedir.php   */  public function dir_closedir() {    closedir($this->handle);    // We do not really have a way to signal a failure as closedir() does not    // have a return value.    return TRUE;  }}/** * Drupal public (public://) stream wrapper class. * * Provides support for storing publicly accessible files with the Drupal file * interface. */class DrupalPublicStreamWrapper extends DrupalLocalStreamWrapper {  /**   * Implements abstract public function getDirectoryPath()   */  public function getDirectoryPath() {    return variable_get('file_public_path', conf_path() . '/files');  }  /**   * Overrides getExternalUrl().   *   * Return the HTML URI of a public file.   */  function getExternalUrl() {    $path = str_replace('\\', '/', $this->getTarget());    return $GLOBALS['base_url'] . '/' . self::getDirectoryPath() . '/' . drupal_encode_path($path);  }}/** * Drupal private (private://) stream wrapper class. * * Provides support for storing privately accessible files with the Drupal file * interface. */class DrupalPrivateStreamWrapper extends DrupalLocalStreamWrapper {  /**   * Implements abstract public function getDirectoryPath()   */  public function getDirectoryPath() {    return variable_get('file_private_path', '');  }  /**   * Overrides getExternalUrl().   *   * Return the HTML URI of a private file.   */  function getExternalUrl() {    $path = str_replace('\\', '/', $this->getTarget());    return url('system/files/' . $path, array('absolute' => TRUE));  }}/** * Drupal temporary (temporary://) stream wrapper class. * * Provides support for storing temporarily accessible files with the Drupal * file interface. * * Extends DrupalPublicStreamWrapper. */class DrupalTemporaryStreamWrapper extends DrupalLocalStreamWrapper {  /**   * Implements abstract public function getDirectoryPath()   */  public function getDirectoryPath() {    return variable_get('file_temporary_path', file_directory_temp());  }  /**   * Overrides getExternalUrl().   */  public function getExternalUrl() {    $path = str_replace('\\', '/', $this->getTarget());    return url('system/temporary/' . $path, array('absolute' => TRUE));  }}
 |