├── webint ├── version.ini ├── layout │ ├── templates │ │ ├── footer.tpl.php │ │ ├── login.tpl.php │ │ ├── header.tpl.php │ │ ├── config.tpl.php │ │ └── browser.tpl.php │ ├── images │ │ ├── icons.png │ │ ├── upload.gif │ │ ├── toplogo.png │ │ └── fancybox │ │ │ ├── blank.gif │ │ │ ├── fancybox.png │ │ │ ├── fancy_close.png │ │ │ ├── fancybox-x.png │ │ │ ├── fancybox-y.png │ │ │ ├── fancy_loading.png │ │ │ ├── fancy_nav_left.png │ │ │ ├── fancy_shadow_e.png │ │ │ ├── fancy_shadow_n.png │ │ │ ├── fancy_shadow_s.png │ │ │ ├── fancy_shadow_w.png │ │ │ ├── fancy_nav_right.png │ │ │ ├── fancy_shadow_ne.png │ │ │ ├── fancy_shadow_nw.png │ │ │ ├── fancy_shadow_se.png │ │ │ ├── fancy_shadow_sw.png │ │ │ ├── fancy_title_left.png │ │ │ ├── fancy_title_main.png │ │ │ ├── fancy_title_over.png │ │ │ └── fancy_title_right.png │ └── css │ │ ├── media.css │ │ ├── baseline.compress.css │ │ ├── style.css │ │ └── fancybox.css ├── system │ ├── config │ │ ├── config.php │ │ └── config.org.php │ ├── savant │ │ ├── Savant3 │ │ │ ├── Exception.php │ │ │ ├── Plugin.php │ │ │ ├── resources │ │ │ │ ├── Savant3_Plugin_htmlAttribs.php │ │ │ │ ├── Savant3_Plugin_ahref.php │ │ │ │ ├── Savant3_Plugin_date.php │ │ │ │ ├── Savant3_Filter_trimwhitespace.php │ │ │ │ └── Savant3_Plugin_image.php │ │ │ ├── Filter.php │ │ │ └── Error.php │ │ └── Savant3.php │ ├── classes │ │ ├── Filesystem.php │ │ ├── Gui.php │ │ ├── Security.php │ │ └── Upload.php │ └── js │ │ ├── fancybox.js │ │ └── fileuploader.js ├── upload.php ├── ajax.php └── index.php └── README.md /webint/version.ini: -------------------------------------------------------------------------------- 1 | [Version] 2 | latest=0.2.3 -------------------------------------------------------------------------------- /webint/layout/templates/footer.tpl.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /webint/layout/images/icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FTPbox/Web-Interface/HEAD/webint/layout/images/icons.png -------------------------------------------------------------------------------- /webint/layout/images/upload.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FTPbox/Web-Interface/HEAD/webint/layout/images/upload.gif -------------------------------------------------------------------------------- /webint/layout/images/toplogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FTPbox/Web-Interface/HEAD/webint/layout/images/toplogo.png -------------------------------------------------------------------------------- /webint/layout/images/fancybox/blank.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FTPbox/Web-Interface/HEAD/webint/layout/images/fancybox/blank.gif -------------------------------------------------------------------------------- /webint/layout/images/fancybox/fancybox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FTPbox/Web-Interface/HEAD/webint/layout/images/fancybox/fancybox.png -------------------------------------------------------------------------------- /webint/layout/images/fancybox/fancy_close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FTPbox/Web-Interface/HEAD/webint/layout/images/fancybox/fancy_close.png -------------------------------------------------------------------------------- /webint/layout/images/fancybox/fancybox-x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FTPbox/Web-Interface/HEAD/webint/layout/images/fancybox/fancybox-x.png -------------------------------------------------------------------------------- /webint/layout/images/fancybox/fancybox-y.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FTPbox/Web-Interface/HEAD/webint/layout/images/fancybox/fancybox-y.png -------------------------------------------------------------------------------- /webint/layout/images/fancybox/fancy_loading.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FTPbox/Web-Interface/HEAD/webint/layout/images/fancybox/fancy_loading.png -------------------------------------------------------------------------------- /webint/layout/images/fancybox/fancy_nav_left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FTPbox/Web-Interface/HEAD/webint/layout/images/fancybox/fancy_nav_left.png -------------------------------------------------------------------------------- /webint/layout/images/fancybox/fancy_shadow_e.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FTPbox/Web-Interface/HEAD/webint/layout/images/fancybox/fancy_shadow_e.png -------------------------------------------------------------------------------- /webint/layout/images/fancybox/fancy_shadow_n.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FTPbox/Web-Interface/HEAD/webint/layout/images/fancybox/fancy_shadow_n.png -------------------------------------------------------------------------------- /webint/layout/images/fancybox/fancy_shadow_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FTPbox/Web-Interface/HEAD/webint/layout/images/fancybox/fancy_shadow_s.png -------------------------------------------------------------------------------- /webint/layout/images/fancybox/fancy_shadow_w.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FTPbox/Web-Interface/HEAD/webint/layout/images/fancybox/fancy_shadow_w.png -------------------------------------------------------------------------------- /webint/layout/images/fancybox/fancy_nav_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FTPbox/Web-Interface/HEAD/webint/layout/images/fancybox/fancy_nav_right.png -------------------------------------------------------------------------------- /webint/layout/images/fancybox/fancy_shadow_ne.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FTPbox/Web-Interface/HEAD/webint/layout/images/fancybox/fancy_shadow_ne.png -------------------------------------------------------------------------------- /webint/layout/images/fancybox/fancy_shadow_nw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FTPbox/Web-Interface/HEAD/webint/layout/images/fancybox/fancy_shadow_nw.png -------------------------------------------------------------------------------- /webint/layout/images/fancybox/fancy_shadow_se.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FTPbox/Web-Interface/HEAD/webint/layout/images/fancybox/fancy_shadow_se.png -------------------------------------------------------------------------------- /webint/layout/images/fancybox/fancy_shadow_sw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FTPbox/Web-Interface/HEAD/webint/layout/images/fancybox/fancy_shadow_sw.png -------------------------------------------------------------------------------- /webint/layout/images/fancybox/fancy_title_left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FTPbox/Web-Interface/HEAD/webint/layout/images/fancybox/fancy_title_left.png -------------------------------------------------------------------------------- /webint/layout/images/fancybox/fancy_title_main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FTPbox/Web-Interface/HEAD/webint/layout/images/fancybox/fancy_title_main.png -------------------------------------------------------------------------------- /webint/layout/images/fancybox/fancy_title_over.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FTPbox/Web-Interface/HEAD/webint/layout/images/fancybox/fancy_title_over.png -------------------------------------------------------------------------------- /webint/layout/images/fancybox/fancy_title_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FTPbox/Web-Interface/HEAD/webint/layout/images/fancybox/fancy_title_right.png -------------------------------------------------------------------------------- /webint/system/config/config.php: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /webint/system/config/config.org.php: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /webint/upload.php: -------------------------------------------------------------------------------- 1 | handleUpload($_GET['path'].'/'); 8 | echo htmlspecialchars(json_encode($result), ENT_NOQUOTES); 9 | } 10 | ?> 11 | -------------------------------------------------------------------------------- /webint/ajax.php: -------------------------------------------------------------------------------- 1 | renderResults($filesystem->read($_GET['absolutePath'], $_GET['relativePath'], $_GET['sortName'], $_GET['sortOrder'])); 9 | ?> 10 | -------------------------------------------------------------------------------- /webint/layout/templates/login.tpl.php: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 5 | 6 | 7 |
8 |
9 |
10 | -------------------------------------------------------------------------------- /webint/system/savant/Savant3/Exception.php: -------------------------------------------------------------------------------- 1 | 9 | * 10 | * @license http://www.gnu.org/copyleft/lesser.html LGPL 11 | * 12 | * @version $Id: Exception.php,v 1.1 2005/05/27 14:04:36 pmjones Exp $ 13 | * 14 | */ 15 | 16 | 17 | /** 18 | * 19 | * A simple Savant3_Exception class. 20 | * 21 | * @package Savant3 22 | * 23 | * @author Paul M. Jones 24 | * 25 | */ 26 | 27 | class Savant3_Exception extends Exception { 28 | } 29 | ?> -------------------------------------------------------------------------------- /webint/layout/templates/header.tpl.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | absolutePath)): ?> 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 27 | -------------------------------------------------------------------------------- /webint/system/savant/Savant3/Plugin.php: -------------------------------------------------------------------------------- 1 | 10 | * 11 | * @license http://www.gnu.org/copyleft/lesser.html LGPL 12 | * 13 | * @version $Id: Plugin.php,v 1.5 2005/04/29 16:23:50 pmjones Exp $ 14 | * 15 | */ 16 | 17 | /** 18 | * 19 | * Abstract Savant3_Plugin class. 20 | * 21 | * You have to extend this class for it to be useful; e.g., "class 22 | * Savant3_Plugin_example extends Savant2_Plugin". Be sure to add a 23 | * method named for the plugin itself; e.g., "function example()". 24 | * 25 | * @package Savant3 26 | * 27 | * @author Paul M. Jones 28 | * 29 | */ 30 | 31 | abstract class Savant3_Plugin { 32 | 33 | /** 34 | * 35 | * Reference to the calling Savant object. 36 | * 37 | * @access protected 38 | * 39 | * @var object 40 | * 41 | */ 42 | 43 | protected $Savant = null; 44 | 45 | 46 | /** 47 | * 48 | * Constructor. 49 | * 50 | * @access public 51 | * 52 | * @param array $conf An array of configuration keys and values for 53 | * this plugin. 54 | * 55 | * @return void 56 | * 57 | */ 58 | 59 | public function __construct($conf = null) 60 | { 61 | settype($conf, 'array'); 62 | foreach ($conf as $key => $val) { 63 | $this->$key = $val; 64 | } 65 | } 66 | } 67 | ?> -------------------------------------------------------------------------------- /webint/system/savant/Savant3/resources/Savant3_Plugin_htmlAttribs.php: -------------------------------------------------------------------------------- 1 | 10 | * 11 | * @license http://www.gnu.org/copyleft/lesser.html LGPL 12 | * 13 | * @version $Id: Savant3_Plugin_htmlAttribs.php,v 1.3 2005/09/12 17:49:27 pmjones Exp $ 14 | * 15 | */ 16 | 17 | /** 18 | * 19 | * Plugin to convert an associative array to a string of tag attributes. 20 | * 21 | * @package Savant3 22 | * 23 | * @author Paul M. Jones 24 | * 25 | */ 26 | 27 | class Savant3_Plugin_htmlAttribs extends Savant3_Plugin { 28 | 29 | /** 30 | * 31 | * Converts an associative array to a string of tag attributes. 32 | * 33 | * @access public 34 | * 35 | * @param array $attribs From this array, each key-value pair is 36 | * converted to an attribute name and value. 37 | * 38 | * @return string The XHTML for the attributes. 39 | * 40 | */ 41 | 42 | public function htmlAttribs($attribs) 43 | { 44 | $xhtml = ''; 45 | foreach ((array) $attribs as $key => $val) { 46 | 47 | if ($val === null) { 48 | continue; 49 | } 50 | 51 | if (is_array($val)) { 52 | $val = implode(' ', $val); 53 | } 54 | 55 | $key = htmlspecialchars($key); 56 | $val = htmlspecialchars($val); 57 | 58 | $xhtml .= " $key=\"$val\""; 59 | } 60 | return $xhtml; 61 | } 62 | } 63 | ?> -------------------------------------------------------------------------------- /webint/system/savant/Savant3/Filter.php: -------------------------------------------------------------------------------- 1 | 10 | * 11 | * @license http://www.gnu.org/copyleft/lesser.html LGPL 12 | * 13 | * @version $Id: Filter.php,v 1.5 2005/04/29 16:23:50 pmjones Exp $ 14 | * 15 | */ 16 | 17 | /** 18 | * 19 | * Abstract Savant3_Filter class. 20 | * 21 | * You have to extend this class for it to be useful; e.g., "class 22 | * Savant3_Filter_example extends Savant3_Filter". 23 | * 24 | * @package Savant3 25 | * 26 | * @author Paul M. Jones 27 | * 28 | */ 29 | 30 | abstract class Savant3_Filter { 31 | 32 | 33 | /** 34 | * 35 | * Optional reference to the calling Savant object. 36 | * 37 | * @access protected 38 | * 39 | * @var object 40 | * 41 | */ 42 | 43 | protected $Savant = null; 44 | 45 | 46 | /** 47 | * 48 | * Constructor. 49 | * 50 | * @access public 51 | * 52 | * @param array $conf An array of configuration keys and values for 53 | * this filter. 54 | * 55 | * @return void 56 | * 57 | */ 58 | 59 | public function __construct($conf = null) 60 | { 61 | settype($conf, 'array'); 62 | foreach ($conf as $key => $val) { 63 | $this->$key = $val; 64 | } 65 | } 66 | 67 | 68 | /** 69 | * 70 | * Stub method for extended behaviors. 71 | * 72 | * @access public 73 | * 74 | * @param string $text The text buffer to filter. 75 | * 76 | * @return string The text buffer after it has been filtered. 77 | * 78 | */ 79 | 80 | public static function filter($text) 81 | { 82 | return $text; 83 | } 84 | } 85 | ?> -------------------------------------------------------------------------------- /webint/layout/templates/config.tpl.php: -------------------------------------------------------------------------------- 1 | 15 |
16 |
17 | 18 | content['status'])): ?> 19 |
content['status']; ?>
20 | 21 | 22 | content['locked'] === 'true'): ?>checked="checked" /> 23 | 24 | 25 | 26 | 28 | 29 | 30 | 31 | 32 |
33 |
34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | FTPbox Web-Interface 2 | ============= 3 | 4 | About 5 | -------------- 6 | 7 | This repository contains all the files needed for the Web Interface to work. This is mainly for development purposes. If you want to install the WebUI, head to the options and select to use it, the program will install it automatically! 8 | 9 | 10 | Development 11 | ============= 12 | 13 | To-Do 14 | -------------- 15 | 16 | - Open/Show file content inside the UI, no need to use a direct link 17 | - New icons, maybe Fugue Icons ( http://p.yusukekamiyamane.com ) 18 | - Option to copy a file's direct link to clipboard 19 | - Fix post_max_size and upload_max_filesize errors when uploading 20 | - Password should be required to access the settings 21 | - Optional: if deleting is publicly enabled for a UI that isn't pass-protected 22 | 23 | 24 | Installing 25 | ============= 26 | 27 | Uploading 28 | -------------- 29 | 30 | The uploading process has been automated with the FTPbox program to save you the trouble. If you have troubles or just want to do it manually, here's how: 31 | You only need to upload all the files to your folder of preference (using an FTP client, etc). If you're using webint.zip from the downloads, you'll have to extract its contents first and then upload them. 32 | 33 | *If you want the FTPbox program to ignore the WebUI files during synchronization and save some time, put them in a folder named 'webint'.* 34 | 35 | Setup 36 | -------------- 37 | 38 | To setup the WebUI, launch your browser and visit the HTTP path of the folder in which you uploaded the WebUI files. You'll be prompted with a form to password-protect the interface. 39 | **It is highly recommend that you use a password to protect your files.** 40 | Finish this simple form and you're ready to use the WebUI. 41 | 42 | Requirements 43 | -------------- 44 | 45 | The requirements to use the WebUI are: 46 | 47 | - PHP version 5 or later installed. 48 | - HTTP access to your WebUI folder -------------------------------------------------------------------------------- /webint/index.php: -------------------------------------------------------------------------------- 1 | dirname($_SERVER['SCRIPT_FILENAME']).'/layout/templates' 8 | ); 9 | $tpl = new Savant3($conf); 10 | $security = new Security; 11 | $gui = new Gui; 12 | $filesystem = new Filesystem; 13 | $gui->filesystem = $filesystem; 14 | switch($security->checkAuth(isset($_REQUEST['config']))) { 15 | case 'config': 16 | if(isset($_POST['root'])) { 17 | $status = $security->setConfig(array('root' => $_POST['root'], 'locked' => (isset($_POST['locked']))?'true':'false', 'password' => $_POST['password'], 'password_repeat' => $_POST['password_repeat'])); 18 | } else { 19 | $status = ''; 20 | } 21 | $tpl->content = $gui->renderConfig($security->config, $status); 22 | $content = 'config.tpl.php'; 23 | break; 24 | case 'login': 25 | if(isset($_POST['password'])) $retry = $security->checkLogin($_POST['password']); 26 | $tpl->content = $gui->renderLogin(isset($retry)); 27 | $content = 'login.tpl.php'; 28 | break; 29 | case 'browser': 30 | $security->checkPath(); 31 | if(isset($_POST['submit_delete'])) { 32 | unset($_POST['submit_delete'], $_POST['p']); 33 | $filesystem->delete($security->absolutePath, $_POST); 34 | } 35 | $tpl->absolutePath = $security->absolutePath; 36 | $tpl->relativePath = $security->relativePath; 37 | $tpl->sortName = (isset($_GET['sortName'])?$_GET['sortName']:'filename'); 38 | $tpl->sortOrder = (isset($_GET['sortOrder'])?$_GET['sortOrder']:'asc'); 39 | $tpl->content = $gui->renderResults($filesystem->read($security->absolutePath, $security->relativePath, $tpl->sortName, $tpl->sortOrder)); 40 | $tpl->up = $gui->renderUp($filesystem->dirUp($security->relativePath), $security->config['root']); 41 | $content = 'browser.tpl.php'; 42 | break; 43 | } 44 | $tpl->display('header.tpl.php'); 45 | $tpl->display($content); 46 | $tpl->display('footer.tpl.php'); 47 | ?> 48 | -------------------------------------------------------------------------------- /webint/system/savant/Savant3/Error.php: -------------------------------------------------------------------------------- 1 | 10 | * 11 | * @license http://www.gnu.org/copyleft/lesser.html LGPL 12 | * 13 | * @version $Id: Error.php,v 1.5 2005/05/27 14:03:50 pmjones Exp $ 14 | * 15 | */ 16 | 17 | /** 18 | * 19 | * Provides a simple error class for Savant. 20 | * 21 | * @package Savant3 22 | * 23 | * @author Paul M. Jones 24 | * 25 | */ 26 | 27 | class Savant3_Error { 28 | 29 | 30 | /** 31 | * 32 | * The error code, typically a Savant 'ERR_*' string. 33 | * 34 | * @access public 35 | * 36 | * @var string 37 | * 38 | */ 39 | 40 | public $code = null; 41 | 42 | 43 | /** 44 | * 45 | * An array of error-specific information. 46 | * 47 | * @access public 48 | * 49 | * @var array 50 | * 51 | */ 52 | 53 | public $info = array(); 54 | 55 | 56 | /** 57 | * 58 | * The error severity level. 59 | * 60 | * @access public 61 | * 62 | * @var int 63 | * 64 | */ 65 | 66 | public $level = E_USER_ERROR; 67 | 68 | 69 | /** 70 | * 71 | * A debug backtrace for the error, if any. 72 | * 73 | * @access public 74 | * 75 | * @var array 76 | * 77 | */ 78 | 79 | public $trace = null; 80 | 81 | 82 | /** 83 | * 84 | * Constructor. 85 | * 86 | * @access public 87 | * 88 | * @param array $conf An associative array where the key is a 89 | * Savant3_Error property and the value is the value for that 90 | * property. 91 | * 92 | */ 93 | 94 | public function __construct($conf = array()) 95 | { 96 | // set public properties 97 | foreach ($conf as $key => $val) { 98 | $this->$key = $val; 99 | } 100 | 101 | // add a backtrace 102 | if ($conf['trace'] === true) { 103 | $this->trace = debug_backtrace(); 104 | } 105 | } 106 | 107 | 108 | /** 109 | * 110 | * Magic method for output dump. 111 | * 112 | * @access public 113 | * 114 | * @return void 115 | */ 116 | 117 | public function __toString() 118 | { 119 | ob_start(); 120 | echo get_class($this) . ': '; 121 | print_r(get_object_vars($this)); 122 | return ob_get_clean(); 123 | } 124 | } 125 | ?> -------------------------------------------------------------------------------- /webint/system/classes/Filesystem.php: -------------------------------------------------------------------------------- 1 | $field) { 23 | if($field == 'asc') { 24 | $args[$n] = SORT_ASC; 25 | $field = $args[$n]; 26 | } 27 | if($field == 'desc') { 28 | $args[$n] = SORT_DESC; 29 | $field = $args[$n]; 30 | } 31 | if(is_string($field)) { 32 | $tmp = array(); 33 | foreach ($data as $key => $row) $tmp[$key] = strtolower($row[$field]); 34 | $args[$n] = $tmp; 35 | } 36 | } 37 | $args[] = &$data; 38 | call_user_func_array('array_multisort', $args); 39 | return array_pop($args); 40 | } 41 | 42 | public function read($absolutePath, $relativePath, $sortName='filename', $sortOrder=SORT_ASC) { 43 | for($list = array(), $handle = opendir($absolutePath); (FALSE !== ($file = readdir($handle)));) { 44 | if(($file != '.' && $file != '..' && $file != 'webint') && (file_exists($path = $absolutePath.DIRECTORY_SEPARATOR.$file))) { 45 | $entry = array('filename' => $file, 'permission' => substr(sprintf('%o', fileperms($path)), -4)); 46 | $entry['modtime'] = filemtime($path); 47 | do if(!is_dir($path)) { 48 | $entry['size'] = filesize($path); 49 | $entry['mode'] = 'file'; 50 | $entry['dirpath'] = $relativePath.DIRECTORY_SEPARATOR.$file; 51 | break; 52 | } else { 53 | $entry['size'] = ''; 54 | $entry['mode'] = 'folder'; 55 | $entry['dirpath'] = urlencode($relativePath.DIRECTORY_SEPARATOR.$file); 56 | break; 57 | } while (FALSE); 58 | $list[] = $entry; 59 | } 60 | } 61 | closedir($handle); 62 | $list = $this->sortArray($list, 'mode', 'desc', $sortName, $sortOrder); 63 | return $list; 64 | } 65 | 66 | public function delete($absolutePath, $files) { 67 | foreach($files as $file => $on) { 68 | $file = $absolutePath.'/'.$this->decodeString($file); 69 | if(!is_writeable($file)) die('You are not allowed to delete this file'); 70 | if(is_dir($file)) rmdir($file); 71 | if(is_file($file)) unlink($file); 72 | } 73 | } 74 | } 75 | ?> 76 | -------------------------------------------------------------------------------- /webint/system/savant/Savant3/resources/Savant3_Plugin_ahref.php: -------------------------------------------------------------------------------- 1 | ... tag. 6 | * 7 | * @package Savant3 8 | * 9 | * @author Paul M. Jones 10 | * 11 | * @license http://www.gnu.org/copyleft/lesser.html LGPL 12 | * 13 | * @version $Id: Savant3_Plugin_ahref.php,v 1.4 2005/08/09 12:56:14 pmjones Exp $ 14 | * 15 | */ 16 | 17 | /** 18 | * 19 | * Generates an ... tag. 20 | * 21 | * @package Savant3 22 | * 23 | * @author Paul M. Jones 24 | * 25 | */ 26 | 27 | class Savant3_Plugin_ahref extends Savant3_Plugin { 28 | 29 | /** 30 | * 31 | * Generate an HTML ... tag. 32 | * 33 | * @access public 34 | * 35 | * @param string|array $href A string URL for the resulting tag. May 36 | * also be an array with any combination of the keys 'scheme', 37 | * 'host', 'path', 'query', and 'fragment' (c.f. PHP's native 38 | * parse_url() function). 39 | * 40 | * @param string $text The displayed text of the link. 41 | * 42 | * @param string|array $attr Any extra attributes for the tag. 43 | * 44 | * @return string The ... tag. 45 | * 46 | */ 47 | 48 | public function ahref($href, $text, $attr = null) 49 | { 50 | $html = ' $val) { 95 | $key = htmlspecialchars($key); 96 | $val = htmlspecialchars($val); 97 | $html .= " $key=\"$val\""; 98 | } 99 | } elseif (! is_null($attr)) { 100 | // from scalar 101 | $html .= htmlspecialchars(" $attr"); 102 | } 103 | 104 | // set the link text, close the tag, and return 105 | $html .= '>' . $text . ''; 106 | return $html; 107 | } 108 | } 109 | ?> -------------------------------------------------------------------------------- /webint/system/savant/Savant3/resources/Savant3_Plugin_date.php: -------------------------------------------------------------------------------- 1 | 10 | * 11 | * @license http://www.gnu.org/copyleft/lesser.html LGPL 12 | * 13 | * @version $Id: Savant3_Plugin_date.php,v 1.3 2005/03/07 14:40:16 pmjones Exp $ 14 | * 15 | */ 16 | 17 | /** 18 | * 19 | * Plugin to generate a formatted date using strftime() conventions. 20 | * 21 | * @package Savant3 22 | * 23 | * @author Paul M. Jones 24 | * 25 | */ 26 | 27 | class Savant3_Plugin_date extends Savant3_Plugin { 28 | 29 | /** 30 | * 31 | * The default strftime() format string. 32 | * 33 | * @access public 34 | * 35 | * @var array 36 | * 37 | */ 38 | 39 | public $default = '%c'; 40 | 41 | 42 | /** 43 | * 44 | * Custom strftime() format strings to use for dates. 45 | * 46 | * You can preset the format strings via Savant3::setPluginConf(). 47 | * 48 | * 49 | * $conf = array( 50 | * 'custom' => array( 51 | * 'mydate' => '%Y-%m-%d', 52 | * 'mytime' => '%R' 53 | * ) 54 | * ); 55 | * 56 | * $Savant->setPluginConf('date', $conf); 57 | * 58 | * 59 | * ... and in your template, to use a preset custom string by name: 60 | * 61 | * 62 | * echo $this->date($value, 'mydate'); 63 | * 64 | * 65 | * @access public 66 | * 67 | * @var array 68 | * 69 | */ 70 | 71 | public $custom = array( 72 | 'date' => '%Y-%m-%d', 73 | 'time' => '%H:%M:%S' 74 | ); 75 | 76 | 77 | /** 78 | * 79 | * Outputs a formatted date using strftime() conventions. 80 | * 81 | * @access public 82 | * 83 | * @param string $datestring Any date-time string suitable for 84 | * strtotime(). 85 | * 86 | * @param string $format The strftime() formatting string, or a named 87 | * custom string key from $this->custom. 88 | * 89 | * @return string The formatted date string. 90 | * 91 | */ 92 | 93 | function date($datestring, $format = null) 94 | { 95 | settype($format, 'string'); 96 | 97 | if (is_null($format)) { 98 | $format = $this->default; 99 | } 100 | 101 | // does the format string have a % sign in it? 102 | if (strpos($format, '%') === false) { 103 | // no, look for a custom format string 104 | if (! empty($this->custom[$format])) { 105 | // found a custom format string 106 | $format = $this->custom[$format]; 107 | } else { 108 | // did not find the custom format, revert to default 109 | $format = $this->default; 110 | } 111 | } 112 | 113 | // convert the date string to the specified format 114 | if (trim($datestring != '')) { 115 | return strftime($format, strtotime($datestring)); 116 | } else { 117 | // no datestring, return VOID 118 | return; 119 | } 120 | } 121 | 122 | } 123 | ?> -------------------------------------------------------------------------------- /webint/system/classes/Gui.php: -------------------------------------------------------------------------------- 1 | filesystem->dirUp(getcwd()); 27 | } else { 28 | $array['root'] = $config['root']; 29 | } 30 | $array['root_label'] = 'Rootpath'; 31 | return $array; 32 | } 33 | 34 | public function renderLogin($retry = false) { 35 | if($retry) { 36 | $string = 'Please try again!'; 37 | } else { 38 | $string = 'Please enter your password'; 39 | } 40 | return $string; 41 | } 42 | 43 | public function renderResults($result) { 44 | $string = ''; 45 | foreach ($result as $file) { 46 | $string .= '
'; 47 | if($file['mode'] != 'up') $string .= ''; 48 | 49 | if($file['mode'] == 'file') { 50 | if (substr($file['dirpath'], 0, 1) == '/') 51 | $string .= '
'; 52 | else 53 | $string .= '
'; 54 | } 55 | else if ($file['mode'] == 'folder') $string .= '
'; 56 | 57 | if(isset($file['permission'])) $string .= $file['permission']; 58 | $string .= '
'; 59 | if(!empty($file['size'])) $string .= $this->formatfilesize($file['size']); 60 | $string .= '
'; 61 | if(isset($file['modtime'])) { 62 | if(time() - $file['modtime'] < 60 * 60 * 12) { 63 | $string .= date('H:i',$file['modtime']); 64 | } else { 65 | $string .= date('d.m.Y',$file['modtime']); 66 | } 67 | } 68 | $string .= '
'; 69 | } 70 | return $string; 71 | } 72 | 73 | public function renderUp($dir, $root){ 74 | if(strlen(getcwd()) > strlen($root)) { 75 | $string = 'Up'; 76 | } else { 77 | $string = ''; 78 | } 79 | return $string; 80 | } 81 | } 82 | ?> 83 | -------------------------------------------------------------------------------- /webint/system/classes/Security.php: -------------------------------------------------------------------------------- 1 | getConfig(); 11 | } 12 | 13 | public function checkAuth($edit) { 14 | if($this->config['locked'] === 'false' || $this->checkSession()) { 15 | if(empty($this->config['root']) || !is_dir($this->config['root']) || $edit) { 16 | return 'config'; 17 | } else { 18 | return 'browser'; 19 | } 20 | } else { 21 | return 'login'; 22 | } 23 | } 24 | 25 | public function checkLogin($password) { 26 | if(md5($password) === $this->config['password']) { 27 | $this->setSession($password); 28 | Header("Location: index.php"); 29 | } else { 30 | return true; 31 | } 32 | } 33 | 34 | private function checkSession() { 35 | if(isset($_SESSION['sid']) && $_SESSION['sid'] == session_id() && isset($_SESSION['password']) && $_SESSION['password'] == $this->config['password']) { 36 | return true; 37 | } 38 | } 39 | 40 | private function getConfig() { 41 | $root = $_SERVER['DOCUMENT_ROOT']; 42 | require_once('system/config/config.php'); 43 | $this->config = $config; 44 | } 45 | 46 | public function checkPath() { 47 | $path = ''; 48 | if(isset($_REQUEST['p'])) { 49 | $path = $_REQUEST['p']; 50 | } 51 | if(substr($path, 0, 1) == DIRECTORY_SEPARATOR) { 52 | $path = substr($path, 1); 53 | } 54 | if(is_dir($this->config['root'].$path) && !strpos($path, '..'.DIRECTORY_SEPARATOR)) { 55 | $this->absolutePath = $this->config['root'].$path; 56 | chdir($this->absolutePath); 57 | $this->relativePath = $path; 58 | } else { 59 | die('No access!'); 60 | } 61 | } 62 | 63 | public function setConfig($array) { 64 | if(!is_writable('system/config/config.php')) { 65 | return 'You are not allowed to change the config'; 66 | } 67 | if(!empty($array['password']) && $array['locked'] == 'false') { 68 | return 'Please check "Protect the interface with a password" if you want to set a password'; 69 | } 70 | if($array['password'] !== $array['password_repeat']) { 71 | return 'Please enter the same password'; 72 | } 73 | if(!is_dir($array['root'])) { 74 | return 'Your root path doesn\'t exist'; 75 | } 76 | unset($array['password_repeat']); 77 | $lines = file('system/config/config.php'); 78 | foreach($array as $key => $value) { 79 | if($this->config[$key] != $value && !empty($value)) { 80 | if($key == 'root' && substr($value, -1) != DIRECTORY_SEPARATOR) { 81 | $value .= DIRECTORY_SEPARATOR; 82 | } 83 | if($key == 'password') { 84 | $value = md5($value); 85 | } 86 | $lines = $this->writeConfig($key, $value, $lines); 87 | } 88 | } 89 | $handle = fopen('system/config/config.php', 'w'); 90 | fwrite($handle, implode($lines)); 91 | fclose($handle); 92 | Header("Location: index.php"); 93 | } 94 | 95 | private function writeConfig($key, $value, $lines) { 96 | foreach($lines as $linekey => $line) { 97 | if(strstr($line, '$config[\''.$key.'\']')) { 98 | $lines[$linekey] = '$config[\''.$key.'\'] = \''.$value.'\';'."\n"; 99 | $this->config[$key] = $value; 100 | } 101 | } 102 | return $lines; 103 | } 104 | 105 | private function setSession($password) { 106 | $_SESSION['sid'] = session_id(); 107 | $_SESSION['password'] = md5($password); 108 | } 109 | } 110 | ?> 111 | -------------------------------------------------------------------------------- /webint/layout/templates/browser.tpl.php: -------------------------------------------------------------------------------- 1 | 62 |
63 | 67 |
68 | up; ?> 69 |
70 | 71 | 72 |
73 |
74 | Upload 75 | 76 |
77 |
78 |
79 |
80 | 81 | 82 | 83 | 84 |
85 |
86 | content; ?> 87 |
88 |
89 | -------------------------------------------------------------------------------- /webint/system/savant/Savant3/resources/Savant3_Filter_trimwhitespace.php: -------------------------------------------------------------------------------- 1 | 10 | * 11 | * @author Contributions from Lars Noschinski 12 | * 13 | * @author Converted to a Savant3 filter by Paul M. Jones 14 | * 15 | * @license http://www.gnu.org/copyleft/lesser.html LGPL 16 | * 17 | * @version $Id: Savant3_Filter_trimwhitespace.php,v 1.4 2005/05/29 15:27:07 pmjones Exp $ 18 | * 19 | */ 20 | 21 | /** 22 | * 23 | * Filter to remove extra white space within the text. 24 | * 25 | * @package Savant3 26 | * 27 | * @author Monte Ohrt 28 | * 29 | * @author Contributions from Lars Noschinski 30 | * 31 | * @author Converted to a Savant3 filter by Paul M. Jones 32 | * 33 | */ 34 | 35 | class Savant3_Filter_trimwhitespace extends Savant3_Filter { 36 | 37 | 38 | /** 39 | * 40 | * Removes extra white space within the text. 41 | * 42 | * Trim leading white space and blank lines from template source 43 | * after it gets interpreted, cleaning up code and saving bandwidth. 44 | * Does not affect
, , or
 45 | 	*  blocks.
 46 | 	* 
 47 | 	* @access public
 48 | 	* 
 49 | 	* @param string $buffer The source text to be filtered.
 50 | 	* 
 51 | 	* @return string The filtered text.
 52 | 	* 
 53 | 	*/
 54 | 	
 55 | 	public static function filter($buffer)
 56 | 	{
 57 | 		// Pull out the script blocks
 58 | 		preg_match_all("!]+>.*?!is", $buffer, $match);
 59 | 		$script_blocks = $match[0];
 60 | 		$buffer = preg_replace(
 61 | 			"!]+>.*?!is",
 62 | 			'@@@SAVANT:TRIM:SCRIPT@@@',
 63 | 			$buffer
 64 | 		);
 65 | 	
 66 | 		// Pull out the pre blocks
 67 | 		preg_match_all("!]*>.*?!is", $buffer, $match);
 68 | 		$pre_blocks = $match[0];
 69 | 		$buffer = preg_replace(
 70 | 			"!]*>.*?!is",
 71 | 			'@@@SAVANT:TRIM:PRE@@@',
 72 | 			$buffer
 73 | 		);
 74 | 	
 75 | 		// Pull out the textarea blocks
 76 | 		preg_match_all("!]+>.*?!is", $buffer, $match);
 77 | 		$textarea_blocks = $match[0];
 78 | 		$buffer = preg_replace(
 79 | 			"!]+>.*?!is",
 80 | 			'@@@SAVANT:TRIM:TEXTAREA@@@',
 81 | 			$buffer
 82 | 		);
 83 | 	
 84 | 		// remove all leading spaces, tabs and carriage returns NOT
 85 | 		// preceeded by a php close tag.
 86 | 		$buffer = trim(preg_replace('/((?)\n)[\s]+/m', '\1', $buffer));
 87 | 	
 88 | 		// replace script blocks
 89 | 		Savant3_Filter_trimwhitespace::replace(
 90 | 			"@@@SAVANT:TRIM:SCRIPT@@@",
 91 | 			$script_blocks,
 92 | 			$buffer
 93 | 		);
 94 | 	
 95 | 		// replace pre blocks
 96 | 		Savant3_Filter_trimwhitespace::replace(
 97 | 			"@@@SAVANT:TRIM:PRE@@@",
 98 | 			$pre_blocks,
 99 | 			$buffer
100 | 		);
101 | 	
102 | 		// replace textarea blocks
103 | 		Savant3_Filter_trimwhitespace::replace(
104 | 			"@@@SAVANT:TRIM:TEXTAREA@@@",
105 | 			$textarea_blocks,
106 | 			$buffer
107 | 		);
108 | 	
109 | 		return $buffer;
110 | 	}
111 | 	
112 | 	
113 | 	/**
114 | 	* 
115 | 	* Does a simple search-and-replace on the source text.
116 | 	* 
117 | 	* @access protected
118 | 	* 
119 | 	* @param string $search The string to search for.
120 | 	* 
121 | 	* @param string $replace Replace with this text.
122 | 	* 
123 | 	* @param string &$buffer The source text.
124 | 	* 
125 | 	* @return string The text after search-and-replace.
126 | 	* 
127 | 	*/
128 | 	
129 | 	protected static function replace($search, $replace, &$buffer)
130 | 	{
131 | 		$len = strlen($search);
132 | 		$pos = 0;
133 | 		$count = count($replace);
134 | 		
135 | 		for ($i = 0; $i < $count; $i++) {
136 | 			// does the search-string exist in the buffer?
137 | 			$pos = strpos($buffer, $search, $pos);
138 | 			if ($pos !== false) {
139 | 				// replace the search-string
140 | 				$buffer = substr_replace($buffer, $replace[$i], $pos, $len);
141 | 			} else {
142 | 				break;
143 | 			}
144 | 		}
145 | 	}
146 | }
147 | ?>


--------------------------------------------------------------------------------
/webint/system/classes/Upload.php:
--------------------------------------------------------------------------------
  1 | getSize()){            
 14 |             return false;
 15 |         }
 16 |         
 17 |         $target = fopen($path, "w");        
 18 |         fseek($temp, 0, SEEK_SET);
 19 |         stream_copy_to_stream($temp, $target);
 20 |         fclose($target);
 21 |         
 22 |         return true;
 23 |     }
 24 |     function getName() {
 25 |         return $_GET['qqfile'];
 26 |     }
 27 |     function getSize() {
 28 |         if (isset($_SERVER["CONTENT_LENGTH"])){
 29 |             return (int)$_SERVER["CONTENT_LENGTH"];            
 30 |         } else {
 31 |             throw new Exception('Getting content length is not supported.');
 32 |         }      
 33 |     }   
 34 | }
 35 | 
 36 | /**
 37 |  * Handle file uploads via regular form post (uses the $_FILES array)
 38 |  */
 39 | class FileForm {  
 40 |     /**
 41 |      * Save the file to the specified path
 42 |      * @return boolean TRUE on success
 43 |      */
 44 |     function save($path) {
 45 |         if(!move_uploaded_file($_FILES['qqfile']['tmp_name'], $path)){
 46 |             return false;
 47 |         }
 48 |         return true;
 49 |     }
 50 |     function getName() {
 51 |         return $_FILES['qqfile']['name'];
 52 |     }
 53 |     function getSize() {
 54 |         return $_FILES['qqfile']['size'];
 55 |     }
 56 | }
 57 | 
 58 | class Upload {
 59 |     private $allowedExtensions = array();
 60 |     private $sizeLimit = 10485760;
 61 |     private $file;
 62 | 
 63 |     function __construct(array $allowedExtensions = array(), $sizeLimit = 10485760){        
 64 |         $allowedExtensions = array_map("strtolower", $allowedExtensions);
 65 |             
 66 |         $this->allowedExtensions = $allowedExtensions;        
 67 |         $this->sizeLimit = $sizeLimit;
 68 |         
 69 |         $this->checkServerSettings();       
 70 | 
 71 |         if (isset($_GET['qqfile'])) {
 72 |             $this->file = new FileXhr();
 73 |         } elseif (isset($_FILES['qqfile'])) {
 74 |             $this->file = new FileForm();
 75 |         } else {
 76 |             $this->file = false; 
 77 |         }
 78 |     }
 79 |     
 80 |     private function checkServerSettings(){        
 81 |         $postSize = $this->toBytes(ini_get('post_max_size'));
 82 |         $uploadSize = $this->toBytes(ini_get('upload_max_filesize'));        
 83 |         
 84 |         if ($postSize < $this->sizeLimit || $uploadSize < $this->sizeLimit){
 85 |             $size = max(1, $this->sizeLimit / 1024 / 1024) . 'M';             
 86 |             die("{'error':'increase post_max_size and upload_max_filesize to $size'}");    
 87 |         }        
 88 |     }
 89 |     
 90 |     private function toBytes($str){
 91 |         $val = trim($str);
 92 |         $last = strtolower($str[strlen($str)-1]);
 93 |         switch($last) {
 94 |             case 'g': $val *= 1024;
 95 |             case 'm': $val *= 1024;
 96 |             case 'k': $val *= 1024;        
 97 |         }
 98 |         return $val;
 99 |     }
100 |     
101 |     /**
102 |      * Returns array('success'=>true) or array('error'=>'error message')
103 |      */
104 |     function handleUpload($uploadDirectory, $replaceOldFile = FALSE){
105 |         if (!is_writable($uploadDirectory)){
106 |             return array('error' => "Server error. Upload directory isn't writable.");
107 |         }
108 |         
109 |         if (!$this->file){
110 |             return array('error' => 'No files were uploaded.');
111 |         }
112 |         
113 |         $size = $this->file->getSize();
114 |         
115 |         if ($size == 0) {
116 |             return array('error' => 'File is empty');
117 |         }
118 |         
119 |         if ($size > $this->sizeLimit) {
120 |             return array('error' => 'File is too large');
121 |         }
122 |         
123 |         $pathinfo = pathinfo($this->file->getName());
124 |         $filename = $pathinfo['filename'];
125 |         //$filename = md5(uniqid());
126 |         $ext = $pathinfo['extension'];
127 | 
128 |         if($this->allowedExtensions && !in_array(strtolower($ext), $this->allowedExtensions)){
129 |             $these = implode(', ', $this->allowedExtensions);
130 |             return array('error' => 'File has an invalid extension, it should be one of '. $these . '.');
131 |         }
132 |         
133 |         if(!$replaceOldFile){
134 |             /// don't overwrite previous files that were uploaded
135 |             while (file_exists($uploadDirectory . $filename . '.' . $ext)) {
136 |                 $filename .= rand(10, 99);
137 |             }
138 |         }
139 |         
140 |         if ($this->file->save($uploadDirectory . $filename . '.' . $ext)){
141 |             return array('success'=>true);
142 |         } else {
143 |             return array('error'=> 'Could not save uploaded file.' .
144 |                 'The upload was cancelled, or server error encountered');
145 |         }
146 |         
147 |     }    
148 | }
149 | ?>
150 | 


--------------------------------------------------------------------------------
/webint/system/savant/Savant3/resources/Savant3_Plugin_image.php:
--------------------------------------------------------------------------------
  1 |  tag.
  6 | * 
  7 | * @package Savant3
  8 | * 
  9 | * @author Paul M. Jones 
 10 | * 
 11 | * @license http://www.gnu.org/copyleft/lesser.html LGPL
 12 | * 
 13 | * @version $Id: Savant3_Plugin_image.php,v 1.7 2005/08/12 14:34:09 pmjones Exp $
 14 | *
 15 | */
 16 | 
 17 | /**
 18 | * 
 19 | * Plugin to generate an  tag.
 20 | *
 21 | * Support for alpha transparency of PNG files in Microsoft IE added by
 22 | * Edward Ritter; thanks, Edward.
 23 | * 
 24 | * @package Savant3
 25 | * 
 26 | * @author Paul M. Jones 
 27 | * 
 28 | */
 29 | 
 30 | class Savant3_Plugin_image extends Savant3_Plugin {
 31 | 	
 32 | 	
 33 | 	/**
 34 | 	* 
 35 | 	* The document root.
 36 | 	* 
 37 | 	* @access public
 38 | 	* 
 39 | 	* @var string
 40 | 	* 
 41 | 	*/
 42 | 	
 43 | 	protected $documentRoot = null;
 44 | 	
 45 | 	
 46 | 	/**
 47 | 	* 
 48 | 	* The base directory for images within the document root.
 49 | 	* 
 50 | 	* @access public
 51 | 	* 
 52 | 	* @var string
 53 | 	* 
 54 | 	*/
 55 | 	
 56 | 	protected $imageDir = null;
 57 | 	
 58 | 	
 59 | 	/**
 60 | 	* 
 61 | 	* Outputs an  tag.
 62 | 	* 
 63 | 	* Microsoft IE alpha PNG support added by Edward Ritter.
 64 | 	* 
 65 | 	* @access public
 66 | 	* 
 67 | 	* @param string $file The path to the image on the local file system
 68 | 	* relative to $this->imageDir.
 69 | 	* 
 70 | 	* @param string $alt Alternative descriptive text for the image;
 71 | 	* defaults to the filename of the image.
 72 | 	* 
 73 | 	* @param int $border The border width for the image; defaults to zero.
 74 | 	* 
 75 | 	* @param int $width The displayed image width in pixels; defaults to
 76 | 	* the width of the image.
 77 | 	* 
 78 | 	* @param int $height The displayed image height in pixels; defaults to
 79 | 	* the height of the image.
 80 | 	* 
 81 | 	* @return string An  tag.
 82 | 	* 
 83 | 	*/
 84 | 	
 85 | 	public function image($file, $alt = null, $height = null, $width = null,
 86 | 		$attr = null)
 87 | 	{
 88 | 		// is the document root set?
 89 | 		if (is_null($this->documentRoot) && isset($_SERVER['DOCUMENT_ROOT'])) {
 90 | 			// no, so set it
 91 | 			$this->documentRoot = $_SERVER['DOCUMENT_ROOT'];
 92 | 		}
 93 | 		
 94 | 		// make sure there's a DIRECTORY_SEPARATOR between the docroot
 95 | 		// and the image dir
 96 | 		if (substr($this->documentRoot, -1) != DIRECTORY_SEPARATOR &&
 97 | 			substr($this->imageDir, 0, 1) != DIRECTORY_SEPARATOR) {
 98 | 			$this->documentRoot .= DIRECTORY_SEPARATOR;
 99 | 		}
100 | 		
101 | 		// make sure there's a separator between the imageDir and the
102 | 		// file name
103 | 		if (substr($this->imageDir, -1) != DIRECTORY_SEPARATOR &&
104 | 			substr($file, 0, 1) != DIRECTORY_SEPARATOR) {
105 | 			$this->imageDir .= DIRECTORY_SEPARATOR;
106 | 		}
107 | 		
108 | 		// the image file type code (PNG = 3)
109 | 		$type = null;
110 | 		
111 | 		// get the file information
112 | 		$info = false;
113 | 		
114 | 		if (strpos($file, '://') === false) {
115 | 			// no "://" in the file, so it's local
116 | 			$file = $this->imageDir . $file;
117 | 			$tmp = $this->documentRoot . $file;
118 | 			$info = @getimagesize($tmp);
119 | 		} else {
120 | 			// don't attempt to get file info from streams, it takes
121 | 			// way too long.
122 | 			$info = false;
123 | 		}
124 | 		
125 | 		// did we find the file info?
126 | 		if (is_array($info)) {
127 | 		
128 | 			// capture type info regardless
129 | 			$type = $info[2];
130 | 			
131 | 			// capture size info where both not specified
132 | 			if (is_null($width) && is_null($height)) {
133 | 				$width = $info[0];
134 | 				$height = $info[1];
135 | 			}
136 | 		}
137 | 		
138 | 		// clean up
139 | 		unset($info);
140 | 		
141 | 		// is the file a PNG? if so, check user agent, we will need to
142 | 		// make special allowances for Microsoft IE.
143 | 		if (stristr($_SERVER['HTTP_USER_AGENT'], 'MSIE') && $type === 3) {
144 | 			
145 | 			// support alpha transparency for PNG files in MSIE
146 | 			$html = 'Savant->htmlAttribs($attr);
161 | 
162 | 			// done
163 | 			$html .= '>';
164 | 			
165 | 		} else {
166 | 			
167 | 			// not IE, so build a normal image tag.
168 | 			$html = 'Savant->htmlAttribs($attr);
188 | 			
189 | 			// done
190 | 			$html .= ' />';
191 | 			
192 | 		}
193 | 		
194 | 		// done!
195 | 		return $html;
196 | 	}
197 | }
198 | 
199 | ?>


--------------------------------------------------------------------------------
/webint/layout/css/media.css:
--------------------------------------------------------------------------------
  1 | @media screen and (max-width: 1024px) {
  2 | 
  3 | 	#page {
  4 | 		width: 100%;
  5 | 	}
  6 | 	
  7 | 	#head{
  8 | 		float:none;
  9 | 	}
 10 | 	
 11 | 	#head, #page form {
 12 | 		width: 98%;
 13 | 		margin-left: auto;
 14 | 	}
 15 | 	
 16 | 	#page form{
 17 | 		float: none;
 18 | 	}
 19 | 	
 20 | 	#toolbox, #browser_head, #browser {
 21 | 		width: 98%;
 22 | 		margin: 0 auto;
 23 | 	}
 24 | 	
 25 | 	#toolbox_path input[type="text"] {
 26 | 		width: 90%;
 27 | 	}
 28 | 	
 29 | 	#browser_head_link{
 30 | 		width: 50%;
 31 | 		border-right: none;
 32 | 	}
 33 | 	
 34 | 	.row{
 35 | 		width: 98%;
 36 | 	}
 37 | 	
 38 | 	#toolbox{
 39 | 		padding: 0;
 40 | 	}
 41 | 	
 42 | 	.details-link{
 43 | 		width: 40%;
 44 | 	}
 45 | 	
 46 | 	#login  {
 47 | 		margin-left: auto;
 48 | 		margin-right: auto;
 49 | 		width: 410px;
 50 | 		float: none;
 51 | 	}
 52 | 	
 53 | 	#login_01_01 {
 54 | 		
 55 | 	}
 56 | 	
 57 | 	#login_01_02 {
 58 | 		
 59 | 	}
 60 | 	
 61 | 	#toolbox_path_submit{
 62 | 		float: right;		
 63 | 	}
 64 | 	
 65 | 	#toolbox_path{
 66 | 		width: 60%;
 67 | 	}
 68 | 	
 69 | 	#browser_head_permission, .details-permission{
 70 | 		display: none;
 71 | 	}
 72 | 	
 73 | 	#browser_head_modtime, #browser_head_size{
 74 | 		float: right;
 75 | 		text-align: center;
 76 | 	}
 77 | 	
 78 | 	#browser_head_size{
 79 | 		border-left: 1px solid #BBB;
 80 | 		border-right: none;
 81 | 	}
 82 | 	
 83 | 	#browser_head_modtime{
 84 | 		border-left: 1px solid #BBB;
 85 | 		border-right: 1px solid white;
 86 | 	}
 87 | 	
 88 | 	#browser_head_modtime a{
 89 | 		margin: 0 auto;
 90 | 	}
 91 | 	
 92 | 	.details-modtime, .details-size{
 93 | 		float:right;
 94 | 		text-align: center;
 95 | 	}
 96 | 	
 97 | 	.details-modtime{
 98 | 		position: absolute; 
 99 | 		right: 70px;
100 | 		
101 | 		width: 118px;
102 | 	}	
103 | 	
104 | 	#details-size{
105 | 		width:60px;
106 | 	}
107 | 	
108 | 	/* Config */
109 | 	
110 | 	#config{
111 | 		margin-right: auto;
112 | 		margin-left: auto;
113 | 		width: 410px;
114 | 		float: none;
115 | 	}
116 | 	
117 | 	#head_settings{
118 | 		margin-right: 10px;
119 | 	}
120 | }
121 | 
122 | @media screen and (max-width: 650px) {
123 | 
124 | 	/*
125 | 	#page {
126 | 		width: 98%;		
127 | 	}
128 | 	
129 | 	#head {
130 | 		width: 95%;
131 | 	}
132 | 	
133 | 	#login  {
134 | 		width: 95%;
135 | 		margin: 10% 0px;
136 | 	}
137 | 	
138 | 	#login_01_01 {
139 | 		width: 100%;		
140 | 	}
141 | 	
142 | 	#login_01_02 {
143 | 		width: 70%;		
144 | 	}
145 | 	
146 | 	#toolbox_buttons .button{
147 | 		float: right;
148 | 		position: relative;
149 | 		margin: 0 4px;
150 | 	}
151 | 	
152 | 	#toolbox_path{
153 | 		position: absolute;
154 | 		margin-left: 3px;
155 | 		right: 3px;
156 | 		float: none;
157 | 	}
158 | 	*/
159 | }
160 | 
161 | @media screen and (max-width: 480px) {
162 | 
163 | 	#page {
164 | 		width: 95%;		
165 | 	}
166 | 	
167 | 	#head {
168 | 		width: auto;
169 | 		float: none;
170 | 	}
171 | 	
172 | 	#head_logo{
173 | 		margin: 0 auto;
174 | 		width: 100%;		
175 | 	} 
176 | 	
177 | 	#head_logo a{
178 | 		margin: 0 auto;
179 | 	}
180 | 	
181 | 	#head_settings{
182 | 		display: none;
183 | 	}
184 | 	
185 | 	#page form {
186 | 		width: 100%;
187 | 		margin: 0;
188 | 		display: block;
189 | 		margin-top: 40px;
190 | 	}
191 | 	
192 | 	#login  {
193 | 		width: auto;
194 | 		margin-top: 10%;
195 | 		margin-left: 0px;
196 | 		margin-right: 0px;
197 | 	}
198 | 	
199 | 	#login_01 {
200 | 		float: none;
201 | 		width: 90%;
202 | 	}
203 | 	
204 | 	#login_01_01 {
205 | 		width: auto;
206 | 		margin: 0 5%;
207 | 	}
208 | 	
209 | 	#login_01_02 {
210 | 		width: 90%;		
211 | 		margin: 10px 5%;
212 | 	}
213 | 	
214 | 	#login_01_03{
215 | 		margin: 0 45%;
216 | 	}
217 | 	
218 | 	#browser_head, #browser_head_link{
219 | 		width: 95%;
220 | 	}
221 | 	
222 | 	#browser_head_link{
223 | 		float: none;
224 | 		border: none;
225 | 	}
226 | 	
227 | 	#browser_head_permission, #browser_head_size, #browser_head_modtime,
228 | 	.details-permission, .details-size, .details-modtime {
229 | 		display: none;
230 | 		width: 0;
231 | 	}
232 | 	
233 | 	.details-link{
234 | 		width: 80%;
235 | 	}
236 | 	
237 | 	#toolbox{
238 | 		height: 90px;
239 | 		margin-left: 0;
240 | 	}
241 | 	
242 | 	#toolbox, #browser_head{
243 | 		width: 95%;
244 | 		padding: 0;
245 | 		margin-left: 2.5%;
246 | 	}
247 | 	
248 | 	#toolbox_path, #toolbox_path input[type="text"] {
249 | 		width: 85%;
250 | 	}
251 | 	
252 | 	#toolbox_buttons_up {
253 | 		/*float: none;*/
254 | 		position: absolute;
255 | 		margin-top: 50px;
256 | 		left: 15px;
257 | 	}
258 | 	
259 | 	#toolbox_buttons{
260 | 		position: relative;
261 | 		float: none;
262 | 		right: 5px;
263 | 	}
264 | 	
265 | 	#toolbox_buttons .button{
266 | 		margin: 0 4px 0 0;
267 | 	}
268 | 	
269 | 	#toolbox_path_submit{
270 | 		float: right;
271 | 	}
272 | 	
273 | 	#toolbox_path{
274 | 		margin: 10px 3%;
275 | 	}
276 | 	
277 | 	#browser {
278 | 		width: 95%;
279 | 		margin-left: 2.5%;
280 | 	}
281 | 	
282 | 	.row {
283 | 		width: 95%;
284 | 	}
285 | 	
286 | 	/* Pop-Up "Select Files to Upload" window */	
287 | 	
288 | 	#fancybox-wrap {
289 | 		width: 80% !important;
290 | 		left: 10% !important;
291 | 		padding: 0 !important;
292 | 	}
293 | 	
294 | 	#uploader{
295 | 		width: 100%;
296 | 	}
297 | 	
298 | 	#fancybox-content{
299 | 		width: 90% !important;
300 | 		margin-left: 2.5%;
301 | 	}
302 | 	
303 | 	/* Config Window */
304 | 	
305 | 	#head_settings{
306 | 		position: fixed;
307 | 		right: -50px;
308 | 		display: inline;
309 | 		margin-right: 0;
310 | 	}
311 | 	
312 | 	#config{
313 | 		width: 100%;
314 | 		margin: 0;		
315 | 	}
316 | 	
317 | 	#config_01_01{
318 | 		margin-left: 10%;
319 | 		margin-top: 15px;
320 | 	}
321 | 	
322 | 	#config_01_02{
323 | 		width: auto;
324 | 		margin-top: 15px;
325 | 	}
326 | 	
327 | 	#config_01_03, #config_01_04 {
328 | 		width: 80%;		
329 | 		margin-left: 10%;
330 | 	}
331 | 	
332 | 	#config_01_04{
333 | 		margin-top: 10px;
334 | 	}
335 | 	
336 | 	#config_02_01, #config_02_04{
337 | 		width: auto;
338 | 		margin-left: 10%;
339 | 		margin-top: 10px;
340 | 	
341 | 	}
342 | 	#config_02_02{
343 | 		width: 80%;	
344 | 		margin-left: 10%;		
345 | 	}	
346 | 	
347 | 	#config_02_03{
348 | 		margin-top: 10px;
349 | 		margin-left: 10%;
350 | 	}
351 | }


--------------------------------------------------------------------------------
/webint/layout/css/baseline.compress.css:
--------------------------------------------------------------------------------
 1 | /* Baseline - a designer framework, Copyright (C) 2009 Stephane Curzi, ProjetUrbain.com, Creative Commons Attribution-Share Alike 3.0 License */
 2 | /* reset */
 3 | html,body,div,span,a,img,h1,h2,h3,h4,h5,h6,hgroup,p,dl,dialog,dt,dd,ol,ul,li,abbr,acronym,address,b,big,blockquote,cite,code,del,dfn,em,i,ins,kbd,pre,q,samp,tt,var,small,strong,sub,sup,object,iframe,form,fieldset,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,footer,header,nav,section,figure,menu,time,mark,audio,video{font-family:inherit;font-size:100%;font-weight:inherit;font-style:inherit;vertical-align:baseline;white-space:normal;text-align:left;margin:0;padding:0;border:0;outline:0;background:transparent}textarea{font-family:inherit;font-size:100%;font-weight:normal;font-style:normal;white-space:normal;text-align:left;margin:0;padding:0}article,aside,footer,header,nav,section,dialog,figure,hgroup,menu{display:block}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal}del,ins{text-decoration:none}ol,ul{list-style:none}nav ul{list-style-type:none}table{border-collapse:separate;border-spacing:0;background-color:transparent;width:auto;height:auto}:focus{outline:0}blockquote:before,blockquote:after,q:before,q:after{content:""}blockquote,q{quotes:"" ""}input{margin:0}applet,basefont,dir,font,isindex,menu,s,strike,u{font-family:inherit;font-size:100%;font-weight:normal;font-style:normal;white-space:normal;vertical-align:baseline;text-decoration:inherit;text-align:left;color:inherit;margin:0;padding:0;border:0;outline:0}dir,menu{list-style:none}nobr{white-space:normal}blink{text-decoration:none}marquee{overflow:visible}
 4 | /* base */
 5 | body{font-family:helvetica,arial,sans-serif;line-height:1.5;background:white;color:black}h1,h2,h3,h4,h5,h6{line-height:1.2}h4,h5,h6{font-weight:bold}b,strong,caption,th,thead,dt,legend{font-weight:bold}cite,dfn,em,i{font-style:italic}code,kbd,samp,pre,tt,var{font-family:mono-space,monospace}h1,h2,h3,h4,h5,h6{word-spacing:-0.125em}p{word-spacing:0.125em;hyphenate:auto;hyphenate-lines:3}p+p{text-indent:1.5em}p+p.no-indent{text-indent:0}pre{white-space:pre}del{text-decoration:line-through}mark{background:rgba(255, 255, 0, 0.4);padding:0 .25em}ins{color:#f00}small,sup,sub{font-size:80%}big{font-size:125%;line-height:80%}abbr,acronym{font-size:85%;text-transform:uppercase;letter-spacing:.1em}abbr[title],acronym[title],dfn[title]{border-bottom:1px dotted black;cursor:help}sup,sub{line-height:0}sup{vertical-align:super}sub{vertical-align:sub}blockquote{padding:1.5em}hr{border:none;background:#ddd;width:100%}ul,ol{margin-left:1.5em}ul{list-style:disc outside}ol{list-style:decimal outside}input,select,button{cursor:pointer}table{font:inherit;width:100%}article,aside,header,hgroup,nav,figure,section,footer{display:block}.debug{outline:solid gold 1px}.debug-background{background:rgba(255, 215, 0, 0.2) !important}
 6 | /* type */
 7 | body{font-size:75%;line-height:1.5}h1,h2,h3,h4,h5,h6{position:relative}h1,h2{line-height:36px;margin-bottom:18px}h1,h2,h3,h4{margin-top:18px}h3,h4,h5,h6{line-height:18px}h1{font-size:36px;top:5px}h2{font-size:28px;top:8px}h3{font-size:22px;top:1px}h4{font-size:18px;top:2px}h5{font-size:15px;top:4px}h6{font-size:13px;top:5px}h1:first-child,h2:first-child,h3:first-child,h4:first-child{margin-top:0}p,pre,address{font-size:13px;line-height:18px;position:relative;top:5px}small{font-size:11px}abbr,code,kbd,samp,small,var{line-height:15px}ul,ol,dl,dialog{font-size:13px;line-height:18px;position:relative;top:5px;margin-top:18px;margin-bottom:18px}li ul,li ol,ul ul,ol ol{top:0;margin-top:0;margin-bottom:0}li h1,li h2,li h3,li h4,li h5,li h6,li p{top:0}form,legend,label{font-size:13px;line-height:18px}legend{position:relative;top:5px}table{font-size:13px}caption{font-size:13px;line-height:18px;position:relative}hr{position:relative;height:4px;margin:18px 0 14px 0}
 8 | /* table */
 9 | table{border-collapse:collapse;border-top:solid 3px #000;position:relative;margin-top:18px}th,td{line-height:18px;padding:9px 18px 8px 0}thead th,thead td{padding-top:7px}tfoot th,tfoot td{padding-bottom:8px}tbody th,tbody td,tfoot th,tfoot td{border-top:solid 1px #000} th:first-child,td:first-child{padding-left:0}th:last-child,td:last-child{padding-right:0}tr:nth-child(even) td{}tbody tr:nth-child(odd) th,tbody tr:nth-child(odd) td{background:rgba(0, 0, 0, 0.035)}caption{top:5px;margin-bottom:18px}
10 | /* form */
11 | form{overflow:auto}legend{padding-bottom:18px}label{width:100%;position:relative;top:5px;margin-bottom:18px;line-height:18px;display:block}input[type="text"],input[type="password"],input[type="select"],input[type="search"]{width:100%;margin-bottom:-1px;display:block}input[type="radio"]{top:-1px;margin:0 4px 3px 1px}input[type="checkbox"]{top:-2px;margin:0 4px 3px 1px}input[type="file"]{margin:0px 6px 3px 6px}input[type="submit"],input[type="reset"],input[type="button"]{position:relative;top:5px;margin-bottom:18px}select{display:block;margin:0px}textarea{width:99%;line-height:18px;margin-bottom:-2px;display:block;clear:left;overflow:auto}
12 | /* grid */
13 | #page{width:990px;position:relative}#page:after{content:".";display:block;height:0;clear:both;visibility:hidden}.column{margin-left:18px;display:block;float:left}.colgroup{display:block;float:left}.first{margin-left:0;clear:left}.gutter{margin-left:18px}.no-gutter{margin-left:0}.align-left{float:left}.align-right{float:right;text-align:right}.clear{float:left}header,section{padding-bottom:18px}.leading{margin-bottom:18px}.noleading{margin-bottom:0 !important}.width1{width:234px}.width2{width:486px}.width3{width:738px}.width4{width:990px;margin-left:0 !important}.full{display:block;float:left;width:100%;margin-left:0 !important}.unitx1{width:108px}.unitx2{width:234px}.unitx3{width:360px}.unitx4{width:486px}.unitx5{width:612px}.unitx6{width:738px}.unitx7{width:864px}.unitx8{width:990px;margin-left:0 !important}.columnsx2{-webkit-column-count:2;-webkit-column-gap:18px;-moz-column-count:2;-moz-column-gap:18px;column-count:2;column-gap:18px}.columnsx4{-webkit-column-count:4;-webkit-column-gap:18px;-moz-column-count:4;-moz-column-gap:18px;column-count:4;column-gap:18px}th.width1,td.width1{width:234px}th.width2,td.width2{width:486px}th.width3,td.width3{width:738px}th.width4,td.width4{width:990px}th.unitx1,th.unitx1{width:108px}th.unitx2,td.unitx2{width:234px}th.unitx3,td.unitx3{width:360px}th.unitx4,td.unitx4{width:486px}th.unitx5,td.unitx5{width:612px}th.unitx6,td.unitx6{width:738px}th.unitx7,td.unitx7{width:864px}th.unitx8,td.unitx8{width:990px}label.width1,label.width2,label.width3,label.width4{margin-left:18px;float:left}label.unitx1,label.unitx2,label.unitx3,label.unitx4,label.unitx5,label.unitx6,label.unitx7,label.unitx8{margin-left:18px;float:left}label.first{margin-left:0}label.width4,label.unitx8{width:990px;overflow:hidden}label.width1 input[type="text"],label.width1 input[type="password"],label.width1 input[type="select"],label.width1 input[type="search"]{width:228px}label.width2 input[type="text"],label.width2 input[type="password"],label.width2 input[type="select"],label.width2 input[type="search"]{width:480px}label.width3 input[type="text"],label.width3 input[type="password"],label.width3 input[type="select"],label.width3 input[type="search"]{width:732px}label.width4 input[type="text"],label.width4 input[type="password"],label.width4 input[type="select"],label.width4 input[type="search"]{width:984px}label.width1 select{width:234px}label.width2 select{width:486px}label.width3 select{width:738px}label.width4 select{width:990px}label.unitx1 input[type="text"],label.unitx1 input[type="password"],label.unitx1 input[type="select"],label.unitx1 input[type="search"]{width:102px}label.unitx2 input[type="text"],label.unitx2 input[type="password"],label.unitx2 input[type="select"],label.unitx2 input[type="search"]{width:228px}label.unitx3 input[type="text"],label.unitx3 input[type="password"],label.unitx3 input[type="select"],label.unitx3 input[type="search"]{width:354px}label.unitx4 input[type="text"],label.unitx4 input[type="password"],label.unitx4 input[type="select"],label.unitx4 input[type="search"]{width:480px}label.unitx5 input[type="text"],label.unitx5 input[type="password"],label.unitx5 input[type="select"],label.unitx5 input[type="search"]{width:606px}label.unitx6 input[type="text"],label.unitx6 input[type="password"],label.unitx6 input[type="select"],label.unitx6 input[type="search"]{width:732px}label.unitx7 input[type="text"],label.unitx7 input[type="password"],label.unitx7 input[type="select"],label.unitx7 input[type="search"]{width:858px}label.unitx8 input[type="text"],label.unitx8 input[type="password"],label.unitx8 input[type="select"],label.unitx8 input[type="search"]{width:984px}label.unitx1 select{width:108px}label.unitx2 select{width:234px}label.unitx3 select{width:360px}label.unitx4 select{width:486px}label.unitx5 select{width:612px}label.unitx6 select{width:738px}label.unitx7 select{width:864px}label.unitx8 select{width:990px}


--------------------------------------------------------------------------------
/webint/layout/css/style.css:
--------------------------------------------------------------------------------
  1 | *[readonly]{
  2 | 	background:#eeeeee;
  3 | }
  4 | 
  5 | a{
  6 | 	text-decoration:none;
  7 | }
  8 | 
  9 | input{
 10 | 	font-family:arial;
 11 | 	line-height:14px;
 12 | }
 13 | 
 14 | label{
 15 | 	margin:0 0 12px;
 16 | }
 17 | 
 18 | .button{
 19 | 	margin:10px 4px 0 0;
 20 | 	font-weight:bold;
 21 | 	border:1px solid #b0b0b0;
 22 | 	font-size:11px;
 23 | 	padding:8px 8px 7px 29px;
 24 | 	background:url(../images/icons.png) no-repeat;
 25 | 	background-color:#FFF;
 26 | 	-webkit-border-radius: 4px;
 27 | 	-moz-border-radius: 4px;
 28 | 	border-radius: 4px;
 29 | 	color: #335065; /*#646464; */
 30 | 	line-height:13px;
 31 | 	width:auto;
 32 | 	cursor:pointer;
 33 | }
 34 | 
 35 | .button:hover{
 36 | 	background-color:#7bbbf9;
 37 | 	color:#FFF;
 38 | }
 39 | 
 40 | .button input{
 41 | 	width:0;
 42 | 	border:0;
 43 | 	background:none;
 44 | 	margin:0;
 45 | 	top:0;
 46 | 	position:absolute;
 47 | 	font-size:0;
 48 | }
 49 | 
 50 | #page{
 51 | 	width:1000px;
 52 | 	margin:0 auto;
 53 | 	font-family:arial;
 54 | }
 55 | 
 56 | #page form{
 57 | 	float:left;
 58 | 	width:auto;
 59 | 	overflow:hidden;
 60 | }
 61 | 
 62 | #page input[type=text], #page input[type=password]{
 63 | 	padding:6px 8px;
 64 | 	font-size:13px;
 65 | 	border:1px solid #bbbbbb;
 66 | 	-webkit-border-radius: 4px;
 67 | 	-moz-border-radius: 4px;
 68 | 	border-radius: 4px;
 69 | }
 70 | 
 71 | #head{
 72 | 	float:left;
 73 | 	width:1000px;
 74 | 	margin:10px 0;
 75 | }
 76 | 
 77 | #head_logo{
 78 | 	float:left;
 79 | 	/*width:300px*/
 80 | }
 81 | 
 82 | #head_logo a{
 83 | 	display:block;
 84 | 	width:202px;
 85 | 	height:50px;
 86 | 	background:url(../images/toplogo.png);
 87 | }
 88 | 
 89 | #head_settings{
 90 | 	float:right;
 91 | 	/*width:300px;*/
 92 | }
 93 | 
 94 | #head_settings a{
 95 | 	padding:0 0 0 24px;
 96 | 	float:right;
 97 | 	display:block;
 98 | 	height:16px;
 99 | 	color:#BBB;
100 | 	font-size:11px;
101 | 	font-weight:bold;
102 | 	background:url(../images/icons.png) no-repeat left -117px;
103 | }
104 | 
105 | #browser, #login, #config{
106 | 	float:left;
107 | 	color:#646464;
108 | }
109 | 
110 | /* Browser */
111 | 
112 | #uploader{
113 | 	width:350px;
114 | }
115 | 
116 | .qq-uploader {
117 | 	position:relative;
118 | 	width: 90%;
119 | 	margin: 20px auto;
120 | }
121 | 
122 | .qq-upload-button {
123 | 	display:block;
124 | 	width: 100%;
125 | 	padding: 15px 0 11px;
126 | 	text-align:center;    
127 | 	background:#7BBBF9;
128 | 	border-bottom:1px solid #ddd;
129 | 	font-size:16px;
130 | 	border-bottom:4px #326D94 solid;
131 | 	color:#fff;
132 | 	text-transform:uppercase;
133 | }
134 | 
135 | .qq-upload-button-hover {
136 | 	background:#326D94;
137 | }
138 | 
139 | .qq-upload-drop-area {
140 |     position:absolute; top:0; left:0; width:100%; height:100%; min-height: 60px; z-index:2; background:#7DCE7E;
141 | }
142 | .qq-upload-drop-area span {
143 |     display:block; position:absolute; top: 50%; width:100%; margin-top:-8px; font-size:15px; text-align:center;
144 | }
145 | .qq-upload-drop-area-active {
146 | 	background:#47C249;
147 | }
148 | 
149 | .qq-upload-list {
150 | 	margin:15px 35px; padding:0; list-style:disc;
151 | }
152 | .qq-upload-list li {
153 | 	margin:0; padding:0; line-height:15px; font-size:12px;
154 | }
155 | .qq-upload-file, .qq-upload-spinner, .qq-upload-size, .qq-upload-cancel, .qq-upload-failed-text {
156 |     margin-right: 7px;
157 | }
158 | 
159 | .qq-upload-file {}
160 | .qq-upload-spinner {
161 | 	display:inline-block; background: url("../images/upload.gif"); width:15px; height:15px; vertical-align:text-bottom;
162 | }
163 | .qq-upload-size,.qq-upload-cancel {
164 | 	font-size:11px;
165 | }
166 | 
167 | .qq-upload-failed-text {
168 | 	display:none;
169 | }
170 | .qq-upload-fail .qq-upload-failed-text {
171 | 	display:inline;
172 | }
173 | 
174 | #toolbox{
175 | 	background:-moz-linear-gradient(top, #f5f5f5, #e9e9e9); /* Firefox */
176 | 	background:-webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e9e9e9)); /* Safari, Chrome */
177 | 	background:-webkit-linear-gradient(top, #f5f5f5, #e9e9e9); /* Safari, Chrome - neue Syntax! */
178 | 	background:-o-linear-gradient(top, #f5f5f5, #e9e9e9); /* Opera */
179 | 	background:-ms-linear-gradient(top, #f5f5f5, #e9e9e9); /* IE */
180 | 	background:linear-gradient(top, #f5f5f5, #e9e9e9); /* W3C Standard */
181 | 	border:1px solid #b0b0b0;
182 | 	border-bottom:0;
183 | 	width:990px;
184 | 	padding:0 4px;
185 | 	float:left;
186 | 	text-align:right;
187 | }
188 | 
189 | #toolbox_path{
190 | 	float:left;
191 | 	border:1px solid #b0b0b0;
192 | 	-webkit-border-radius: 4px;
193 | 	-moz-border-radius: 4px;
194 | 	border-radius: 4px;
195 | 	width:570px;
196 | 	height:19px;
197 | 	background:#FFF;
198 | 	margin:10px 4px;
199 | 	padding:5px 8px 4px;
200 | }
201 | 
202 | #toolbox_path input[type=text]{
203 | 	background:none;
204 | 	border:0;
205 | 	width:548px;
206 | 	color:#646464;
207 | 	padding:0;
208 | }
209 | 
210 | #toolbox_path_text{
211 | 	float:left;
212 | }
213 | 
214 | #toolbox_path_text:hover, #toolbox_path_text:focus{
215 | 	color:#000;
216 | }
217 | 
218 | #toolbox_path_submit{
219 | 	float:left;
220 | 	width:16px;
221 | 	height:16px;
222 | 	margin:1px 2px;
223 | 	display:block;
224 | 	background:url(../images/icons.png) no-repeat left -73px;
225 | 	border:0;
226 | 	font-size:0;
227 | 	top:0;
228 | }
229 | 
230 | #toolbox_buttons_up{
231 | 	background-position:8px -89px;
232 | 	float:left;
233 | 	line-height:14px;
234 | 	margin:10px 4px 0 4px;
235 | }
236 | 
237 | #toolbox_buttons{
238 | 	float:right;
239 | }
240 | 
241 | #toolbox_buttons .button{
242 | 	float:right;
243 | }
244 | 
245 | #toolbox_buttons_upload{
246 | 	background-position:8px -90px;
247 | }
248 | 
249 | #toolbox_buttons_delete{
250 | 	background-position:8px 2px;
251 | 	top:0;
252 | 	margin-bottom:0;
253 | }
254 | 
255 | #browser_head{
256 | 	width:998px;
257 | 	margin:0 0 8px;
258 | 	background-color:#7d7d7d;
259 | 	color:#646464;
260 | 	float:left;
261 | 	border:1px solid #bbbbbb;
262 | 	font-weight:bold;
263 | 	background:-moz-linear-gradient(top, #f5f5f5, #e9e9e9); /* Firefox */
264 | 	background:-webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e9e9e9)); /* Safari, Chrome */
265 | 	background:-webkit-linear-gradient(top, #f5f5f5, #e9e9e9); /* Safari, Chrome - neue Syntax! */
266 | 	background:-o-linear-gradient(top, #f5f5f5, #e9e9e9); /* Opera */
267 | 	background:-ms-linear-gradient(top, #f5f5f5, #e9e9e9); /* IE */
268 | 	background:linear-gradient(top, #f5f5f5, #e9e9e9); /* W3C Standard */
269 | }
270 | 
271 | #browser_head a{
272 | 	color:#646464;
273 | }
274 | 
275 | #browser_head_checkbox{
276 | 	width:23px;
277 | 	float:left;
278 | 	margin:0 0 -2px;
279 | 	padding:6px 7px;
280 | }
281 | 
282 | #browser_head_checkbox input{
283 | 	margin:2px 0 0;
284 | }
285 | 
286 | #browser_head_link{
287 | 	width:683px;
288 | 	float:left;
289 | 	border-right:1px solid #bbbbbb;
290 | 	padding:6px 10px 6px 0px;
291 | }
292 | 
293 | #browser_head_permission{
294 | 	width:68px;
295 | 	border-right:1px solid #bbbbbb;
296 | 	border-left:1px solid #FFF;
297 | 	padding:6px 10px;
298 | 	float:left;
299 | }
300 | 
301 | #browser_head_size{
302 | 	width:38px;
303 | 	float:left;
304 | 	border-right:1px solid #bbbbbb;
305 | 	border-left:1px solid #FFF;
306 | 	padding:6px 10px;
307 | }
308 | 
309 | #browser_head_modtime{
310 | 	width:96px;
311 | 	float:left;
312 | 	text-align:right;
313 | 	border-left:1px solid #FFF;
314 | 	padding:6px 10px;
315 | }
316 | 
317 | #browser{
318 | 	width:1000px;
319 | }
320 | 
321 | .row{
322 | 	width:984px;
323 | 	padding:8px;
324 | 	float:left;
325 | 	-webkit-border-radius: 4px;
326 | 	-moz-border-radius: 4px;
327 | 	border-radius: 4px;
328 | 	margin:0 0 1px;
329 | }
330 | 
331 | .row:nth-child(2n){
332 | 	background:#eeeeee;
333 | }
334 | 
335 | .row:hover, .checked{
336 | 	background:#7bbbf9 !important;
337 | 	color:#FFF;	;
338 | }
339 | 
340 | .details-checkbox{
341 | 	float:left;
342 | 	width:30px;
343 | 	height:20px;
344 | 	margin:0 0 -2px;
345 | }
346 | 
347 | .details-checkbox input{
348 | 	margin:2px 0 0;
349 | }
350 | 
351 | .details-link{
352 | 	float:left;
353 | 	width:704px;
354 | }
355 | 
356 | .details-link a{
357 | 	color:#646464;
358 | 	width:680px;
359 | 	display:block;
360 | 	font-weight:bold;
361 | 	padding:0 0 0 24px;
362 | 	background:url(../images/icons.png) no-repeat;
363 | }
364 | 
365 | .row:hover .details-link a, .checked .details-link a{
366 | 	color:#FFF;
367 | }
368 | 
369 | .folder .details-link a{
370 | 	background-position:left -48px;
371 | }
372 | 
373 | .file .details-link a{
374 | 	background-position:left -25px;
375 | }
376 | 
377 | .up .details-link a{
378 | 	background-position: left -140px;
379 | }
380 | 
381 | .details-permission{
382 | 	float:left;
383 | 	width:90px;
384 | }
385 | 
386 | .details-size{
387 | 	float:left;
388 | 	/*width:60px;*/
389 | }
390 | 
391 | .details-modtime{
392 | 	float:right;
393 | 	/*width:118px;*/
394 | 	text-align:right;
395 | }
396 | 
397 | /* Login */
398 | 
399 | #login{
400 | 	width:400px;
401 | 	margin:20% 300px;
402 | }
403 | 
404 | #login_01{
405 | 	float:left;
406 | }
407 | 
408 | #login_01_01{
409 | 	width:400px;
410 | 	float:left;
411 | 	font-size:14px;
412 | }
413 | 
414 | #login_01_02{
415 | 	width:303px;
416 | 	float:left;
417 | 	padding:5px 8px 4px;
418 | }
419 | 
420 | #login_01_03{
421 | 	float:left;
422 | 	margin:0 0 0 10px;
423 | 	top:0;
424 | }
425 | 
426 | #login_01_03{
427 | 	background-position:8px -90px;
428 | }
429 | 
430 | /* Config */
431 | 
432 | #config{
433 | 	width:400px;
434 | 	margin:20% 300px;
435 | }
436 | 
437 | #config_status{
438 | 	float:left;
439 | 	width:400px;
440 | 	margin:0 0 15px;
441 | 	color:#FF0000;
442 | 	font-style:italic;
443 | }
444 | 
445 | #config_01, #config_02{
446 | 	float:left;
447 | 	margin:0 0 15px;
448 | }
449 | 
450 | #config_01_01{
451 | 	float:left;
452 | 	width:20px;
453 | 	margin-top:2px;
454 | }
455 | 
456 | #config_01_02{
457 | 	float:left;
458 | 	width:370px;
459 | 	top:0;
460 | }
461 | 
462 | #config_01_03, #config_01_04{
463 | 	float:left;
464 | 	width:177px;
465 | 	margin:0 10px 0 0;
466 | }
467 | 
468 | #config_01_04{
469 | 	margin:0;
470 | }
471 | 
472 | #config_02_01{
473 | 	width:400px;
474 | 	float:left;
475 | 	position:inherit;
476 | 	margin-top: 10px;
477 | }
478 | 
479 | #config_02_02{
480 | 	width:307px;
481 | 	float:left;
482 | 	padding:5px 8px 4px;
483 | }
484 | 
485 | #config_02_03{
486 | 	float:left;
487 | 	margin:0 0 0 10px;
488 | 	top:0;
489 | }
490 | 
491 | #config_02_03{
492 | 	background-position:8px -90px;
493 | }
494 | 


--------------------------------------------------------------------------------
/webint/layout/css/fancybox.css:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * FancyBox - jQuery Plugin
  3 |  * Simple and fancy lightbox alternative
  4 |  *
  5 |  * Examples and documentation at: http://fancybox.net
  6 |  * 
  7 |  * Copyright (c) 2008 - 2010 Janis Skarnelis
  8 |  * That said, it is hardly a one-person project. Many people have submitted bugs, code, and offered their advice freely. Their support is greatly appreciated.
  9 |  * 
 10 |  * Version: 1.3.4 (11/11/2010)
 11 |  * Requires: jQuery v1.3+
 12 |  *
 13 |  * Dual licensed under the MIT and GPL licenses:
 14 |  *   http://www.opensource.org/licenses/mit-license.php
 15 |  *   http://www.gnu.org/licenses/gpl.html
 16 |  */
 17 | 
 18 | #fancybox-loading {
 19 | 	position: fixed;
 20 | 	top: 50%;
 21 | 	left: 50%;
 22 | 	width: 40px;
 23 | 	height: 40px;
 24 | 	margin-top: -20px;
 25 | 	margin-left: -20px;
 26 | 	cursor: pointer;
 27 | 	overflow: hidden;
 28 | 	z-index: 1104;
 29 | 	display: none;
 30 | }
 31 | 
 32 | #fancybox-loading div {
 33 | 	position: absolute;
 34 | 	top: 0;
 35 | 	left: 0;
 36 | 	width: 40px;
 37 | 	height: 480px;
 38 | 	background-image: url('../images/../images/fancybox/fancybox.png');
 39 | }
 40 | 
 41 | #fancybox-overlay {
 42 | 	position: absolute;
 43 | 	top: 0;
 44 | 	left: 0;
 45 | 	width: 100%;
 46 | 	z-index: 1100;
 47 | 	display: none;
 48 | }
 49 | 
 50 | #fancybox-tmp {
 51 | 	padding: 0;
 52 | 	margin: 0;
 53 | 	border: 0;
 54 | 	overflow: auto;
 55 | 	display: none;
 56 | }
 57 | 
 58 | #fancybox-wrap {
 59 | 	position: absolute;
 60 | 	top: 0;
 61 | 	left: 0;
 62 | 	padding: 20px;
 63 | 	z-index: 1101;
 64 | 	outline: none;
 65 | 	display: none;
 66 | }
 67 | 
 68 | #fancybox-outer {
 69 | 	position: relative;
 70 | 	width: 100%;
 71 | 	height: 100%;
 72 | 	background: #fff;
 73 | }
 74 | 
 75 | #fancybox-content {
 76 | 	width: 0;
 77 | 	height: 0;
 78 | 	padding: 0;
 79 | 	outline: none;
 80 | 	position: relative;
 81 | 	overflow: hidden;
 82 | 	z-index: 1102;
 83 | 	border: 0px solid #fff;
 84 | }
 85 | 
 86 | #fancybox-hide-sel-frame {
 87 | 	position: absolute;
 88 | 	top: 0;
 89 | 	left: 0;
 90 | 	width: 100%;
 91 | 	height: 100%;
 92 | 	background: transparent;
 93 | 	z-index: 1101;
 94 | }
 95 | 
 96 | #fancybox-close {
 97 | 	position: absolute;
 98 | 	top: -15px;
 99 | 	right: -15px;
100 | 	width: 30px;
101 | 	height: 30px;
102 | 	background: transparent url('../images/../images/fancybox/fancybox.png') -40px 0px;
103 | 	cursor: pointer;
104 | 	z-index: 1103;
105 | 	display: none;
106 | }
107 | 
108 | #fancybox-error {
109 | 	color: #444;
110 | 	font: normal 12px/20px Arial;
111 | 	padding: 14px;
112 | 	margin: 0;
113 | }
114 | 
115 | #fancybox-img {
116 | 	width: 100%;
117 | 	height: 100%;
118 | 	padding: 0;
119 | 	margin: 0;
120 | 	border: none;
121 | 	outline: none;
122 | 	line-height: 0;
123 | 	vertical-align: top;
124 | }
125 | 
126 | #fancybox-frame {
127 | 	width: 100%;
128 | 	height: 100%;
129 | 	border: none;
130 | 	display: block;
131 | }
132 | 
133 | #fancybox-left, #fancybox-right {
134 | 	position: absolute;
135 | 	bottom: 0px;
136 | 	height: 100%;
137 | 	width: 35%;
138 | 	cursor: pointer;
139 | 	outline: none;
140 | 	background: transparent url('../images/../images/fancybox/blank.gif');
141 | 	z-index: 1102;
142 | 	display: none;
143 | }
144 | 
145 | #fancybox-left {
146 | 	left: 0px;
147 | }
148 | 
149 | #fancybox-right {
150 | 	right: 0px;
151 | }
152 | 
153 | #fancybox-left-ico, #fancybox-right-ico {
154 | 	position: absolute;
155 | 	top: 50%;
156 | 	left: -9999px;
157 | 	width: 30px;
158 | 	height: 30px;
159 | 	margin-top: -15px;
160 | 	cursor: pointer;
161 | 	z-index: 1102;
162 | 	display: block;
163 | }
164 | 
165 | #fancybox-left-ico {
166 | 	background-image: url('../images/../images/fancybox/fancybox.png');
167 | 	background-position: -40px -30px;
168 | }
169 | 
170 | #fancybox-right-ico {
171 | 	background-image: url('../images/../images/fancybox/fancybox.png');
172 | 	background-position: -40px -60px;
173 | }
174 | 
175 | #fancybox-left:hover, #fancybox-right:hover {
176 | 	visibility: visible; /* IE6 */
177 | }
178 | 
179 | #fancybox-left:hover span {
180 | 	left: 20px;
181 | }
182 | 
183 | #fancybox-right:hover span {
184 | 	left: auto;
185 | 	right: 20px;
186 | }
187 | 
188 | .fancybox-bg {
189 | 	position: absolute;
190 | 	padding: 0;
191 | 	margin: 0;
192 | 	border: 0;
193 | 	width: 20px;
194 | 	height: 20px;
195 | 	z-index: 1001;
196 | }
197 | 
198 | #fancybox-bg-n {
199 | 	top: -20px;
200 | 	left: 0;
201 | 	width: 100%;
202 | 	background-image: url('../images/../images/fancybox/fancybox-x.png');
203 | }
204 | 
205 | #fancybox-bg-ne {
206 | 	top: -20px;
207 | 	right: -20px;
208 | 	background-image: url('../images/../images/fancybox/fancybox.png');
209 | 	background-position: -40px -162px;
210 | }
211 | 
212 | #fancybox-bg-e {
213 | 	top: 0;
214 | 	right: -20px;
215 | 	height: 100%;
216 | 	background-image: url('../images/../images/fancybox/fancybox-y.png');
217 | 	background-position: -20px 0px;
218 | }
219 | 
220 | #fancybox-bg-se {
221 | 	bottom: -20px;
222 | 	right: -20px;
223 | 	background-image: url('../images/../images/fancybox/fancybox.png');
224 | 	background-position: -40px -182px; 
225 | }
226 | 
227 | #fancybox-bg-s {
228 | 	bottom: -20px;
229 | 	left: 0;
230 | 	width: 100%;
231 | 	background-image: url('../images/../images/fancybox/fancybox-x.png');
232 | 	background-position: 0px -20px;
233 | }
234 | 
235 | #fancybox-bg-sw {
236 | 	bottom: -20px;
237 | 	left: -20px;
238 | 	background-image: url('../images/../images/fancybox/fancybox.png');
239 | 	background-position: -40px -142px;
240 | }
241 | 
242 | #fancybox-bg-w {
243 | 	top: 0;
244 | 	left: -20px;
245 | 	height: 100%;
246 | 	background-image: url('../images/../images/fancybox/fancybox-y.png');
247 | }
248 | 
249 | #fancybox-bg-nw {
250 | 	top: -20px;
251 | 	left: -20px;
252 | 	background-image: url('../images/../images/fancybox/fancybox.png');
253 | 	background-position: -40px -122px;
254 | }
255 | 
256 | #fancybox-title {
257 | 	font-family: Helvetica;
258 | 	font-size: 12px;
259 | 	z-index: 1102;
260 | }
261 | 
262 | .fancybox-title-inside {
263 | 	padding-bottom: 10px;
264 | 	text-align: center;
265 | 	color: #333;
266 | 	background: #fff;
267 | 	position: relative;
268 | }
269 | 
270 | .fancybox-title-outside {
271 | 	padding-top: 10px;
272 | 	color: #fff;
273 | }
274 | 
275 | .fancybox-title-over {
276 | 	position: absolute;
277 | 	bottom: 0;
278 | 	left: 0;
279 | 	color: #FFF;
280 | 	text-align: left;
281 | }
282 | 
283 | #fancybox-title-over {
284 | 	padding: 10px;
285 | 	background-image: url('../images/../images/fancybox/fancy_title_over.png');
286 | 	display: block;
287 | }
288 | 
289 | .fancybox-title-float {
290 | 	position: absolute;
291 | 	left: 0;
292 | 	bottom: -20px;
293 | 	height: 32px;
294 | }
295 | 
296 | #fancybox-title-float-wrap {
297 | 	border: none;
298 | 	border-collapse: collapse;
299 | 	width: auto;
300 | }
301 | 
302 | #fancybox-title-float-wrap td {
303 | 	border: none;
304 | 	white-space: nowrap;
305 | }
306 | 
307 | #fancybox-title-float-left {
308 | 	padding: 0 0 0 15px;
309 | 	background: url('../images/../images/fancybox/fancybox.png') -40px -90px no-repeat;
310 | }
311 | 
312 | #fancybox-title-float-main {
313 | 	color: #FFF;
314 | 	line-height: 29px;
315 | 	font-weight: bold;
316 | 	padding: 0 0 3px 0;
317 | 	background: url('../images/../images/fancybox/fancybox-x.png') 0px -40px;
318 | }
319 | 
320 | #fancybox-title-float-right {
321 | 	padding: 0 0 0 15px;
322 | 	background: url('../images/../images/fancybox/fancybox.png') -55px -90px no-repeat;
323 | }
324 | 
325 | /* IE6 */
326 | 
327 | .fancybox-ie6 #fancybox-close { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../images/fancybox/fancy_close.png', sizingMethod='scale'); }
328 | 
329 | .fancybox-ie6 #fancybox-left-ico { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../images/fancybox/fancy_nav_left.png', sizingMethod='scale'); }
330 | .fancybox-ie6 #fancybox-right-ico { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../images/fancybox/fancy_nav_right.png', sizingMethod='scale'); }
331 | 
332 | .fancybox-ie6 #fancybox-title-over { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../images/fancybox/fancy_title_over.png', sizingMethod='scale'); zoom: 1; }
333 | .fancybox-ie6 #fancybox-title-float-left { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../images/fancybox/fancy_title_left.png', sizingMethod='scale'); }
334 | .fancybox-ie6 #fancybox-title-float-main { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../images/fancybox/fancy_title_main.png', sizingMethod='scale'); }
335 | .fancybox-ie6 #fancybox-title-float-right { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../images/fancybox/fancy_title_right.png', sizingMethod='scale'); }
336 | 
337 | .fancybox-ie6 #fancybox-bg-w, .fancybox-ie6 #fancybox-bg-e, .fancybox-ie6 #fancybox-left, .fancybox-ie6 #fancybox-right, #fancybox-hide-sel-frame {
338 | 	height: expression(this.parentNode.clientHeight + "px");
339 | }
340 | 
341 | #fancybox-loading.fancybox-ie6 {
342 | 	position: absolute; margin-top: 0;
343 | 	top: expression( (-20 + (document.documentElement.clientHeight ? document.documentElement.clientHeight/2 : document.body.clientHeight/2 ) + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop )) + 'px');
344 | }
345 | 
346 | #fancybox-loading.fancybox-ie6 div	{ background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../images/fancybox/fancy_loading.png', sizingMethod='scale'); }
347 | 
348 | /* IE6, IE7, IE8 */
349 | 
350 | .fancybox-ie .fancybox-bg { background: transparent !important; }
351 | 
352 | .fancybox-ie #fancybox-bg-n { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../images/fancybox/fancy_shadow_n.png', sizingMethod='scale'); }
353 | .fancybox-ie #fancybox-bg-ne { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../images/fancybox/fancy_shadow_ne.png', sizingMethod='scale'); }
354 | .fancybox-ie #fancybox-bg-e { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../images/fancybox/fancy_shadow_e.png', sizingMethod='scale'); }
355 | .fancybox-ie #fancybox-bg-se { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../images/fancybox/fancy_shadow_se.png', sizingMethod='scale'); }
356 | .fancybox-ie #fancybox-bg-s { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../images/fancybox/fancy_shadow_s.png', sizingMethod='scale'); }
357 | .fancybox-ie #fancybox-bg-sw { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../images/fancybox/fancy_shadow_sw.png', sizingMethod='scale'); }
358 | .fancybox-ie #fancybox-bg-w { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../images/fancybox/fancy_shadow_w.png', sizingMethod='scale'); }
359 | .fancybox-ie #fancybox-bg-nw { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../images/fancybox/fancy_shadow_nw.png', sizingMethod='scale'); }
360 | 


--------------------------------------------------------------------------------
/webint/system/js/fancybox.js:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * FancyBox - jQuery Plugin
 3 |  * Simple and fancy lightbox alternative
 4 |  *
 5 |  * Examples and documentation at: http://fancybox.net
 6 |  * 
 7 |  * Copyright (c) 2008 - 2010 Janis Skarnelis
 8 |  * That said, it is hardly a one-person project. Many people have submitted bugs, code, and offered their advice freely. Their support is greatly appreciated.
 9 |  * 
10 |  * Version: 1.3.4 (11/11/2010)
11 |  * Requires: jQuery v1.3+
12 |  *
13 |  * Dual licensed under the MIT and GPL licenses:
14 |  *   http://www.opensource.org/licenses/mit-license.php
15 |  *   http://www.gnu.org/licenses/gpl.html
16 |  */
17 | 
18 | ;(function(b){var m,t,u,f,D,j,E,n,z,A,q=0,e={},o=[],p=0,d={},l=[],G=null,v=new Image,J=/\.(jpg|gif|png|bmp|jpeg)(.*)?$/i,W=/[^\.]\.(swf)\s*$/i,K,L=1,y=0,s="",r,i,h=false,B=b.extend(b("
")[0],{prop:0}),M=b.browser.msie&&b.browser.version<7&&!window.XMLHttpRequest,N=function(){t.hide();v.onerror=v.onload=null;G&&G.abort();m.empty()},O=function(){if(false===e.onError(o,q,e)){t.hide();h=false}else{e.titleShow=false;e.width="auto";e.height="auto";m.html('

The requested content cannot be loaded.
Please try again later.

'); 19 | F()}},I=function(){var a=o[q],c,g,k,C,P,w;N();e=b.extend({},b.fn.fancybox.defaults,typeof b(a).data("fancybox")=="undefined"?e:b(a).data("fancybox"));w=e.onStart(o,q,e);if(w===false)h=false;else{if(typeof w=="object")e=b.extend(e,w);k=e.title||(a.nodeName?b(a).attr("title"):a.title)||"";if(a.nodeName&&!e.orig)e.orig=b(a).children("img:first").length?b(a).children("img:first"):b(a);if(k===""&&e.orig&&e.titleFromAlt)k=e.orig.attr("alt");c=e.href||(a.nodeName?b(a).attr("href"):a.href)||null;if(/^(?:javascript)/i.test(c)|| 20 | c=="#")c=null;if(e.type){g=e.type;if(!c)c=e.content}else if(e.content)g="html";else if(c)g=c.match(J)?"image":c.match(W)?"swf":b(a).hasClass("iframe")?"iframe":c.indexOf("#")===0?"inline":"ajax";if(g){if(g=="inline"){a=c.substr(c.indexOf("#"));g=b(a).length>0?"inline":"ajax"}e.type=g;e.href=c;e.title=k;if(e.autoDimensions)if(e.type=="html"||e.type=="inline"||e.type=="ajax"){e.width="auto";e.height="auto"}else e.autoDimensions=false;if(e.modal){e.overlayShow=true;e.hideOnOverlayClick=false;e.hideOnContentClick= 21 | false;e.enableEscapeButton=false;e.showCloseButton=false}e.padding=parseInt(e.padding,10);e.margin=parseInt(e.margin,10);m.css("padding",e.padding+e.margin);b(".fancybox-inline-tmp").unbind("fancybox-cancel").bind("fancybox-change",function(){b(this).replaceWith(j.children())});switch(g){case "html":m.html(e.content);F();break;case "inline":if(b(a).parent().is("#fancybox-content")===true){h=false;break}b('
').hide().insertBefore(b(a)).bind("fancybox-cleanup",function(){b(this).replaceWith(j.children())}).bind("fancybox-cancel", 22 | function(){b(this).replaceWith(m.children())});b(a).appendTo(m);F();break;case "image":h=false;b.fancybox.showActivity();v=new Image;v.onerror=function(){O()};v.onload=function(){h=true;v.onerror=v.onload=null;e.width=v.width;e.height=v.height;b("").attr({id:"fancybox-img",src:v.src,alt:e.title}).appendTo(m);Q()};v.src=c;break;case "swf":e.scrolling="no";C='';P="";b.each(e.swf,function(x,H){C+='';P+=" "+x+'="'+H+'"'});C+='";m.html(C);F();break;case "ajax":h=false;b.fancybox.showActivity();e.ajax.win=e.ajax.success;G=b.ajax(b.extend({},e.ajax,{url:c,data:e.ajax.data||{},error:function(x){x.status>0&&O()},success:function(x,H,R){if((typeof R=="object"?R:G).status==200){if(typeof e.ajax.win== 24 | "function"){w=e.ajax.win(c,x,H,R);if(w===false){t.hide();return}else if(typeof w=="string"||typeof w=="object")x=w}m.html(x);F()}}}));break;case "iframe":Q()}}else O()}},F=function(){var a=e.width,c=e.height;a=a.toString().indexOf("%")>-1?parseInt((b(window).width()-e.margin*2)*parseFloat(a)/100,10)+"px":a=="auto"?"auto":a+"px";c=c.toString().indexOf("%")>-1?parseInt((b(window).height()-e.margin*2)*parseFloat(c)/100,10)+"px":c=="auto"?"auto":c+"px";m.wrapInner('
');e.width=m.width();e.height=m.height();Q()},Q=function(){var a,c;t.hide();if(f.is(":visible")&&false===d.onCleanup(l,p,d)){b.event.trigger("fancybox-cancel");h=false}else{h=true;b(j.add(u)).unbind();b(window).unbind("resize.fb scroll.fb");b(document).unbind("keydown.fb");f.is(":visible")&&d.titlePosition!=="outside"&&f.css("height",f.height());l=o;p=q;d=e;if(d.overlayShow){u.css({"background-color":d.overlayColor, 26 | opacity:d.overlayOpacity,cursor:d.hideOnOverlayClick?"pointer":"auto",height:b(document).height()});if(!u.is(":visible")){M&&b("select:not(#fancybox-tmp select)").filter(function(){return this.style.visibility!=="hidden"}).css({visibility:"hidden"}).one("fancybox-cleanup",function(){this.style.visibility="inherit"});u.show()}}else u.hide();i=X();s=d.title||"";y=0;n.empty().removeAttr("style").removeClass();if(d.titleShow!==false){if(b.isFunction(d.titleFormat))a=d.titleFormat(s,l,p,d);else a=s&&s.length? 27 | d.titlePosition=="float"?'
'+s+'
':'
'+s+"
":false;s=a;if(!(!s||s==="")){n.addClass("fancybox-title-"+d.titlePosition).html(s).appendTo("body").show();switch(d.titlePosition){case "inside":n.css({width:i.width-d.padding*2,marginLeft:d.padding,marginRight:d.padding}); 28 | y=n.outerHeight(true);n.appendTo(D);i.height+=y;break;case "over":n.css({marginLeft:d.padding,width:i.width-d.padding*2,bottom:d.padding}).appendTo(D);break;case "float":n.css("left",parseInt((n.width()-i.width-40)/2,10)*-1).appendTo(f);break;default:n.css({width:i.width-d.padding*2,paddingLeft:d.padding,paddingRight:d.padding}).appendTo(f)}}}n.hide();if(f.is(":visible")){b(E.add(z).add(A)).hide();a=f.position();r={top:a.top,left:a.left,width:f.width(),height:f.height()};c=r.width==i.width&&r.height== 29 | i.height;j.fadeTo(d.changeFade,0.3,function(){var g=function(){j.html(m.contents()).fadeTo(d.changeFade,1,S)};b.event.trigger("fancybox-change");j.empty().removeAttr("filter").css({"border-width":d.padding,width:i.width-d.padding*2,height:e.autoDimensions?"auto":i.height-y-d.padding*2});if(c)g();else{B.prop=0;b(B).animate({prop:1},{duration:d.changeSpeed,easing:d.easingChange,step:T,complete:g})}})}else{f.removeAttr("style");j.css("border-width",d.padding);if(d.transitionIn=="elastic"){r=V();j.html(m.contents()); 30 | f.show();if(d.opacity)i.opacity=0;B.prop=0;b(B).animate({prop:1},{duration:d.speedIn,easing:d.easingIn,step:T,complete:S})}else{d.titlePosition=="inside"&&y>0&&n.show();j.css({width:i.width-d.padding*2,height:e.autoDimensions?"auto":i.height-y-d.padding*2}).html(m.contents());f.css(i).fadeIn(d.transitionIn=="none"?0:d.speedIn,S)}}}},Y=function(){if(d.enableEscapeButton||d.enableKeyboardNav)b(document).bind("keydown.fb",function(a){if(a.keyCode==27&&d.enableEscapeButton){a.preventDefault();b.fancybox.close()}else if((a.keyCode== 31 | 37||a.keyCode==39)&&d.enableKeyboardNav&&a.target.tagName!=="INPUT"&&a.target.tagName!=="TEXTAREA"&&a.target.tagName!=="SELECT"){a.preventDefault();b.fancybox[a.keyCode==37?"prev":"next"]()}});if(d.showNavArrows){if(d.cyclic&&l.length>1||p!==0)z.show();if(d.cyclic&&l.length>1||p!=l.length-1)A.show()}else{z.hide();A.hide()}},S=function(){if(!b.support.opacity){j.get(0).style.removeAttribute("filter");f.get(0).style.removeAttribute("filter")}e.autoDimensions&&j.css("height","auto");f.css("height","auto"); 32 | s&&s.length&&n.show();d.showCloseButton&&E.show();Y();d.hideOnContentClick&&j.bind("click",b.fancybox.close);d.hideOnOverlayClick&&u.bind("click",b.fancybox.close);b(window).bind("resize.fb",b.fancybox.resize);d.centerOnScroll&&b(window).bind("scroll.fb",b.fancybox.center);if(d.type=="iframe")b('').appendTo(j); 33 | f.show();h=false;b.fancybox.center();d.onComplete(l,p,d);var a,c;if(l.length-1>p){a=l[p+1].href;if(typeof a!=="undefined"&&a.match(J)){c=new Image;c.src=a}}if(p>0){a=l[p-1].href;if(typeof a!=="undefined"&&a.match(J)){c=new Image;c.src=a}}},T=function(a){var c={width:parseInt(r.width+(i.width-r.width)*a,10),height:parseInt(r.height+(i.height-r.height)*a,10),top:parseInt(r.top+(i.top-r.top)*a,10),left:parseInt(r.left+(i.left-r.left)*a,10)};if(typeof i.opacity!=="undefined")c.opacity=a<0.5?0.5:a;f.css(c); 34 | j.css({width:c.width-d.padding*2,height:c.height-y*a-d.padding*2})},U=function(){return[b(window).width()-d.margin*2,b(window).height()-d.margin*2,b(document).scrollLeft()+d.margin,b(document).scrollTop()+d.margin]},X=function(){var a=U(),c={},g=d.autoScale,k=d.padding*2;c.width=d.width.toString().indexOf("%")>-1?parseInt(a[0]*parseFloat(d.width)/100,10):d.width+k;c.height=d.height.toString().indexOf("%")>-1?parseInt(a[1]*parseFloat(d.height)/100,10):d.height+k;if(g&&(c.width>a[0]||c.height>a[1]))if(e.type== 35 | "image"||e.type=="swf"){g=d.width/d.height;if(c.width>a[0]){c.width=a[0];c.height=parseInt((c.width-k)/g+k,10)}if(c.height>a[1]){c.height=a[1];c.width=parseInt((c.height-k)*g+k,10)}}else{c.width=Math.min(c.width,a[0]);c.height=Math.min(c.height,a[1])}c.top=parseInt(Math.max(a[3]-20,a[3]+(a[1]-c.height-40)*0.5),10);c.left=parseInt(Math.max(a[2]-20,a[2]+(a[0]-c.width-40)*0.5),10);return c},V=function(){var a=e.orig?b(e.orig):false,c={};if(a&&a.length){c=a.offset();c.top+=parseInt(a.css("paddingTop"), 36 | 10)||0;c.left+=parseInt(a.css("paddingLeft"),10)||0;c.top+=parseInt(a.css("border-top-width"),10)||0;c.left+=parseInt(a.css("border-left-width"),10)||0;c.width=a.width();c.height=a.height();c={width:c.width+d.padding*2,height:c.height+d.padding*2,top:c.top-d.padding-20,left:c.left-d.padding-20}}else{a=U();c={width:d.padding*2,height:d.padding*2,top:parseInt(a[3]+a[1]*0.5,10),left:parseInt(a[2]+a[0]*0.5,10)}}return c},Z=function(){if(t.is(":visible")){b("div",t).css("top",L*-40+"px");L=(L+1)%12}else clearInterval(K)}; 37 | b.fn.fancybox=function(a){if(!b(this).length)return this;b(this).data("fancybox",b.extend({},a,b.metadata?b(this).metadata():{})).unbind("click.fb").bind("click.fb",function(c){c.preventDefault();if(!h){h=true;b(this).blur();o=[];q=0;c=b(this).attr("rel")||"";if(!c||c==""||c==="nofollow")o.push(this);else{o=b("a[rel="+c+"], area[rel="+c+"]");q=o.index(this)}I()}});return this};b.fancybox=function(a,c){var g;if(!h){h=true;g=typeof c!=="undefined"?c:{};o=[];q=parseInt(g.index,10)||0;if(b.isArray(a)){for(var k= 38 | 0,C=a.length;ko.length||q<0)q=0;I()}};b.fancybox.showActivity=function(){clearInterval(K);t.show();K=setInterval(Z,66)};b.fancybox.hideActivity=function(){t.hide()};b.fancybox.next=function(){return b.fancybox.pos(p+ 39 | 1)};b.fancybox.prev=function(){return b.fancybox.pos(p-1)};b.fancybox.pos=function(a){if(!h){a=parseInt(a);o=l;if(a>-1&&a1){q=a>=l.length?0:l.length-1;I()}}};b.fancybox.cancel=function(){if(!h){h=true;b.event.trigger("fancybox-cancel");N();e.onCancel(o,q,e);h=false}};b.fancybox.close=function(){function a(){u.fadeOut("fast");n.empty().hide();f.hide();b.event.trigger("fancybox-cleanup");j.empty();d.onClosed(l,p,d);l=e=[];p=q=0;d=e={};h=false}if(!(h||f.is(":hidden"))){h= 40 | true;if(d&&false===d.onCleanup(l,p,d))h=false;else{N();b(E.add(z).add(A)).hide();b(j.add(u)).unbind();b(window).unbind("resize.fb scroll.fb");b(document).unbind("keydown.fb");j.find("iframe").attr("src",M&&/^https/i.test(window.location.href||"")?"javascript:void(false)":"about:blank");d.titlePosition!=="inside"&&n.empty();f.stop();if(d.transitionOut=="elastic"){r=V();var c=f.position();i={top:c.top,left:c.left,width:f.width(),height:f.height()};if(d.opacity)i.opacity=1;n.empty().hide();B.prop=1; 41 | b(B).animate({prop:0},{duration:d.speedOut,easing:d.easingOut,step:T,complete:a})}else f.fadeOut(d.transitionOut=="none"?0:d.speedOut,a)}}};b.fancybox.resize=function(){u.is(":visible")&&u.css("height",b(document).height());b.fancybox.center(true)};b.fancybox.center=function(a){var c,g;if(!h){g=a===true?1:0;c=U();!g&&(f.width()>c[0]||f.height()>c[1])||f.stop().animate({top:parseInt(Math.max(c[3]-20,c[3]+(c[1]-j.height()-40)*0.5-d.padding)),left:parseInt(Math.max(c[2]-20,c[2]+(c[0]-j.width()-40)*0.5- 42 | d.padding))},typeof a=="number"?a:200)}};b.fancybox.init=function(){if(!b("#fancybox-wrap").length){b("body").append(m=b('
'),t=b('
'),u=b('
'),f=b('
'));D=b('
').append('
').appendTo(f); 43 | D.append(j=b('
'),E=b(''),n=b('
'),z=b(''),A=b(''));E.click(b.fancybox.close);t.click(b.fancybox.cancel);z.click(function(a){a.preventDefault();b.fancybox.prev()});A.click(function(a){a.preventDefault();b.fancybox.next()}); 44 | b.fn.mousewheel&&f.bind("mousewheel.fb",function(a,c){if(h)a.preventDefault();else if(b(a.target).get(0).clientHeight==0||b(a.target).get(0).scrollHeight===b(a.target).get(0).clientHeight){a.preventDefault();b.fancybox[c>0?"prev":"next"]()}});b.support.opacity||f.addClass("fancybox-ie");if(M){t.addClass("fancybox-ie6");f.addClass("fancybox-ie6");b('').prependTo(D)}}}; 45 | b.fn.fancybox.defaults={padding:10,margin:40,opacity:false,modal:false,cyclic:false,scrolling:"auto",width:560,height:340,autoScale:true,autoDimensions:true,centerOnScroll:false,ajax:{},swf:{wmode:"transparent"},hideOnOverlayClick:true,hideOnContentClick:false,overlayShow:true,overlayOpacity:0.7,overlayColor:"#777",titleShow:true,titlePosition:"float",titleFormat:null,titleFromAlt:false,transitionIn:"fade",transitionOut:"fade",speedIn:300,speedOut:300,changeSpeed:300,changeFade:"fast",easingIn:"swing", 46 | easingOut:"swing",showCloseButton:true,showNavArrows:true,enableEscapeButton:true,enableKeyboardNav:true,onStart:function(){},onCancel:function(){},onComplete:function(){},onCleanup:function(){},onClosed:function(){},onError:function(){}};b(document).ready(function(){b.fancybox.init()})})(jQuery); -------------------------------------------------------------------------------- /webint/system/savant/Savant3.php: -------------------------------------------------------------------------------- 1 | 10 | * 11 | * @license http://www.gnu.org/copyleft/lesser.html LGPL 12 | * 13 | * @version $Id: Savant3.php,v 1.42 2006/01/01 18:31:00 pmjones Exp $ 14 | * 15 | */ 16 | 17 | 18 | /** 19 | * Always have these classes available. 20 | */ 21 | include_once dirname(__FILE__) . '/Savant3/Filter.php'; 22 | include_once dirname(__FILE__) . '/Savant3/Plugin.php'; 23 | 24 | 25 | /** 26 | * 27 | * Provides an object-oriented template system for PHP5. 28 | * 29 | * Savant3 helps you separate business logic from presentation logic 30 | * using PHP as the template language. By default, Savant3 does not 31 | * compile templates. However, you may pass an optional compiler object 32 | * to compile template source to include-able PHP code. It is E_STRICT 33 | * compliant for PHP5. 34 | * 35 | * Please see the documentation at {@link http://phpsavant.com/}, and be 36 | * sure to donate! :-) 37 | * 38 | * @author Paul M. Jones 39 | * 40 | * @package Savant3 41 | * 42 | * @version @package_version@ 43 | * 44 | */ 45 | 46 | class Savant3 { 47 | 48 | 49 | /** 50 | * 51 | * Array of configuration parameters. 52 | * 53 | * @access protected 54 | * 55 | * @var array 56 | * 57 | */ 58 | 59 | protected $__config = array( 60 | 'template_path' => array(), 61 | 'resource_path' => array(), 62 | 'error_text' => "\n\ntemplate error, examine fetch() result\n\n", 63 | 'exceptions' => false, 64 | 'autoload' => false, 65 | 'compiler' => null, 66 | 'filters' => array(), 67 | 'plugins' => array(), 68 | 'template' => null, 69 | 'plugin_conf' => array(), 70 | 'extract' => false, 71 | 'fetch' => null, 72 | 'escape' => array('htmlspecialchars'), 73 | ); 74 | 75 | 76 | // ----------------------------------------------------------------- 77 | // 78 | // Constructor and magic methods 79 | // 80 | // ----------------------------------------------------------------- 81 | 82 | 83 | /** 84 | * 85 | * Constructor. 86 | * 87 | * @access public 88 | * 89 | * @param array $config An associative array of configuration keys for 90 | * the Savant3 object. Any, or none, of the keys may be set. 91 | * 92 | * @return object Savant3 A Savant3 instance. 93 | * 94 | */ 95 | 96 | public function __construct($config = null) 97 | { 98 | // force the config to an array 99 | settype($config, 'array'); 100 | 101 | // set the default template search path 102 | if (isset($config['template_path'])) { 103 | // user-defined dirs 104 | $this->setPath('template', $config['template_path']); 105 | } else { 106 | // no directories set, use the 107 | // default directory only 108 | $this->setPath('template', null); 109 | } 110 | 111 | // set the default resource search path 112 | if (isset($config['resource_path'])) { 113 | // user-defined dirs 114 | $this->setPath('resource', $config['resource_path']); 115 | } else { 116 | // no directories set, use the 117 | // default directory only 118 | $this->setPath('resource', null); 119 | } 120 | 121 | // set the error reporting text 122 | if (isset($config['error_text'])) { 123 | $this->setErrorText($config['error_text']); 124 | } 125 | 126 | // set the autoload flag 127 | if (isset($config['autoload'])) { 128 | $this->setAutoload($config['autoload']); 129 | } 130 | 131 | // set the extraction flag 132 | if (isset($config['extract'])) { 133 | $this->setExtract($config['extract']); 134 | } 135 | 136 | // set the exceptions flag 137 | if (isset($config['exceptions'])) { 138 | $this->setExceptions($config['exceptions']); 139 | } 140 | 141 | // set the template to use for output 142 | if (isset($config['template'])) { 143 | $this->setTemplate($config['template']); 144 | } 145 | 146 | // set the output escaping callbacks 147 | if (isset($config['escape'])) { 148 | $this->setEscape($config['escape']); 149 | } 150 | 151 | // set the default plugin configs 152 | if (isset($config['plugin_conf']) && is_array($config['plugin_conf'])) { 153 | foreach ($config['plugin_conf'] as $name => $opts) { 154 | $this->setPluginConf($name, $opts); 155 | } 156 | } 157 | 158 | // set the default filter callbacks 159 | if (isset($config['filters'])) { 160 | $this->addFilters($config['filters']); 161 | } 162 | } 163 | 164 | 165 | /** 166 | * 167 | * Executes a main plugin method with arbitrary parameters. 168 | * 169 | * @access public 170 | * 171 | * @param string $func The plugin method name. 172 | * 173 | * @param array $args The parameters passed to the method. 174 | * 175 | * @return mixed The plugin output, or a Savant3_Error with an 176 | * ERR_PLUGIN code if it can't find the plugin. 177 | * 178 | */ 179 | 180 | public function __call($func, $args) 181 | { 182 | $plugin = $this->plugin($func); 183 | 184 | if ($this->isError($plugin)) { 185 | return $plugin; 186 | } 187 | 188 | // try to avoid the very-slow call_user_func_array() 189 | // for plugins with very few parameters. thanks to 190 | // Andreas Korthaus for profiling the code to find 191 | // the slowdown. 192 | switch (count($args)) { 193 | 194 | case 0: 195 | return $plugin->$func(); 196 | 197 | case 1: 198 | return $plugin->$func($args[0]); 199 | break; 200 | 201 | case 2: 202 | return $plugin->$func($args[0], $args[1]); 203 | break; 204 | 205 | case 3: 206 | return $plugin->$func($args[0], $args[1], $args[2]); 207 | break; 208 | 209 | default: 210 | return call_user_func_array(array($plugin, $func), $args); 211 | break; 212 | } 213 | } 214 | 215 | 216 | /** 217 | * 218 | * Magic method to echo this object as template output. 219 | * 220 | * Note that if there is an error, this will output a simple 221 | * error text string and will not return an error object. Use 222 | * fetch() to get an error object when errors occur. 223 | * 224 | * @access public 225 | * 226 | * @return string The template output. 227 | * 228 | */ 229 | 230 | public function __toString() 231 | { 232 | return $this->getOutput(); 233 | } 234 | 235 | 236 | /** 237 | * 238 | * Reports the API version for this class. 239 | * 240 | * @access public 241 | * 242 | * @return string A PHP-standard version number. 243 | * 244 | */ 245 | 246 | public function apiVersion() 247 | { 248 | return '@package_version@'; 249 | } 250 | 251 | 252 | /** 253 | * 254 | * Returns an internal plugin object; creates it as needed. 255 | * 256 | * @access public 257 | * 258 | * @param string $name The plugin name. If this plugin has not 259 | * been created yet, this method creates it automatically. 260 | * 261 | * @return mixed The plugin object, or a Savant3_Error with an 262 | * ERR_PLUGIN code if it can't find the plugin. 263 | * 264 | */ 265 | 266 | public function plugin($name) 267 | { 268 | // shorthand reference 269 | $plugins =& $this->__config['plugins']; 270 | $autoload = $this->__config['autoload']; 271 | 272 | // is the plugin method object already instantiated? 273 | if (! array_key_exists($name, $plugins)) { 274 | 275 | // not already instantiated, so load it up. 276 | // set up the class name. 277 | $class = "Savant3_Plugin_$name"; 278 | 279 | // has the class been loaded? 280 | if (! class_exists($class, $autoload)) { 281 | 282 | // class is not loaded, set up the file name. 283 | $file = "$class.php"; 284 | 285 | // make sure the class file is available from the resource path. 286 | $result = $this->findFile('resource', $file); 287 | if (! $result) { 288 | // not available, this is an error 289 | return $this->error( 290 | 'ERR_PLUGIN', 291 | array('method' => $name) 292 | ); 293 | } else { 294 | // available, load the class file 295 | include_once $result; 296 | } 297 | } 298 | 299 | // get the default configuration for the plugin. 300 | $plugin_conf =& $this->__config['plugin_conf']; 301 | if (! empty($plugin_conf[$name])) { 302 | $opts = $plugin_conf[$name]; 303 | } else { 304 | $opts = array(); 305 | } 306 | 307 | // add the Savant reference 308 | $opts['Savant'] = $this; 309 | 310 | // instantiate the plugin with its options. 311 | $plugins[$name] = new $class($opts); 312 | } 313 | 314 | // return the plugin object 315 | return $plugins[$name]; 316 | } 317 | 318 | 319 | // ----------------------------------------------------------------- 320 | // 321 | // Public configuration management (getters and setters). 322 | // 323 | // ----------------------------------------------------------------- 324 | 325 | 326 | /** 327 | * 328 | * Returns a copy of the Savant3 configuration parameters. 329 | * 330 | * @access public 331 | * 332 | * @param string $key The specific configuration key to return. If null, 333 | * returns the entire configuration array. 334 | * 335 | * @return mixed A copy of the $this->__config array. 336 | * 337 | */ 338 | 339 | public function getConfig($key = null) 340 | { 341 | if (is_null($key)) { 342 | // no key requested, return the entire config array 343 | return $this->__config; 344 | } elseif (empty($this->__config[$key])) { 345 | // no such key 346 | return null; 347 | } else { 348 | // return the requested key 349 | return $this->__config[$key]; 350 | } 351 | } 352 | 353 | 354 | /** 355 | * 356 | * Sets __autoload() usage on or off. 357 | * 358 | * @access public 359 | * 360 | * @param bool $flag True to use __autoload(), false to not use it. 361 | * 362 | * @return void 363 | * 364 | */ 365 | 366 | public function setAutoload($flag) 367 | { 368 | $this->__config['autoload'] = (bool) $flag; 369 | } 370 | 371 | 372 | /** 373 | * 374 | * Sets a custom compiler/pre-processor callback for template sources. 375 | * 376 | * By default, Savant3 does not use a compiler; use this to set your 377 | * own custom compiler (pre-processor) for template sources. 378 | * 379 | * @access public 380 | * 381 | * @param mixed $compiler A compiler callback value suitable for the 382 | * first parameter of call_user_func(). Set to null/false/empty to 383 | * use PHP itself as the template markup (i.e., no compiling). 384 | * 385 | * @return void 386 | * 387 | */ 388 | 389 | public function setCompiler($compiler) 390 | { 391 | $this->__config['compiler'] = $compiler; 392 | } 393 | 394 | 395 | /** 396 | * 397 | * Sets the custom error text for __toString(). 398 | * 399 | * @access public 400 | * 401 | * @param string $text The error text when a template is echoed. 402 | * 403 | * @return void 404 | * 405 | */ 406 | 407 | public function setErrorText($text) 408 | { 409 | $this->__config['error_text'] = $text; 410 | } 411 | 412 | 413 | /** 414 | * 415 | * Sets whether or not exceptions will be thrown. 416 | * 417 | * @access public 418 | * 419 | * @param bool $flag True to turn on exception throwing, false 420 | * to turn it off. 421 | * 422 | * @return void 423 | * 424 | */ 425 | 426 | public function setExceptions($flag) 427 | { 428 | $this->__config['exceptions'] = (bool) $flag; 429 | } 430 | 431 | 432 | /** 433 | * 434 | * Sets whether or not variables will be extracted. 435 | * 436 | * @access public 437 | * 438 | * @param bool $flag True to turn on variable extraction, false 439 | * to turn it off. 440 | * 441 | * @return void 442 | * 443 | */ 444 | 445 | public function setExtract($flag) 446 | { 447 | $this->__config['extract'] = (bool) $flag; 448 | } 449 | 450 | 451 | /** 452 | * 453 | * Sets config array for a plugin. 454 | * 455 | * @access public 456 | * 457 | * @param string $plugin The plugin to configure. 458 | * 459 | * @param array $config The configuration array for the plugin. 460 | * 461 | * @return void 462 | * 463 | */ 464 | 465 | public function setPluginConf($plugin, $config = null) 466 | { 467 | $this->__config['plugin_conf'][$plugin] = $config; 468 | } 469 | 470 | 471 | /** 472 | * 473 | * Sets the template name to use. 474 | * 475 | * @access public 476 | * 477 | * @param string $template The template name. 478 | * 479 | * @return void 480 | * 481 | */ 482 | 483 | public function setTemplate($template) 484 | { 485 | $this->__config['template'] = $template; 486 | } 487 | 488 | 489 | // ----------------------------------------------------------------- 490 | // 491 | // Output escaping and management. 492 | // 493 | // ----------------------------------------------------------------- 494 | 495 | 496 | /** 497 | * 498 | * Clears then sets the callbacks to use when calling $this->escape(). 499 | * 500 | * Each parameter passed to this function is treated as a separate 501 | * callback. For example: 502 | * 503 | * 504 | * $savant->setEscape( 505 | * 'stripslashes', 506 | * 'htmlspecialchars', 507 | * array('StaticClass', 'method'), 508 | * array($object, $method) 509 | * ); 510 | * 511 | * 512 | * @access public 513 | * 514 | * @return void 515 | * 516 | */ 517 | 518 | public function setEscape() 519 | { 520 | $this->__config['escape'] = (array) @func_get_args(); 521 | } 522 | 523 | 524 | /** 525 | * 526 | * Adds to the callbacks used when calling $this->escape(). 527 | * 528 | * Each parameter passed to this function is treated as a separate 529 | * callback. For example: 530 | * 531 | * 532 | * $savant->addEscape( 533 | * 'stripslashes', 534 | * 'htmlspecialchars', 535 | * array('StaticClass', 'method'), 536 | * array($object, $method) 537 | * ); 538 | * 539 | * 540 | * @access public 541 | * 542 | * @return void 543 | * 544 | */ 545 | 546 | public function addEscape() 547 | { 548 | $args = (array) @func_get_args(); 549 | $this->__config['escape'] = array_merge( 550 | $this->__config['escape'], $args 551 | ); 552 | } 553 | 554 | 555 | /** 556 | * 557 | * Gets the array of output-escaping callbacks. 558 | * 559 | * @access public 560 | * 561 | * @return array The array of output-escaping callbacks. 562 | * 563 | */ 564 | 565 | public function getEscape() 566 | { 567 | return $this->__config['escape']; 568 | } 569 | 570 | 571 | /** 572 | * 573 | * Applies escaping to a value. 574 | * 575 | * You can override the predefined escaping callbacks by passing 576 | * added parameters as replacement callbacks. 577 | * 578 | * 579 | * // use predefined callbacks 580 | * $result = $savant->escape($value); 581 | * 582 | * // use replacement callbacks 583 | * $result = $savant->escape( 584 | * $value, 585 | * 'stripslashes', 586 | * 'htmlspecialchars', 587 | * array('StaticClass', 'method'), 588 | * array($object, $method) 589 | * ); 590 | * 591 | * 592 | * 593 | * Unfortunately, a call to "echo htmlspecialchars()" is twice 594 | * as fast as a call to "echo $this->escape()" under the default 595 | * escaping (which is htmlspecialchars). The benchmark showed 596 | * 0.007 seconds for htmlspecialchars(), and 0.014 seconds for 597 | * $this->escape(), on 300 calls each. 598 | * 599 | * @access public 600 | * 601 | * @param mixed $value The value to be escaped. 602 | * 603 | * @return mixed 604 | * 605 | */ 606 | 607 | public function escape($value) 608 | { 609 | // were custom callbacks passed? 610 | if (func_num_args() == 1) { 611 | 612 | // no, only a value was passed. 613 | // loop through the predefined callbacks. 614 | foreach ($this->__config['escape'] as $func) { 615 | // this if() shaves 0.001sec off of 300 calls. 616 | if (is_string($func)) { 617 | $value = $func($value); 618 | } else { 619 | $value = call_user_func($func, $value); 620 | } 621 | } 622 | 623 | } else { 624 | 625 | // yes, use the custom callbacks 626 | $callbacks = func_get_args(); 627 | 628 | // drop $value 629 | array_shift($callbacks); 630 | 631 | // loop through custom callbacks. 632 | foreach ($callbacks as $func) { 633 | // this if() shaves 0.001sec off of 300 calls. 634 | if (is_string($func)) { 635 | $value = $func($value); 636 | } else { 637 | $value = call_user_func($func, $value); 638 | } 639 | } 640 | 641 | } 642 | 643 | return $value; 644 | } 645 | 646 | 647 | /** 648 | * 649 | * Prints a value after escaping it for output. 650 | * 651 | * You can override the predefined escaping callbacks by passing 652 | * added parameters as replacement callbacks. 653 | * 654 | * 655 | * // use predefined callbacks 656 | * $this->eprint($value); 657 | * 658 | * // use replacement callbacks 659 | * $this->eprint( 660 | * $value, 661 | * 'stripslashes', 662 | * 'htmlspecialchars', 663 | * array('StaticClass', 'method'), 664 | * array($object, $method) 665 | * ); 666 | * 667 | * 668 | * @access public 669 | * 670 | * @param mixed $value The value to be escaped and printed. 671 | * 672 | * @return void 673 | * 674 | */ 675 | 676 | public function eprint($value) 677 | { 678 | // avoid the very slow call_user_func_array() when there 679 | // are no custom escaping callbacks. thanks to 680 | // Andreas Korthaus for profiling the code to find 681 | // the slowdown. 682 | $num = func_num_args(); 683 | if ($num == 1) { 684 | echo $this->escape($value); 685 | } else { 686 | $args = func_get_args(); 687 | echo call_user_func_array( 688 | array($this, 'escape'), 689 | $args 690 | ); 691 | } 692 | } 693 | 694 | 695 | // ----------------------------------------------------------------- 696 | // 697 | // File management 698 | // 699 | // ----------------------------------------------------------------- 700 | 701 | 702 | /** 703 | * 704 | * Sets an entire array of search paths for templates or resources. 705 | * 706 | * @access public 707 | * 708 | * @param string $type The type of path to set, typically 'template' 709 | * or 'resource'. 710 | * 711 | * @param string|array $path The new set of search paths. If null or 712 | * false, resets to the current directory only. 713 | * 714 | * @return void 715 | * 716 | */ 717 | 718 | public function setPath($type, $path) 719 | { 720 | // clear out the prior search dirs 721 | $this->__config[$type . '_path'] = array(); 722 | 723 | // always add the fallback directories as last resort 724 | switch (strtolower($type)) { 725 | case 'template': 726 | // the current directory 727 | $this->addPath($type, '.'); 728 | break; 729 | case 'resource': 730 | // the Savant3 distribution resources 731 | $this->addPath($type, dirname(__FILE__) . '/Savant3/resources/'); 732 | break; 733 | } 734 | 735 | // actually add the user-specified directories 736 | $this->addPath($type, $path); 737 | } 738 | 739 | 740 | /** 741 | * 742 | * Adds to the search path for templates and resources. 743 | * 744 | * @access public 745 | * 746 | * @param string|array $path The directory or stream to search. 747 | * 748 | * @return void 749 | * 750 | */ 751 | 752 | public function addPath($type, $path) 753 | { 754 | // convert from path string to array of directories 755 | if (is_string($path) && ! strpos($path, '://')) { 756 | 757 | // the path config is a string, and it's not a stream 758 | // identifier (the "://" piece). add it as a path string. 759 | $path = explode(PATH_SEPARATOR, $path); 760 | 761 | // typically in path strings, the first one is expected 762 | // to be searched first. however, Savant3 uses a stack, 763 | // so the first would be last. reverse the path string 764 | // so that it behaves as expected with path strings. 765 | $path = array_reverse($path); 766 | 767 | } else { 768 | 769 | // just force to array 770 | settype($path, 'array'); 771 | 772 | } 773 | 774 | // loop through the path directories 775 | foreach ($path as $dir) { 776 | 777 | // no surrounding spaces allowed! 778 | $dir = trim($dir); 779 | 780 | // add trailing separators as needed 781 | if (strpos($dir, '://') && substr($dir, -1) != '/') { 782 | // stream 783 | $dir .= '/'; 784 | } elseif (substr($dir, -1) != DIRECTORY_SEPARATOR) { 785 | // directory 786 | $dir .= DIRECTORY_SEPARATOR; 787 | } 788 | 789 | // add to the top of the search dirs 790 | array_unshift( 791 | $this->__config[$type . '_path'], 792 | $dir 793 | ); 794 | } 795 | } 796 | 797 | 798 | /** 799 | * 800 | * Searches the directory paths for a given file. 801 | * 802 | * @param array $type The type of path to search (template or resource). 803 | * 804 | * @param string $file The file name to look for. 805 | * 806 | * @return string|bool The full path and file name for the target file, 807 | * or boolean false if the file is not found in any of the paths. 808 | * 809 | */ 810 | 811 | protected function findFile($type, $file) 812 | { 813 | // get the set of paths 814 | $set = $this->__config[$type . '_path']; 815 | 816 | // start looping through the path set 817 | foreach ($set as $path) { 818 | 819 | // get the path to the file 820 | $fullname = $path . $file; 821 | 822 | // is the path based on a stream? 823 | if (strpos($path, '://') === false) { 824 | // not a stream, so do a realpath() to avoid 825 | // directory traversal attempts on the local file 826 | // system. Suggested by Ian Eure, initially 827 | // rejected, but then adopted when the secure 828 | // compiler was added. 829 | $path = realpath($path); // needed for substr() later 830 | $fullname = realpath($fullname); 831 | } 832 | 833 | // the substr() check added by Ian Eure to make sure 834 | // that the realpath() results in a directory registered 835 | // with Savant so that non-registered directores are not 836 | // accessible via directory traversal attempts. 837 | if (file_exists($fullname) && is_readable($fullname) && 838 | substr($fullname, 0, strlen($path)) == $path) { 839 | return $fullname; 840 | } 841 | } 842 | 843 | // could not find the file in the set of paths 844 | return false; 845 | } 846 | 847 | 848 | // ----------------------------------------------------------------- 849 | // 850 | // Variable and reference assignment 851 | // 852 | // ----------------------------------------------------------------- 853 | 854 | 855 | /** 856 | * 857 | * Sets variables for the template (by copy). 858 | * 859 | * This method is overloaded; you can assign all the properties of 860 | * an object, an associative array, or a single value by name. 861 | * 862 | * You are not allowed to assign any variable named '__config' as 863 | * it would conflict with internal configuration tracking. 864 | * 865 | * In the following examples, the template will have two variables 866 | * assigned to it; the variables will be known inside the template as 867 | * "$this->var1" and "$this->var2". 868 | * 869 | * 870 | * $Savant3 = new Savant3(); 871 | * 872 | * // assign by object 873 | * $obj = new stdClass; 874 | * $obj->var1 = 'something'; 875 | * $obj->var2 = 'else'; 876 | * $Savant3->assign($obj); 877 | * 878 | * // assign by associative array 879 | * $ary = array('var1' => 'something', 'var2' => 'else'); 880 | * $Savant3->assign($ary); 881 | * 882 | * // assign by name and value 883 | * $Savant3->assign('var1', 'something'); 884 | * $Savant3->assign('var2', 'else'); 885 | * 886 | * // assign directly 887 | * $Savant3->var1 = 'something'; 888 | * $Savant3->var2 = 'else'; 889 | * 890 | * 891 | * @access public 892 | * 893 | * @return bool True on success, false on failure. 894 | * 895 | */ 896 | 897 | public function assign() 898 | { 899 | // get the arguments; there may be 1 or 2. 900 | $arg0 = @func_get_arg(0); 901 | $arg1 = @func_get_arg(1); 902 | 903 | // assign from object 904 | if (is_object($arg0)) { 905 | // assign public properties 906 | foreach (get_object_vars($arg0) as $key => $val) { 907 | // can't assign to __config 908 | if ($key != '__config') { 909 | $this->$key = $val; 910 | } 911 | } 912 | return true; 913 | } 914 | 915 | // assign from associative array 916 | if (is_array($arg0)) { 917 | foreach ($arg0 as $key => $val) { 918 | // can't assign to __config 919 | if ($key != '__config') { 920 | $this->$key = $val; 921 | } 922 | } 923 | return true; 924 | } 925 | 926 | // assign by name and value (can't assign to __config). 927 | if (is_string($arg0) && func_num_args() > 1 && $arg0 != '__config') { 928 | $this->$arg0 = $arg1; 929 | return true; 930 | } 931 | 932 | // $arg0 was not object, array, or string. 933 | return false; 934 | } 935 | 936 | 937 | /** 938 | * 939 | * Sets variables for the template (by reference). 940 | * 941 | * You are not allowed to assign any variable named '__config' as 942 | * it would conflict with internal configuration tracking. 943 | * 944 | * 945 | * $Savant3 = new Savant3(); 946 | * 947 | * // assign by name and value 948 | * $Savant3->assignRef('var1', $ref); 949 | * 950 | * // assign directly 951 | * $Savant3->ref =& $var1; 952 | * 953 | * 954 | * @access public 955 | * 956 | * @return bool True on success, false on failure. 957 | * 958 | */ 959 | 960 | public function assignRef($key, &$val) 961 | { 962 | // assign by name and reference (can't assign to __config). 963 | if ($key != '__config') { 964 | $this->$key =& $val; 965 | return true; 966 | } else { 967 | return false; 968 | } 969 | } 970 | 971 | 972 | // ----------------------------------------------------------------- 973 | // 974 | // Template processing 975 | // 976 | // ----------------------------------------------------------------- 977 | 978 | 979 | /** 980 | * 981 | * Displays a template directly (equivalent to echo $tpl). 982 | * 983 | * @access public 984 | * 985 | * @param string $tpl The template source to compile and display. 986 | * 987 | * @return void 988 | * 989 | */ 990 | 991 | public function display($tpl = null) 992 | { 993 | echo $this->getOutput($tpl); 994 | } 995 | 996 | /** 997 | * Returns output, including error_text if an error occurs. 998 | * 999 | * @param $tpl The template to process; if null, uses the 1000 | * default template set with setTemplate(). 1001 | * 1002 | * @return string The template output. 1003 | */ 1004 | public function getOutput($tpl = null) 1005 | { 1006 | $output = $this->fetch($tpl); 1007 | if ($this->isError($output)) { 1008 | $text = $this->__config['error_text']; 1009 | return $this->escape($text); 1010 | } else { 1011 | return $output; 1012 | } 1013 | } 1014 | 1015 | 1016 | /** 1017 | * 1018 | * Compiles, executes, and filters a template source. 1019 | * 1020 | * @access public 1021 | * 1022 | * @param string $tpl The template to process; if null, uses the 1023 | * default template set with setTemplate(). 1024 | * 1025 | * @return mixed The template output string, or a Savant3_Error. 1026 | * 1027 | */ 1028 | 1029 | public function fetch($tpl = null) 1030 | { 1031 | // make sure we have a template source to work with 1032 | if (is_null($tpl)) { 1033 | $tpl = $this->__config['template']; 1034 | } 1035 | 1036 | // get a path to the compiled template script 1037 | $result = $this->template($tpl); 1038 | 1039 | // did we get a path? 1040 | if (! $result || $this->isError($result)) { 1041 | 1042 | // no. return the error result. 1043 | return $result; 1044 | 1045 | } else { 1046 | 1047 | // yes. execute the template script. move the script-path 1048 | // out of the local scope, then clean up the local scope to 1049 | // avoid variable name conflicts. 1050 | $this->__config['fetch'] = $result; 1051 | unset($result); 1052 | unset($tpl); 1053 | 1054 | // are we doing extraction? 1055 | if ($this->__config['extract']) { 1056 | // pull variables into the local scope. 1057 | extract(get_object_vars($this), EXTR_REFS); 1058 | } 1059 | 1060 | // buffer output so we can return it instead of displaying. 1061 | ob_start(); 1062 | 1063 | // are we using filters? 1064 | if ($this->__config['filters']) { 1065 | // use a second buffer to apply filters. we used to set 1066 | // the ob_start() filter callback, but that would 1067 | // silence errors in the filters. Hendy Irawan provided 1068 | // the next three lines as a "verbose" fix. 1069 | ob_start(); 1070 | include $this->__config['fetch']; 1071 | echo $this->applyFilters(ob_get_clean()); 1072 | } else { 1073 | // no filters being used. 1074 | include $this->__config['fetch']; 1075 | } 1076 | 1077 | // reset the fetch script value, get the buffer, and return. 1078 | $this->__config['fetch'] = null; 1079 | return ob_get_clean(); 1080 | } 1081 | } 1082 | 1083 | 1084 | /** 1085 | * 1086 | * Compiles a template and returns path to compiled script. 1087 | * 1088 | * By default, Savant does not compile templates, it uses PHP as the 1089 | * markup language, so the "compiled" template is the same as the source 1090 | * template. 1091 | * 1092 | * Used inside a template script like so: 1093 | * 1094 | * 1095 | * include $this->template($tpl); 1096 | * 1097 | * 1098 | * @access protected 1099 | * 1100 | * @param string $tpl The template source name to look for. 1101 | * 1102 | * @return string The full path to the compiled template script. 1103 | * 1104 | * @throws object An error object with a 'ERR_TEMPLATE' code. 1105 | * 1106 | */ 1107 | 1108 | protected function template($tpl = null) 1109 | { 1110 | // set to default template if none specified. 1111 | if (is_null($tpl)) { 1112 | $tpl = $this->__config['template']; 1113 | } 1114 | 1115 | // find the template source. 1116 | $file = $this->findFile('template', $tpl); 1117 | if (! $file) { 1118 | return $this->error( 1119 | 'ERR_TEMPLATE', 1120 | array('template' => $tpl) 1121 | ); 1122 | } 1123 | 1124 | // are we compiling source into a script? 1125 | if ($this->__config['compiler']) { 1126 | // compile the template source and get the path to the 1127 | // compiled script (will be returned instead of the 1128 | // source path) 1129 | $result = call_user_func( 1130 | array($this->__config['compiler'], 'compile'), 1131 | $file 1132 | ); 1133 | } else { 1134 | // no compiling requested, use the source path 1135 | $result = $file; 1136 | } 1137 | 1138 | // is there a script from the compiler? 1139 | if (! $result || $this->isError($result)) { 1140 | // return an error, along with any error info 1141 | // generated by the compiler. 1142 | return $this->error( 1143 | 'ERR_COMPILER', 1144 | array( 1145 | 'template' => $tpl, 1146 | 'compiler' => $result 1147 | ) 1148 | ); 1149 | } else { 1150 | // no errors, the result is a path to a script 1151 | return $result; 1152 | } 1153 | } 1154 | 1155 | 1156 | // ----------------------------------------------------------------- 1157 | // 1158 | // Filter management and processing 1159 | // 1160 | // ----------------------------------------------------------------- 1161 | 1162 | 1163 | /** 1164 | * 1165 | * Resets the filter stack to the provided list of callbacks. 1166 | * 1167 | * @access protected 1168 | * 1169 | * @param array An array of filter callbacks. 1170 | * 1171 | * @return void 1172 | * 1173 | */ 1174 | 1175 | public function setFilters() 1176 | { 1177 | $this->__config['filters'] = (array) @func_get_args(); 1178 | } 1179 | 1180 | 1181 | /** 1182 | * 1183 | * Adds filter callbacks to the stack of filters. 1184 | * 1185 | * @access protected 1186 | * 1187 | * @param array An array of filter callbacks. 1188 | * 1189 | * @return void 1190 | * 1191 | */ 1192 | 1193 | public function addFilters() 1194 | { 1195 | // add the new filters to the static config variable 1196 | // via the reference 1197 | foreach ((array) @func_get_args() as $callback) { 1198 | $this->__config['filters'][] = $callback; 1199 | } 1200 | } 1201 | 1202 | 1203 | /** 1204 | * 1205 | * Runs all filter callbacks on buffered output. 1206 | * 1207 | * @access protected 1208 | * 1209 | * @param string The template output. 1210 | * 1211 | * @return void 1212 | * 1213 | */ 1214 | 1215 | protected function applyFilters($buffer) 1216 | { 1217 | $autoload = $this->__config['autoload']; 1218 | foreach ($this->__config['filters'] as $callback) { 1219 | 1220 | // if the callback is a static Savant3_Filter method, 1221 | // and not already loaded, try to auto-load it. 1222 | if (is_array($callback) && 1223 | is_string($callback[0]) && 1224 | substr($callback[0], 0, 15) == 'Savant3_Filter_' && 1225 | ! class_exists($callback[0], $autoload)) { 1226 | 1227 | // load the Savant3_Filter_*.php resource 1228 | $file = $callback[0] . '.php'; 1229 | $result = $this->findFile('resource', $file); 1230 | if ($result) { 1231 | include_once $result; 1232 | } 1233 | } 1234 | 1235 | // can't pass a third $this param, it chokes the OB system. 1236 | $buffer = call_user_func($callback, $buffer); 1237 | } 1238 | 1239 | return $buffer; 1240 | } 1241 | 1242 | 1243 | // ----------------------------------------------------------------- 1244 | // 1245 | // Error handling 1246 | // 1247 | // ----------------------------------------------------------------- 1248 | 1249 | 1250 | /** 1251 | * 1252 | * Returns an error object or throws an exception. 1253 | * 1254 | * @access public 1255 | * 1256 | * @param string $code A Savant3 'ERR_*' string. 1257 | * 1258 | * @param array $info An array of error-specific information. 1259 | * 1260 | * @param int $level The error severity level, default is 1261 | * E_USER_ERROR (the most severe possible). 1262 | * 1263 | * @param bool $trace Whether or not to include a backtrace, default 1264 | * true. 1265 | * 1266 | * @return object Savant3_Error 1267 | * 1268 | */ 1269 | 1270 | public function error($code, $info = array(), $level = E_USER_ERROR, 1271 | $trace = true) 1272 | { 1273 | $autoload = $this->__config['autoload']; 1274 | 1275 | // are we throwing exceptions? 1276 | if ($this->__config['exceptions']) { 1277 | if (! class_exists('Savant3_Exception', $autoload)) { 1278 | include_once dirname(__FILE__) . '/Savant3/Exception.php'; 1279 | } 1280 | throw new Savant3_Exception($code); 1281 | } 1282 | 1283 | 1284 | // the error config array 1285 | $config = array( 1286 | 'code' => $code, 1287 | 'info' => (array) $info, 1288 | 'level' => $level, 1289 | 'trace' => $trace 1290 | ); 1291 | 1292 | // make sure the Savant3 error class is available 1293 | if (! class_exists('Savant3_Error', $autoload)) { 1294 | include_once dirname(__FILE__) . '/Savant3/Error.php'; 1295 | } 1296 | 1297 | // return it 1298 | $err = new Savant3_Error($config); 1299 | return $err; 1300 | } 1301 | 1302 | 1303 | /** 1304 | * 1305 | * Tests if an object is of the Savant3_Error class. 1306 | * 1307 | * @access public 1308 | * 1309 | * @param object $obj The object to be tested. 1310 | * 1311 | * @return boolean True if $obj is an error object of the type 1312 | * Savant3_Error, or is a subclass that Savant3_Error. False if not. 1313 | * 1314 | */ 1315 | 1316 | public function isError($obj) 1317 | { 1318 | $autoload = $this->__config['autoload']; 1319 | 1320 | // is it even an object? 1321 | if (! is_object($obj)) { 1322 | // not an object, so can't be a Savant3_Error 1323 | return false; 1324 | } else { 1325 | // make sure the Savant3 error class is available for 1326 | // comparison 1327 | if (! class_exists('Savant3_Error', $autoload)) { 1328 | include_once dirname(__FILE__) . '/Savant3/Error.php'; 1329 | } 1330 | // now compare the parentage 1331 | $is = $obj instanceof Savant3_Error; 1332 | $sub = is_subclass_of($obj, 'Savant3_Error'); 1333 | return ($is || $sub); 1334 | } 1335 | } 1336 | } 1337 | ?> 1338 | -------------------------------------------------------------------------------- /webint/system/js/fileuploader.js: -------------------------------------------------------------------------------- 1 | /** 2 | * http://github.com/valums/file-uploader 3 | * 4 | * Multiple file upload component with progress-bar, drag-and-drop. 5 | * © 2010 Andrew Valums ( andrew(at)valums.com ) 6 | * 7 | * Licensed under GNU GPL 2 or later and GNU LGPL 2 or later, see license.txt. 8 | */ 9 | 10 | // 11 | // Helper functions 12 | // 13 | 14 | var qq = qq || {}; 15 | 16 | /** 17 | * Adds all missing properties from second obj to first obj 18 | */ 19 | qq.extend = function(first, second){ 20 | for (var prop in second){ 21 | first[prop] = second[prop]; 22 | } 23 | }; 24 | 25 | /** 26 | * Searches for a given element in the array, returns -1 if it is not present. 27 | * @param {Number} [from] The index at which to begin the search 28 | */ 29 | qq.indexOf = function(arr, elt, from){ 30 | if (arr.indexOf) return arr.indexOf(elt, from); 31 | 32 | from = from || 0; 33 | var len = arr.length; 34 | 35 | if (from < 0) from += len; 36 | 37 | for (; from < len; from++){ 38 | if (from in arr && arr[from] === elt){ 39 | return from; 40 | } 41 | } 42 | return -1; 43 | }; 44 | 45 | qq.getUniqueId = (function(){ 46 | var id = 0; 47 | return function(){ return id++; }; 48 | })(); 49 | 50 | // 51 | // Events 52 | 53 | qq.attach = function(element, type, fn){ 54 | if (element.addEventListener){ 55 | element.addEventListener(type, fn, false); 56 | } else if (element.attachEvent){ 57 | element.attachEvent('on' + type, fn); 58 | } 59 | }; 60 | qq.detach = function(element, type, fn){ 61 | if (element.removeEventListener){ 62 | element.removeEventListener(type, fn, false); 63 | } else if (element.attachEvent){ 64 | element.detachEvent('on' + type, fn); 65 | } 66 | }; 67 | 68 | qq.preventDefault = function(e){ 69 | if (e.preventDefault){ 70 | e.preventDefault(); 71 | } else{ 72 | e.returnValue = false; 73 | } 74 | }; 75 | 76 | // 77 | // Node manipulations 78 | 79 | /** 80 | * Insert node a before node b. 81 | */ 82 | qq.insertBefore = function(a, b){ 83 | b.parentNode.insertBefore(a, b); 84 | }; 85 | qq.remove = function(element){ 86 | element.parentNode.removeChild(element); 87 | }; 88 | 89 | qq.contains = function(parent, descendant){ 90 | // compareposition returns false in this case 91 | if (parent == descendant) return true; 92 | 93 | if (parent.contains){ 94 | return parent.contains(descendant); 95 | } else { 96 | return !!(descendant.compareDocumentPosition(parent) & 8); 97 | } 98 | }; 99 | 100 | /** 101 | * Creates and returns element from html string 102 | * Uses innerHTML to create an element 103 | */ 104 | qq.toElement = (function(){ 105 | var div = document.createElement('div'); 106 | return function(html){ 107 | div.innerHTML = html; 108 | var element = div.firstChild; 109 | div.removeChild(element); 110 | return element; 111 | }; 112 | })(); 113 | 114 | // 115 | // Node properties and attributes 116 | 117 | /** 118 | * Sets styles for an element. 119 | * Fixes opacity in IE6-8. 120 | */ 121 | qq.css = function(element, styles){ 122 | if (styles.opacity != null){ 123 | if (typeof element.style.opacity != 'string' && typeof(element.filters) != 'undefined'){ 124 | styles.filter = 'alpha(opacity=' + Math.round(100 * styles.opacity) + ')'; 125 | } 126 | } 127 | qq.extend(element.style, styles); 128 | }; 129 | qq.hasClass = function(element, name){ 130 | var re = new RegExp('(^| )' + name + '( |$)'); 131 | return re.test(element.className); 132 | }; 133 | qq.addClass = function(element, name){ 134 | if (!qq.hasClass(element, name)){ 135 | element.className += ' ' + name; 136 | } 137 | }; 138 | qq.removeClass = function(element, name){ 139 | var re = new RegExp('(^| )' + name + '( |$)'); 140 | element.className = element.className.replace(re, ' ').replace(/^\s+|\s+$/g, ""); 141 | }; 142 | qq.setText = function(element, text){ 143 | element.innerText = text; 144 | element.textContent = text; 145 | }; 146 | 147 | // 148 | // Selecting elements 149 | 150 | qq.children = function(element){ 151 | var children = [], 152 | child = element.firstChild; 153 | 154 | while (child){ 155 | if (child.nodeType == 1){ 156 | children.push(child); 157 | } 158 | child = child.nextSibling; 159 | } 160 | 161 | return children; 162 | }; 163 | 164 | qq.getByClass = function(element, className){ 165 | if (element.querySelectorAll){ 166 | return element.querySelectorAll('.' + className); 167 | } 168 | 169 | var result = []; 170 | var candidates = element.getElementsByTagName("*"); 171 | var len = candidates.length; 172 | 173 | for (var i = 0; i < len; i++){ 174 | if (qq.hasClass(candidates[i], className)){ 175 | result.push(candidates[i]); 176 | } 177 | } 178 | return result; 179 | }; 180 | 181 | /** 182 | * obj2url() takes a json-object as argument and generates 183 | * a querystring. pretty much like jQuery.param() 184 | * 185 | * how to use: 186 | * 187 | * `qq.obj2url({a:'b',c:'d'},'http://any.url/upload?otherParam=value');` 188 | * 189 | * will result in: 190 | * 191 | * `http://any.url/upload?otherParam=value&a=b&c=d` 192 | * 193 | * @param Object JSON-Object 194 | * @param String current querystring-part 195 | * @return String encoded querystring 196 | */ 197 | qq.obj2url = function(obj, temp, prefixDone){ 198 | var uristrings = [], 199 | prefix = '&', 200 | add = function(nextObj, i){ 201 | var nextTemp = temp 202 | ? (/\[\]$/.test(temp)) // prevent double-encoding 203 | ? temp 204 | : temp+'['+i+']' 205 | : i; 206 | if ((nextTemp != 'undefined') && (i != 'undefined')) { 207 | uristrings.push( 208 | (typeof nextObj === 'object') 209 | ? qq.obj2url(nextObj, nextTemp, true) 210 | : (Object.prototype.toString.call(nextObj) === '[object Function]') 211 | ? encodeURIComponent(nextTemp) + '=' + encodeURIComponent(nextObj()) 212 | : encodeURIComponent(nextTemp) + '=' + encodeURIComponent(nextObj) 213 | ); 214 | } 215 | }; 216 | 217 | if (!prefixDone && temp) { 218 | prefix = (/\?/.test(temp)) ? (/\?$/.test(temp)) ? '' : '&' : '?'; 219 | uristrings.push(temp); 220 | uristrings.push(qq.obj2url(obj)); 221 | } else if ((Object.prototype.toString.call(obj) === '[object Array]') && (typeof obj != 'undefined') ) { 222 | // we wont use a for-in-loop on an array (performance) 223 | for (var i = 0, len = obj.length; i < len; ++i){ 224 | add(obj[i], i); 225 | } 226 | } else if ((typeof obj != 'undefined') && (obj !== null) && (typeof obj === "object")){ 227 | // for anything else but a scalar, we will use for-in-loop 228 | for (var i in obj){ 229 | add(obj[i], i); 230 | } 231 | } else { 232 | uristrings.push(encodeURIComponent(temp) + '=' + encodeURIComponent(obj)); 233 | } 234 | 235 | return uristrings.join(prefix) 236 | .replace(/^&/, '') 237 | .replace(/%20/g, '+'); 238 | }; 239 | 240 | // 241 | // 242 | // Uploader Classes 243 | // 244 | // 245 | 246 | var qq = qq || {}; 247 | 248 | /** 249 | * Creates upload button, validates upload, but doesn't create file list or dd. 250 | */ 251 | qq.FileUploaderBasic = function(o){ 252 | this._options = { 253 | // set to true to see the server response 254 | debug: false, 255 | action: '/server/upload', 256 | params: {}, 257 | button: null, 258 | multiple: true, 259 | maxConnections: 3, 260 | // validation 261 | allowedExtensions: [], 262 | sizeLimit: 0, 263 | minSizeLimit: 0, 264 | // events 265 | // return false to cancel submit 266 | onSubmit: function(id, fileName){}, 267 | onProgress: function(id, fileName, loaded, total){}, 268 | onComplete: function(id, fileName, responseJSON){}, 269 | onCancel: function(id, fileName){}, 270 | // messages 271 | messages: { 272 | typeError: "{file} has invalid extension. Only {extensions} are allowed.", 273 | sizeError: "{file} is too large, maximum file size is {sizeLimit}.", 274 | minSizeError: "{file} is too small, minimum file size is {minSizeLimit}.", 275 | emptyError: "{file} is empty, please select files again without it.", 276 | onLeave: "The files are being uploaded, if you leave now the upload will be cancelled." 277 | }, 278 | showMessage: function(message){ 279 | alert(message); 280 | } 281 | }; 282 | qq.extend(this._options, o); 283 | 284 | // number of files being uploaded 285 | this._filesInProgress = 0; 286 | this._handler = this._createUploadHandler(); 287 | 288 | if (this._options.button){ 289 | this._button = this._createUploadButton(this._options.button); 290 | } 291 | 292 | this._preventLeaveInProgress(); 293 | }; 294 | 295 | qq.FileUploaderBasic.prototype = { 296 | setParams: function(params){ 297 | this._options.params = params; 298 | }, 299 | getInProgress: function(){ 300 | return this._filesInProgress; 301 | }, 302 | _createUploadButton: function(element){ 303 | var self = this; 304 | 305 | return new qq.UploadButton({ 306 | element: element, 307 | multiple: this._options.multiple && qq.UploadHandlerXhr.isSupported(), 308 | onChange: function(input){ 309 | self._onInputChange(input); 310 | } 311 | }); 312 | }, 313 | _createUploadHandler: function(){ 314 | var self = this, 315 | handlerClass; 316 | 317 | if(qq.UploadHandlerXhr.isSupported()){ 318 | handlerClass = 'UploadHandlerXhr'; 319 | } else { 320 | handlerClass = 'UploadHandlerForm'; 321 | } 322 | 323 | var handler = new qq[handlerClass]({ 324 | debug: this._options.debug, 325 | action: this._options.action, 326 | maxConnections: this._options.maxConnections, 327 | onProgress: function(id, fileName, loaded, total){ 328 | self._onProgress(id, fileName, loaded, total); 329 | self._options.onProgress(id, fileName, loaded, total); 330 | }, 331 | onComplete: function(id, fileName, result){ 332 | self._onComplete(id, fileName, result); 333 | self._options.onComplete(id, fileName, result); 334 | }, 335 | onCancel: function(id, fileName){ 336 | self._onCancel(id, fileName); 337 | self._options.onCancel(id, fileName); 338 | } 339 | }); 340 | 341 | return handler; 342 | }, 343 | _preventLeaveInProgress: function(){ 344 | var self = this; 345 | 346 | qq.attach(window, 'beforeunload', function(e){ 347 | if (!self._filesInProgress){return;} 348 | 349 | var e = e || window.event; 350 | // for ie, ff 351 | e.returnValue = self._options.messages.onLeave; 352 | // for webkit 353 | return self._options.messages.onLeave; 354 | }); 355 | }, 356 | _onSubmit: function(id, fileName){ 357 | this._filesInProgress++; 358 | }, 359 | _onProgress: function(id, fileName, loaded, total){ 360 | }, 361 | _onComplete: function(id, fileName, result){ 362 | this._filesInProgress--; 363 | if (result.error){ 364 | this._options.showMessage(result.error); 365 | } 366 | }, 367 | _onCancel: function(id, fileName){ 368 | this._filesInProgress--; 369 | }, 370 | _onInputChange: function(input){ 371 | if (this._handler instanceof qq.UploadHandlerXhr){ 372 | this._uploadFileList(input.files); 373 | } else { 374 | if (this._validateFile(input)){ 375 | this._uploadFile(input); 376 | } 377 | } 378 | this._button.reset(); 379 | }, 380 | _uploadFileList: function(files){ 381 | for (var i=0; i this._options.sizeLimit){ 422 | this._error('sizeError', name); 423 | return false; 424 | 425 | } else if (size && size < this._options.minSizeLimit){ 426 | this._error('minSizeError', name); 427 | return false; 428 | } 429 | 430 | return true; 431 | }, 432 | _error: function(code, fileName){ 433 | var message = this._options.messages[code]; 434 | function r(name, replacement){ message = message.replace(name, replacement); } 435 | 436 | r('{file}', this._formatFileName(fileName)); 437 | r('{extensions}', this._options.allowedExtensions.join(', ')); 438 | r('{sizeLimit}', this._formatSize(this._options.sizeLimit)); 439 | r('{minSizeLimit}', this._formatSize(this._options.minSizeLimit)); 440 | 441 | this._options.showMessage(message); 442 | }, 443 | _formatFileName: function(name){ 444 | if (name.length > 33){ 445 | name = name.slice(0, 19) + '...' + name.slice(-13); 446 | } 447 | return name; 448 | }, 449 | _isAllowedExtension: function(fileName){ 450 | var ext = (-1 !== fileName.indexOf('.')) ? fileName.replace(/.*[.]/, '').toLowerCase() : ''; 451 | var allowed = this._options.allowedExtensions; 452 | 453 | if (!allowed.length){return true;} 454 | 455 | for (var i=0; i 99); 467 | 468 | return Math.max(bytes, 0.1).toFixed(1) + ['kB', 'MB', 'GB', 'TB', 'PB', 'EB'][i]; 469 | } 470 | }; 471 | 472 | 473 | /** 474 | * Class that creates upload widget with drag-and-drop and file list 475 | * @inherits qq.FileUploaderBasic 476 | */ 477 | qq.FileUploader = function(o){ 478 | // call parent constructor 479 | qq.FileUploaderBasic.apply(this, arguments); 480 | 481 | // additional options 482 | qq.extend(this._options, { 483 | element: null, 484 | // if set, will be used instead of qq-upload-list in template 485 | listElement: null, 486 | 487 | template: '
' + 488 | '
Drop files here to upload
' + 489 | '
Select Files
' + 490 | '
    ' + 491 | '
    ', 492 | 493 | // template for one item in file list 494 | fileTemplate: '
  • ' + 495 | '' + 496 | '' + 497 | '' + 498 | 'Cancel' + 499 | 'Failed' + 500 | '
  • ', 501 | 502 | classes: { 503 | // used to get elements from templates 504 | button: 'qq-upload-button', 505 | drop: 'qq-upload-drop-area', 506 | dropActive: 'qq-upload-drop-area-active', 507 | list: 'qq-upload-list', 508 | 509 | file: 'qq-upload-file', 510 | spinner: 'qq-upload-spinner', 511 | size: 'qq-upload-size', 512 | cancel: 'qq-upload-cancel', 513 | 514 | // added to list item when upload completes 515 | // used in css to hide progress spinner 516 | success: 'qq-upload-success', 517 | fail: 'qq-upload-fail' 518 | } 519 | }); 520 | // overwrite options with user supplied 521 | qq.extend(this._options, o); 522 | 523 | this._element = this._options.element; 524 | this._element.innerHTML = this._options.template; 525 | this._listElement = this._options.listElement || this._find(this._element, 'list'); 526 | 527 | this._classes = this._options.classes; 528 | 529 | this._button = this._createUploadButton(this._find(this._element, 'button')); 530 | 531 | this._bindCancelEvent(); 532 | this._setupDragDrop(); 533 | }; 534 | 535 | // inherit from Basic Uploader 536 | qq.extend(qq.FileUploader.prototype, qq.FileUploaderBasic.prototype); 537 | 538 | qq.extend(qq.FileUploader.prototype, { 539 | /** 540 | * Gets one of the elements listed in this._options.classes 541 | **/ 542 | _find: function(parent, type){ 543 | var element = qq.getByClass(parent, this._options.classes[type])[0]; 544 | if (!element){ 545 | throw new Error('element not found ' + type); 546 | } 547 | 548 | return element; 549 | }, 550 | _setupDragDrop: function(){ 551 | var self = this, 552 | dropArea = this._find(this._element, 'drop'); 553 | 554 | var dz = new qq.UploadDropZone({ 555 | element: dropArea, 556 | onEnter: function(e){ 557 | qq.addClass(dropArea, self._classes.dropActive); 558 | e.stopPropagation(); 559 | }, 560 | onLeave: function(e){ 561 | e.stopPropagation(); 562 | }, 563 | onLeaveNotDescendants: function(e){ 564 | qq.removeClass(dropArea, self._classes.dropActive); 565 | }, 566 | onDrop: function(e){ 567 | dropArea.style.display = 'none'; 568 | qq.removeClass(dropArea, self._classes.dropActive); 569 | self._uploadFileList(e.dataTransfer.files); 570 | } 571 | }); 572 | 573 | dropArea.style.display = 'none'; 574 | 575 | qq.attach(document, 'dragenter', function(e){ 576 | if (!dz._isValidFileDrag(e)) return; 577 | 578 | dropArea.style.display = 'block'; 579 | }); 580 | qq.attach(document, 'dragleave', function(e){ 581 | if (!dz._isValidFileDrag(e)) return; 582 | 583 | var relatedTarget = document.elementFromPoint(e.clientX, e.clientY); 584 | // only fire when leaving document out 585 | if ( ! relatedTarget || relatedTarget.nodeName == "HTML"){ 586 | dropArea.style.display = 'none'; 587 | } 588 | }); 589 | }, 590 | _onSubmit: function(id, fileName){ 591 | qq.FileUploaderBasic.prototype._onSubmit.apply(this, arguments); 592 | this._addToList(id, fileName); 593 | }, 594 | _onProgress: function(id, fileName, loaded, total){ 595 | qq.FileUploaderBasic.prototype._onProgress.apply(this, arguments); 596 | 597 | var item = this._getItemByFileId(id); 598 | var size = this._find(item, 'size'); 599 | size.style.display = 'inline'; 600 | 601 | var text; 602 | if (loaded != total){ 603 | text = Math.round(loaded / total * 100) + '% from ' + this._formatSize(total); 604 | } else { 605 | text = this._formatSize(total); 606 | } 607 | 608 | qq.setText(size, text); 609 | }, 610 | _onComplete: function(id, fileName, result){ 611 | qq.FileUploaderBasic.prototype._onComplete.apply(this, arguments); 612 | 613 | // mark completed 614 | var item = this._getItemByFileId(id); 615 | qq.remove(this._find(item, 'cancel')); 616 | qq.remove(this._find(item, 'spinner')); 617 | 618 | if (result.success){ 619 | qq.addClass(item, this._classes.success); 620 | } else { 621 | qq.addClass(item, this._classes.fail); 622 | } 623 | }, 624 | _addToList: function(id, fileName){ 625 | var item = qq.toElement(this._options.fileTemplate); 626 | item.qqFileId = id; 627 | 628 | var fileElement = this._find(item, 'file'); 629 | qq.setText(fileElement, this._formatFileName(fileName)); 630 | this._find(item, 'size').style.display = 'none'; 631 | 632 | this._listElement.appendChild(item); 633 | }, 634 | _getItemByFileId: function(id){ 635 | var item = this._listElement.firstChild; 636 | 637 | // there can't be txt nodes in dynamically created list 638 | // and we can use nextSibling 639 | while (item){ 640 | if (item.qqFileId == id) return item; 641 | item = item.nextSibling; 642 | } 643 | }, 644 | /** 645 | * delegate click event for cancel link 646 | **/ 647 | _bindCancelEvent: function(){ 648 | var self = this, 649 | list = this._listElement; 650 | 651 | qq.attach(list, 'click', function(e){ 652 | e = e || window.event; 653 | var target = e.target || e.srcElement; 654 | 655 | if (qq.hasClass(target, self._classes.cancel)){ 656 | qq.preventDefault(e); 657 | 658 | var item = target.parentNode; 659 | self._handler.cancel(item.qqFileId); 660 | qq.remove(item); 661 | } 662 | }); 663 | } 664 | }); 665 | 666 | qq.UploadDropZone = function(o){ 667 | this._options = { 668 | element: null, 669 | onEnter: function(e){}, 670 | onLeave: function(e){}, 671 | // is not fired when leaving element by hovering descendants 672 | onLeaveNotDescendants: function(e){}, 673 | onDrop: function(e){} 674 | }; 675 | qq.extend(this._options, o); 676 | 677 | this._element = this._options.element; 678 | 679 | this._disableDropOutside(); 680 | this._attachEvents(); 681 | }; 682 | 683 | qq.UploadDropZone.prototype = { 684 | _disableDropOutside: function(e){ 685 | // run only once for all instances 686 | if (!qq.UploadDropZone.dropOutsideDisabled ){ 687 | 688 | qq.attach(document, 'dragover', function(e){ 689 | if (e.dataTransfer){ 690 | e.dataTransfer.dropEffect = 'none'; 691 | e.preventDefault(); 692 | } 693 | }); 694 | 695 | qq.UploadDropZone.dropOutsideDisabled = true; 696 | } 697 | }, 698 | _attachEvents: function(){ 699 | var self = this; 700 | 701 | qq.attach(self._element, 'dragover', function(e){ 702 | if (!self._isValidFileDrag(e)) return; 703 | 704 | var effect = e.dataTransfer.effectAllowed; 705 | if (effect == 'move' || effect == 'linkMove'){ 706 | e.dataTransfer.dropEffect = 'move'; // for FF (only move allowed) 707 | } else { 708 | e.dataTransfer.dropEffect = 'copy'; // for Chrome 709 | } 710 | 711 | e.stopPropagation(); 712 | e.preventDefault(); 713 | }); 714 | 715 | qq.attach(self._element, 'dragenter', function(e){ 716 | if (!self._isValidFileDrag(e)) return; 717 | 718 | self._options.onEnter(e); 719 | }); 720 | 721 | qq.attach(self._element, 'dragleave', function(e){ 722 | if (!self._isValidFileDrag(e)) return; 723 | 724 | self._options.onLeave(e); 725 | 726 | var relatedTarget = document.elementFromPoint(e.clientX, e.clientY); 727 | // do not fire when moving a mouse over a descendant 728 | if (qq.contains(this, relatedTarget)) return; 729 | 730 | self._options.onLeaveNotDescendants(e); 731 | }); 732 | 733 | qq.attach(self._element, 'drop', function(e){ 734 | if (!self._isValidFileDrag(e)) return; 735 | 736 | e.preventDefault(); 737 | self._options.onDrop(e); 738 | }); 739 | }, 740 | _isValidFileDrag: function(e){ 741 | var dt = e.dataTransfer, 742 | // do not check dt.types.contains in webkit, because it crashes safari 4 743 | isWebkit = navigator.userAgent.indexOf("AppleWebKit") > -1; 744 | 745 | // dt.effectAllowed is none in Safari 5 746 | // dt.types.contains check is for firefox 747 | return dt && dt.effectAllowed != 'none' && 748 | (dt.files || (!isWebkit && dt.types.contains && dt.types.contains('Files'))); 749 | 750 | } 751 | }; 752 | 753 | qq.UploadButton = function(o){ 754 | this._options = { 755 | element: null, 756 | // if set to true adds multiple attribute to file input 757 | multiple: false, 758 | // name attribute of file input 759 | name: 'file', 760 | onChange: function(input){}, 761 | hoverClass: 'qq-upload-button-hover', 762 | focusClass: 'qq-upload-button-focus' 763 | }; 764 | 765 | qq.extend(this._options, o); 766 | 767 | this._element = this._options.element; 768 | 769 | // make button suitable container for input 770 | qq.css(this._element, { 771 | position: 'relative', 772 | overflow: 'hidden', 773 | // Make sure browse button is in the right side 774 | // in Internet Explorer 775 | direction: 'ltr' 776 | }); 777 | 778 | this._input = this._createInput(); 779 | }; 780 | 781 | qq.UploadButton.prototype = { 782 | /* returns file input element */ 783 | getInput: function(){ 784 | return this._input; 785 | }, 786 | /* cleans/recreates the file input */ 787 | reset: function(){ 788 | if (this._input.parentNode){ 789 | qq.remove(this._input); 790 | } 791 | 792 | qq.removeClass(this._element, this._options.focusClass); 793 | this._input = this._createInput(); 794 | }, 795 | _createInput: function(){ 796 | var input = document.createElement("input"); 797 | 798 | if (this._options.multiple){ 799 | input.setAttribute("multiple", "multiple"); 800 | } 801 | 802 | input.setAttribute("type", "file"); 803 | input.setAttribute("name", this._options.name); 804 | 805 | qq.css(input, { 806 | position: 'absolute', 807 | // in Opera only 'browse' button 808 | // is clickable and it is located at 809 | // the right side of the input 810 | right: 0, 811 | top: 0, 812 | fontFamily: 'Arial', 813 | // 4 persons reported this, the max values that worked for them were 243, 236, 236, 118 814 | fontSize: '118px', 815 | margin: 0, 816 | padding: 0, 817 | cursor: 'pointer', 818 | opacity: 0 819 | }); 820 | 821 | this._element.appendChild(input); 822 | 823 | var self = this; 824 | qq.attach(input, 'change', function(){ 825 | self._options.onChange(input); 826 | }); 827 | 828 | qq.attach(input, 'mouseover', function(){ 829 | qq.addClass(self._element, self._options.hoverClass); 830 | }); 831 | qq.attach(input, 'mouseout', function(){ 832 | qq.removeClass(self._element, self._options.hoverClass); 833 | }); 834 | qq.attach(input, 'focus', function(){ 835 | qq.addClass(self._element, self._options.focusClass); 836 | }); 837 | qq.attach(input, 'blur', function(){ 838 | qq.removeClass(self._element, self._options.focusClass); 839 | }); 840 | 841 | // IE and Opera, unfortunately have 2 tab stops on file input 842 | // which is unacceptable in our case, disable keyboard access 843 | if (window.attachEvent){ 844 | // it is IE or Opera 845 | input.setAttribute('tabIndex', "-1"); 846 | } 847 | 848 | return input; 849 | } 850 | }; 851 | 852 | /** 853 | * Class for uploading files, uploading itself is handled by child classes 854 | */ 855 | qq.UploadHandlerAbstract = function(o){ 856 | this._options = { 857 | debug: false, 858 | action: '/upload.php', 859 | // maximum number of concurrent uploads 860 | maxConnections: 999, 861 | onProgress: function(id, fileName, loaded, total){}, 862 | onComplete: function(id, fileName, response){}, 863 | onCancel: function(id, fileName){} 864 | }; 865 | qq.extend(this._options, o); 866 | 867 | this._queue = []; 868 | // params for files in queue 869 | this._params = []; 870 | }; 871 | qq.UploadHandlerAbstract.prototype = { 872 | log: function(str){ 873 | if (this._options.debug && window.console) console.log('[uploader] ' + str); 874 | }, 875 | /** 876 | * Adds file or file input to the queue 877 | * @returns id 878 | **/ 879 | add: function(file){}, 880 | /** 881 | * Sends the file identified by id and additional query params to the server 882 | */ 883 | upload: function(id, params){ 884 | var len = this._queue.push(id); 885 | 886 | var copy = {}; 887 | qq.extend(copy, params); 888 | this._params[id] = copy; 889 | 890 | // if too many active uploads, wait... 891 | if (len <= this._options.maxConnections){ 892 | this._upload(id, this._params[id]); 893 | } 894 | }, 895 | /** 896 | * Cancels file upload by id 897 | */ 898 | cancel: function(id){ 899 | this._cancel(id); 900 | this._dequeue(id); 901 | }, 902 | /** 903 | * Cancells all uploads 904 | */ 905 | cancelAll: function(){ 906 | for (var i=0; i= max && i < max){ 944 | var nextId = this._queue[max-1]; 945 | this._upload(nextId, this._params[nextId]); 946 | } 947 | } 948 | }; 949 | 950 | /** 951 | * Class for uploading files using form and iframe 952 | * @inherits qq.UploadHandlerAbstract 953 | */ 954 | qq.UploadHandlerForm = function(o){ 955 | qq.UploadHandlerAbstract.apply(this, arguments); 956 | 957 | this._inputs = {}; 958 | }; 959 | // @inherits qq.UploadHandlerAbstract 960 | qq.extend(qq.UploadHandlerForm.prototype, qq.UploadHandlerAbstract.prototype); 961 | 962 | qq.extend(qq.UploadHandlerForm.prototype, { 963 | add: function(fileInput){ 964 | fileInput.setAttribute('name', 'qqfile'); 965 | var id = 'qq-upload-handler-iframe' + qq.getUniqueId(); 966 | 967 | this._inputs[id] = fileInput; 968 | 969 | // remove file input from DOM 970 | if (fileInput.parentNode){ 971 | qq.remove(fileInput); 972 | } 973 | 974 | return id; 975 | }, 976 | getName: function(id){ 977 | // get input value and remove path to normalize 978 | return this._inputs[id].value.replace(/.*(\/|\\)/, ""); 979 | }, 980 | _cancel: function(id){ 981 | this._options.onCancel(id, this.getName(id)); 982 | 983 | delete this._inputs[id]; 984 | 985 | var iframe = document.getElementById(id); 986 | if (iframe){ 987 | // to cancel request set src to something else 988 | // we use src="javascript:false;" because it doesn't 989 | // trigger ie6 prompt on https 990 | iframe.setAttribute('src', 'javascript:false;'); 991 | 992 | qq.remove(iframe); 993 | } 994 | }, 995 | _upload: function(id, params){ 996 | var input = this._inputs[id]; 997 | 998 | if (!input){ 999 | throw new Error('file with passed id was not added, or already uploaded or cancelled'); 1000 | } 1001 | 1002 | var fileName = this.getName(id); 1003 | 1004 | var iframe = this._createIframe(id); 1005 | var form = this._createForm(iframe, params); 1006 | form.appendChild(input); 1007 | 1008 | var self = this; 1009 | this._attachLoadEvent(iframe, function(){ 1010 | self.log('iframe loaded'); 1011 | 1012 | var response = self._getIframeContentJSON(iframe); 1013 | 1014 | self._options.onComplete(id, fileName, response); 1015 | self._dequeue(id); 1016 | 1017 | delete self._inputs[id]; 1018 | // timeout added to fix busy state in FF3.6 1019 | setTimeout(function(){ 1020 | qq.remove(iframe); 1021 | }, 1); 1022 | }); 1023 | 1024 | form.submit(); 1025 | qq.remove(form); 1026 | 1027 | return id; 1028 | }, 1029 | _attachLoadEvent: function(iframe, callback){ 1030 | qq.attach(iframe, 'load', function(){ 1031 | // when we remove iframe from dom 1032 | // the request stops, but in IE load 1033 | // event fires 1034 | if (!iframe.parentNode){ 1035 | return; 1036 | } 1037 | 1038 | // fixing Opera 10.53 1039 | if (iframe.contentDocument && 1040 | iframe.contentDocument.body && 1041 | iframe.contentDocument.body.innerHTML == "false"){ 1042 | // In Opera event is fired second time 1043 | // when body.innerHTML changed from false 1044 | // to server response approx. after 1 sec 1045 | // when we upload file with iframe 1046 | return; 1047 | } 1048 | 1049 | callback(); 1050 | }); 1051 | }, 1052 | /** 1053 | * Returns json object received by iframe from server. 1054 | */ 1055 | _getIframeContentJSON: function(iframe){ 1056 | // iframe.contentWindow.document - for IE<7 1057 | var doc = iframe.contentDocument ? iframe.contentDocument: iframe.contentWindow.document, 1058 | response; 1059 | 1060 | this.log("converting iframe's innerHTML to JSON"); 1061 | this.log("innerHTML = " + doc.body.innerHTML); 1062 | 1063 | try { 1064 | response = eval("(" + doc.body.innerHTML + ")"); 1065 | } catch(err){ 1066 | response = {}; 1067 | } 1068 | 1069 | return response; 1070 | }, 1071 | /** 1072 | * Creates iframe with unique name 1073 | */ 1074 | _createIframe: function(id){ 1075 | // We can't use following code as the name attribute 1076 | // won't be properly registered in IE6, and new window 1077 | // on form submit will open 1078 | // var iframe = document.createElement('iframe'); 1079 | // iframe.setAttribute('name', id); 1080 | 1081 | var iframe = qq.toElement('