diff --git a/filemanager/cli.php b/filemanager/cli.php index f8d400e592..fcf749ae64 100755 --- a/filemanager/cli.php +++ b/filemanager/cli.php @@ -21,7 +21,7 @@ if (isset($_SERVER['HTTP_HOST'])) // security precaution: forbit calling ls as w } /** - * callback if the session-check fails, redirects via xajax to login.php + * callback if the session-check fails, creates session from user/passwd in $GLOBALS['egw_login_data'] * * @param array &$account account_info with keys 'login', 'passwd' and optional 'passwd_type' * @return boolean/string true if we allow the access and account is set, a sessionid or false otherwise @@ -58,7 +58,7 @@ function usage($action=null,$ret=0) echo "\t$cmd chmod [-r|--recursive] mode=[ugoa]*[+-=][rwx]+,... URL [URL2 ...]\n"; echo "\t$cmd chown [-r|--recursive] user URL [URL2 ...]\n"; echo "\t$cmd chgrp [-r|--recursive] group URL [URL2 ...]\n"; - echo "\t$cmd find URL [URL2 ...] [-type (d|f)][-dirs_last][-mime type[/sub]][-name pattern][-path pattern][-uid id][-user name][-nouser][-gid id][-group name][-nogroup][-size N][-cmin N][-ctime N][-mmin N][-mtime N] (N: +n --> >n, -n --> =n)\n"; + echo "\t$cmd find URL [URL2 ...] [-type (d|f)][-depth][-mindepth n][-maxdepth n][-mime type[/sub]][-name pattern][-path pattern][-uid id][-user name][-nouser][-gid id][-group name][-nogroup][-size N][-cmin N][-ctime N][-mmin N][-mtime N] (N: +n --> >n, -n --> =n)\n"; echo "\t$cmd mount URL [path] (without path prints out the mounts)\n"; echo "\t$cmd umount URL|path\n"; @@ -92,13 +92,13 @@ while(!is_null($option = array_shift($argv))) default: if ($cmd == 'find') { - if (!in_array($option,array('-type','-dirs_last','-name','-path', + if (!in_array($option,array('-type','-depth','-mindepth','-maxdepth','-name','-path', '-uid','-user','-nouser','-gid','-group','-nogroup','-mime', '-empty','-size','-cmin','-ctime','-mmin','-mtime'))) { usage(); } - if (in_array($option,array('-empty','-dirs_last','-nouser','-nogroup'))) + if (in_array($option,array('-empty','-depth','-nouser','-nogroup'))) { $find_options[substr($option,1)] = true; } @@ -328,7 +328,7 @@ switch($cmd) { load_wrapper($url); array_unshift($argv,$url); - egw_vfs::find($argv,array('dirs_last'=>true),'do_stat',array($long,$numeric,true)); + egw_vfs::find($argv,array('url'=>true,),'do_stat',array($long,$numeric,true)); $argv = array(); } elseif (is_dir($url) && ($dir = opendir($url))) @@ -431,6 +431,12 @@ function load_wrapper($url) } set_exception_handler('cli_exception_handler'); // otherwise we get html! } + $cmd = $GLOBALS['cmd']; + if (!in_array($cmd,array('ls','find','mount','umount')) && $GLOBALS['egw_info']['server']['files_dir'] && !is_writable($GLOBALS['egw_info']['server']['files_dir'])) + { + echo "\nError: eGroupWare's files directory {$GLOBALS['egw_info']['server']['files_dir']} is NOT writable by the user running ".basename(__FILE__)."!\n". + "--> Please run it as the same user the webserver uses or root, otherwise the $cmd command will fail!\n\n"; + } } require_once(EGW_API_INC.'/class.'.$scheme.'_stream_wrapper.inc.php'); break; @@ -549,7 +555,7 @@ function do_cp($argv,$recursive=false,$perms=false) { if (is_dir($from) && (!file_exists($to) || is_dir($to)) && $recursive && class_exists('egw_vfs')) { - foreach(egw_vfs::find($from) as $f) + foreach(egw_vfs::find($from,array('url' => true)) as $f) { $t = $to.substr($f,strlen($from)); if (is_dir($f)) @@ -629,6 +635,8 @@ function do_find($bases,$options) { load_wrapper($url); } + $options['url'] = true; // we use url's not vfs pathes in filemanager/cli.php + foreach(egw_vfs::find($bases,$options) as $path) { echo "$path\n"; diff --git a/filemanager/inc/class.filemanager_hooks.inc.php b/filemanager/inc/class.filemanager_hooks.inc.php index a837994550..c4919a9642 100644 --- a/filemanager/inc/class.filemanager_hooks.inc.php +++ b/filemanager/inc/class.filemanager_hooks.inc.php @@ -28,7 +28,8 @@ class filemanager_hooks 'Search', 'text' => 'Search', 'link' => $GLOBALS['egw']->link('/index.php',array('menuaction'=>'filemanager.uifilemanager.index', 'action'=>'search')), - ) + ), + 'New GUI' => $GLOBALS['egw']->link('/index.php',array('menuaction'=>'filemanager.filemanager_ui.index')), ); display_sidebox($appname,$title,$file); } diff --git a/filemanager/inc/class.filemanager_ui.inc.php b/filemanager/inc/class.filemanager_ui.inc.php new file mode 100644 index 0000000000..69caff795b --- /dev/null +++ b/filemanager/inc/class.filemanager_ui.inc.php @@ -0,0 +1,376 @@ + + * @copyright (c) 2008 by Ralf Becker + * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License + * @version $Id$ + */ + +class filemanager_ui +{ + /** + * Methods callable via menuaction + * + * @var array + */ + var $public_functions = array( + 'index' => true, + ); + + /** + * Main filemanager page + * + * @param array $content=null + * @param string $msg=null + */ + function index($content=null,$msg=null) + { + $tpl = new etemplate('filemanager.index'); + + //_debug_array($content); + + if (!is_array($content)) + { + $content = array( + 'nm' => $GLOBALS['egw']->session->appsession('index','filemanager'), + ); + if (!is_array($content['nm'])) + { + $content['nm'] = array( + 'get_rows' => 'filemanager.filemanager_ui.get_rows', // I method/callback to request the data for the rows eg. 'notes.bo.get_rows' +// 'filter_label' => // I label for filter (optional) +// 'filter_help' => // I help-msg for filter (optional) + 'no_filter' => True, // I disable the 1. filter + 'no_filter2' => True, // I disable the 2. filter (params are the same as for filter) + 'no_cat' => True, // I disable the cat-selectbox +// 'cat_app' => // I application the cat's should be from, default app in get_rows +// 'template' => // I template to use for the rows, if not set via options +// 'header_left' => // I template to show left of the range-value, left-aligned (optional) +// 'header_right' => // I template to show right of the range-value, right-aligned (optional) +// 'bottom_too' => True// I show the nextmatch-line (arrows, filters, search, ...) again after the rows +// 'never_hide' => True, // I never hide the nextmatch-line if less then maxmatch entrie +// 'lettersearch' => True, // I show a lettersearch + 'searchletter' => false, // I0 active letter of the lettersearch or false for [all] + 'start' => 0, // IO position in list +// 'num_rows' => // IO number of rows to show, defaults to maxmatches from the general prefs +// 'cat_id' => // IO category, if not 'no_cat' => True +// 'search' => // IO search pattern + 'order' => 'name', // IO name of the column to sort after (optional for the sortheaders) + 'sort' => 'ASC', // IO direction of the sort: 'ASC' or 'DESC' +// 'col_filter' => // IO array of column-name value pairs (optional for the filterheaders) +// 'filter' => // IO filter, if not 'no_filter' => True +// 'filter_no_lang' => True// I set no_lang for filter (=dont translate the options) +// 'filter_onchange'=> 'this.form.submit();'// I onChange action for filter, default: this.form.submit(); +// 'filter2' => // IO filter2, if not 'no_filter2' => True +// 'filter2_no_lang'=> True// I set no_lang for filter2 (=dont translate the options) +// 'filter2_onchange'=> 'this.form.submit();'// I onChange action for filter, default: this.form.submit(); + 'default_cols' => '!comment', // I columns to use if there's no user or default pref (! as first char uses all but the named columns), default all columns + 'csv_fields' => false, // I false=disable csv export, true or unset=enable it with auto-detected fieldnames, + //or array with name=>label or name=>array('label'=>label,'type'=>type) pairs (type is a eT widget-type) + 'path' => '/home/'.$GLOBALS['egw_info']['user']['account_lid'], + ); + } + if (isset($_GET['path']) && ($path = $_GET['path']) && $path[0] == '/' && egw_vfs::is_dir($path)) + { + $content['nm']['path'] = $path; + } + } + $content['nm']['msg'] = $msg; + + if ($content['action'] || $content['nm']['rows']) + { + if ($content['action']) + { + $content['nm']['msg'] = self::action($content['action'],$content['nm']['rows']['checked'],$content['nm']['path']); + unset($content['action']); + } + elseif($content['nm']['rows']['delete']) + { + $content['nm']['msg'] = self::action('delete',array_keys($content['nm']['rows']['delete']),$content['nm']['path']); + } + unset($content['nm']['rows']); + } + $clipboard_files = $GLOBALS['egw']->session->appsession('clipboard_files','filemanager'); + + if ($content['button']) + { + if ($content['button']) + { + list($button) = each($content['button']); + unset($content['button']); + } + switch($button) + { + case 'up': + if ($content['nm']['path'] != '/') + { + $content['nm']['path'] = dirname($content['nm']['path']); + } + break; + case 'home': + $content['nm']['path'] = '/home/'.$GLOBALS['egw_info']['user']['account_lid']; + break; + case 'createdir': + if ($content['nm']['path'][0] != '/') + { + $ses = $GLOBALS['egw']->session->appsession('index','filemanager'); + $old_path = $ses['path']; + $content['nm']['path'] = $old_path.'/'.$content['nm']['path']; + } + if (!@egw_vfs::mkdir($content['nm']['path'],null,STREAM_MKDIR_RECURSIVE)) + { + $content['nm']['msg'] = !egw_vfs::is_writable(dirname($content['nm']['path'])) ? + lang('Permission denied!') : lang('Failed to create directory!'); + if (!$old_path) + { + $ses = $GLOBALS['egw']->session->appsession('index','filemanager'); + $old_path = $ses['path']; + } + $content['nm']['path'] = $old_path; + } + break; + case 'paste': + $clipboard_type = $GLOBALS['egw']->session->appsession('clipboard_type','filemanager'); + $content['nm']['msg'] = self::action($clipboard_type.'_paste',$clipboard_files,$content['nm']['path']); + break; + case 'upload': + $to = $content['nm']['path'].'/'.$content['upload']['name']; + if ($content['upload'] && is_uploaded_file($content['upload']['tmp_name']) && + (egw_vfs::is_writable($content['nm']['path']) || egw_vfs::is_writable($to)) && + copy($content['upload']['tmp_name'],egw_vfs::PREFIX.$to)) + { + $content['nm']['msg'] = lang('File successful uploaded.'); + } + else + { + $content['nm']['msg'] = lang('Error uploading file!'); + } + break; + } + } + if (!egw_vfs::is_dir($content['nm']['path'])) + { + $content['nm']['msg'] .= lang('Directory not found or no permission to access it!'); + } + else + { + $dir_is_writable = egw_vfs::is_writable($content['nm']['path']); + } + //_debug_array($content); + $readonlys['button[paste]'] = !$clipboard_files; + $readonlys['button[createdir]'] = !$dir_is_writable; + $readonlys['button[upload]'] = !$dir_is_writable; + + if ($dir_is_writable) $sel_options['action']['delete'] = lang('Delete'); + $sel_options['action']['copy'] = lang('Copy to clipboard'); + if ($dir_is_writable) $sel_options['action']['cut'] = lang('Cut to clipboard'); + + $tpl->exec('filemanager.filemanager_ui.index',$content,$sel_options,$readonlys,array('nm' => $content['nm'])); + } + + /** + * Run a certain action with the selected file + * + * @param string $action + * @param array $selected selected pathes + * @param mixed $dir=null current directory + * @return string success or failure message displayed to the user + */ + static private function action($action,$selected,$dir=null) + { + //echo '

'.__METHOD__."($action,array(".implode(', ',$selected).",$dir)

\n"; + if (!count($selected)) + { + return lang('You need to select some files first!'); + } + $errs = $dirs = $files = 0; + switch($action) + { + case 'delete': + $dirs = $files = $errs = 0; + foreach(egw_vfs::find($selected,array('depth'=>true)) as $path) + { + if (($is_dir = egw_vfs::is_dir($path)) && egw_vfs::rmdir($path,0)) + { + ++$dirs; + } + elseif (!$is_dir && egw_vfs::unlink($path)) + { + ++$files; + } + else + { + ++$errs; + } + } + if ($errs) + { + return lang('%1 errors deleteting (%2 directories and %3 files deleted)!',$errs,$dirs,$files); + } + if ($dirs) + { + return lang('%1 directories and %2 files deleted.',$dirs,$files); + } + return $files == 1 ? lang('File deleted.') : lang('%1 files deleted.',$files); + + case 'copy': + case 'cut': + $GLOBALS['egw']->session->appsession('clipboard_files','filemanager',$selected); + $GLOBALS['egw']->session->appsession('clipboard_type','filemanager',$action); + return lang('%1 URLs %2 to clipboard.',count($selected),$action=='copy'?lang('copied'):lang('cut')); + + case 'copy_paste': + foreach($selected as $path) + { + if (!egw_vfs::is_dir($path)) + { + $to = $dir.'/'.egw_vfs::basename($path); + if (egw_vfs::copy($path,$to)) + { + ++$files; + } + else + { + ++$errs; + } + } + else + { + $len = strlen(dirname($path)); + foreach(egw_vfs::find($path) as $p) + { + $to = $dir.substr($p,$len); + if (($is_dir = egw_vfs::is_dir($p)) && egw_vfs::mkdir($to,null,STREAM_MKDIR_RECURSIVE)) + { + ++$dirs; + } + elseif(!$is_dir && egw_vfs::copy($p,$to)) + { + ++$files; + } + else + { + ++$errs; + } + } + } + } + if ($errs) + { + return lang('%1 errors copying (%2 diretories and %3 files copied)!',$errs,$dirs,$files); + } + return $dirs ? lang('%1 directories and %2 files copied.',$dirs,$files) : lang('%1 files copied.',$files); + + case 'cut_paste': + foreach($selected as $path) + { + $to = $dir.'/'.egw_vfs::basename($path); + if (egw_vfs::rename($path,$to)) + { + ++$files; + } + else + { + ++$errs; + } + } + $GLOBALS['egw']->session->appsession('clipboard_files','filemanager',false); // cant move again + if ($errs) + { + return lang('%1 errors moving (%2 files moved)!',$errs,$files); + } + return lang('%1 files moved.',$files); + } + return "Unknown action '$action'!"; + } + + /** + * Get the closest mime icon + * + * @param string $mime_type + * @param int $size=16 + * @return string + */ + static private function mime_icon($mime_type, $size=16) + { + if ($mime_type == egw_vfs::DIR_MIME_TYPE) + { + $mime_type = 'Directory'; + } + if(!$mime_type) + { + $mime_type='unknown'; + } + $mime_type= strtolower(str_replace ('/','_',$mime_type)); + list($mime_part) = explode('_',$mime_type); + + if (!($img=$GLOBALS['egw']->common->image('filemanager',$icon='mime'.$size.'_'.$mime_type)) && + !($img=$GLOBALS['egw']->common->image('filemanager',$icon='mime'.$size.'_'.$mime_part))) + { + $img = $GLOBALS['egw']->common->image('filemanager',$icon='mime'.$size.'_unknown'); + } + return 'filemanager/'.$icon; + } + + /** + * Callback to fetch the rows for the nextmatch widget + * + * @param array $query + * @param array &$rows + * @param array &$readonlys + */ + function get_rows($query,&$rows,&$readonlys) + { + $GLOBALS['egw']->session->appsession('index','filemanager',$query); + //_debug_array($query); + + if (!egw_vfs::is_dir($query['path'])) + { + $rows = array(); + $query['total'] = 0; + } + $dir_is_writable = egw_vfs::is_writable($query['path']); + + $rows = array(); + foreach(egw_vfs::find($query['path'],array('mindepth'=>1,'maxdepth'=>1)) as $path) + { + $row = egw_vfs::stat($path); + $row['name'] = egw_vfs::basename($path); + $row['path'] = $path; + $row['mime'] = egw_vfs::mime_content_type($path); + $row['icon'] = self::mime_icon($row['mime']); + $row['perms'] = egw_vfs::int2mode($row['mode']); + // only show link if we have access to the file or dir + if (egw_vfs::check_access($row,egw_vfs::READABLE)) + { + if ($row['mime'] == egw_vfs::DIR_MIME_TYPE) + { + $row['link'] = '/index.php?menuaction=filemanager.filemanager_ui.index&path='.$path; + } + else + { + $row['link'] = '/index.php?menuaction=filemanager.uifilemanager.view&path='.base64_encode(dirname($path)).'&file='.base64_encode(egw_vfs::basename($path)); +// $row['link'] = '/filemanager/webdav.php'.$path; + } + } + $row['user'] = $row['uid'] ? $GLOBALS['egw']->accounts->id2name($row['uid']) : 'root'; + $row['group'] = $row['gid'] ? $GLOBALS['egw']->accounts->id2name(-$row['gid']) : 'root'; + $row['hsize'] = egw_vfs::hsize($row['size']); + + //echo $path; _debug_array($row); + + $rows[++$n] = $row; + + if (!$dir_is_writable) + { + $readonlys["delete[$path]"] = true; // no rights to delete the file + } + } + //_debug_array($readonlys); + return count($rows); + } +} \ No newline at end of file diff --git a/filemanager/setup/etemplates.inc.php b/filemanager/setup/etemplates.inc.php index d7af20309e..d752dd222e 100644 --- a/filemanager/setup/etemplates.inc.php +++ b/filemanager/setup/etemplates.inc.php @@ -2,7 +2,7 @@ /** * eGroupWare - eTemplates for Application filemanager * http://www.egroupware.org - * generated by soetemplate::dump4setup() 2008-01-15 04:17 + * generated by soetemplate::dump4setup() 2008-03-02 23:05 * * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License * @package filemanager @@ -12,6 +12,10 @@ $templ_version=1; +$templ_data[] = array('name' => 'filemanager.index','template' => '','lang' => '','group' => '0','version' => '1.5.001','data' => 'a:1:{i:0;a:4:{s:4:"type";s:4:"grid";s:4:"data";a:5:{i:0;a:1:{s:1:"A";s:3:"250";}i:1;a:2:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:4:"span";s:13:"all,redItalic";s:4:"name";s:7:"nm[msg]";}s:1:"B";a:1:{s:4:"type";s:5:"label";}}i:2;a:2:{s:1:"A";a:10:{s:4:"type";s:4:"hbox";s:4:"size";s:1:"7";i:1;a:4:{s:4:"type";s:6:"button";s:4:"size";s:4:"goup";s:5:"label";s:2:"Up";s:4:"name";s:10:"button[up]";}i:2;a:4:{s:4:"type";s:6:"button";s:4:"name";s:12:"button[home]";s:4:"size";s:6:"gohome";s:5:"label";s:20:"Go to home directory";}s:4:"span";s:3:"all";i:3;a:6:{s:4:"type";s:4:"text";s:4:"name";s:8:"nm[path]";s:4:"size";s:2:"80";s:5:"label";s:4:"Path";s:8:"onchange";i:1;s:4:"span";s:8:",address";}i:4;a:4:{s:4:"type";s:6:"button";s:4:"name";s:10:"button[go]";s:4:"size";s:9:"key_enter";s:5:"label";s:5:"Go to";}i:5;a:2:{s:4:"type";s:5:"image";s:4:"name";s:15:"buttonseparator";}i:6;a:5:{s:4:"type";s:6:"button";s:4:"name";s:17:"button[createdir]";s:4:"size";s:16:"button_createdir";s:5:"label";s:16:"Create directory";s:7:"onclick";s:128:"var dir = prompt(egw::lang(\'New directory\')); if (!dir) return false; document.getElementById(form::name(\'nm[path]\')).value=dir;";}i:7;a:5:{s:4:"type";s:6:"button";s:4:"name";s:13:"button[paste]";s:4:"size";s:9:"editpaste";s:5:"label";s:5:"Paste";s:4:"help";s:46:"Paste cut or copied files to current directory";}}s:1:"B";a:1:{s:4:"type";s:5:"label";}}i:3;a:2:{s:1:"A";a:4:{s:4:"type";s:9:"nextmatch";s:4:"size";s:22:"filemanager.index.rows";s:4:"span";s:3:"all";s:4:"name";s:2:"nm";}s:1:"B";a:1:{s:4:"type";s:5:"label";}}i:4;a:2:{s:1:"A";a:4:{s:4:"type";s:4:"hbox";s:4:"size";s:1:"2";i:1;a:3:{s:4:"type";s:4:"file";s:4:"name";s:6:"upload";s:4:"help";s:42:"Select file to upload in current directory";}i:2;a:3:{s:4:"type";s:6:"button";s:5:"label";s:6:"Upload";s:4:"name";s:14:"button[upload]";}}s:1:"B";a:5:{s:4:"type";s:4:"hbox";s:4:"size";s:1:"2";s:5:"align";s:5:"right";i:1;a:4:{s:4:"type";s:6:"select";s:4:"name";s:6:"action";s:4:"size";s:16:"Select action...";s:8:"onchange";i:1;}i:2;a:8:{s:4:"type";s:6:"button";s:4:"size";s:9:"arrow_ltr";s:5:"label";s:9:"Check all";s:4:"name";s:9:"check_all";s:4:"help";s:9:"Check all";s:7:"onclick";s:70:"toggle_all(this.form,form::name(\'nm[rows][checked][]\')); return false;";s:6:"needed";s:1:"1";s:4:"span";s:14:",checkAllArrow";}}}}s:4:"rows";i:4;s:4:"cols";i:2;}}','size' => '','style' => '','modified' => '1204374710',); + +$templ_data[] = array('name' => 'filemanager.index.rows','template' => '','lang' => '','group' => '0','version' => '1.5.001','data' => 'a:1:{i:0;a:6:{s:4:"type";s:4:"grid";s:4:"data";a:3:{i:0;a:4:{s:2:"c1";s:2:"th";s:2:"c2";s:3:"row";s:1:"B";s:3:"30%";s:1:"D";s:3:"120";}i:1;a:9:{s:1:"A";a:4:{s:4:"type";s:20:"nextmatch-sortheader";s:5:"label";s:4:"Type";s:4:"name";s:4:"type";s:5:"align";s:6:"center";}s:1:"B";a:3:{s:4:"type";s:20:"nextmatch-sortheader";s:5:"label";s:4:"Name";s:4:"name";s:4:"name";}s:1:"C";a:3:{s:4:"type";s:20:"nextmatch-sortheader";s:5:"label";s:4:"Size";s:4:"name";s:4:"size";}s:1:"D";a:3:{s:4:"type";s:20:"nextmatch-sortheader";s:5:"label";s:8:"Modified";s:4:"name";s:5:"mtime";}s:1:"E";a:3:{s:4:"type";s:20:"nextmatch-sortheader";s:5:"label";s:11:"Permissions";s:4:"name";s:4:"mode";}s:1:"F";a:3:{s:4:"type";s:20:"nextmatch-sortheader";s:4:"name";s:3:"uid";s:5:"label";s:5:"Owner";}s:1:"G";a:3:{s:4:"type";s:20:"nextmatch-sortheader";s:4:"name";s:3:"gid";s:5:"label";s:5:"Group";}s:1:"H";a:3:{s:4:"type";s:16:"nextmatch-header";s:5:"label";s:7:"Comment";s:4:"name";s:7:"comment";}s:1:"I";a:4:{s:4:"type";s:4:"hbox";s:4:"size";s:6:"2,,0,0";i:1;a:2:{s:4:"type";s:5:"label";s:5:"label";s:7:"Actions";}i:2;a:8:{s:4:"type";s:6:"button";s:4:"size";s:5:"check";s:5:"label";s:9:"Check all";s:4:"name";s:9:"check_all";s:4:"help";s:9:"Check all";s:7:"onclick";s:60:"toggle_all(this.form,form::name(\'checked[]\')); return false;";s:6:"needed";s:1:"1";s:5:"align";s:5:"right";}}}i:2;a:9:{s:1:"A";a:4:{s:4:"type";s:5:"image";s:5:"label";s:15:"$row_cont[mime]";s:4:"name";s:12:"${row}[icon]";s:5:"align";s:6:"center";}s:1:"B";a:4:{s:4:"type";s:5:"label";s:4:"size";s:16:",$row_cont[link]";s:4:"name";s:12:"${row}[name]";s:7:"no_lang";s:1:"1";}s:1:"C";a:3:{s:4:"type";s:5:"label";s:4:"name";s:13:"${row}[hsize]";s:5:"align";s:5:"right";}s:1:"D";a:3:{s:4:"type";s:9:"date-time";s:4:"name";s:13:"${row}[mtime]";s:8:"readonly";s:1:"1";}s:1:"E";a:3:{s:4:"type";s:5:"label";s:5:"label";s:16:"$row_cont[perms]";s:4:"span";s:6:",perms";}s:1:"F";a:3:{s:4:"type";s:5:"label";s:4:"name";s:12:"${row}[user]";s:7:"no_lang";s:1:"1";}s:1:"G";a:3:{s:4:"type";s:5:"label";s:4:"name";s:13:"${row}[group]";s:7:"no_lang";s:1:"1";}s:1:"H";a:2:{s:4:"type";s:5:"label";s:4:"name";s:15:"${row}[comment]";}s:1:"I";a:6:{s:4:"type";s:4:"hbox";s:4:"size";s:1:"3";i:1;a:5:{s:4:"type";s:6:"button";s:4:"size";s:4:"edit";s:5:"label";s:13:"Edit settings";s:4:"name";s:21:"edit[$row_cont[path]]";s:4:"help";s:39:"Rename, change permissions or ownership";}i:2;a:7:{s:4:"type";s:6:"button";s:4:"name";s:23:"delete[$row_cont[path]]";s:4:"size";s:6:"delete";s:5:"label";s:6:"Delete";s:4:"help";s:29:"Delete this file or directory";s:7:"onclick";s:48:"return confirm(\'Delete this file or directory\');";s:5:"align";s:6:"center";}i:3;a:4:{s:4:"type";s:8:"checkbox";s:4:"name";s:9:"checked[]";s:5:"align";s:5:"right";s:4:"size";s:15:"$row_cont[path]";}s:5:"align";s:5:"right";}}}s:4:"rows";i:2;s:4:"cols";i:9;s:4:"size";s:4:"100%";s:7:"options";a:1:{i:0;s:4:"100%";}}}','size' => '100%','style' => '','modified' => '1204370567',); + $templ_data[] = array('name' => 'filemanager.search','template' => '','lang' => '','group' => '0','version' => '1.3.001','data' => 'a:4:{i:0;a:9:{s:4:"type";s:8:"groupbox";s:4:"name";s:10:"debuginfos";s:4:"size";s:1:"4";s:5:"label";s:10:"Debuginfos";s:8:"disabled";s:1:"1";i:1;a:3:{s:4:"type";s:8:"textarea";s:4:"name";s:7:"message";s:8:"readonly";s:1:"1";}i:2;a:1:{s:4:"type";s:5:"label";}i:3;a:1:{s:4:"type";s:5:"label";}i:4;a:1:{s:4:"type";s:5:"label";}}i:1;a:4:{s:4:"type";s:4:"grid";s:4:"data";a:7:{i:0;a:2:{s:1:"C";s:3:"120";s:1:"D";s:3:"120";}i:1;a:5:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:5:"label";s:12:"searchstring";s:4:"name";s:17:"searchstringlabel";}s:1:"B";a:3:{s:4:"type";s:4:"text";s:4:"span";s:1:"2";s:4:"name";s:12:"searchstring";}s:1:"C";a:1:{s:4:"type";s:5:"label";}s:1:"D";a:3:{s:4:"type";s:6:"button";s:5:"label";s:12:"start search";s:4:"name";s:12:"start_search";}s:1:"E";a:1:{s:4:"type";s:5:"label";}}i:2;a:5:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:9:"mime type";}s:1:"B";a:2:{s:4:"type";s:8:"checkbox";s:4:"name";s:8:"checkall";}s:1:"C";a:3:{s:4:"type";s:5:"label";s:5:"label";s:3:"All";s:4:"name";s:8:"alllabel";}s:1:"D";a:4:{s:4:"type";s:5:"label";s:4:"data";a:2:{i:0;a:0:{}i:1;a:1:{s:1:"A";a:3:{s:4:"type";s:8:"checkbox";s:5:"label";s:5:"files";s:4:"name";s:14:"checkonlyfiles";}}}s:4:"rows";i:1;s:4:"cols";i:1;}s:1:"E";a:1:{s:4:"type";s:5:"label";}}i:3;a:5:{s:1:"A";a:1:{s:4:"type";s:5:"label";}s:1:"B";a:2:{s:4:"type";s:8:"checkbox";s:4:"name";s:14:"checkonlyfiles";}s:1:"C";a:3:{s:4:"type";s:5:"label";s:5:"label";s:5:"files";s:4:"name";s:9:"filelabel";}s:1:"D";a:4:{s:4:"type";s:6:"button";s:5:"label";s:12:"clear search";s:4:"name";s:12:"clear_search";s:7:"onclick";s:71:"menuaction=filemanager.uifilemanager.index&action=search&actioncd=clear";}s:1:"E";a:1:{s:4:"type";s:5:"label";}}i:4;a:5:{s:1:"A";a:1:{s:4:"type";s:5:"label";}s:1:"B";a:2:{s:4:"type";s:8:"checkbox";s:4:"name";s:13:"checkonlydirs";}s:1:"C";a:3:{s:4:"type";s:5:"label";s:5:"label";s:9:"directory";s:4:"name";s:8:"dirlabel";}s:1:"D";a:4:{s:4:"type";s:8:"checkbox";s:5:"label";s:5:"Debug";s:4:"name";s:5:"debug";s:8:"disabled";s:1:"1";}s:1:"E";a:1:{s:4:"type";s:5:"label";}}i:5;a:5:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:5:"label";s:15:"created between";s:4:"name";s:12:"createdlabel";}s:1:"B";a:2:{s:4:"type";s:8:"checkbox";s:4:"name";s:13:"searchcreated";}s:1:"C";a:3:{s:4:"type";s:4:"date";s:4:"name";s:15:"datecreatedfrom";s:4:"size";s:2:",8";}s:1:"D";a:3:{s:4:"type";s:4:"date";s:4:"name";s:13:"datecreatedto";s:4:"size";s:2:",8";}s:1:"E";a:4:{s:4:"type";s:8:"textarea";s:4:"name";s:17:"searchcreatedtext";s:8:"readonly";s:1:"1";s:7:"no_lang";s:1:"1";}}i:6;a:5:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:5:"label";s:16:"modified between";s:4:"name";s:13:"modifiedlabel";}s:1:"B";a:2:{s:4:"type";s:8:"checkbox";s:4:"name";s:14:"searchmodified";}s:1:"C";a:3:{s:4:"type";s:4:"date";s:4:"name";s:16:"datemodifiedfrom";s:4:"size";s:2:",8";}s:1:"D";a:3:{s:4:"type";s:4:"date";s:4:"name";s:14:"datemodifiedto";s:4:"size";s:2:",8";}s:1:"E";a:4:{s:4:"type";s:8:"textarea";s:4:"name";s:18:"searchmodifiedtext";s:8:"readonly";s:1:"1";s:7:"no_lang";s:1:"1";}}}s:4:"rows";i:6;s:4:"cols";i:5;}i:2;a:1:{s:4:"type";s:5:"hrule";}i:3;a:3:{s:4:"type";s:9:"nextmatch";s:4:"size";s:4:"rows";s:4:"name";s:2:"nm";}}','size' => '','style' => '','modified' => '1173101430',); $templ_data[] = array('name' => 'filemanager.search.rows','template' => '','lang' => '','group' => '0','version' => '','data' => 'a:1:{i:0;a:6:{s:4:"type";s:4:"grid";s:4:"data";a:3:{i:0;a:2:{s:2:"c1";s:2:"th";s:2:"c2";s:3:"row";}i:1;a:8:{s:1:"A";a:3:{s:4:"type";s:20:"nextmatch-sortheader";s:5:"label";s:2:"Id";s:4:"name";s:11:"vfs_file_id";}s:1:"B";a:3:{s:4:"type";s:5:"label";s:5:"label";s:4:"file";s:4:"name";s:7:"fulldir";}s:1:"C";a:3:{s:4:"type";s:20:"nextmatch-sortheader";s:5:"label";s:9:"Directory";s:4:"name";s:13:"vfs_directory";}s:1:"D";a:3:{s:4:"type";s:20:"nextmatch-sortheader";s:5:"label";s:4:"name";s:4:"name";s:8:"vfs_name";}s:1:"E";a:3:{s:4:"type";s:20:"nextmatch-sortheader";s:5:"label";s:7:"comment";s:4:"name";s:11:"vfs_comment";}s:1:"F";a:3:{s:4:"type";s:20:"nextmatch-sortheader";s:5:"label";s:9:"mime type";s:4:"name";s:13:"vfs_mime_type";}s:1:"G";a:3:{s:4:"type";s:20:"nextmatch-sortheader";s:5:"label";s:7:"created";s:4:"name";s:11:"vfs_created";}s:1:"H";a:3:{s:4:"type";s:20:"nextmatch-sortheader";s:5:"label";s:8:"modified";s:4:"name";s:12:"vfs_modified";}}i:2;a:8:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:4:"name";s:19:"${row}[vfs_file_id]";s:7:"no_lang";s:1:"1";}s:1:"B";a:3:{s:4:"type";s:4:"html";s:4:"name";s:15:"${row}[fulldir]";s:7:"no_lang";s:1:"1";}s:1:"C";a:3:{s:4:"type";s:4:"html";s:4:"name";s:21:"${row}[vfs_directory]";s:7:"no_lang";s:1:"1";}s:1:"D";a:3:{s:4:"type";s:5:"label";s:4:"name";s:16:"${row}[vfs_name]";s:7:"no_lang";s:1:"1";}s:1:"E";a:3:{s:4:"type";s:5:"label";s:4:"name";s:19:"${row}[vfs_comment]";s:7:"no_lang";s:1:"1";}s:1:"F";a:3:{s:4:"type";s:5:"label";s:4:"name";s:21:"${row}[vfs_mime_type]";s:7:"no_lang";s:1:"1";}s:1:"G";a:3:{s:4:"type";s:5:"label";s:4:"name";s:19:"${row}[vfs_created]";s:7:"no_lang";s:1:"1";}s:1:"H";a:3:{s:4:"type";s:5:"label";s:4:"name";s:20:"${row}[vfs_modified]";s:7:"no_lang";s:1:"1";}}}s:4:"rows";i:2;s:4:"cols";i:8;s:4:"size";s:9:"100%,auto";s:7:"options";a:2:{i:0;s:4:"100%";i:1;s:4:"auto";}}}','size' => '100%,auto','style' => '','modified' => '1173104345',); diff --git a/filemanager/templates/default/app.css b/filemanager/templates/default/app.css index 6137f054f5..e58ecf8d73 100644 --- a/filemanager/templates/default/app.css +++ b/filemanager/templates/default/app.css @@ -1,41 +1,48 @@ -/* - CSS for the filemanager -*/ - -#fmStatusBar -{ - margin-left:4px; - margin-bottom:3px; -} - -.fmButton -{ - background-repeat: no-repeat; - background-image:url(../default/images/buttonbackground.png); - width:28px; - height:28px; -} - -#fmLocation -{ - position:relative; - margin-bottom:3px; - height:27px; -} - -#fmMenu -{ - position:relative; -} - -#fmFileWindow -{ - background-color:#ffffff; - margin-left:4px; - padding:5px; - position:relative; - border-right: #cccccc 1px solid; - border-top: #9c9c9c 2px solid; - border-left: #9c9c9c 2px solid; - border-bottom: #cccccc 1px solid -} +/** + * CSS for new eTemplate filemanager UI + */ + +.perms { font-family: monospace; font-weight: bold; } +.address input { font-size: 140%; font-weight: bold; } + +/* + CSS for the filemanager +*/ + +#fmStatusBar +{ + margin-left:4px; + margin-bottom:3px; +} + +.fmButton +{ + background-repeat: no-repeat; + background-image:url(../default/images/buttonbackground.png); + width:28px; + height:28px; +} + +#fmLocation +{ + position:relative; + margin-bottom:3px; + height:27px; +} + +#fmMenu +{ + position:relative; +} + +#fmFileWindow +{ + background-color:#ffffff; + margin-left:4px; + padding:5px; + position:relative; + border-right: #cccccc 1px solid; + border-top: #9c9c9c 2px solid; + border-left: #9c9c9c 2px solid; + border-bottom: #cccccc 1px solid +} diff --git a/filemanager/templates/default/index.xet b/filemanager/templates/default/index.xet new file mode 100644 index 0000000000..224d42037f --- /dev/null +++ b/filemanager/templates/default/index.xet @@ -0,0 +1,90 @@ + + + + + + \ No newline at end of file diff --git a/phpgwapi/inc/class.egw_vfs.inc.php b/phpgwapi/inc/class.egw_vfs.inc.php index 3648fd277d..f326507144 100644 --- a/phpgwapi/inc/class.egw_vfs.inc.php +++ b/phpgwapi/inc/class.egw_vfs.inc.php @@ -59,6 +59,7 @@ */ class egw_vfs extends vfs_stream_wrapper { + const PREFIX = 'vfs://default'; /** * Readable bit, for dirs traversable */ @@ -97,7 +98,7 @@ class egw_vfs extends vfs_stream_wrapper { throw new egw_exception_assertion_failed("Filename '$path' is not an absolute path!"); } - return fopen(self::SCHEME.'://default'.$path); + return fopen(self::SCHEME.'://default'.$path,$mode); } /** @@ -129,7 +130,7 @@ class egw_vfs extends vfs_stream_wrapper if (($from_fp = self::fopen($from,'r')) && ($to_fp = self::fopen($to,'w'))) { - $ret = stream_copy_to_stream($from,$to) !== false; + $ret = stream_copy_to_stream($from_fp,$to_fp) !== false; } if ($from_fp) { @@ -154,7 +155,22 @@ class egw_vfs extends vfs_stream_wrapper { throw new egw_exception_assertion_failed("File '$path' is not an absolute path!"); } - return self::url_stat($path,0); + if (($stat = self::url_stat($path,0))) + { + $stat = array_slice($stat,13); // remove numerical indices 0-12 + } + return $stat; + } + + /** + * is_dir() version working only inside the vfs + * + * @param string $path + * @return boolean + */ + static function is_dir($path) + { + return $path[0] == '/' && is_dir(self::SCHEME.'://default'.$path); } @@ -224,7 +240,8 @@ class egw_vfs extends vfs_stream_wrapper * @param string/array $base base of the search * @param array $options=null the following keys are allowed: * - type => {d|f} d=dirs, f=files, default both - * - dirs_last => {true|false(default)} put the dirs behind the files they contain + * - depth => {true|false(default)} put the contents of a dir before the dir itself + * - mindepth,maxdepth minimal or maximal depth to be returned * - name,path => pattern with *,? wildcards, eg. "*.php" * - name_preg,path_preg => preg regular expresion, eg. "/(vfs|wrapper)/" * - uid,user,gid,group,nouser,nogroup file belongs to user/group with given name or (numerical) id @@ -232,18 +249,20 @@ class egw_vfs extends vfs_stream_wrapper * - empty,size => (+|-|)N * - cmin/mmin => (+|-|)N file/dir create/modified in the last N minutes * - ctime/mtime => (+|-|)N file/dir created/modified in the last N days + * - depth => (+|-)N + * - url => false(default),true allow (and return) full URL's instead of VFS pathes (only set it, if you know what you doing securitywise!) * @param string/array/true $exec=null function to call with each found file or dir as first param or * true to return file => stat pairs * @param array $exec_params=null further params for exec as array, path is always the first param! * @return array of pathes if no $exec, otherwise path => stat pairs */ - function find($base,$options=null,$exec=null,$exec_params=null) + static function find($base,$options=null,$exec=null,$exec_params=null) { //error_log(__METHOD__."(".print_r($base,true).",".print_r($options,true).",".print_r($exec,true).",".print_r($exec_params,true).")\n"); $type = $options['type']; // 'd' or 'f' - $dirs_last = $options['dirs_last']; // list dirs after the files they contain - + $dirs_last = $options['depth']; // put content of dirs before the dir itself + // process some of the options (need to be done only once) if (isset($options['name']) && !isset($options['name_preg'])) // change from simple *,? wildcards to preg regular expression once { @@ -275,6 +294,7 @@ class egw_vfs extends vfs_stream_wrapper $options['gid'] = 0; } } + $url = $options['url']; if (!is_array($base)) { @@ -295,23 +315,30 @@ class egw_vfs extends vfs_stream_wrapper $result = array(); foreach($base as $path) { + if (!$url) $path = egw_vfs::PREFIX . $path; + $is_dir = is_dir($path); - if (!$dirs_last || !$is_dir) + if ((int)$options['mindepth'] == 0 && (!$dirs_last || !$is_dir)) { self::_check_add($options,$path,$result); } - if ($is_dir && ($dir = opendir($path))) + if ($is_dir && (!isset($options['maxdepth']) || $options['maxdepth'] > 0) && ($dir = @opendir($path))) { while($file = readdir($dir)) { $file = $path.'/'.$file; - self::_check_add($options,$file,$result); - - if (is_dir($file)) + if ((int)$options['mindepth'] <= 1) { - foreach(self::find($file,$options,true) as $p => $s) + self::_check_add($options,$file,$result,1); + } + if (is_dir($file) && (!isset($options['maxdepth']) || $options['maxdepth'] > 1)) + { + $opts = $options; + if ($opts['mindepth']) $opts['mindepth']--; + if ($opts['maxdepth']) $opts['maxdepth']++; + foreach(self::find($options['url']?$file:parse_url($file,PHP_URL_PATH),$opts,true) as $p => $s) { unset($result[$p]); $result[$p] = $s; @@ -319,14 +346,13 @@ class egw_vfs extends vfs_stream_wrapper } } closedir($dir); - - if ($dirs_last) - { - self::_check_add($options,$path,$result); - } + } + if ($is_dir && (int)$options['mindepth'] == 0 && $dirs_last) + { + self::_check_add($options,$path,$result); } } - //_debug_array($result); + //echo $path; _debug_array($result); if ($exec !== true && is_callable($exec)) { if (!is_array($exec_params)) @@ -342,6 +368,7 @@ class egw_vfs extends vfs_stream_wrapper } return $result; } + //echo "egw_vfs::find($path)="; _debug_array(array_keys($result)); if ($exec !== true) { return array_keys($result); @@ -356,7 +383,7 @@ class egw_vfs extends vfs_stream_wrapper * @param string $path name of path to add * @param array &$result here we add the stat for the key $path, if the checks are successful */ - private function _check_add($options,$path,&$result) + private static function _check_add($options,$path,&$result) { $type = $options['type']; // 'd' or 'f' @@ -368,7 +395,7 @@ class egw_vfs extends vfs_stream_wrapper { return; // not found, should not happen } - if (isset($options['name_preg']) && !preg_match($options['name_preg'],basename($path)) || + if (isset($options['name_preg']) && !preg_match($options['name_preg'],self::basename($path)) || isset($options['path_preg']) && !preg_match($options['path_preg'],$path)) { return; // wrong name or path @@ -399,10 +426,15 @@ class egw_vfs extends vfs_stream_wrapper { return; // not create/modified in the spezified time } + // do we return url or just vfs pathes + if (!$options['url']) + { + $path = parse_url($path,PHP_URL_PATH); + } $result[$path] = $stat; } - private function _check_num($value,$argument) + private static function _check_num($value,$argument) { if (is_int($argument) && $argument >= 0 || $argument[0] != '-' && $argument[0] != '+') { @@ -417,7 +449,7 @@ class egw_vfs extends vfs_stream_wrapper //echo "_check_num($value,$argument) check > == ".(int)($value > (int)substr($argument,1))."\n"; return $value > (int) substr($argument,1); } - + /** * Recursiv remove all given url's, including it's content if they are files * @@ -426,7 +458,7 @@ class egw_vfs extends vfs_stream_wrapper */ static function remove($urls) { - return self::find($urls,array('dirs_last'=>true),array(__CLASS__,'_rm_rmdir')); + return self::find($urls,array('depth'=>true),array(__CLASS__,'_rm_rmdir')); } /** @@ -671,6 +703,32 @@ class egw_vfs extends vfs_stream_wrapper return $sP; } + + /** + * Human readable size values in k or M + * + * @param int $size + * @return string + */ + static function hsize($size) + { + if ($size < 1024) return $size; + if ($size < 1024*1024) return sprintf('%3.1lfk',(float)$size/1024); + return sprintf('%3.1lfM',(float)$size/(1024*1024)); + } + + /** + * like basename($path), but also working if the 1. char of the basename is non-ascii + * + * @param string $path + * @return string + */ + static function basename($path) + { + $parts = explode('/',$path); + + return array_pop($parts); + } } egw_vfs::$user = (int) $GLOBALS['egw_info']['user']['account_id']; diff --git a/phpgwapi/inc/class.sqlfs_stream_wrapper.inc.php b/phpgwapi/inc/class.sqlfs_stream_wrapper.inc.php index c99dcd2401..55fd995c4b 100644 --- a/phpgwapi/inc/class.sqlfs_stream_wrapper.inc.php +++ b/phpgwapi/inc/class.sqlfs_stream_wrapper.inc.php @@ -177,14 +177,14 @@ class sqlfs_stream_wrapper implements iface_stream_wrapper // new file --> create it in the DB if ($this->operation == self::STORE2FS) { - $stmt = self::$pdo->prepare('INSERT INTO '.self::TABLE.' (fs_name,fs_dir,fs_mode,fs_uid,fs_gid,fs_created,fs_modified,fs_creator'. + $stmt = self::$pdo->prepare($query='INSERT INTO '.self::TABLE.' (fs_name,fs_dir,fs_mode,fs_uid,fs_gid,fs_created,fs_modified,fs_creator'. ') VALUES (:fs_name,:fs_dir,:fs_mode,:fs_uid,:fs_gid,:fs_created,:fs_modified,:fs_creator)'); } else { - $stmt = self::$pdo->prepare('INSERT INTO '.self::TABLE.' (fs_name,fs_dir,fs_mode,fs_uid,fs_gid,fs_created,fs_modified,fs_creator,fs_content'. + $stmt = self::$pdo->prepare($query='INSERT INTO '.self::TABLE.' (fs_name,fs_dir,fs_mode,fs_uid,fs_gid,fs_created,fs_modified,fs_creator,fs_content'. ') VALUES (:fs_name,:fs_dir,:fs_mode,:fs_uid,:fs_gid,:fs_created,:fs_modified,:fs_creator,:fs_content)'); - $stmt->bindParam(':fs_content',$this->open_stream,PDO::PARAM_LOB); + $stmt->bindParam(':fs_content',$this->opened_stream,PDO::PARAM_LOB); } $values = array( 'fs_name' => basename($path), @@ -203,8 +203,12 @@ class sqlfs_stream_wrapper implements iface_stream_wrapper { $stmt->bindParam(':'.$name,$val); } - $stmt->execute(); - $this->opened_fs_id = self::$pdo->lastInsertId('fs_id'); + if (!$stmt->execute() || !($this->opened_fs_id = self::$pdo->lastInsertId('fs_id'))) + { + $this->opened_stream = $this->opened_path = $this->opened_mode = null; + echo self::$pdo->errorInfo()."\n"; + return false; + } } else { @@ -242,7 +246,7 @@ class sqlfs_stream_wrapper implements iface_stream_wrapper { if (self::LOG_LEVEL > 1) error_log(__METHOD__."()"); - if (is_null($this->opened_path) || !is_resource($this->opened_stream)) + if (is_null($this->opened_path) || !is_resource($this->opened_stream) || !$this->opened_fs_id) { return false; } @@ -813,13 +817,15 @@ class sqlfs_stream_wrapper implements iface_stream_wrapper $this->opened_dir = null; return false; } - self::$stat_cache = $this->opened_dir = array(); + $this->opened_dir = array(); $query = 'SELECT fs_id,fs_name,fs_mode,fs_uid,fs_gid,fs_size,fs_mime,fs_created,fs_modified FROM '.self::TABLE.' WHERE fs_dir=?'; // only return readable files, if dir is not writable by user if (!egw_vfs::check_access($stat,egw_vfs::WRITABLE)) { $query .= ' AND '.self::_sql_readable(); } + $query = "/* sqlfs::dir_opendir($path) */ ".$query; + $stmt = self::$pdo->prepare($query); $stmt->setFetchMode(PDO::FETCH_ASSOC); if ($stmt->execute(array($stat['ino']))) @@ -906,6 +912,7 @@ class sqlfs_stream_wrapper implements iface_stream_wrapper $query = str_replace('fs_name=?','fs_name='.self::$pdo->quote($name),$base_query).'('.$query.')'; } } + $query = "/* sqlfs::url_stat($path) */ ".$query; //echo "query=$query\n"; if (!($result = self::$pdo->query($query)) || !($info = $result->fetch(PDO::FETCH_ASSOC))) @@ -954,8 +961,8 @@ class sqlfs_stream_wrapper implements iface_stream_wrapper if (!is_array($this->opened_dir)) return false; $file = current($this->opened_dir); next($this->opened_dir); - - return $file ? $file : false; + + return $file; } /** @@ -1036,7 +1043,24 @@ class sqlfs_stream_wrapper implements iface_stream_wrapper $dsn = $server['db_type'].':host='.$server['db_host'].';dbname='.$server['db_name']; break; } - return self::$pdo = new PDO($dsn,$server['db_user'],$server['db_pass']); + self::$pdo = new PDO($dsn,$server['db_user'],$server['db_pass']); + + // set client charset of the connection + $charset = $GLOBALS['egw']->translation->charset(); + switch($server['db_type']) + { + case 'mysql': + if (isset($GLOBALS['egw']->db->Link_ID->charset2mysql[$charset])) $charset = $GLOBALS['egw']->db->Link_ID->charset2mysql[$charset]; + // fall throught + case 'pgsql': + $query = "SET NAMES '$charset'"; + break; + } + if ($query) + { + self::$pdo->exec($query); + } + return self::$pdo; } /** diff --git a/phpgwapi/inc/class.vfs_stream_wrapper.inc.php b/phpgwapi/inc/class.vfs_stream_wrapper.inc.php index 385b2ac7f5..e5f15b2105 100644 --- a/phpgwapi/inc/class.vfs_stream_wrapper.inc.php +++ b/phpgwapi/inc/class.vfs_stream_wrapper.inc.php @@ -504,7 +504,7 @@ class vfs_stream_wrapper implements iface_stream_wrapper static $mime_magic; if (is_null($mime_magic)) { - $mime_magic = mime_magic(); + $mime_magic = new mime_magic(); } $mime = $mime_magic->filename2mime(parse_url($url,PHP_URL_PATH)); }