mConfig['$_REQUEST['ajax_path_conf']] is used as 'jail'. * Paths outside this 'jail' will be ignored including ../../ or symbolic links. * Evil extensions as defined in EVIL_EXTENSION_PATTERN will be ignored as are [dot] files e.g.: .private.txt * * e.g.: * /home/ftp/public/ is the 'jail' * /home/ftp/public/ftp -> /home/ftp/ is a symbolic link that points outside the 'jail' and will therefore be ignored completely. * Also makes it impossible to import stuff like /home/ftp/public/../../../../../etc/passwd * * You can define ajax_path_conf in two places with different effects: * 1. define the ajax_path_conf when you include the template: * {include file="bitpackage:kernel/ajax_file_browser.tpl" ajax_path_conf=treasury_file_import_path} * This will show a link to "Load Files" which will then load the file list when you click on the link. * 2. If you provide $_REQUEST['ajax_path_conf'] when you include it from your php file, all files in the root directory will already be loaded. * $_REQUEST['ajax_path_conf'] = 'treasury_file_import_path'; * require_once( KERNEL_PKG_PATH.'ajax_file_browser.php' ); * * NOTE: when you process the imported files, make sure you use realpath() to check of files are really in your 'jail'. */ require_once 'setup_inc.php'; // we need to set these global that we can include this file from functions global $gBitThemes, $gBitSystem, $gBitSmarty; if( !empty( $_REQUEST['ajax_path_conf'] ) && $gBitSystem->isFeatureActive( $_REQUEST['ajax_path_conf'] ) ) { $fileList = ajax_dir_list( $gBitSystem->getConfig( $_REQUEST['ajax_path_conf'] ), !empty( $_REQUEST['relpath'] ) ? $_REQUEST['relpath'] . "/" : null); $gBitSmarty->assign( 'fileList', $fileList ); } $gBitThemes->loadJavascript( KERNEL_PKG_PATH."scripts/BitFileBrowser.js", true ); if( $gBitThemes->isAjaxRequest() ) { $gBitSmarty->display( 'bitpackage:kernel/ajax_file_browser_inc.tpl' ); } /** * ajax_dir_list * * @param string $pDir Base directory * @param string $pRelPath relative path on top of base directory * @access public * @return array */ function ajax_dir_list( $pDir, $pRelPath = null ) { global $gBitSystem; $ret = $files = []; if( !empty( $pDir ) && is_dir( $pDir.$pRelPath )) { if( $handle = opendir( $pDir.$pRelPath )) { while( false !== ( $file = readdir( $handle ))) { if( !preg_match( "#^\.#",$file ) && is_readable( $pDir.$pRelPath.$file )) { array_push( $files, $file ); } } sort( $files ); foreach( $files as $i ) { $relFile = $pRelPath.$i; $file = realpath( $pDir.$relFile ); if( strpos( $file, $pDir ) === 0 ) { $info = [ 'name' => $i, 'relpath' => $relFile, 'indent' => ( count( explode( '/', $relFile )) * 10 ), 'size' => filesize( $file ), 'mtime' => filemtime( $file ), ]; if( is_dir( $file )) { $ret['dir'][$i] = $info; } elseif( !preg_match( EVIL_EXTENSION_PATTERN, $file )) { $ret['file'][$i] = $info; } } } closedir( $handle ); } } if( empty( $ret )) { $ret['file'][] = [ 'indent' => ( count( explode( '/', $pRelPath )) * 10 ), ]; } return $ret; }