From 0a00a710f7738e82ea3f6fb3c2eec024cae33617 Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Sat, 18 Oct 2014 12:01:10 +0000 Subject: [PATCH] * Filemanager: fix since PHP 5.5.18 not longer working non-ascii chars in filenames, eg. German umlauts or accents --- phpgwapi/inc/class.egw_vfs.inc.php | 29 ++--- .../class.filesystem_stream_wrapper.inc.php | 22 ++-- .../inc/class.global_stream_wrapper.inc.php | 2 +- .../inc/class.links_stream_wrapper.inc.php | 8 +- .../inc/class.sqlfs_stream_wrapper.inc.php | 36 +++--- phpgwapi/inc/class.vfs_stream_wrapper.inc.php | 110 +++++++++++++----- 6 files changed, 131 insertions(+), 76 deletions(-) diff --git a/phpgwapi/inc/class.egw_vfs.inc.php b/phpgwapi/inc/class.egw_vfs.inc.php index d52b05a1e7..a2793fde20 100644 --- a/phpgwapi/inc/class.egw_vfs.inc.php +++ b/phpgwapi/inc/class.egw_vfs.inc.php @@ -7,7 +7,7 @@ * @package api * @subpackage vfs * @author Ralf Becker - * @copyright (c) 2008-10 by Ralf Becker + * @copyright (c) 2008-14 by Ralf Becker * @version $Id$ */ @@ -56,6 +56,9 @@ * * The static egw_vfs::copy() method does exactly that, but you have to do it eg. on your own, if * you want to copy eg. an uploaded file into the vfs. + * + * egw_vfs::parse_url($url, $component=-1), egw_vfs::dirname($url) and egw_vfs::basename($url) work + * on urls containing utf-8 characters, which get NOT urlencoded in our VFS! */ class egw_vfs extends vfs_stream_wrapper { @@ -331,7 +334,7 @@ class egw_vfs extends vfs_stream_wrapper if (self::LOG_LEVEL > 0) error_log(__METHOD__.'('.array2string($url).','.array2string($path).') already mounted.'); return true; // already mounted } - self::load_wrapper(parse_url($url,PHP_URL_SCHEME)); + self::load_wrapper(self::parse_url($url,PHP_URL_SCHEME)); if ($check_url && (!file_exists($url) || opendir($url) === false)) { @@ -517,7 +520,7 @@ class egw_vfs extends vfs_stream_wrapper if ($opts['maxdepth']) $opts['depth']++;; unset($opts['order']); unset($opts['limit']); - foreach(self::find($options['url']?$file:parse_url($file,PHP_URL_PATH),$opts,true) as $p => $s) + foreach(self::find($options['url']?$file:self::parse_url($file,PHP_URL_PATH),$opts,true) as $p => $s) { unset($result[$p]); $result[$p] = $s; @@ -641,7 +644,7 @@ class egw_vfs extends vfs_stream_wrapper return; // wrong type } $stat = array_slice($stat,13); // remove numerical indices 0-12 - $stat['path'] = parse_url($path,PHP_URL_PATH); + $stat['path'] = self::parse_url($path,PHP_URL_PATH); $stat['name'] = $options['remove'] > 0 ? implode('/',array_slice(explode('/',$stat['path']),$options['remove'])) : self::basename($path); if ($options['mime'] || $options['need_mime']) @@ -683,7 +686,7 @@ class egw_vfs extends vfs_stream_wrapper // do we return url or just vfs pathes if (!$options['url']) { - $path = parse_url($path,PHP_URL_PATH); + $path = self::parse_url($path,PHP_URL_PATH); } $result[$path] = $stat; } @@ -717,7 +720,7 @@ class egw_vfs extends vfs_stream_wrapper // some precaution to never allow to (recursivly) remove /, /apps or /home foreach((array)$urls as $url) { - if (preg_match('/^\/?(home|apps|)\/*$/',parse_url($url,PHP_URL_PATH))) + if (preg_match('/^\/?(home|apps|)\/*$/',self::parse_url($url,PHP_URL_PATH))) { throw new egw_exception_assertion_failed(__METHOD__.'('.array2string($urls).") Cautiously rejecting to remove folder '$url'!"); } @@ -832,7 +835,7 @@ class egw_vfs extends vfs_stream_wrapper } // check if we use an EGroupwre stream wrapper, or a stock php one // if it's not an EGroupware one, we can NOT use uid, gid and mode! - if (($scheme = parse_url($stat['url'],PHP_URL_SCHEME)) && !(class_exists(self::scheme2class($scheme)))) + if (($scheme = self::parse_url($stat['url'],PHP_URL_SCHEME)) && !(class_exists(self::scheme2class($scheme)))) { switch($check) { @@ -1214,7 +1217,7 @@ class egw_vfs extends vfs_stream_wrapper { list($url,$query) = explode('?',$url,2); // strip the query first, as it can contain slashes - if ($url == '/' || $url[0] != '/' && parse_url($url,PHP_URL_PATH) == '/') + if ($url == '/' || $url[0] != '/' && self::parse_url($url,PHP_URL_PATH) == '/') { //error_log(__METHOD__."($url) returning FALSE: already in root!"); return false; @@ -1313,7 +1316,7 @@ class egw_vfs extends vfs_stream_wrapper } if ($path[0] != '/') { - $path = parse_url($path,PHP_URL_PATH); + $path = self::parse_url($path,PHP_URL_PATH); } // we do NOT need to encode % itself, as our path are already url encoded, with the exception of ' ' and '+' // we urlencode double quotes '"', as that fixes many problems in html markup @@ -1331,7 +1334,7 @@ class egw_vfs extends vfs_stream_wrapper public static function download_zip(Array $files, $name = false) { error_log(__METHOD__ . ': '.implode(',',$files)); - + // Create zip file $zip_file = tempnam($GLOBALS['egw_info']['server']['temp_dir'], 'zip'); @@ -1403,7 +1406,7 @@ class egw_vfs extends vfs_stream_wrapper { $base_dir .='/'; } - + // Go into directories, find them all $files = self::find($files); $links = array(); @@ -1477,7 +1480,7 @@ class egw_vfs extends vfs_stream_wrapper error_log('close() result: '.array2string($result)); return 'Error creating zip file'; } - + error_log("Total files: " . $total_files . " Peak memory to zip: " . self::hsize(memory_get_peak_usage(true))); // Stop any buffering @@ -1804,7 +1807,7 @@ class egw_vfs extends vfs_stream_wrapper { if (substr($file, 0, 6) == '/apps/') { - $file = parse_url(egw_vfs::resolve_url_symlinks($path), PHP_URL_PATH); + $file = self::parse_url(egw_vfs::resolve_url_symlinks($path), PHP_URL_PATH); } //Assemble the thumbnail parameters diff --git a/phpgwapi/inc/class.filesystem_stream_wrapper.inc.php b/phpgwapi/inc/class.filesystem_stream_wrapper.inc.php index e76360a82b..dc45a62758 100644 --- a/phpgwapi/inc/class.filesystem_stream_wrapper.inc.php +++ b/phpgwapi/inc/class.filesystem_stream_wrapper.inc.php @@ -7,7 +7,7 @@ * @package api * @subpackage vfs * @author Ralf Becker - * @copyright (c) 2008-10 by Ralf Becker + * @copyright (c) 2008-14 by Ralf Becker * @version $Id$ */ @@ -160,7 +160,7 @@ class filesystem_stream_wrapper implements iface_stream_wrapper } // open the "real" file - if (!($this->opened_stream = fopen($path=egw_vfs::decodePath(parse_url($url,PHP_URL_PATH)),$mode,$options))) + if (!($this->opened_stream = fopen($path=egw_vfs::decodePath(egw_vfs::parse_url($url,PHP_URL_PATH)),$mode,$options))) { if (self::LOG_LEVEL) error_log(__METHOD__."($url,$mode,$options) fopen('$path','$mode',$options) returned false!"); return false; @@ -302,7 +302,7 @@ class filesystem_stream_wrapper implements iface_stream_wrapper */ static function unlink ( $url ) { - $path = egw_vfs::decodePath(parse_url($url,PHP_URL_PATH)); + $path = egw_vfs::decodePath(egw_vfs::parse_url($url,PHP_URL_PATH)); // check access rights (file need to exist and directory need to be writable if (!file_exists($path) || is_dir($path) || !egw_vfs::check_access(egw_vfs::dirname($url),egw_vfs::WRITABLE)) @@ -327,8 +327,8 @@ class filesystem_stream_wrapper implements iface_stream_wrapper */ static function rename ( $url_from, $url_to ) { - $from = parse_url($url_from); - $to = parse_url($url_to); + $from = egw_vfs::parse_url($url_from); + $to = egw_vfs::parse_url($url_to); // check access rights if (!($from_stat = self::url_stat($url_from,0)) || !egw_vfs::check_access(egw_vfs::dirname($url_from),egw_vfs::WRITABLE)) @@ -378,7 +378,7 @@ class filesystem_stream_wrapper implements iface_stream_wrapper */ static function mkdir ( $url, $mode, $options ) { - $path = egw_vfs::decodePath(parse_url($url,PHP_URL_PATH)); + $path = egw_vfs::decodePath(egw_vfs::parse_url($url,PHP_URL_PATH)); $recursive = (bool)($options & STREAM_MKDIR_RECURSIVE); // find the real parent (might be more then one level if $recursive!) @@ -410,7 +410,7 @@ class filesystem_stream_wrapper implements iface_stream_wrapper */ static function rmdir ( $url, $options ) { - $path = egw_vfs::decodePath(parse_url($url,PHP_URL_PATH)); + $path = egw_vfs::decodePath(egw_vfs::parse_url($url,PHP_URL_PATH)); $parent = dirname($path); // check access rights (in real filesystem AND by mount perms) @@ -432,7 +432,7 @@ class filesystem_stream_wrapper implements iface_stream_wrapper */ static function touch($url,$time=null,$atime=null) { - $path = egw_vfs::decodePath(parse_url($url,PHP_URL_PATH)); + $path = egw_vfs::decodePath(egw_vfs::parse_url($url,PHP_URL_PATH)); $parent = dirname($path); // check access rights (in real filesystem AND by mount perms) @@ -499,7 +499,7 @@ class filesystem_stream_wrapper implements iface_stream_wrapper $this->opened_dir = null; - $path = egw_vfs::decodePath(parse_url($this->opened_dir_url = $url,PHP_URL_PATH)); + $path = egw_vfs::decodePath(egw_vfs::parse_url($this->opened_dir_url = $url,PHP_URL_PATH)); // ToDo: check access rights @@ -539,7 +539,7 @@ class filesystem_stream_wrapper implements iface_stream_wrapper */ static function url_stat ( $url, $flags ) { - $parts = parse_url($url); + $parts = egw_vfs::parse_url($url); $path = egw_vfs::decodePath($parts['path']); $stat = @stat($path); // suppressed the stat failed warnings @@ -712,7 +712,7 @@ class filesystem_stream_wrapper implements iface_stream_wrapper */ static function deny_script($url) { - $parts = parse_url($url); + $parts = egw_vfs::parse_url($url); parse_str($parts['query'],$get); $deny = !$get['exec'] && preg_match(self::SCRIPT_EXTENSIONS_PREG,$parts['path']); diff --git a/phpgwapi/inc/class.global_stream_wrapper.inc.php b/phpgwapi/inc/class.global_stream_wrapper.inc.php index 1c362f1660..c134baf387 100644 --- a/phpgwapi/inc/class.global_stream_wrapper.inc.php +++ b/phpgwapi/inc/class.global_stream_wrapper.inc.php @@ -29,7 +29,7 @@ class global_stream_wrapper public function stream_open($path, $mode, $options, &$opened_path) { - $this->stream = &$GLOBALS[$this->name=parse_url($path,PHP_URL_HOST)]; + $this->stream = &$GLOBALS[$this->name=egw_vfs::parse_url($path,PHP_URL_HOST)]; $this->pos = 0; if (!is_string($this->stream)) return false; return true; diff --git a/phpgwapi/inc/class.links_stream_wrapper.inc.php b/phpgwapi/inc/class.links_stream_wrapper.inc.php index 3a303a1a38..5ebeb33dc7 100644 --- a/phpgwapi/inc/class.links_stream_wrapper.inc.php +++ b/phpgwapi/inc/class.links_stream_wrapper.inc.php @@ -74,7 +74,7 @@ class links_stream_wrapper extends links_stream_wrapper_parent { return true; } - $path = parse_url($url,PHP_URL_PATH); + $path = egw_vfs::parse_url($url,PHP_URL_PATH); list(,$apps,$app,$id,$rel_path) = explode('/',$path,5); @@ -154,7 +154,7 @@ class links_stream_wrapper extends links_stream_wrapper_parent // if entry directory does not exist --> return fake directory elseif (!($ret = parent::url_stat($url,$flags,$eacl_check)) && $eacl_check) { - list(,/*$apps*/,/*$app*/,$id,$rel_path) = explode('/', parse_url($url, PHP_URL_PATH), 5); + list(,/*$apps*/,/*$app*/,$id,$rel_path) = explode('/', egw_vfs::parse_url($url, PHP_URL_PATH), 5); if ($id && !isset($rel_path)) { $ret = array( @@ -230,8 +230,8 @@ class links_stream_wrapper extends links_stream_wrapper_parent if($path[0] != '/') { - if (strpos($path,'?') !== false) $query = parse_url($path,PHP_URL_QUERY); - $path = parse_url($path,PHP_URL_PATH).($query ? '?'.$query : ''); + if (strpos($path,'?') !== false) $query = egw_vfs::parse_url($path,PHP_URL_QUERY); + $path = egw_vfs::parse_url($path,PHP_URL_PATH).($query ? '?'.$query : ''); } list(,$apps,$app,$id) = explode('/',$path); diff --git a/phpgwapi/inc/class.sqlfs_stream_wrapper.inc.php b/phpgwapi/inc/class.sqlfs_stream_wrapper.inc.php index ecb9118e70..49f4819949 100644 --- a/phpgwapi/inc/class.sqlfs_stream_wrapper.inc.php +++ b/phpgwapi/inc/class.sqlfs_stream_wrapper.inc.php @@ -192,7 +192,7 @@ class sqlfs_stream_wrapper implements iface_stream_wrapper { if (self::LOG_LEVEL > 1) error_log(__METHOD__."($url,$mode,$options)"); - $path = parse_url($url,PHP_URL_PATH); + $path = egw_vfs::parse_url($url,PHP_URL_PATH); $this->operation = self::url2operation($url); $dir = egw_vfs::dirname($url); @@ -542,7 +542,7 @@ class sqlfs_stream_wrapper implements iface_stream_wrapper { if (self::LOG_LEVEL > 1) error_log(__METHOD__."($url)"); - $path = parse_url($url,PHP_URL_PATH); + $path = egw_vfs::parse_url($url,PHP_URL_PATH); if (!($stat = self::url_stat($path,STREAM_URL_STAT_LINK)) || !egw_vfs::check_access(egw_vfs::dirname($path),egw_vfs::WRITABLE, $parent_stat)) { @@ -590,9 +590,9 @@ class sqlfs_stream_wrapper implements iface_stream_wrapper { if (self::LOG_LEVEL > 1) error_log(__METHOD__."($url_from,$url_to)"); - $path_from = parse_url($url_from,PHP_URL_PATH); + $path_from = egw_vfs::parse_url($url_from,PHP_URL_PATH); $from_dir = egw_vfs::dirname($path_from); - $path_to = parse_url($url_to,PHP_URL_PATH); + $path_to = egw_vfs::parse_url($url_to,PHP_URL_PATH); $to_dir = egw_vfs::dirname($path_to); $operation = self::url2operation($url_from); @@ -684,7 +684,7 @@ class sqlfs_stream_wrapper implements iface_stream_wrapper { if (self::LOG_LEVEL > 1) error_log(__METHOD__."($url,$mode,$options)"); if (self::LOG_LEVEL > 1) error_log(__METHOD__." called from:".function_backtrace()); - $path = parse_url($url,PHP_URL_PATH); + $path = egw_vfs::parse_url($url,PHP_URL_PATH); if (self::url_stat($path,STREAM_URL_STAT_QUIET)) { @@ -698,7 +698,7 @@ class sqlfs_stream_wrapper implements iface_stream_wrapper return false; } $parent_path = egw_vfs::dirname($path); - if (($query = parse_url($url,PHP_URL_QUERY))) $parent_path .= '?'.$query; + if (($query = egw_vfs::parse_url($url,PHP_URL_QUERY))) $parent_path .= '?'.$query; $parent = self::url_stat($parent_path,STREAM_URL_STAT_QUIET); // check if we should also create all non-existing path components and our parent does not exist, @@ -771,7 +771,7 @@ class sqlfs_stream_wrapper implements iface_stream_wrapper { if (self::LOG_LEVEL > 1) error_log(__METHOD__."($url)"); - $path = parse_url($url,PHP_URL_PATH); + $path = egw_vfs::parse_url($url,PHP_URL_PATH); $parent = egw_vfs::dirname($path); if (!($stat = self::url_stat($path,0)) || $stat['mime'] != self::DIR_MIME_TYPE || @@ -826,7 +826,7 @@ class sqlfs_stream_wrapper implements iface_stream_wrapper unset($atime); // not used if (self::LOG_LEVEL > 1) error_log(__METHOD__."($url, $time)"); - $path = parse_url($url,PHP_URL_PATH); + $path = egw_vfs::parse_url($url,PHP_URL_PATH); if (!($stat = self::url_stat($path,STREAM_URL_STAT_QUIET))) { @@ -862,7 +862,7 @@ class sqlfs_stream_wrapper implements iface_stream_wrapper { if (self::LOG_LEVEL > 1) error_log(__METHOD__."($url,$owner)"); - $path = parse_url($url,PHP_URL_PATH); + $path = egw_vfs::parse_url($url,PHP_URL_PATH); if (!($stat = self::url_stat($path,0))) { @@ -902,7 +902,7 @@ class sqlfs_stream_wrapper implements iface_stream_wrapper { if (self::LOG_LEVEL > 1) error_log(__METHOD__."($url,$owner)"); - $path = parse_url($url,PHP_URL_PATH); + $path = egw_vfs::parse_url($url,PHP_URL_PATH); if (!($stat = self::url_stat($path,0))) { @@ -943,7 +943,7 @@ class sqlfs_stream_wrapper implements iface_stream_wrapper { if (self::LOG_LEVEL > 1) error_log(__METHOD__."($url, $mode)"); - $path = parse_url($url,PHP_URL_PATH); + $path = egw_vfs::parse_url($url,PHP_URL_PATH); if (!($stat = self::url_stat($path,0))) { @@ -983,7 +983,7 @@ class sqlfs_stream_wrapper implements iface_stream_wrapper { $this->opened_dir = null; - $path = parse_url($url,PHP_URL_PATH); + $path = egw_vfs::parse_url($url,PHP_URL_PATH); if (!($stat = self::url_stat($url,0)) || // dir not found $stat['mime'] != self::DIR_MIME_TYPE || // no dir @@ -1055,7 +1055,7 @@ class sqlfs_stream_wrapper implements iface_stream_wrapper } if (self::LOG_LEVEL > 1) error_log(__METHOD__."('$url',$flags,$eacl_access)"); - $path = parse_url($url,PHP_URL_PATH); + $path = egw_vfs::parse_url($url,PHP_URL_PATH); // webdav adds a trailing slash to dirs, which causes url_stat to NOT find the file otherwise if ($path != '/' && substr($path,-1) == '/') @@ -1279,7 +1279,7 @@ class sqlfs_stream_wrapper implements iface_stream_wrapper ') VALUES (:fs_name,:fs_dir,:fs_mode,:fs_uid,:fs_gid,:fs_created,:fs_modified,:fs_creator,:fs_mime,:fs_size,:fs_link)'; if (self::LOG_LEVEL > 2) $query = '/* '.__METHOD__.': '.__LINE__.' */ '.$query; $stmt = self::$pdo->prepare($query); - unset(self::$stat_cache[parse_url($link,PHP_URL_PATH)]); + unset(self::$stat_cache[egw_vfs::parse_url($link,PHP_URL_PATH)]); return !!$stmt->execute(array( 'fs_name' => egw_vfs::basename($link), @@ -1310,7 +1310,7 @@ class sqlfs_stream_wrapper implements iface_stream_wrapper */ static function check_extended_acl($url,$check) { - $url_path = parse_url($url,PHP_URL_PATH); + $url_path = egw_vfs::parse_url($url,PHP_URL_PATH); if (is_null(self::$extended_acl)) { @@ -1380,7 +1380,7 @@ class sqlfs_stream_wrapper implements iface_stream_wrapper { if ($path[0] != '/') { - $path = parse_url($path,PHP_URL_PATH); + $path = egw_vfs::parse_url($path,PHP_URL_PATH); } if (is_null($fs_id)) { @@ -1731,7 +1731,7 @@ class sqlfs_stream_wrapper implements iface_stream_wrapper */ static protected function _remove_password(&$url) { - $parts = parse_url($url); + $parts = egw_vfs::parse_url($url); if ($parts['pass'] || $parts['scheme']) { @@ -1753,7 +1753,7 @@ class sqlfs_stream_wrapper implements iface_stream_wrapper if (strpos(is_array($url) ? $url['query'] : $url,'storage=') !== false) { $query = null; - parse_str(is_array($url) ? $url['query'] : parse_url($url,PHP_URL_QUERY), $query); + parse_str(is_array($url) ? $url['query'] : egw_vfs::parse_url($url,PHP_URL_QUERY), $query); switch ($query['storage']) { case 'db': diff --git a/phpgwapi/inc/class.vfs_stream_wrapper.inc.php b/phpgwapi/inc/class.vfs_stream_wrapper.inc.php index 4328424c1c..b0c886a72b 100644 --- a/phpgwapi/inc/class.vfs_stream_wrapper.inc.php +++ b/phpgwapi/inc/class.vfs_stream_wrapper.inc.php @@ -7,7 +7,7 @@ * @package api * @subpackage vfs * @author Ralf Becker - * @copyright (c) 2008-10 by Ralf Becker + * @copyright (c) 2008-14 by Ralf Becker * @version $Id$ */ @@ -159,9 +159,9 @@ class vfs_stream_wrapper implements iface_stream_wrapper $url = $stat['url']; } // if the url resolves to a symlink to the vfs, resolve this vfs:// url direct - if ($url && parse_url($url,PHP_URL_SCHEME) == self::SCHEME) + if ($url && self::parse_url($url,PHP_URL_SCHEME) == self::SCHEME) { - $url = self::resolve_url(parse_url($url,PHP_URL_PATH)); + $url = self::resolve_url(self::parse_url($url,PHP_URL_PATH)); } if (self::LOG_LEVEL > 1) error_log(__METHOD__."($path,file_exists=$file_exists,resolve_last_symlink=$resolve_last_symlink) = '$url'$log"); return $url; @@ -204,7 +204,7 @@ class vfs_stream_wrapper implements iface_stream_wrapper 'home' => str_replace(array('\\\\','\\'),array('','/'),$GLOBALS['egw_info']['user']['homedirectory']), ); } - $parts = array_merge(parse_url($path),$defaults); + $parts = array_merge(self::parse_url($path),$defaults); if (!$parts['host']) $parts['host'] = 'default'; // otherwise we get an invalid url (scheme:///path/to/something)! if (!empty($parts['scheme']) && $parts['scheme'] != self::SCHEME) @@ -218,7 +218,7 @@ class vfs_stream_wrapper implements iface_stream_wrapper { if ($mounted == '/' || $mounted == $parts['path'] || $mounted.'/' == substr($parts['path'],0,strlen($mounted)+1)) { - $scheme = parse_url($url,PHP_URL_SCHEME); + $scheme = self::parse_url($url,PHP_URL_SCHEME); if (is_null(self::$wrappers) || !in_array($scheme,self::$wrappers)) { self::load_wrapper($scheme); @@ -295,7 +295,7 @@ class vfs_stream_wrapper implements iface_stream_wrapper return false; } $this->opened_stream_mode = $mode; - $this->opened_stream_path = $path[0] == '/' ? $path : parse_url($path, PHP_URL_PATH); + $this->opened_stream_path = $path[0] == '/' ? $path : self::parse_url($path, PHP_URL_PATH); $this->opened_stream_url = $url; $this->opened_stream_is_new = !$stat; @@ -470,7 +470,7 @@ class vfs_stream_wrapper implements iface_stream_wrapper { $GLOBALS['egw']->hooks->process(array( 'location' => 'vfs_unlink', - 'path' => $path[0] == '/' ? $path : parse_url($path, PHP_URL_PATH), + 'path' => $path[0] == '/' ? $path : self::parse_url($path, PHP_URL_PATH), 'url' => $url, 'stat' => $stat, ),'',true); @@ -498,7 +498,7 @@ class vfs_stream_wrapper implements iface_stream_wrapper return false; } // if file is moved from one filesystem / wrapper to an other --> copy it (rename fails cross wrappers) - if (parse_url($url_from,PHP_URL_SCHEME) == parse_url($url_to,PHP_URL_SCHEME)) + if (self::parse_url($url_from,PHP_URL_SCHEME) == self::parse_url($url_to,PHP_URL_SCHEME)) { self::symlinkCache_remove($path_from); $ret = rename($url_from,$url_to); @@ -523,8 +523,8 @@ class vfs_stream_wrapper implements iface_stream_wrapper { $GLOBALS['egw']->hooks->process(array( 'location' => 'vfs_rename', - 'from' => $path_from[0] == '/' ? $path_from : parse_url($path_from, PHP_URL_PATH), - 'to' => $path_to[0] == '/' ? $path_to : parse_url($path_to, PHP_URL_PATH), + 'from' => $path_from[0] == '/' ? $path_from : self::parse_url($path_from, PHP_URL_PATH), + 'to' => $path_to[0] == '/' ? $path_to : self::parse_url($path_to, PHP_URL_PATH), 'url_from' => $url_from, 'url_to' => $url_to, ),'',true); @@ -556,7 +556,7 @@ class vfs_stream_wrapper implements iface_stream_wrapper { $GLOBALS['egw']->hooks->process(array( 'location' => 'vfs_mkdir', - 'path' => $path[0] == '/' ? $path : parse_url($path, PHP_URL_PATH), + 'path' => $path[0] == '/' ? $path : self::parse_url($path, PHP_URL_PATH), 'url' => $url, ),'',true); } @@ -589,7 +589,7 @@ class vfs_stream_wrapper implements iface_stream_wrapper { $GLOBALS['egw']->hooks->process(array( 'location' => 'vfs_rmdir', - 'path' => $path[0] == '/' ? $path : parse_url($path, PHP_URL_PATH), + 'path' => $path[0] == '/' ? $path : self::parse_url($path, PHP_URL_PATH), 'url' => $url, 'stat' => $stat, ),'',true); @@ -620,7 +620,7 @@ class vfs_stream_wrapper implements iface_stream_wrapper { return false; } - $k=(string)parse_url($url,PHP_URL_SCHEME); + $k=(string)self::parse_url($url,PHP_URL_SCHEME); if (!(is_array($scheme2urls[$k]))) $scheme2urls[$k] = array(); $scheme2urls[$k][$path] = $url; } @@ -648,7 +648,7 @@ class vfs_stream_wrapper implements iface_stream_wrapper // we need to re-translate the urls to pathes, as they can eg. contain symlinks foreach($urls as $path => $url) { - if (isset($r[$url]) || isset($r[$url=parse_url($url,PHP_URL_PATH)])) + if (isset($r[$url]) || isset($r[$url=self::parse_url($url,PHP_URL_PATH)])) { $ret[$path] = $r[$url]; } @@ -774,7 +774,7 @@ class vfs_stream_wrapper implements iface_stream_wrapper { return false; } - if (($scheme = parse_url($url,PHP_URL_SCHEME)) && !$recheck) + if (($scheme = self::parse_url($url,PHP_URL_SCHEME)) && !$recheck) { // check it it's an eGW stream wrapper returning mime-type via url_stat // we need to first check if the constant is defined, as we get a fatal error in php5.3 otherwise @@ -782,7 +782,7 @@ class vfs_stream_wrapper implements iface_stream_wrapper defined($class.'::STAT_RETURN_MIME_TYPE') && ($mime_attr = constant($class.'::STAT_RETURN_MIME_TYPE'))) { - $stat = call_user_func(array($class,'url_stat'),parse_url($url,PHP_URL_PATH),0); + $stat = call_user_func(array($class,'url_stat'),self::parse_url($url,PHP_URL_PATH),0); if ($stat && $stat[$mime_attr]) { $mime = $stat[$mime_attr]; @@ -801,7 +801,7 @@ class vfs_stream_wrapper implements iface_stream_wrapper // using EGw's own mime magic (currently only checking the extension!) if (!$mime) { - $mime = mime_magic::filename2mime(parse_url($url,PHP_URL_PATH)); + $mime = mime_magic::filename2mime(self::parse_url($url,PHP_URL_PATH)); } //error_log(__METHOD__."($path,$recheck) mime=$mime"); return $mime; @@ -830,7 +830,7 @@ class vfs_stream_wrapper implements iface_stream_wrapper } $this->opened_dir_writable = egw_vfs::check_access($this->opened_dir_url,egw_vfs::WRITABLE); // check our fstab if we need to add some of the mountpoints - $basepath = parse_url($path,PHP_URL_PATH); + $basepath = self::parse_url($path,PHP_URL_PATH); foreach(self::$fstab as $mounted => $url) { if (((egw_vfs::dirname($mounted) == $basepath || egw_vfs::dirname($mounted).'/' == $basepath) && $mounted != '/') && @@ -901,7 +901,7 @@ class vfs_stream_wrapper implements iface_stream_wrapper { if ($lpath[0] != '/') // concat relative path { - $lpath = egw_vfs::concat(parse_url($path,PHP_URL_PATH),'../'.$lpath); + $lpath = egw_vfs::concat(self::parse_url($path,PHP_URL_PATH),'../'.$lpath); } $url = egw_vfs::PREFIX.$lpath; if (self::LOG_LEVEL > 1) error_log(__METHOD__."($path,$flags) symlif (substr($path,-1) == '/' && $path != '/') $path = substr($path,0,-1); // remove trailing slash eg. added by WebDAVink found and resolved to $url"); @@ -929,7 +929,7 @@ class vfs_stream_wrapper implements iface_stream_wrapper throw $e; } // check if a failed url_stat was for a home dir, in that case silently create it - if (!$stat && $try_create_home && egw_vfs::dirname(parse_url($path,PHP_URL_PATH)) == '/home' && + if (!$stat && $try_create_home && egw_vfs::dirname(self::parse_url($path,PHP_URL_PATH)) == '/home' && ($id = $GLOBALS['egw']->accounts->name2id(basename($path))) && $GLOBALS['egw']->accounts->id2name($id) == basename($path)) // make sure path has the right case! { @@ -994,7 +994,7 @@ class vfs_stream_wrapper implements iface_stream_wrapper if ($lpath[0] != '/') { - $lpath = egw_vfs::concat(parse_url($url,PHP_URL_PATH),'../'.$lpath); + $lpath = egw_vfs::concat(self::parse_url($url,PHP_URL_PATH),'../'.$lpath); } //self::symlinkCache_add($path,egw_vfs::PREFIX.$lpath); $url = egw_vfs::PREFIX.egw_vfs::concat($lpath,$rel_path); @@ -1029,7 +1029,7 @@ class vfs_stream_wrapper implements iface_stream_wrapper if (isset(self::$symlink_cache[$path])) return; // nothing to do - if ($target[0] != '/') $target = parse_url($target,PHP_URL_PATH); + if ($target[0] != '/') $target = self::parse_url($target,PHP_URL_PATH); self::$symlink_cache[$path] = $target; @@ -1229,26 +1229,78 @@ class vfs_stream_wrapper implements iface_stream_wrapper return str_replace('.','_',$scheme).'_stream_wrapper'; } + /** + * Utf-8 save version of parse_url + * + * Does caching withing request, to not have to parse urls over and over again. + * + * @param string $url + * @param int $component =-1 PHP_URL_* constants + * @return array|string|boolean on success array or string, if $component given, or false on failure + */ + static function parse_url($url, $component=-1) + { + static $component2str = array( + PHP_URL_SCHEME => 'scheme', + PHP_URL_HOST => 'host', + PHP_URL_PORT => 'port', + PHP_URL_USER => 'user', + PHP_URL_PASS => 'pass', + PHP_URL_PATH => 'path', + PHP_URL_QUERY => 'query', + PHP_URL_FRAGMENT => 'fragment', + ); + static $cache = array(); // some caching + + $result =& $cache[$url]; + + if (!isset($result)) + { + // Build arrays of values we need to decode before parsing + static $entities = array('%21', '%2A', '%27', '%28', '%29', '%3B', '%3A', '%40', '%26', '%3D', '%24', '%2C', '%2F', '%3F', '%23', '%5B', '%5D'); + static $replacements = array('!', '*', "'", "(", ")", ";", ":", "@", "&", "=", "$", ",", "/", "?", "#", "[", "]"); + static $str_replace = null; + if (!isset($str_replace)) $str_replace = function_exists('mb_str_replace') ? 'mb_str_replace' : 'str_replace'; + + // Create encoded URL with special URL characters decoded so it can be parsed + // All other characters will be encoded + $encodedURL = $str_replace($entities, $replacements, urlencode($url)); + + // Parse the encoded URL + $result = $encodedParts = parse_url($encodedURL); + + // Now, decode each value of the resulting array + if ($encodedParts) + { + $result = array(); + foreach ($encodedParts as $key => $value) + { + $result[$key] = urldecode($str_replace($replacements, $entities, $value)); + } + } + } + return $component >= 0 ? $result[$component2str[$component]] : $result; + } + /** * Getting the path from an url (or path) AND removing trailing slashes * * @param string $path url or path (might contain trailing slash from WebDAV!) - * @param string $only_remove_scheme=self::SCHEME if given only that scheme get's removed + * @param string $only_remove_scheme =self::SCHEME if given only that scheme get's removed * @return string path without training slash */ static protected function get_path($path,$only_remove_scheme=self::SCHEME) { - $url_parts = parse_url($path); - if ($path[0] != '/' && (!$only_remove_scheme || $url_parts['scheme'] == $only_remove_scheme)) + if ($path[0] != '/' && (!$only_remove_scheme || self::parse_url($path, PHP_URL_SCHEME) == $only_remove_scheme)) { - $path = $url_parts['path']; + $path = self::parse_url($path, PHP_URL_PATH); } // remove trailing slashes eg. added by WebDAV - if ($url_parts['path'] != '/') + if ($path != '/') { - while (substr($path,-1) == '/' && $path != '/') + while (mb_substr($path, -1) == '/' && $path != '/') { - $path = substr($path,0,-1); + $path = mb_substr($path,0,-1); } } return $path;