+ Licensed under the MIT license
+ (See http://www.opensource.org/licenses/mit-license)
+*/
+function d(c){var b,a;if(!this.length)return this;b=this[0];b.ownerDocument?a=b.ownerDocument:(a=b,b=a.documentElement);if(null==c){if(!a.exitFullscreen&&!a.webkitExitFullscreen&&!a.webkitCancelFullScreen&&!a.msExitFullscreen&&!a.mozCancelFullScreen)return null;c=!!a.fullscreenElement||!!a.msFullscreenElement||!!a.webkitIsFullScreen||!!a.mozFullScreen;return!c?c:a.fullscreenElement||a.webkitFullscreenElement||a.webkitCurrentFullScreenElement||a.msFullscreenElement||a.mozFullScreenElement||c}c?(c=
+b.requestFullscreen||b.webkitRequestFullscreen||b.webkitRequestFullScreen||b.msRequestFullscreen||b.mozRequestFullScreen)&&c.call(b):(c=a.exitFullscreen||a.webkitExitFullscreen||a.webkitCancelFullScreen||a.msExitFullscreen||a.mozCancelFullScreen)&&c.call(a);return this}jQuery.fn.fullScreen=d;jQuery.fn.toggleFullScreen=function(){return d.call(this,!d.call(this))};var e,f,g;e=document;
+e.webkitCancelFullScreen?(f="webkitfullscreenchange",g="webkitfullscreenerror"):e.msExitFullscreen?(f="MSFullscreenChange",g="MSFullscreenError"):e.mozCancelFullScreen?(f="mozfullscreenchange",g="mozfullscreenerror"):(f="fullscreenchange",g="fullscreenerror");jQuery(document).bind(f,function(){jQuery(document).trigger(new jQuery.Event("fullscreenchange"))});jQuery(document).bind(g,function(){jQuery(document).trigger(new jQuery.Event("fullscreenerror"))});
\ No newline at end of file
diff --git a/app/mihaildev/elfinder/assets/js/no.conflict.js b/app/mihaildev/elfinder/assets/js/no.conflict.js
new file mode 100755
index 0000000..e6a43dd
--- /dev/null
+++ b/app/mihaildev/elfinder/assets/js/no.conflict.js
@@ -0,0 +1,5 @@
+jQuery(function(){
+ if(jQuery.fn.button.noConflict) {
+ jQuery.fn.btn = jQuery.fn.button.noConflict();
+ }
+});
diff --git a/app/mihaildev/elfinder/assets/js/proxy/elFinderSupportVer1.js b/app/mihaildev/elfinder/assets/js/proxy/elFinderSupportVer1.js
new file mode 100755
index 0000000..6c33dc6
--- /dev/null
+++ b/app/mihaildev/elfinder/assets/js/proxy/elFinderSupportVer1.js
@@ -0,0 +1,338 @@
+"use strict";
+/**
+ * elFinder transport to support old protocol.
+ *
+ * @example
+ * $('selector').elfinder({
+ * ....
+ * transport : new elFinderSupportVer1()
+ * })
+ *
+ * @author Dmitry (dio) Levashov
+ **/
+window.elFinderSupportVer1 = function(upload) {
+ var self = this;
+
+ this.upload = upload || 'auto';
+
+ this.init = function(fm) {
+ this.fm = fm;
+ this.fm.parseUploadData = function(text) {
+ var data;
+
+ if (!$.trim(text)) {
+ return {error : ['errResponse', 'errDataEmpty']};
+ }
+
+ try {
+ data = $.parseJSON(text);
+ } catch (e) {
+ return {error : ['errResponse', 'errDataNotJSON']}
+ }
+
+ return self.normalize('upload', data);
+ }
+ }
+
+
+ this.send = function(opts) {
+ var self = this,
+ fm = this.fm,
+ dfrd = $.Deferred(),
+ cmd = opts.data.cmd,
+ args = [],
+ _opts = {},
+ data,
+ xhr;
+
+ dfrd.abort = function() {
+ xhr.state() == 'pending' && xhr.abort();
+ }
+
+ switch (cmd) {
+ case 'open':
+ opts.data.tree = 1;
+ break;
+ case 'parents':
+ case 'tree':
+ return dfrd.resolve({tree : []});
+ break;
+ case 'get':
+ opts.data.cmd = 'read';
+ opts.data.current = fm.file(opts.data.target).phash;
+ break;
+ case 'put':
+ opts.data.cmd = 'edit';
+ opts.data.current = fm.file(opts.data.target).phash;
+ break;
+ case 'archive':
+ case 'rm':
+ opts.data.current = fm.file(opts.data.targets[0]).phash;
+ break;
+ case 'extract':
+ case 'rename':
+ case 'resize':
+ opts.data.current = fm.file(opts.data.target).phash;
+ break;
+ case 'duplicate':
+ _opts = $.extend(true, {}, opts);
+
+ $.each(opts.data.targets, function(i, hash) {
+ $.ajax($.extend(_opts, {data : {cmd : 'duplicate', target : hash, current : fm.file(hash).phash}}))
+ .error(function(error) {
+ fm.error(fm.res('error', 'connect'));
+ })
+ .done(function(data) {
+ data = self.normalize('duplicate', data);
+ if (data.error) {
+ fm.error(data.error);
+ } else if (data.added) {
+ fm.trigger('add', {added : data.added});
+ }
+ })
+ });
+ return dfrd.resolve({})
+ break;
+
+ case 'mkdir':
+ case 'mkfile':
+ opts.data.current = opts.data.target;
+ break;
+ case 'paste':
+ opts.data.current = opts.data.dst
+ break;
+
+ case 'size':
+ return dfrd.resolve({error : fm.res('error', 'cmdsupport')});
+ break;
+ case 'search':
+ return dfrd.resolve({error : fm.res('error', 'cmdsupport')});
+ break;
+
+ }
+ // cmd = opts.data.cmd
+
+ xhr = $.ajax(opts)
+ .fail(function(error) {
+ dfrd.reject(error)
+ })
+ .done(function(raw) {
+ data = self.normalize(cmd, raw);
+
+ // cmd != 'open' && self.fm.log(data);
+
+ if (cmd == 'paste' && !data.error) {
+ fm.sync();
+ dfrd.resolve({});
+ } else {
+ dfrd.resolve(data);
+ }
+ })
+
+ return dfrd;
+
+ return $.ajax(opts);
+ }
+
+ // fix old connectors errors messages as possible
+ // this.errors = {
+ // 'Unknown command' : 'Unknown command.',
+ // 'Invalid backend configuration' : 'Invalid backend configuration.',
+ // 'Access denied' : 'Access denied.',
+ // 'PHP JSON module not installed' : 'PHP JSON module not installed.',
+ // 'File not found' : 'File not found.',
+ // 'Invalid name' : 'Invalid file name.',
+ // 'File or folder with the same name already exists' : 'File named "$1" already exists in this location.',
+ // 'Not allowed file type' : 'Not allowed file type.',
+ // 'File exceeds the maximum allowed filesize' : 'File exceeds maximum allowed size.',
+ // 'Unable to copy into itself' : 'Unable to copy "$1" into itself.',
+ // 'Unable to create archive' : 'Unable to create archive.',
+ // 'Unable to extract files from archive' : 'Unable to extract files from "$1".'
+ // }
+
+ this.normalize = function(cmd, data) {
+ var self = this,
+ files = {},
+ filter = function(file) { return file && file.hash && file.name && file.mime ? file : null; },
+ phash;
+
+ if ((cmd == 'tmb' || cmd == 'get')) {
+ return data;
+ }
+
+ // if (data.error) {
+ // $.each(data.error, function(i, msg) {
+ // if (self.errors[msg]) {
+ // data.error[i] = self.errors[msg];
+ // }
+ // });
+ // }
+
+ if (cmd == 'upload' && data.error && data.cwd) {
+ data.warning = $.extend({}, data.error);
+ data.error = false;
+ }
+
+
+ if (data.error) {
+ return data;
+ }
+
+ if (cmd == 'put') {
+
+ phash = this.fm.file(data.target.hash).phash;
+ return {changed : [this.normalizeFile(data.target, phash)]};
+ }
+
+ phash = data.cwd.hash;
+
+ if (data.tree) {
+ $.each(this.normalizeTree(data.tree), function(i, file) {
+ files[file.hash] = file;
+ });
+ }
+
+ $.each(data.cdc||[], function(i, file) {
+ var hash = file.hash;
+
+ if (files[hash]) {
+ files[hash].date = file.date;
+ files[hash].locked = file.hash == phash ? true : file.rm === void(0) ? false : !file.rm;
+ } else {
+ files[hash] = self.normalizeFile(file, phash, data.tmb);
+ }
+ });
+
+ if (!data.tree) {
+ $.each(this.fm.files(), function(hash, file) {
+ if (!files[hash] && file.phash != phash && file.mime == 'directory') {
+ files[hash] = file;
+ }
+ });
+ }
+
+ if (cmd == 'open') {
+ return {
+ cwd : files[phash] || this.normalizeFile(data.cwd),
+ files : $.map(files, function(f) { return f }),
+ options : self.normalizeOptions(data),
+ init : !!data.params,
+ debug : data.debug
+ };
+ }
+
+
+
+ return $.extend({
+ current : data.cwd.hash,
+ error : data.error,
+ warning : data.warning,
+ options : {tmb : !!data.tmb}
+ }, this.fm.diff($.map(files, filter)));
+
+ }
+
+ /**
+ * Convert old api tree into plain array of dirs
+ *
+ * @param Object root dir
+ * @return Array
+ */
+ this.normalizeTree = function(root) {
+ var self = this,
+ result = [],
+ traverse = function(dirs, phash) {
+ var i, dir;
+
+ for (i = 0; i < dirs.length; i++) {
+ dir = dirs[i];
+ result.push(self.normalizeFile(dir, phash))
+ dir.dirs.length && traverse(dir.dirs, dir.hash);
+ }
+ };
+
+ traverse([root]);
+
+ return result;
+ }
+
+ /**
+ * Convert file info from old api format into new one
+ *
+ * @param Object file
+ * @param String parent dir hash
+ * @return Object
+ */
+ this.normalizeFile = function(file, phash, tmb) {
+ var mime = file.mime || 'directory',
+ size = mime == 'directory' && !file.linkTo ? 0 : file.size,
+ info = {
+ url : file.url,
+ hash : file.hash,
+ phash : phash,
+ name : file.name,
+ mime : mime,
+ date : file.date || 'unknown',
+ size : size,
+ read : file.read,
+ write : file.write,
+ locked : !phash ? true : file.rm === void(0) ? false : !file.rm
+ };
+
+ if (file.mime == 'application/x-empty') {
+ info.mime = 'text/plain';
+ }
+ if (file.linkTo) {
+ info.alias = file.linkTo;
+ }
+
+ if (file.linkTo) {
+ info.linkTo = file.linkTo;
+ }
+
+ if (file.tmb) {
+ info.tmb = file.tmb;
+ } else if (info.mime.indexOf('image/') === 0 && tmb) {
+ info.tmb = 1;
+
+ }
+
+ if (file.dirs && file.dirs.length) {
+ info.dirs = true;
+ }
+ if (file.dim) {
+ info.dim = file.dim;
+ }
+ if (file.resize) {
+ info.resize = file.resize;
+ }
+ return info;
+ }
+
+ this.normalizeOptions = function(data) {
+ var opts = {
+ path : data.cwd.rel,
+ disabled : data.disabled || [],
+ tmb : !!data.tmb,
+ copyOverwrite : true
+ };
+
+ if (data.params) {
+ opts.api = 1;
+ opts.url = data.params.url;
+ opts.archivers = {
+ create : data.params.archives || [],
+ extract : data.params.extract || []
+ }
+ }
+
+ if (opts.path.indexOf('/') !== -1) {
+ opts.separator = '/';
+ } else if (opts.path.indexOf('\\') !== -1) {
+ opts.separator = '\\';
+ }
+ return opts;
+ }
+
+
+}
diff --git a/app/mihaildev/elfinder/composer.json b/app/mihaildev/elfinder/composer.json
new file mode 100755
index 0000000..5254045
--- /dev/null
+++ b/app/mihaildev/elfinder/composer.json
@@ -0,0 +1,22 @@
+{
+ "name": "mihaildev/yii2-elfinder",
+ "keywords": ["yii", "elfinder", "filemanager"],
+ "description": "Yii2 ElFinder",
+ "homepage": "https://github.com/MihailDev/yii2-elfinder",
+ "type": "yii2-extension",
+ "license": "BSD-3-Clause",
+ "authors": [
+ {
+ "name": "Mihail",
+ "email": "mihail.kucher@gmail.com",
+ "homepage": "https://github.com/MihailDev",
+ "role": "Developer"
+ }
+ ],
+ "autoload": {
+ "psr-4": {"mihaildev\\elfinder\\": ""}
+ },
+ "require": {
+ "yiisoft/yii2-jui": "*"
+ }
+}
\ No newline at end of file
diff --git a/app/mihaildev/elfinder/php/MySQLStorage.sql b/app/mihaildev/elfinder/php/MySQLStorage.sql
new file mode 100755
index 0000000..67a33ec
--- /dev/null
+++ b/app/mihaildev/elfinder/php/MySQLStorage.sql
@@ -0,0 +1,23 @@
+DROP TABLE IF EXISTS `elfinder_file`;
+CREATE TABLE IF NOT EXISTS `elfinder_file` (
+ `id` int(7) unsigned NOT NULL auto_increment,
+ `parent_id` int(7) unsigned NOT NULL,
+ `name` varchar(256) NOT NULL,
+ `content` longblob NOT NULL,
+ `size` int(10) unsigned NOT NULL default '0',
+ `mtime` int(10) unsigned NOT NULL,
+ `mime` varchar(256) NOT NULL default 'unknown',
+ `read` enum('1', '0') NOT NULL default '1',
+ `write` enum('1', '0') NOT NULL default '1',
+ `locked` enum('1', '0') NOT NULL default '0',
+ `hidden` enum('1', '0') NOT NULL default '0',
+ `width` int(5) NOT NULL,
+ `height` int(5) NOT NULL,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `parent_name` (`parent_id`, `name`),
+ KEY `parent_id` (`parent_id`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
+
+INSERT INTO `elfinder_file`
+(`id`, `parent_id`, `name`, `content`, `size`, `mtime`, `mime`, `read`, `write`, `locked`, `hidden`, `width`, `height`) VALUES
+('1', '0', 'DATABASE', '', '0', '0', 'directory', '1', '1', '0', '0', '0', '0');
diff --git a/app/mihaildev/elfinder/php/connector.minimal.php b/app/mihaildev/elfinder/php/connector.minimal.php
new file mode 100755
index 0000000..a98ba17
--- /dev/null
+++ b/app/mihaildev/elfinder/php/connector.minimal.php
@@ -0,0 +1,47 @@
+ true,
+ 'roots' => array(
+ array(
+ 'driver' => 'LocalFileSystem', // driver for accessing file system (REQUIRED)
+ 'path' => '../files/', // path to files (REQUIRED)
+ 'URL' => dirname($_SERVER['PHP_SELF']) . '/../files/', // URL to files (REQUIRED)
+ 'accessControl' => 'access' // disable and hide dot starting files (OPTIONAL)
+ )
+ )
+);
+
+// run elFinder
+$connector = new elFinderConnector(new elFinder($opts));
+$connector->run();
+
diff --git a/app/mihaildev/elfinder/php/connector.php b/app/mihaildev/elfinder/php/connector.php
new file mode 100755
index 0000000..a98ba17
--- /dev/null
+++ b/app/mihaildev/elfinder/php/connector.php
@@ -0,0 +1,47 @@
+ true,
+ 'roots' => array(
+ array(
+ 'driver' => 'LocalFileSystem', // driver for accessing file system (REQUIRED)
+ 'path' => '../files/', // path to files (REQUIRED)
+ 'URL' => dirname($_SERVER['PHP_SELF']) . '/../files/', // URL to files (REQUIRED)
+ 'accessControl' => 'access' // disable and hide dot starting files (OPTIONAL)
+ )
+ )
+);
+
+// run elFinder
+$connector = new elFinderConnector(new elFinder($opts));
+$connector->run();
+
diff --git a/app/mihaildev/elfinder/php/elFinder.class.php b/app/mihaildev/elfinder/php/elFinder.class.php
new file mode 100755
index 0000000..163748e
--- /dev/null
+++ b/app/mihaildev/elfinder/php/elFinder.class.php
@@ -0,0 +1,1560 @@
+ array('target' => false, 'tree' => false, 'init' => false, 'mimes' => false),
+ 'ls' => array('target' => true, 'mimes' => false),
+ 'tree' => array('target' => true),
+ 'parents' => array('target' => true),
+ 'tmb' => array('targets' => true),
+ 'file' => array('target' => true, 'download' => false),
+ 'size' => array('targets' => true),
+ 'mkdir' => array('target' => true, 'name' => true),
+ 'mkfile' => array('target' => true, 'name' => true, 'mimes' => false),
+ 'rm' => array('targets' => true),
+ 'rename' => array('target' => true, 'name' => true, 'mimes' => false),
+ 'duplicate' => array('targets' => true, 'suffix' => false),
+ 'paste' => array('dst' => true, 'targets' => true, 'cut' => false, 'mimes' => false),
+ 'upload' => array('target' => true, 'FILES' => true, 'mimes' => false, 'html' => false, 'upload' => false, 'name' => false, 'upload_path' => false),
+ 'get' => array('target' => true),
+ 'put' => array('target' => true, 'content' => '', 'mimes' => false),
+ 'archive' => array('targets' => true, 'type' => true, 'mimes' => false),
+ 'extract' => array('target' => true, 'mimes' => false),
+ 'search' => array('q' => true, 'mimes' => false),
+ 'info' => array('targets' => true),
+ 'dim' => array('target' => true),
+ 'resize' => array('target' => true, 'width' => true, 'height' => true, 'mode' => false, 'x' => false, 'y' => false, 'degree' => false),
+ 'netmount' => array('protocol' => true, 'host' => true, 'path' => false, 'port' => false, 'user' => true, 'pass' => true, 'alias' => false, 'options' => false)
+ );
+
+ /**
+ * Plugins instance
+ *
+ * @var array
+ **/
+ protected $plugins = array();
+
+ /**
+ * Commands listeners
+ *
+ * @var array
+ **/
+ protected $listeners = array();
+
+ /**
+ * script work time for debug
+ *
+ * @var string
+ **/
+ protected $time = 0;
+ /**
+ * Is elFinder init correctly?
+ *
+ * @var bool
+ **/
+ protected $loaded = false;
+ /**
+ * Send debug to client?
+ *
+ * @var string
+ **/
+ protected $debug = false;
+
+ /**
+ * session expires timeout
+ *
+ * @var int
+ **/
+ protected $timeout = 0;
+
+ /**
+ * undocumented class variable
+ *
+ * @var string
+ **/
+ protected $uploadDebug = '';
+
+ /**
+ * Errors from not mounted volumes
+ *
+ * @var array
+ **/
+ public $mountErrors = array();
+
+ // Errors messages
+ const ERROR_UNKNOWN = 'errUnknown';
+ const ERROR_UNKNOWN_CMD = 'errUnknownCmd';
+ const ERROR_CONF = 'errConf';
+ const ERROR_CONF_NO_JSON = 'errJSON';
+ const ERROR_CONF_NO_VOL = 'errNoVolumes';
+ const ERROR_INV_PARAMS = 'errCmdParams';
+ const ERROR_OPEN = 'errOpen';
+ const ERROR_DIR_NOT_FOUND = 'errFolderNotFound';
+ const ERROR_FILE_NOT_FOUND = 'errFileNotFound'; // 'File not found.'
+ const ERROR_TRGDIR_NOT_FOUND = 'errTrgFolderNotFound'; // 'Target folder "$1" not found.'
+ const ERROR_NOT_DIR = 'errNotFolder';
+ const ERROR_NOT_FILE = 'errNotFile';
+ const ERROR_PERM_DENIED = 'errPerm';
+ const ERROR_LOCKED = 'errLocked'; // '"$1" is locked and can not be renamed, moved or removed.'
+ const ERROR_EXISTS = 'errExists'; // 'File named "$1" already exists.'
+ const ERROR_INVALID_NAME = 'errInvName'; // 'Invalid file name.'
+ const ERROR_MKDIR = 'errMkdir';
+ const ERROR_MKFILE = 'errMkfile';
+ const ERROR_RENAME = 'errRename';
+ const ERROR_COPY = 'errCopy';
+ const ERROR_MOVE = 'errMove';
+ const ERROR_COPY_FROM = 'errCopyFrom';
+ const ERROR_COPY_TO = 'errCopyTo';
+ const ERROR_COPY_ITSELF = 'errCopyInItself';
+ const ERROR_REPLACE = 'errReplace'; // 'Unable to replace "$1".'
+ const ERROR_RM = 'errRm'; // 'Unable to remove "$1".'
+ const ERROR_RM_SRC = 'errRmSrc'; // 'Unable remove source file(s)'
+ const ERROR_UPLOAD = 'errUpload'; // 'Upload error.'
+ const ERROR_UPLOAD_FILE = 'errUploadFile'; // 'Unable to upload "$1".'
+ const ERROR_UPLOAD_NO_FILES = 'errUploadNoFiles'; // 'No files found for upload.'
+ const ERROR_UPLOAD_TOTAL_SIZE = 'errUploadTotalSize'; // 'Data exceeds the maximum allowed size.'
+ const ERROR_UPLOAD_FILE_SIZE = 'errUploadFileSize'; // 'File exceeds maximum allowed size.'
+ const ERROR_UPLOAD_FILE_MIME = 'errUploadMime'; // 'File type not allowed.'
+ const ERROR_UPLOAD_TRANSFER = 'errUploadTransfer'; // '"$1" transfer error.'
+ // const ERROR_ACCESS_DENIED = 'errAccess';
+ const ERROR_NOT_REPLACE = 'errNotReplace'; // Object "$1" already exists at this location and can not be replaced with object of another type.
+ const ERROR_SAVE = 'errSave';
+ const ERROR_EXTRACT = 'errExtract';
+ const ERROR_ARCHIVE = 'errArchive';
+ const ERROR_NOT_ARCHIVE = 'errNoArchive';
+ const ERROR_ARCHIVE_TYPE = 'errArcType';
+ const ERROR_ARC_SYMLINKS = 'errArcSymlinks';
+ const ERROR_ARC_MAXSIZE = 'errArcMaxSize';
+ const ERROR_RESIZE = 'errResize';
+ const ERROR_UNSUPPORT_TYPE = 'errUsupportType';
+ const ERROR_NOT_UTF8_CONTENT = 'errNotUTF8Content';
+ const ERROR_NETMOUNT = 'errNetMount';
+ const ERROR_NETMOUNT_NO_DRIVER = 'errNetMountNoDriver';
+ const ERROR_NETMOUNT_FAILED = 'errNetMountFailed';
+
+ const ERROR_SESSION_EXPIRES = 'errSessionExpires';
+
+ const ERROR_CREATING_TEMP_DIR = 'errCreatingTempDir';
+ const ERROR_FTP_DOWNLOAD_FILE = 'errFtpDownloadFile';
+ const ERROR_FTP_UPLOAD_FILE = 'errFtpUploadFile';
+ const ERROR_FTP_MKDIR = 'errFtpMkdir';
+ const ERROR_ARCHIVE_EXEC = 'errArchiveExec';
+ const ERROR_EXTRACT_EXEC = 'errExtractExec';
+
+ /**
+ * Constructor
+ *
+ * @param array elFinder and roots configurations
+ * @return void
+ * @author Dmitry (dio) Levashov
+ **/
+ public function __construct($opts) {
+ if (session_id() == '') {
+ session_start();
+ }
+
+ $this->time = $this->utime();
+ $this->debug = (isset($opts['debug']) && $opts['debug'] ? true : false);
+ $this->timeout = (isset($opts['timeout']) ? $opts['timeout'] : 0);
+
+ setlocale(LC_ALL, !empty($opts['locale']) ? $opts['locale'] : 'en_US.UTF-8');
+
+ // bind events listeners
+ if (!empty($opts['bind']) && is_array($opts['bind'])) {
+ $_req = $_SERVER["REQUEST_METHOD"] == 'POST' ? $_POST : $_GET;
+ $_reqCmd = isset($_req['cmd']) ? $_req['cmd'] : '';
+ foreach ($opts['bind'] as $cmd => $handlers) {
+ $doRegist = (strpos($cmd, '*') !== false);
+ if (! $doRegist) {
+ $_getcmd = create_function('$cmd', 'list($ret) = explode(\'.\', $cmd);return trim($ret);');
+ $doRegist = ($_reqCmd && in_array($_reqCmd, array_map($_getcmd, explode(' ', $cmd))));
+ }
+ if ($doRegist) {
+ if (! is_array($handlers) || is_object($handlers[0])) {
+ $handlers = array($handlers);
+ }
+ foreach($handlers as $handler) {
+ if ($handler) {
+ if (is_string($handler) && strpos($handler, '.')) {
+ list($_domain, $_name, $_method) = array_pad(explode('.', $handler), 3, '');
+ if (strcasecmp($_domain, 'plugin') === 0) {
+ if ($plugin = $this->getPluginInstance($_name, isset($opts['plugin'][$_name])? $opts['plugin'][$_name] : array())
+ and method_exists($plugin, $_method)) {
+ $this->bind($cmd, array($plugin, $_method));
+ }
+ }
+ } else {
+ $this->bind($cmd, $handler);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!isset($opts['roots']) || !is_array($opts['roots'])) {
+ $opts['roots'] = array();
+ }
+
+ // check for net volumes stored in session
+ foreach ($this->getNetVolumes() as $root) {
+ $opts['roots'][] = $root;
+ }
+
+ // "mount" volumes
+ foreach ($opts['roots'] as $i => $o) {
+ $class = 'elFinderVolume'.(isset($o['driver']) ? $o['driver'] : '');
+
+ if (class_exists($class)) {
+ $volume = new $class();
+
+ if ($volume->mount($o)) {
+ // unique volume id (ends on "_") - used as prefix to files hash
+ $id = $volume->id();
+
+ $this->volumes[$id] = $volume;
+ if (!$this->default && $volume->isReadable()) {
+ $this->default = $this->volumes[$id];
+ }
+ } else {
+ $this->mountErrors[] = 'Driver "'.$class.'" : '.implode(' ', $volume->error());
+ }
+ } else {
+ $this->mountErrors[] = 'Driver "'.$class.'" does not exists';
+ }
+ }
+
+ // if at least one redable volume - ii desu >_<
+ $this->loaded = !empty($this->default);
+ }
+
+ /**
+ * Return true if fm init correctly
+ *
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ public function loaded() {
+ return $this->loaded;
+ }
+
+ /**
+ * Return version (api) number
+ *
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ public function version() {
+ return $this->version;
+ }
+
+ /**
+ * Add handler to elFinder command
+ *
+ * @param string command name
+ * @param string|array callback name or array(object, method)
+ * @return elFinder
+ * @author Dmitry (dio) Levashov
+ **/
+ public function bind($cmd, $handler) {
+ $allCmds = array_keys($this->commands);
+ $cmds = array();
+ foreach(explode(' ', $cmd) as $_cmd) {
+ if ($_cmd !== '') {
+ if ($all = strpos($_cmd, '*') !== false) {
+ list(, $sub) = array_pad(explode('.', $_cmd), 2, '');
+ if ($sub) {
+ $sub = str_replace('\'', '\\\'', $sub);
+ $addSub = create_function('$cmd', 'return $cmd . \'.\' . trim(\'' . $sub . '\');');
+ $cmds = array_merge($cmds, array_map($addSub, $allCmds));
+ } else {
+ $cmds = array_merge($cmds, $allCmds);
+ }
+ } else {
+ $cmds[] = $_cmd;
+ }
+ }
+ }
+ $cmds = array_unique($cmds);
+
+ foreach ($cmds as $cmd) {
+ if (!isset($this->listeners[$cmd])) {
+ $this->listeners[$cmd] = array();
+ }
+
+ if (is_callable($handler)) {
+ $this->listeners[$cmd][] = $handler;
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Remove event (command exec) handler
+ *
+ * @param string command name
+ * @param string|array callback name or array(object, method)
+ * @return elFinder
+ * @author Dmitry (dio) Levashov
+ **/
+ public function unbind($cmd, $handler) {
+ if (!empty($this->listeners[$cmd])) {
+ foreach ($this->listeners[$cmd] as $i => $h) {
+ if ($h === $handler) {
+ unset($this->listeners[$cmd][$i]);
+ return $this;
+ }
+ }
+ }
+ return $this;
+ }
+
+ /**
+ * Return true if command exists
+ *
+ * @param string command name
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ public function commandExists($cmd) {
+ return $this->loaded && isset($this->commands[$cmd]) && method_exists($this, $cmd);
+ }
+
+ /**
+ * Return command required arguments info
+ *
+ * @param string command name
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ public function commandArgsList($cmd) {
+ return $this->commandExists($cmd) ? $this->commands[$cmd] : array();
+ }
+
+ private function session_expires() {
+
+ if (!isset($_SESSION['LAST_ACTIVITY'])) {
+ $_SESSION['LAST_ACTIVITY'] = time();
+ return false;
+ }
+
+ if ( ($this->timeout > 0) && (time() - $_SESSION['LAST_ACTIVITY'] > $this->timeout) ) {
+ return true;
+ }
+
+ $_SESSION['LAST_ACTIVITY'] = time();
+ return false;
+ }
+
+ /**
+ * Exec command and return result
+ *
+ * @param string $cmd command name
+ * @param array $args command arguments
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ public function exec($cmd, $args) {
+
+ if (!$this->loaded) {
+ return array('error' => $this->error(self::ERROR_CONF, self::ERROR_CONF_NO_VOL));
+ }
+
+ if ($this->session_expires()) {
+ return array('error' => $this->error(self::ERROR_SESSION_EXPIRES));
+ }
+
+ if (!$this->commandExists($cmd)) {
+ return array('error' => $this->error(self::ERROR_UNKNOWN_CMD));
+ }
+
+ if (!empty($args['mimes']) && is_array($args['mimes'])) {
+ foreach ($this->volumes as $id => $v) {
+ $this->volumes[$id]->setMimesFilter($args['mimes']);
+ }
+ }
+
+ // call pre handlers for this command
+ if (!empty($this->listeners[$cmd.'.pre'])) {
+ $volume = isset($args['target'])? $this->volume($args['target']) : false;
+ foreach ($this->listeners[$cmd.'.pre'] as $handler) {
+ call_user_func_array($handler, array($cmd, &$args, $this, $volume));
+ }
+ }
+
+ $result = $this->$cmd($args);
+
+ if (isset($result['removed'])) {
+ foreach ($this->volumes as $volume) {
+ $result['removed'] = array_merge($result['removed'], $volume->removed());
+ $volume->resetRemoved();
+ }
+ }
+
+ // call handlers for this command
+ if (!empty($this->listeners[$cmd])) {
+ foreach ($this->listeners[$cmd] as $handler) {
+ if (call_user_func($handler,$cmd,$result,$args,$this)) {
+ // handler return true to force sync client after command completed
+ $result['sync'] = true;
+ }
+ }
+ }
+
+ // replace removed files info with removed files hashes
+ if (!empty($result['removed'])) {
+ $removed = array();
+ foreach ($result['removed'] as $file) {
+ $removed[] = $file['hash'];
+ }
+ $result['removed'] = array_unique($removed);
+ }
+ // remove hidden files and filter files by mimetypes
+ if (!empty($result['added'])) {
+ $result['added'] = $this->filter($result['added']);
+ }
+ // remove hidden files and filter files by mimetypes
+ if (!empty($result['changed'])) {
+ $result['changed'] = $this->filter($result['changed']);
+ }
+
+ if ($this->debug || !empty($args['debug'])) {
+ $result['debug'] = array(
+ 'connector' => 'php',
+ 'phpver' => PHP_VERSION,
+ 'time' => $this->utime() - $this->time,
+ 'memory' => (function_exists('memory_get_peak_usage') ? ceil(memory_get_peak_usage()/1024).'Kb / ' : '').ceil(memory_get_usage()/1024).'Kb / '.ini_get('memory_limit'),
+ 'upload' => $this->uploadDebug,
+ 'volumes' => array(),
+ 'mountErrors' => $this->mountErrors
+ );
+
+ foreach ($this->volumes as $id => $volume) {
+ $result['debug']['volumes'][] = $volume->debug();
+ }
+ }
+
+ foreach ($this->volumes as $volume) {
+ $volume->umount();
+ }
+
+ return $result;
+ }
+
+ /**
+ * Return file real path
+ *
+ * @param string $hash file hash
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ public function realpath($hash) {
+ if (($volume = $this->volume($hash)) == false) {
+ return false;
+ }
+ return $volume->realpath($hash);
+ }
+
+ /**
+ * Return network volumes config.
+ *
+ * @return array
+ * @author Dmitry (dio) Levashov
+ */
+ protected function getNetVolumes() {
+ return isset($_SESSION['elFinderNetVolumes']) && is_array($_SESSION['elFinderNetVolumes']) ? $_SESSION['elFinderNetVolumes'] : array();
+ }
+
+ /**
+ * Save network volumes config.
+ *
+ * @param array $volumes volumes config
+ * @return void
+ * @author Dmitry (dio) Levashov
+ */
+ protected function saveNetVolumes($volumes) {
+ $_SESSION['elFinderNetVolumes'] = $volumes;
+ }
+
+ /**
+ * Get plugin instance & set to $this->plugins
+ *
+ * @param string $name Plugin name (dirctory name)
+ * @param array $opts Plugin options (optional)
+ * @return object | bool Plugin object instance Or false
+ * @author Naoki Sawada
+ */
+ protected function getPluginInstance($name, $opts = array()) {
+ $key = strtolower($name);
+ if (! isset($this->plugins[$key])) {
+ $p_file = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . $name . DIRECTORY_SEPARATOR . 'plugin.php';
+ if (is_file($p_file)) {
+ require_once $p_file;
+ $class = 'elFinderPlugin' . $name;
+ $this->plugins[$key] = new $class($opts);
+ } else {
+ $this->plugins[$key] = false;
+ }
+ }
+ return $this->plugins[$key];
+ }
+
+ /***************************************************************************/
+ /* commands */
+ /***************************************************************************/
+
+ /**
+ * Normalize error messages
+ *
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ public function error() {
+ $errors = array();
+
+ foreach (func_get_args() as $msg) {
+ if (is_array($msg)) {
+ $errors = array_merge($errors, $msg);
+ } else {
+ $errors[] = $msg;
+ }
+ }
+
+ return count($errors) ? $errors : array(self::ERROR_UNKNOWN);
+ }
+
+ protected function netmount($args) {
+ $options = array();
+ $protocol = $args['protocol'];
+ $driver = isset(self::$netDrivers[$protocol]) ? $protocol : '';
+ $class = 'elfindervolume'.$protocol;
+
+ if (!$driver) {
+ return array('error' => $this->error(self::ERROR_NETMOUNT, $args['host'], self::ERROR_NETMOUNT_NO_DRIVER));
+ }
+
+ if (!$args['path']) {
+ $args['path'] = '/';
+ }
+
+ foreach ($args as $k => $v) {
+ if ($k != 'options' && $k != 'protocol' && $v) {
+ $options[$k] = $v;
+ }
+ }
+
+ if (is_array($args['options'])) {
+ foreach ($args['options'] as $key => $value) {
+ $options[$key] = $value;
+ }
+ }
+
+ $volume = new $class();
+
+ if ($volume->mount($options)) {
+ $netVolumes = $this->getNetVolumes();
+ $options['driver'] = $driver;
+ $netVolumes[] = $options;
+ $netVolumes = array_unique($netVolumes);
+ $this->saveNetVolumes($netVolumes);
+ return array('sync' => true);
+ } else {
+ return array('error' => $this->error(self::ERROR_NETMOUNT, $args['host'], implode(' ', $volume->error())));
+ }
+
+ }
+
+ /**
+ * "Open" directory
+ * Return array with following elements
+ * - cwd - opened dir info
+ * - files - opened dir content [and dirs tree if $args[tree]]
+ * - api - api version (if $args[init])
+ * - uplMaxSize - if $args[init]
+ * - error - on failed
+ *
+ * @param array command arguments
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function open($args) {
+ $target = $args['target'];
+ $init = !empty($args['init']);
+ $tree = !empty($args['tree']);
+ $volume = $this->volume($target);
+ $cwd = $volume ? $volume->dir($target, true) : false;
+ $hash = $init ? 'default folder' : '#'.$target;
+
+ // on init request we can get invalid dir hash -
+ // dir which can not be opened now, but remembered by client,
+ // so open default dir
+ if ((!$cwd || !$cwd['read']) && $init) {
+ $volume = $this->default;
+ $cwd = $volume->dir($volume->defaultPath(), true);
+ }
+
+ if (!$cwd) {
+ return array('error' => $this->error(self::ERROR_OPEN, $hash, self::ERROR_DIR_NOT_FOUND));
+ }
+ if (!$cwd['read']) {
+ return array('error' => $this->error(self::ERROR_OPEN, $hash, self::ERROR_PERM_DENIED));
+ }
+
+ $files = array();
+
+ // get folders trees
+ if ($args['tree']) {
+ foreach ($this->volumes as $id => $v) {
+ if (($tree = $v->tree('', 0, $cwd['hash'])) != false) {
+ $files = array_merge($files, $tree);
+ }
+ }
+ }
+
+ // get current working directory files list and add to $files if not exists in it
+ if (($ls = $volume->scandir($cwd['hash'])) === false) {
+ return array('error' => $this->error(self::ERROR_OPEN, $cwd['name'], $volume->error()));
+ }
+
+ foreach ($ls as $file) {
+ if (!in_array($file, $files)) {
+ $files[] = $file;
+ }
+ }
+
+ $result = array(
+ 'cwd' => $cwd,
+ 'options' => $volume->options($cwd['hash']),
+ 'files' => $files
+ );
+
+ if (!empty($args['init'])) {
+ $result['api'] = $this->version;
+ $result['uplMaxSize'] = ini_get('upload_max_filesize');
+ $result['uplMaxFile'] = ini_get('max_file_uploads');
+ $result['netDrivers'] = array_keys(self::$netDrivers);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Return dir files names list
+ *
+ * @param array command arguments
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function ls($args) {
+ $target = $args['target'];
+
+ if (($volume = $this->volume($target)) == false
+ || ($list = $volume->ls($target)) === false) {
+ return array('error' => $this->error(self::ERROR_OPEN, '#'.$target));
+ }
+ return array('list' => $list);
+ }
+
+ /**
+ * Return subdirs for required directory
+ *
+ * @param array command arguments
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function tree($args) {
+ $target = $args['target'];
+
+ if (($volume = $this->volume($target)) == false
+ || ($tree = $volume->tree($target)) == false) {
+ return array('error' => $this->error(self::ERROR_OPEN, '#'.$target));
+ }
+
+ return array('tree' => $tree);
+ }
+
+ /**
+ * Return parents dir for required directory
+ *
+ * @param array command arguments
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function parents($args) {
+ $target = $args['target'];
+
+ if (($volume = $this->volume($target)) == false
+ || ($tree = $volume->parents($target)) == false) {
+ return array('error' => $this->error(self::ERROR_OPEN, '#'.$target));
+ }
+
+ return array('tree' => $tree);
+ }
+
+ /**
+ * Return new created thumbnails list
+ *
+ * @param array command arguments
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function tmb($args) {
+
+ $result = array('images' => array());
+ $targets = $args['targets'];
+
+ foreach ($targets as $target) {
+ if (($volume = $this->volume($target)) != false
+ && (($tmb = $volume->tmb($target)) != false)) {
+ $result['images'][$target] = $tmb;
+ }
+ }
+ return $result;
+ }
+
+ /**
+ * Required to output file in browser when volume URL is not set
+ * Return array contains opened file pointer, root itself and required headers
+ *
+ * @param array command arguments
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function file($args) {
+ $target = $args['target'];
+ $download = !empty($args['download']);
+ $h403 = 'HTTP/1.x 403 Access Denied';
+ $h404 = 'HTTP/1.x 404 Not Found';
+
+ if (($volume = $this->volume($target)) == false) {
+ return array('error' => 'File not found', 'header' => $h404, 'raw' => true);
+ }
+
+ if (($file = $volume->file($target)) == false) {
+ return array('error' => 'File not found', 'header' => $h404, 'raw' => true);
+ }
+
+ if (!$file['read']) {
+ return array('error' => 'Access denied', 'header' => $h403, 'raw' => true);
+ }
+
+ if (($fp = $volume->open($target)) == false) {
+ return array('error' => 'File not found', 'header' => $h404, 'raw' => true);
+ }
+
+ if ($download) {
+ $disp = 'attachment';
+ $mime = 'application/octet-stream';
+ } else {
+ $disp = preg_match('/^(image|text)/i', $file['mime']) || $file['mime'] == 'application/x-shockwave-flash'
+ ? 'inline'
+ : 'attachment';
+ $mime = $file['mime'];
+ }
+
+ $filenameEncoded = rawurlencode($file['name']);
+ if (strpos($filenameEncoded, '%') === false) { // ASCII only
+ $filename = 'filename="'.$file['name'].'"';
+ } else {
+ $ua = $_SERVER["HTTP_USER_AGENT"];
+ if (preg_match('/MSIE [4-8]/', $ua)) { // IE < 9 do not support RFC 6266 (RFC 2231/RFC 5987)
+ $filename = 'filename="'.$filenameEncoded.'"';
+ } elseif (strpos($ua, 'Chrome') === false && strpos($ua, 'Safari') !== false) { // Safari
+ $filename = 'filename="'.str_replace('"', '', $file['name']).'"';
+ } else { // RFC 6266 (RFC 2231/RFC 5987)
+ $filename = 'filename*=UTF-8\'\''.$filenameEncoded;
+ }
+ }
+
+ $result = array(
+ 'volume' => $volume,
+ 'pointer' => $fp,
+ 'info' => $file,
+ 'header' => array(
+ 'Content-Type: '.$mime,
+ 'Content-Disposition: '.$disp.'; '.$filename,
+ 'Content-Location: '.$file['name'],
+ 'Content-Transfer-Encoding: binary',
+ 'Content-Length: '.$file['size'],
+ 'Connection: close'
+ )
+ );
+ return $result;
+ }
+
+ /**
+ * Count total files size
+ *
+ * @param array command arguments
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function size($args) {
+ $size = 0;
+
+ foreach ($args['targets'] as $target) {
+ if (($volume = $this->volume($target)) == false
+ || ($file = $volume->file($target)) == false
+ || !$file['read']) {
+ return array('error' => $this->error(self::ERROR_OPEN, '#'.$target));
+ }
+
+ $size += $volume->size($target);
+ }
+ return array('size' => $size);
+ }
+
+ /**
+ * Create directory
+ *
+ * @param array command arguments
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function mkdir($args) {
+ $target = $args['target'];
+ $name = $args['name'];
+
+ if (($volume = $this->volume($target)) == false) {
+ return array('error' => $this->error(self::ERROR_MKDIR, $name, self::ERROR_TRGDIR_NOT_FOUND, '#'.$target));
+ }
+
+ return ($dir = $volume->mkdir($target, $name)) == false
+ ? array('error' => $this->error(self::ERROR_MKDIR, $name, $volume->error()))
+ : array('added' => array($dir));
+ }
+
+ /**
+ * Create empty file
+ *
+ * @param array command arguments
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function mkfile($args) {
+ $target = $args['target'];
+ $name = $args['name'];
+
+ if (($volume = $this->volume($target)) == false) {
+ return array('error' => $this->error(self::ERROR_MKFILE, $name, self::ERROR_TRGDIR_NOT_FOUND, '#'.$target));
+ }
+
+ return ($file = $volume->mkfile($target, $args['name'])) == false
+ ? array('error' => $this->error(self::ERROR_MKFILE, $name, $volume->error()))
+ : array('added' => array($file));
+ }
+
+ /**
+ * Rename file
+ *
+ * @param array $args
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function rename($args) {
+ $target = $args['target'];
+ $name = $args['name'];
+
+ if (($volume = $this->volume($target)) == false
+ || ($rm = $volume->file($target)) == false) {
+ return array('error' => $this->error(self::ERROR_RENAME, '#'.$target, self::ERROR_FILE_NOT_FOUND));
+ }
+ $rm['realpath'] = $volume->realpath($target);
+
+ return ($file = $volume->rename($target, $name)) == false
+ ? array('error' => $this->error(self::ERROR_RENAME, $rm['name'], $volume->error()))
+ : array('added' => array($file), 'removed' => array($rm));
+ }
+
+ /**
+ * Duplicate file - create copy with "copy %d" suffix
+ *
+ * @param array $args command arguments
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function duplicate($args) {
+ $targets = is_array($args['targets']) ? $args['targets'] : array();
+ $result = array('added' => array());
+ $suffix = empty($args['suffix']) ? 'copy' : $args['suffix'];
+
+ foreach ($targets as $target) {
+ if (($volume = $this->volume($target)) == false
+ || ($src = $volume->file($target)) == false) {
+ $result['warning'] = $this->error(self::ERROR_COPY, '#'.$target, self::ERROR_FILE_NOT_FOUND);
+ break;
+ }
+
+ if (($file = $volume->duplicate($target, $suffix)) == false) {
+ $result['warning'] = $this->error($volume->error());
+ break;
+ }
+
+ $result['added'][] = $file;
+ }
+
+ return $result;
+ }
+
+ /**
+ * Remove dirs/files
+ *
+ * @param array command arguments
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function rm($args) {
+ $targets = is_array($args['targets']) ? $args['targets'] : array();
+ $result = array('removed' => array());
+
+ foreach ($targets as $target) {
+ if (($volume = $this->volume($target)) == false) {
+ $result['warning'] = $this->error(self::ERROR_RM, '#'.$target, self::ERROR_FILE_NOT_FOUND);
+ return $result;
+ }
+ if (!$volume->rm($target)) {
+ $result['warning'] = $this->error($volume->error());
+ return $result;
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Get remote contents
+ *
+ * @param string $url target url
+ * @param int $timeout timeout (sec)
+ * @param int $redirect_max redirect max count
+ * @param string $ua
+ * @return string or bool(false)
+ * @retval string contents
+ * @retval false error
+ * @author Naoki Sawada
+ **/
+ protected function get_remote_contents( $url, $timeout = 30, $redirect_max = 5, $ua = 'Mozilla/5.0' ) {
+ $method = (function_exists('curl_exec') && !ini_get('safe_mode'))? 'curl_get_contents' : 'fsock_get_contents';
+ return $this->$method( $url, $timeout, $redirect_max, $ua );
+ }
+
+ /**
+ * Get remote contents with cURL
+ *
+ * @param string $url target url
+ * @param int $timeout timeout (sec)
+ * @param int $redirect_max redirect max count
+ * @param string $ua
+ * @return string or bool(false)
+ * @retval string contents
+ * @retval false error
+ * @author Naoki Sawada
+ **/
+ protected function curl_get_contents( $url, $timeout, $redirect_max, $ua ){
+ $ch = curl_init();
+ curl_setopt( $ch, CURLOPT_URL, $url );
+ curl_setopt( $ch, CURLOPT_HEADER, false );
+ curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
+ curl_setopt( $ch, CURLOPT_BINARYTRANSFER, true );
+ curl_setopt( $ch, CURLOPT_TIMEOUT, $timeout );
+ curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false );
+ curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, 1);
+ curl_setopt( $ch, CURLOPT_MAXREDIRS, $redirect_max);
+ curl_setopt( $ch, CURLOPT_USERAGENT, $ua);
+ $result = curl_exec( $ch );
+ curl_close( $ch );
+ return $result;
+ }
+
+ /**
+ * Get remote contents with fsockopen()
+ *
+ * @param string $url url
+ * @param int $timeout timeout (sec)
+ * @param int $redirect_max redirect max count
+ * @param string $ua
+ * @return string or bool(false)
+ * @retval string contents
+ * @retval false error
+ * @author Naoki Sawada
+ */
+ protected function fsock_get_contents( $url, $timeout, $redirect_max, $ua ) {
+
+ $connect_timeout = 3;
+ $connect_try = 3;
+ $method = 'GET';
+ $readsize = 4096;
+
+ $getSize = null;
+ $headers = '';
+
+ $arr = parse_url($url);
+ if (!$arr){
+ // Bad request
+ return false;
+ }
+
+ // query
+ $arr['query'] = isset($arr['query']) ? '?'.$arr['query'] : '';
+ // port
+ $arr['port'] = isset($arr['port']) ? $arr['port'] : (!empty($arr['https'])? 443 : 80);
+
+ $url_base = $arr['scheme'].'://'.$arr['host'].':'.$arr['port'];
+ $url_path = isset($arr['path']) ? $arr['path'] : '/';
+ $uri = $url_path.$arr['query'];
+
+ $query = $method.' '.$uri." HTTP/1.0\r\n";
+ $query .= "Host: ".$arr['host']."\r\n";
+ if (!empty($ua)) $query .= "User-Agent: ".$ua."\r\n";
+ if (!is_null($getSize)) $query .= 'Range: bytes=0-' . ($getSize - 1) . "\r\n";
+
+ $query .= $headers;
+
+ $query .= "\r\n";
+
+ $fp = $connect_try_count = 0;
+ while( !$fp && $connect_try_count < $connect_try ) {
+
+ $errno = 0;
+ $errstr = "";
+ $fp = @ fsockopen(
+ $arr['https'].$arr['host'],
+ $arr['port'],
+ $errno,$errstr,$connect_timeout);
+ if ($fp) break;
+ $connect_try_count++;
+ if (connection_aborted()) {
+ exit();
+ }
+ sleep(1); // wait 1sec
+ }
+
+ $fwrite = 0;
+ for ($written = 0; $written < strlen($query); $written += $fwrite) {
+ $fwrite = fwrite($fp, substr($query, $written));
+ if (!$fwrite) {
+ break;
+ }
+ }
+
+ $response = '';
+
+ if ($timeout) {
+ socket_set_timeout($fp, $timeout);
+ }
+
+ $_response = true;
+ while ($_response && (is_null($getSize) || strlen($response) < $getSize)) {
+ if (connection_aborted()) {
+ exit();
+ }
+ if ($_response = fread($fp, $readsize)) {
+ $response .= $_response;
+ }
+ }
+
+ if ($timeout) {
+ $_status = socket_get_status($fp);
+ if ($_status['timed_out']) {
+ fclose($fp);
+ return false; // Request Time-out
+ }
+ }
+
+ fclose($fp);
+
+ $resp = array_pad(explode("\r\n\r\n",$response,2), 2, '');
+ $rccd = array_pad(explode(' ',$resp[0],3), 3, ''); // array('HTTP/1.1','200','OK\r\n...')
+ $rc = (int)$rccd[1];
+
+ // Redirect
+ switch ($rc) {
+ case 307: // Temporary Redirect
+ case 303: // See Other
+ case 302: // Moved Temporarily
+ case 301: // Moved Permanently
+ $matches = array();
+ if (preg_match('/^Location: (.+?)(#.+)?$/im',$resp[0],$matches) && --$redirect_max > 0) {
+ $url = trim($matches[1]);
+ $hash = isset($matches[2])? trim($matches[2]) : '';
+ if (!preg_match('/^https?:\//',$url)) { // no scheme
+ if ($url{0} != '/') { // Relative path
+ // to Absolute path
+ $url = substr($url_path,0,strrpos($url_path,'/')).'/'.$url;
+ }
+ // add sheme,host
+ $url = $url_base.$url;
+ }
+ return $this->fsock_get_contents( $url, $timeout, $redirect_max, $ua );
+ }
+ }
+
+ return $resp[1]; // Data
+ }
+
+ /**
+ * Parse Data URI scheme
+ *
+ * @param string $str
+ * @param array $mimeTable
+ * @return array
+ * @author Naoki Sawada
+ */
+ protected function parse_data_scheme( $str, $mimeTable ) {
+ $data = $name = '';
+ if ($fp = fopen('data://'.substr($str, 5), 'rb')) {
+ if ($data = stream_get_contents($fp)) {
+ $exts = array_flip($mimeTable);
+ $meta = stream_get_meta_data($fp);
+ $ext = isset($exts[$meta['mediatype']])? '.' . $exts[$meta['mediatype']] : '';
+ $name = substr(md5($data), 0, 8) . $ext;
+ }
+ fclose($fp);
+ }
+ return array($data, $name);
+ }
+
+ /**
+ * Save uploaded files
+ *
+ * @param array
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function upload($args) {
+ $target = $args['target'];
+ $volume = $this->volume($target);
+ $files = isset($args['FILES']['upload']) && is_array($args['FILES']['upload']) ? $args['FILES']['upload'] : array();
+ $result = array('added' => array(), 'header' => empty($args['html']) ? false : 'Content-Type: text/html; charset=utf-8');
+ $paths = $args['upload_path']? $args['upload_path'] : array();
+
+ if (!$volume) {
+ return array('error' => $this->error(self::ERROR_UPLOAD, self::ERROR_TRGDIR_NOT_FOUND, '#'.$target), 'header' => $header);
+ }
+
+ $non_uploads = array();
+ if (empty($files)) {
+ if (isset($args['upload']) && is_array($args['upload'])) {
+ foreach($args['upload'] as $i => $url) {
+ // check is data:
+ if (substr($url, 0, 5) === 'data:') {
+ list($data, $args['name'][$i]) = $this->parse_data_scheme($url, $volume->getMimeTable());
+ } else {
+ $data = $this->get_remote_contents($url);
+ }
+ if ($data) {
+ $_name = isset($args['name'][$i])? $args['name'][$i] : preg_replace('~^.*?([^/#?]+)(?:\?.*)?(?:#.*)?$~', '$1', rawurldecode($url));
+ if ($_name) {
+ $_ext = '';
+ if (preg_match('/(\.[a-z0-9]{1,7})$/', $_name, $_match)) {
+ $_ext = $_match[1];
+ }
+ $tmpfname = DIRECTORY_SEPARATOR . 'ELF_FATCH_' . md5($url.microtime()) . $_ext;
+ $tmpPath = sys_get_temp_dir();
+ if (! @ touch($tmpPath . $tmpfname)) {
+ if ($tmpPath = $volume->getTempPath()) {
+ $tmpfname = $tmpPath . $tmpfname;
+ } else {
+ $tmpfname = '';
+ }
+ } else {
+ $tmpfname = $tmpPath . $tmpfname;
+ }
+ if ($tmpfname) {
+ if (file_put_contents($tmpfname, $data)) {
+ $non_uploads[$tmpfname] = true;
+ $files['tmp_name'][$i] = $tmpfname;
+ $files['name'][$i] = preg_replace('/[\/\\?*:|"<>]/', '_', $_name);
+ $files['error'][$i] = 0;
+ } else {
+ @ unlink($tmpfname);
+ }
+ }
+ }
+ }
+ }
+ }
+ if (empty($files)) {
+ return array('error' => $this->error(self::ERROR_UPLOAD, self::ERROR_UPLOAD_NO_FILES), 'header' => $header);
+ }
+ }
+
+ foreach ($files['name'] as $i => $name) {
+ if (($error = $files['error'][$i]) > 0) {
+ $result['warning'] = $this->error(self::ERROR_UPLOAD_FILE, $name, $error == UPLOAD_ERR_INI_SIZE || $error == UPLOAD_ERR_FORM_SIZE ? self::ERROR_UPLOAD_FILE_SIZE : self::ERROR_UPLOAD_TRANSFER);
+ $this->uploadDebug = 'Upload error code: '.$error;
+ break;
+ }
+
+ $tmpname = $files['tmp_name'][$i];
+ $path = ($paths && !empty($paths[$i]))? $paths[$i] : '';
+
+ // do hook function 'upload.presave'
+ if (! empty($this->listeners['upload.presave'])) {
+ foreach($this->listeners['upload.presave'] as $handler) {
+ call_user_func_array($handler, array(&$path, &$name, $tmpname, $this, $volume));
+ }
+ }
+
+ if (($fp = fopen($tmpname, 'rb')) == false) {
+ $result['warning'] = $this->error(self::ERROR_UPLOAD_FILE, $name, self::ERROR_UPLOAD_TRANSFER);
+ $this->uploadDebug = 'Upload error: unable open tmp file';
+ if (! is_uploaded_file($tmpname)) {
+ if (@ unlink($tmpname)) unset($non_uploads[$tmpfname]);
+ continue;
+ }
+ break;
+ }
+ if ($path) {
+ $_target = $volume->getUploadTaget($target, $path, $result);
+ } else {
+ $_target = $target;
+ }
+ if (! $_target || ($file = $volume->upload($fp, $_target, $name, $tmpname)) === false) {
+ $result['warning'] = $this->error(self::ERROR_UPLOAD_FILE, $name, $volume->error());
+ fclose($fp);
+ if (! is_uploaded_file($tmpname)) {
+ if (@ unlink($tmpname)) unset($non_uploads[$tmpfname]);;
+ continue;
+ }
+ break;
+ }
+
+ fclose($fp);
+ if (! is_uploaded_file($tmpname) && @ unlink($tmpname)) unset($non_uploads[$tmpfname]);
+ $result['added'][] = $file;
+ }
+ if ($non_uploads) {
+ foreach(array_keys($non_uploads) as $_temp) {
+ @ unlink($_temp);
+ }
+ }
+ return $result;
+ }
+
+ /**
+ * Copy/move files into new destination
+ *
+ * @param array command arguments
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function paste($args) {
+ $dst = $args['dst'];
+ $targets = is_array($args['targets']) ? $args['targets'] : array();
+ $cut = !empty($args['cut']);
+ $error = $cut ? self::ERROR_MOVE : self::ERROR_COPY;
+ $result = array('added' => array(), 'removed' => array());
+
+ if (($dstVolume = $this->volume($dst)) == false) {
+ return array('error' => $this->error($error, '#'.$targets[0], self::ERROR_TRGDIR_NOT_FOUND, '#'.$dst));
+ }
+
+ foreach ($targets as $target) {
+ if (($srcVolume = $this->volume($target)) == false) {
+ $result['warning'] = $this->error($error, '#'.$target, self::ERROR_FILE_NOT_FOUND);
+ break;
+ }
+
+ if (($file = $dstVolume->paste($srcVolume, $target, $dst, $cut)) == false) {
+ $result['warning'] = $this->error($dstVolume->error());
+ break;
+ }
+
+ $result['added'][] = $file;
+ }
+ return $result;
+ }
+
+ /**
+ * Return file content
+ *
+ * @param array $args command arguments
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function get($args) {
+ $target = $args['target'];
+ $volume = $this->volume($target);
+
+ if (!$volume || ($file = $volume->file($target)) == false) {
+ return array('error' => $this->error(self::ERROR_OPEN, '#'.$target, self::ERROR_FILE_NOT_FOUND));
+ }
+
+ if (($content = $volume->getContents($target)) === false) {
+ return array('error' => $this->error(self::ERROR_OPEN, $volume->path($target), $volume->error()));
+ }
+
+ $json = json_encode($content);
+
+ if ($json == 'null' && strlen($json) < strlen($content)) {
+ return array('error' => $this->error(self::ERROR_NOT_UTF8_CONTENT, $volume->path($target)));
+ }
+
+ return array('content' => $content);
+ }
+
+ /**
+ * Save content into text file
+ *
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function put($args) {
+ $target = $args['target'];
+
+ if (($volume = $this->volume($target)) == false
+ || ($file = $volume->file($target)) == false) {
+ return array('error' => $this->error(self::ERROR_SAVE, '#'.$target, self::ERROR_FILE_NOT_FOUND));
+ }
+
+ if (($file = $volume->putContents($target, $args['content'])) == false) {
+ return array('error' => $this->error(self::ERROR_SAVE, $volume->path($target), $volume->error()));
+ }
+
+ return array('changed' => array($file));
+ }
+
+ /**
+ * Extract files from archive
+ *
+ * @param array $args command arguments
+ * @return array
+ * @author Dmitry (dio) Levashov,
+ * @author Alexey Sukhotin
+ **/
+ protected function extract($args) {
+ $target = $args['target'];
+ $mimes = !empty($args['mimes']) && is_array($args['mimes']) ? $args['mimes'] : array();
+ $error = array(self::ERROR_EXTRACT, '#'.$target);
+
+ if (($volume = $this->volume($target)) == false
+ || ($file = $volume->file($target)) == false) {
+ return array('error' => $this->error(self::ERROR_EXTRACT, '#'.$target, self::ERROR_FILE_NOT_FOUND));
+ }
+
+ return ($file = $volume->extract($target))
+ ? array('added' => array($file))
+ : array('error' => $this->error(self::ERROR_EXTRACT, $volume->path($target), $volume->error()));
+ }
+
+ /**
+ * Create archive
+ *
+ * @param array $args command arguments
+ * @return array
+ * @author Dmitry (dio) Levashov,
+ * @author Alexey Sukhotin
+ **/
+ protected function archive($args) {
+ $type = $args['type'];
+ $targets = isset($args['targets']) && is_array($args['targets']) ? $args['targets'] : array();
+
+ if (($volume = $this->volume($targets[0])) == false) {
+ return $this->error(self::ERROR_ARCHIVE, self::ERROR_TRGDIR_NOT_FOUND);
+ }
+
+ return ($file = $volume->archive($targets, $args['type']))
+ ? array('added' => array($file))
+ : array('error' => $this->error(self::ERROR_ARCHIVE, $volume->error()));
+ }
+
+ /**
+ * Search files
+ *
+ * @param array $args command arguments
+ * @return array
+ * @author Dmitry Levashov
+ **/
+ protected function search($args) {
+ $q = trim($args['q']);
+ $mimes = !empty($args['mimes']) && is_array($args['mimes']) ? $args['mimes'] : array();
+ $result = array();
+
+ foreach ($this->volumes as $volume) {
+ $result = array_merge($result, $volume->search($q, $mimes));
+ }
+
+ return array('files' => $result);
+ }
+
+ /**
+ * Return file info (used by client "places" ui)
+ *
+ * @param array $args command arguments
+ * @return array
+ * @author Dmitry Levashov
+ **/
+ protected function info($args) {
+ $files = array();
+
+ foreach ($args['targets'] as $hash) {
+ if (($volume = $this->volume($hash)) != false
+ && ($info = $volume->file($hash)) != false) {
+ $files[] = $info;
+ }
+ }
+
+ return array('files' => $files);
+ }
+
+ /**
+ * Return image dimmensions
+ *
+ * @param array $args command arguments
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function dim($args) {
+ $target = $args['target'];
+
+ if (($volume = $this->volume($target)) != false) {
+ $dim = $volume->dimensions($target);
+ return $dim ? array('dim' => $dim) : array();
+ }
+ return array();
+ }
+
+ /**
+ * Resize image
+ *
+ * @param array command arguments
+ * @return array
+ * @author Dmitry (dio) Levashov
+ * @author Alexey Sukhotin
+ **/
+ protected function resize($args) {
+ $target = $args['target'];
+ $width = $args['width'];
+ $height = $args['height'];
+ $x = (int)$args['x'];
+ $y = (int)$args['y'];
+ $mode = $args['mode'];
+ $bg = null;
+ $degree = (int)$args['degree'];
+
+ if (($volume = $this->volume($target)) == false
+ || ($file = $volume->file($target)) == false) {
+ return array('error' => $this->error(self::ERROR_RESIZE, '#'.$target, self::ERROR_FILE_NOT_FOUND));
+ }
+
+ return ($file = $volume->resize($target, $width, $height, $x, $y, $mode, $bg, $degree))
+ ? array('changed' => array($file))
+ : array('error' => $this->error(self::ERROR_RESIZE, $volume->path($target), $volume->error()));
+ }
+
+ /***************************************************************************/
+ /* utils */
+ /***************************************************************************/
+
+ /**
+ * Return root - file's owner
+ *
+ * @param string file hash
+ * @return elFinderStorageDriver
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function volume($hash) {
+ foreach ($this->volumes as $id => $v) {
+ if (strpos(''.$hash, $id) === 0) {
+ return $this->volumes[$id];
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Return files info array
+ *
+ * @param array $data one file info or files info
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function toArray($data) {
+ return isset($data['hash']) || !is_array($data) ? array($data) : $data;
+ }
+
+ /**
+ * Return fils hashes list
+ *
+ * @param array $files files info
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function hashes($files) {
+ $ret = array();
+ foreach ($files as $file) {
+ $ret[] = $file['hash'];
+ }
+ return $ret;
+ }
+
+ /**
+ * Remove from files list hidden files and files with required mime types
+ *
+ * @param array $files files info
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function filter($files) {
+ foreach ($files as $i => $file) {
+ if (!empty($file['hidden']) || !$this->default->mimeAccepted($file['mime'])) {
+ unset($files[$i]);
+ }
+ }
+ return array_merge($files, array());
+ }
+
+ protected function utime() {
+ $time = explode(" ", microtime());
+ return (double)$time[1] + (double)$time[0];
+ }
+
+} // END class
diff --git a/app/mihaildev/elfinder/php/elFinderConnector.class.php b/app/mihaildev/elfinder/php/elFinderConnector.class.php
new file mode 100755
index 0000000..0c4a0ce
--- /dev/null
+++ b/app/mihaildev/elfinder/php/elFinderConnector.class.php
@@ -0,0 +1,133 @@
+elFinder = $elFinder;
+ if ($debug) {
+ $this->header = 'Content-Type: text/html; charset=utf-8';
+ }
+ }
+
+ /**
+ * Execute elFinder command and output result
+ *
+ * @return void
+ * @author Dmitry (dio) Levashov
+ **/
+ public function run() {
+ $isPost = $_SERVER["REQUEST_METHOD"] == 'POST';
+ $src = $_SERVER["REQUEST_METHOD"] == 'POST' ? $_POST : $_GET;
+ $cmd = isset($src['cmd']) ? $src['cmd'] : '';
+ $args = array();
+
+ if (!function_exists('json_encode')) {
+ $error = $this->elFinder->error(elFinder::ERROR_CONF, elFinder::ERROR_CONF_NO_JSON);
+ $this->output(array('error' => '{"error":["'.implode('","', $error).'"]}', 'raw' => true));
+ }
+
+ if (!$this->elFinder->loaded()) {
+ $this->output(array('error' => $this->elFinder->error(elFinder::ERROR_CONF, elFinder::ERROR_CONF_NO_VOL), 'debug' => $this->elFinder->mountErrors));
+ }
+
+ // telepat_mode: on
+ if (!$cmd && $isPost) {
+ $this->output(array('error' => $this->elFinder->error(elFinder::ERROR_UPLOAD, elFinder::ERROR_UPLOAD_TOTAL_SIZE), 'header' => 'Content-Type: text/html'));
+ }
+ // telepat_mode: off
+
+ if (!$this->elFinder->commandExists($cmd)) {
+ $this->output(array('error' => $this->elFinder->error(elFinder::ERROR_UNKNOWN_CMD)));
+ }
+
+ // collect required arguments to exec command
+ foreach ($this->elFinder->commandArgsList($cmd) as $name => $req) {
+ $arg = $name == 'FILES'
+ ? $_FILES
+ : (isset($src[$name]) ? $src[$name] : '');
+
+ if (!is_array($arg)) {
+ $arg = trim($arg);
+ }
+ if ($req && (!isset($arg) || $arg === '')) {
+ $this->output(array('error' => $this->elFinder->error(elFinder::ERROR_INV_PARAMS, $cmd)));
+ }
+ $args[$name] = $arg;
+ }
+
+ $args['debug'] = isset($src['debug']) ? !!$src['debug'] : false;
+
+ $this->output($this->elFinder->exec($cmd, $args));
+ }
+
+ /**
+ * Output json
+ *
+ * @param array data to output
+ * @return void
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function output(array $data) {
+ $header = isset($data['header']) ? $data['header'] : $this->header;
+ unset($data['header']);
+ if ($header) {
+ if (is_array($header)) {
+ foreach ($header as $h) {
+ header($h);
+ }
+ } else {
+ header($header);
+ }
+ }
+
+ if (isset($data['pointer'])) {
+ rewind($data['pointer']);
+ fpassthru($data['pointer']);
+ if (!empty($data['volume'])) {
+ $data['volume']->close($data['pointer'], $data['info']['hash']);
+ }
+ exit();
+ } else {
+ if (!empty($data['raw']) && !empty($data['error'])) {
+ exit($data['error']);
+ } else {
+ exit(json_encode($data));
+ }
+ }
+
+ }
+
+}// END class
diff --git a/app/mihaildev/elfinder/php/elFinderVolumeDriver.class.php b/app/mihaildev/elfinder/php/elFinderVolumeDriver.class.php
new file mode 100755
index 0000000..dd64ef8
--- /dev/null
+++ b/app/mihaildev/elfinder/php/elFinderVolumeDriver.class.php
@@ -0,0 +1,3566 @@
+ array(),
+ 'extract' => array()
+ );
+
+ /**
+ * How many subdirs levels return for tree
+ *
+ * @var int
+ **/
+ protected $treeDeep = 1;
+
+ /**
+ * Errors from last failed action
+ *
+ * @var array
+ **/
+ protected $error = array();
+
+ /**
+ * Today 24:00 timestamp
+ *
+ * @var int
+ **/
+ protected $today = 0;
+
+ /**
+ * Yesterday 24:00 timestamp
+ *
+ * @var int
+ **/
+ protected $yesterday = 0;
+
+ /**
+ * Object configuration
+ *
+ * @var array
+ **/
+ protected $options = array(
+ 'id' => '',
+ // root directory path
+ 'path' => '',
+ // open this path on initial request instead of root path
+ 'startPath' => '',
+ // how many subdirs levels return per request
+ 'treeDeep' => 1,
+ // root url, not set to disable sending URL to client (replacement for old "fileURL" option)
+ 'URL' => '',
+ // directory separator. required by client to show paths correctly
+ 'separator' => DIRECTORY_SEPARATOR,
+ // library to crypt/uncrypt files names (not implemented)
+ 'cryptLib' => '',
+ // how to detect files mimetypes. (auto/internal/finfo/mime_content_type)
+ 'mimeDetect' => 'auto',
+ // mime.types file path (for mimeDetect==internal)
+ 'mimefile' => '',
+ // directory for thumbnails
+ 'tmbPath' => '.tmb',
+ // mode to create thumbnails dir
+ 'tmbPathMode' => 0777,
+ // thumbnails dir URL. Set it if store thumbnails outside root directory
+ 'tmbURL' => '',
+ // thumbnails size (px)
+ 'tmbSize' => 48,
+ // thumbnails crop (true - crop, false - scale image to fit thumbnail size)
+ 'tmbCrop' => true,
+ // thumbnails background color (hex #rrggbb or 'transparent')
+ 'tmbBgColor' => '#ffffff',
+ // image manipulations library
+ 'imgLib' => 'auto',
+ // on paste file - if true - old file will be replaced with new one, if false new file get name - original_name-number.ext
+ 'copyOverwrite' => true,
+ // if true - join new and old directories content on paste
+ 'copyJoin' => true,
+ // on upload - if true - old file will be replaced with new one, if false new file get name - original_name-number.ext
+ 'uploadOverwrite' => true,
+ // mimetypes allowed to upload
+ 'uploadAllow' => array(),
+ // mimetypes not allowed to upload
+ 'uploadDeny' => array(),
+ // order to proccess uploadAllow and uploadDeny options
+ 'uploadOrder' => array('deny', 'allow'),
+ // maximum upload file size. NOTE - this is size for every uploaded files
+ 'uploadMaxSize' => 0,
+ // files dates format
+ 'dateFormat' => 'j M Y H:i',
+ // files time format
+ 'timeFormat' => 'H:i',
+ // if true - every folder will be check for children folders, otherwise all folders will be marked as having subfolders
+ 'checkSubfolders' => true,
+ // allow to copy from this volume to other ones?
+ 'copyFrom' => true,
+ // allow to copy from other volumes to this one?
+ 'copyTo' => true,
+ // list of commands disabled on this root
+ 'disabled' => array(),
+ // regexp or function name to validate new file name
+ 'acceptedName' => '/^[^\.].*/', //<-- DONT touch this! Use constructor options to overwrite it!
+ // function/class method to control files permissions
+ 'accessControl' => null,
+ // some data required by access control
+ 'accessControlData' => null,
+ // default permissions. not set hidden/locked here - take no effect
+ 'defaults' => array(
+ 'read' => true,
+ 'write' => true
+ ),
+ // files attributes
+ 'attributes' => array(),
+ // Allowed archive's mimetypes to create. Leave empty for all available types.
+ 'archiveMimes' => array(),
+ // Manual config for archivers. See example below. Leave empty for auto detect
+ 'archivers' => array(),
+ // plugin settings
+ 'plugin' => array(),
+ // required to fix bug on macos
+ 'utf8fix' => false,
+ // й ё Й Ё Ø Å
+ 'utf8patterns' => array("\u0438\u0306", "\u0435\u0308", "\u0418\u0306", "\u0415\u0308", "\u00d8A", "\u030a"),
+ 'utf8replace' => array("\u0439", "\u0451", "\u0419", "\u0401", "\u00d8", "\u00c5")
+ );
+
+ /**
+ * Defaults permissions
+ *
+ * @var array
+ **/
+ protected $defaults = array(
+ 'read' => true,
+ 'write' => true,
+ 'locked' => false,
+ 'hidden' => false
+ );
+
+ /**
+ * Access control function/class
+ *
+ * @var mixed
+ **/
+ protected $attributes = array();
+
+ /**
+ * Access control function/class
+ *
+ * @var mixed
+ **/
+ protected $access = null;
+
+ /**
+ * Mime types allowed to upload
+ *
+ * @var array
+ **/
+ protected $uploadAllow = array();
+
+ /**
+ * Mime types denied to upload
+ *
+ * @var array
+ **/
+ protected $uploadDeny = array();
+
+ /**
+ * Order to validate uploadAllow and uploadDeny
+ *
+ * @var array
+ **/
+ protected $uploadOrder = array();
+
+ /**
+ * Maximum allowed upload file size.
+ * Set as number or string with unit - "10M", "500K", "1G"
+ *
+ * @var int|string
+ **/
+ protected $uploadMaxSize = 0;
+
+ /**
+ * Mimetype detect method
+ *
+ * @var string
+ **/
+ protected $mimeDetect = 'auto';
+
+ /**
+ * Flag - mimetypes from externail file was loaded
+ *
+ * @var bool
+ **/
+ private static $mimetypesLoaded = false;
+
+ /**
+ * Finfo object for mimeDetect == 'finfo'
+ *
+ * @var object
+ **/
+ protected $finfo = null;
+
+ /**
+ * List of disabled client's commands
+ *
+ * @var array
+ **/
+ protected $diabled = array();
+
+ /**
+ * default extensions/mimetypes for mimeDetect == 'internal'
+ *
+ * @var array
+ **/
+ protected static $mimetypes = array(
+ // applications
+ 'ai' => 'application/postscript',
+ 'eps' => 'application/postscript',
+ 'exe' => 'application/x-executable',
+ 'doc' => 'application/vnd.ms-word',
+ 'xls' => 'application/vnd.ms-excel',
+ 'ppt' => 'application/vnd.ms-powerpoint',
+ 'pps' => 'application/vnd.ms-powerpoint',
+ 'pdf' => 'application/pdf',
+ 'xml' => 'application/xml',
+ 'swf' => 'application/x-shockwave-flash',
+ 'torrent' => 'application/x-bittorrent',
+ 'jar' => 'application/x-jar',
+ // open office (finfo detect as application/zip)
+ 'odt' => 'application/vnd.oasis.opendocument.text',
+ 'ott' => 'application/vnd.oasis.opendocument.text-template',
+ 'oth' => 'application/vnd.oasis.opendocument.text-web',
+ 'odm' => 'application/vnd.oasis.opendocument.text-master',
+ 'odg' => 'application/vnd.oasis.opendocument.graphics',
+ 'otg' => 'application/vnd.oasis.opendocument.graphics-template',
+ 'odp' => 'application/vnd.oasis.opendocument.presentation',
+ 'otp' => 'application/vnd.oasis.opendocument.presentation-template',
+ 'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
+ 'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template',
+ 'odc' => 'application/vnd.oasis.opendocument.chart',
+ 'odf' => 'application/vnd.oasis.opendocument.formula',
+ 'odb' => 'application/vnd.oasis.opendocument.database',
+ 'odi' => 'application/vnd.oasis.opendocument.image',
+ 'oxt' => 'application/vnd.openofficeorg.extension',
+ // MS office 2007 (finfo detect as application/zip)
+ 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
+ 'docm' => 'application/vnd.ms-word.document.macroEnabled.12',
+ 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
+ 'dotm' => 'application/vnd.ms-word.template.macroEnabled.12',
+ 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
+ 'xlsm' => 'application/vnd.ms-excel.sheet.macroEnabled.12',
+ 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
+ 'xltm' => 'application/vnd.ms-excel.template.macroEnabled.12',
+ 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
+ 'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12',
+ 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
+ 'pptm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12',
+ 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
+ 'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12',
+ 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
+ 'potm' => 'application/vnd.ms-powerpoint.template.macroEnabled.12',
+ 'ppam' => 'application/vnd.ms-powerpoint.addin.macroEnabled.12',
+ 'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide',
+ 'sldm' => 'application/vnd.ms-powerpoint.slide.macroEnabled.12',
+ // archives
+ 'gz' => 'application/x-gzip',
+ 'tgz' => 'application/x-gzip',
+ 'bz' => 'application/x-bzip2',
+ 'bz2' => 'application/x-bzip2',
+ 'tbz' => 'application/x-bzip2',
+ 'zip' => 'application/zip',
+ 'rar' => 'application/x-rar',
+ 'tar' => 'application/x-tar',
+ '7z' => 'application/x-7z-compressed',
+ // texts
+ 'txt' => 'text/plain',
+ 'php' => 'text/x-php',
+ 'html' => 'text/html',
+ 'htm' => 'text/html',
+ 'js' => 'text/javascript',
+ 'css' => 'text/css',
+ 'rtf' => 'text/rtf',
+ 'rtfd' => 'text/rtfd',
+ 'py' => 'text/x-python',
+ 'java' => 'text/x-java-source',
+ 'rb' => 'text/x-ruby',
+ 'sh' => 'text/x-shellscript',
+ 'pl' => 'text/x-perl',
+ 'xml' => 'text/xml',
+ 'sql' => 'text/x-sql',
+ 'c' => 'text/x-csrc',
+ 'h' => 'text/x-chdr',
+ 'cpp' => 'text/x-c++src',
+ 'hh' => 'text/x-c++hdr',
+ 'log' => 'text/plain',
+ 'csv' => 'text/x-comma-separated-values',
+ // images
+ 'bmp' => 'image/x-ms-bmp',
+ 'jpg' => 'image/jpeg',
+ 'jpeg' => 'image/jpeg',
+ 'gif' => 'image/gif',
+ 'png' => 'image/png',
+ 'tif' => 'image/tiff',
+ 'tiff' => 'image/tiff',
+ 'tga' => 'image/x-targa',
+ 'psd' => 'image/vnd.adobe.photoshop',
+ 'ai' => 'image/vnd.adobe.photoshop',
+ 'xbm' => 'image/xbm',
+ 'pxm' => 'image/pxm',
+ //audio
+ 'mp3' => 'audio/mpeg',
+ 'mid' => 'audio/midi',
+ 'ogg' => 'audio/ogg',
+ 'oga' => 'audio/ogg',
+ 'm4a' => 'audio/x-m4a',
+ 'wav' => 'audio/wav',
+ 'wma' => 'audio/x-ms-wma',
+ // video
+ 'avi' => 'video/x-msvideo',
+ 'dv' => 'video/x-dv',
+ 'mp4' => 'video/mp4',
+ 'mpeg' => 'video/mpeg',
+ 'mpg' => 'video/mpeg',
+ 'mov' => 'video/quicktime',
+ 'wm' => 'video/x-ms-wmv',
+ 'flv' => 'video/x-flv',
+ 'mkv' => 'video/x-matroska',
+ 'webm' => 'video/webm',
+ 'ogv' => 'video/ogg',
+ 'ogm' => 'video/ogg'
+ );
+
+ /**
+ * Directory separator - required by client
+ *
+ * @var string
+ **/
+ protected $separator = DIRECTORY_SEPARATOR;
+
+ /**
+ * Mimetypes allowed to display
+ *
+ * @var array
+ **/
+ protected $onlyMimes = array();
+
+ /**
+ * Store files moved or overwrited files info
+ *
+ * @var array
+ **/
+ protected $removed = array();
+
+ /**
+ * Cache storage
+ *
+ * @var array
+ **/
+ protected $cache = array();
+
+ /**
+ * Cache by folders
+ *
+ * @var array
+ **/
+ protected $dirsCache = array();
+
+ /*********************************************************************/
+ /* INITIALIZATION */
+ /*********************************************************************/
+
+ /**
+ * Prepare driver before mount volume.
+ * Return true if volume is ready.
+ *
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function init() {
+ return true;
+ }
+
+ /**
+ * Configure after successfull mount.
+ * By default set thumbnails path and image manipulation library.
+ *
+ * @return void
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function configure() {
+ // set thumbnails path
+ $path = $this->options['tmbPath'];
+ if ($path) {
+ if (!file_exists($path)) {
+ if (@mkdir($path)) {
+ chmod($path, $this->options['tmbPathMode']);
+ } else {
+ $path = '';
+ }
+ }
+
+ if (is_dir($path) && is_readable($path)) {
+ $this->tmbPath = $path;
+ $this->tmbPathWritable = is_writable($path);
+ }
+ }
+
+ // set image manipulation library
+ $type = preg_match('/^(imagick|gd|auto)$/i', $this->options['imgLib'])
+ ? strtolower($this->options['imgLib'])
+ : 'auto';
+
+ if (($type == 'imagick' || $type == 'auto') && extension_loaded('imagick')) {
+ $this->imgLib = 'imagick';
+ } else {
+ $this->imgLib = function_exists('gd_info') ? 'gd' : '';
+ }
+
+ }
+
+
+ /*********************************************************************/
+ /* PUBLIC API */
+ /*********************************************************************/
+
+ /**
+ * Return driver id. Used as a part of volume id.
+ *
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ public function driverId() {
+ return $this->driverId;
+ }
+
+ /**
+ * Return volume id
+ *
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ public function id() {
+ return $this->id;
+ }
+
+ /**
+ * Return debug info for client
+ *
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ public function debug() {
+ return array(
+ 'id' => $this->id(),
+ 'name' => strtolower(substr(get_class($this), strlen('elfinderdriver'))),
+ 'mimeDetect' => $this->mimeDetect,
+ 'imgLib' => $this->imgLib
+ );
+ }
+
+ /**
+ * "Mount" volume.
+ * Return true if volume available for read or write,
+ * false - otherwise
+ *
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ * @author Alexey Sukhotin
+ **/
+ public function mount(array $opts) {
+ if (!isset($opts['path']) || $opts['path'] === '') {
+ return $this->setError('Path undefined.');;
+ }
+
+ $this->options = array_merge($this->options, $opts);
+ $this->id = $this->driverId.(!empty($this->options['id']) ? $this->options['id'] : elFinder::$volumesCnt++).'_';
+ $this->root = $this->_normpath($this->options['path']);
+ $this->separator = isset($this->options['separator']) ? $this->options['separator'] : DIRECTORY_SEPARATOR;
+
+ // default file attribute
+ $this->defaults = array(
+ 'read' => isset($this->options['defaults']['read']) ? !!$this->options['defaults']['read'] : true,
+ 'write' => isset($this->options['defaults']['write']) ? !!$this->options['defaults']['write'] : true,
+ 'locked' => false,
+ 'hidden' => false
+ );
+
+ // root attributes
+ $this->attributes[] = array(
+ 'pattern' => '~^'.preg_quote(DIRECTORY_SEPARATOR).'$~',
+ 'locked' => true,
+ 'hidden' => false
+ );
+ // set files attributes
+ if (!empty($this->options['attributes']) && is_array($this->options['attributes'])) {
+
+ foreach ($this->options['attributes'] as $a) {
+ // attributes must contain pattern and at least one rule
+ if (!empty($a['pattern']) || count($a) > 1) {
+ $this->attributes[] = $a;
+ }
+ }
+ }
+
+ if (!empty($this->options['accessControl']) && is_callable($this->options['accessControl'])) {
+ $this->access = $this->options['accessControl'];
+ }
+
+ $this->today = mktime(0,0,0, date('m'), date('d'), date('Y'));
+ $this->yesterday = $this->today-86400;
+
+ // debug($this->attributes);
+ if (!$this->init()) {
+ return false;
+ }
+
+ // check some options is arrays
+ $this->uploadAllow = isset($this->options['uploadAllow']) && is_array($this->options['uploadAllow'])
+ ? $this->options['uploadAllow']
+ : array();
+
+ $this->uploadDeny = isset($this->options['uploadDeny']) && is_array($this->options['uploadDeny'])
+ ? $this->options['uploadDeny']
+ : array();
+
+ if (is_string($this->options['uploadOrder'])) { // telephat_mode on, compatibility with 1.x
+ $parts = explode(',', isset($this->options['uploadOrder']) ? $this->options['uploadOrder'] : 'deny,allow');
+ $this->uploadOrder = array(trim($parts[0]), trim($parts[1]));
+ } else { // telephat_mode off
+ $this->uploadOrder = $this->options['uploadOrder'];
+ }
+
+ if (!empty($this->options['uploadMaxSize'])) {
+ $size = ''.$this->options['uploadMaxSize'];
+ $unit = strtolower(substr($size, strlen($size) - 1));
+ $n = 1;
+ switch ($unit) {
+ case 'k':
+ $n = 1024;
+ break;
+ case 'm':
+ $n = 1048576;
+ break;
+ case 'g':
+ $n = 1073741824;
+ }
+ $this->uploadMaxSize = intval($size)*$n;
+ }
+
+ $this->disabled = isset($this->options['disabled']) && is_array($this->options['disabled'])
+ ? $this->options['disabled']
+ : array();
+
+ $this->cryptLib = $this->options['cryptLib'];
+ $this->mimeDetect = $this->options['mimeDetect'];
+
+ // find available mimetype detect method
+ $type = strtolower($this->options['mimeDetect']);
+ $type = preg_match('/^(finfo|mime_content_type|internal|auto)$/i', $type) ? $type : 'auto';
+ $regexp = '/text\/x\-(php|c\+\+)/';
+
+ if (($type == 'finfo' || $type == 'auto')
+ && class_exists('finfo')) {
+ $tmpFileInfo = @explode(';', @finfo_file(finfo_open(FILEINFO_MIME), __FILE__));
+ } else {
+ $tmpFileInfo = false;
+ }
+
+ if ($tmpFileInfo && preg_match($regexp, array_shift($tmpFileInfo))) {
+ $type = 'finfo';
+ $this->finfo = finfo_open(FILEINFO_MIME);
+ } elseif (($type == 'mime_content_type' || $type == 'auto')
+ && function_exists('mime_content_type')
+ && preg_match($regexp, array_shift(explode(';', mime_content_type(__FILE__))))) {
+ $type = 'mime_content_type';
+ } else {
+ $type = 'internal';
+ }
+ $this->mimeDetect = $type;
+
+ // load mimes from external file for mimeDetect == 'internal'
+ // based on Alexey Sukhotin idea and patch: http://elrte.org/redmine/issues/163
+ // file must be in file directory or in parent one
+ if ($this->mimeDetect == 'internal' && !self::$mimetypesLoaded) {
+ self::$mimetypesLoaded = true;
+ $this->mimeDetect = 'internal';
+ $file = false;
+ if (!empty($this->options['mimefile']) && file_exists($this->options['mimefile'])) {
+ $file = $this->options['mimefile'];
+ } elseif (file_exists(dirname(__FILE__).DIRECTORY_SEPARATOR.'mime.types')) {
+ $file = dirname(__FILE__).DIRECTORY_SEPARATOR.'mime.types';
+ } elseif (file_exists(dirname(dirname(__FILE__)).DIRECTORY_SEPARATOR.'mime.types')) {
+ $file = dirname(dirname(__FILE__)).DIRECTORY_SEPARATOR.'mime.types';
+ }
+
+ if ($file && file_exists($file)) {
+ $mimecf = file($file);
+
+ foreach ($mimecf as $line_num => $line) {
+ if (!preg_match('/^\s*#/', $line)) {
+ $mime = preg_split('/\s+/', $line, -1, PREG_SPLIT_NO_EMPTY);
+ for ($i = 1, $size = count($mime); $i < $size ; $i++) {
+ if (!isset(self::$mimetypes[$mime[$i]])) {
+ self::$mimetypes[$mime[$i]] = $mime[0];
+ }
+ }
+ }
+ }
+ }
+ }
+
+ $this->rootName = empty($this->options['alias']) ? $this->_basename($this->root) : $this->options['alias'];
+ $root = $this->stat($this->root);
+
+ if (!$root) {
+ return $this->setError('Root folder does not exists.');
+ }
+ if (!$root['read'] && !$root['write']) {
+ return $this->setError('Root folder has not read and write permissions.');
+ }
+
+ // debug($root);
+
+ if ($root['read']) {
+ // check startPath - path to open by default instead of root
+ if ($this->options['startPath']) {
+ $start = $this->stat($this->options['startPath']);
+ if (!empty($start)
+ && $start['mime'] == 'directory'
+ && $start['read']
+ && empty($start['hidden'])
+ && $this->_inpath($this->options['startPath'], $this->root)) {
+ $this->startPath = $this->options['startPath'];
+ if (substr($this->startPath, -1, 1) == $this->options['separator']) {
+ $this->startPath = substr($this->startPath, 0, -1);
+ }
+ }
+ }
+ } else {
+ $this->options['URL'] = '';
+ $this->options['tmbURL'] = '';
+ $this->options['tmbPath'] = '';
+ // read only volume
+ array_unshift($this->attributes, array(
+ 'pattern' => '/.*/',
+ 'read' => false
+ ));
+ }
+ $this->treeDeep = $this->options['treeDeep'] > 0 ? (int)$this->options['treeDeep'] : 1;
+ $this->tmbSize = $this->options['tmbSize'] > 0 ? (int)$this->options['tmbSize'] : 48;
+ $this->URL = $this->options['URL'];
+ if ($this->URL && preg_match("|[^/?&=]$|", $this->URL)) {
+ $this->URL .= '/';
+ }
+
+ $this->tmbURL = !empty($this->options['tmbURL']) ? $this->options['tmbURL'] : '';
+ if ($this->tmbURL && preg_match("|[^/?&=]$|", $this->tmbURL)) {
+ $this->tmbURL .= '/';
+ }
+
+ $this->nameValidator = is_string($this->options['acceptedName']) && !empty($this->options['acceptedName'])
+ ? $this->options['acceptedName']
+ : '';
+
+ $this->_checkArchivers();
+ // manual control archive types to create
+ if (!empty($this->options['archiveMimes']) && is_array($this->options['archiveMimes'])) {
+ foreach ($this->archivers['create'] as $mime => $v) {
+ if (!in_array($mime, $this->options['archiveMimes'])) {
+ unset($this->archivers['create'][$mime]);
+ }
+ }
+ }
+
+ // manualy add archivers
+ if (!empty($this->options['archivers']['create']) && is_array($this->options['archivers']['create'])) {
+ foreach ($this->options['archivers']['create'] as $mime => $conf) {
+ if (strpos($mime, 'application/') === 0
+ && !empty($conf['cmd'])
+ && isset($conf['argc'])
+ && !empty($conf['ext'])
+ && !isset($this->archivers['create'][$mime])) {
+ $this->archivers['create'][$mime] = $conf;
+ }
+ }
+ }
+
+ if (!empty($this->options['archivers']['extract']) && is_array($this->options['archivers']['extract'])) {
+ foreach ($this->options['archivers']['extract'] as $mime => $conf) {
+ if (strpos($mime, 'application/') === 0
+ && !empty($conf['cmd'])
+ && isset($conf['argc'])
+ && !empty($conf['ext'])
+ && !isset($this->archivers['extract'][$mime])) {
+ $this->archivers['extract'][$mime] = $conf;
+ }
+ }
+ }
+
+ $this->configure();
+ // echo $this->uploadMaxSize;
+ // echo $this->options['uploadMaxSize'];
+ return $this->mounted = true;
+ }
+
+ /**
+ * Some "unmount" stuffs - may be required by virtual fs
+ *
+ * @return void
+ * @author Dmitry (dio) Levashov
+ **/
+ public function umount() {
+ }
+
+ /**
+ * Return error message from last failed action
+ *
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ public function error() {
+ return $this->error;
+ }
+
+ /**
+ * Return Extention/MIME Table (elFinderVolumeDriver::$mimetypes)
+ *
+ * @return array
+ * @author Naoki Sawada
+ */
+ public function getMimeTable() {
+ return elFinderVolumeDriver::$mimetypes;
+ }
+
+ /**
+ * Set mimetypes allowed to display to client
+ *
+ * @param array $mimes
+ * @return void
+ * @author Dmitry (dio) Levashov
+ **/
+ public function setMimesFilter($mimes) {
+ if (is_array($mimes)) {
+ $this->onlyMimes = $mimes;
+ }
+ }
+
+ /**
+ * Return root folder hash
+ *
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ public function root() {
+ return $this->encode($this->root);
+ }
+
+ /**
+ * Return root or startPath hash
+ *
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ public function defaultPath() {
+ return $this->encode($this->startPath ? $this->startPath : $this->root);
+ }
+
+ /**
+ * Return volume options required by client:
+ *
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ public function options($hash) {
+ return array(
+ 'path' => $this->_path($this->decode($hash)),
+ 'url' => $this->URL,
+ 'tmbUrl' => $this->tmbURL,
+ 'disabled' => $this->disabled,
+ 'separator' => $this->separator,
+ 'copyOverwrite' => intval($this->options['copyOverwrite']),
+ 'uploadMaxSize' => intval($this->uploadMaxSize),
+ 'archivers' => array(
+ // 'create' => array_keys($this->archivers['create']),
+ // 'extract' => array_keys($this->archivers['extract']),
+ 'create' => is_array($this->archivers['create']) ? array_keys($this->archivers['create']) : array(),
+ 'extract' => is_array($this->archivers['extract']) ? array_keys($this->archivers['extract']) : array()
+ )
+ );
+ }
+
+ /**
+ * Get plugin values of this options
+ *
+ * @param string $name Plugin name
+ * @return NULL|array Plugin values
+ * @author Naoki Sawada
+ */
+ public function getOptionsPlugin($name = '') {
+ if ($name) {
+ return isset($this->options['plugin'][$name])? $this->options['plugin'][$name] : array();
+ } else {
+ return $this->options['plugin'];
+ }
+ }
+
+ /**
+ * Return true if command disabled in options
+ *
+ * @param string $cmd command name
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ public function commandDisabled($cmd) {
+ return in_array($cmd, $this->disabled);
+ }
+
+ /**
+ * Return true if mime is required mimes list
+ *
+ * @param string $mime mime type to check
+ * @param array $mimes allowed mime types list or not set to use client mimes list
+ * @param bool|null $empty what to return on empty list
+ * @return bool|null
+ * @author Dmitry (dio) Levashov
+ * @author Troex Nevelin
+ **/
+ public function mimeAccepted($mime, $mimes = array(), $empty = true) {
+ $mimes = !empty($mimes) ? $mimes : $this->onlyMimes;
+ if (empty($mimes)) {
+ return $empty;
+ }
+ return $mime == 'directory'
+ || in_array('all', $mimes)
+ || in_array('All', $mimes)
+ || in_array($mime, $mimes)
+ || in_array(substr($mime, 0, strpos($mime, '/')), $mimes);
+ }
+
+ /**
+ * Return true if voume is readable.
+ *
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ public function isReadable() {
+ $stat = $this->stat($this->root);
+ return $stat['read'];
+ }
+
+ /**
+ * Return true if copy from this volume allowed
+ *
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ public function copyFromAllowed() {
+ return !!$this->options['copyFrom'];
+ }
+
+ /**
+ * Return file path related to root
+ *
+ * @param string $hash file hash
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ public function path($hash) {
+ return $this->_path($this->decode($hash));
+ }
+
+ /**
+ * Return file real path if file exists
+ *
+ * @param string $hash file hash
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ public function realpath($hash) {
+ $path = $this->decode($hash);
+ return $this->stat($path) ? $path : false;
+ }
+
+ /**
+ * Return list of moved/overwrited files
+ *
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ public function removed() {
+ return $this->removed;
+ }
+
+ /**
+ * Clean removed files list
+ *
+ * @return void
+ * @author Dmitry (dio) Levashov
+ **/
+ public function resetRemoved() {
+ $this->removed = array();
+ }
+
+ /**
+ * Return file/dir hash or first founded child hash with required attr == $val
+ *
+ * @param string $hash file hash
+ * @param string $attr attribute name
+ * @param bool $val attribute value
+ * @return string|false
+ * @author Dmitry (dio) Levashov
+ **/
+ public function closest($hash, $attr, $val) {
+ return ($path = $this->closestByAttr($this->decode($hash), $attr, $val)) ? $this->encode($path) : false;
+ }
+
+ /**
+ * Return file info or false on error
+ *
+ * @param string $hash file hash
+ * @param bool $realpath add realpath field to file info
+ * @return array|false
+ * @author Dmitry (dio) Levashov
+ **/
+ public function file($hash) {
+ $path = $this->decode($hash);
+
+ return ($file = $this->stat($path)) ? $file : $this->setError(elFinder::ERROR_FILE_NOT_FOUND);
+
+ if (($file = $this->stat($path)) != false) {
+ if ($realpath) {
+ $file['realpath'] = $path;
+ }
+ return $file;
+ }
+ return $this->setError(elFinder::ERROR_FILE_NOT_FOUND);
+ }
+
+ /**
+ * Return folder info
+ *
+ * @param string $hash folder hash
+ * @param bool $hidden return hidden file info
+ * @return array|false
+ * @author Dmitry (dio) Levashov
+ **/
+ public function dir($hash, $resolveLink=false) {
+ if (($dir = $this->file($hash)) == false) {
+ return $this->setError(elFinder::ERROR_DIR_NOT_FOUND);
+ }
+
+ if ($resolveLink && !empty($dir['thash'])) {
+ $dir = $this->file($dir['thash']);
+ }
+
+ return $dir && $dir['mime'] == 'directory' && empty($dir['hidden'])
+ ? $dir
+ : $this->setError(elFinder::ERROR_NOT_DIR);
+ }
+
+ /**
+ * Return directory content or false on error
+ *
+ * @param string $hash file hash
+ * @return array|false
+ * @author Dmitry (dio) Levashov
+ **/
+ public function scandir($hash) {
+ if (($dir = $this->dir($hash)) == false) {
+ return false;
+ }
+
+ return $dir['read']
+ ? $this->getScandir($this->decode($hash))
+ : $this->setError(elFinder::ERROR_PERM_DENIED);
+ }
+
+ /**
+ * Return dir files names list
+ *
+ * @param string $hash file hash
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ public function ls($hash) {
+ if (($dir = $this->dir($hash)) == false || !$dir['read']) {
+ return false;
+ }
+
+ $list = array();
+ $path = $this->decode($hash);
+
+ foreach ($this->getScandir($path) as $stat) {
+ if (empty($stat['hidden']) && $this->mimeAccepted($stat['mime'])) {
+ $list[] = $stat['name'];
+ }
+ }
+
+ return $list;
+ }
+
+ /**
+ * Return subfolders for required folder or false on error
+ *
+ * @param string $hash folder hash or empty string to get tree from root folder
+ * @param int $deep subdir deep
+ * @param string $exclude dir hash which subfolders must be exluded from result, required to not get stat twice on cwd subfolders
+ * @return array|false
+ * @author Dmitry (dio) Levashov
+ **/
+ public function tree($hash='', $deep=0, $exclude='') {
+ $path = $hash ? $this->decode($hash) : $this->root;
+
+ if (($dir = $this->stat($path)) == false || $dir['mime'] != 'directory') {
+ return false;
+ }
+
+ $dirs = $this->gettree($path, $deep > 0 ? $deep -1 : $this->treeDeep-1, $exclude ? $this->decode($exclude) : null);
+ array_unshift($dirs, $dir);
+ return $dirs;
+ }
+
+ /**
+ * Return part of dirs tree from required dir up to root dir
+ *
+ * @param string $hash directory hash
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ public function parents($hash) {
+ if (($current = $this->dir($hash)) == false) {
+ return false;
+ }
+
+ $path = $this->decode($hash);
+ $tree = array();
+
+ while ($path && $path != $this->root) {
+ $path = $this->_dirname($path);
+ $stat = $this->stat($path);
+ if (!empty($stat['hidden']) || !$stat['read']) {
+ return false;
+ }
+
+ array_unshift($tree, $stat);
+ if ($path != $this->root) {
+ foreach ($this->gettree($path, 0) as $dir) {
+ if (!in_array($dir, $tree)) {
+ $tree[] = $dir;
+ }
+ }
+ }
+ }
+
+ return $tree ? $tree : array($current);
+ }
+
+ /**
+ * Create thumbnail for required file and return its name of false on failed
+ *
+ * @return string|false
+ * @author Dmitry (dio) Levashov
+ **/
+ public function tmb($hash) {
+ $path = $this->decode($hash);
+ $stat = $this->stat($path);
+
+ if (isset($stat['tmb'])) {
+ return $stat['tmb'] == "1" ? $this->createTmb($path, $stat) : $stat['tmb'];
+ }
+ return false;
+ }
+
+ /**
+ * Return file size / total directory size
+ *
+ * @param string file hash
+ * @return int
+ * @author Dmitry (dio) Levashov
+ **/
+ public function size($hash) {
+ return $this->countSize($this->decode($hash));
+ }
+
+ /**
+ * Open file for reading and return file pointer
+ *
+ * @param string file hash
+ * @return Resource
+ * @author Dmitry (dio) Levashov
+ **/
+ public function open($hash) {
+ if (($file = $this->file($hash)) == false
+ || $file['mime'] == 'directory') {
+ return false;
+ }
+
+ return $this->_fopen($this->decode($hash), 'rb');
+ }
+
+ /**
+ * Close file pointer
+ *
+ * @param Resource $fp file pointer
+ * @param string $hash file hash
+ * @return void
+ * @author Dmitry (dio) Levashov
+ **/
+ public function close($fp, $hash) {
+ $this->_fclose($fp, $this->decode($hash));
+ }
+
+ /**
+ * Create directory and return dir info
+ *
+ * @param string $dst destination directory
+ * @param string $name directory name
+ * @return array|false
+ * @author Dmitry (dio) Levashov
+ **/
+ public function mkdir($dst, $name) {
+ if ($this->commandDisabled('mkdir')) {
+ return $this->setError(elFinder::ERROR_PERM_DENIED);
+ }
+
+ if (!$this->nameAccepted($name)) {
+ return $this->setError(elFinder::ERROR_INVALID_NAME);
+ }
+
+ if (($dir = $this->dir($dst)) == false) {
+ return $this->setError(elFinder::ERROR_TRGDIR_NOT_FOUND, '#'.$dst);
+ }
+
+ if (!$dir['write']) {
+ return $this->setError(elFinder::ERROR_PERM_DENIED);
+ }
+
+ $path = $this->decode($dst);
+ $dst = $this->_joinPath($path, $name);
+ $stat = $this->stat($dst);
+ if (!empty($stat)) {
+ return $this->setError(elFinder::ERROR_EXISTS, $name);
+ }
+ $this->clearcache();
+ return ($path = $this->_mkdir($path, $name)) ? $this->stat($path) : false;
+ }
+
+ /**
+ * Create empty file and return its info
+ *
+ * @param string $dst destination directory
+ * @param string $name file name
+ * @return array|false
+ * @author Dmitry (dio) Levashov
+ **/
+ public function mkfile($dst, $name) {
+ if ($this->commandDisabled('mkfile')) {
+ return $this->setError(elFinder::ERROR_PERM_DENIED);
+ }
+
+ if (!$this->nameAccepted($name)) {
+ return $this->setError(elFinder::ERROR_INVALID_NAME);
+ }
+
+ if (($dir = $this->dir($dst)) == false) {
+ return $this->setError(elFinder::ERROR_TRGDIR_NOT_FOUND, '#'.$dst);
+ }
+
+ $path = $this->decode($dst);
+
+ if (!$dir['write'] || !$this->allowCreate($path, $name)) {
+ return $this->setError(elFinder::ERROR_PERM_DENIED);
+ }
+
+ if ($this->stat($this->_joinPath($path, $name))) {
+ return $this->setError(elFinder::ERROR_EXISTS, $name);
+ }
+
+ $this->clearcache();
+ return ($path = $this->_mkfile($path, $name)) ? $this->stat($path) : false;
+ }
+
+ /**
+ * Rename file and return file info
+ *
+ * @param string $hash file hash
+ * @param string $name new file name
+ * @return array|false
+ * @author Dmitry (dio) Levashov
+ **/
+ public function rename($hash, $name) {
+ if ($this->commandDisabled('rename')) {
+ return $this->setError(elFinder::ERROR_PERM_DENIED);
+ }
+
+ if (!$this->nameAccepted($name)) {
+ return $this->setError(elFinder::ERROR_INVALID_NAME, $name);
+ }
+
+ if (!($file = $this->file($hash))) {
+ return $this->setError(elFinder::ERROR_FILE_NOT_FOUND);
+ }
+
+ if ($name == $file['name']) {
+ return $file;
+ }
+
+ if (!empty($file['locked'])) {
+ return $this->setError(elFinder::ERROR_LOCKED, $file['name']);
+ }
+
+ $path = $this->decode($hash);
+ $dir = $this->_dirname($path);
+ $stat = $this->stat($this->_joinPath($dir, $name));
+ if ($stat) {
+ return $this->setError(elFinder::ERROR_EXISTS, $name);
+ }
+
+ if (!$this->allowCreate($dir, $name)) {
+ return $this->setError(elFinder::ERROR_PERM_DENIED);
+ }
+
+ $this->rmTmb($file); // remove old name tmbs, we cannot do this after dir move
+
+
+ if (($path = $this->_move($path, $dir, $name))) {
+ $this->clearcache();
+ return $this->stat($path);
+ }
+ return false;
+ }
+
+ /**
+ * Create file copy with suffix "copy number" and return its info
+ *
+ * @param string $hash file hash
+ * @param string $suffix suffix to add to file name
+ * @return array|false
+ * @author Dmitry (dio) Levashov
+ **/
+ public function duplicate($hash, $suffix='copy') {
+ if ($this->commandDisabled('duplicate')) {
+ return $this->setError(elFinder::ERROR_COPY, '#'.$hash, elFinder::ERROR_PERM_DENIED);
+ }
+
+ if (($file = $this->file($hash)) == false) {
+ return $this->setError(elFinder::ERROR_COPY, elFinder::ERROR_FILE_NOT_FOUND);
+ }
+
+ $path = $this->decode($hash);
+ $dir = $this->_dirname($path);
+ $name = $this->uniqueName($dir, $this->_basename($path), ' '.$suffix.' ');
+
+ if (!$this->allowCreate($dir, $name)) {
+ return $this->setError(elFinder::ERROR_PERM_DENIED);
+ }
+
+ return ($path = $this->copy($path, $dir, $name)) == false
+ ? false
+ : $this->stat($path);
+ }
+
+ /**
+ * Save uploaded file.
+ * On success return array with new file stat and with removed file hash (if existed file was replaced)
+ *
+ * @param Resource $fp file pointer
+ * @param string $dst destination folder hash
+ * @param string $src file name
+ * @param string $tmpname file tmp name - required to detect mime type
+ * @return array|false
+ * @author Dmitry (dio) Levashov
+ **/
+ public function upload($fp, $dst, $name, $tmpname) {
+ if ($this->commandDisabled('upload')) {
+ return $this->setError(elFinder::ERROR_PERM_DENIED);
+ }
+
+ if (($dir = $this->dir($dst)) == false) {
+ return $this->setError(elFinder::ERROR_TRGDIR_NOT_FOUND, '#'.$dst);
+ }
+
+ if (!$dir['write']) {
+ return $this->setError(elFinder::ERROR_PERM_DENIED);
+ }
+
+ if (!$this->nameAccepted($name)) {
+ return $this->setError(elFinder::ERROR_INVALID_NAME);
+ }
+
+ $mime = $this->mimetype($this->mimeDetect == 'internal' ? $name : $tmpname, $name);
+ if ($mime == 'unknown' && $this->mimeDetect == 'internal') {
+ $mime = elFinderVolumeDriver::mimetypeInternalDetect($name);
+ }
+
+ // logic based on http://httpd.apache.org/docs/2.2/mod/mod_authz_host.html#order
+ $allow = $this->mimeAccepted($mime, $this->uploadAllow, null);
+ $deny = $this->mimeAccepted($mime, $this->uploadDeny, null);
+ $upload = true; // default to allow
+ if (strtolower($this->uploadOrder[0]) == 'allow') { // array('allow', 'deny'), default is to 'deny'
+ $upload = false; // default is deny
+ if (!$deny && ($allow === true)) { // match only allow
+ $upload = true;
+ }// else (both match | no match | match only deny) { deny }
+ } else { // array('deny', 'allow'), default is to 'allow' - this is the default rule
+ $upload = true; // default is allow
+ if (($deny === true) && !$allow) { // match only deny
+ $upload = false;
+ } // else (both match | no match | match only allow) { allow }
+ }
+ if (!$upload) {
+ return $this->setError(elFinder::ERROR_UPLOAD_FILE_MIME);
+ }
+
+ if ($this->uploadMaxSize > 0 && filesize($tmpname) > $this->uploadMaxSize) {
+ return $this->setError(elFinder::ERROR_UPLOAD_FILE_SIZE);
+ }
+
+ $dstpath = $this->decode($dst);
+ $test = $this->_joinPath($dstpath, $name);
+
+ $file = $this->stat($test);
+ $this->clearcache();
+
+ if ($file) { // file exists
+ if ($this->options['uploadOverwrite']) {
+ if (!$file['write']) {
+ return $this->setError(elFinder::ERROR_PERM_DENIED);
+ } elseif ($file['mime'] == 'directory') {
+ return $this->setError(elFinder::ERROR_NOT_REPLACE, $name);
+ }
+ $this->remove($test);
+ } else {
+ $name = $this->uniqueName($dstpath, $name, '-', false);
+ }
+ }
+
+ $stat = array(
+ 'mime' => $mime,
+ 'width' => 0,
+ 'height' => 0,
+ 'size' => filesize($tmpname));
+
+ // $w = $h = 0;
+ if (strpos($mime, 'image') === 0 && ($s = getimagesize($tmpname))) {
+ $stat['width'] = $s[0];
+ $stat['height'] = $s[1];
+ }
+ // $this->clearcache();
+ if (($path = $this->_save($fp, $dstpath, $name, $stat)) == false) {
+ return false;
+ }
+
+
+
+ return $this->stat($path);
+ }
+
+ /**
+ * Paste files
+ *
+ * @param Object $volume source volume
+ * @param string $source file hash
+ * @param string $dst destination dir hash
+ * @param bool $rmSrc remove source after copy?
+ * @return array|false
+ * @author Dmitry (dio) Levashov
+ **/
+ public function paste($volume, $src, $dst, $rmSrc = false) {
+ $err = $rmSrc ? elFinder::ERROR_MOVE : elFinder::ERROR_COPY;
+
+ if ($this->commandDisabled('paste')) {
+ return $this->setError($err, '#'.$src, elFinder::ERROR_PERM_DENIED);
+ }
+
+ if (($file = $volume->file($src, $rmSrc)) == false) {
+ return $this->setError($err, '#'.$src, elFinder::ERROR_FILE_NOT_FOUND);
+ }
+
+ $name = $file['name'];
+ $errpath = $volume->path($src);
+
+ if (($dir = $this->dir($dst)) == false) {
+ return $this->setError($err, $errpath, elFinder::ERROR_TRGDIR_NOT_FOUND, '#'.$dst);
+ }
+
+ if (!$dir['write'] || !$file['read']) {
+ return $this->setError($err, $errpath, elFinder::ERROR_PERM_DENIED);
+ }
+
+ $destination = $this->decode($dst);
+
+ if (($test = $volume->closest($src, $rmSrc ? 'locked' : 'read', $rmSrc))) {
+ return $rmSrc
+ ? $this->setError($err, $errpath, elFinder::ERROR_LOCKED, $volume->path($test))
+ : $this->setError($err, $errpath, elFinder::ERROR_PERM_DENIED);
+ }
+
+ $test = $this->_joinPath($destination, $name);
+ $stat = $this->stat($test);
+ $this->clearcache();
+ if ($stat) {
+ if ($this->options['copyOverwrite']) {
+ // do not replace file with dir or dir with file
+ if (!$this->isSameType($file['mime'], $stat['mime'])) {
+ return $this->setError(elFinder::ERROR_NOT_REPLACE, $this->_path($test));
+ }
+ // existed file is not writable
+ if (!$stat['write']) {
+ return $this->setError($err, $errpath, elFinder::ERROR_PERM_DENIED);
+ }
+ // existed file locked or has locked child
+ if (($locked = $this->closestByAttr($test, 'locked', true))) {
+ return $this->setError(elFinder::ERROR_LOCKED, $this->_path($locked));
+ }
+ // target is entity file of alias
+ if ($volume == $this && ($test == @$file['target'] || $test == $this->decode($src))) {
+ return $this->setError(elFinder::ERROR_REPLACE, $errpath);
+ }
+ // remove existed file
+ if (!$this->remove($test)) {
+ return $this->setError(elFinder::ERROR_REPLACE, $this->_path($test));
+ }
+ } else {
+ $name = $this->uniqueName($destination, $name, ' ', false);
+ }
+ }
+
+ // copy/move inside current volume
+ if ($volume == $this) {
+ $source = $this->decode($src);
+ // do not copy into itself
+ if ($this->_inpath($destination, $source)) {
+ return $this->setError(elFinder::ERROR_COPY_INTO_ITSELF, $errpath);
+ }
+ $method = $rmSrc ? 'move' : 'copy';
+ return ($path = $this->$method($source, $destination, $name)) ? $this->stat($path) : false;
+ }
+
+ // copy/move from another volume
+ if (!$this->options['copyTo'] || !$volume->copyFromAllowed()) {
+ return $this->setError(elFinder::ERROR_COPY, $errpath, elFinder::ERROR_PERM_DENIED);
+ }
+
+ if (($path = $this->copyFrom($volume, $src, $destination, $name)) == false) {
+ return false;
+ }
+
+ if ($rmSrc) {
+ if ($volume->rm($src)) {
+ $this->removed[] = $file;
+ } else {
+ return $this->setError(elFinder::ERROR_MOVE, $errpath, elFinder::ERROR_RM_SRC);
+ }
+ }
+ return $this->stat($path);
+ }
+
+ /**
+ * Return file contents
+ *
+ * @param string $hash file hash
+ * @return string|false
+ * @author Dmitry (dio) Levashov
+ **/
+ public function getContents($hash) {
+ $file = $this->file($hash);
+
+ if (!$file) {
+ return $this->setError(elFinder::ERROR_FILE_NOT_FOUND);
+ }
+
+ if ($file['mime'] == 'directory') {
+ return $this->setError(elFinder::ERROR_NOT_FILE);
+ }
+
+ if (!$file['read']) {
+ return $this->setError(elFinder::ERROR_PERM_DENIED);
+ }
+
+ return $this->_getContents($this->decode($hash));
+ }
+
+ /**
+ * Put content in text file and return file info.
+ *
+ * @param string $hash file hash
+ * @param string $content new file content
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ public function putContents($hash, $content) {
+ if ($this->commandDisabled('edit')) {
+ return $this->setError(elFinder::ERROR_PERM_DENIED);
+ }
+
+ $path = $this->decode($hash);
+
+ if (!($file = $this->file($hash))) {
+ return $this->setError(elFinder::ERROR_FILE_NOT_FOUND);
+ }
+
+ if (!$file['write']) {
+ return $this->setError(elFinder::ERROR_PERM_DENIED);
+ }
+ $this->clearcache();
+ return $this->_filePutContents($path, $content) ? $this->stat($path) : false;
+ }
+
+ /**
+ * Extract files from archive
+ *
+ * @param string $hash archive hash
+ * @return array|bool
+ * @author Dmitry (dio) Levashov,
+ * @author Alexey Sukhotin
+ **/
+ public function extract($hash) {
+ if ($this->commandDisabled('extract')) {
+ return $this->setError(elFinder::ERROR_PERM_DENIED);
+ }
+
+ if (($file = $this->file($hash)) == false) {
+ return $this->setError(elFinder::ERROR_FILE_NOT_FOUND);
+ }
+
+ $archiver = isset($this->archivers['extract'][$file['mime']])
+ ? $this->archivers['extract'][$file['mime']]
+ : false;
+
+ if (!$archiver) {
+ return $this->setError(elFinder::ERROR_NOT_ARCHIVE);
+ }
+
+ $path = $this->decode($hash);
+ $parent = $this->stat($this->_dirname($path));
+
+ if (!$file['read'] || !$parent['write']) {
+ return $this->setError(elFinder::ERROR_PERM_DENIED);
+ }
+ $this->clearcache();
+ return ($path = $this->_extract($path, $archiver)) ? $this->stat($path) : false;
+ }
+
+ /**
+ * Add files to archive
+ *
+ * @return void
+ **/
+ public function archive($hashes, $mime) {
+ if ($this->commandDisabled('archive')) {
+ return $this->setError(elFinder::ERROR_PERM_DENIED);
+ }
+
+ $archiver = isset($this->archivers['create'][$mime])
+ ? $this->archivers['create'][$mime]
+ : false;
+
+ if (!$archiver) {
+ return $this->setError(elFinder::ERROR_ARCHIVE_TYPE);
+ }
+
+ $files = array();
+
+ foreach ($hashes as $hash) {
+ if (($file = $this->file($hash)) == false) {
+ return $this->error(elFinder::ERROR_FILE_NOT_FOUND, '#'+$hash);
+ }
+ if (!$file['read']) {
+ return $this->error(elFinder::ERROR_PERM_DENIED);
+ }
+ $path = $this->decode($hash);
+ if (!isset($dir)) {
+ $dir = $this->_dirname($path);
+ $stat = $this->stat($dir);
+ if (!$stat['write']) {
+ return $this->error(elFinder::ERROR_PERM_DENIED);
+ }
+ }
+
+ $files[] = $this->_basename($path);
+ }
+
+ $name = (count($files) == 1 ? $files[0] : 'Archive').'.'.$archiver['ext'];
+ $name = $this->uniqueName($dir, $name, '');
+ $this->clearcache();
+ return ($path = $this->_archive($dir, $files, $name, $archiver)) ? $this->stat($path) : false;
+ }
+
+ /**
+ * Resize image
+ *
+ * @param string $hash image file
+ * @param int $width new width
+ * @param int $height new height
+ * @param int $x X start poistion for crop
+ * @param int $y Y start poistion for crop
+ * @param string $mode action how to mainpulate image
+ * @return array|false
+ * @author Dmitry (dio) Levashov
+ * @author Alexey Sukhotin
+ * @author nao-pon
+ * @author Troex Nevelin
+ **/
+ public function resize($hash, $width, $height, $x, $y, $mode = 'resize', $bg = '', $degree = 0) {
+ if ($this->commandDisabled('resize')) {
+ return $this->setError(elFinder::ERROR_PERM_DENIED);
+ }
+
+ if (($file = $this->file($hash)) == false) {
+ return $this->setError(elFinder::ERROR_FILE_NOT_FOUND);
+ }
+
+ if (!$file['write'] || !$file['read']) {
+ return $this->setError(elFinder::ERROR_PERM_DENIED);
+ }
+
+ $path = $this->decode($hash);
+
+ if (!$this->canResize($path, $file)) {
+ return $this->setError(elFinder::ERROR_UNSUPPORT_TYPE);
+ }
+
+ switch($mode) {
+
+ case 'propresize':
+ $result = $this->imgResize($path, $width, $height, true, true);
+ break;
+
+ case 'crop':
+ $result = $this->imgCrop($path, $width, $height, $x, $y);
+ break;
+
+ case 'fitsquare':
+ $result = $this->imgSquareFit($path, $width, $height, 'center', 'middle', ($bg ? $bg : $this->options['tmbBgColor']));
+ break;
+
+ case 'rotate':
+ $result = $this->imgRotate($path, $degree, ($bg ? $bg : $this->options['tmbBgColor']));
+ break;
+
+ default:
+ $result = $this->imgResize($path, $width, $height, false, true);
+ break;
+ }
+
+ if ($result) {
+ $this->rmTmb($file);
+ $this->clearcache();
+ return $this->stat($path);
+ }
+
+ return false;
+ }
+
+ /**
+ * Remove file/dir
+ *
+ * @param string $hash file hash
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ public function rm($hash) {
+ return $this->commandDisabled('rm')
+ ? array(elFinder::ERROR_ACCESS_DENIED)
+ : $this->remove($this->decode($hash));
+ }
+
+ /**
+ * Search files
+ *
+ * @param string $q search string
+ * @param array $mimes
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ public function search($q, $mimes) {
+ return $this->doSearch($this->root, $q, $mimes);
+ }
+
+ /**
+ * Return image dimensions
+ *
+ * @param string $hash file hash
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ public function dimensions($hash) {
+ if (($file = $this->file($hash)) == false) {
+ return false;
+ }
+
+ return $this->_dimensions($this->decode($hash), $file['mime']);
+ }
+
+ /**
+ * Return temp path
+ *
+ * @return string
+ * @author Naoki Sawada
+ */
+ public function getTempPath() {
+ if (@ $this->tmpPath) {
+ return $this->tmpPath;
+ } else if (@ $this->tmp) {
+ return $this->tmp;
+ } else if (@ $this->tmbPath) {
+ return $this->tmbPath;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * (Make &) Get upload taget dirctory hash
+ *
+ * @param string $baseTargetHash
+ * @param string $path
+ * @param array $result
+ * @return boolean|string
+ * @author Naoki Sawada
+ */
+ public function getUploadTaget($baseTargetHash, $path, & $result) {
+ $base = $this->decode($baseTargetHash);
+ $targetHash = $baseTargetHash;
+ $path = ltrim($path, '/');
+ $dirs = explode('/', $path);
+ array_pop($dirs);
+ foreach($dirs as $dir) {
+ $targetPath = $this->_joinPath($base, $dir);
+ if (! $_realpath = $this->realpath($this->encode($targetPath))) {
+ if ($stat = $this->mkdir($targetHash, $dir)) {
+ $result['added'][] = $stat;
+ $targetHash = $stat['hash'];
+ $base = $this->decode($targetHash);
+ } else {
+ return false;
+ }
+ } else {
+ $targetHash = $this->encode($_realpath);
+ if ($this->dir($targetHash)) {
+ $base = $this->decode($targetHash);
+ } else {
+ return false;
+ }
+ }
+ }
+ return $targetHash;
+ }
+
+ /**
+ * Save error message
+ *
+ * @param array error
+ * @return false
+ * @author Dmitry(dio) Levashov
+ **/
+ protected function setError($error) {
+
+ $this->error = array();
+
+ foreach (func_get_args() as $err) {
+ if (is_array($err)) {
+ $this->error = array_merge($this->error, $err);
+ } else {
+ $this->error[] = $err;
+ }
+ }
+
+ // $this->error = is_array($error) ? $error : func_get_args();
+ return false;
+ }
+
+ /*********************************************************************/
+ /* FS API */
+ /*********************************************************************/
+
+ /***************** paths *******************/
+
+ /**
+ * Encode path into hash
+ *
+ * @param string file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ * @author Troex Nevelin
+ **/
+ protected function encode($path) {
+ if ($path !== '') {
+
+ // cut ROOT from $path for security reason, even if hacker decodes the path he will not know the root
+ $p = $this->_relpath($path);
+ // if reqesting root dir $path will be empty, then assign '/' as we cannot leave it blank for crypt
+ if ($p === '') {
+ $p = DIRECTORY_SEPARATOR;
+ }
+
+ // TODO crypt path and return hash
+ $hash = $this->crypt($p);
+ // hash is used as id in HTML that means it must contain vaild chars
+ // make base64 html safe and append prefix in begining
+ $hash = strtr(base64_encode($hash), '+/=', '-_.');
+ // remove dots '.' at the end, before it was '=' in base64
+ $hash = rtrim($hash, '.');
+ // append volume id to make hash unique
+ return $this->id.$hash;
+ }
+ }
+
+ /**
+ * Decode path from hash
+ *
+ * @param string file hash
+ * @return string
+ * @author Dmitry (dio) Levashov
+ * @author Troex Nevelin
+ **/
+ protected function decode($hash) {
+ if (strpos($hash, $this->id) === 0) {
+ // cut volume id after it was prepended in encode
+ $h = substr($hash, strlen($this->id));
+ // replace HTML safe base64 to normal
+ $h = base64_decode(strtr($h, '-_.', '+/='));
+ // TODO uncrypt hash and return path
+ $path = $this->uncrypt($h);
+ // append ROOT to path after it was cut in encode
+ return $this->_abspath($path);//$this->root.($path == DIRECTORY_SEPARATOR ? '' : DIRECTORY_SEPARATOR.$path);
+ }
+ }
+
+ /**
+ * Return crypted path
+ * Not implemented
+ *
+ * @param string path
+ * @return mixed
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function crypt($path) {
+ return $path;
+ }
+
+ /**
+ * Return uncrypted path
+ * Not implemented
+ *
+ * @param mixed hash
+ * @return mixed
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function uncrypt($hash) {
+ return $hash;
+ }
+
+ /**
+ * Validate file name based on $this->options['acceptedName'] regexp
+ *
+ * @param string $name file name
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function nameAccepted($name) {
+ if ($this->nameValidator) {
+ if (function_exists($this->nameValidator)) {
+ $f = $this->nameValidator;
+ return $f($name);
+ }
+
+ return preg_match($this->nameValidator, $name);
+ }
+ return true;
+ }
+
+ /**
+ * Return new unique name based on file name and suffix
+ *
+ * @param string $path file path
+ * @param string $suffix suffix append to name
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ public function uniqueName($dir, $name, $suffix = ' copy', $checkNum=true) {
+ $ext = '';
+
+ if (preg_match('/\.((tar\.(gz|bz|bz2|z|lzo))|cpio\.gz|ps\.gz|xcf\.(gz|bz2)|[a-z0-9]{1,4})$/i', $name, $m)) {
+ $ext = '.'.$m[1];
+ $name = substr($name, 0, strlen($name)-strlen($m[0]));
+ }
+
+ if ($checkNum && preg_match('/('.$suffix.')(\d*)$/i', $name, $m)) {
+ $i = (int)$m[2];
+ $name = substr($name, 0, strlen($name)-strlen($m[2]));
+ } else {
+ $i = 1;
+ $name .= $suffix;
+ }
+ $max = $i+100000;
+
+ while ($i <= $max) {
+ $n = $name.($i > 0 ? $i : '').$ext;
+
+ if (!$this->stat($this->_joinPath($dir, $n))) {
+ $this->clearcache();
+ return $n;
+ }
+ $i++;
+ }
+ return $name.md5($dir).$ext;
+ }
+
+ /*********************** file stat *********************/
+
+ /**
+ * Check file attribute
+ *
+ * @param string $path file path
+ * @param string $name attribute name (read|write|locked|hidden)
+ * @param bool $val attribute value returned by file system
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function attr($path, $name, $val=null) {
+ if (!isset($this->defaults[$name])) {
+ return false;
+ }
+
+
+ $perm = null;
+
+ if ($this->access) {
+ $perm = call_user_func($this->access, $name, $path, $this->options['accessControlData'], $this);
+
+ if ($perm !== null) {
+ return !!$perm;
+ }
+ }
+
+ if ($this->separator != '/') {
+ $path = str_replace($this->separator, '/', $this->_relpath($path));
+ } else {
+ $path = $this->_relpath($path);
+ }
+
+ $path = '/'.$path;
+
+ for ($i = 0, $c = count($this->attributes); $i < $c; $i++) {
+ $attrs = $this->attributes[$i];
+
+ if (isset($attrs[$name]) && isset($attrs['pattern']) && preg_match($attrs['pattern'], $path)) {
+ $perm = $attrs[$name];
+ }
+ }
+
+ return $perm === null ? (is_null($val)? $this->defaults[$name] : $val) : !!$perm;
+ }
+
+ /**
+ * Return true if file with given name can be created in given folder.
+ *
+ * @param string $dir parent dir path
+ * @param string $name new file name
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function allowCreate($dir, $name) {
+ $path = $this->_joinPath($dir, $name);
+ $perm = null;
+
+ if ($this->access) {
+ $perm = call_user_func($this->access, 'write', $path, $this->options['accessControlData'], $this);
+ if ($perm !== null) {
+ return !!$perm;
+ }
+ }
+
+ $testPath = $this->separator.$this->_relpath($path);
+
+ for ($i = 0, $c = count($this->attributes); $i < $c; $i++) {
+ $attrs = $this->attributes[$i];
+
+ if (isset($attrs['write']) && isset($attrs['pattern']) && preg_match($attrs['pattern'], $testPath)) {
+ $perm = $attrs['write'];
+ }
+ }
+
+ return $perm === null ? true : $perm;
+ }
+
+ /**
+ * Return fileinfo
+ *
+ * @param string $path file cache
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function stat($path) {
+ if ($path === false) {
+ return false;
+ }
+ return isset($this->cache[$path])
+ ? $this->cache[$path]
+ : $this->updateCache($path, $this->_stat($path));
+ }
+
+ /**
+ * Put file stat in cache and return it
+ *
+ * @param string $path file path
+ * @param array $stat file stat
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function updateCache($path, $stat) {
+ if (empty($stat) || !is_array($stat)) {
+ return $this->cache[$path] = array();
+ }
+
+ $stat['hash'] = $this->encode($path);
+
+ $root = $path == $this->root;
+
+ if ($root) {
+ $stat['volumeid'] = $this->id;
+ if ($this->rootName) {
+ $stat['name'] = $this->rootName;
+ }
+ } else {
+ if (!isset($stat['name']) || !strlen($stat['name'])) {
+ $stat['name'] = $this->_basename($path);
+ }
+ if (empty($stat['phash'])) {
+ $stat['phash'] = $this->encode($this->_dirname($path));
+ }
+ }
+
+ // fix name if required
+ if ($this->options['utf8fix'] && $this->options['utf8patterns'] && $this->options['utf8replace']) {
+ $stat['name'] = json_decode(str_replace($this->options['utf8patterns'], $this->options['utf8replace'], json_encode($stat['name'])));
+ }
+
+
+ if (empty($stat['mime'])) {
+ $stat['mime'] = $this->mimetype($stat['name']);
+ }
+
+ // @todo move dateformat to client
+ // $stat['date'] = isset($stat['ts'])
+ // ? $this->formatDate($stat['ts'])
+ // : 'unknown';
+
+ if (!isset($stat['size'])) {
+ $stat['size'] = 'unknown';
+ }
+
+ $stat['read'] = intval($this->attr($path, 'read', isset($stat['read']) ? !!$stat['read'] : null));
+ $stat['write'] = intval($this->attr($path, 'write', isset($stat['write']) ? !!$stat['write'] : null));
+ if ($root) {
+ $stat['locked'] = 1;
+ } elseif ($this->attr($path, 'locked', !empty($stat['locked']))) {
+ $stat['locked'] = 1;
+ } else {
+ unset($stat['locked']);
+ }
+
+ if ($root) {
+ unset($stat['hidden']);
+ } elseif ($this->attr($path, 'hidden', !empty($stat['hidden']))
+ || !$this->mimeAccepted($stat['mime'])) {
+ $stat['hidden'] = $root ? 0 : 1;
+ } else {
+ unset($stat['hidden']);
+ }
+
+ if ($stat['read'] && empty($stat['hidden'])) {
+
+ if ($stat['mime'] == 'directory') {
+ // for dir - check for subdirs
+
+ if ($this->options['checkSubfolders']) {
+ if (isset($stat['dirs'])) {
+ if ($stat['dirs']) {
+ $stat['dirs'] = 1;
+ } else {
+ unset($stat['dirs']);
+ }
+ } elseif (!empty($stat['alias']) && !empty($stat['target'])) {
+ $stat['dirs'] = isset($this->cache[$stat['target']])
+ ? intval(isset($this->cache[$stat['target']]['dirs']))
+ : $this->_subdirs($stat['target']);
+
+ } elseif ($this->_subdirs($path)) {
+ $stat['dirs'] = 1;
+ }
+ } else {
+ $stat['dirs'] = 1;
+ }
+ } else {
+ // for files - check for thumbnails
+ $p = isset($stat['target']) ? $stat['target'] : $path;
+ if ($this->tmbURL && !isset($stat['tmb']) && $this->canCreateTmb($p, $stat)) {
+ $tmb = $this->gettmb($p, $stat);
+ $stat['tmb'] = $tmb ? $tmb : 1;
+ }
+
+ }
+ }
+
+ if (!empty($stat['alias']) && !empty($stat['target'])) {
+ $stat['thash'] = $this->encode($stat['target']);
+ unset($stat['target']);
+ }
+
+ return $this->cache[$path] = $stat;
+ }
+
+ /**
+ * Get stat for folder content and put in cache
+ *
+ * @param string $path
+ * @return void
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function cacheDir($path) {
+ $this->dirsCache[$path] = array();
+
+ foreach ($this->_scandir($path) as $p) {
+ if (($stat = $this->stat($p)) && empty($stat['hidden'])) {
+ $this->dirsCache[$path][] = $p;
+ }
+ }
+ }
+
+ /**
+ * Clean cache
+ *
+ * @return void
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function clearcache() {
+ $this->cache = $this->dirsCache = array();
+ }
+
+ /**
+ * Return file mimetype
+ *
+ * @param string $path file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function mimetype($path, $name = '') {
+ $type = '';
+
+ if ($this->mimeDetect == 'finfo') {
+ if ($type = @finfo_file($this->finfo, $path)) {
+ if ($name === '') {
+ $name = $path;
+ }
+ $ext = (false === $pos = strrpos($name, '.')) ? '' : substr($name, $pos + 1);
+ if ($ext && preg_match('~^application/(?:octet-stream|(?:x-)?zip)~', $type)) {
+ if (isset(elFinderVolumeDriver::$mimetypes[$ext])) $type = elFinderVolumeDriver::$mimetypes[$ext];
+ }
+ }
+ } elseif ($type == 'mime_content_type') {
+ $type = mime_content_type($path);
+ } else {
+ $type = elFinderVolumeDriver::mimetypeInternalDetect($path);
+ }
+
+ $type = explode(';', $type);
+ $type = trim($type[0]);
+
+ if (in_array($type, array('application/x-empty', 'inode/x-empty'))) {
+ // finfo return this mime for empty files
+ $type = 'text/plain';
+ } elseif ($type == 'application/x-zip') {
+ // http://elrte.org/redmine/issues/163
+ $type = 'application/zip';
+ }
+
+ return $type == 'unknown' && $this->mimeDetect != 'internal'
+ ? elFinderVolumeDriver::mimetypeInternalDetect($path)
+ : $type;
+
+ }
+
+ /**
+ * Detect file mimetype using "internal" method
+ *
+ * @param string $path file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ static protected function mimetypeInternalDetect($path) {
+ $pinfo = pathinfo($path);
+ $ext = isset($pinfo['extension']) ? strtolower($pinfo['extension']) : '';
+ return isset(elFinderVolumeDriver::$mimetypes[$ext]) ? elFinderVolumeDriver::$mimetypes[$ext] : 'unknown';
+
+ }
+
+ /**
+ * Return file/total directory size
+ *
+ * @param string $path file path
+ * @return int
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function countSize($path) {
+ $stat = $this->stat($path);
+
+ if (empty($stat) || !$stat['read'] || !empty($stat['hidden'])) {
+ return 'unknown';
+ }
+
+ if ($stat['mime'] != 'directory') {
+ return $stat['size'];
+ }
+
+ $subdirs = $this->options['checkSubfolders'];
+ $this->options['checkSubfolders'] = true;
+ $result = 0;
+ foreach ($this->getScandir($path) as $stat) {
+ $size = $stat['mime'] == 'directory' && $stat['read']
+ ? $this->countSize($this->_joinPath($path, $stat['name']))
+ : (isset($stat['size']) ? intval($stat['size']) : 0);
+ if ($size > 0) {
+ $result += $size;
+ }
+ }
+ $this->options['checkSubfolders'] = $subdirs;
+ return $result;
+ }
+
+ /**
+ * Return true if all mimes is directory or files
+ *
+ * @param string $mime1 mimetype
+ * @param string $mime2 mimetype
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function isSameType($mime1, $mime2) {
+ return ($mime1 == 'directory' && $mime1 == $mime2) || ($mime1 != 'directory' && $mime2 != 'directory');
+ }
+
+ /**
+ * If file has required attr == $val - return file path,
+ * If dir has child with has required attr == $val - return child path
+ *
+ * @param string $path file path
+ * @param string $attr attribute name
+ * @param bool $val attribute value
+ * @return string|false
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function closestByAttr($path, $attr, $val) {
+ $stat = $this->stat($path);
+
+ if (empty($stat)) {
+ return false;
+ }
+
+ $v = isset($stat[$attr]) ? $stat[$attr] : false;
+
+ if ($v == $val) {
+ return $path;
+ }
+
+ return $stat['mime'] == 'directory'
+ ? $this->childsByAttr($path, $attr, $val)
+ : false;
+ }
+
+ /**
+ * Return first found children with required attr == $val
+ *
+ * @param string $path file path
+ * @param string $attr attribute name
+ * @param bool $val attribute value
+ * @return string|false
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function childsByAttr($path, $attr, $val) {
+ foreach ($this->_scandir($path) as $p) {
+ if (($_p = $this->closestByAttr($p, $attr, $val)) != false) {
+ return $_p;
+ }
+ }
+ return false;
+ }
+
+ /***************** get content *******************/
+
+ /**
+ * Return required dir's files info.
+ * If onlyMimes is set - return only dirs and files of required mimes
+ *
+ * @param string $path dir path
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function getScandir($path) {
+ $files = array();
+
+ !isset($this->dirsCache[$path]) && $this->cacheDir($path);
+
+ foreach ($this->dirsCache[$path] as $p) {
+ if (($stat = $this->stat($p)) && empty($stat['hidden'])) {
+ $files[] = $stat;
+ }
+ }
+
+ return $files;
+ }
+
+
+ /**
+ * Return subdirs tree
+ *
+ * @param string $path parent dir path
+ * @param int $deep tree deep
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function gettree($path, $deep, $exclude='') {
+ $dirs = array();
+
+ !isset($this->dirsCache[$path]) && $this->cacheDir($path);
+
+ foreach ($this->dirsCache[$path] as $p) {
+ $stat = $this->stat($p);
+
+ if ($stat && empty($stat['hidden']) && $p != $exclude && $stat['mime'] == 'directory') {
+ $dirs[] = $stat;
+ if ($deep > 0 && !empty($stat['dirs'])) {
+ $dirs = array_merge($dirs, $this->gettree($p, $deep-1));
+ }
+ }
+ }
+
+ return $dirs;
+ }
+
+ /**
+ * Recursive files search
+ *
+ * @param string $path dir path
+ * @param string $q search string
+ * @param array $mimes
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function doSearch($path, $q, $mimes) {
+ $result = array();
+
+ foreach($this->_scandir($path) as $p) {
+ $stat = $this->stat($p);
+
+ if (!$stat) { // invalid links
+ continue;
+ }
+
+ if (!empty($stat['hidden']) || !$this->mimeAccepted($stat['mime'])) {
+ continue;
+ }
+
+ $name = $stat['name'];
+
+ if ($this->stripos($name, $q) !== false) {
+ $stat['path'] = $this->_path($p);
+ if ($this->URL && !isset($stat['url'])) {
+ $stat['url'] = $this->URL . str_replace($this->separator, '/', substr($p, strlen($this->root) + 1));
+ }
+
+ $result[] = $stat;
+ }
+ if ($stat['mime'] == 'directory' && $stat['read'] && !isset($stat['alias'])) {
+ $result = array_merge($result, $this->doSearch($p, $q, $mimes));
+ }
+ }
+
+ return $result;
+ }
+
+ /********************** manuipulations ******************/
+
+ /**
+ * Copy file/recursive copy dir only in current volume.
+ * Return new file path or false.
+ *
+ * @param string $src source path
+ * @param string $dst destination dir path
+ * @param string $name new file name (optionaly)
+ * @return string|false
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function copy($src, $dst, $name) {
+ $srcStat = $this->stat($src);
+ $this->clearcache();
+
+ if (!empty($srcStat['thash'])) {
+ $target = $this->decode($srcStat['thash']);
+ $stat = $this->stat($target);
+ $this->clearcache();
+ return $stat && $this->_symlink($target, $dst, $name)
+ ? $this->_joinPath($dst, $name)
+ : $this->setError(elFinder::ERROR_COPY, $this->_path($src));
+ }
+
+ if ($srcStat['mime'] == 'directory') {
+ $test = $this->stat($this->_joinPath($dst, $name));
+
+ if (($test && $test['mime'] != 'directory') || !$this->_mkdir($dst, $name)) {
+ return $this->setError(elFinder::ERROR_COPY, $this->_path($src));
+ }
+
+ $dst = $this->_joinPath($dst, $name);
+
+ foreach ($this->getScandir($src) as $stat) {
+ if (empty($stat['hidden'])) {
+ $name = $stat['name'];
+ if (!$this->copy($this->_joinPath($src, $name), $dst, $name)) {
+ $this->remove($dst, true); // fall back
+ return false;
+ }
+ }
+ }
+ $this->clearcache();
+ return $dst;
+ }
+
+ return $this->_copy($src, $dst, $name)
+ ? $this->_joinPath($dst, $name)
+ : $this->setError(elFinder::ERROR_COPY, $this->_path($src));
+ }
+
+ /**
+ * Move file
+ * Return new file path or false.
+ *
+ * @param string $src source path
+ * @param string $dst destination dir path
+ * @param string $name new file name
+ * @return string|false
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function move($src, $dst, $name) {
+ $stat = $this->stat($src);
+ $stat['realpath'] = $src;
+ $this->rmTmb($stat); // can not do rmTmb() after _move()
+ $this->clearcache();
+
+ if ($this->_move($src, $dst, $name)) {
+ $this->removed[] = $stat;
+
+ return $this->_joinPath($dst, $name);
+ }
+
+ return $this->setError(elFinder::ERROR_MOVE, $this->_path($src));
+ }
+
+ /**
+ * Copy file from another volume.
+ * Return new file path or false.
+ *
+ * @param Object $volume source volume
+ * @param string $src source file hash
+ * @param string $destination destination dir path
+ * @param string $name file name
+ * @return string|false
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function copyFrom($volume, $src, $destination, $name) {
+
+ if (($source = $volume->file($src)) == false) {
+ return $this->setError(elFinder::ERROR_COPY, '#'.$src, $volume->error());
+ }
+
+ $errpath = $volume->path($src);
+
+ if (!$this->nameAccepted($source['name'])) {
+ return $this->setError(elFinder::ERROR_COPY, $errpath, elFinder::ERROR_INVALID_NAME);
+ }
+
+ if (!$source['read']) {
+ return $this->setError(elFinder::ERROR_COPY, $errpath, elFinder::ERROR_PERM_DENIED);
+ }
+
+ if ($source['mime'] == 'directory') {
+ $stat = $this->stat($this->_joinPath($destination, $name));
+ $this->clearcache();
+ if ((!$stat || $stat['mime'] != 'directory') && !$this->_mkdir($destination, $name)) {
+ return $this->setError(elFinder::ERROR_COPY, $errpath);
+ }
+
+ $path = $this->_joinPath($destination, $name);
+
+ foreach ($volume->scandir($src) as $entr) {
+ if (!$this->copyFrom($volume, $entr['hash'], $path, $entr['name'])) {
+ return false;
+ }
+ }
+
+ } else {
+ // $mime = $source['mime'];
+ // $w = $h = 0;
+ if (($dim = $volume->dimensions($src))) {
+ $s = explode('x', $dim);
+ $source['width'] = $s[0];
+ $source['height'] = $s[1];
+ }
+
+ if (($fp = $volume->open($src)) == false
+ || ($path = $this->_save($fp, $destination, $name, $source)) == false) {
+ $fp && $volume->close($fp, $src);
+ return $this->setError(elFinder::ERROR_COPY, $errpath);
+ }
+ $volume->close($fp, $src);
+ }
+
+ return $path;
+ }
+
+ /**
+ * Remove file/ recursive remove dir
+ *
+ * @param string $path file path
+ * @param bool $force try to remove even if file locked
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function remove($path, $force = false) {
+ $stat = $this->stat($path);
+
+ if (empty($stat)) {
+ return $this->setError(elFinder::ERROR_RM, $this->_path($path), elFinder::ERROR_FILE_NOT_FOUND);
+ }
+
+ $stat['realpath'] = $path;
+ $this->rmTmb($stat);
+ $this->clearcache();
+
+ if (!$force && !empty($stat['locked'])) {
+ return $this->setError(elFinder::ERROR_LOCKED, $this->_path($path));
+ }
+
+ if ($stat['mime'] == 'directory') {
+ foreach ($this->_scandir($path) as $p) {
+ $name = $this->_basename($p);
+ if ($name != '.' && $name != '..' && !$this->remove($p)) {
+ return false;
+ }
+ }
+ if (!$this->_rmdir($path)) {
+ return $this->setError(elFinder::ERROR_RM, $this->_path($path));
+ }
+
+ } else {
+ if (!$this->_unlink($path)) {
+ return $this->setError(elFinder::ERROR_RM, $this->_path($path));
+ }
+ }
+
+ $this->removed[] = $stat;
+ return true;
+ }
+
+
+ /************************* thumbnails **************************/
+
+ /**
+ * Return thumbnail file name for required file
+ *
+ * @param array $stat file stat
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function tmbname($stat) {
+ return $stat['hash'].$stat['ts'].'.png';
+ }
+
+ /**
+ * Return thumnbnail name if exists
+ *
+ * @param string $path file path
+ * @param array $stat file stat
+ * @return string|false
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function gettmb($path, $stat) {
+ if ($this->tmbURL && $this->tmbPath) {
+ // file itself thumnbnail
+ if (strpos($path, $this->tmbPath) === 0) {
+ return basename($path);
+ }
+
+ $name = $this->tmbname($stat);
+ if (file_exists($this->tmbPath.DIRECTORY_SEPARATOR.$name)) {
+ return $name;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Return true if thumnbnail for required file can be created
+ *
+ * @param string $path thumnbnail path
+ * @param array $stat file stat
+ * @return string|bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function canCreateTmb($path, $stat) {
+ return $this->tmbPathWritable
+ && strpos($path, $this->tmbPath) === false // do not create thumnbnail for thumnbnail
+ && $this->imgLib
+ && strpos($stat['mime'], 'image') === 0
+ && ($this->imgLib == 'gd' ? $stat['mime'] == 'image/jpeg' || $stat['mime'] == 'image/png' || $stat['mime'] == 'image/gif' : true);
+ }
+
+ /**
+ * Return true if required file can be resized.
+ * By default - the same as canCreateTmb
+ *
+ * @param string $path thumnbnail path
+ * @param array $stat file stat
+ * @return string|bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function canResize($path, $stat) {
+ return $this->canCreateTmb($path, $stat);
+ }
+
+ /**
+ * Create thumnbnail and return it's URL on success
+ *
+ * @param string $path file path
+ * @param string $mime file mime type
+ * @return string|false
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function createTmb($path, $stat) {
+ if (!$stat || !$this->canCreateTmb($path, $stat)) {
+ return false;
+ }
+
+ $name = $this->tmbname($stat);
+ $tmb = $this->tmbPath.DIRECTORY_SEPARATOR.$name;
+
+ // copy image into tmbPath so some drivers does not store files on local fs
+ if (($src = $this->_fopen($path, 'rb')) == false) {
+ return false;
+ }
+
+ if (($trg = fopen($tmb, 'wb')) == false) {
+ $this->_fclose($src, $path);
+ return false;
+ }
+
+ while (!feof($src)) {
+ fwrite($trg, fread($src, 8192));
+ }
+
+ $this->_fclose($src, $path);
+ fclose($trg);
+
+ $result = false;
+
+ $tmbSize = $this->tmbSize;
+
+ if (($s = getimagesize($tmb)) == false) {
+ return false;
+ }
+
+ /* If image smaller or equal thumbnail size - just fitting to thumbnail square */
+ if ($s[0] <= $tmbSize && $s[1] <= $tmbSize) {
+ $result = $this->imgSquareFit($tmb, $tmbSize, $tmbSize, 'center', 'middle', $this->options['tmbBgColor'], 'png' );
+ } else {
+
+ if ($this->options['tmbCrop']) {
+
+ /* Resize and crop if image bigger than thumbnail */
+ if (!(($s[0] > $tmbSize && $s[1] <= $tmbSize) || ($s[0] <= $tmbSize && $s[1] > $tmbSize) ) || ($s[0] > $tmbSize && $s[1] > $tmbSize)) {
+ $result = $this->imgResize($tmb, $tmbSize, $tmbSize, true, false, 'png');
+ }
+
+ if (($s = getimagesize($tmb)) != false) {
+ $x = $s[0] > $tmbSize ? intval(($s[0] - $tmbSize)/2) : 0;
+ $y = $s[1] > $tmbSize ? intval(($s[1] - $tmbSize)/2) : 0;
+ $result = $this->imgCrop($tmb, $tmbSize, $tmbSize, $x, $y, 'png');
+ }
+
+ } else {
+ $result = $this->imgResize($tmb, $tmbSize, $tmbSize, true, true, 'png');
+ }
+
+ $result = $this->imgSquareFit($tmb, $tmbSize, $tmbSize, 'center', 'middle', $this->options['tmbBgColor'], 'png' );
+ }
+
+ if (!$result) {
+ unlink($tmb);
+ return false;
+ }
+
+ return $name;
+ }
+
+ /**
+ * Resize image
+ *
+ * @param string $path image file
+ * @param int $width new width
+ * @param int $height new height
+ * @param bool $keepProportions crop image
+ * @param bool $resizeByBiggerSide resize image based on bigger side if true
+ * @param string $destformat image destination format
+ * @return string|false
+ * @author Dmitry (dio) Levashov
+ * @author Alexey Sukhotin
+ **/
+ protected function imgResize($path, $width, $height, $keepProportions = false, $resizeByBiggerSide = true, $destformat = null) {
+ if (($s = @getimagesize($path)) == false) {
+ return false;
+ }
+
+ $result = false;
+
+ list($size_w, $size_h) = array($width, $height);
+
+ if ($keepProportions == true) {
+
+ list($orig_w, $orig_h, $new_w, $new_h) = array($s[0], $s[1], $width, $height);
+
+ /* Calculating image scale width and height */
+ $xscale = $orig_w / $new_w;
+ $yscale = $orig_h / $new_h;
+
+ /* Resizing by biggest side */
+
+ if ($resizeByBiggerSide) {
+
+ if ($orig_w > $orig_h) {
+ $size_h = $orig_h * $width / $orig_w;
+ $size_w = $width;
+ } else {
+ $size_w = $orig_w * $height / $orig_h;
+ $size_h = $height;
+ }
+
+ } else {
+ if ($orig_w > $orig_h) {
+ $size_w = $orig_w * $height / $orig_h;
+ $size_h = $height;
+ } else {
+ $size_h = $orig_h * $width / $orig_w;
+ $size_w = $width;
+ }
+ }
+ }
+
+ switch ($this->imgLib) {
+ case 'imagick':
+
+ try {
+ $img = new imagick($path);
+ } catch (Exception $e) {
+
+ return false;
+ }
+
+ $img->resizeImage($size_w, $size_h, Imagick::FILTER_LANCZOS, true);
+
+ $result = $img->writeImage($path);
+
+ return $result ? $path : false;
+
+ break;
+
+ case 'gd':
+ $img = self::gdImageCreate($path,$s['mime']);
+
+ if ($img && false != ($tmp = imagecreatetruecolor($size_w, $size_h))) {
+
+ self::gdImageBackground($tmp,$this->options['tmbBgColor']);
+
+ if (!imagecopyresampled($tmp, $img, 0, 0, 0, 0, $size_w, $size_h, $s[0], $s[1])) {
+ return false;
+ }
+
+ $result = self::gdImage($tmp, $path, $destformat, $s['mime']);
+
+ imagedestroy($img);
+ imagedestroy($tmp);
+
+ return $result ? $path : false;
+
+ }
+ break;
+ }
+
+ return false;
+ }
+
+ /**
+ * Crop image
+ *
+ * @param string $path image file
+ * @param int $width crop width
+ * @param int $height crop height
+ * @param bool $x crop left offset
+ * @param bool $y crop top offset
+ * @param string $destformat image destination format
+ * @return string|false
+ * @author Dmitry (dio) Levashov
+ * @author Alexey Sukhotin
+ **/
+ protected function imgCrop($path, $width, $height, $x, $y, $destformat = null) {
+ if (($s = @getimagesize($path)) == false) {
+ return false;
+ }
+
+ $result = false;
+
+ switch ($this->imgLib) {
+ case 'imagick':
+
+ try {
+ $img = new imagick($path);
+ } catch (Exception $e) {
+
+ return false;
+ }
+
+ $img->cropImage($width, $height, $x, $y);
+
+ $result = $img->writeImage($path);
+
+ return $result ? $path : false;
+
+ break;
+
+ case 'gd':
+ $img = self::gdImageCreate($path,$s['mime']);
+
+ if ($img && false != ($tmp = imagecreatetruecolor($width, $height))) {
+
+ self::gdImageBackground($tmp,$this->options['tmbBgColor']);
+
+ $size_w = $width;
+ $size_h = $height;
+
+ if ($s[0] < $width || $s[1] < $height) {
+ $size_w = $s[0];
+ $size_h = $s[1];
+ }
+
+ if (!imagecopy($tmp, $img, 0, 0, $x, $y, $size_w, $size_h)) {
+ return false;
+ }
+
+ $result = self::gdImage($tmp, $path, $destformat, $s['mime']);
+
+ imagedestroy($img);
+ imagedestroy($tmp);
+
+ return $result ? $path : false;
+
+ }
+ break;
+ }
+
+ return false;
+ }
+
+ /**
+ * Put image to square
+ *
+ * @param string $path image file
+ * @param int $width square width
+ * @param int $height square height
+ * @param int $align reserved
+ * @param int $valign reserved
+ * @param string $bgcolor square background color in #rrggbb format
+ * @param string $destformat image destination format
+ * @return string|false
+ * @author Dmitry (dio) Levashov
+ * @author Alexey Sukhotin
+ **/
+ protected function imgSquareFit($path, $width, $height, $align = 'center', $valign = 'middle', $bgcolor = '#0000ff', $destformat = null) {
+ if (($s = @getimagesize($path)) == false) {
+ return false;
+ }
+
+ $result = false;
+
+ /* Coordinates for image over square aligning */
+ $y = ceil(abs($height - $s[1]) / 2);
+ $x = ceil(abs($width - $s[0]) / 2);
+
+ switch ($this->imgLib) {
+ case 'imagick':
+ try {
+ $img = new imagick($path);
+ } catch (Exception $e) {
+ return false;
+ }
+
+ $img1 = new Imagick();
+ $img1->newImage($width, $height, new ImagickPixel($bgcolor));
+ $img1->setImageColorspace($img->getImageColorspace());
+ $img1->setImageFormat($destformat != null ? $destformat : $img->getFormat());
+ $img1->compositeImage( $img, imagick::COMPOSITE_OVER, $x, $y );
+ $result = $img1->writeImage($path);
+ return $result ? $path : false;
+
+ break;
+
+ case 'gd':
+ $img = self::gdImageCreate($path,$s['mime']);
+
+ if ($img && false != ($tmp = imagecreatetruecolor($width, $height))) {
+
+ self::gdImageBackground($tmp,$bgcolor);
+
+ if (!imagecopy($tmp, $img, $x, $y, 0, 0, $s[0], $s[1])) {
+ return false;
+ }
+
+ $result = self::gdImage($tmp, $path, $destformat, $s['mime']);
+
+ imagedestroy($img);
+ imagedestroy($tmp);
+
+ return $result ? $path : false;
+ }
+ break;
+ }
+
+ return false;
+ }
+
+ /**
+ * Rotate image
+ *
+ * @param string $path image file
+ * @param int $degree rotete degrees
+ * @param string $bgcolor square background color in #rrggbb format
+ * @param string $destformat image destination format
+ * @return string|false
+ * @author nao-pon
+ * @author Troex Nevelin
+ **/
+ protected function imgRotate($path, $degree, $bgcolor = '#ffffff', $destformat = null) {
+ if (($s = @getimagesize($path)) == false) {
+ return false;
+ }
+
+ $result = false;
+
+ switch ($this->imgLib) {
+ case 'imagick':
+ try {
+ $img = new imagick($path);
+ } catch (Exception $e) {
+ return false;
+ }
+
+ $img->rotateImage(new ImagickPixel($bgcolor), $degree);
+ $result = $img->writeImage($path);
+ return $result ? $path : false;
+
+ break;
+
+ case 'gd':
+ $img = self::gdImageCreate($path,$s['mime']);
+
+ $degree = 360 - $degree;
+ list($r, $g, $b) = sscanf($bgcolor, "#%02x%02x%02x");
+ $bgcolor = imagecolorallocate($img, $r, $g, $b);
+ $tmp = imageRotate($img, $degree, (int)$bgcolor);
+
+ $result = self::gdImage($tmp, $path, $destformat, $s['mime']);
+
+ imageDestroy($img);
+ imageDestroy($tmp);
+
+ return $result ? $path : false;
+
+ break;
+ }
+
+ return false;
+ }
+
+ /**
+ * Execute shell command
+ *
+ * @param string $command command line
+ * @param array $output stdout strings
+ * @param array $return_var process exit code
+ * @param array $error_output stderr strings
+ * @return int exit code
+ * @author Alexey Sukhotin
+ **/
+ protected function procExec($command , array &$output = null, &$return_var = -1, array &$error_output = null) {
+
+ $descriptorspec = array(
+ 0 => array("pipe", "r"), // stdin
+ 1 => array("pipe", "w"), // stdout
+ 2 => array("pipe", "w") // stderr
+ );
+
+ $process = proc_open($command, $descriptorspec, $pipes, null, null);
+
+ if (is_resource($process)) {
+
+ fclose($pipes[0]);
+
+ $tmpout = '';
+ $tmperr = '';
+
+ $output = stream_get_contents($pipes[1]);
+ $error_output = stream_get_contents($pipes[2]);
+
+ fclose($pipes[1]);
+ fclose($pipes[2]);
+ $return_var = proc_close($process);
+
+
+ }
+
+ return $return_var;
+
+ }
+
+ /**
+ * Remove thumbnail, also remove recursively if stat is directory
+ *
+ * @param string $stat file stat
+ * @return void
+ * @author Dmitry (dio) Levashov
+ * @author Naoki Sawada
+ * @author Troex Nevelin
+ **/
+ protected function rmTmb($stat) {
+ if ($stat['mime'] === 'directory') {
+ foreach ($this->_scandir($this->decode($stat['hash'])) as $p) {
+ $name = $this->_basename($p);
+ $name != '.' && $name != '..' && $this->rmTmb($this->stat($p));
+ }
+ } else if (!empty($stat['tmb']) && $stat['tmb'] != "1") {
+ $tmb = $this->tmbPath.DIRECTORY_SEPARATOR.$stat['tmb'];
+ file_exists($tmb) && @unlink($tmb);
+ clearstatcache();
+ }
+ }
+
+ /**
+ * Create an gd image according to the specified mime type
+ *
+ * @param string $path image file
+ * @param string $mime
+ * @return gd image resource identifier
+ */
+ protected function gdImageCreate($path,$mime){
+ switch($mime){
+ case 'image/jpeg':
+ return imagecreatefromjpeg($path);
+
+ case 'image/png':
+ return imagecreatefrompng($path);
+
+ case 'image/gif':
+ return imagecreatefromgif($path);
+
+ case 'image/xbm':
+ return imagecreatefromxbm($path);
+ }
+ return false;
+ }
+
+ /**
+ * Output gd image to file
+ *
+ * @param resource $image gd image resource
+ * @param string $filename The path to save the file to.
+ * @param string $destformat The Image type to use for $filename
+ * @param string $mime The original image mime type
+ */
+ protected function gdImage($image, $filename, $destformat, $mime ){
+
+ if ($destformat == 'jpg' || ($destformat == null && $mime == 'image/jpeg')) {
+ return imagejpeg($image, $filename, 100);
+ }
+
+ if ($destformat == 'gif' || ($destformat == null && $mime == 'image/gif')) {
+ return imagegif($image, $filename, 7);
+ }
+
+ return imagepng($image, $filename, 7);
+ }
+
+ /**
+ * Assign the proper background to a gd image
+ *
+ * @param resource $image gd image resource
+ * @param string $bgcolor background color in #rrggbb format
+ */
+ protected function gdImageBackground($image, $bgcolor){
+
+ if( $bgcolor == 'transparent' ){
+ imagesavealpha($image,true);
+ $bgcolor1 = imagecolorallocatealpha($image, 255, 255, 255, 127);
+
+ }else{
+ list($r, $g, $b) = sscanf($bgcolor, "#%02x%02x%02x");
+ $bgcolor1 = imagecolorallocate($image, $r, $g, $b);
+ }
+
+ imagefill($image, 0, 0, $bgcolor1);
+ }
+
+ /*********************** misc *************************/
+
+ /**
+ * Return smart formatted date
+ *
+ * @param int $ts file timestamp
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ // protected function formatDate($ts) {
+ // if ($ts > $this->today) {
+ // return 'Today '.date($this->options['timeFormat'], $ts);
+ // }
+ //
+ // if ($ts > $this->yesterday) {
+ // return 'Yesterday '.date($this->options['timeFormat'], $ts);
+ // }
+ //
+ // return date($this->options['dateFormat'], $ts);
+ // }
+
+ /**
+ * Find position of first occurrence of string in a string with multibyte support
+ *
+ * @param string $haystack The string being checked.
+ * @param string $needle The string to find in haystack.
+ * @param int $offset The search offset. If it is not specified, 0 is used.
+ * @return int|bool
+ * @author Alexey Sukhotin
+ **/
+ protected function stripos($haystack , $needle , $offset = 0) {
+ if (function_exists('mb_stripos')) {
+ return mb_stripos($haystack , $needle , $offset);
+ } else if (function_exists('mb_strtolower') && function_exists('mb_strpos')) {
+ return mb_strpos(mb_strtolower($haystack), mb_strtolower($needle), $offset);
+ }
+ return stripos($haystack , $needle , $offset);
+ }
+
+ /**==================================* abstract methods *====================================**/
+
+ /*********************** paths/urls *************************/
+
+ /**
+ * Return parent directory path
+ *
+ * @param string $path file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ abstract protected function _dirname($path);
+
+ /**
+ * Return file name
+ *
+ * @param string $path file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ abstract protected function _basename($path);
+
+ /**
+ * Join dir name and file name and return full path.
+ * Some drivers (db) use int as path - so we give to concat path to driver itself
+ *
+ * @param string $dir dir path
+ * @param string $name file name
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ abstract protected function _joinPath($dir, $name);
+
+ /**
+ * Return normalized path
+ *
+ * @param string $path file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ abstract protected function _normpath($path);
+
+ /**
+ * Return file path related to root dir
+ *
+ * @param string $path file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ abstract protected function _relpath($path);
+
+ /**
+ * Convert path related to root dir into real path
+ *
+ * @param string $path rel file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ abstract protected function _abspath($path);
+
+ /**
+ * Return fake path started from root dir.
+ * Required to show path on client side.
+ *
+ * @param string $path file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ abstract protected function _path($path);
+
+ /**
+ * Return true if $path is children of $parent
+ *
+ * @param string $path path to check
+ * @param string $parent parent path
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ abstract protected function _inpath($path, $parent);
+
+ /**
+ * Return stat for given path.
+ * Stat contains following fields:
+ * - (int) size file size in b. required
+ * - (int) ts file modification time in unix time. required
+ * - (string) mime mimetype. required for folders, others - optionally
+ * - (bool) read read permissions. required
+ * - (bool) write write permissions. required
+ * - (bool) locked is object locked. optionally
+ * - (bool) hidden is object hidden. optionally
+ * - (string) alias for symlinks - link target path relative to root path. optionally
+ * - (string) target for symlinks - link target path. optionally
+ *
+ * If file does not exists - returns empty array or false.
+ *
+ * @param string $path file path
+ * @return array|false
+ * @author Dmitry (dio) Levashov
+ **/
+ abstract protected function _stat($path);
+
+
+ /***************** file stat ********************/
+
+
+ /**
+ * Return true if path is dir and has at least one childs directory
+ *
+ * @param string $path dir path
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ abstract protected function _subdirs($path);
+
+ /**
+ * Return object width and height
+ * Ususaly used for images, but can be realize for video etc...
+ *
+ * @param string $path file path
+ * @param string $mime file mime type
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ abstract protected function _dimensions($path, $mime);
+
+ /******************** file/dir content *********************/
+
+ /**
+ * Return files list in directory
+ *
+ * @param string $path dir path
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ abstract protected function _scandir($path);
+
+ /**
+ * Open file and return file pointer
+ *
+ * @param string $path file path
+ * @param bool $write open file for writing
+ * @return resource|false
+ * @author Dmitry (dio) Levashov
+ **/
+ abstract protected function _fopen($path, $mode="rb");
+
+ /**
+ * Close opened file
+ *
+ * @param resource $fp file pointer
+ * @param string $path file path
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ abstract protected function _fclose($fp, $path='');
+
+ /******************** file/dir manipulations *************************/
+
+ /**
+ * Create dir and return created dir path or false on failed
+ *
+ * @param string $path parent dir path
+ * @param string $name new directory name
+ * @return string|bool
+ * @author Dmitry (dio) Levashov
+ **/
+ abstract protected function _mkdir($path, $name);
+
+ /**
+ * Create file and return it's path or false on failed
+ *
+ * @param string $path parent dir path
+ * @param string $name new file name
+ * @return string|bool
+ * @author Dmitry (dio) Levashov
+ **/
+ abstract protected function _mkfile($path, $name);
+
+ /**
+ * Create symlink
+ *
+ * @param string $source file to link to
+ * @param string $targetDir folder to create link in
+ * @param string $name symlink name
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ abstract protected function _symlink($source, $targetDir, $name);
+
+ /**
+ * Copy file into another file (only inside one volume)
+ *
+ * @param string $source source file path
+ * @param string $target target dir path
+ * @param string $name file name
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ abstract protected function _copy($source, $targetDir, $name);
+
+ /**
+ * Move file into another parent dir.
+ * Return new file path or false.
+ *
+ * @param string $source source file path
+ * @param string $target target dir path
+ * @param string $name file name
+ * @return string|bool
+ * @author Dmitry (dio) Levashov
+ **/
+ abstract protected function _move($source, $targetDir, $name);
+
+ /**
+ * Remove file
+ *
+ * @param string $path file path
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ abstract protected function _unlink($path);
+
+ /**
+ * Remove dir
+ *
+ * @param string $path dir path
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ abstract protected function _rmdir($path);
+
+ /**
+ * Create new file and write into it from file pointer.
+ * Return new file path or false on error.
+ *
+ * @param resource $fp file pointer
+ * @param string $dir target dir path
+ * @param string $name file name
+ * @param array $stat file stat (required by some virtual fs)
+ * @return bool|string
+ * @author Dmitry (dio) Levashov
+ **/
+ abstract protected function _save($fp, $dir, $name, $stat);
+
+ /**
+ * Get file contents
+ *
+ * @param string $path file path
+ * @return string|false
+ * @author Dmitry (dio) Levashov
+ **/
+ abstract protected function _getContents($path);
+
+ /**
+ * Write a string to a file
+ *
+ * @param string $path file path
+ * @param string $content new file content
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ abstract protected function _filePutContents($path, $content);
+
+ /**
+ * Extract files from archive
+ *
+ * @param string $path file path
+ * @param array $arc archiver options
+ * @return bool
+ * @author Dmitry (dio) Levashov,
+ * @author Alexey Sukhotin
+ **/
+ abstract protected function _extract($path, $arc);
+
+ /**
+ * Create archive and return its path
+ *
+ * @param string $dir target dir
+ * @param array $files files names list
+ * @param string $name archive name
+ * @param array $arc archiver options
+ * @return string|bool
+ * @author Dmitry (dio) Levashov,
+ * @author Alexey Sukhotin
+ **/
+ abstract protected function _archive($dir, $files, $name, $arc);
+
+ /**
+ * Detect available archivers
+ *
+ * @return void
+ * @author Dmitry (dio) Levashov,
+ * @author Alexey Sukhotin
+ **/
+ abstract protected function _checkArchivers();
+
+} // END class
diff --git a/app/mihaildev/elfinder/php/elFinderVolumeDropbox.class.php b/app/mihaildev/elfinder/php/elFinderVolumeDropbox.class.php
new file mode 100755
index 0000000..b7208f4
--- /dev/null
+++ b/app/mihaildev/elfinder/php/elFinderVolumeDropbox.class.php
@@ -0,0 +1,1500 @@
+dropbox_phpFound = in_array('Dropbox_autoload', spl_autoload_functions());
+
+ $opts = array(
+ 'consumerKey' => '',
+ 'consumerSecret' => '',
+ 'accessToken' => '',
+ 'accessTokenSecret' => '',
+ 'dropboxUid' => '',
+ 'root' => 'dropbox',
+ 'path' => '/',
+ 'PDO_DSN' => '', // if empty use 'sqlite:(metaCachePath|tmbPath)/elFinder_dropbox_db_(hash:dropboxUid+consumerSecret)'
+ 'PDO_User' => '',
+ 'PDO_Pass' => '',
+ 'PDO_Options' => array(),
+ 'PDO_DBName' => 'dropbox',
+ 'treeDeep' => 0,
+ 'tmbPath' => '../files/.tmb',
+ 'tmbURL' => 'files/.tmb',
+ 'tmpPath' => '',
+ 'getTmbSize' => 'medium', // small: 32x32, medium or s: 64x64, large or m: 128x128, l: 640x480, xl: 1024x768
+ 'metaCachePath' => '',
+ 'metaCacheTime' => '600', // 10m
+ 'acceptedName' => '#^[^/\\?*:|"<>]*[^./\\?*:|"<>]$#',
+ 'icon' => (defined('ELFINDER_IMG_PARENT_URL')? (rtrim(ELFINDER_IMG_PARENT_URL, '/').'/') : '').'img/volume_icon_dropbox.png'
+ );
+ $this->options = array_merge($this->options, $opts);
+ $this->options['mimeDetect'] = 'internal';
+ }
+
+ /**
+ * Prepare
+ * Call from elFinder::netmout() before volume->mount()
+ *
+ * @return Array
+ * @author Naoki Sawada
+ **/
+ public function netmountPrepare($options) {
+ if (empty($options['consumerKey']) && defined('ELFINDER_DROPBOX_CONSUMERKEY')) $options['consumerKey'] = ELFINDER_DROPBOX_CONSUMERKEY;
+ if (empty($options['consumerSecret']) && defined('ELFINDER_DROPBOX_CONSUMERSECRET')) $options['consumerSecret'] = ELFINDER_DROPBOX_CONSUMERSECRET;
+
+ if ($options['user'] === 'init') {
+
+ if (! $this->dropbox_phpFound || empty($options['consumerKey']) || empty($options['consumerSecret'])) {
+ return array('exit' => true, 'body' => '{msg:errNetMountNoDriver}');
+ }
+
+ if (class_exists('OAuth')) {
+ $this->oauth = new Dropbox_OAuth_PHP($options['consumerKey'], $options['consumerSecret']);
+ } else {
+ if (! class_exists('HTTP_OAuth_Consumer')) {
+ // We're going to try to load in manually
+ include 'HTTP/OAuth/Consumer.php';
+ }
+ if (class_exists('HTTP_OAuth_Consumer')) {
+ $this->oauth = new Dropbox_OAuth_PEAR($options['consumerKey'], $options['consumerSecret']);
+ }
+ }
+
+ if (! $this->oauth) {
+ return array('exit' => true, 'body' => '{msg:errNetMountNoDriver}');
+ }
+
+ if ($options['pass'] === 'init') {
+ $html = '';
+ if (isset($_SESSION['elFinderDropboxTokens'])) {
+ // token check
+ try {
+ list(, $accessToken, $accessTokenSecret) = $_SESSION['elFinderDropboxTokens'];
+ $this->oauth->setToken($accessToken, $accessTokenSecret);
+ $this->dropbox = new Dropbox_API($this->oauth, $this->options['root']);
+ $this->dropbox->getAccountInfo();
+ $script = '';
+ $html = 'Dropbox.com'.$script;
+ } catch (Dropbox_Exception $e) {
+ unset($_SESSION['elFinderDropboxTokens']);
+ }
+ }
+ if (! $html) {
+ // get customdata
+ $cdata = '';
+ $innerKeys = array('cmd', 'host', 'options', 'pass', 'protocol', 'user');
+ $post = (strtolower($_SERVER['REQUEST_METHOD']) === 'post')? $_POST : $_GET;
+ foreach($post as $k => $v) {
+ if (! in_array($k, $innerKeys)) {
+ $cdata .= '&' . $k . '=' . rawurlencode($v);
+ }
+ }
+ if (strpos($options['url'], 'http') !== 0 ) {
+ $options['url'] = $this->getConnectorUrl();
+ }
+ $callback = $options['url']
+ . '?cmd=netmount&protocol=dropbox&host=dropbox.com&user=init&pass=return'.$cdata;
+
+ try {
+ $tokens = $this->oauth->getRequestToken();
+ $url= $this->oauth->getAuthorizeUrl(rawurlencode($callback));
+ } catch (Dropbox_Exception $e) {
+ return array('exit' => true, 'body' => '{msg:errAccess}');
+ }
+
+ $_SESSION['elFinderDropboxAuthTokens'] = $tokens;
+ $html = ' ';
+ }
+ return array('exit' => true, 'body' => $html);
+ } else {
+ $this->oauth->setToken($_SESSION['elFinderDropboxAuthTokens']);
+ unset($_SESSION['elFinderDropboxAuthTokens']);
+ $tokens = $this->oauth->getAccessToken();
+ $_SESSION['elFinderDropboxTokens'] = array($_GET['uid'], $tokens['token'], $tokens['token_secret']);
+ $script = '
+ var p = window.opener;
+ p.$("#elfinder-cmd-netmout-dropbox-host").html("Dropbox.com");
+ p.$("#elfinder-cmd-netmout-dropbox-user").val("done");
+ p.$("#elfinder-cmd-netmout-dropbox-pass").val("done");
+ window.close();';
+
+ $out = 'Close this window ';
+
+ while( ob_get_level() ) {
+ if (! ob_end_clean()) {
+ break;
+ }
+ }
+
+ header('Content-Type: text/html; charset=utf-8');
+ header('Content-Length: '.strlen($out));
+ header('Cache-Control: private');
+ header('Pragma: no-cache');
+ echo $out;
+
+ exit();
+ }
+ }
+ if (isset($_SESSION['elFinderDropboxTokens'])) {
+ list($options['dropboxUid'], $options['accessToken'], $options['accessTokenSecret']) = $_SESSION['elFinderDropboxTokens'];
+ }
+ unset($options['user'], $options['pass']);
+ return $options;
+ }
+
+ /**
+ * process of on netunmount
+ * Drop table `dropbox` & rm thumbs
+ *
+ * @param array $options
+ * @return boolean
+ */
+ public function netunmount($options) {
+ $this->DB->exec('drop table '.$this->DB_TableName);
+ foreach(glob(rtrim($this->options['tmbPath'], '\\/').DIRECTORY_SEPARATOR.$this->tmbPrefix.'*.png') as $tmb) {
+ unlink($tmb);
+ }
+ return true;
+ }
+
+ /**
+ * Get script url
+ *
+ * @return string full URL
+ * @author Naoki Sawada
+ */
+ private function getConnectorUrl() {
+ $url = ((isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off')? 'https://' : 'http://')
+ . $_SERVER['SERVER_NAME'] // host
+ . ($_SERVER['SERVER_PORT'] == 80 ? '' : ':' . $_SERVER['SERVER_PORT']) // port
+ . $_SERVER['REQUEST_URI']; // path & query
+ list($url) = explode('?', $url);
+ return $url;
+ }
+
+ /*********************************************************************/
+ /* INIT AND CONFIGURE */
+ /*********************************************************************/
+
+ /**
+ * Prepare FTP connection
+ * Connect to remote server and check if credentials are correct, if so, store the connection id in $ftp_conn
+ *
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ * @author Cem (DiscoFever)
+ **/
+ protected function init() {
+ if (!$this->options['consumerKey']
+ || !$this->options['consumerSecret']
+ || !$this->options['accessToken']
+ || !$this->options['accessTokenSecret']) {
+ return $this->setError('Required options undefined.');
+ }
+
+ if (empty($this->options['metaCachePath']) && defined('ELFINDER_DROPBOX_META_CACHE_PATH')) {
+ $this->options['metaCachePath'] = ELFINDER_DROPBOX_META_CACHE_PATH;
+ }
+
+ // make net mount key
+ $this->netMountKey = md5(join('-', array('dropbox', $this->options['path'])));
+
+ if (! $this->oauth) {
+ if (class_exists('OAuth')) {
+ $this->oauth = new Dropbox_OAuth_PHP($this->options['consumerKey'], $this->options['consumerSecret']);
+ } else {
+ if (! class_exists('HTTP_OAuth_Consumer')) {
+ // We're going to try to load in manually
+ include 'HTTP/OAuth/Consumer.php';
+ }
+ if (class_exists('HTTP_OAuth_Consumer')) {
+ $this->oauth = new Dropbox_OAuth_PEAR($this->options['consumerKey'], $this->options['consumerSecret']);
+ }
+ }
+ }
+
+ if (! $this->oauth) {
+ return $this->setError('OAuth extension not loaded.');
+ }
+
+ // normalize root path
+ $this->root = $this->options['path'] = $this->_normpath($this->options['path']);
+
+ if (empty($this->options['alias'])) {
+ $this->options['alias'] = ($this->options['path'] === '/')? 'Dropbox.com' : 'Dropbox'.$this->options['path'];
+ }
+
+ $this->rootName = $this->options['alias'];
+ $this->options['separator'] = '/';
+
+ try {
+ $this->oauth->setToken($this->options['accessToken'], $this->options['accessTokenSecret']);
+ $this->dropbox = new Dropbox_API($this->oauth, $this->options['root']);
+ } catch (Dropbox_Exception $e) {
+ unset($_SESSION['elFinderDropboxTokens']);
+ return $this->setError('Dropbox error: '.$e->getMessage());
+ }
+
+ // user
+ if (empty($this->options['dropboxUid'])) {
+ try {
+ $res = $this->dropbox->getAccountInfo();
+ $this->options['dropboxUid'] = $res['uid'];
+ } catch (Dropbox_Exception $e) {
+ unset($_SESSION['elFinderDropboxTokens']);
+ return $this->setError('Dropbox error: '.$e->getMessage());
+ }
+ }
+ $this->dropboxUid = $this->options['dropboxUid'];
+ $this->tmbPrefix = 'dropbox'.base_convert($this->dropboxUid, 10, 32);
+
+ if (!empty($this->options['tmpPath'])) {
+ if ((is_dir($this->options['tmpPath']) || @mkdir($this->options['tmpPath'])) && is_writable($this->options['tmpPath'])) {
+ $this->tmp = $this->options['tmpPath'];
+ }
+ }
+ if (!$this->tmp && is_writable($this->options['tmbPath'])) {
+ $this->tmp = $this->options['tmbPath'];
+ }
+
+ if (!empty($this->options['metaCachePath'])) {
+ if ((is_dir($this->options['metaCachePath']) || @mkdir($this->options['metaCachePath'])) && is_writable($this->options['metaCachePath'])) {
+ $this->metaCache = $this->options['metaCachePath'];
+ }
+ }
+ if (!$this->metaCache && $this->tmp) {
+ $this->metaCache = $this->tmp;
+ }
+
+ if (!$this->tmp) {
+ $this->disabled[] = 'archive';
+ $this->disabled[] = 'extract';
+ }
+
+ if (!$this->metaCache) {
+ return $this->setError('Cache dirctory (metaCachePath or tmp) is require.');
+ }
+
+ // setup PDO
+ if (! $this->options['PDO_DSN']) {
+ $this->options['PDO_DSN'] = 'sqlite:'.$this->metaCache.DIRECTORY_SEPARATOR.'.elFinder_dropbox_db_'.md5($this->dropboxUid.$this->options['consumerSecret']);
+ }
+ // DataBase table name
+ $this->DB_TableName = $this->options['PDO_DBName'];
+ // DataBase check or make table
+ if ($this->DB = new PDO($this->options['PDO_DSN'], $this->options['PDO_User'], $this->options['PDO_Pass'], $this->options['PDO_Options'])) {
+ if (! $this->checkDB()) {
+ return $this->setError('Can not make DB table');
+ }
+ } else {
+ return $this->setError('Could not use PDO');
+ }
+
+ $res = $this->deltaCheck(!empty($_REQUEST['init']));
+ if ($res !== true) {
+ if (is_string($res)) {
+ return $this->setError($res);
+ } else {
+ return $this->setError('Could not check API "delta"');
+ }
+ }
+
+ return true;
+ }
+
+
+ /**
+ * Configure after successfull mount.
+ *
+ * @return void
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function configure() {
+ parent::configure();
+
+ if (!$this->tmp) {
+ $this->disabled[] = 'archive';
+ $this->disabled[] = 'extract';
+ }
+ }
+
+ /**
+ * Check DB for delta cache
+ *
+ * @return void
+ */
+ private function checkDB() {
+ $res = $this->query('select * from sqlite_master where type=\'table\' and name=\'dropbox\'; ');
+ if (! $res) {
+ try {
+ $this->DB->exec('create table '.$this->DB_TableName.'(path text, fname text, dat blob, isdir integer);');
+ $this->DB->exec('create index nameidx on '.$this->DB_TableName.'(path, fname)');
+ $this->DB->exec('create index isdiridx on '.$this->DB_TableName.'(isdir)');
+ } catch (PDOException $e) {
+ return $this->setError($e->getMessage());
+ }
+ }
+ return true;
+ }
+
+ /**
+ * DB query and fetchAll
+ *
+ * @param string $sql
+ * @return boolean|array
+ */
+ private function query($sql) {
+ if ($sth = $this->DB->query($sql)) {
+ $res = $sth->fetchAll(PDO::FETCH_COLUMN);
+ } else {
+ $res = false;
+ }
+ return $res;
+ }
+
+ /**
+ * Get dat(dropbox metadata) from DB
+ *
+ * @param string $path
+ * @return array dropbox metadata
+ */
+ private function getDBdat($path) {
+ if ($res = $this->query('select dat from '.$this->DB_TableName.' where path='.$this->DB->quote(strtolower(dirname($path))).' and fname='.$this->DB->quote(strtolower(basename($path))).' limit 1')) {
+ return unserialize($res[0]);
+ } else {
+ return array();
+ }
+ }
+
+ /**
+ * Update DB dat(dropbox metadata)
+ *
+ * @param string $path
+ * @param array $dat
+ * @return bool|array
+ */
+ private function updateDBdat($path, $dat) {
+ return $this->query('update '.$this->DB_TableName.' set dat='.$this->DB->quote(serialize($dat))
+ . ', isdir=' . ($dat['is_dir']? 1 : 0)
+ . ' where path='.$this->DB->quote(strtolower(dirname($path))).' and fname='.$this->DB->quote(strtolower(basename($path))));
+ }
+ /*********************************************************************/
+ /* FS API */
+ /*********************************************************************/
+
+ /**
+ * Close opened connection
+ *
+ * @return void
+ * @author Dmitry (dio) Levashov
+ **/
+ public function umount() {
+
+ }
+
+ /**
+ * Get local temp filename
+ *
+ * @return string | false
+ * @author Naoki Sawada
+ **/
+ protected function getLocalName($path) {
+ if ($this->tmp) {
+ return $this->tmp.DIRECTORY_SEPARATOR.md5($this->dropboxUid.$path);
+ }
+ return false;
+ }
+
+ /**
+ * Get delta data and DB update
+ *
+ * @param boolean $refresh force refresh
+ * @return true|string error message
+ */
+ protected function deltaCheck($refresh = true) {
+ $chk = false;
+ if (! $refresh && $chk = $this->query('select dat from '.$this->DB_TableName.' where path=\'\' and fname=\'\' limit 1')) {
+ $chk = unserialize($chk[0]);
+ }
+ if ($chk && ($chk['mtime'] + $this->options['metaCacheTime']) > $_SERVER['REQUEST_TIME']) {
+ return true;
+ }
+
+ try {
+ $more = true;
+ $this->DB->beginTransaction();
+
+ if ($res = $this->query('select dat from '.$this->DB_TableName.' where path=\'\' and fname=\'\' limit 1')) {
+ $res = unserialize($res[0]);
+ $cursor = $res['cursor'];
+ } else {
+ $cursor = '';
+ }
+ $delete = false;
+ $reset = false;
+ do {
+ @ ini_set('max_execution_time', 120);
+ $_info = $this->dropbox->delta($cursor);
+ if (! empty($_info['reset'])) {
+ $this->DB->exec('TRUNCATE table '.$this->DB_TableName);
+ $this->DB->exec('insert into '.$this->DB_TableName.' values(\'\', \'\', \''.serialize(array('cursor' => '', 'mtime' => 0)).'\', 0);');
+ $this->DB->exec('insert into '.$this->DB_TableName.' values(\'/\', \'\', \''.serialize(array(
+ 'path' => '/',
+ 'is_dir' => 1,
+ 'mime_type' => '',
+ 'bytes' => 0
+ )).'\', 0);');
+ $reset = true;
+ }
+ $cursor = $_info['cursor'];
+
+ foreach($_info['entries'] as $entry) {
+ $key = strtolower($entry[0]);
+ $pkey = strtolower(dirname($key));
+
+ $path = $this->DB->quote($pkey);
+ $fname = $this->DB->quote(strtolower(basename($key)));
+ $where = 'where path='.$path.' and fname='.$fname;
+
+ if (empty($entry[1])) {
+ $this->DB->exec('delete from '.$this->DB_TableName.' '.$where);
+ ! $delete && $delete = true;
+ continue;
+ }
+
+ $sql = 'select path from '.$this->DB_TableName.' '.$where.' limit 1';
+ if (! $reset && $this->query($sql)) {
+ $this->DB->exec('update '.$this->DB_TableName.' set dat='.$this->DB->quote(serialize($entry[1])).', isdir='.($entry[1]['is_dir']? 1 : 0).' ' .$where);
+ } else {
+ $this->DB->exec('insert into '.$this->DB_TableName.' values ('.$path.', '.$fname.', '.$this->DB->quote(serialize($entry[1])).', '.(int)$entry[1]['is_dir'].')');
+ }
+ }
+ } while (! empty($_info['has_more']));
+ $this->DB->exec('update '.$this->DB_TableName.' set dat='.$this->DB->quote(serialize(array('cursor'=>$cursor, 'mtime'=>$_SERVER['REQUEST_TIME']))).' where path=\'\' and fname=\'\'');
+ if (! $this->DB->commit()) {
+ $e = $this->DB->errorInfo();
+ return $e[2];
+ }
+ if ($delete) {
+ $this->DB->exec('vacuum');
+ }
+ } catch(Dropbox_Exception $e) {
+ return $e->getMessage();
+ }
+ return true;
+ }
+
+ /**
+ * Parse line from dropbox metadata output and return file stat (array)
+ *
+ * @param string $raw line from ftp_rawlist() output
+ * @return array
+ * @author Dmitry Levashov
+ **/
+ protected function parseRaw($raw) {
+ $stat = array();
+
+ $stat['rev'] = isset($raw['rev'])? $raw['rev'] : 'root';
+ $stat['name'] = basename($raw['path']);
+ $stat['mime'] = $raw['is_dir']? 'directory' : $raw['mime_type'];
+ $stat['size'] = $stat['mime'] == 'directory' ? 0 : $raw['bytes'];
+ $stat['ts'] = isset($raw['client_mtime'])? strtotime($raw['client_mtime']) :
+ (isset($raw['modified'])? strtotime($raw['modified']) : $_SERVER['REQUEST_TIME']);
+ $stat['dirs'] = 0;
+ if ($raw['is_dir']) {
+ $stat['dirs'] = (int)(bool)$this->query('select path from '.$this->DB_TableName.' where isdir=1 and path='.$this->DB->quote(strtolower($raw['path'])));
+ }
+
+ if (isset($raw['url'])) {
+ $stat['url'] = $raw['url'];
+ } else {
+ $stat['url'] = '1';
+ }
+ if (isset($raw['width'])) $stat['width'] = $raw['width'];
+ if (isset($raw['height'])) $stat['height'] = $raw['height'];
+
+ return $stat;
+ }
+
+ /**
+ * Cache dir contents
+ *
+ * @param string $path dir path
+ * @return void
+ * @author Dmitry Levashov
+ **/
+ protected function cacheDir($path) {
+ $this->dirsCache[$path] = array();
+ $res = $this->query('select dat from '.$this->DB_TableName.' where path='.$this->DB->quote(strtolower($path)));
+
+ if ($res) {
+ foreach($res as $raw) {
+ $raw = unserialize($raw);
+ if ($stat = $this->parseRaw($raw)) {
+ $stat = $this->updateCache($raw['path'], $stat);
+ if (empty($stat['hidden'])) {
+ $this->dirsCache[$path][] = $raw['path'];
+ }
+ }
+ }
+ }
+ return $this->dirsCache[$path];
+ }
+
+ /**
+ * Recursive files search
+ *
+ * @param string $path dir path
+ * @param string $q search string
+ * @param array $mimes
+ * @return array
+ * @author Naoki Sawada
+ **/
+ protected function doSearch($path, $q, $mimes) {
+
+ $result = array();
+
+ try {
+ if ($path === '/') $path = '';
+ $res = $this->dropbox->search($q, null, $path);
+ } catch (Dropbox_Exception $e) {
+ return $this->setError('Dropbox error: '.$e->getMessage());
+ }
+
+ if ($res) {
+ foreach($res as $raw) {
+ if ($stat = $this->parseRaw($raw)) {
+ if ($stat['mime'] === 'directory' || !$this->mimeAccepted($stat['mime'], $mimes)) {
+ continue;
+ }
+ $result[] = $this->stat($raw['path']);
+ }
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Copy file/recursive copy dir only in current volume.
+ * Return new file path or false.
+ *
+ * @param string $src source path
+ * @param string $dst destination dir path
+ * @param string $name new file name (optionaly)
+ * @return string|false
+ * @author Dmitry (dio) Levashov
+ * @author Naoki Sawada
+ **/
+ protected function copy($src, $dst, $name) {
+
+ $this->clearcache();
+
+ return $this->_copy($src, $dst, $name)
+ ? $this->_joinPath($dst, $name)
+ : $this->setError(elFinder::ERROR_COPY, $this->_path($src));
+ }
+
+ /**
+ * Remove file/ recursive remove dir
+ *
+ * @param string $path file path
+ * @param bool $force try to remove even if file locked
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ * @author Naoki Sawada
+ **/
+ protected function remove($path, $force = false, $recursive = false) {
+ $stat = $this->stat($path);
+ $stat['realpath'] = $path;
+ $this->rmTmb($stat);
+ $this->clearcache();
+
+ if (empty($stat)) {
+ return $this->setError(elFinder::ERROR_RM, $this->_path($path), elFinder::ERROR_FILE_NOT_FOUND);
+ }
+
+ if (!$force && !empty($stat['locked'])) {
+ return $this->setError(elFinder::ERROR_LOCKED, $this->_path($path));
+ }
+
+ if ($stat['mime'] == 'directory') {
+ if (!$recursive && !$this->_rmdir($path)) {
+ return $this->setError(elFinder::ERROR_RM, $this->_path($path));
+ }
+ } else {
+ if (!$recursive && !$this->_unlink($path)) {
+ return $this->setError(elFinder::ERROR_RM, $this->_path($path));
+ }
+ }
+
+ $this->removed[] = $stat;
+ return true;
+ }
+
+ /**
+ * Resize image
+ *
+ * @param string $hash image file
+ * @param int $width new width
+ * @param int $height new height
+ * @param int $x X start poistion for crop
+ * @param int $y Y start poistion for crop
+ * @param string $mode action how to mainpulate image
+ * @return array|false
+ * @author Dmitry (dio) Levashov
+ * @author Alexey Sukhotin
+ * @author nao-pon
+ * @author Troex Nevelin
+ **/
+ public function resize($hash, $width, $height, $x, $y, $mode = 'resize', $bg = '', $degree = 0) {
+ if ($this->commandDisabled('resize')) {
+ return $this->setError(elFinder::ERROR_PERM_DENIED);
+ }
+
+ if (($file = $this->file($hash)) == false) {
+ return $this->setError(elFinder::ERROR_FILE_NOT_FOUND);
+ }
+
+ if (!$file['write'] || !$file['read']) {
+ return $this->setError(elFinder::ERROR_PERM_DENIED);
+ }
+
+ $path = $this->decode($hash);
+
+ if (!$this->canResize($path, $file)) {
+ return $this->setError(elFinder::ERROR_UNSUPPORT_TYPE);
+ }
+
+ $path4stat = $path;
+ if (! $path = $this->getLocalName($path)) {
+ return false;
+ }
+
+ if (! $contents = $this->_getContents($path4stat)) {
+ return false;
+ }
+
+ if (! @ file_put_contents($path, $contents, LOCK_EX)) {
+ return false;
+ }
+
+ switch($mode) {
+
+ case 'propresize':
+ $result = $this->imgResize($path, $width, $height, true, true);
+ break;
+
+ case 'crop':
+ $result = $this->imgCrop($path, $width, $height, $x, $y);
+ break;
+
+ case 'fitsquare':
+ $result = $this->imgSquareFit($path, $width, $height, 'center', 'middle', ($bg ? $bg : $this->options['tmbBgColor']));
+ break;
+
+ case 'rotate':
+ $result = $this->imgRotate($path, $degree, ($bg ? $bg : $this->options['tmbBgColor']));
+ break;
+
+ default:
+ $result = $this->imgResize($path, $width, $height, false, true);
+ break;
+ }
+
+ $result && $size = getimagesize($path);
+
+ if ($result) {
+ clearstatcache();
+ $size = getimagesize($path);
+ if ($fp = @fopen($path, 'rb')) {
+ $res = $this->_save($fp, $path4stat, '', array());
+ @fclose($fp);
+
+ file_exists($path) && @unlink($path);
+
+ $this->rmTmb($file);
+ $this->clearcache();
+
+ if ($size) {
+ $raw = $this->getDBdat($path4stat);
+ $raw['width'] = $size[0];
+ $raw['height'] = $size[1];
+ $this->updateDBdat($path4stat, $raw);
+ }
+
+ return $this->stat($path4stat);
+ }
+ }
+
+ is_file($path) && @unlink($path);
+
+ return false;
+ }
+
+ /**
+ * Create thumnbnail and return it's URL on success
+ *
+ * @param string $path file path
+ * @param string $mime file mime type
+ * @return string|false
+ * @author Dmitry (dio) Levashov
+ * @author Naoki Sawada
+ **/
+ protected function createTmb($path, $stat) {
+ if (!$stat || !$this->canCreateTmb($path, $stat)) {
+ return false;
+ }
+
+ $name = $this->tmbname($stat);
+ $tmb = $this->tmbPath.DIRECTORY_SEPARATOR.$name;
+
+ // copy image into tmbPath so some drivers does not store files on local fs
+ if (! $data = $this->getThumbnail($path, $this->options['getTmbSize'])) {
+ return false;
+ }
+ if (! file_put_contents($tmb, $data)) {
+ return false;
+ }
+
+ $result = false;
+
+ $tmbSize = $this->tmbSize;
+
+ if (($s = getimagesize($tmb)) == false) {
+ return false;
+ }
+
+ /* If image smaller or equal thumbnail size - just fitting to thumbnail square */
+ if ($s[0] <= $tmbSize && $s[1] <= $tmbSize) {
+ $result = $this->imgSquareFit($tmb, $tmbSize, $tmbSize, 'center', 'middle', $this->options['tmbBgColor'], 'png' );
+
+ } else {
+
+ if ($this->options['tmbCrop']) {
+
+ /* Resize and crop if image bigger than thumbnail */
+ if (!(($s[0] > $tmbSize && $s[1] <= $tmbSize) || ($s[0] <= $tmbSize && $s[1] > $tmbSize) ) || ($s[0] > $tmbSize && $s[1] > $tmbSize)) {
+ $result = $this->imgResize($tmb, $tmbSize, $tmbSize, true, false, 'png');
+ }
+
+ if (($s = getimagesize($tmb)) != false) {
+ $x = $s[0] > $tmbSize ? intval(($s[0] - $tmbSize)/2) : 0;
+ $y = $s[1] > $tmbSize ? intval(($s[1] - $tmbSize)/2) : 0;
+ $result = $this->imgCrop($tmb, $tmbSize, $tmbSize, $x, $y, 'png');
+ }
+
+ } else {
+ $result = $this->imgResize($tmb, $tmbSize, $tmbSize, true, true, $this->imgLib, 'png');
+ $result = $this->imgSquareFit($tmb, $tmbSize, $tmbSize, 'center', 'middle', $this->options['tmbBgColor'], 'png' );
+ }
+
+ }
+ if (!$result) {
+ unlink($tmb);
+ return false;
+ }
+
+ return $name;
+ }
+
+ /**
+ * Return thumbnail file name for required file
+ *
+ * @param array $stat file stat
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function tmbname($stat) {
+ return $this->tmbPrefix.$stat['rev'].'.png';
+ }
+
+ /**
+ * Get thumbnail from dropbox.com
+ * @param string $path
+ * @param string $size
+ * @return string | boolean
+ */
+ protected function getThumbnail($path, $size = 'small') {
+ try {
+ return $this->dropbox->getThumbnail($path, $size);
+ } catch (Dropbox_Exception $e) {
+ return false;
+ }
+ }
+
+ /**
+ * Return content URL
+ *
+ * @param string $hash file hash
+ * @param array $options options
+ * @return array
+ * @author Naoki Sawada
+ **/
+ public function getContentUrl($hash, $options = array()) {
+ if (($file = $this->file($hash)) == false || !$file['url'] || $file['url'] == 1) {
+ $path = $this->decode($hash);
+ $cache = $this->getDBdat($path);
+ $url = '';
+ if (isset($cache['share'])) {
+ $res = $this->getHttpResponseHeader($cache['share']);
+ if (preg_match("/^HTTP\/[01\.]+ ([0-9]{3})/", $res, $match)) {
+ if (preg_match('/^location:\s*(http[^\s]+)/im', $res, $match)) {
+ $url = $match[1];
+ } else if ($match[1] >= 400) {
+ $url = '';
+ }
+ } else {
+ $url = '';
+ }
+ }
+ if (! $url) {
+ try {
+ $res = $this->dropbox->share($path);
+ $res = $this->getHttpResponseHeader($res['url']);
+ if (preg_match('/^location:\s*(http[^\s]+)/im', $res, $match)) {
+ $url = $match[1] . '?dl=1';
+ }
+ if ($url) {
+ if (! isset($cache['share']) || $cache['share'] !== $url) {
+ $cache['share'] = $url;
+ $this->updateDBdat($path, $cache);
+ }
+ $res = $this->getHttpResponseHeader($url);
+ if (preg_match('/^location:\s*(http[^\s?]+)/im', $res, $match)) {
+ $url = $match[1];
+ }
+ }
+ } catch (Dropbox_Exception $e) {
+ return false;
+ }
+ }
+ return $url;
+ }
+ return $file['url'];
+ }
+
+ /**
+ * Get HTTP request response header string
+ *
+ * @param string $url target URL
+ * @return string
+ * @author Naoki Sawada
+ */
+ private function getHttpResponseHeader($url) {
+ if (function_exists('curl_exec')) {
+
+ $c = curl_init();
+ curl_setopt( $c, CURLOPT_RETURNTRANSFER, true );
+ curl_setopt( $c, CURLOPT_CUSTOMREQUEST, 'HEAD' );
+ curl_setopt( $c, CURLOPT_HEADER, 1 );
+ curl_setopt( $c, CURLOPT_NOBODY, true );
+ curl_setopt( $c, CURLOPT_URL, $url );
+ $res = curl_exec( $c );
+
+ } else {
+
+ require_once 'HTTP/Request2.php';
+ try {
+ $request2 = new HTTP_Request2();
+ $request2->setConfig(array(
+ 'ssl_verify_peer' => false,
+ 'ssl_verify_host' => false
+ ));
+ $request2->setUrl($url);
+ $request2->setMethod(HTTP_Request2::METHOD_HEAD);
+ $result = $request2->send();
+ $res = array();
+ $res[] = 'HTTP/'.$result->getVersion().' '.$result->getStatus().' '.$result->getReasonPhrase();
+ foreach($result->getHeader() as $key => $val) {
+ $res[] = $key . ': ' . $val;
+ }
+ $res = join("\r\n", $res);
+ } catch( HTTP_Request2_Exception $e ){
+ $res = '';
+ } catch (Exception $e){
+ $res = '';
+ }
+
+ }
+ return $res;
+ }
+
+ /*********************** paths/urls *************************/
+
+ /**
+ * Return parent directory path
+ *
+ * @param string $path file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _dirname($path) {
+ return dirname($path);
+ }
+
+ /**
+ * Return file name
+ *
+ * @param string $path file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _basename($path) {
+ return basename($path);
+ }
+
+ /**
+ * Join dir name and file name and retur full path
+ *
+ * @param string $dir
+ * @param string $name
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _joinPath($dir, $name) {
+ return $this->_normpath($dir.'/'.$name);
+ }
+
+ /**
+ * Return normalized path, this works the same as os.path.normpath() in Python
+ *
+ * @param string $path path
+ * @return string
+ * @author Troex Nevelin
+ **/
+ protected function _normpath($path) {
+ $path = str_replace(DIRECTORY_SEPARATOR, '/', $path);
+ $path = '/' . ltrim($path, '/');
+ return $path;
+ }
+
+ /**
+ * Return file path related to root dir
+ *
+ * @param string $path file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _relpath($path) {
+ return $path;
+ }
+
+ /**
+ * Convert path related to root dir into real path
+ *
+ * @param string $path file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _abspath($path) {
+ return $path;
+ }
+
+ /**
+ * Return fake path started from root dir
+ *
+ * @param string $path file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _path($path) {
+ return $path;
+ }
+
+ /**
+ * Return true if $path is children of $parent
+ *
+ * @param string $path path to check
+ * @param string $parent parent path
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _inpath($path, $parent) {
+ return $path == $parent || strpos($path, $parent.'/') === 0;
+ }
+
+ /***************** file stat ********************/
+ /**
+ * Return stat for given path.
+ * Stat contains following fields:
+ * - (int) size file size in b. required
+ * - (int) ts file modification time in unix time. required
+ * - (string) mime mimetype. required for folders, others - optionally
+ * - (bool) read read permissions. required
+ * - (bool) write write permissions. required
+ * - (bool) locked is object locked. optionally
+ * - (bool) hidden is object hidden. optionally
+ * - (string) alias for symlinks - link target path relative to root path. optionally
+ * - (string) target for symlinks - link target path. optionally
+ *
+ * If file does not exists - returns empty array or false.
+ *
+ * @param string $path file path
+ * @return array|false
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _stat($path) {
+ if ($raw = $this->getDBdat($path)) {
+ return $this->parseRaw($raw);
+ }
+ return false;
+ }
+
+ /**
+ * Return true if path is dir and has at least one childs directory
+ *
+ * @param string $path dir path
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _subdirs($path) {
+ return ($stat = $this->stat($path)) && isset($stat['dirs']) ? $stat['dirs'] : false;
+ }
+
+ /**
+ * Return object width and height
+ * Ususaly used for images, but can be realize for video etc...
+ *
+ * @param string $path file path
+ * @param string $mime file mime type
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _dimensions($path, $mime) {
+ if (strpos($mime, 'image') !== 0) return '';
+ $cache = $this->getDBdat($path);
+ if (isset($cache['width']) && isset($cache['height'])) {
+ return $cache['width'].'x'.$cache['height'];
+ }
+ if ($local = $this->getLocalName($path)) {
+ if (file_put_contents($local, $this->dropbox->getFile($path), LOCK_EX)) {
+ if ($size = @getimagesize($local)) {
+ $cache['width'] = $size[0];
+ $cache['height'] = $size[1];
+ $this->updateDBdat($path, $cache);
+ unlink($local);
+ return $size[0].'x'.$size[1];
+ }
+ unlink($local);
+ }
+ }
+ return '';
+ }
+
+ /******************** file/dir content *********************/
+
+ /**
+ * Return files list in directory.
+ *
+ * @param string $path dir path
+ * @return array
+ * @author Dmitry (dio) Levashov
+ * @author Cem (DiscoFever)
+ **/
+ protected function _scandir($path) {
+ return isset($this->dirsCache[$path])
+ ? $this->dirsCache[$path]
+ : $this->cacheDir($path);
+ }
+
+ /**
+ * Open file and return file pointer
+ *
+ * @param string $path file path
+ * @param bool $write open file for writing
+ * @return resource|false
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _fopen($path, $mode='rb') {
+
+ if ($this->tmp) {
+ $contents = $this->_getContents($path);
+
+ if ($contents === false) {
+ return false;
+ }
+
+ if ($local = $this->getLocalName($path)) {
+ if (file_put_contents($local, $contents, LOCK_EX) !== false) {
+ return @fopen($local, $mode);
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Close opened file
+ *
+ * @param resource $fp file pointer
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _fclose($fp, $path='') {
+ @fclose($fp);
+ if ($path) {
+ @unlink($this->getLocalName($path));
+ }
+ }
+
+ /******************** file/dir manipulations *************************/
+
+ /**
+ * Create dir and return created dir path or false on failed
+ *
+ * @param string $path parent dir path
+ * @param string $name new directory name
+ * @return string|bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _mkdir($path, $name) {
+ $path = $this->_normpath($path.'/'.$name);
+ try {
+ $this->dropbox->createFolder($path);
+ } catch (Dropbox_Exception $e) {
+ return $this->setError('Dropbox error: '.$e->getMessage());
+ }
+ $this->deltaCheck();
+ return $path;
+ }
+
+ /**
+ * Create file and return it's path or false on failed
+ *
+ * @param string $path parent dir path
+ * @param string $name new file name
+ * @return string|bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _mkfile($path, $name) {
+ return $this->_filePutContents($path.'/'.$name, '');
+ }
+
+ /**
+ * Create symlink. FTP driver does not support symlinks.
+ *
+ * @param string $target link target
+ * @param string $path symlink path
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _symlink($target, $path, $name) {
+ return false;
+ }
+
+ /**
+ * Copy file into another file
+ *
+ * @param string $source source file path
+ * @param string $targetDir target directory path
+ * @param string $name new file name
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _copy($source, $targetDir, $name) {
+ $path = $this->_normpath($targetDir.'/'.$name);
+ try {
+ $this->dropbox->copy($source, $path);
+ } catch (Dropbox_Exception $e) {
+ return $this->setError('Dropbox error: '.$e->getMessage());
+ }
+ $this->deltaCheck();
+ return true;
+ }
+
+ /**
+ * Move file into another parent dir.
+ * Return new file path or false.
+ *
+ * @param string $source source file path
+ * @param string $target target dir path
+ * @param string $name file name
+ * @return string|bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _move($source, $targetDir, $name) {
+ $target = $this->_normpath($targetDir.'/'.$name);
+ try {
+ $this->dropbox->move($source, $target);
+ } catch (Dropbox_Exception $e) {
+ return $this->setError('Dropbox error: '.$e->getMessage());
+ }
+ $this->deltaCheck();
+ return $target;
+ }
+
+ /**
+ * Remove file
+ *
+ * @param string $path file path
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _unlink($path) {
+ try {
+ $this->dropbox->delete($path);
+ } catch (Dropbox_Exception $e) {
+ return $this->setError('Dropbox error: '.$e->getMessage());
+ }
+ $this->deltaCheck();
+ return true;
+ }
+
+ /**
+ * Remove dir
+ *
+ * @param string $path dir path
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _rmdir($path) {
+ return $this->_unlink($path);
+ }
+
+ /**
+ * Create new file and write into it from file pointer.
+ * Return new file path or false on error.
+ *
+ * @param resource $fp file pointer
+ * @param string $dir target dir path
+ * @param string $name file name
+ * @param array $stat file stat (required by some virtual fs)
+ * @return bool|string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _save($fp, $path, $name, $stat) {
+ if ($name) $path .= '/'.$name;
+ $path = $this->_normpath($path);
+ try {
+ $this->dropbox->putFile($path, $fp);
+ } catch (Dropbox_Exception $e) {
+ return $this->setError('Dropbox error: '.$e->getMessage());
+ }
+ $this->deltaCheck();
+ return $path;
+ }
+
+ /**
+ * Get file contents
+ *
+ * @param string $path file path
+ * @return string|false
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _getContents($path) {
+ $contents = '';
+ try {
+ $contents = $this->dropbox->getFile($path);
+ } catch (Dropbox_Exception $e) {
+ return $this->setError('Dropbox error: '.$e->getMessage());
+ }
+ return $contents;
+ }
+
+ /**
+ * Write a string to a file
+ *
+ * @param string $path file path
+ * @param string $content new file content
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _filePutContents($path, $content) {
+ $res = false;
+
+ if ($local = $this->getLocalName($path)) {
+ $local .= '.txt';
+
+ if (@file_put_contents($local, $content, LOCK_EX) !== false
+ && ($fp = @fopen($local, 'rb'))) {
+ clearstatcache();
+ $res = $this->_save($fp, $path, '', array());
+ @fclose($fp);
+ }
+ file_exists($local) && @unlink($local);
+ }
+
+ return $res;
+ }
+
+ /**
+ * Detect available archivers
+ *
+ * @return void
+ **/
+ protected function _checkArchivers() {
+ // die('Not yet implemented. (_checkArchivers)');
+ return array();
+ }
+
+ /**
+ * Unpack archive
+ *
+ * @param string $path archive path
+ * @param array $arc archiver command and arguments (same as in $this->archivers)
+ * @return true
+ * @return void
+ * @author Dmitry (dio) Levashov
+ * @author Alexey Sukhotin
+ **/
+ protected function _unpack($path, $arc) {
+ die('Not yet implemented. (_unpack)');
+ return false;
+ }
+
+ /**
+ * Recursive symlinks search
+ *
+ * @param string $path file/dir path
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _findSymlinks($path) {
+ die('Not yet implemented. (_findSymlinks)');
+ if (is_link($path)) {
+ return true;
+ }
+ if (is_dir($path)) {
+ foreach (scandir($path) as $name) {
+ if ($name != '.' && $name != '..') {
+ $p = $path.DIRECTORY_SEPARATOR.$name;
+ if (is_link($p)) {
+ return true;
+ }
+ if (is_dir($p) && $this->_findSymlinks($p)) {
+ return true;
+ } elseif (is_file($p)) {
+ $this->archiveSize += filesize($p);
+ }
+ }
+ }
+ } else {
+ $this->archiveSize += filesize($path);
+ }
+
+ return false;
+ }
+
+ /**
+ * Extract files from archive
+ *
+ * @param string $path archive path
+ * @param array $arc archiver command and arguments (same as in $this->archivers)
+ * @return true
+ * @author Dmitry (dio) Levashov,
+ * @author Alexey Sukhotin
+ **/
+ protected function _extract($path, $arc) {
+ die('Not yet implemented. (_extract)');
+
+ }
+
+ /**
+ * Create archive and return its path
+ *
+ * @param string $dir target dir
+ * @param array $files files names list
+ * @param string $name archive name
+ * @param array $arc archiver options
+ * @return string|bool
+ * @author Dmitry (dio) Levashov,
+ * @author Alexey Sukhotin
+ **/
+ protected function _archive($dir, $files, $name, $arc) {
+ die('Not yet implemented. (_archive)');
+ return false;
+ }
+
+} // END class
diff --git a/app/mihaildev/elfinder/php/elFinderVolumeFTP.class.php b/app/mihaildev/elfinder/php/elFinderVolumeFTP.class.php
new file mode 100755
index 0000000..892b651
--- /dev/null
+++ b/app/mihaildev/elfinder/php/elFinderVolumeFTP.class.php
@@ -0,0 +1,1402 @@
+ '0', 'r' => '4', 'w' => '2', 'x' => '1');
+ $chmod = substr(strtr($chmod, $trans), 1);
+ $array = str_split($chmod, 3);
+ return array_sum(str_split($array[0])) . array_sum(str_split($array[1])) . array_sum(str_split($array[2]));
+}
+
+elFinder::$netDrivers['ftp'] = 'FTP';
+
+/**
+ * Simple elFinder driver for FTP
+ *
+ * @author Dmitry (dio) Levashov
+ * @author Cem (discofever)
+ **/
+class elFinderVolumeFTP extends elFinderVolumeDriver {
+
+ /**
+ * Driver id
+ * Must be started from letter and contains [a-z0-9]
+ * Used as part of volume id
+ *
+ * @var string
+ **/
+ protected $driverId = 'f';
+
+ /**
+ * FTP Connection Instance
+ *
+ * @var ftp
+ **/
+ protected $connect = null;
+
+ /**
+ * Directory for tmp files
+ * If not set driver will try to use tmbDir as tmpDir
+ *
+ * @var string
+ **/
+ protected $tmpPath = '';
+
+ /**
+ * Last FTP error message
+ *
+ * @var string
+ **/
+ protected $ftpError = '';
+
+ /**
+ * FTP server output list as ftp on linux
+ *
+ * @var bool
+ **/
+ protected $ftpOsUnix;
+
+ /**
+ * Tmp folder path
+ *
+ * @var string
+ **/
+ protected $tmp = '';
+
+ /**
+ * Constructor
+ * Extend options with required fields
+ *
+ * @return void
+ * @author Dmitry (dio) Levashov
+ * @author Cem (DiscoFever)
+ **/
+ public function __construct() {
+ $opts = array(
+ 'host' => 'localhost',
+ 'user' => '',
+ 'pass' => '',
+ 'port' => 21,
+ 'mode' => 'passive',
+ 'path' => '/',
+ 'timeout' => 20,
+ 'owner' => true,
+ 'tmbPath' => '',
+ 'tmpPath' => '',
+ 'dirMode' => 0755,
+ 'fileMode' => 0644
+ );
+ $this->options = array_merge($this->options, $opts);
+ $this->options['mimeDetect'] = 'internal';
+ }
+
+ /*********************************************************************/
+ /* INIT AND CONFIGURE */
+ /*********************************************************************/
+
+ /**
+ * Prepare FTP connection
+ * Connect to remote server and check if credentials are correct, if so, store the connection id in $ftp_conn
+ *
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ * @author Cem (DiscoFever)
+ **/
+ protected function init() {
+ if (!$this->options['host']
+ || !$this->options['user']
+ || !$this->options['pass']
+ || !$this->options['port']) {
+ return $this->setError('Required options undefined.');
+ }
+
+ if (!function_exists('ftp_connect')) {
+ return $this->setError('FTP extension not loaded.');
+ }
+
+ // remove protocol from host
+ $scheme = parse_url($this->options['host'], PHP_URL_SCHEME);
+
+ if ($scheme) {
+ $this->options['host'] = substr($this->options['host'], strlen($scheme)+3);
+ }
+
+ // normalize root path
+ $this->root = $this->options['path'] = $this->_normpath($this->options['path']);
+
+ if (empty($this->options['alias'])) {
+ $this->options['alias'] = $this->options['user'].'@'.$this->options['host'];
+ // $num = elFinder::$volumesCnt-1;
+ // $this->options['alias'] = $this->root == '/' || $this->root == '.' ? 'FTP folder '.$num : basename($this->root);
+ }
+
+ $this->rootName = $this->options['alias'];
+ $this->options['separator'] = '/';
+
+ return $this->connect();
+
+ }
+
+
+ /**
+ * Configure after successfull mount.
+ *
+ * @return void
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function configure() {
+ parent::configure();
+
+ if (!empty($this->options['tmpPath'])) {
+ if ((is_dir($this->options['tmpPath']) || @mkdir($this->options['tmpPath'], 0755, true)) && is_writable($this->options['tmpPath'])) {
+ $this->tmp = $this->options['tmpPath'];
+ }
+ }
+
+ if (!$this->tmp && $this->tmbPath) {
+ $this->tmp = $this->tmbPath;
+ }
+
+ if (!$this->tmp) {
+ $this->disabled[] = 'mkfile';
+ $this->disabled[] = 'paste';
+ $this->disabled[] = 'duplicate';
+ $this->disabled[] = 'upload';
+ $this->disabled[] = 'edit';
+ $this->disabled[] = 'archive';
+ $this->disabled[] = 'extract';
+ }
+
+ // echo $this->tmp;
+
+ }
+
+ /**
+ * Connect to ftp server
+ *
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function connect() {
+ if (!($this->connect = ftp_connect($this->options['host'], $this->options['port'], $this->options['timeout']))) {
+ return $this->setError('Unable to connect to FTP server '.$this->options['host']);
+ }
+ if (!ftp_login($this->connect, $this->options['user'], $this->options['pass'])) {
+ $this->umount();
+ return $this->setError('Unable to login into '.$this->options['host']);
+ }
+
+ // switch off extended passive mode - may be usefull for some servers
+ @ftp_exec($this->connect, 'epsv4 off' );
+ // enter passive mode if required
+ ftp_pasv($this->connect, $this->options['mode'] == 'passive');
+
+ // enter root folder
+ if (!ftp_chdir($this->connect, $this->root)
+ || $this->root != ftp_pwd($this->connect)) {
+ $this->umount();
+ return $this->setError('Unable to open root folder.');
+ }
+
+ // check for MLST support
+ $features = ftp_raw($this->connect, 'FEAT');
+ if (!is_array($features)) {
+ $this->umount();
+ return $this->setError('Server does not support command FEAT.');
+ }
+
+ foreach ($features as $feat) {
+ if (strpos(trim($feat), 'MLST') === 0) {
+ return true;
+ }
+ }
+
+ return $this->setError('Server does not support command MLST.');
+ }
+
+ /*********************************************************************/
+ /* FS API */
+ /*********************************************************************/
+
+ /**
+ * Close opened connection
+ *
+ * @return void
+ * @author Dmitry (dio) Levashov
+ **/
+ public function umount() {
+ $this->connect && @ftp_close($this->connect);
+ }
+
+
+ /**
+ * Parse line from ftp_rawlist() output and return file stat (array)
+ *
+ * @param string $raw line from ftp_rawlist() output
+ * @return array
+ * @author Dmitry Levashov
+ **/
+ protected function parseRaw($raw) {
+ $info = preg_split("/\s+/", $raw, 9);
+ $stat = array();
+
+ if (count($info) < 9 || $info[8] == '.' || $info[8] == '..') {
+ return false;
+ }
+
+ if (!isset($this->ftpOsUnix)) {
+ $this->ftpOsUnix = !preg_match('/\d/', substr($info[0], 0, 1));
+ }
+
+ if ($this->ftpOsUnix) {
+
+ $stat['ts'] = strtotime($info[5].' '.$info[6].' '.$info[7]);
+ if (empty($stat['ts'])) {
+ $stat['ts'] = strtotime($info[6].' '.$info[5].' '.$info[7]);
+ }
+
+ $name = $info[8];
+
+ if (preg_match('|(.+)\-\>(.+)|', $name, $m)) {
+ $name = trim($m[1]);
+ $target = trim($m[2]);
+ if (substr($target, 0, 1) != '/') {
+ $target = $this->root.'/'.$target;
+ }
+ $target = $this->_normpath($target);
+ $stat['name'] = $name;
+ if ($this->_inpath($target, $this->root)
+ && ($tstat = $this->stat($target))) {
+ $stat['size'] = $tstat['mime'] == 'directory' ? 0 : $info[4];
+ $stat['alias'] = $this->_relpath($target);
+ $stat['thash'] = $tstat['hash'];
+ $stat['mime'] = $tstat['mime'];
+ $stat['read'] = $tstat['read'];
+ $stat['write'] = $tstat['write'];
+ } else {
+
+ $stat['mime'] = 'symlink-broken';
+ $stat['read'] = false;
+ $stat['write'] = false;
+ $stat['size'] = 0;
+
+ }
+ return $stat;
+ }
+
+ $perm = $this->parsePermissions($info[0]);
+ $stat['name'] = $name;
+ $stat['mime'] = substr(strtolower($info[0]), 0, 1) == 'd' ? 'directory' : $this->mimetype($stat['name']);
+ $stat['size'] = $stat['mime'] == 'directory' ? 0 : $info[4];
+ $stat['read'] = $perm['read'];
+ $stat['write'] = $perm['write'];
+ $stat['perm'] = substr($info[0], 1);
+ } else {
+ die('Windows ftp servers not supported yet');
+ }
+
+ return $stat;
+ }
+
+ /**
+ * Parse permissions string. Return array(read => true/false, write => true/false)
+ *
+ * @param string $perm permissions string
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function parsePermissions($perm) {
+ $res = array();
+ $parts = array();
+ $owner = $this->options['owner'];
+ for ($i = 0, $l = strlen($perm); $i < $l; $i++) {
+ $parts[] = substr($perm, $i, 1);
+ }
+
+ $read = ($owner && $parts[0] == 'r') || $parts[4] == 'r' || $parts[7] == 'r';
+
+ return array(
+ 'read' => $parts[0] == 'd' ? $read && (($owner && $parts[3] == 'x') || $parts[6] == 'x' || $parts[9] == 'x') : $read,
+ 'write' => ($owner && $parts[2] == 'w') || $parts[5] == 'w' || $parts[8] == 'w'
+ );
+ }
+
+ /**
+ * Cache dir contents
+ *
+ * @param string $path dir path
+ * @return void
+ * @author Dmitry Levashov
+ **/
+ protected function cacheDir($path) {
+ $this->dirsCache[$path] = array();
+
+ if (preg_match('/\'|\"/', $path)) {
+ foreach (ftp_nlist($this->connect, $path) as $p) {
+ if (($stat = $this->_stat($p)) &&empty($stat['hidden'])) {
+ // $files[] = $stat;
+ $this->dirsCache[$path][] = $p;
+ }
+ }
+ return;
+ }
+ foreach (ftp_rawlist($this->connect, $path) as $raw) {
+ if (($stat = $this->parseRaw($raw))) {
+ $p = $path.'/'.$stat['name'];
+ $stat = $this->updateCache($p, $stat);
+ if (empty($stat['hidden'])) {
+ // $files[] = $stat;
+ $this->dirsCache[$path][] = $p;
+ }
+ }
+ }
+ }
+
+ /**
+ * Return ftp transfer mode for file
+ *
+ * @param string $path file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function ftpMode($path) {
+ return strpos($this->mimetype($path), 'text/') === 0 ? FTP_ASCII : FTP_BINARY;
+ }
+
+ /*********************** paths/urls *************************/
+
+ /**
+ * Return parent directory path
+ *
+ * @param string $path file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _dirname($path) {
+ return dirname($path);
+ }
+
+ /**
+ * Return file name
+ *
+ * @param string $path file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _basename($path) {
+ return basename($path);
+ }
+
+ /**
+ * Join dir name and file name and retur full path
+ *
+ * @param string $dir
+ * @param string $name
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _joinPath($dir, $name) {
+ return $dir.DIRECTORY_SEPARATOR.$name;
+ }
+
+ /**
+ * Return normalized path, this works the same as os.path.normpath() in Python
+ *
+ * @param string $path path
+ * @return string
+ * @author Troex Nevelin
+ **/
+ protected function _normpath($path) {
+ if (empty($path)) {
+ $path = '.';
+ }
+ // path must be start with /
+ $path = preg_replace('|^\.\/?|', '/', $path);
+ $path = preg_replace('/^([^\/])/', "/$1", $path);
+
+ if (strpos($path, '/') === 0) {
+ $initial_slashes = true;
+ } else {
+ $initial_slashes = false;
+ }
+
+ if (($initial_slashes)
+ && (strpos($path, '//') === 0)
+ && (strpos($path, '///') === false)) {
+ $initial_slashes = 2;
+ }
+
+ $initial_slashes = (int) $initial_slashes;
+
+ $comps = explode('/', $path);
+ $new_comps = array();
+ foreach ($comps as $comp) {
+ if (in_array($comp, array('', '.'))) {
+ continue;
+ }
+
+ if (($comp != '..')
+ || (!$initial_slashes && !$new_comps)
+ || ($new_comps && (end($new_comps) == '..'))) {
+ array_push($new_comps, $comp);
+ } elseif ($new_comps) {
+ array_pop($new_comps);
+ }
+ }
+ $comps = $new_comps;
+ $path = implode('/', $comps);
+ if ($initial_slashes) {
+ $path = str_repeat('/', $initial_slashes) . $path;
+ }
+
+ return $path ? $path : '.';
+ }
+
+ /**
+ * Return file path related to root dir
+ *
+ * @param string $path file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _relpath($path) {
+ return $path == $this->root ? '' : substr($path, strlen($this->root)+1);
+ }
+
+ /**
+ * Convert path related to root dir into real path
+ *
+ * @param string $path file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _abspath($path) {
+ return $path == $this->separator ? $this->root : $this->root.$this->separator.$path;
+ }
+
+ /**
+ * Return fake path started from root dir
+ *
+ * @param string $path file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _path($path) {
+ return $this->rootName.($path == $this->root ? '' : $this->separator.$this->_relpath($path));
+ }
+
+ /**
+ * Return true if $path is children of $parent
+ *
+ * @param string $path path to check
+ * @param string $parent parent path
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _inpath($path, $parent) {
+ return $path == $parent || strpos($path, $parent.'/') === 0;
+ }
+
+ /***************** file stat ********************/
+ /**
+ * Return stat for given path.
+ * Stat contains following fields:
+ * - (int) size file size in b. required
+ * - (int) ts file modification time in unix time. required
+ * - (string) mime mimetype. required for folders, others - optionally
+ * - (bool) read read permissions. required
+ * - (bool) write write permissions. required
+ * - (bool) locked is object locked. optionally
+ * - (bool) hidden is object hidden. optionally
+ * - (string) alias for symlinks - link target path relative to root path. optionally
+ * - (string) target for symlinks - link target path. optionally
+ *
+ * If file does not exists - returns empty array or false.
+ *
+ * @param string $path file path
+ * @return array|false
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _stat($path) {
+ $raw = ftp_raw($this->connect, 'MLST '.$path);
+
+ if (is_array($raw) && count($raw) > 1 && substr(trim($raw[0]), 0, 1) == 2) {
+ $parts = explode(';', trim($raw[1]));
+ array_pop($parts);
+ $parts = array_map('strtolower', $parts);
+ $stat = array();
+ // debug($parts);
+ foreach ($parts as $part) {
+
+ list($key, $val) = explode('=', $part);
+
+ switch ($key) {
+ case 'type':
+ $stat['mime'] = strpos($val, 'dir') !== false ? 'directory' : $this->mimetype($path);
+ break;
+
+ case 'size':
+ $stat['size'] = $val;
+ break;
+
+ case 'modify':
+ $ts = mktime(intval(substr($val, 8, 2)), intval(substr($val, 10, 2)), intval(substr($val, 12, 2)), intval(substr($val, 4, 2)), intval(substr($val, 6, 2)), substr($val, 0, 4));
+ $stat['ts'] = $ts;
+ // $stat['date'] = $this->formatDate($ts);
+ break;
+
+ case 'unix.mode':
+ $stat['chmod'] = $val;
+ break;
+
+ case 'perm':
+ $val = strtolower($val);
+ $stat['read'] = (int)preg_match('/e|l|r/', $val);
+ $stat['write'] = (int)preg_match('/w|m|c/', $val);
+ if (!preg_match('/f|d/', $val)) {
+ $stat['locked'] = 1;
+ }
+ break;
+ }
+ }
+ if (empty($stat['mime'])) {
+ return array();
+ }
+ if ($stat['mime'] == 'directory') {
+ $stat['size'] = 0;
+ }
+
+ if (isset($stat['chmod'])) {
+ $stat['perm'] = '';
+ if ($stat['chmod'][0] == 0) {
+ $stat['chmod'] = substr($stat['chmod'], 1);
+ }
+
+ for ($i = 0; $i <= 2; $i++) {
+ $perm[$i] = array(false, false, false);
+ $n = isset($stat['chmod'][$i]) ? $stat['chmod'][$i] : 0;
+
+ if ($n - 4 >= 0) {
+ $perm[$i][0] = true;
+ $n = $n - 4;
+ $stat['perm'] .= 'r';
+ } else {
+ $stat['perm'] .= '-';
+ }
+
+ if ($n - 2 >= 0) {
+ $perm[$i][1] = true;
+ $n = $n - 2;
+ $stat['perm'] .= 'w';
+ } else {
+ $stat['perm'] .= '-';
+ }
+
+ if ($n - 1 == 0) {
+ $perm[$i][2] = true;
+ $stat['perm'] .= 'x';
+ } else {
+ $stat['perm'] .= '-';
+ }
+
+ $stat['perm'] .= ' ';
+ }
+
+ $stat['perm'] = trim($stat['perm']);
+
+ $owner = $this->options['owner'];
+ $read = ($owner && $perm[0][0]) || $perm[1][0] || $perm[2][0];
+
+ $stat['read'] = $stat['mime'] == 'directory' ? $read && (($owner && $perm[0][2]) || $perm[1][2] || $perm[2][2]) : $read;
+ $stat['write'] = ($owner && $perm[0][1]) || $perm[1][1] || $perm[2][1];
+ unset($stat['chmod']);
+
+ }
+
+ return $stat;
+
+ }
+
+ return array();
+ }
+
+ /**
+ * Return true if path is dir and has at least one childs directory
+ *
+ * @param string $path dir path
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _subdirs($path) {
+
+ if (preg_match('/\s|\'|\"/', $path)) {
+ foreach (ftp_nlist($this->connect, $path) as $p) {
+ if (($stat = $this->stat($path.'/'.$p)) && $stat['mime'] == 'directory') {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ foreach (ftp_rawlist($this->connect, $path) as $str) {
+ if (($stat = $this->parseRaw($str)) && $stat['mime'] == 'directory') {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Return object width and height
+ * Ususaly used for images, but can be realize for video etc...
+ *
+ * @param string $path file path
+ * @param string $mime file mime type
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _dimensions($path, $mime) {
+ return false;
+ }
+
+ /******************** file/dir content *********************/
+
+ /**
+ * Return files list in directory.
+ *
+ * @param string $path dir path
+ * @return array
+ * @author Dmitry (dio) Levashov
+ * @author Cem (DiscoFever)
+ **/
+ protected function _scandir($path) {
+ $files = array();
+
+ foreach (ftp_rawlist($this->connect, $path) as $str) {
+ if (($stat = $this->parseRaw($str))) {
+ $files[] = $path.DIRECTORY_SEPARATOR.$stat['name'];
+ }
+ }
+
+ return $files;
+ }
+
+ /**
+ * Open file and return file pointer
+ *
+ * @param string $path file path
+ * @param bool $write open file for writing
+ * @return resource|false
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _fopen($path, $mode='rb') {
+
+ if ($this->tmp) {
+ $local = $this->tmp.DIRECTORY_SEPARATOR.md5($path);
+
+ if (ftp_get($this->connect, $local, $path, FTP_BINARY)) {
+ return @fopen($local, $mode);
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Close opened file
+ *
+ * @param resource $fp file pointer
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _fclose($fp, $path='') {
+ @fclose($fp);
+ if ($path) {
+ @unlink($this->tmp.DIRECTORY_SEPARATOR.md5($path));
+ }
+ }
+
+ /******************** file/dir manipulations *************************/
+
+ /**
+ * Create dir and return created dir path or false on failed
+ *
+ * @param string $path parent dir path
+ * @param string $name new directory name
+ * @return string|bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _mkdir($path, $name) {
+ $path = $path.'/'.$name;
+ if (ftp_mkdir($this->connect, $path) === false) {
+ return false;
+ }
+
+ $this->options['dirMode'] && @ftp_chmod($this->connect, $this->options['dirMode'], $path);
+ return $path;
+ }
+
+ /**
+ * Create file and return it's path or false on failed
+ *
+ * @param string $path parent dir path
+ * @param string $name new file name
+ * @return string|bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _mkfile($path, $name) {
+ if ($this->tmp) {
+ $path = $path.'/'.$name;
+ $local = $this->tmp.DIRECTORY_SEPARATOR.md5($path);
+ $res = touch($local) && ftp_put($this->connect, $path, $local, FTP_ASCII);
+ @unlink($local);
+ return $res ? $path : false;
+ }
+ return false;
+ }
+
+ /**
+ * Create symlink. FTP driver does not support symlinks.
+ *
+ * @param string $target link target
+ * @param string $path symlink path
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _symlink($target, $path, $name) {
+ return false;
+ }
+
+ /**
+ * Copy file into another file
+ *
+ * @param string $source source file path
+ * @param string $targetDir target directory path
+ * @param string $name new file name
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _copy($source, $targetDir, $name) {
+ $res = false;
+
+ if ($this->tmp) {
+ $local = $this->tmp.DIRECTORY_SEPARATOR.md5($source);
+ $target = $targetDir.DIRECTORY_SEPARATOR.$name;
+
+ if (ftp_get($this->connect, $local, $source, FTP_BINARY)
+ && ftp_put($this->connect, $target, $local, $this->ftpMode($target))) {
+ $res = $target;
+ }
+ @unlink($local);
+ }
+
+ return $res;
+ }
+
+ /**
+ * Move file into another parent dir.
+ * Return new file path or false.
+ *
+ * @param string $source source file path
+ * @param string $target target dir path
+ * @param string $name file name
+ * @return string|bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _move($source, $targetDir, $name) {
+ $target = $targetDir.DIRECTORY_SEPARATOR.$name;
+ return ftp_rename($this->connect, $source, $target) ? $target : false;
+ }
+
+ /**
+ * Remove file
+ *
+ * @param string $path file path
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _unlink($path) {
+ return ftp_delete($this->connect, $path);
+ }
+
+ /**
+ * Remove dir
+ *
+ * @param string $path dir path
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _rmdir($path) {
+ return ftp_rmdir($this->connect, $path);
+ }
+
+ /**
+ * Create new file and write into it from file pointer.
+ * Return new file path or false on error.
+ *
+ * @param resource $fp file pointer
+ * @param string $dir target dir path
+ * @param string $name file name
+ * @param array $stat file stat (required by some virtual fs)
+ * @return bool|string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _save($fp, $dir, $name, $stat) {
+ $path = $dir.'/'.$name;
+ return ftp_fput($this->connect, $path, $fp, $this->ftpMode($path))
+ ? $path
+ : false;
+ }
+
+ /**
+ * Get file contents
+ *
+ * @param string $path file path
+ * @return string|false
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _getContents($path) {
+ $contents = '';
+ if (($fp = $this->_fopen($path))) {
+ while (!feof($fp)) {
+ $contents .= fread($fp, 8192);
+ }
+ $this->_fclose($fp, $path);
+ return $contents;
+ }
+ return false;
+ }
+
+ /**
+ * Write a string to a file
+ *
+ * @param string $path file path
+ * @param string $content new file content
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _filePutContents($path, $content) {
+ $res = false;
+
+ if ($this->tmp) {
+ $local = $this->tmp.DIRECTORY_SEPARATOR.md5($path).'.txt';
+
+ if (@file_put_contents($local, $content, LOCK_EX) !== false
+ && ($fp = @fopen($local, 'rb'))) {
+ clearstatcache();
+ $res = ftp_fput($this->connect, $path, $fp, $this->ftpMode($path));
+ @fclose($fp);
+ }
+ file_exists($local) && @unlink($local);
+ }
+
+ return $res;
+ }
+
+ /**
+ * Detect available archivers
+ *
+ * @return void
+ **/
+ protected function _checkArchivers() {
+ // die('Not yet implemented. (_checkArchivers)');
+ return array();
+ }
+
+ /**
+ * Unpack archive
+ *
+ * @param string $path archive path
+ * @param array $arc archiver command and arguments (same as in $this->archivers)
+ * @return true
+ * @return void
+ * @author Dmitry (dio) Levashov
+ * @author Alexey Sukhotin
+ **/
+ protected function _unpack($path, $arc) {
+ die('Not yet implemented. (_unpack)');
+ return false;
+ }
+
+ /**
+ * Recursive symlinks search
+ *
+ * @param string $path file/dir path
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _findSymlinks($path) {
+ die('Not yet implemented. (_findSymlinks)');
+ if (is_link($path)) {
+ return true;
+ }
+ if (is_dir($path)) {
+ foreach (scandir($path) as $name) {
+ if ($name != '.' && $name != '..') {
+ $p = $path.DIRECTORY_SEPARATOR.$name;
+ if (is_link($p)) {
+ return true;
+ }
+ if (is_dir($p) && $this->_findSymlinks($p)) {
+ return true;
+ } elseif (is_file($p)) {
+ $this->archiveSize += filesize($p);
+ }
+ }
+ }
+ } else {
+ $this->archiveSize += filesize($path);
+ }
+
+ return false;
+ }
+
+ /**
+ * Extract files from archive
+ *
+ * @param string $path archive path
+ * @param array $arc archiver command and arguments (same as in $this->archivers)
+ * @return true
+ * @author Dmitry (dio) Levashov,
+ * @author Alexey Sukhotin
+ **/
+ protected function _extract($path, $arc)
+ {
+ // get current directory
+ $cwd = getcwd();
+
+ $tmpDir = $this->tempDir();
+ if (!$tmpDir) {
+ return false;
+ }
+
+ $basename = $this->_basename($path);
+ $localPath = $tmpDir . DIRECTORY_SEPARATOR . $basename;
+
+ if (!ftp_get($this->connect, $localPath, $path, FTP_BINARY)) {
+ //cleanup
+ $this->deleteDir($tmpDir);
+ return false;
+ }
+
+ $remoteDirectory = dirname($path);
+ chdir($tmpDir);
+ $command = escapeshellcmd($arc['cmd'] . ' ' . $arc['argc'] . ' "' . $basename . '"');
+ exec($command, $output, $return_value);
+ unlink($basename);
+ if ($return_value != 0) {
+ $this->setError(elFinder::ERROR_EXTRACT_EXEC, 'Command failed '.escapeshellarg($command));
+ $this->deleteDir($tmpDir); //cleanup
+ return false;
+ }
+
+ $filesToProcess = elFinderVolumeFTP::listFilesInDirectory($tmpDir, true);
+ if(!$filesToProcess) {
+ $this->setError(elFinder::ERROR_EXTRACT_EXEC, $tmpDir." is not a directory");
+ $this->deleteDir($tmpDir); //cleanup
+ return false;
+ }
+ if (count($filesToProcess) > 1) {
+
+ // for several files - create new directory
+ // create unique name for directory
+ $name = basename($path);
+ if (preg_match('/\.((tar\.(gz|bz|bz2|z|lzo))|cpio\.gz|ps\.gz|xcf\.(gz|bz2)|[a-z0-9]{1,4})$/i', $name, $m)) {
+ $name = substr($name, 0, strlen($name) - strlen($m[0]));
+ }
+
+ $test = dirname($path) . DIRECTORY_SEPARATOR . $name;
+ if ($this->stat($test)) {
+ $name = $this->uniqueName(dirname($path), $name, '-', false);
+ }
+
+ $newPath = dirname($path) . DIRECTORY_SEPARATOR . $name;
+
+ $success = $this->_mkdir(dirname($path), $name);
+ foreach ($filesToProcess as $filename) {
+ if (!$success) {
+ break;
+ }
+ $targetPath = $newPath . DIRECTORY_SEPARATOR . $filename;
+ if (is_dir($filename)) {
+ $success = $this->_mkdir($newPath, $filename);
+ } else {
+ $success = ftp_put($this->connect, $targetPath, $filename, FTP_BINARY);
+ }
+ }
+ unset($filename);
+
+ } else {
+ $filename = $filesToProcess[0];
+ $newPath = $remoteDirectory . DIRECTORY_SEPARATOR . $filename;
+ $success = ftp_put($this->connect, $newPath, $filename, FTP_BINARY);
+ }
+
+ // return to initial directory
+ chdir($cwd);
+
+ //cleanup
+ if(!$this->deleteDir($tmpDir)) {
+ return false;
+ }
+
+ if (!$success) {
+ $this->setError(elFinder::ERROR_FTP_UPLOAD_FILE, $newPath);
+ return false;
+ }
+ $this->clearcache();
+ return $newPath;
+ }
+
+ /**
+ * Create archive and return its path
+ *
+ * @param string $dir target dir
+ * @param array $files files names list
+ * @param string $name archive name
+ * @param array $arc archiver options
+ * @return string|bool
+ * @author Dmitry (dio) Levashov,
+ * @author Alexey Sukhotin
+ **/
+ protected function _archive($dir, $files, $name, $arc)
+ {
+ // get current directory
+ $cwd = getcwd();
+
+ $tmpDir = $this->tempDir();
+ if (!$tmpDir) {
+ return false;
+ }
+
+ //download data
+ if (!$this->ftp_download_files($dir, $files, $tmpDir)) {
+ //cleanup
+ $this->deleteDir($tmpDir);
+ return false;
+ }
+
+ // go to the temporary directory
+ chdir($tmpDir);
+
+ // path to local copy of archive
+ $path = $tmpDir . DIRECTORY_SEPARATOR . $name;
+
+ $file_names_string = "";
+ foreach (scandir($tmpDir) as $filename) {
+ if ('.' == $filename) {
+ continue;
+ }
+ if ('..' == $filename) {
+ continue;
+ }
+ $file_names_string = $file_names_string . '"' . $filename . '" ';
+ }
+ $command = escapeshellcmd($arc['cmd'] . ' ' . $arc['argc'] . ' "' . $name . '" ' . $file_names_string);
+
+ exec($command, $output, $return_value);
+ if ($return_value != 0) {
+ $this->setError(elFinder::ERROR_ARCHIVE_EXEC, 'Command failed '.escapeshellarg($command));
+ $this->deleteDir($tmpDir); //cleanup
+ return false;
+ }
+
+ $remoteArchiveFile = $dir . DIRECTORY_SEPARATOR . $name;
+
+ // upload archive
+ if (!ftp_put($this->connect, $remoteArchiveFile, $path, FTP_BINARY)) {
+ $this->setError(elFinder::ERROR_FTP_UPLOAD_FILE, $remoteArchiveFile);
+ $this->deleteDir($tmpDir); //cleanup
+ return false;
+ }
+
+ // return to initial work directory
+ chdir($cwd);
+
+ //cleanup
+ if(!$this->deleteDir($tmpDir)) {
+ return false;
+ }
+
+ return $remoteArchiveFile;
+ }
+
+ /**
+ * Create writable temporary directory and return path to it.
+ * @return string path to the new temporary directory or false in case of error.
+ */
+ private function tempDir()
+ {
+ $tempPath = tempnam($this->tmp, 'elFinder');
+ if (!$tempPath) {
+ $this->setError(elFinder::ERROR_CREATING_TEMP_DIR, $this->tmp);
+ return false;
+ }
+ $success = unlink($tempPath);
+ if (!$success) {
+ $this->setError(elFinder::ERROR_CREATING_TEMP_DIR, $this->tmp);
+ return false;
+ }
+ $success = mkdir($tempPath, 0755, true);
+ if (!$success) {
+ $this->setError(elFinder::ERROR_CREATING_TEMP_DIR, $this->tmp);
+ return false;
+ }
+ return $tempPath;
+ }
+
+ /**
+ * Gets in a single FTP request an array of absolute remote FTP paths of files and
+ * folders in $remote_directory omitting symbolic links.
+ * @param $remote_directory string remote FTP path to scan for file and folders recursively
+ * @return array of elements each of which is an array of two elements:
+ *
+ * $item['path'] - absolute remote FTP path
+ * $item['type'] - either 'f' for file or 'd' for directory
+ *
+ */
+ private function ftp_scan_dir($remote_directory)
+ {
+ $buff = ftp_rawlist($this->connect, $remote_directory, true);
+ $next_folder = false;
+ $items = array();
+ foreach ($buff as $str) {
+ if ('' == $str) {
+ $next_folder = true;
+ continue;
+ }
+ if ($next_folder) {
+ $remote_directory = preg_replace('/\:/', '', $str);
+ $next_folder = false;
+ $item = array();
+ $item['path'] = $remote_directory;
+ $item['type'] = 'd'; // directory
+ $items[] = $item;
+ continue;
+ }
+ $info = preg_split("/\s+/", $str, 9);
+ $type = substr($info[0], 0, 1);
+ switch ($type) {
+ case 'l' : //omit symbolic links
+ case 'd' :
+ break;
+ default:
+ $remote_file_path = $remote_directory . DIRECTORY_SEPARATOR . $info[8];
+ $item = array();
+ $item['path'] = $remote_file_path;
+ $item['type'] = 'f'; // normal file
+ $items[] = $item;
+ }
+ }
+ return $items;
+ }
+
+ /**
+ * Downloads specified files from remote directory
+ * if there is a directory among files it is downloaded recursively (omitting symbolic links).
+ * @param $remote_directory string remote FTP path to a source directory to download from.
+ * @param array $files list of files to download from remote directory.
+ * @param $dest_local_directory string destination folder to store downloaded files.
+ * @return bool true on success and false on failure.
+ */
+ private function ftp_download_files($remote_directory, array $files, $dest_local_directory)
+ {
+ $contents = $this->ftp_scan_dir($remote_directory);
+ if (!isset($contents)) {
+ $this->setError(elFinder::ERROR_FTP_DOWNLOAD_FILE, $remote_directory);
+ return false;
+ }
+ foreach ($contents as $item) {
+ $drop = true;
+ foreach ($files as $file) {
+ if ($remote_directory . DIRECTORY_SEPARATOR . $file == $item['path'] || strstr($item['path'], $remote_directory . DIRECTORY_SEPARATOR . $file . DIRECTORY_SEPARATOR)) {
+ $drop = false;
+ break;
+ }
+ }
+ if ($drop) continue;
+ $relative_path = str_replace($remote_directory, '', $item['path']);
+ $local_path = $dest_local_directory . DIRECTORY_SEPARATOR . $relative_path;
+ switch ($item['type']) {
+ case 'd':
+ $success = mkdir($local_path);
+ break;
+ case 'f':
+ $success = ftp_get($this->connect, $local_path, $item['path'], FTP_BINARY);
+ break;
+ default:
+ $success = true;
+ }
+ if (!$success) {
+ $this->setError(elFinder::ERROR_FTP_DOWNLOAD_FILE, $remote_directory);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Delete local directory recursively.
+ * @param $dirPath string to directory to be erased.
+ * @return bool true on success and false on failure.
+ */
+ private function deleteDir($dirPath)
+ {
+ if (!is_dir($dirPath)) {
+ $success = unlink($dirPath);
+ } else {
+ $success = true;
+ foreach (array_reverse(elFinderVolumeFTP::listFilesInDirectory($dirPath, false)) as $path) {
+ $path = $dirPath . DIRECTORY_SEPARATOR . $path;
+ if(is_link($path)) {
+ unlink($path);
+ } else if (is_dir($path)) {
+ $success = rmdir($path);
+ } else {
+ $success = unlink($path);
+ }
+ if (!$success) {
+ break;
+ }
+ }
+ if($success) {
+ $success = rmdir($dirPath);
+ }
+ }
+ if(!$success) {
+ $this->setError(elFinder::ERROR_RM, $dirPath);
+ return false;
+ }
+ return $success;
+ }
+
+ /**
+ * Returns array of strings containing all files and folders in the specified local directory.
+ * @param $dir
+ * @param string $prefix
+ * @internal param string $path path to directory to scan.
+ * @return array array of files and folders names relative to the $path
+ * or an empty array if the directory $path is empty,
+ *
+ * false if $path is not a directory or does not exist.
+ */
+ private static function listFilesInDirectory($dir, $omitSymlinks, $prefix = '')
+ {
+ if (!is_dir($dir)) {
+ return false;
+ }
+ $excludes = array(".","..");
+ $result = array();
+ $files = scandir($dir);
+ if(!$files) {
+ return array();
+ }
+ foreach($files as $file) {
+ if(!in_array($file, $excludes)) {
+ $path = $dir.DIRECTORY_SEPARATOR.$file;
+ if(is_link($path)) {
+ if($omitSymlinks) {
+ continue;
+ } else {
+ $result[] = $prefix.$file;
+ }
+ } else if(is_dir($path)) {
+ $result[] = $prefix.$file.DIRECTORY_SEPARATOR;
+ $subs = elFinderVolumeFTP::listFilesInDirectory($path, $omitSymlinks, $prefix.$file.DIRECTORY_SEPARATOR);
+ if($subs) {
+ $result = array_merge($result, $subs);
+ }
+
+ } else {
+ $result[] = $prefix.$file;
+ }
+ }
+ }
+ return $result;
+ }
+
+/**
+ * Resize image
+ * @param string $hash
+ * @param int $width
+ * @param int $height
+ * @param int $x
+ * @param int $y
+ * @param string $mode
+ * @param string $bg
+ * @param int $degree
+ * @return array|bool|false
+ */
+ public function resize($hash, $width, $height, $x, $y, $mode = 'resize', $bg = '', $degree = 0) {
+ if ($this->commandDisabled('resize')) {
+ return $this->setError(elFinder::ERROR_PERM_DENIED);
+ }
+
+ if (($file = $this->file($hash)) == false) {
+ return $this->setError(elFinder::ERROR_FILE_NOT_FOUND);
+ }
+
+ if (!$file['write'] || !$file['read']) {
+ return $this->setError(elFinder::ERROR_PERM_DENIED);
+ }
+
+ $path = $this->decode($hash);
+
+ $tmpDir = $this->tempDir();
+ if (!$tmpDir) {
+ return false;
+ }
+
+ $local_path = $tmpDir . DIRECTORY_SEPARATOR . basename($path);
+ $remote_directory = ftp_pwd($this->connect);
+ $success = ftp_get($this->connect, $local_path, $path, FTP_BINARY);
+ if (!$success) {
+ $this->setError(elFinder::ERROR_FTP_DOWNLOAD_FILE, $remote_directory);
+ return false;
+ }
+
+ if (!$this->canResize($path, $file)) {
+ return $this->setError(elFinder::ERROR_UNSUPPORT_TYPE);
+ }
+
+ switch($mode) {
+
+ case 'propresize':
+ $result = $this->imgResize($local_path, $width, $height, true, true);
+ break;
+
+ case 'crop':
+ $result = $this->imgCrop($local_path, $width, $height, $x, $y);
+ break;
+
+ case 'fitsquare':
+ $result = $this->imgSquareFit($local_path, $width, $height, 'center', 'middle', ($bg ? $bg : $this->options['tmbBgColor']));
+ break;
+
+ case 'rotate':
+ $result = $this->imgRotate($local_path, $degree, ($bg ? $bg : $this->options['tmbBgColor']));
+ break;
+
+ default:
+ $result = $this->imgResize($local_path, $width, $height, false, true);
+ break;
+ }
+
+ if ($result) {
+
+ // upload to FTP and clear temp local file
+
+ if (!ftp_put($this->connect, $path, $local_path, FTP_BINARY)) {
+ $this->setError(elFinder::ERROR_FTP_UPLOAD_FILE, $path);
+ $this->deleteDir($tmpDir); //cleanup
+ }
+
+ $this->clearcache();
+ return $this->stat($path);
+ }
+
+ $this->setError(elFinder::ERROR_UNKNOWN);
+ return false;
+ }
+
+} // END class
+
diff --git a/app/mihaildev/elfinder/php/elFinderVolumeLocalFileSystem.class.php b/app/mihaildev/elfinder/php/elFinderVolumeLocalFileSystem.class.php
new file mode 100755
index 0000000..a3dc6fe
--- /dev/null
+++ b/app/mihaildev/elfinder/php/elFinderVolumeLocalFileSystem.class.php
@@ -0,0 +1,853 @@
+options['alias'] = ''; // alias to replace root dir name
+ $this->options['dirMode'] = 0755; // new dirs mode
+ $this->options['fileMode'] = 0644; // new files mode
+ $this->options['quarantine'] = '.quarantine'; // quarantine folder name - required to check archive (must be hidden)
+ $this->options['maxArcFilesSize'] = 0; // max allowed archive files size (0 - no limit)
+ }
+
+ /*********************************************************************/
+ /* INIT AND CONFIGURE */
+ /*********************************************************************/
+
+ /**
+ * Configure after successfull mount.
+ *
+ * @return void
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function configure() {
+ $this->aroot = realpath($this->root);
+ $root = $this->stat($this->root);
+
+ if ($this->options['quarantine']) {
+ $this->attributes[] = array(
+ 'pattern' => '~^'.preg_quote(DIRECTORY_SEPARATOR.$this->options['quarantine']).'$~',
+ 'read' => false,
+ 'write' => false,
+ 'locked' => true,
+ 'hidden' => true
+ );
+ }
+
+ // chek thumbnails path
+ if ($this->options['tmbPath']) {
+ $this->options['tmbPath'] = strpos($this->options['tmbPath'], DIRECTORY_SEPARATOR) === false
+ // tmb path set as dirname under root dir
+ ? $this->root.DIRECTORY_SEPARATOR.$this->options['tmbPath']
+ // tmb path as full path
+ : $this->_normpath($this->options['tmbPath']);
+ }
+
+ parent::configure();
+
+ // if no thumbnails url - try detect it
+ if ($root['read'] && !$this->tmbURL && $this->URL) {
+ if (strpos($this->tmbPath, $this->root) === 0) {
+ $this->tmbURL = $this->URL.str_replace(DIRECTORY_SEPARATOR, '/', substr($this->tmbPath, strlen($this->root)+1));
+ if (preg_match("|[^/?&=]$|", $this->tmbURL)) {
+ $this->tmbURL .= '/';
+ }
+ }
+ }
+
+ // check quarantine dir
+ if (!empty($this->options['quarantine'])) {
+ $this->quarantine = $this->root.DIRECTORY_SEPARATOR.$this->options['quarantine'];
+ if ((!is_dir($this->quarantine) && !$this->_mkdir($this->root, $this->options['quarantine'])) || !is_writable($this->quarantine)) {
+ $this->archivers['extract'] = array();
+ $this->disabled[] = 'extract';
+ }
+ } else {
+ $this->archivers['extract'] = array();
+ $this->disabled[] = 'extract';
+ }
+
+ }
+
+ /*********************************************************************/
+ /* FS API */
+ /*********************************************************************/
+
+ /*********************** paths/urls *************************/
+
+ /**
+ * Return parent directory path
+ *
+ * @param string $path file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _dirname($path) {
+ return dirname($path);
+ }
+
+ /**
+ * Return file name
+ *
+ * @param string $path file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _basename($path) {
+ return basename($path);
+ }
+
+ /**
+ * Join dir name and file name and retur full path
+ *
+ * @param string $dir
+ * @param string $name
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _joinPath($dir, $name) {
+ return $dir.DIRECTORY_SEPARATOR.$name;
+ }
+
+ /**
+ * Return normalized path, this works the same as os.path.normpath() in Python
+ *
+ * @param string $path path
+ * @return string
+ * @author Troex Nevelin
+ **/
+ protected function _normpath($path) {
+ if (empty($path)) {
+ return '.';
+ }
+
+ if (strpos($path, '/') === 0) {
+ $initial_slashes = true;
+ } else {
+ $initial_slashes = false;
+ }
+
+ if (($initial_slashes)
+ && (strpos($path, '//') === 0)
+ && (strpos($path, '///') === false)) {
+ $initial_slashes = 2;
+ }
+
+ $initial_slashes = (int) $initial_slashes;
+
+ $comps = explode('/', $path);
+ $new_comps = array();
+ foreach ($comps as $comp) {
+ if (in_array($comp, array('', '.'))) {
+ continue;
+ }
+
+ if (($comp != '..')
+ || (!$initial_slashes && !$new_comps)
+ || ($new_comps && (end($new_comps) == '..'))) {
+ array_push($new_comps, $comp);
+ } elseif ($new_comps) {
+ array_pop($new_comps);
+ }
+ }
+ $comps = $new_comps;
+ $path = implode('/', $comps);
+ if ($initial_slashes) {
+ $path = str_repeat('/', $initial_slashes) . $path;
+ }
+
+ return $path ? $path : '.';
+ }
+
+ /**
+ * Return file path related to root dir
+ *
+ * @param string $path file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _relpath($path) {
+ return $path == $this->root ? '' : substr($path, strlen($this->root)+1);
+ }
+
+ /**
+ * Convert path related to root dir into real path
+ *
+ * @param string $path file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _abspath($path) {
+ return $path == DIRECTORY_SEPARATOR ? $this->root : $this->root.DIRECTORY_SEPARATOR.$path;
+ }
+
+ /**
+ * Return fake path started from root dir
+ *
+ * @param string $path file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _path($path) {
+ return $this->rootName.($path == $this->root ? '' : $this->separator.$this->_relpath($path));
+ }
+
+ /**
+ * Return true if $path is children of $parent
+ *
+ * @param string $path path to check
+ * @param string $parent parent path
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _inpath($path, $parent) {
+ return $path == $parent || strpos($path, $parent.DIRECTORY_SEPARATOR) === 0;
+ }
+
+
+
+ /***************** file stat ********************/
+
+ /**
+ * Return stat for given path.
+ * Stat contains following fields:
+ * - (int) size file size in b. required
+ * - (int) ts file modification time in unix time. required
+ * - (string) mime mimetype. required for folders, others - optionally
+ * - (bool) read read permissions. required
+ * - (bool) write write permissions. required
+ * - (bool) locked is object locked. optionally
+ * - (bool) hidden is object hidden. optionally
+ * - (string) alias for symlinks - link target path relative to root path. optionally
+ * - (string) target for symlinks - link target path. optionally
+ *
+ * If file does not exists - returns empty array or false.
+ *
+ * @param string $path file path
+ * @return array|false
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _stat($path) {
+ $stat = array();
+
+ if (!file_exists($path)) {
+ return $stat;
+ }
+
+ //Verifies the given path is the root or is inside the root. Prevents directory traveral.
+ if (!$this->aroot) {
+ // for Inheritance class ( not calling parent::configure() )
+ $this->aroot = realpath($this->root);
+ }
+ if (!$this->_inpath(realpath($path), $this->aroot)) {
+ return $stat;
+ }
+
+ if ($path != $this->root && is_link($path)) {
+ if (($target = $this->readlink($path)) == false
+ || $target == $path) {
+ $stat['mime'] = 'symlink-broken';
+ $stat['read'] = false;
+ $stat['write'] = false;
+ $stat['size'] = 0;
+ return $stat;
+ }
+ $stat['alias'] = $this->_path($target);
+ $stat['target'] = $target;
+ $path = $target;
+ $lstat = lstat($path);
+ $size = $lstat['size'];
+ } else {
+ $size = @filesize($path);
+ }
+
+ $dir = is_dir($path);
+
+ $stat['mime'] = $dir ? 'directory' : $this->mimetype($path);
+ $stat['ts'] = filemtime($path);
+ $stat['read'] = is_readable($path)?null:false;
+ $stat['write'] = is_writable($path)?null:false;
+ if ($stat['read']) {
+ $stat['size'] = $dir ? 0 : $size;
+ }
+
+ return $stat;
+ }
+
+
+ /**
+ * Return true if path is dir and has at least one childs directory
+ *
+ * @param string $path dir path
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _subdirs($path) {
+
+ if (($dir = dir($path))) {
+ $dir = dir($path);
+ while (($entry = $dir->read()) !== false) {
+ $p = $dir->path.DIRECTORY_SEPARATOR.$entry;
+ if ($entry != '.' && $entry != '..' && is_dir($p) && !$this->attr($p, 'hidden')) {
+ $dir->close();
+ return true;
+ }
+ }
+ $dir->close();
+ }
+ return false;
+ }
+
+ /**
+ * Return object width and height
+ * Usualy used for images, but can be realize for video etc...
+ *
+ * @param string $path file path
+ * @param string $mime file mime type
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _dimensions($path, $mime) {
+ clearstatcache();
+ return strpos($mime, 'image') === 0 && ($s = @getimagesize($path)) !== false
+ ? $s[0].'x'.$s[1]
+ : false;
+ }
+ /******************** file/dir content *********************/
+
+ /**
+ * Return symlink target file
+ *
+ * @param string $path link path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function readlink($path) {
+ if (!($target = @readlink($path))) {
+ return false;
+ }
+
+ if (substr($target, 0, 1) != DIRECTORY_SEPARATOR) {
+ $target = dirname($path).DIRECTORY_SEPARATOR.$target;
+ }
+
+ $atarget = realpath($target);
+
+ if (!$atarget) {
+ return false;
+ }
+
+ $root = $this->root;
+ $aroot = $this->aroot;
+
+ if ($this->_inpath($atarget, $this->aroot)) {
+ return $this->_normpath($this->root.DIRECTORY_SEPARATOR.substr($atarget, strlen($this->aroot)+1));
+ }
+
+ return false;
+ }
+
+ /**
+ * Return files list in directory.
+ *
+ * @param string $path dir path
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _scandir($path) {
+ $files = array();
+
+ foreach (scandir($path) as $name) {
+ if ($name != '.' && $name != '..') {
+ $files[] = $path.DIRECTORY_SEPARATOR.$name;
+ }
+ }
+ return $files;
+ }
+
+ /**
+ * Open file and return file pointer
+ *
+ * @param string $path file path
+ * @param bool $write open file for writing
+ * @return resource|false
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _fopen($path, $mode='rb') {
+ return @fopen($path, 'r');
+ }
+
+ /**
+ * Close opened file
+ *
+ * @param resource $fp file pointer
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _fclose($fp, $path='') {
+ return @fclose($fp);
+ }
+
+ /******************** file/dir manipulations *************************/
+
+ /**
+ * Create dir and return created dir path or false on failed
+ *
+ * @param string $path parent dir path
+ * @param string $name new directory name
+ * @return string|bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _mkdir($path, $name) {
+ $path = $path.DIRECTORY_SEPARATOR.$name;
+
+ if (@mkdir($path)) {
+ @chmod($path, $this->options['dirMode']);
+ return $path;
+ }
+
+ return false;
+ }
+
+ /**
+ * Create file and return it's path or false on failed
+ *
+ * @param string $path parent dir path
+ * @param string $name new file name
+ * @return string|bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _mkfile($path, $name) {
+ $path = $path.DIRECTORY_SEPARATOR.$name;
+
+ if (($fp = @fopen($path, 'w'))) {
+ @fclose($fp);
+ @chmod($path, $this->options['fileMode']);
+ return $path;
+ }
+ return false;
+ }
+
+ /**
+ * Create symlink
+ *
+ * @param string $source file to link to
+ * @param string $targetDir folder to create link in
+ * @param string $name symlink name
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _symlink($source, $targetDir, $name) {
+ return @symlink($source, $targetDir.DIRECTORY_SEPARATOR.$name);
+ }
+
+ /**
+ * Copy file into another file
+ *
+ * @param string $source source file path
+ * @param string $targetDir target directory path
+ * @param string $name new file name
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _copy($source, $targetDir, $name) {
+ return copy($source, $targetDir.DIRECTORY_SEPARATOR.$name);
+ }
+
+ /**
+ * Move file into another parent dir.
+ * Return new file path or false.
+ *
+ * @param string $source source file path
+ * @param string $target target dir path
+ * @param string $name file name
+ * @return string|bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _move($source, $targetDir, $name) {
+ $target = $targetDir.DIRECTORY_SEPARATOR.$name;
+ return @rename($source, $target) ? $target : false;
+ }
+
+ /**
+ * Remove file
+ *
+ * @param string $path file path
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _unlink($path) {
+ return @unlink($path);
+ }
+
+ /**
+ * Remove dir
+ *
+ * @param string $path dir path
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _rmdir($path) {
+ return @rmdir($path);
+ }
+
+ /**
+ * Create new file and write into it from file pointer.
+ * Return new file path or false on error.
+ *
+ * @param resource $fp file pointer
+ * @param string $dir target dir path
+ * @param string $name file name
+ * @param array $stat file stat (required by some virtual fs)
+ * @return bool|string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _save($fp, $dir, $name, $stat) {
+ $path = $dir.DIRECTORY_SEPARATOR.$name;
+
+ if (!($target = @fopen($path, 'wb'))) {
+ return false;
+ }
+
+ while (!feof($fp)) {
+ fwrite($target, fread($fp, 8192));
+ }
+ fclose($target);
+ @chmod($path, $this->options['fileMode']);
+ clearstatcache();
+ return $path;
+ }
+
+ /**
+ * Get file contents
+ *
+ * @param string $path file path
+ * @return string|false
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _getContents($path) {
+ return file_get_contents($path);
+ }
+
+ /**
+ * Write a string to a file
+ *
+ * @param string $path file path
+ * @param string $content new file content
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _filePutContents($path, $content) {
+ if (@file_put_contents($path, $content, LOCK_EX) !== false) {
+ clearstatcache();
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Detect available archivers
+ *
+ * @return void
+ **/
+ protected function _checkArchivers() {
+ if (!function_exists('exec')) {
+ $this->options['archivers'] = $this->options['archive'] = array();
+ return;
+ }
+ $arcs = array(
+ 'create' => array(),
+ 'extract' => array()
+ );
+
+ //exec('tar --version', $o, $ctar);
+ $this->procExec('tar --version', $o, $ctar);
+
+ if ($ctar == 0) {
+ $arcs['create']['application/x-tar'] = array('cmd' => 'tar', 'argc' => '-cf', 'ext' => 'tar');
+ $arcs['extract']['application/x-tar'] = array('cmd' => 'tar', 'argc' => '-xf', 'ext' => 'tar');
+ //$test = exec('gzip --version', $o, $c);
+ unset($o);
+ $test = $this->procExec('gzip --version', $o, $c);
+
+ if ($c == 0) {
+ $arcs['create']['application/x-gzip'] = array('cmd' => 'tar', 'argc' => '-czf', 'ext' => 'tgz');
+ $arcs['extract']['application/x-gzip'] = array('cmd' => 'tar', 'argc' => '-xzf', 'ext' => 'tgz');
+ }
+ unset($o);
+ //$test = exec('bzip2 --version', $o, $c);
+ $test = $this->procExec('bzip2 --version', $o, $c);
+ if ($c == 0) {
+ $arcs['create']['application/x-bzip2'] = array('cmd' => 'tar', 'argc' => '-cjf', 'ext' => 'tbz');
+ $arcs['extract']['application/x-bzip2'] = array('cmd' => 'tar', 'argc' => '-xjf', 'ext' => 'tbz');
+ }
+ }
+ unset($o);
+ //exec('zip --version', $o, $c);
+ $this->procExec('zip -v', $o, $c);
+ if ($c == 0) {
+ $arcs['create']['application/zip'] = array('cmd' => 'zip', 'argc' => '-r9', 'ext' => 'zip');
+ }
+ unset($o);
+ $this->procExec('unzip --help', $o, $c);
+ if ($c == 0) {
+ $arcs['extract']['application/zip'] = array('cmd' => 'unzip', 'argc' => '', 'ext' => 'zip');
+ }
+ unset($o);
+ //exec('rar --version', $o, $c);
+ $this->procExec('rar --version', $o, $c);
+ if ($c == 0 || $c == 7) {
+ $arcs['create']['application/x-rar'] = array('cmd' => 'rar', 'argc' => 'a -inul', 'ext' => 'rar');
+ $arcs['extract']['application/x-rar'] = array('cmd' => 'rar', 'argc' => 'x -y', 'ext' => 'rar');
+ } else {
+ unset($o);
+ //$test = exec('unrar', $o, $c);
+ $test = $this->procExec('unrar', $o, $c);
+ if ($c==0 || $c == 7) {
+ $arcs['extract']['application/x-rar'] = array('cmd' => 'unrar', 'argc' => 'x -y', 'ext' => 'rar');
+ }
+ }
+ unset($o);
+ //exec('7za --help', $o, $c);
+ $this->procExec('7za --help', $o, $c);
+ if ($c == 0) {
+ $arcs['create']['application/x-7z-compressed'] = array('cmd' => '7za', 'argc' => 'a', 'ext' => '7z');
+ $arcs['extract']['application/x-7z-compressed'] = array('cmd' => '7za', 'argc' => 'e -y', 'ext' => '7z');
+
+ if (empty($arcs['create']['application/x-gzip'])) {
+ $arcs['create']['application/x-gzip'] = array('cmd' => '7za', 'argc' => 'a -tgzip', 'ext' => 'tar.gz');
+ }
+ if (empty($arcs['extract']['application/x-gzip'])) {
+ $arcs['extract']['application/x-gzip'] = array('cmd' => '7za', 'argc' => 'e -tgzip -y', 'ext' => 'tar.gz');
+ }
+ if (empty($arcs['create']['application/x-bzip2'])) {
+ $arcs['create']['application/x-bzip2'] = array('cmd' => '7za', 'argc' => 'a -tbzip2', 'ext' => 'tar.bz');
+ }
+ if (empty($arcs['extract']['application/x-bzip2'])) {
+ $arcs['extract']['application/x-bzip2'] = array('cmd' => '7za', 'argc' => 'a -tbzip2 -y', 'ext' => 'tar.bz');
+ }
+ if (empty($arcs['create']['application/zip'])) {
+ $arcs['create']['application/zip'] = array('cmd' => '7za', 'argc' => 'a -tzip -l', 'ext' => 'zip');
+ }
+ if (empty($arcs['extract']['application/zip'])) {
+ $arcs['extract']['application/zip'] = array('cmd' => '7za', 'argc' => 'e -tzip -y', 'ext' => 'zip');
+ }
+ if (empty($arcs['create']['application/x-tar'])) {
+ $arcs['create']['application/x-tar'] = array('cmd' => '7za', 'argc' => 'a -ttar -l', 'ext' => 'tar');
+ }
+ if (empty($arcs['extract']['application/x-tar'])) {
+ $arcs['extract']['application/x-tar'] = array('cmd' => '7za', 'argc' => 'e -ttar -y', 'ext' => 'tar');
+ }
+ }
+
+ $this->archivers = $arcs;
+ }
+
+ /**
+ * Unpack archive
+ *
+ * @param string $path archive path
+ * @param array $arc archiver command and arguments (same as in $this->archivers)
+ * @return void
+ * @author Dmitry (dio) Levashov
+ * @author Alexey Sukhotin
+ **/
+ protected function _unpack($path, $arc) {
+ $cwd = getcwd();
+ $dir = $this->_dirname($path);
+ chdir($dir);
+ $cmd = $arc['cmd'].' '.$arc['argc'].' '.escapeshellarg($this->_basename($path));
+ $this->procExec($cmd, $o, $c);
+ chdir($cwd);
+ }
+
+ /**
+ * Recursive symlinks search
+ *
+ * @param string $path file/dir path
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _findSymlinks($path) {
+ if (is_link($path)) {
+ return true;
+ }
+
+ if (is_dir($path)) {
+ foreach (scandir($path) as $name) {
+ if ($name != '.' && $name != '..') {
+ $p = $path.DIRECTORY_SEPARATOR.$name;
+ if (is_link($p) || !$this->nameAccepted($name)) {
+ return true;
+ }
+ if (is_dir($p) && $this->_findSymlinks($p)) {
+ return true;
+ } elseif (is_file($p)) {
+ $this->archiveSize += filesize($p);
+ }
+ }
+ }
+ } else {
+
+ $this->archiveSize += filesize($path);
+ }
+
+ return false;
+ }
+
+ /**
+ * Extract files from archive
+ *
+ * @param string $path archive path
+ * @param array $arc archiver command and arguments (same as in $this->archivers)
+ * @return true
+ * @author Dmitry (dio) Levashov,
+ * @author Alexey Sukhotin
+ **/
+ protected function _extract($path, $arc) {
+
+ if ($this->quarantine) {
+ $dir = $this->quarantine.DIRECTORY_SEPARATOR.str_replace(' ', '_', microtime()).basename($path);
+ $archive = $dir.DIRECTORY_SEPARATOR.basename($path);
+
+ if (!@mkdir($dir)) {
+ return false;
+ }
+
+ chmod($dir, 0777);
+
+ // copy in quarantine
+ if (!copy($path, $archive)) {
+ return false;
+ }
+
+ // extract in quarantine
+ $this->_unpack($archive, $arc);
+ unlink($archive);
+
+ // get files list
+ $ls = array();
+ foreach (scandir($dir) as $i => $name) {
+ if ($name != '.' && $name != '..') {
+ $ls[] = $name;
+ }
+ }
+
+ // no files - extract error ?
+ if (empty($ls)) {
+ return false;
+ }
+
+ $this->archiveSize = 0;
+
+ // find symlinks
+ $symlinks = $this->_findSymlinks($dir);
+ // remove arc copy
+ $this->remove($dir);
+
+ if ($symlinks) {
+ return $this->setError(elFinder::ERROR_ARC_SYMLINKS);
+ }
+
+ // check max files size
+ if ($this->options['maxArcFilesSize'] > 0 && $this->options['maxArcFilesSize'] < $this->archiveSize) {
+ return $this->setError(elFinder::ERROR_ARC_MAXSIZE);
+ }
+
+
+
+ // archive contains one item - extract in archive dir
+ if (count($ls) == 1) {
+ $this->_unpack($path, $arc);
+ $result = dirname($path).DIRECTORY_SEPARATOR.$ls[0];
+
+
+ } else {
+ // for several files - create new directory
+ // create unique name for directory
+ $name = basename($path);
+ if (preg_match('/\.((tar\.(gz|bz|bz2|z|lzo))|cpio\.gz|ps\.gz|xcf\.(gz|bz2)|[a-z0-9]{1,4})$/i', $name, $m)) {
+ $name = substr($name, 0, strlen($name)-strlen($m[0]));
+ }
+ $test = dirname($path).DIRECTORY_SEPARATOR.$name;
+ if (file_exists($test) || is_link($test)) {
+ $name = $this->uniqueName(dirname($path), $name, '-', false);
+ }
+
+ $result = dirname($path).DIRECTORY_SEPARATOR.$name;
+ $archive = $result.DIRECTORY_SEPARATOR.basename($path);
+
+ if (!$this->_mkdir(dirname($path), $name) || !copy($path, $archive)) {
+ return false;
+ }
+
+ $this->_unpack($archive, $arc);
+ @unlink($archive);
+ }
+
+ return file_exists($result) ? $result : false;
+ }
+ }
+
+ /**
+ * Create archive and return its path
+ *
+ * @param string $dir target dir
+ * @param array $files files names list
+ * @param string $name archive name
+ * @param array $arc archiver options
+ * @return string|bool
+ * @author Dmitry (dio) Levashov,
+ * @author Alexey Sukhotin
+ **/
+ protected function _archive($dir, $files, $name, $arc) {
+ $cwd = getcwd();
+ chdir($dir);
+
+ $files = array_map('escapeshellarg', $files);
+
+ $cmd = $arc['cmd'].' '.$arc['argc'].' '.escapeshellarg($name).' '.implode(' ', $files);
+ $this->procExec($cmd, $o, $c);
+ chdir($cwd);
+
+ $path = $dir.DIRECTORY_SEPARATOR.$name;
+ return file_exists($path) ? $path : false;
+ }
+
+} // END class
diff --git a/app/mihaildev/elfinder/php/elFinderVolumeMySQL.class.php b/app/mihaildev/elfinder/php/elFinderVolumeMySQL.class.php
new file mode 100755
index 0000000..06396c2
--- /dev/null
+++ b/app/mihaildev/elfinder/php/elFinderVolumeMySQL.class.php
@@ -0,0 +1,960 @@
+ 'localhost',
+ 'user' => '',
+ 'pass' => '',
+ 'db' => '',
+ 'port' => null,
+ 'socket' => null,
+ 'files_table' => 'elfinder_file',
+ 'tmbPath' => '',
+ 'tmpPath' => ''
+ );
+ $this->options = array_merge($this->options, $opts);
+ $this->options['mimeDetect'] = 'internal';
+ }
+
+ /*********************************************************************/
+ /* INIT AND CONFIGURE */
+ /*********************************************************************/
+
+ /**
+ * Prepare driver before mount volume.
+ * Connect to db, check required tables and fetch root path
+ *
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function init() {
+
+ if (!($this->options['host'] || $this->options['socket'])
+ || !$this->options['user']
+ || !$this->options['pass']
+ || !$this->options['db']
+ || !$this->options['path']
+ || !$this->options['files_table']) {
+ return false;
+ }
+
+
+ $this->db = new mysqli($this->options['host'], $this->options['user'], $this->options['pass'], $this->options['db'], $this->options['port'], $this->options['socket']);
+ if ($this->db->connect_error || @mysqli_connect_error()) {
+ return false;
+ }
+
+ $this->db->set_charset('utf8');
+
+ if ($res = $this->db->query('SHOW TABLES')) {
+ while ($row = $res->fetch_array()) {
+ if ($row[0] == $this->options['files_table']) {
+ $this->tbf = $this->options['files_table'];
+ break;
+ }
+ }
+ }
+
+ if (!$this->tbf) {
+ return false;
+ }
+
+ $this->updateCache($this->options['path'], $this->_stat($this->options['path']));
+
+ return true;
+ }
+
+
+
+ /**
+ * Set tmp path
+ *
+ * @return void
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function configure() {
+ parent::configure();
+
+ if (($tmp = $this->options['tmpPath'])) {
+ if (!file_exists($tmp)) {
+ if (@mkdir($tmp)) {
+ @chmod($tmp, $this->options['tmbPathMode']);
+ }
+ }
+
+ $this->tmpPath = is_dir($tmp) && is_writable($tmp) ? $tmp : false;
+ }
+
+ if (!$this->tmpPath && $this->tmbPath && $this->tmbPathWritable) {
+ $this->tmpPath = $this->tmbPath;
+ }
+
+ $this->mimeDetect = 'internal';
+ }
+
+ /**
+ * Close connection
+ *
+ * @return void
+ * @author Dmitry (dio) Levashov
+ **/
+ public function umount() {
+ $this->db->close();
+ }
+
+ /**
+ * Return debug info for client
+ *
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ public function debug() {
+ $debug = parent::debug();
+ $debug['sqlCount'] = $this->sqlCnt;
+ if ($this->dbError) {
+ $debug['dbError'] = $this->dbError;
+ }
+ return $debug;
+ }
+
+ /**
+ * Perform sql query and return result.
+ * Increase sqlCnt and save error if occured
+ *
+ * @param string $sql query
+ * @return misc
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function query($sql) {
+ $this->sqlCnt++;
+ $res = $this->db->query($sql);
+ if (!$res) {
+ $this->dbError = $this->db->error;
+ }
+ return $res;
+ }
+
+ /**
+ * Create empty object with required mimetype
+ *
+ * @param string $path parent dir path
+ * @param string $name object name
+ * @param string $mime mime type
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function make($path, $name, $mime) {
+ $sql = 'INSERT INTO %s (`parent_id`, `name`, `size`, `mtime`, `mime`, `content`, `read`, `write`) VALUES ("%s", "%s", 0, %d, "%s", "", "%d", "%d")';
+ $sql = sprintf($sql, $this->tbf, $path, $this->db->real_escape_string($name), time(), $mime, $this->defaults['read'], $this->defaults['write']);
+ // echo $sql;
+ return $this->query($sql) && $this->db->affected_rows > 0;
+ }
+
+ /**
+ * Search files
+ *
+ * @param string $q search string
+ * @param array $mimes
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ public function search($q, $mimes) {
+ $result = array();
+
+ $sql = 'SELECT f.id, f.parent_id, f.name, f.size, f.mtime AS ts, f.mime, f.read, f.write, f.locked, f.hidden, f.width, f.height, 0 AS dirs
+ FROM %s AS f
+ WHERE f.name RLIKE "%s"';
+
+ $sql = sprintf($sql, $this->tbf, $this->db->real_escape_string($q));
+
+ if (($res = $this->query($sql))) {
+ while ($row = $res->fetch_assoc()) {
+ if ($this->mimeAccepted($row['mime'], $mimes)) {
+ $id = $row['id'];
+ if ($row['parent_id']) {
+ $row['phash'] = $this->encode($row['parent_id']);
+ }
+
+ if ($row['mime'] == 'directory') {
+ unset($row['width']);
+ unset($row['height']);
+ } else {
+ unset($row['dirs']);
+ }
+
+ unset($row['id']);
+ unset($row['parent_id']);
+
+
+
+ if (($stat = $this->updateCache($id, $row)) && empty($stat['hidden'])) {
+ $result[] = $stat;
+ }
+ }
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Return temporary file path for required file
+ *
+ * @param string $path file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function tmpname($path) {
+ return $this->tmpPath.DIRECTORY_SEPARATOR.md5($path);
+ }
+
+ /**
+ * Resize image
+ *
+ * @param string $hash image file
+ * @param int $width new width
+ * @param int $height new height
+ * @param bool $crop crop image
+ * @return array|false
+ * @author Dmitry (dio) Levashov
+ * @author Alexey Sukhotin
+ **/
+ public function resize($hash, $width, $height, $x, $y, $mode = 'resize', $bg = '', $degree = 0) {
+ if ($this->commandDisabled('resize')) {
+ return $this->setError(elFinder::ERROR_PERM_DENIED);
+ }
+
+ if (($file = $this->file($hash)) == false) {
+ return $this->setError(elFinder::ERROR_FILE_NOT_FOUND);
+ }
+
+ if (!$file['write'] || !$file['read']) {
+ return $this->setError(elFinder::ERROR_PERM_DENIED);
+ }
+
+ $path = $this->decode($hash);
+
+ if (!$this->canResize($path, $file)) {
+ return $this->setError(elFinder::ERROR_UNSUPPORT_TYPE);
+ }
+
+ $img = $this->tmpname($path);
+
+ if (!($fp = @fopen($img, 'w+'))) {
+ return false;
+ }
+
+ if (($res = $this->query('SELECT content FROM '.$this->tbf.' WHERE id="'.$path.'"'))
+ && ($r = $res->fetch_assoc())) {
+ fwrite($fp, $r['content']);
+ rewind($fp);
+ fclose($fp);
+ } else {
+ return false;
+ }
+
+
+ switch($mode) {
+
+ case 'propresize':
+ $result = $this->imgResize($img, $width, $height, true, true);
+ break;
+
+ case 'crop':
+ $result = $this->imgCrop($img, $width, $height, $x, $y);
+ break;
+
+ case 'fitsquare':
+ $result = $this->imgSquareFit($img, $width, $height, 'center', 'middle', $bg ? $bg : $this->options['tmbBgColor']);
+ break;
+
+ default:
+ $result = $this->imgResize($img, $width, $height, false, true);
+ break;
+ }
+
+ if ($result) {
+
+ $sql = sprintf('UPDATE %s SET content=LOAD_FILE("%s"), mtime=UNIX_TIMESTAMP() WHERE id=%d', $this->tbf, $this->loadFilePath($img), $path);
+
+ if (!$this->query($sql)) {
+ $content = file_get_contents($img);
+ $sql = sprintf('UPDATE %s SET content="%s", mtime=UNIX_TIMESTAMP() WHERE id=%d', $this->tbf, $this->db->real_escape_string($content), $path);
+ if (!$this->query($sql)) {
+ @unlink($img);
+ return false;
+ }
+ }
+ @unlink($img);
+ $this->rmTmb($file);
+ $this->clearcache();
+ return $this->stat($path);
+ }
+
+ return false;
+ }
+
+
+ /*********************************************************************/
+ /* FS API */
+ /*********************************************************************/
+
+ /**
+ * Cache dir contents
+ *
+ * @param string $path dir path
+ * @return void
+ * @author Dmitry Levashov
+ **/
+ protected function cacheDir($path) {
+ $this->dirsCache[$path] = array();
+
+ $sql = 'SELECT f.id, f.parent_id, f.name, f.size, f.mtime AS ts, f.mime, f.read, f.write, f.locked, f.hidden, f.width, f.height, IF(ch.id, 1, 0) AS dirs
+ FROM '.$this->tbf.' AS f
+ LEFT JOIN '.$this->tbf.' AS ch ON ch.parent_id=f.id AND ch.mime="directory"
+ WHERE f.parent_id="'.$path.'"
+ GROUP BY f.id';
+
+ $res = $this->query($sql);
+ if ($res) {
+ while ($row = $res->fetch_assoc()) {
+ // debug($row);
+ $id = $row['id'];
+ if ($row['parent_id']) {
+ $row['phash'] = $this->encode($row['parent_id']);
+ }
+
+ if ($row['mime'] == 'directory') {
+ unset($row['width']);
+ unset($row['height']);
+ } else {
+ unset($row['dirs']);
+ }
+
+ unset($row['id']);
+ unset($row['parent_id']);
+
+
+
+ if (($stat = $this->updateCache($id, $row)) && empty($stat['hidden'])) {
+ $this->dirsCache[$path][] = $id;
+ }
+ }
+ }
+
+ return $this->dirsCache[$path];
+ }
+
+ /**
+ * Return array of parents paths (ids)
+ *
+ * @param int $path file path (id)
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function getParents($path) {
+ $parents = array();
+
+ while ($path) {
+ if ($file = $this->stat($path)) {
+ array_unshift($parents, $path);
+ $path = isset($file['phash']) ? $this->decode($file['phash']) : false;
+ }
+ }
+
+ if (count($parents)) {
+ array_pop($parents);
+ }
+ return $parents;
+ }
+
+ /**
+ * Return correct file path for LOAD_FILE method
+ *
+ * @param string $path file path (id)
+ * @return string
+ * @author Troex Nevelin
+ **/
+ protected function loadFilePath($path) {
+ $realPath = realpath($path);
+ if (DIRECTORY_SEPARATOR == '\\') { // windows
+ $realPath = str_replace('\\', '\\\\', $realPath);
+ }
+ return $this->db->real_escape_string($realPath);
+ }
+
+ /**
+ * Recursive files search
+ *
+ * @param string $path dir path
+ * @param string $q search string
+ * @param array $mimes
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function doSearch($path, $q, $mimes) {
+ return array();
+ }
+
+
+ /*********************** paths/urls *************************/
+
+ /**
+ * Return parent directory path
+ *
+ * @param string $path file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _dirname($path) {
+ return ($stat = $this->stat($path)) ? ($stat['phash'] ? $this->decode($stat['phash']) : $this->root) : false;
+ }
+
+ /**
+ * Return file name
+ *
+ * @param string $path file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _basename($path) {
+ return ($stat = $this->stat($path)) ? $stat['name'] : false;
+ }
+
+ /**
+ * Join dir name and file name and return full path
+ *
+ * @param string $dir
+ * @param string $name
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _joinPath($dir, $name) {
+ $sql = 'SELECT id FROM '.$this->tbf.' WHERE parent_id="'.$dir.'" AND name="'.$this->db->real_escape_string($name).'"';
+
+ if (($res = $this->query($sql)) && ($r = $res->fetch_assoc())) {
+ $this->updateCache($r['id'], $this->_stat($r['id']));
+ return $r['id'];
+ }
+ return -1;
+ }
+
+ /**
+ * Return normalized path, this works the same as os.path.normpath() in Python
+ *
+ * @param string $path path
+ * @return string
+ * @author Troex Nevelin
+ **/
+ protected function _normpath($path) {
+ return $path;
+ }
+
+ /**
+ * Return file path related to root dir
+ *
+ * @param string $path file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _relpath($path) {
+ return $path;
+ }
+
+ /**
+ * Convert path related to root dir into real path
+ *
+ * @param string $path file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _abspath($path) {
+ return $path;
+ }
+
+ /**
+ * Return fake path started from root dir
+ *
+ * @param string $path file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _path($path) {
+ if (($file = $this->stat($path)) == false) {
+ return '';
+ }
+
+ $parentsIds = $this->getParents($path);
+ $path = '';
+ foreach ($parentsIds as $id) {
+ $dir = $this->stat($id);
+ $path .= $dir['name'].$this->separator;
+ }
+ return $path.$file['name'];
+ }
+
+ /**
+ * Return true if $path is children of $parent
+ *
+ * @param string $path path to check
+ * @param string $parent parent path
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _inpath($path, $parent) {
+ return $path == $parent
+ ? true
+ : in_array($parent, $this->getParents($path));
+ }
+
+ /***************** file stat ********************/
+ /**
+ * Return stat for given path.
+ * Stat contains following fields:
+ * - (int) size file size in b. required
+ * - (int) ts file modification time in unix time. required
+ * - (string) mime mimetype. required for folders, others - optionally
+ * - (bool) read read permissions. required
+ * - (bool) write write permissions. required
+ * - (bool) locked is object locked. optionally
+ * - (bool) hidden is object hidden. optionally
+ * - (string) alias for symlinks - link target path relative to root path. optionally
+ * - (string) target for symlinks - link target path. optionally
+ *
+ * If file does not exists - returns empty array or false.
+ *
+ * @param string $path file path
+ * @return array|false
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _stat($path) {
+ $sql = 'SELECT f.id, f.parent_id, f.name, f.size, f.mtime AS ts, f.mime, f.read, f.write, f.locked, f.hidden, f.width, f.height, IF(ch.id, 1, 0) AS dirs
+ FROM '.$this->tbf.' AS f
+ LEFT JOIN '.$this->tbf.' AS p ON p.id=f.parent_id
+ LEFT JOIN '.$this->tbf.' AS ch ON ch.parent_id=f.id AND ch.mime="directory"
+ WHERE f.id="'.$path.'"
+ GROUP BY f.id';
+
+ $res = $this->query($sql);
+
+ if ($res) {
+ $stat = $res->fetch_assoc();
+ if ($stat['parent_id']) {
+ $stat['phash'] = $this->encode($stat['parent_id']);
+ }
+ if ($stat['mime'] == 'directory') {
+ unset($stat['width']);
+ unset($stat['height']);
+ } else {
+ unset($stat['dirs']);
+ }
+ unset($stat['id']);
+ unset($stat['parent_id']);
+ return $stat;
+
+ }
+ return array();
+ }
+
+ /**
+ * Return true if path is dir and has at least one childs directory
+ *
+ * @param string $path dir path
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _subdirs($path) {
+ return ($stat = $this->stat($path)) && isset($stat['dirs']) ? $stat['dirs'] : false;
+ }
+
+ /**
+ * Return object width and height
+ * Usualy used for images, but can be realize for video etc...
+ *
+ * @param string $path file path
+ * @param string $mime file mime type
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _dimensions($path, $mime) {
+ return ($stat = $this->stat($path)) && isset($stat['width']) && isset($stat['height']) ? $stat['width'].'x'.$stat['height'] : '';
+ }
+
+ /******************** file/dir content *********************/
+
+ /**
+ * Return files list in directory.
+ *
+ * @param string $path dir path
+ * @return array
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _scandir($path) {
+ return isset($this->dirsCache[$path])
+ ? $this->dirsCache[$path]
+ : $this->cacheDir($path);
+ }
+
+ /**
+ * Open file and return file pointer
+ *
+ * @param string $path file path
+ * @param string $mode open file mode (ignored in this driver)
+ * @return resource|false
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _fopen($path, $mode='rb') {
+ $fp = $this->tmbPath
+ ? @fopen($this->tmpname($path), 'w+')
+ : @tmpfile();
+
+
+ if ($fp) {
+ if (($res = $this->query('SELECT content FROM '.$this->tbf.' WHERE id="'.$path.'"'))
+ && ($r = $res->fetch_assoc())) {
+ fwrite($fp, $r['content']);
+ rewind($fp);
+ return $fp;
+ } else {
+ $this->_fclose($fp, $path);
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Close opened file
+ *
+ * @param resource $fp file pointer
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _fclose($fp, $path='') {
+ @fclose($fp);
+ if ($path) {
+ @unlink($this->tmpname($path));
+ }
+ }
+
+ /******************** file/dir manipulations *************************/
+
+ /**
+ * Create dir and return created dir path or false on failed
+ *
+ * @param string $path parent dir path
+ * @param string $name new directory name
+ * @return string|bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _mkdir($path, $name) {
+ return $this->make($path, $name, 'directory') ? $this->_joinPath($path, $name) : false;
+ }
+
+ /**
+ * Create file and return it's path or false on failed
+ *
+ * @param string $path parent dir path
+ * @param string $name new file name
+ * @return string|bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _mkfile($path, $name) {
+ return $this->make($path, $name, 'text/plain') ? $this->_joinPath($path, $name) : false;
+ }
+
+ /**
+ * Create symlink. FTP driver does not support symlinks.
+ *
+ * @param string $target link target
+ * @param string $path symlink path
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _symlink($target, $path, $name) {
+ return false;
+ }
+
+ /**
+ * Copy file into another file
+ *
+ * @param string $source source file path
+ * @param string $targetDir target directory path
+ * @param string $name new file name
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _copy($source, $targetDir, $name) {
+ $this->clearcache();
+ $id = $this->_joinPath($targetDir, $name);
+
+ $sql = $id > 0
+ ? sprintf('REPLACE INTO %s (id, parent_id, name, content, size, mtime, mime, width, height, `read`, `write`, `locked`, `hidden`) (SELECT %d, %d, name, content, size, mtime, mime, width, height, `read`, `write`, `locked`, `hidden` FROM %s WHERE id=%d)', $this->tbf, $id, $this->_dirname($id), $this->tbf, $source)
+ : sprintf('INSERT INTO %s (parent_id, name, content, size, mtime, mime, width, height, `read`, `write`, `locked`, `hidden`) SELECT %d, "%s", content, size, %d, mime, width, height, `read`, `write`, `locked`, `hidden` FROM %s WHERE id=%d', $this->tbf, $targetDir, $this->db->real_escape_string($name), time(), $this->tbf, $source);
+
+ return $this->query($sql);
+ }
+
+ /**
+ * Move file into another parent dir.
+ * Return new file path or false.
+ *
+ * @param string $source source file path
+ * @param string $target target dir path
+ * @param string $name file name
+ * @return string|bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _move($source, $targetDir, $name) {
+ $sql = 'UPDATE %s SET parent_id=%d, name="%s" WHERE id=%d LIMIT 1';
+ $sql = sprintf($sql, $this->tbf, $targetDir, $this->db->real_escape_string($name), $source);
+ return $this->query($sql) && $this->db->affected_rows > 0 ? $source : false;
+ }
+
+ /**
+ * Remove file
+ *
+ * @param string $path file path
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _unlink($path) {
+ return $this->query(sprintf('DELETE FROM %s WHERE id=%d AND mime!="directory" LIMIT 1', $this->tbf, $path)) && $this->db->affected_rows;
+ }
+
+ /**
+ * Remove dir
+ *
+ * @param string $path dir path
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _rmdir($path) {
+ return $this->query(sprintf('DELETE FROM %s WHERE id=%d AND mime="directory" LIMIT 1', $this->tbf, $path)) && $this->db->affected_rows;
+ }
+
+ /**
+ * undocumented function
+ *
+ * @return void
+ * @author Dmitry Levashov
+ **/
+ protected function _setContent($path, $fp) {
+ rewind($fp);
+ $fstat = fstat($fp);
+ $size = $fstat['size'];
+
+
+ }
+
+ /**
+ * Create new file and write into it from file pointer.
+ * Return new file path or false on error.
+ *
+ * @param resource $fp file pointer
+ * @param string $dir target dir path
+ * @param string $name file name
+ * @param array $stat file stat (required by some virtual fs)
+ * @return bool|string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _save($fp, $dir, $name, $stat) {
+ $this->clearcache();
+
+ $mime = $stat['mime'];
+ $w = !empty($stat['width']) ? $stat['width'] : 0;
+ $h = !empty($stat['height']) ? $stat['height'] : 0;
+
+ $id = $this->_joinPath($dir, $name);
+ rewind($fp);
+ $stat = fstat($fp);
+ $size = $stat['size'];
+
+ if (($tmpfile = tempnam($this->tmpPath, $this->id))) {
+ if (($trgfp = fopen($tmpfile, 'wb')) == false) {
+ unlink($tmpfile);
+ } else {
+ while (!feof($fp)) {
+ fwrite($trgfp, fread($fp, 8192));
+ }
+ fclose($trgfp);
+
+ $sql = $id > 0
+ ? 'REPLACE INTO %s (id, parent_id, name, content, size, mtime, mime, width, height) VALUES ('.$id.', %d, "%s", LOAD_FILE("%s"), %d, %d, "%s", %d, %d)'
+ : 'INSERT INTO %s (parent_id, name, content, size, mtime, mime, width, height) VALUES (%d, "%s", LOAD_FILE("%s"), %d, %d, "%s", %d, %d)';
+ $sql = sprintf($sql, $this->tbf, $dir, $this->db->real_escape_string($name), $this->loadFilePath($tmpfile), $size, time(), $mime, $w, $h);
+
+ $res = $this->query($sql);
+ unlink($tmpfile);
+
+ if ($res) {
+ return $id > 0 ? $id : $this->db->insert_id;
+ }
+ }
+ }
+
+
+ $content = '';
+ rewind($fp);
+ while (!feof($fp)) {
+ $content .= fread($fp, 8192);
+ }
+
+ $sql = $id > 0
+ ? 'REPLACE INTO %s (id, parent_id, name, content, size, mtime, mime, width, height) VALUES ('.$id.', %d, "%s", "%s", %d, %d, "%s", %d, %d)'
+ : 'INSERT INTO %s (parent_id, name, content, size, mtime, mime, width, height) VALUES (%d, "%s", "%s", %d, %d, "%s", %d, %d)';
+ $sql = sprintf($sql, $this->tbf, $dir, $this->db->real_escape_string($name), $this->db->real_escape_string($content), $size, time(), $mime, $w, $h);
+
+ unset($content);
+
+ if ($this->query($sql)) {
+ return $id > 0 ? $id : $this->db->insert_id;
+ }
+
+ return false;
+ }
+
+ /**
+ * Get file contents
+ *
+ * @param string $path file path
+ * @return string|false
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _getContents($path) {
+ return ($res = $this->query(sprintf('SELECT content FROM %s WHERE id=%d', $this->tbf, $path))) && ($r = $res->fetch_assoc()) ? $r['content'] : false;
+ }
+
+ /**
+ * Write a string to a file
+ *
+ * @param string $path file path
+ * @param string $content new file content
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _filePutContents($path, $content) {
+ return $this->query(sprintf('UPDATE %s SET content="%s", size=%d, mtime=%d WHERE id=%d LIMIT 1', $this->tbf, $this->db->real_escape_string($content), strlen($content), time(), $path));
+ }
+
+ /**
+ * Detect available archivers
+ *
+ * @return void
+ **/
+ protected function _checkArchivers() {
+ return;
+ }
+
+ /**
+ * Unpack archive
+ *
+ * @param string $path archive path
+ * @param array $arc archiver command and arguments (same as in $this->archivers)
+ * @return void
+ * @author Dmitry (dio) Levashov
+ * @author Alexey Sukhotin
+ **/
+ protected function _unpack($path, $arc) {
+ return;
+ }
+
+ /**
+ * Recursive symlinks search
+ *
+ * @param string $path file/dir path
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _findSymlinks($path) {
+ return false;
+ }
+
+ /**
+ * Extract files from archive
+ *
+ * @param string $path archive path
+ * @param array $arc archiver command and arguments (same as in $this->archivers)
+ * @return true
+ * @author Dmitry (dio) Levashov,
+ * @author Alexey Sukhotin
+ **/
+ protected function _extract($path, $arc) {
+ return false;
+ }
+
+ /**
+ * Create archive and return its path
+ *
+ * @param string $dir target dir
+ * @param array $files files names list
+ * @param string $name archive name
+ * @param array $arc archiver options
+ * @return string|bool
+ * @author Dmitry (dio) Levashov,
+ * @author Alexey Sukhotin
+ **/
+ protected function _archive($dir, $files, $name, $arc) {
+ return false;
+ }
+
+} // END class
diff --git a/app/mihaildev/elfinder/php/elFinderVolumeS3.class.php b/app/mihaildev/elfinder/php/elFinderVolumeS3.class.php
new file mode 100755
index 0000000..52ad19a
--- /dev/null
+++ b/app/mihaildev/elfinder/php/elFinderVolumeS3.class.php
@@ -0,0 +1,732 @@
+ '',
+ 'secretkey' => '',
+ 'bucket' => '',
+ 'tmpPath' => '',
+ );
+ $this->options = array_merge($this->options, $opts);
+ $this->options['mimeDetect'] = 'internal';
+
+ }
+
+
+ protected function init() {
+ if (!$this->options['accesskey']
+ || !$this->options['secretkey']
+ || !$this->options['bucket']) {
+ return $this->setError('Required options undefined.');
+ }
+
+ $this->s3 = new S3SoapClient($this->options['accesskey'], $this->options['secretkey']);
+
+ $this->root = $this->options['path'];
+
+ $this->rootName = 's3';
+
+ return true;
+ }
+
+ protected function configure() {
+ parent::configure();
+ if (!empty($this->options['tmpPath'])) {
+ if ((is_dir($this->options['tmpPath']) || @mkdir($this->options['tmpPath'])) && is_writable($this->options['tmpPath'])) {
+ $this->tmpPath = $this->options['tmpPath'];
+ }
+ }
+ $this->mimeDetect = 'internal';
+ }
+
+ /**
+ * Return parent directory path
+ *
+ * @param string $path file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _dirname($path) {
+
+ $newpath = preg_replace("/\/$/", "", $path);
+ $dn = substr($path, 0, strrpos($newpath, '/')) ;
+
+ if (substr($dn, 0, 1) != '/') {
+ $dn = "/$dn";
+ }
+
+ return $dn;
+ }
+
+ /**
+ * Return file name
+ *
+ * @param string $path file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _basename($path) {
+ return basename($path);
+ }
+
+
+
+ /**
+ * Join dir name and file name and return full path.
+ * Some drivers (db) use int as path - so we give to concat path to driver itself
+ *
+ * @param string $dir dir path
+ * @param string $name file name
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _joinPath($dir, $name) {
+ return $dir.DIRECTORY_SEPARATOR.$name;
+ }
+
+ /**
+ * Return normalized path, this works the same as os.path.normpath() in Python
+ *
+ * @param string $path path
+ * @return string
+ * @author Troex Nevelin
+ **/
+ protected function _normpath($path) {
+ $tmp = preg_replace("/^\//", "", $path);
+ $tmp = preg_replace("/\/\//", "/", $tmp);
+ $tmp = preg_replace("/\/$/", "", $tmp);
+ return $tmp;
+ }
+
+ /**
+ * Return file path related to root dir
+ *
+ * @param string $path file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _relpath($path) {
+
+
+ $newpath = $path;
+
+
+ if (substr($path, 0, 1) != '/') {
+ $newpath = "/$newpath";
+ }
+
+ $newpath = preg_replace("/\/$/", "", $newpath);
+
+ $ret = ($newpath == $this->root) ? '' : substr($newpath, strlen($this->root)+1);
+
+ return $ret;
+ }
+
+ /**
+ * Convert path related to root dir into real path
+ *
+ * @param string $path file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _abspath($path) {
+ return $path == $this->separator ? $this->root : $this->root.$this->separator.$path;
+ }
+
+ /**
+ * Return fake path started from root dir
+ *
+ * @param string $path file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _path($path) {
+ return $this->rootName.($path == $this->root ? '' : $this->separator.$this->_relpath($path));
+ }
+
+ /**
+ * Return true if $path is children of $parent
+ *
+ * @param string $path path to check
+ * @param string $parent parent path
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _inpath($path, $parent) {
+ return $path == $parent || strpos($path, $parent.'/') === 0;
+ }
+
+
+ /**
+ * Converting array of objects with name and value properties to
+ * array[key] = value
+ * @param array $metadata source array
+ * @return array
+ * @author Alexey Sukhotin
+ **/
+ protected function metaobj2array($metadata) {
+ $arr = array();
+
+ if (is_array($metadata)) {
+ foreach ($metadata as $meta) {
+ $arr[$meta->Name] = $meta->Value;
+ }
+ } else {
+ $arr[$metadata->Name] = $metadata->Value;
+ }
+ return $arr;
+ }
+
+ /**
+ * Return stat for given path.
+ * Stat contains following fields:
+ * - (int) size file size in b. required
+ * - (int) ts file modification time in unix time. required
+ * - (string) mime mimetype. required for folders, others - optionally
+ * - (bool) read read permissions. required
+ * - (bool) write write permissions. required
+ * - (bool) locked is object locked. optionally
+ * - (bool) hidden is object hidden. optionally
+ * - (string) alias for symlinks - link target path relative to root path. optionally
+ * - (string) target for symlinks - link target path. optionally
+ *
+ * If file does not exists - returns empty array or false.
+ *
+ * @param string $path file path
+ * @return array|false
+ * @author Dmitry (dio) Levashov,
+ * @author Alexey Sukhotin
+ **/
+ protected function _stat($path) {
+
+ $stat = array(
+ 'size' => 0,
+ 'ts' => time(),
+ 'read' => true,
+ 'write' => true,
+ 'locked' => false,
+ 'hidden' => false,
+ 'mime' => 'directory',
+ );
+
+
+ if ($this->root == $path) {
+ return $stat;
+ }
+
+
+ $np = $this->_normpath($path);
+
+ try {
+ $obj = $this->s3->GetObject(array('Bucket' => $this->options['bucket'], 'Key' => $np , 'GetMetadata' => true, 'InlineData' => false, 'GetData' => false));
+ } catch (Exception $e) {
+
+ }
+
+ if (!isset($obj) || ($obj->GetObjectResponse->Status->Code != 200)) {
+ $np .= '/';
+ try {
+ $obj = $this->s3->GetObject(array('Bucket' => $this->options['bucket'], 'Key' => $np , 'GetMetadata' => true, 'InlineData' => false, 'GetData' => false));
+ } catch (Exception $e) {
+
+ }
+ }
+
+ if (!(isset($obj) && $obj->GetObjectResponse->Status->Code == 200)) {
+ return array();
+ }
+
+ $mime = '';
+
+ $metadata = $this->metaobj2array($obj->GetObjectResponse->Metadata);
+
+ $mime = $metadata['Content-Type'];
+
+ if (!empty($mime)) {
+ $stat['mime'] = ($mime == 'binary/octet-stream') ? 'directory' : $mime;
+ }
+
+ if (isset($obj->GetObjectResponse->LastModified)) {
+ $stat['ts'] = strtotime($obj->GetObjectResponse->LastModified);
+ }
+
+ try {
+ $files = $this->s3->ListBucket(array('Bucket' => $this->options['bucket'], 'Prefix' => $np, 'Delimiter' => '/'))->ListBucketResponse->Contents;
+ } catch (Exception $e) {
+
+ }
+
+ if (!is_array($files)) {
+ $files = array($files);
+ }
+
+ foreach ($files as $file) {
+ if ($file->Key == $np) {
+ $stat['size'] = $file->Size;
+ }
+ }
+
+ return $stat;
+ }
+
+
+
+ /***************** file stat ********************/
+
+
+ /**
+ * Return true if path is dir and has at least one childs directory
+ *
+ * @param string $path dir path
+ * @return bool
+ * @author Alexey Sukhotin
+ **/
+ protected function _subdirs($path) {
+ $stat = $this->_stat($path);
+
+ if ($stat['mime'] == 'directory') {
+ $files = $this->_scandir($path);
+ foreach ($files as $file) {
+ $fstat = $this->_stat($file);
+ if ($fstat['mime'] == 'directory') {
+ return true;
+ }
+ }
+
+ }
+
+ return false;
+ }
+
+ /**
+ * Return object width and height
+ * Ususaly used for images, but can be realize for video etc...
+ *
+ * @param string $path file path
+ * @param string $mime file mime type
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _dimensions($path, $mime) {
+ return false;
+ }
+
+ /******************** file/dir content *********************/
+
+ /**
+ * Return files list in directory
+ *
+ * @param string $path dir path
+ * @return array
+ * @author Dmitry (dio) Levashov,
+ * @author Alexey Sukhotin
+ **/
+ protected function _scandir($path) {
+
+ $s3path = preg_replace("/^\//", "", $path) . '/';
+
+ $files = $this->s3->ListBucket(array('Bucket' => $this->options['bucket'], 'delimiter' => '/', 'Prefix' => $s3path))->ListBucketResponse->Contents;
+
+ $finalfiles = array();
+
+ foreach ($files as $file) {
+ if (preg_match("|^" . $s3path . "[^/]*/?$|", $file->Key)) {
+ $fname = preg_replace("/\/$/", "", $file->Key);
+ $fname = $file->Key;
+
+ if ($fname != preg_replace("/\/$/", "", $s3path)) {
+
+ }
+
+ $finalfiles[] = $fname;
+ }
+ }
+
+ sort($finalfiles);
+ return $finalfiles;
+ }
+
+ /**
+ * Return temporary file path for required file
+ *
+ * @param string $path file path
+ * @return string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function tmpname($path) {
+ return $this->tmpPath.DIRECTORY_SEPARATOR.md5($path);
+ }
+
+ /**
+ * Open file and return file pointer
+ *
+ * @param string $path file path
+ * @param bool $write open file for writing
+ * @return resource|false
+ * @author Dmitry (dio) Levashov,
+ * @author Alexey Sukhotin
+ **/
+ protected function _fopen($path, $mode="rb") {
+
+ $tn = $this->tmpname($path);
+
+ $fp = $this->tmbPath
+ ? @fopen($tn, 'w+')
+ : @tmpfile();
+
+
+ if ($fp) {
+
+ try {
+ $obj = $this->s3->GetObject(array('Bucket' => $this->options['bucket'], 'Key' => $this->_normpath($path) , 'GetMetadata' => true, 'InlineData' => true, 'GetData' => true));
+ } catch (Exception $e) {
+
+ }
+
+ $mime = '';
+
+ $metadata = $this->metaobj2array($obj->GetObjectResponse->Metadata);
+
+ fwrite($fp, $obj->GetObjectResponse->Data);
+ rewind($fp);
+ return $fp;
+ }
+
+ return false;
+ }
+
+ /**
+ * Close opened file
+ *
+ * @param resource $fp file pointer
+ * @param string $path file path
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _fclose($fp, $path='') {
+ @fclose($fp);
+ if ($path) {
+ @unlink($this->tmpname($path));
+ }
+ }
+
+ /******************** file/dir manipulations *************************/
+
+ /**
+ * Create dir and return created dir path or false on failed
+ *
+ * @param string $path parent dir path
+ * @param string $name new directory name
+ * @return string|bool
+ * @author Dmitry (dio) Levashov,
+ * @author Alexey Sukhotin
+ **/
+ protected function _mkdir($path, $name) {
+
+ $newkey = $this->_normpath($path);
+ $newkey = preg_replace("/\/$/", "", $newkey);
+ $newkey = "$newkey/$name/";
+
+ try {
+ $obj = $this->s3->PutObjectInline(array('Bucket' => $this->options['bucket'], 'Key' => $newkey , 'ContentLength' => 0, 'Data' => ''));
+ } catch (Exception $e) {
+
+ }
+
+ if (isset($obj)) {
+ return "$path/$name";
+ }
+
+ return false;
+ }
+
+ /**
+ * Create file and return it's path or false on failed
+ *
+ * @param string $path parent dir path
+ * @param string $name new file name
+ * @return string|bool
+ * @author Dmitry (dio) Levashov,
+ * @author Alexey Sukhotin
+ **/
+ protected function _mkfile($path, $name) {
+ $newkey = $this->_normpath($path);
+ $newkey = preg_replace("/\/$/", "", $newkey);
+ $newkey = "$newkey/$name";
+
+ try {
+ $obj = $this->s3->PutObjectInline(array('Bucket' => $this->options['bucket'], 'Key' => $newkey , 'ContentLength' => 0, 'Data' => '', 'Metadata' => array(array('Name' => 'Content-Type', 'Value' => 'text/plain'))));
+ } catch (Exception $e) {
+
+ }
+
+ if (isset($obj)) {
+ return "$path/$name";
+ }
+
+ return false;
+
+ }
+
+ /**
+ * Create symlink
+ *
+ * @param string $source file to link to
+ * @param string $targetDir folder to create link in
+ * @param string $name symlink name
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _symlink($source, $targetDir, $name) {
+ return false;
+ }
+
+ /**
+ * Copy file into another file (only inside one volume)
+ *
+ * @param string $source source file path
+ * @param string $target target dir path
+ * @param string $name file name
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _copy($source, $targetDir, $name) {
+ return false;
+ }
+
+ /**
+ * Move file into another parent dir.
+ * Return new file path or false.
+ *
+ * @param string $source source file path
+ * @param string $target target dir path
+ * @param string $name file name
+ * @return string|bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _move($source, $targetDir, $name) {
+ return false;
+ }
+
+ /**
+ * Remove file
+ *
+ * @param string $path file path
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _unlink($path) {
+
+ $newkey = $this->_normpath($path);
+ $newkey = preg_replace("/\/$/", "", $newkey);
+
+ try {
+ $obj = $this->s3->DeleteObject(array('Bucket' => $this->options['bucket'], 'Key' => $newkey));
+ } catch (Exception $e) {
+
+ }
+
+ /*$fp = fopen('/tmp/eltest.txt','a+');
+
+ fwrite($fp, 'key='.$newkey);*/
+
+ if (is_object($obj)) {
+ //fwrite($fp, 'obj='.var_export($obj,true));
+
+ if (isset($obj->DeleteObjectResponse->Code)) {
+ $rc = $obj->DeleteObjectResponse->Code;
+
+ if (substr($rc, 0, 1) == '2') {
+ return true;
+ }
+ }
+ }
+
+
+ //fclose($fp);
+
+ return false;
+ }
+
+ /**
+ * Remove dir
+ *
+ * @param string $path dir path
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _rmdir($path) {
+ return $this->_unlink($path . '/');
+ }
+
+ /**
+ * Create new file and write into it from file pointer.
+ * Return new file path or false on error.
+ *
+ * @param resource $fp file pointer
+ * @param string $dir target dir path
+ * @param string $name file name
+ * @return bool|string
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _save($fp, $dir, $name, $mime, $w, $h) {
+ return false;
+ }
+
+ /**
+ * Get file contents
+ *
+ * @param string $path file path
+ * @return string|false
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _getContents($path) {
+ return false;
+ }
+
+ /**
+ * Write a string to a file
+ *
+ * @param string $path file path
+ * @param string $content new file content
+ * @return bool
+ * @author Dmitry (dio) Levashov
+ **/
+ protected function _filePutContents($path, $content) {
+ return false;
+ }
+
+ /**
+ * Extract files from archive
+ *
+ * @param string $path file path
+ * @param array $arc archiver options
+ * @return bool
+ * @author Dmitry (dio) Levashov,
+ * @author Alexey Sukhotin
+ **/
+ protected function _extract($path, $arc) {
+ return false;
+ }
+
+ /**
+ * Create archive and return its path
+ *
+ * @param string $dir target dir
+ * @param array $files files names list
+ * @param string $name archive name
+ * @param array $arc archiver options
+ * @return string|bool
+ * @author Dmitry (dio) Levashov,
+ * @author Alexey Sukhotin
+ **/
+ protected function _archive($dir, $files, $name, $arc) {
+ return false;
+ }
+
+ /**
+ * Detect available archivers
+ *
+ * @return void
+ * @author Dmitry (dio) Levashov,
+ * @author Alexey Sukhotin
+ **/
+ protected function _checkArchivers() {
+
+ }
+
+}
+
+/**
+ * SoapClient extension with Amazon S3 WSDL and request signing support
+ *
+ * @author Alexey Sukhotin
+ **/
+class S3SoapClient extends SoapClient {
+
+ private $accesskey = '';
+ private $secretkey = '';
+ public $client = NULL;
+
+
+ public function __construct($key = '', $secret = '') {
+ $this->accesskey = $key;
+ $this->secretkey = $secret;
+ parent::__construct('http://s3.amazonaws.com/doc/2006-03-01/AmazonS3.wsdl');
+ }
+
+
+ /**
+ * Method call wrapper which adding S3 signature and default arguments to all S3 operations
+ *
+ * @author Alexey Sukhotin
+ **/
+ public function __call($method, $arguments) {
+
+ /* Getting list of S3 web service functions which requires signing */
+ $funcs = $this->__getFunctions();
+
+ $funcnames = array();
+
+ foreach ($funcs as $func) {
+ preg_match("/\S+\s+([^\)]+)\(/", $func, $m);
+
+ if (isset($m[1])) {
+ $funcnames[] = $m[1];
+ }
+ }
+
+ /* adding signature to arguments */
+ if (in_array("{$method}", $funcnames)) {
+
+ if (is_array($arguments[0])) {
+ $arguments[0] = array_merge($arguments[0], $this->sign("{$method}"));
+ } else {
+ $arguments[0] = $this->sign("{$method}");
+ }
+
+ }
+
+ /*$fp = fopen('/tmp/s3debug.txt', 'a+');
+ fwrite($fp, 'method='."{$method}". ' timestamp='.date('Y-m-d H:i:s').' args='.var_export($arguments,true) . "\n");
+ fclose($fp);*/
+ return parent::__call($method, $arguments);
+ }
+
+ /**
+ * Generating signature and timestamp for specified S3 operation
+ *
+ * @param string $operation S3 operation name
+ * @return array
+ * @author Alexey Sukhotin
+ **/
+ protected function sign($operation) {
+
+ $params = array(
+ 'AWSAccessKeyId' => $this->accesskey,
+ 'Timestamp' => gmdate('Y-m-d\TH:i:s.000\Z'),
+ );
+
+ $sign_str = 'AmazonS3' . $operation . $params['Timestamp'];
+
+ $params['Signature'] = base64_encode(hash_hmac('sha1', $sign_str, $this->secretkey, TRUE));
+
+ return $params;
+ }
+
+}
+
+?>
diff --git a/app/mihaildev/elfinder/php/mime.types b/app/mihaildev/elfinder/php/mime.types
new file mode 100755
index 0000000..94b99b7
--- /dev/null
+++ b/app/mihaildev/elfinder/php/mime.types
@@ -0,0 +1,512 @@
+# This file controls what Internet media types are sent to the client for
+# given file extension(s). Sending the correct media type to the client
+# is important so they know how to handle the content of the file.
+# For more information about Internet media types, please read
+# RFC 2045, 2046, 2047, 2048, and 2077. The Internet media type
+# registry is at .
+
+# MIME type Extension
+application/andrew-inset ez
+application/chemtool cht
+application/dicom dcm
+application/docbook+xml docbook
+application/ecmascript ecma
+application/flash-video flv
+application/illustrator ai
+application/javascript js
+application/mac-binhex40
+application/mathematica nb
+application/msword doc
+application/octet-stream bin
+application/oda oda
+application/ogg ogg
+application/pdf pdf
+application/pgp pgp
+application/pgp-encrypted
+application/pgp-encrypted pgp gpg
+application/pgp-keys
+application/pgp-keys skr pkr
+application/pgp-signature
+application/pgp-signature sig
+application/pkcs7-mime
+application/pkcs7-signature p7s
+application/postscript ps
+application/rtf rtf
+application/sdp sdp
+application/smil smil smi sml
+application/stuffit sit
+application/vnd.corel-draw cdr
+application/vnd.hp-hpgl hpgl
+application/vnd.hp-pcl pcl
+application/vnd.lotus-1-2-3 123 wk1 wk3 wk4 wks
+application/vnd.mozilla.xul+xml xul
+application/vnd.ms-excel xls xlc xll xlm xlw xla xlt xld
+application/vnd.ms-powerpoint ppz ppt pps pot
+application/vnd.oasis.opendocument.chart odc
+application/vnd.oasis.opendocument.database odb
+application/vnd.oasis.opendocument.formula odf
+application/vnd.oasis.opendocument.graphics odg
+application/vnd.oasis.opendocument.graphics-template otg
+application/vnd.oasis.opendocument.image odi
+application/vnd.oasis.opendocument.presentation odp
+application/vnd.oasis.opendocument.presentation-template otp
+application/vnd.oasis.opendocument.spreadsheet ods
+application/vnd.oasis.opendocument.spreadsheet-template ots
+application/vnd.oasis.opendocument.text odt
+application/vnd.oasis.opendocument.text-master odm
+application/vnd.oasis.opendocument.text-template ott
+application/vnd.oasis.opendocument.text-web oth
+application/vnd.palm pdb
+application/vnd.rn-realmedia
+application/vnd.rn-realmedia rm
+application/vnd.rn-realmedia-secure rms
+application/vnd.rn-realmedia-vbr rmvb
+application/vnd.stardivision.calc sdc
+application/vnd.stardivision.chart sds
+application/vnd.stardivision.draw sda
+application/vnd.stardivision.impress sdd sdp
+application/vnd.stardivision.mail smd
+application/vnd.stardivision.math smf
+application/vnd.stardivision.writer sdw vor sgl
+application/vnd.sun.xml.calc sxc
+application/vnd.sun.xml.calc.template stc
+application/vnd.sun.xml.draw sxd
+application/vnd.sun.xml.draw.template std
+application/vnd.sun.xml.impress sxi
+application/vnd.sun.xml.impress.template sti
+application/vnd.sun.xml.math sxm
+application/vnd.sun.xml.writer sxw
+application/vnd.sun.xml.writer.global sxg
+application/vnd.sun.xml.writer.template stw
+application/vnd.wordperfect wpd
+application/x-abiword abw abw.CRASHED abw.gz zabw
+application/x-amipro sam
+application/x-anjuta-project prj
+application/x-applix-spreadsheet as
+application/x-applix-word aw
+application/x-arc
+application/x-archive a
+application/x-arj arj
+application/x-asax asax
+application/x-ascx ascx
+application/x-ashx ashx
+application/x-asix asix
+application/x-asmx asmx
+application/x-asp asp
+application/x-awk
+application/x-axd axd
+application/x-bcpio bcpio
+application/x-bittorrent torrent
+application/x-blender blender blend BLEND
+application/x-bzip bz bz2
+application/x-bzip bz2 bz
+application/x-bzip-compressed-tar tar.bz tar.bz2
+application/x-bzip-compressed-tar tar.bz tar.bz2 tbz tbz2
+application/x-cd-image iso
+application/x-cgi cgi
+application/x-chess-pgn pgn
+application/x-chm chm
+application/x-class-file
+application/x-cmbx cmbx
+application/x-compress Z
+application/x-compressed-tar tar.gz tar.Z tgz taz
+application/x-compressed-tar tar.gz tgz
+application/x-config config
+application/x-core
+application/x-cpio cpio
+application/x-cpio-compressed cpio.gz
+application/x-csh csh
+application/x-cue cue
+application/x-dbase dbf
+application/x-dbm
+application/x-dc-rom dc
+application/x-deb deb
+application/x-designer ui
+application/x-desktop desktop kdelnk
+application/x-devhelp devhelp
+application/x-dia-diagram dia
+application/x-disco disco
+application/x-dvi dvi
+application/x-e-theme etheme
+application/x-egon egon
+application/x-executable exe
+application/x-font-afm afm
+application/x-font-bdf bdf
+application/x-font-dos
+application/x-font-framemaker
+application/x-font-libgrx
+application/x-font-linux-psf psf
+application/x-font-otf
+application/x-font-pcf pcf
+application/x-font-pcf pcf.gz
+application/x-font-speedo spd
+application/x-font-sunos-news
+application/x-font-tex
+application/x-font-tex-tfm
+application/x-font-ttf ttc TTC
+application/x-font-ttf ttf
+application/x-font-type1 pfa pfb gsf pcf.Z
+application/x-font-vfont
+application/x-frame
+application/x-frontline aop
+application/x-gameboy-rom gb
+application/x-gdbm
+application/x-gdesklets-display display
+application/x-genesis-rom gen md
+application/x-gettext-translation gmo
+application/x-glabels glabels
+application/x-glade glade
+application/x-gmc-link
+application/x-gnome-db-connection connection
+application/x-gnome-db-database database
+application/x-gnome-stones caves
+application/x-gnucash gnucash gnc xac
+application/x-gnumeric gnumeric
+application/x-graphite gra
+application/x-gtar gtar
+application/x-gtktalog
+application/x-gzip gz
+application/x-gzpostscript ps.gz
+application/x-hdf hdf
+application/x-ica ica
+application/x-ipod-firmware
+application/x-jamin jam
+application/x-jar jar
+application/x-java class
+application/x-java-archive jar ear war
+
+application/x-jbuilder-project jpr jpx
+application/x-karbon karbon
+application/x-kchart chrt
+application/x-kformula kfo
+application/x-killustrator kil
+application/x-kivio flw
+application/x-kontour kon
+application/x-kpovmodeler kpm
+application/x-kpresenter kpr kpt
+application/x-krita kra
+application/x-kspread ksp
+application/x-kspread-crypt
+application/x-ksysv-package
+application/x-kugar kud
+application/x-kword kwd kwt
+application/x-kword-crypt
+application/x-lha lha lzh
+application/x-lha lzh
+application/x-lhz lhz
+application/x-linguist ts
+application/x-lyx lyx
+application/x-lzop lzo
+application/x-lzop-compressed-tar tar.lzo tzo
+application/x-macbinary
+application/x-machine-config
+application/x-magicpoint mgp
+application/x-master-page master
+application/x-matroska mkv
+application/x-mdp mdp
+application/x-mds mds
+application/x-mdsx mdsx
+application/x-mergeant mergeant
+application/x-mif mif
+application/x-mozilla-bookmarks
+application/x-mps mps
+application/x-ms-dos-executable exe
+application/x-mswinurl
+application/x-mswrite wri
+application/x-msx-rom msx
+application/x-n64-rom n64
+application/x-nautilus-link
+application/x-nes-rom nes
+application/x-netcdf cdf nc
+application/x-netscape-bookmarks
+application/x-object o
+application/x-ole-storage
+application/x-oleo oleo
+application/x-palm-database
+application/x-palm-database pdb prc
+application/x-par2 PAR2 par2
+application/x-pef-executable
+application/x-perl pl pm al perl
+application/x-php php php3 php4
+application/x-pkcs12 p12 pfx
+application/x-planner planner mrproject
+application/x-planperfect pln
+application/x-prjx prjx
+application/x-profile
+application/x-ptoptimizer-script pto
+application/x-pw pw
+application/x-python-bytecode pyc pyo
+application/x-quattro-pro wb1 wb2 wb3
+application/x-quattropro wb1 wb2 wb3
+application/x-qw qif
+application/x-rar rar
+application/x-rar-compressed rar
+application/x-rdp rdp
+application/x-reject rej
+application/x-remoting rem
+application/x-resources resources
+application/x-resourcesx resx
+application/x-rpm rpm
+application/x-ruby
+application/x-sc
+application/x-sc sc
+application/x-scribus sla sla.gz scd scd.gz
+application/x-shar shar
+application/x-shared-library-la la
+application/x-sharedlib so
+application/x-shellscript sh
+application/x-shockwave-flash swf
+application/x-siag siag
+application/x-slp
+application/x-smil kino
+application/x-smil smi smil
+application/x-sms-rom sms gg
+application/x-soap-remoting soap
+application/x-streamingmedia ssm
+application/x-stuffit
+application/x-stuffit bin sit
+application/x-sv4cpio sv4cpio
+application/x-sv4crc sv4crc
+application/x-tar tar
+application/x-tarz tar.Z
+application/x-tex-gf gf
+application/x-tex-pk k
+application/x-tgif obj
+application/x-theme theme
+application/x-toc toc
+application/x-toutdoux
+application/x-trash bak old sik
+application/x-troff tr roff t
+application/x-troff-man man
+application/x-troff-man-compressed
+application/x-tzo tar.lzo tzo
+application/x-ustar ustar
+application/x-wais-source src
+application/x-web-config
+application/x-wpg wpg
+application/x-wsdl wsdl
+application/x-x509-ca-cert der cer crt cert pem
+application/x-xbel xbel
+application/x-zerosize
+application/x-zoo zoo
+application/xhtml+xml xhtml
+application/zip zip
+audio/ac3 ac3
+audio/basic au snd
+audio/midi mid midi
+audio/mpeg mp3
+audio/prs.sid sid psid
+audio/vnd.rn-realaudio ra
+audio/x-aac aac
+audio/x-adpcm
+audio/x-aifc
+audio/x-aiff aif aiff
+audio/x-aiff aiff aif aifc
+audio/x-aiffc
+audio/x-flac flac
+audio/x-m4a m4a
+audio/x-mod mod ult uni XM m15 mtm 669
+audio/x-mp3-playlist
+audio/x-mpeg
+audio/x-mpegurl m3u
+audio/x-ms-asx
+audio/x-pn-realaudio ra ram rm
+audio/x-pn-realaudio ram rmm
+audio/x-riff
+audio/x-s3m s3m
+audio/x-scpls pls
+audio/x-scpls pls xpl
+audio/x-stm stm
+audio/x-voc voc
+audio/x-wav wav
+audio/x-xi xi
+audio/x-xm xm
+image/bmp bmp
+image/cgm cgm
+image/dpx
+image/fax-g3 g3
+image/g3fax
+image/gif gif
+image/ief ief
+image/jpeg jpeg jpg jpe
+image/jpeg2000 jp2
+image/png png
+image/rle rle
+image/svg+xml svg
+image/tiff tif tiff
+image/vnd.djvu djvu djv
+image/vnd.dwg dwg
+image/vnd.dxf dxf
+image/x-3ds 3ds
+image/x-applix-graphics ag
+image/x-cmu-raster ras
+image/x-compressed-xcf xcf.gz xcf.bz2
+image/x-dcraw bay BAY bmq BMQ cr2 CR2 crw CRW cs1 CS1 dc2 DC2 dcr DCR fff FFF k25 K25 kdc KDC mos MOS mrw MRW nef NEF orf ORF pef PEF raf RAF rdc RDC srf SRF x3f X3F
+image/x-dib
+image/x-eps eps epsi epsf
+image/x-fits fits
+image/x-fpx
+image/x-icb icb
+image/x-ico ico
+image/x-iff iff
+image/x-ilbm ilbm
+image/x-jng jng
+image/x-lwo lwo lwob
+image/x-lws lws
+image/x-msod msod
+image/x-niff
+image/x-pcx
+image/x-photo-cd pcd
+image/x-pict pict pict1 pict2
+image/x-portable-anymap pnm
+image/x-portable-bitmap pbm
+image/x-portable-graymap pgm
+image/x-portable-pixmap ppm
+image/x-psd psd
+image/x-rgb rgb
+image/x-sgi sgi
+image/x-sun-raster sun
+image/x-tga tga
+image/x-win-bitmap cur
+image/x-wmf wmf
+image/x-xbitmap xbm
+image/x-xcf xcf
+image/x-xfig fig
+image/x-xpixmap xpm
+image/x-xwindowdump xwd
+inode/blockdevice
+inode/chardevice
+inode/directory
+inode/fifo
+inode/mount-point
+inode/socket
+inode/symlink
+message/delivery-status
+message/disposition-notification
+message/external-body
+message/news
+message/partial
+message/rfc822
+message/x-gnu-rmail
+model/vrml wrl
+multipart/alternative
+multipart/appledouble
+multipart/digest
+multipart/encrypted
+multipart/mixed
+multipart/related
+multipart/report
+multipart/signed
+multipart/x-mixed-replace
+text/calendar vcs ics
+text/css css CSSL
+text/directory vcf vct gcrd
+text/enriched
+text/html html htm
+text/htmlh
+text/mathml mml
+text/plain txt asc
+text/rdf rdf
+text/rfc822-headers
+text/richtext rtx
+text/rss rss
+text/sgml sgml sgm
+text/spreadsheet sylk slk
+text/tab-separated-values tsv
+text/vnd.rn-realtext rt
+text/vnd.wap.wml wml
+text/x-adasrc adb ads
+text/x-authors
+text/x-bibtex bib
+text/x-boo boo
+text/x-c++hdr hh
+text/x-c++src cpp cxx cc C c++
+text/x-chdr h h++ hp
+text/x-comma-separated-values csv
+text/x-copying
+text/x-credits
+text/x-csrc c
+text/x-dcl dcl
+text/x-dsl dsl
+text/x-dsrc d
+text/x-dtd dtd
+text/x-emacs-lisp el
+text/x-fortran f
+text/x-gettext-translation po
+text/x-gettext-translation-template pot
+text/x-gtkrc
+text/x-haskell hs
+text/x-idl idl
+text/x-install
+text/x-java java
+text/x-js js
+text/x-ksysv-log
+text/x-literate-haskell lhs
+text/x-log log
+text/x-makefile
+text/x-moc moc
+text/x-msil il
+text/x-nemerle n
+text/x-objcsrc m
+text/x-pascal p pas
+text/x-patch diff patch
+text/x-python py
+text/x-readme
+text/x-rng rng
+text/x-scheme scm
+text/x-setext etx
+text/x-speech
+text/x-sql sql
+text/x-suse-ymp ymp
+text/x-suse-ymu ymu
+text/x-tcl tcl tk
+text/x-tex tex ltx sty cls
+text/x-texinfo texi texinfo
+text/x-texmacs tm ts
+text/x-troff-me me
+text/x-troff-mm mm
+text/x-troff-ms ms
+text/x-uil uil
+text/x-uri uri url
+text/x-vb vb
+text/x-xds xds
+text/x-xmi xmi
+text/x-xsl xsl
+text/x-xslfo fo xslfo
+text/x-xslt xslt xsl
+text/xmcd
+text/xml xml
+video/3gpp 3gp
+video/dv dv dif
+video/isivideo
+video/mpeg mpeg mpg mp2 mpe vob dat
+video/quicktime qt mov moov qtvr
+video/vivo
+video/vnd.rn-realvideo rv
+video/wavelet
+video/x-3gpp2 3g2
+video/x-anim anim[1-9j]
+video/x-avi
+video/x-flic fli flc
+video/x-mng mng
+video/x-ms-asf asf asx
+video/x-ms-wmv wmv
+video/x-msvideo avi
+video/x-nsv nsv NSV
+video/x-real-video
+video/x-sgi-movie movie
+application/x-java-jnlp-file jnlp
+application/vnd.openxmlformats-officedocument.wordprocessingml.document docx
+application/vnd.openxmlformats-officedocument.wordprocessingml.template dotx
+application/vnd.ms-word.document.macroEnabled.12 docm
+application/vnd.ms-word.template.macroEnabled.12 dotm
+application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx
+application/vnd.openxmlformats-officedocument.spreadsheetml.template xltx
+application/vnd.ms-excel.sheet.macroEnabled.12 xlsm
+application/vnd.ms-excel.template.macroEnabled.12 xltm
+application/vnd.ms-excel.addin.macroEnabled.12 xlam
+application/vnd.ms-excel.sheet.binary.macroEnabled.12 xlsb
+application/vnd.openxmlformats-officedocument.presentationml.presentation pptx
+application/vnd.openxmlformats-officedocument.presentationml.template potx
+application/vnd.openxmlformats-officedocument.presentationml.slideshow ppsx
+application/vnd.ms-powerpoint.addin.macroEnabled.12 ppam
diff --git a/app/mihaildev/elfinder/php/plugins/AutoResize/plugin.php b/app/mihaildev/elfinder/php/plugins/AutoResize/plugin.php
new file mode 100755
index 0000000..d9f0e67
--- /dev/null
+++ b/app/mihaildev/elfinder/php/plugins/AutoResize/plugin.php
@@ -0,0 +1,157 @@
+ true, // For control by volume driver
+ 'maxWidth' => 1024, // Path to Water mark image
+ 'maxHeight' => 1024, // Margin right pixel
+ 'quality' => 95, // JPEG image save quality
+ 'targetType' => IMG_GIF|IMG_JPG|IMG_PNG|IMG_WBMP // Target image formats ( bit-field )
+ );
+
+ $this->opts = array_merge($defaults, $opts);
+
+ }
+
+ public function onUpLoadPreSave(&$path, &$name, $src, $elfinder, $volume) {
+ $opts = $this->opts;
+ $volOpts = $volume->getOptionsPlugin('AutoResize');
+ if (is_array($volOpts)) {
+ $opts = array_merge($this->opts, $volOpts);
+ }
+
+ if (! $opts['enable']) {
+ return false;
+ }
+
+ $srcImgInfo = @getimagesize($src);
+ if ($srcImgInfo === false) {
+ return false;
+ }
+
+ // check target image type
+ $imgTypes = array(
+ IMAGETYPE_GIF => IMG_GIF,
+ IMAGETYPE_JPEG => IMG_JPEG,
+ IMAGETYPE_PNG => IMG_PNG,
+ IMAGETYPE_WBMP => IMG_WBMP,
+ );
+ if (! ($opts['targetType'] & $imgTypes[$srcImgInfo[2]])) {
+ return false;
+ }
+
+ if ($srcImgInfo[0] > $opts['maxWidth'] || $srcImgInfo[1] > $opts['maxHeight']) {
+ return $this->resize($src, $srcImgInfo, $opts['maxWidth'], $opts['maxHeight'], $opts['quality']);
+ }
+
+ return false;
+ }
+
+ private function resize($src, $srcImgInfo, $maxWidth, $maxHeight, $quality) {
+ $zoom = min(($maxWidth/$srcImgInfo[0]),($maxHeight/$srcImgInfo[1]));
+ $width = round($srcImgInfo[0] * $zoom);
+ $height = round($srcImgInfo[1] * $zoom);
+
+ if (class_exists('Imagick')) {
+ return $this->resize_imagick($src, $width, $height, $quality);
+ } else {
+ return $this->resize_gd($src, $width, $height, $quality, $srcImgInfo);
+ }
+ }
+
+ private function resize_gd($src, $width, $height, $quality, $srcImgInfo) {
+ switch ($srcImgInfo['mime']) {
+ case 'image/gif':
+ if (@imagetypes() & IMG_GIF) {
+ $oSrcImg = @imagecreatefromgif($src);
+ } else {
+ $ermsg = 'GIF images are not supported';
+ }
+ break;
+ case 'image/jpeg':
+ if (@imagetypes() & IMG_JPG) {
+ $oSrcImg = @imagecreatefromjpeg($src) ;
+ } else {
+ $ermsg = 'JPEG images are not supported';
+ }
+ break;
+ case 'image/png':
+ if (@imagetypes() & IMG_PNG) {
+ $oSrcImg = @imagecreatefrompng($src) ;
+ } else {
+ $ermsg = 'PNG images are not supported';
+ }
+ break;
+ case 'image/wbmp':
+ if (@imagetypes() & IMG_WBMP) {
+ $oSrcImg = @imagecreatefromwbmp($src);
+ } else {
+ $ermsg = 'WBMP images are not supported';
+ }
+ break;
+ default:
+ $oSrcImg = false;
+ $ermsg = $srcImgInfo['mime'].' images are not supported';
+ break;
+ }
+
+ if ($oSrcImg && false != ($tmp = imagecreatetruecolor($width, $height))) {
+
+ if (!imagecopyresampled($tmp, $oSrcImg, 0, 0, 0, 0, $width, $height, $srcImgInfo[0], $srcImgInfo[1])) {
+ return false;
+ }
+
+ switch ($srcImgInfo['mime']) {
+ case 'image/gif':
+ imagegif($tmp, $src);
+ break;
+ case 'image/jpeg':
+ imagejpeg($tmp, $src, $quality);
+ break;
+ case 'image/png':
+ if (function_exists('imagesavealpha') && function_exists('imagealphablending')) {
+ imagealphablending($tmp, false);
+ imagesavealpha($tmp, true);
+ }
+ imagepng($tmp, $src);
+ break;
+ case 'image/wbmp':
+ imagewbmp($tmp, $src);
+ break;
+ }
+
+ imagedestroy($oSrcImg);
+ imagedestroy($tmp);
+
+ return true;
+
+ }
+ return false;
+ }
+
+ private function resize_imagick($src, $width, $height, $quality) {
+ try {
+ $img = new imagick($src);
+
+ if (strtoupper($img->getImageFormat()) === 'JPEG') {
+ $img->setImageCompression(imagick::COMPRESSION_JPEG);
+ $img->setCompressionQuality($quality);
+ }
+
+ $img->resizeImage($width, $height, Imagick::FILTER_LANCZOS, true);
+
+ $result = $img->writeImage($src);
+
+ $img->clear();
+ $img->destroy();
+
+ return $result ? true : false;
+ } catch (Exception $e) {
+ return false;
+ }
+ }
+}
diff --git a/app/mihaildev/elfinder/php/plugins/Normalizer/plugin.php b/app/mihaildev/elfinder/php/plugins/Normalizer/plugin.php
new file mode 100755
index 0000000..6c61f73
--- /dev/null
+++ b/app/mihaildev/elfinder/php/plugins/Normalizer/plugin.php
@@ -0,0 +1,119 @@
+= 5.3.0, PECL intl >= 1.0.0)
+ * or PEAR package "I18N_UnicodeNormalizer"
+ *
+ * ex. binding, configure on connector options
+ * $opts = array(
+ * 'bind' => array(
+ * 'mkdir.pre mkfile.pre rename.pre' => 'Plugin.Normalizer.cmdPreprocess',
+ * 'upload.presave' => array(
+ * 'Plugin.Normalizer.onUpLoadPreSave'
+ * )
+ * ),
+ * // global configure (optional)
+ * 'plugin' => array(
+ * 'Normalizer' = array(
+ * 'enable' => true,
+ * 'nfc' => true,
+ * 'nfkc' => true
+ * )
+ * ),
+ * // each volume configure (optional)
+ * 'roots' => array(
+ * array(
+ * 'driver' => 'LocalFileSystem',
+ * 'path' => '/path/to/files/',
+ * 'URL' => 'http://localhost/to/files/'
+ * 'plugin' => array(
+ * 'Normalizer' = array(
+ * 'enable' => true,
+ * 'nfc' => true,
+ * 'nfkc' => true
+ * )
+ * )
+ * )
+ * )
+ * );
+ *
+ * @package elfinder
+ * @author Naoki Sawada
+ * @license New BSD
+ */
+class elFinderPluginNormalizer
+{
+ private $opts = array();
+
+ public function __construct($opts) {
+ $defaults = array(
+ 'enable' => true, // For control by volume driver
+ 'nfc' => true, // Canonical Decomposition followed by Canonical Composition
+ 'nfkc' => true // Compatibility Decomposition followed by Canonical
+ );
+
+ $this->opts = array_merge($defaults, $opts);
+ }
+
+ public function cmdPreprocess($cmd, &$args, $elfinder, $volume) {
+ $opts = $this->getOpts($volume);
+ if (! $opts['enable']) {
+ return false;
+ }
+
+ if (isset($args['name'])) {
+ $args['name'] = $this->normalize($args['name'], $opts);
+ }
+ return true;
+ }
+
+ public function onUpLoadPreSave(&$path, &$name, $src, $elfinder, $volume) {
+ $opts = $this->getOpts($volume);
+ if (! $opts['enable']) {
+ return false;
+ }
+
+ if ($path) {
+ $path = $this->normalize($path, $opts);
+ }
+ $name = $this->normalize($name, $opts);
+ return false;
+ }
+
+ private function getOpts($volume) {
+ $opts = $this->opts;
+ if (is_object($volume)) {
+ $volOpts = $volume->getOptionsPlugin('Normalizer');
+ if (is_array($volOpts)) {
+ $opts = array_merge($this->opts, $volOpts);
+ }
+ }
+ return $opts;
+ }
+
+ private function normalize($str, $opts) {
+ if (class_exists('Normalizer')) {
+ if ($opts['nfc'] && ! Normalizer::isNormalized($str, Normalizer::FORM_C))
+ $str = Normalizer::normalize($str, Normalizer::FORM_C);
+ if ($opts['nfkc'] && ! Normalizer::isNormalized($str, Normalizer::FORM_KC))
+ $str = Normalizer::normalize($str, Normalizer::FORM_KC);
+ } else {
+ if (! class_exists('I18N_UnicodeNormalizer')) {
+ @ include_once 'I18N/UnicodeNormalizer.php';
+ }
+ if (class_exists('I18N_UnicodeNormalizer')) {
+ $normalizer = new I18N_UnicodeNormalizer();
+ if ($opts['nfc'])
+ $str = $normalizer->normalize($str, 'NFC');
+ if ($opts['nfkc'])
+ $str = $normalizer->normalize($str, 'NFKC');
+ }
+ }
+ return $str;
+ }
+}
diff --git a/app/mihaildev/elfinder/php/plugins/Watermark/logo.png b/app/mihaildev/elfinder/php/plugins/Watermark/logo.png
new file mode 100755
index 0000000..ca6fe8a
Binary files /dev/null and b/app/mihaildev/elfinder/php/plugins/Watermark/logo.png differ
diff --git a/app/mihaildev/elfinder/php/plugins/Watermark/plugin.php b/app/mihaildev/elfinder/php/plugins/Watermark/plugin.php
new file mode 100755
index 0000000..84b9bb4
--- /dev/null
+++ b/app/mihaildev/elfinder/php/plugins/Watermark/plugin.php
@@ -0,0 +1,243 @@
+ true, // For control by volume driver
+ 'source' => 'logo.png', // Path to Water mark image
+ 'marginRight' => 5, // Margin right pixel
+ 'marginBottom' => 5, // Margin bottom pixel
+ 'quality' => 95, // JPEG image save quality
+ 'transparency' => 70, // Water mark image transparency ( other than PNG )
+ 'targetType' => IMG_GIF|IMG_JPG|IMG_PNG|IMG_WBMP, // Target image formats ( bit-field )
+ 'targetMinPixel' => 200 // Target image minimum pixel size
+ );
+
+ $this->opts = array_merge($defaults, $opts);
+
+ }
+
+ public function onUpLoadPreSave(&$path, &$name, $src, $elfinder, $volume) {
+
+ $opts = $this->opts;
+ $volOpts = $volume->getOptionsPlugin('Watermark');
+ if (is_array($volOpts)) {
+ $opts = array_merge($this->opts, $volOpts);
+ }
+
+ if (! $opts['enable']) {
+ return false;
+ }
+
+ $srcImgInfo = @getimagesize($src);
+ if ($srcImgInfo === false) {
+ return false;
+ }
+
+ // check water mark image
+ if (! file_exists($opts['source'])) {
+ $opts['source'] = dirname(__FILE__) . "/" . $opts['source'];
+ }
+ if (is_readable($opts['source'])) {
+ $watermarkImgInfo = @getimagesize($opts['source']);
+ if (! $watermarkImgInfo) {
+ return false;
+ }
+ } else {
+ return false;
+ }
+
+ $watermark = $opts['source'];
+ $marginLeft = $opts['marginRight'];
+ $marginBottom = $opts['marginBottom'];
+ $quality = $opts['quality'];
+ $transparency = $opts['transparency'];
+
+ // check target image type
+ $imgTypes = array(
+ IMAGETYPE_GIF => IMG_GIF,
+ IMAGETYPE_JPEG => IMG_JPEG,
+ IMAGETYPE_PNG => IMG_PNG,
+ IMAGETYPE_WBMP => IMG_WBMP,
+ );
+ if (! ($opts['targetType'] & $imgTypes[$srcImgInfo[2]])) {
+ return false;
+ }
+
+ // check target image size
+ if ($opts['targetMinPixel'] > 0 && $opts['targetMinPixel'] > min($srcImgInfo[0], $srcImgInfo[1])) {
+ return false;
+ }
+
+ $watermark_width = $watermarkImgInfo[0];
+ $watermark_height = $watermarkImgInfo[1];
+ $dest_x = $srcImgInfo[0] - $watermark_width - $marginLeft;
+ $dest_y = $srcImgInfo[1] - $watermark_height - $marginBottom;
+
+ if (class_exists('Imagick')) {
+ return $this->watermarkPrint_imagick($src, $watermark, $dest_x, $dest_y, $quality, $transparency, $watermarkImgInfo);
+ } else {
+ return $this->watermarkPrint_gd($src, $watermark, $dest_x, $dest_y, $quality, $transparency, $watermarkImgInfo, $srcImgInfo);
+ }
+ }
+
+ private function watermarkPrint_imagick($src, $watermark, $dest_x, $dest_y, $quality, $transparency, $watermarkImgInfo) {
+
+ try {
+ // Open the original image
+ $img = new Imagick($src);
+
+ // Open the watermark
+ $watermark = new Imagick($watermark);
+
+ // Set transparency
+ if (strtoupper($watermark->getImageFormat()) !== 'PNG') {
+ $watermark->setImageOpacity($transparency/100);
+ }
+
+ // Overlay the watermark on the original image
+ $img->compositeImage($watermark, imagick::COMPOSITE_OVER, $dest_x, $dest_y);
+
+ // Set quality
+ if (strtoupper($img->getImageFormat()) === 'JPEG') {
+ $img->setImageCompression(imagick::COMPRESSION_JPEG);
+ $img->setCompressionQuality($quality);
+ }
+
+ $result = $img->writeImage($src);
+
+ $img->clear();
+ $img->destroy();
+ $watermark->clear();
+ $watermark->destroy();
+
+ return $result ? true : false;
+ } catch (Exception $e) {
+ return false;
+ }
+ }
+
+ private function watermarkPrint_gd($src, $watermark, $dest_x, $dest_y, $quality, $transparency, $watermarkImgInfo, $srcImgInfo) {
+
+ $watermark_width = $watermarkImgInfo[0];
+ $watermark_height = $watermarkImgInfo[1];
+
+ $ermsg = '';
+ switch ($watermarkImgInfo['mime']) {
+ case 'image/gif':
+ if (@imagetypes() & IMG_GIF) {
+ $oWatermarkImg = @imagecreatefromgif($watermark);
+ } else {
+ $ermsg = 'GIF images are not supported';
+ }
+ break;
+ case 'image/jpeg':
+ if (@imagetypes() & IMG_JPG) {
+ $oWatermarkImg = @imagecreatefromjpeg($watermark) ;
+ } else {
+ $ermsg = 'JPEG images are not supported';
+ }
+ break;
+ case 'image/png':
+ if (@imagetypes() & IMG_PNG) {
+ $oWatermarkImg = @imagecreatefrompng($watermark) ;
+ } else {
+ $ermsg = 'PNG images are not supported';
+ }
+ break;
+ case 'image/wbmp':
+ if (@imagetypes() & IMG_WBMP) {
+ $oWatermarkImg = @imagecreatefromwbmp($watermark);
+ } else {
+ $ermsg = 'WBMP images are not supported';
+ }
+ break;
+ default:
+ $oWatermarkImg = false;
+ $ermsg = $watermarkImgInfo['mime'].' images are not supported';
+ break;
+ }
+
+ if (! $ermsg) {
+ switch ($srcImgInfo['mime']) {
+ case 'image/gif':
+ if (@imagetypes() & IMG_GIF) {
+ $oSrcImg = @imagecreatefromgif($src);
+ } else {
+ $ermsg = 'GIF images are not supported';
+ }
+ break;
+ case 'image/jpeg':
+ if (@imagetypes() & IMG_JPG) {
+ $oSrcImg = @imagecreatefromjpeg($src) ;
+ } else {
+ $ermsg = 'JPEG images are not supported';
+ }
+ break;
+ case 'image/png':
+ if (@imagetypes() & IMG_PNG) {
+ $oSrcImg = @imagecreatefrompng($src) ;
+ } else {
+ $ermsg = 'PNG images are not supported';
+ }
+ break;
+ case 'image/wbmp':
+ if (@imagetypes() & IMG_WBMP) {
+ $oSrcImg = @imagecreatefromwbmp($src);
+ } else {
+ $ermsg = 'WBMP images are not supported';
+ }
+ break;
+ default:
+ $oSrcImg = false;
+ $ermsg = $srcImgInfo['mime'].' images are not supported';
+ break;
+ }
+ }
+
+ if ($ermsg || false === $oSrcImg || false === $oWatermarkImg) {
+ return false;
+ }
+
+ if ($srcImgInfo['mime'] === 'image/png') {
+ if (function_exists('imagecolorallocatealpha')) {
+ $bg = imagecolorallocatealpha($oSrcImg, 255, 255, 255, 127);
+ imagefill($oSrcImg, 0, 0 , $bg);
+ }
+ }
+
+ if ($watermarkImgInfo['mime'] === 'image/png') {
+ imagecopy($oSrcImg, $oWatermarkImg, $dest_x, $dest_y, 0, 0, $watermark_width, $watermark_height);
+ } else {
+ imagecopymerge($oSrcImg, $oWatermarkImg, $dest_x, $dest_y, 0, 0, $watermark_width, $watermark_height, $transparency);
+ }
+
+ switch ($srcImgInfo['mime']) {
+ case 'image/gif':
+ imagegif($oSrcImg, $src);
+ break;
+ case 'image/jpeg':
+ imagejpeg($oSrcImg, $src, $quality);
+ break;
+ case 'image/png':
+ if (function_exists('imagesavealpha') && function_exists('imagealphablending')) {
+ imagealphablending($oSrcImg, false);
+ imagesavealpha($oSrcImg, true);
+ }
+ imagepng($oSrcImg, $src);
+ break;
+ case 'image/wbmp':
+ imagewbmp($oSrcImg, $src);
+ break;
+ }
+
+ imageDestroy($oSrcImg);
+ imageDestroy($oWatermarkImg);
+
+ return true;
+ }
+}
diff --git a/app/mihaildev/elfinder/views/connect.php b/app/mihaildev/elfinder/views/connect.php
new file mode 100755
index 0000000..2d544cf
--- /dev/null
+++ b/app/mihaildev/elfinder/views/connect.php
@@ -0,0 +1,18 @@
+run();
\ No newline at end of file
diff --git a/app/mihaildev/elfinder/views/manager.php b/app/mihaildev/elfinder/views/manager.php
new file mode 100755
index 0000000..f8d12d9
--- /dev/null
+++ b/app/mihaildev/elfinder/views/manager.php
@@ -0,0 +1,80 @@
+registerJs("
+function ElFinderGetCommands(disabled){
+ var Commands = elFinder.prototype._options.commands;
+ $.each(disabled, function(i, cmd) {
+ (idx = $.inArray(cmd, Commands)) !== -1 && Commands.splice(idx,1);
+ });
+ return Commands;
+}
+
+ var winHashOld = '';
+ function elFinderFullscreen(){
+
+ var width = $(window).width()-($('#elfinder').outerWidth(true) - $('#elfinder').width());
+ var height = $(window).height()-($('#elfinder').outerHeight(true) - $('#elfinder').height());
+
+ var el = $('#elfinder').elfinder('instance');
+
+ var winhash = $(window).width() + '|' + $(window).height();
+
+
+ if(winHashOld == winhash)
+ return;
+
+ winHashOld = winhash;
+
+ el.resize(width, height);
+ }
+
+ $('#elfinder').elfinder(".Json::encode($options).").elfinder('instance');
+
+ $(window).resize(elFinderFullscreen);
+
+ elFinderFullscreen();
+ ");
+
+
+$this->registerCss("
+html, body {
+ height: 100%;
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ position: relative;
+ padding: 0; margin: 0;
+}
+");
+
+
+
+
+?>
+beginPage() ?>
+
+
+
+
+ elFinder 2.0
+ head() ?>
+
+
+beginBody() ?>
+
+endBody() ?>
+
+
+endPage() ?>
\ No newline at end of file
diff --git a/app/models/1Mod.php b/app/models/1Mod.php
new file mode 100755
index 0000000..cb2a5b8
--- /dev/null
+++ b/app/models/1Mod.php
@@ -0,0 +1,116 @@
+cost)) ? $this->cost : 0;
+ }
+
+ public function addBasket($mod_id,$count){
+ $session=new Session;
+ $session->open();
+ $data = $session['basket'];
+ $i = 0;
+ if(isset($session['basket'])){
+ foreach($session['basket'] as $key=>$basket){
+ if($mod_id == $basket['id']){$data[$key]['count'] += $count;$session['basket'] = $data;$i++;}
+ }}
+ if($i == 0){$data[] = array('id'=>$mod_id, 'count'=>$count);$session['basket'] = $data;}
+ //print_r($_SESSION['basket']);
+ }
+
+ public function rowBasket(){
+ $session=new Session;
+ $session->open();
+ $cost = 0;$count = 0;
+ if(isset($session['basket']) && count($session['basket'])){
+
+ foreach($session['basket'] as $product){
+ //$cost += ($this->getModCost($product['id'])*$product['count']);
+ $count += $product['count'];
+ }
+ //$count = count($_SESSION['basket']);
+ }
+ return (object) array('cost'=>$cost,'count'=>$count);
+ }
+
+
+ public function getBasketMods(){
+ $session=new Session;
+ $session->open();
+ $products = array();
+ if(empty($session['basket']))return array();
+ foreach($session['basket'] as $product){
+ $row = Mod::find()->select(['mod.*','products.name as product_name','products.image','products.translit','catalog.translit as translit_rubric'])
+ ->where(['mod.id'=>$product['id']])
+ ->leftJoin('products', 'products.id = mod.product_id')
+ ->leftJoin('catalog', 'catalog.id = products.catalog_id')
+ ->one();
+ $row->count = $product['count'];
+ $row->sum_cost = $product['count'] * $row->cost;
+ $products[] = $row;
+ }
+ return $products;
+ }
+
+ public function getSumCost(){
+ $session=new Session;
+ $session->open();
+ $cost = 0;
+ if(empty($session['basket']))return false;
+ foreach($session['basket'] as $product){
+ $cost += ($this->getModCost($product['id'])*$product['count']);
+ }
+ return $cost;
+ }
+
+ private function getModCost($mod_id){
+ $mod = Mod::find()->where(['id'=>$mod_id])->one();
+ return $mod->cost;
+ }
+
+ public function updateBasket($row){
+ $session=new Session;
+ $session->open();
+
+ //$data = array();
+
+ if($row['count']>0) $this->data[] = array('id'=>$row['id'], 'count'=>$row['count']);
+ $session['basket'] = $this->data;
+ }
+
+ public function clearBasket(){
+ $session=new Session;
+ $session->open();
+ $session['basket'] = null;
+ }
+
+ public function deleteBasketMod($id){
+ $session=new Session;
+ $session->open();
+ $basket = $session['basket'];
+ foreach($basket as $key=>$product){
+ if($id == $product['id'])unset($basket[$key]);
+ }
+ $session['basket'] = $basket;
+ }
+
+
+
+
+}
\ No newline at end of file
diff --git a/app/models/Brends.php b/app/models/Brends.php
new file mode 100755
index 0000000..945eca2
--- /dev/null
+++ b/app/models/Brends.php
@@ -0,0 +1,16 @@
+hasMany(ProductsBrends::className(), ['brend_id' => 'id']);
+ }
+}
\ No newline at end of file
diff --git a/app/models/Call.php b/app/models/Call.php
new file mode 100755
index 0000000..0e56651
--- /dev/null
+++ b/app/models/Call.php
@@ -0,0 +1,55 @@
+ true],
+ //['email', 'email'],
+ [['body'], 'safe'],
+ ];
+ }
+
+ public function attributeLabels()
+ {
+ return [
+ 'name' => 'Имя',
+ 'phone'=>'Телефон',
+ 'body'=>'Сообщение',
+ ];
+ }
+
+ public function contact($email)
+ {
+ if ($this->validate()) {
+ $body = '';
+ $body .= 'Имя: '.$this->name;
+ $body .= "\n\r";
+ $body .= 'Телефон: '.$this->phone;
+ $body .= "\n\r";
+ $body .= 'Сообщение: '.$this->body;
+ $body .= "\n\r";
+
+ Yii::$app->mailer->compose()
+ ->setTo($email)
+ ->setFrom(['send@artweb.ua' => 'send'])
+ ->setSubject('ОБРАТНЫЙ ЗВОНОК на сайте Бубочка')
+ ->setTextBody($body)
+ ->send();
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/models/Catalog.php b/app/models/Catalog.php
new file mode 100755
index 0000000..773a80b
--- /dev/null
+++ b/app/models/Catalog.php
@@ -0,0 +1,38 @@
+where(['parent_id'=>$parent_id])->orderBy('sort ASC')->with('childs')->all();
+ }
+
+ public function getChilds()
+ {
+ return $this->hasMany(self::className(), ['parent_id' => 'id'])->orderBy('sort ASC');
+ }
+
+ public function getParent()
+ {
+ return $this->hasOne(self::className(), ['id' => 'parent_id']);
+ }
+
+ public function getCatFasovka(){
+ return (!empty($this->fasovka_name)) ? $this->fasovka_name : 'Фасовка';
+ }
+
+ public function getCatType(){
+ return (!empty($this->type_name)) ? $this->type_name : 'Тип';
+ }
+
+ public function getCatBrends(){
+ return (!empty($this->brends_name)) ? $this->brends_name : 'Производители';
+ }
+
+}
\ No newline at end of file
diff --git a/app/models/ContactForm.php b/app/models/ContactForm.php
new file mode 100755
index 0000000..d4052ee
--- /dev/null
+++ b/app/models/ContactForm.php
@@ -0,0 +1,64 @@
+ 'Verification Code',
+ ];
+ }
+
+ /**
+ * Sends an email to the specified email address using the information collected by this model.
+ * @param string $email the target email address
+ * @return boolean whether the model passes validation
+ */
+ public function contact($email)
+ {
+ if ($this->validate()) {
+ Yii::$app->mailer->compose()
+ ->setTo($email)
+ ->setFrom([$this->email => $this->name])
+ ->setSubject($this->subject)
+ ->setTextBody($this->body)
+ ->send();
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/app/models/Fasovka.php b/app/models/Fasovka.php
new file mode 100755
index 0000000..55715a8
--- /dev/null
+++ b/app/models/Fasovka.php
@@ -0,0 +1,17 @@
+hasMany(ProductsFasovka::className(), ['fasovka_id' => 'id']);
+ }
+
+}
\ No newline at end of file
diff --git a/app/models/Fotos.php b/app/models/Fotos.php
new file mode 100755
index 0000000..6ae15b8
--- /dev/null
+++ b/app/models/Fotos.php
@@ -0,0 +1,12 @@
+hasErrors()) {
+ $user = $this->getUser();
+
+ if (!$user || !$user->validatePassword($this->password)) {
+ $this->addError($attribute, 'Incorrect username or password.');
+ }
+ }
+ }
+
+ /**
+ * Logs in a user using the provided username and password.
+ * @return boolean whether the user is logged in successfully
+ */
+ public function login()
+ {
+ if ($this->validate()) {
+ return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600*24*30 : 0);
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Finds user by [[username]]
+ *
+ * @return User|null
+ */
+ public function getUser()
+ {
+ if ($this->_user === false) {
+ $this->_user = User::findByUsername($this->username);
+ }
+
+ return $this->_user;
+ }
+}
diff --git a/app/models/Menu.php b/app/models/Menu.php
new file mode 100755
index 0000000..90b1c9a
--- /dev/null
+++ b/app/models/Menu.php
@@ -0,0 +1,12 @@
+cost)) ? $this->cost : 0;
+// }
+
+ public function addBasket($mod_id,$count){
+ $session=new Session;
+ $session->open();
+ $data = $session['basket'];
+ $i = 0;
+ if(isset($session['basket'])){
+ foreach($session['basket'] as $key=>$basket){
+ if($mod_id == $basket['id']){$data[$key]['count'] += $count;$session['basket'] = $data;$i++;}
+ }}
+ if($i == 0){$data[] = array('id'=>$mod_id, 'count'=>$count);$session['basket'] = $data;}
+ //print_r($_SESSION['basket']);
+ }
+
+ public function rowBasket(){
+ $session=new Session;
+ $session->open();
+ $cost = 0;$count = 0;
+ if(isset($session['basket']) && count($session['basket'])){
+
+ foreach($session['basket'] as $product){
+ $cost += ($this->getModCost($product['id'])*$product['count']);
+ $count += $product['count'];
+ }
+ //$count = count($_SESSION['basket']);
+ }
+ return (object) array(
+ 'cost'=>$cost,
+ 'count'=>$count,
+ );
+ }
+
+
+ public function getBasketMods(){
+ $session=new Session;
+ $session->open();
+ $products = array();
+ if(empty($session['basket']))return array();
+ foreach($session['basket'] as $product){
+ $row = Mod::find()->select(['mod.*','products.name as product_name','products.image','products.translit','catalog.translit as translit_rubric'])
+ ->where(['mod.id'=>$product['id']])
+ ->leftJoin('products', 'products.id = mod.product_id')
+ ->leftJoin('catalog', 'catalog.id = products.catalog_id')
+ ->one();
+ $row->count = $product['count'];
+ $row->sum_cost = $product['count'] * $row->cost;
+ $products[] = $row;
+ }
+ return $products;
+ }
+
+ public function getSumCost(){
+ $session=new Session;
+ $session->open();
+ $cost = 0;
+ if(empty($session['basket']))return false;
+ foreach($session['basket'] as $product){
+ $cost += ($this->getModCost($product['id'])*$product['count']);
+ }
+ return $cost;
+ }
+
+ private function getModCost($mod_id){
+ $mod = Mod::find()->where(['id'=>$mod_id])->one();
+ return $mod->cost;
+ }
+
+ public function updateBasket($row){
+ $session=new Session;
+ $session->open();
+
+ //$data = array();
+
+ if($row['count']>0) $this->data[] = array('id'=>$row['id'], 'count'=>$row['count']);
+ $session['basket'] = $this->data;
+ }
+
+ public function clearBasket(){
+ $session=new Session;
+ $session->open();
+ $session['basket'] = null;
+ }
+
+ public function deleteBasketMod($id){
+ $session=new Session;
+ $session->open();
+ $basket = $session['basket'];
+ foreach($basket as $key=>$product){
+ if($id == $product['id'])unset($basket[$key]);
+ }
+ $session['basket'] = $basket;
+ }
+
+
+
+
+}
\ No newline at end of file
diff --git a/app/models/News.php b/app/models/News.php
new file mode 100755
index 0000000..728537f
--- /dev/null
+++ b/app/models/News.php
@@ -0,0 +1,14 @@
+ true],
+ //['email', 'email'],
+ [['body','patronymic','surname'], 'safe'],
+
+ [
+ [
+ 'total',
+ ],
+ 'number',
+ 'min' => 100,
+ ],
+
+ [['email'],'email'],
+ ];
+ }
+
+ public function attributeLabels()
+ {
+ return [
+ 'name' => 'Имя',
+ 'phone'=>'Телефон',
+ 'body'=>'Сообщение',
+ 'adress'=>'Адрес',
+ 'patronymic'=>'Отчество',
+ 'surname'=>'Фамилия',
+ 'email'=>'E-mail',
+ 'total' => 'Общая сумма',
+ ];
+ }
+
+ public function beforeSave($insert) {
+ $this->date_time = new \yii\db\Expression('NOW()');
+ return parent::beforeSave($insert);
+ }
+
+ public function beforeDelete() {
+ return parent::beforeDelete();
+ }
+
+ public function contact($email,$body)
+ {
+ if ($this->validate()) {
+ $body .= 'Вся сумма: '.$this->total;
+ $body .= "\n\r";
+ $body .= 'Имя: '.$this->name;
+ $body .= "\n\r";
+ $body .= 'Фамилия: '.$this->surname;
+ $body .= "\n\r";
+ $body .= 'Отчество: '.$this->patronymic;
+ $body .= "\n\r";
+ $body .= 'E-mail: '.$this->email;
+ $body .= "\n\r";
+ $body .= 'Телефон: '.$this->phone;
+ $body .= "\n\r";
+ $body .= 'Адрес: '.$this->adress;
+ $body .= "\n\r";
+ $body .= 'Сообщение: '.$this->body;
+ $body .= "\n\r";
+
+ Yii::$app->mailer->compose()
+ ->setTo($email)
+ ->setFrom(['send@artweb.ua' => 'send'])
+ ->setSubject('Заказ на сайте Бубочка')
+ ->setTextBody($body)
+ ->send();
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/models/OrdersProducts.php b/app/models/OrdersProducts.php
new file mode 100755
index 0000000..5442c3e
--- /dev/null
+++ b/app/models/OrdersProducts.php
@@ -0,0 +1,20 @@
+'Фасовка',
+ 'type'=>'Типы',
+ 'brends'=>'Бренды',
+ ];
+ }
+
+ public function getCatalog()
+ {
+ return $this->hasOne(Catalog::className(), ['id' => 'catalog_id']);
+ }
+ public function getMods()
+ {
+ return $this->hasMany(Mod::className(), ['product_id' => 'id']);
+ }
+ public function getMinCost()
+ {
+ return $this->hasOne(Mod::className(), ['product_id' => 'id'])->orderBy('cost');
+
+ }
+ public function getCost()
+ {
+ //$res = $this->hasOne(Mod::className(), ['product_id' => 'id'])->orderBy('cost');
+ //print_r($res);exit;
+ $res = Mod::find()->where(['product_id' => $this->id])->orderBy('cost')->one();
+ return (!empty($res->cost)) ? $res : ((object) ['cost'=>0]);
+ }
+ public function getFasovka()
+ {
+ return $this->hasMany(ProductsFasovka::className(), ['product_id' => 'id']);
+ }
+ public function getType()
+ {
+ return $this->hasMany(ProductsType::className(), ['product_id' => 'id']);
+ }
+ public function getBrends()
+ {
+ return $this->hasMany(ProductsBrends::className(), ['product_id' => 'id']);
+ }
+ public function getFotos()
+ {
+ return $this->hasMany(Fotos::className(), ['product_id' => 'id']);
+ }
+
+
+
+ public function fasovkaAll($catalog_id){
+ $fasovka = Fasovka::find()->where(['catalog_id'=>$catalog_id])->innerJoinWith(['productsFasovka']);
+ if(!empty($this->type)){
+ $fasovka->leftJoin('productsType', 'productsType.product_id = productsFasovka.product_id')->andWhere(['productsType.type_id'=>$this->type]);
+ }
+ if(!empty($this->brends)){
+ $fasovka->leftJoin('productsBrends', 'productsBrends.product_id = productsFasovka.product_id')->andWhere(['productsBrends.brend_id'=>$this->brends]);
+ }
+ return $fasovka->asArray()->orderBy('name')->all();
+ }
+
+ public function typeAll($catalog_id){
+ $type = Type::find()->where(['catalog_id'=>$catalog_id])->innerJoinWith(['productsType']);
+ if(!empty($this->fasovka)){
+ $type->leftJoin('productsFasovka', 'productsFasovka.product_id = productsType.product_id')->andWhere(['productsFasovka.fasovka_id'=>$this->fasovka]);
+ }
+ if(!empty($this->brends)){
+ $type->leftJoin('productsBrends', 'productsBrends.product_id = productsType.product_id')->andWhere(['productsBrends.brend_id'=>$this->brends]);
+ }
+ return $type->asArray()->orderBy('name')->all();
+ }
+
+ public function brendsAll($catalog_id){
+ $brends = Brends::find()->where(['catalog_id'=>$catalog_id])->innerJoinWith(['productsBrends']);
+ if(!empty($this->fasovka)){
+ $brends->leftJoin('productsFasovka', 'productsFasovka.product_id = productsBrends.product_id')->andWhere(['productsFasovka.fasovka_id'=>$this->fasovka]);
+ }
+ if(!empty($this->type)){
+ $brends->leftJoin('productsType', 'productsType.product_id = productsBrends.product_id')->andWhere(['productsType.type_id'=>$this->type]);
+ }
+ return $brends->asArray()->orderBy('name')->all();
+ }
+
+}
\ No newline at end of file
diff --git a/app/models/ProductsBrends.php b/app/models/ProductsBrends.php
new file mode 100755
index 0000000..67b2a8b
--- /dev/null
+++ b/app/models/ProductsBrends.php
@@ -0,0 +1,13 @@
+hasMany(ProductsType::className(), ['type_id' => 'id']);
+ }
+ public function getProductsFasovka()
+ {
+ return $this->hasMany(ProductsFasovka::className(), ['product_id'=>'ProductsType.product_id']);
+ }
+}
\ No newline at end of file
diff --git a/app/models/User.php b/app/models/User.php
new file mode 100755
index 0000000..692673c
--- /dev/null
+++ b/app/models/User.php
@@ -0,0 +1,74 @@
+ $token]);
+ }
+
+ /**
+ * Finds user by username
+ *
+ * @param string $username
+ * @return static|null
+ */
+ public static function findByUsername($username)
+ {
+ return static::findOne(['username' => $username]);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getAuthKey()
+ {
+ return $this->authKey;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function validateAuthKey($authKey)
+ {
+ return $this->authKey === $authKey;
+ }
+
+ /**
+ * Validates password
+ *
+ * @param string $password password to validate
+ * @return boolean if password provided is valid for current user
+ */
+ public function validatePassword($password)
+ {
+ return $this->password === $password;
+ }
+}
diff --git a/app/modules/admin/admin.php b/app/modules/admin/admin.php
new file mode 100755
index 0000000..e8a99e0
--- /dev/null
+++ b/app/modules/admin/admin.php
@@ -0,0 +1,15 @@
+
+ * @since 2.0
+ */
+class AppAsset extends AssetBundle
+{
+ // public $basePath = '@webroot';
+ // public $baseUrl = '@web';
+ public $sourcePath = '@app/modules/admin/assets';
+ public $css = [
+ 'css/admin.css',
+ ];
+ public $js = [
+ ];
+ public $depends = [
+ 'yii\web\YiiAsset',
+ 'yii\bootstrap\BootstrapAsset',
+ ];
+}
diff --git a/app/modules/admin/assets/css/admin.css b/app/modules/admin/assets/css/admin.css
new file mode 100755
index 0000000..472a11d
--- /dev/null
+++ b/app/modules/admin/assets/css/admin.css
@@ -0,0 +1,96 @@
+html,
+body { padding:0px;margin:0px;
+
+}
+
+.wrap {
+ min-height: 100%;
+ height: auto;
+ margin: 0 auto -60px;
+ padding: 0 0 60px;
+}
+
+.wrap > .container {
+ padding: 70px 15px 20px;
+}
+
+.footer {
+ height: 60px;
+ background-color: #f5f5f5;
+ border-top: 1px solid #ddd;
+ padding-top: 20px;
+}
+
+.jumbotron {
+ text-align: center;
+ background-color: transparent;
+}
+
+.jumbotron .btn {
+ font-size: 21px;
+ padding: 14px 24px;
+}
+
+.not-set {
+ color: #c55;
+ font-style: italic;
+}
+
+/* add sorting icons to gridview sort links */
+a.asc:after, a.desc:after {
+ position: relative;
+ top: 1px;
+ display: inline-block;
+ font-family: 'Glyphicons Halflings';
+ font-style: normal;
+ font-weight: normal;
+ line-height: 1;
+ padding-left: 5px;
+}
+
+a.asc:after {
+ content: /*"\e113"*/ "\e151";
+}
+
+a.desc:after {
+ content: /*"\e114"*/ "\e152";
+}
+
+.sort-numerical a.asc:after {
+ content: "\e153";
+}
+
+.sort-numerical a.desc:after {
+ content: "\e154";
+}
+
+.sort-ordinal a.asc:after {
+ content: "\e155";
+}
+
+.sort-ordinal a.desc:after {
+ content: "\e156";
+}
+
+.grid-view th {
+ white-space: nowrap;
+}
+
+.hint-block {
+ display: block;
+ margin-top: 5px;
+ color: #999;
+}
+
+.error-summary {
+ color: #a94442;
+ background: #fdf7f7;
+ border-left: 3px solid #eed3d7;
+ padding: 10px 20px;
+ margin: 0 0 15px 0;
+}
+
+.site-login{width:400px;margin:100px auto 0px auto;}
+.leftbar{float:left;width:240px;padding:30px 0px;}
+.content {overflow:hidden;padding:0px 0px 0px 20px;}
+* html .content{height:1%;}
diff --git a/app/modules/admin/controllers/ArticlesController.php b/app/modules/admin/controllers/ArticlesController.php
new file mode 100644
index 0000000..fb9e0c3
--- /dev/null
+++ b/app/modules/admin/controllers/ArticlesController.php
@@ -0,0 +1,8 @@
+ [
+ 'class' => AccessControl::className(),
+ //'only' => ['logout','index'],
+ 'rules' => [
+ [
+ 'actions' => ['index','save','delete'],
+ 'allow' => true,
+ 'roles' => ['admin'],
+ ],
+ ],
+ ],
+ 'verbs' => [
+ 'class' => VerbFilter::className(),
+ 'actions' => [
+ 'logout' => ['post'],
+ ],
+ ],
+ ];
+ }
+
+ public function actionIndex()
+ {
+ $dataProvider = new ActiveDataProvider([
+ 'query' => Brends::find()->where('catalog_id=:catalog_id',[':catalog_id'=>$_GET['catID']])->orderBy('id'),
+ 'pagination' => [
+ 'pageSize' => 20,
+ ],
+ ]);
+ return $this->render('index',['dataProvider'=>$dataProvider]);
+ }
+
+ public function actionSave()
+ {
+ $model = (!empty($_GET['id'])) ? Brends::findOne($_GET['id']) : new Brends;
+
+ if ($model->load(Yii::$app->request->post()) && $model->save()) {
+
+ return Yii::$app->response->redirect(['/admin/brends/index','catID'=>$_GET['catID']]);
+ }
+ return $this->render('save',['model'=>$model]);
+ }
+
+ public function actionDelete(){
+ $model = Brends::findOne($_GET['id']);
+ $model->delete();
+ return Yii::$app->response->redirect(['/admin/brends/index','catID'=>$_GET['catID']]);
+ }
+}
diff --git a/app/modules/admin/controllers/CatalogController.php b/app/modules/admin/controllers/CatalogController.php
new file mode 100755
index 0000000..e8ad3b8
--- /dev/null
+++ b/app/modules/admin/controllers/CatalogController.php
@@ -0,0 +1,73 @@
+ [
+ 'class' => AccessControl::className(),
+ //'only' => ['logout','index'],
+ 'rules' => [
+ [
+ 'actions' => ['index','save','delete'],
+ 'allow' => true,
+ 'roles' => ['admin'],
+ ],
+ ],
+ ],
+ 'verbs' => [
+ 'class' => VerbFilter::className(),
+ 'actions' => [
+ 'logout' => ['post'],
+ ],
+ ],
+ ];
+ }
+
+ public function actionIndex()
+ {
+ $model = new Catalog;
+
+ $dataCatalog = new ArrayDataProvider([
+ 'allModels' => $model->getDataTree(),
+ 'sort' => [
+ 'attributes' => ['id'],
+ ],
+ 'pagination' => [
+ 'pageSize' => 100,
+ ]
+ ]);
+
+ return $this->render('index',['dataCatalog'=>$dataCatalog]);
+ }
+
+ public function actionSave()
+ {
+ $model = (!empty($_GET['id'])) ? Catalog::findOne($_GET['id']) : new Catalog;
+
+ if ($model->load(Yii::$app->request->post()) && $model->save()) {
+
+ return Yii::$app->response->redirect(['/admin/catalog/index']);
+ }
+ return $this->render('save',['model'=>$model]);
+ }
+
+ public function actionDelete(){
+ $model = Catalog::findOne($_GET['id']);
+ $model->delete();
+ Catalog::deleteAll(['parent_id' => $_GET['id']]);
+ return Yii::$app->response->redirect(['/admin/catalog/index']);
+ }
+}
diff --git a/app/modules/admin/controllers/DefaultController.php b/app/modules/admin/controllers/DefaultController.php
new file mode 100755
index 0000000..7b1f486
--- /dev/null
+++ b/app/modules/admin/controllers/DefaultController.php
@@ -0,0 +1,39 @@
+ [
+ 'class' => AccessControl::className(),
+ //'only' => ['logout','index'],
+ 'rules' => [
+ [
+ 'actions' => ['index'],
+ 'allow' => true,
+ 'roles' => ['admin'],
+ ],
+ ],
+ ],
+ 'verbs' => [
+ 'class' => VerbFilter::className(),
+ 'actions' => [
+ 'logout' => ['post'],
+ ],
+ ],
+ ];
+ }
+
+ public function actionIndex()
+ {
+ return $this->render('index');
+ }
+}
diff --git a/app/modules/admin/controllers/ExportController.php b/app/modules/admin/controllers/ExportController.php
new file mode 100755
index 0000000..1e3c82d
--- /dev/null
+++ b/app/modules/admin/controllers/ExportController.php
@@ -0,0 +1,52 @@
+ [
+ 'class' => AccessControl::className(),
+ //'only' => ['logout','index'],
+ 'rules' => [
+ [
+ 'actions' => ['index','save','delete','success'],
+ 'allow' => true,
+ 'roles' => ['admin'],
+ ],
+ ],
+ ],
+ 'verbs' => [
+ 'class' => VerbFilter::className(),
+ 'actions' => [
+ 'logout' => ['post'],
+ ],
+ ],
+ ];
+ }
+
+ public function actionIndex()
+ {
+ $model = new Export;
+ $file = 'upload/products.csv';
+ $model->saveCsv($file);
+ return Yii::$app->response->sendFile($file)->send();
+ //return $this->render('index');
+ }
+
+
+
+
+
+}
diff --git a/app/modules/admin/controllers/FasovkaController.php b/app/modules/admin/controllers/FasovkaController.php
new file mode 100755
index 0000000..ba918fa
--- /dev/null
+++ b/app/modules/admin/controllers/FasovkaController.php
@@ -0,0 +1,66 @@
+ [
+ 'class' => AccessControl::className(),
+ //'only' => ['logout','index'],
+ 'rules' => [
+ [
+ 'actions' => ['index','save','delete'],
+ 'allow' => true,
+ 'roles' => ['admin'],
+ ],
+ ],
+ ],
+ 'verbs' => [
+ 'class' => VerbFilter::className(),
+ 'actions' => [
+ 'logout' => ['post'],
+ ],
+ ],
+ ];
+ }
+
+ public function actionIndex()
+ {
+ $dataProvider = new ActiveDataProvider([
+ 'query' => Fasovka::find()->where('catalog_id=:catalog_id',[':catalog_id'=>$_GET['catID']])->orderBy('id'),
+ 'pagination' => [
+ 'pageSize' => 20,
+ ],
+ ]);
+ return $this->render('index',['dataProvider'=>$dataProvider]);
+ }
+
+ public function actionSave()
+ {
+ $model = (!empty($_GET['id'])) ? Fasovka::findOne($_GET['id']) : new Fasovka;
+
+ if ($model->load(Yii::$app->request->post()) && $model->save()) {
+
+ return Yii::$app->response->redirect(['/admin/fasovka/index','catID'=>$_GET['catID']]);
+ }
+ return $this->render('save',['model'=>$model]);
+ }
+
+ public function actionDelete(){
+ $model = Fasovka::findOne($_GET['id']);
+ $model->delete();
+ return Yii::$app->response->redirect(['/admin/fasovka/index','catID'=>$_GET['catID']]);
+ }
+}
diff --git a/app/modules/admin/controllers/FotosController.php b/app/modules/admin/controllers/FotosController.php
new file mode 100755
index 0000000..f584559
--- /dev/null
+++ b/app/modules/admin/controllers/FotosController.php
@@ -0,0 +1,67 @@
+ [
+ 'class' => AccessControl::className(),
+ //'only' => ['logout','index'],
+ 'rules' => [
+ [
+ 'actions' => ['index','save','delete'],
+ 'allow' => true,
+ 'roles' => ['admin'],
+ ],
+ ],
+ ],
+ 'verbs' => [
+ 'class' => VerbFilter::className(),
+ 'actions' => [
+ 'logout' => ['post'],
+ ],
+ ],
+ ];
+ }
+
+ public function actionIndex()
+ {
+ $dataProvider = new ActiveDataProvider([
+ 'query' => Fotos::find()->where('product_id=:product_id',[':product_id'=>$_GET['productID']])->orderBy('id'),
+ 'pagination' => [
+ 'pageSize' => 20,
+ ],
+ ]);
+ return $this->render('index',['dataProvider'=>$dataProvider]);
+ }
+
+ public function actionSave()
+ {
+ $model = (!empty($_GET['id'])) ? Fotos::findOne($_GET['id']) : new Fotos;
+
+ if ($model->load(Yii::$app->request->post()) && $model->save()) {
+
+ return Yii::$app->response->redirect(['/admin/fotos/index','productID'=>$_GET['productID'],'catID'=>$_GET['catID']]);
+ }
+ return $this->render('save',['model'=>$model]);
+ }
+
+ public function actionDelete(){
+ $model = Fotos::findOne($_GET['id']);
+ $model->delete();
+ return Yii::$app->response->redirect(['/admin/fotos/index','productID'=>$_GET['productID'],'catID'=>$_GET['catID']]);
+ }
+}
+
diff --git a/app/modules/admin/controllers/ImportController.php b/app/modules/admin/controllers/ImportController.php
new file mode 100755
index 0000000..a32d4e3
--- /dev/null
+++ b/app/modules/admin/controllers/ImportController.php
@@ -0,0 +1,54 @@
+ [
+ 'class' => AccessControl::className(),
+ //'only' => ['logout','index'],
+ 'rules' => [
+ [
+ 'actions' => ['index','save','delete','success'],
+ 'allow' => true,
+ 'roles' => ['admin'],
+ ],
+ ],
+ ],
+ 'verbs' => [
+ 'class' => VerbFilter::className(),
+ 'actions' => [
+ 'logout' => ['post'],
+ ],
+ ],
+ ];
+ }
+
+ public function actionIndex()
+ {
+ $model = new Import;
+ if ($model->load(Yii::$app->request->post()) && $model->go()) {
+
+ return Yii::$app->response->redirect(['/admin/import/success']);
+ }
+ return $this->render('index',['model'=>$model]);
+ }
+
+ public function actionSuccess(){
+ return $this->render('success');
+ }
+
+
+
+
+}
diff --git a/app/modules/admin/controllers/LoginController.php b/app/modules/admin/controllers/LoginController.php
new file mode 100755
index 0000000..0512342
--- /dev/null
+++ b/app/modules/admin/controllers/LoginController.php
@@ -0,0 +1,34 @@
+user->isGuest) {
+ return $this->goHome();
+ }
+
+ $model = new LoginForm();
+ if ($model->load(Yii::$app->request->post()) && $model->login()) {
+ return $this->goBack();
+ } else {
+ return $this->render('index', [
+ 'model' => $model,
+ ]);
+ }
+ }
+
+ public function actionLogout()
+ {
+ Yii::$app->user->logout();
+
+ return $this->goHome();
+ }
+}
\ No newline at end of file
diff --git a/app/modules/admin/controllers/MenuController.php b/app/modules/admin/controllers/MenuController.php
new file mode 100755
index 0000000..54b563e
--- /dev/null
+++ b/app/modules/admin/controllers/MenuController.php
@@ -0,0 +1,65 @@
+ [
+ 'class' => AccessControl::className(),
+ //'only' => ['logout','index'],
+ 'rules' => [
+ [
+ 'actions' => ['index','save','delete'],
+ 'allow' => true,
+ 'roles' => ['admin'],
+ ],
+ ],
+ ],
+ 'verbs' => [
+ 'class' => VerbFilter::className(),
+ 'actions' => [
+ 'logout' => ['post'],
+ ],
+ ],
+ ];
+ }
+
+ public function actionIndex()
+ {
+ $dataProvider = new ActiveDataProvider([
+ 'query' => Menu::find(),
+ 'pagination' => [
+ 'pageSize' => 20,
+ ],
+ ]);
+ return $this->render('index',['dataProvider'=>$dataProvider]);
+ }
+
+ public function actionSave()
+ {
+ $model = (!empty($_GET['id'])) ? Menu::findOne($_GET['id']) : new Menu;
+
+ if ($model->load(Yii::$app->request->post()) && $model->save()) {
+
+ return Yii::$app->response->redirect(['/admin/menu/index']);
+ }
+ return $this->render('save',['model'=>$model]);
+ }
+
+ public function actionDelete(){
+ $model = Menu::findOne($_GET['id']);
+ $model->delete();
+ return Yii::$app->response->redirect(['/admin/menu/index']);
+ }
+}
diff --git a/app/modules/admin/controllers/ModController.php b/app/modules/admin/controllers/ModController.php
new file mode 100755
index 0000000..88df0b0
--- /dev/null
+++ b/app/modules/admin/controllers/ModController.php
@@ -0,0 +1,66 @@
+ [
+ 'class' => AccessControl::className(),
+ //'only' => ['logout','index'],
+ 'rules' => [
+ [
+ 'actions' => ['index','save','delete'],
+ 'allow' => true,
+ 'roles' => ['admin'],
+ ],
+ ],
+ ],
+ 'verbs' => [
+ 'class' => VerbFilter::className(),
+ 'actions' => [
+ 'logout' => ['post'],
+ ],
+ ],
+ ];
+ }
+
+ public function actionIndex()
+ {
+ $dataProvider = new ActiveDataProvider([
+ 'query' => Mod::find()->where('product_id=:product_id',[':product_id'=>$_GET['productID']])->orderBy('id'),
+ 'pagination' => [
+ 'pageSize' => 20,
+ ],
+ ]);
+ return $this->render('index',['dataProvider'=>$dataProvider]);
+ }
+
+ public function actionSave()
+ {
+ $model = (!empty($_GET['id'])) ? Mod::findOne($_GET['id']) : new Mod;
+
+ if ($model->load(Yii::$app->request->post()) && $model->save()) {
+
+ return Yii::$app->response->redirect(['/admin/mod/index','productID'=>$_GET['productID'],'catID'=>$_GET['catID']]);
+ }
+ return $this->render('save',['model'=>$model]);
+ }
+
+ public function actionDelete(){
+ $model = Mod::findOne($_GET['id']);
+ $model->delete();
+ return Yii::$app->response->redirect(['/admin/mod/index','productID'=>$_GET['productID'],'catID'=>$_GET['catID']]);
+ }
+}
diff --git a/app/modules/admin/controllers/NewsController.php b/app/modules/admin/controllers/NewsController.php
new file mode 100755
index 0000000..45a0a37
--- /dev/null
+++ b/app/modules/admin/controllers/NewsController.php
@@ -0,0 +1,65 @@
+ [
+ 'class' => AccessControl::className(),
+ //'only' => ['logout','index'],
+ 'rules' => [
+ [
+ 'actions' => ['index','save','delete'],
+ 'allow' => true,
+ 'roles' => ['admin'],
+ ],
+ ],
+ ],
+ 'verbs' => [
+ 'class' => VerbFilter::className(),
+ 'actions' => [
+ 'logout' => ['post'],
+ ],
+ ],
+ ];
+ }
+
+ public function actionIndex()
+ {
+ $dataProvider = new ActiveDataProvider([
+ 'query' => News::find(),
+ 'pagination' => [
+ 'pageSize' => 20,
+ ],
+ ]);
+ return $this->render('index',['dataProvider'=>$dataProvider]);
+ }
+
+ public function actionSave()
+ {
+ $model = (!empty($_GET['id'])) ? News::findOne($_GET['id']) : new News;
+
+ if ($model->load(Yii::$app->request->post()) && $model->save()) {
+
+ return Yii::$app->response->redirect(['/admin/news/index']);
+ }
+ return $this->render('save',['model'=>$model]);
+ }
+
+ public function actionDelete(){
+ $model = News::findOne($_GET['id']);
+ $model->delete();
+ return Yii::$app->response->redirect(['/admin/news/index']);
+ }
+}
diff --git a/app/modules/admin/controllers/OrdersController.php b/app/modules/admin/controllers/OrdersController.php
new file mode 100755
index 0000000..16fa5f9
--- /dev/null
+++ b/app/modules/admin/controllers/OrdersController.php
@@ -0,0 +1,112 @@
+ [
+ 'class' => AccessControl::className(),
+ //'only' => ['logout','index'],
+ 'rules' => [
+ [
+ 'actions' => ['index','save','delete','show','add','delete_product'],
+ 'allow' => true,
+ 'roles' => ['admin'],
+ ],
+ ],
+ ],
+ 'verbs' => [
+ 'class' => VerbFilter::className(),
+ 'actions' => [
+ 'logout' => ['post'],
+ ],
+ ],
+ ];
+ }
+
+ public function actionIndex()
+ {
+ $searchModel = new Orders;
+ $searchModel->load(Yii::$app->request->queryParams);
+ $query = Orders::find();
+ if(!empty($searchModel->phone))$query->andFilterWhere(['like', 'phone', $searchModel->phone]);
+ if(!empty($searchModel->name))$query->andFilterWhere(['like', 'name', $searchModel->name]);
+ if(!empty($searchModel->surname))$query->andFilterWhere(['like', 'surname', $searchModel->surname]);
+ if(!empty($searchModel->total))$query->andFilterWhere(['like', 'total', $searchModel->total]);
+ if(!empty($searchModel->reserve))$query->andFilterWhere(['like', 'reserve', $searchModel->reserve]);
+ if(!empty($searchModel->status))$query->andFilterWhere(['like', 'status', $searchModel->status]);
+ $dataProvider = new ActiveDataProvider([
+ 'query' =>$query,
+ 'sort'=> ['defaultOrder' => ['id'=>SORT_DESC]],
+ 'pagination' => [
+ 'pageSize' => 20,
+ ],
+ ]);
+
+ return $this->render('index',['dataProvider'=>$dataProvider,'searchModel'=>$searchModel]);
+ }
+
+ public function actionShow()
+ {
+ $model = (!empty($_GET['id'])) ? Orders::findOne($_GET['id']) : new Orders;
+
+
+ if ($model->load(Yii::$app->request->post()) && $model->save()) {
+
+ return Yii::$app->response->redirect(['/admin/orders/show','id'=>$model->id,'success'=>1]);
+ }
+
+ $dataProvider = new ActiveDataProvider([
+ 'query' => OrdersProducts::find()->where(['order_id'=>$_GET['id']]),
+ 'pagination' => [
+ 'pageSize' => 20,
+ ],
+ ]);
+ return $this->render('show',['model'=>$model,'dataProvider'=>$dataProvider]);
+ }
+
+ public function actionDelete(){
+ $model = Orders::findOne($_GET['id']);
+ $model->delete();
+ return Yii::$app->response->redirect(['/admin/orders/index']);
+ }
+
+
+ public function actionAdd(){
+ $model = new OrdersProducts;
+
+ if ($model->load(Yii::$app->request->post())) {
+ if(!$modelMod = Mod::find()->with(['product'])->where(['art'=>$model->art])->one())
+ throw new HttpException(404, 'Данного артикля не существует!');
+ $model->product_name = $modelMod->product->name;
+ $model->name = $modelMod->name;
+ $model->art = $modelMod->art;
+ $model->cost = $modelMod->cost;
+ $model->sum_cost = $model->count*$modelMod->cost;
+ $model->save();
+ return Yii::$app->response->redirect(['/admin/orders/show','id'=>$_GET['order_id']]);
+ }
+
+ return $this->render('add',['model'=>$model]);
+ }
+
+ public function actionDelete_product(){
+ $model = OrdersProducts::findOne($_GET['id']);
+ $model->delete();
+ return Yii::$app->response->redirect(['/admin/orders/show','id'=>$_GET['order_id']]);
+ }
+}
diff --git a/app/modules/admin/controllers/ProductsController.php b/app/modules/admin/controllers/ProductsController.php
new file mode 100644
index 0000000..f1ac8d6
--- /dev/null
+++ b/app/modules/admin/controllers/ProductsController.php
@@ -0,0 +1,66 @@
+ [
+ 'class' => AccessControl::className(),
+ //'only' => ['logout','index'],
+ 'rules' => [
+ [
+ 'actions' => ['index','save','delete'],
+ 'allow' => true,
+ 'roles' => ['admin'],
+ ],
+ ],
+ ],
+ 'verbs' => [
+ 'class' => VerbFilter::className(),
+ 'actions' => [
+ 'logout' => ['post'],
+ ],
+ ],
+ ];
+ }
+
+ public function actionIndex()
+ {
+ $dataProvider = new ActiveDataProvider([
+ 'query' => Products::find()->where('catalog_id=:catalog_id',[':catalog_id'=>$_GET['catID']]),
+ 'pagination' => [
+ 'pageSize' => 150,
+ ],
+ ]);
+ return $this->render('index',['dataProvider'=>$dataProvider]);
+ }
+
+ public function actionSave()
+ {
+ $model = (!empty($_GET['id'])) ? Products::findOne($_GET['id']) : new Products;
+
+ if ($model->load(Yii::$app->request->post()) && $model->save()) {
+
+ return Yii::$app->response->redirect(['/admin/products/index','catID'=>$_GET['catID']]);
+ }
+ return $this->render('save',['model'=>$model]);
+ }
+
+ public function actionDelete(){
+ $model = Products::findOne($_GET['id']);
+ $model->delete();
+ return Yii::$app->response->redirect(['/admin/products/index','catID'=>$_GET['catID']]);
+ }
+}
\ No newline at end of file
diff --git a/app/modules/admin/controllers/SliderController.php b/app/modules/admin/controllers/SliderController.php
new file mode 100755
index 0000000..412aa60
--- /dev/null
+++ b/app/modules/admin/controllers/SliderController.php
@@ -0,0 +1,66 @@
+ [
+ 'class' => AccessControl::className(),
+ //'only' => ['logout','index'],
+ 'rules' => [
+ [
+ 'actions' => ['index','save','delete'],
+ 'allow' => true,
+ 'roles' => ['admin'],
+ ],
+ ],
+ ],
+ 'verbs' => [
+ 'class' => VerbFilter::className(),
+ 'actions' => [
+ 'logout' => ['post'],
+ ],
+ ],
+ ];
+ }
+
+ public function actionIndex()
+ {
+ $dataProvider = new ActiveDataProvider([
+ 'query' => Slider::find(),
+ 'pagination' => [
+ 'pageSize' => 20,
+ ],
+ ]);
+ return $this->render('index',['dataProvider'=>$dataProvider]);
+ }
+
+ public function actionSave()
+ {
+ $model = (!empty($_GET['id'])) ? Slider::findOne($_GET['id']) : new Slider;
+
+ if ($model->load(Yii::$app->request->post()) && $model->save()) {
+
+ return Yii::$app->response->redirect(['/admin/slider/index']);
+ }
+ return $this->render('save',['model'=>$model]);
+ }
+
+ public function actionDelete(){
+ $model = Slider::findOne($_GET['id']);
+ $model->delete();
+ return Yii::$app->response->redirect(['/admin/slider/index']);
+ }
+}
+
diff --git a/app/modules/admin/controllers/TextController.php b/app/modules/admin/controllers/TextController.php
new file mode 100644
index 0000000..b7e4c0f
--- /dev/null
+++ b/app/modules/admin/controllers/TextController.php
@@ -0,0 +1,65 @@
+ [
+ 'class' => AccessControl::className(),
+ //'only' => ['logout','index'],
+ 'rules' => [
+ [
+ 'actions' => ['index','save','delete'],
+ 'allow' => true,
+ 'roles' => ['admin'],
+ ],
+ ],
+ ],
+ 'verbs' => [
+ 'class' => VerbFilter::className(),
+ 'actions' => [
+ 'logout' => ['post'],
+ ],
+ ],
+ ];
+ }
+
+ public function actionIndex()
+ {
+ $dataProvider = new ActiveDataProvider([
+ 'query' => Text::find(),
+ 'pagination' => [
+ 'pageSize' => 20,
+ ],
+ ]);
+ return $this->render('index',['dataProvider'=>$dataProvider]);
+ }
+
+ public function actionSave()
+ {
+ $model = (!empty($_GET['id'])) ? Text::findOne($_GET['id']) : new Text;
+
+ if ($model->load(Yii::$app->request->post()) && $model->save()) {
+
+ return Yii::$app->response->redirect(['/admin/text/index']);
+ }
+ return $this->render('save',['model'=>$model]);
+ }
+
+ public function actionDelete(){
+ $model = Text::findOne($_GET['id']);
+ $model->delete();
+ return Yii::$app->response->redirect(['/admin/text/index']);
+ }
+}
diff --git a/app/modules/admin/controllers/TypeController.php b/app/modules/admin/controllers/TypeController.php
new file mode 100755
index 0000000..9437f68
--- /dev/null
+++ b/app/modules/admin/controllers/TypeController.php
@@ -0,0 +1,66 @@
+ [
+ 'class' => AccessControl::className(),
+ //'only' => ['logout','index'],
+ 'rules' => [
+ [
+ 'actions' => ['index','save','delete'],
+ 'allow' => true,
+ 'roles' => ['admin'],
+ ],
+ ],
+ ],
+ 'verbs' => [
+ 'class' => VerbFilter::className(),
+ 'actions' => [
+ 'logout' => ['post'],
+ ],
+ ],
+ ];
+ }
+
+ public function actionIndex()
+ {
+ $dataProvider = new ActiveDataProvider([
+ 'query' => Type::find()->where('catalog_id=:catalog_id',[':catalog_id'=>$_GET['catID']])->orderBy('id'),
+ 'pagination' => [
+ 'pageSize' => 20,
+ ],
+ ]);
+ return $this->render('index',['dataProvider'=>$dataProvider]);
+ }
+
+ public function actionSave()
+ {
+ $model = (!empty($_GET['id'])) ? Type::findOne($_GET['id']) : new Type;
+
+ if ($model->load(Yii::$app->request->post()) && $model->save()) {
+
+ return Yii::$app->response->redirect(['/admin/type/index','catID'=>$_GET['catID']]);
+ }
+ return $this->render('save',['model'=>$model]);
+ }
+
+ public function actionDelete(){
+ $model = Type::findOne($_GET['id']);
+ $model->delete();
+ return Yii::$app->response->redirect(['/admin/type/index','catID'=>$_GET['catID']]);
+ }
+}
diff --git a/app/modules/admin/controllers/UsersController.php b/app/modules/admin/controllers/UsersController.php
new file mode 100755
index 0000000..ca7724c
--- /dev/null
+++ b/app/modules/admin/controllers/UsersController.php
@@ -0,0 +1,66 @@
+ [
+ 'class' => AccessControl::className(),
+ //'only' => ['logout','index'],
+ 'rules' => [
+ [
+ 'actions' => ['index','save','delete'],
+ 'allow' => true,
+ 'roles' => ['admin'],
+ ],
+ ],
+ ],
+ 'verbs' => [
+ 'class' => VerbFilter::className(),
+ 'actions' => [
+ 'logout' => ['post'],
+ ],
+ ],
+ ];
+ }
+
+ public function actionIndex()
+ {
+ $dataProvider = new ActiveDataProvider([
+ 'query' => User::find(),
+ 'pagination' => [
+ 'pageSize' => 20,
+ ],
+ ]);
+ return $this->render('index',['dataProvider'=>$dataProvider]);
+ }
+
+ public function actionSave()
+ {
+ $model = (!empty($_GET['id'])) ? User::findOne($_GET['id']) : new User;
+ $model->scenario = 'save';
+
+ if ($model->load(Yii::$app->request->post()) && $model->save()) {
+
+ return Yii::$app->response->redirect(['/admin/users/index']);
+ }
+ return $this->render('save',['model'=>$model]);
+ }
+
+ public function actionDelete(){
+ $model = User::findOne($_GET['id']);
+ $model->delete();
+ return Yii::$app->response->redirect(['/admin/users/index']);
+ }
+}
diff --git a/app/modules/admin/controllers/articlesController.php b/app/modules/admin/controllers/articlesController.php
new file mode 100755
index 0000000..fb9e0c3
--- /dev/null
+++ b/app/modules/admin/controllers/articlesController.php
@@ -0,0 +1,8 @@
+ [
+ 'class' => AccessControl::className(),
+ //'only' => ['logout','index'],
+ 'rules' => [
+ [
+ 'actions' => ['index','save','delete'],
+ 'allow' => true,
+ 'roles' => ['admin'],
+ ],
+ ],
+ ],
+ 'verbs' => [
+ 'class' => VerbFilter::className(),
+ 'actions' => [
+ 'logout' => ['post'],
+ ],
+ ],
+ ];
+ }
+
+ public function actionIndex()
+ {
+ $dataProvider = new ActiveDataProvider([
+ 'query' => Products::find(),
+ 'pagination' => [
+ 'pageSize' => 20,
+ ],
+ ]);
+ return $this->render('index',['dataProvider'=>$dataProvider]);
+ }
+
+ public function actionSave()
+ {
+ $model = (!empty($_GET['id'])) ? Products::findOne($_GET['id']) : new Products;
+
+ if ($model->load(Yii::$app->request->post()) && $model->save()) {
+
+ return Yii::$app->response->redirect(['/admin/products/index','catID'=>$_GET['catID']]);
+ }
+ return $this->render('save',['model'=>$model]);
+ }
+
+ public function actionDelete(){
+ $model = Products::findOne($_GET['id']);
+ $model->delete();
+ return Yii::$app->response->redirect(['/admin/products/index','catID'=>$_GET['catID']]);
+ }
+}
\ No newline at end of file
diff --git a/app/modules/admin/controllers/textController.php b/app/modules/admin/controllers/textController.php
new file mode 100755
index 0000000..917b11f
--- /dev/null
+++ b/app/modules/admin/controllers/textController.php
@@ -0,0 +1,65 @@
+ [
+ 'class' => AccessControl::className(),
+ //'only' => ['logout','index'],
+ 'rules' => [
+ [
+ 'actions' => ['index','save','delete'],
+ 'allow' => true,
+ 'roles' => ['admin'],
+ ],
+ ],
+ ],
+ 'verbs' => [
+ 'class' => VerbFilter::className(),
+ 'actions' => [
+ 'logout' => ['post'],
+ ],
+ ],
+ ];
+ }
+
+ public function actionIndex()
+ {
+ $dataProvider = new ActiveDataProvider([
+ 'query' => Text::find(),
+ 'pagination' => [
+ 'pageSize' => 20,
+ ],
+ ]);
+ return $this->render('index',['dataProvider'=>$dataProvider]);
+ }
+
+ public function actionSave()
+ {
+ $model = (!empty($_GET['id'])) ? Text::findOne($_GET['id']) : new Text;
+
+ if ($model->load(Yii::$app->request->post()) && $model->save()) {
+
+ return Yii::$app->response->redirect(['/admin/text/index']);
+ }
+ return $this->render('save',['model'=>$model]);
+ }
+
+ public function actionDelete(){
+ $model = Text::findOne($_GET['id']);
+ $model->delete();
+ return Yii::$app->response->redirect(['/admin/text/index']);
+ }
+}
diff --git a/app/modules/admin/messages/en/admin.php b/app/modules/admin/messages/en/admin.php
new file mode 100755
index 0000000..9d3edb4
--- /dev/null
+++ b/app/modules/admin/messages/en/admin.php
@@ -0,0 +1,4 @@
+ 'Admin panel',
+ ];
\ No newline at end of file
diff --git a/app/modules/admin/messages/ru/admin.php b/app/modules/admin/messages/ru/admin.php
new file mode 100755
index 0000000..41356d4
--- /dev/null
+++ b/app/modules/admin/messages/ru/admin.php
@@ -0,0 +1,4 @@
+ 'Админ панель',
+ ];
\ No newline at end of file
diff --git a/app/modules/admin/models/Articles.php b/app/modules/admin/models/Articles.php
new file mode 100755
index 0000000..9aba485
--- /dev/null
+++ b/app/modules/admin/models/Articles.php
@@ -0,0 +1,71 @@
+'jpg, gif, png', 'skipOnEmpty'=>true],
+
+ ];
+ }
+
+ public function attributeLabels()
+ {
+ return [
+ 'title'=>'Название',
+ 'body'=>'Описание',
+ 'date'=>'Дата',
+ 'image'=>'Изображения',
+ ];
+ }
+
+ public function beforeSave($insert) {
+ if (!$this->translit)
+ $this->translit = Translite::rusencode($this->title);
+
+
+ if($image = UploadedFile::getInstance($this,'image')){
+
+ $this->deleteImage($this->old_image);
+ //$this->image = $image;
+ $this->image = time() . '_' . rand(1, 1000) . '.' . $image->extension;
+ $image->saveAs('upload/articles/'.$this->image);
+
+ $resizeObj = new resize('upload/articles/'.$this->image);
+ $resizeObj -> resizeImage(100, 100, 'crop');
+ $resizeObj -> saveImage('upload/articles/ico/'.$this->image, 100);
+ }else $this->image = $this->old_image;
+
+ return parent::beforeSave($insert);
+ }
+
+ public function beforeDelete() {
+ $this->deleteImage($this->image);
+ return parent::beforeDelete();
+ }
+
+ public function deleteImage($file){
+ if(!empty($file)){
+ @unlink('upload/articles/'.$file);
+ @unlink('upload/articles/ico/'.$file);
+ }
+ }
+
+
+}
+
diff --git a/app/modules/admin/models/Brends.php b/app/modules/admin/models/Brends.php
new file mode 100755
index 0000000..7789b8b
--- /dev/null
+++ b/app/modules/admin/models/Brends.php
@@ -0,0 +1,50 @@
+'jpg, gif, png', 'skipOnEmpty'=>true],
+ ];
+ }
+
+ public function attributeLabels()
+ {
+ return [
+ 'name'=>'Название',
+ 'cost'=>'Цена',
+ 'sort'=>'Сорт.',
+ 'image'=>'Изображения',
+ ];
+ }
+
+ public function beforeSave($insert) {
+ return parent::beforeSave($insert);
+ }
+
+ public function beforeDelete() {
+ return parent::beforeDelete();
+ }
+
+
+
+
+
+
+
+}
diff --git a/app/modules/admin/models/Catalog.php b/app/modules/admin/models/Catalog.php
new file mode 100755
index 0000000..028bb7a
--- /dev/null
+++ b/app/modules/admin/models/Catalog.php
@@ -0,0 +1,116 @@
+'jpg, gif, png', 'skipOnEmpty'=>true],
+ ];
+ }
+
+ public function attributeLabels()
+ {
+ return [
+ 'name'=>'Название',
+ 'body'=>'Описание',
+ 'sort'=>'Сорт.',
+ 'parent_id'=>'Родитель',
+ 'image'=>'Изображения',
+ 'fasovka_name'=>'Название в место фасовки',
+ 'type_name'=>'Название в место типа',
+ 'brends_name'=>'Название в место производителя',
+ ];
+ }
+
+ public function beforeSave($insert) {
+
+ if(empty($this->parent_id))$this->parent_id = 0;
+
+ if (!$this->translit)
+ $this->translit = Translite::rusencode($this->name);
+
+
+ if($image = UploadedFile::getInstance($this,'image')){
+
+ $this->deleteImage($this->old_image);
+ //$this->image = $image;
+ $this->image = time() . '_' . rand(1, 1000) . '.' . $image->extension;
+ $image->saveAs('upload/catalog/'.$this->image);
+
+ $resizeObj = new resize('upload/catalog/'.$this->image);
+ $resizeObj -> resizeImage(195, 186, 'crop');
+ $resizeObj -> saveImage('upload/catalog/ico/'.$this->image, 100);
+ }else $this->image = $this->old_image;
+
+ return parent::beforeSave($insert);
+ }
+
+ public function beforeDelete() {
+ $this->deleteImage($this->image);
+ return parent::beforeDelete();
+ }
+
+ public function deleteImage($file){
+ if(!empty($file)){
+ @unlink('upload/catalog/'.$file);
+ @unlink('upload/catalog/ico/'.$file);
+ }
+ }
+
+
+
+ public function getDataTree($type = 'list',$parent_id = 0,$level = -1,&$list = array())
+ {
+ //global $key;
+ //print_r($arr);
+ $res = Catalog::find()->where(
+ 'parent_id=:parent_id',
+ [':parent_id'=>$parent_id]
+
+ )->orderBy('id')->all();
+ //print_r($res);exit;
+ $level++;
+
+ foreach($res as $row){
+ //$row->level = $level;
+ $row->name = str_repeat("---", $level) . $row->name;
+ $list[] = $row;
+ $this->getDataTree($type,$row->id,$level, $list);
+
+ }
+
+ return $list ;
+ }
+
+
+
+ public function getCatFasovka(){
+ return (!empty($this->fasovka_name)) ? $this->fasovka_name : 'Фасовка';
+ }
+
+ public function getCatType(){
+ return (!empty($this->type_name)) ? $this->type_name : 'Тип';
+ }
+
+ public function getCatBrends(){
+ return (!empty($this->brends_name)) ? $this->brends_name : 'Производители';
+ }
+}
+
diff --git a/app/modules/admin/models/ContactForm.php b/app/modules/admin/models/ContactForm.php
new file mode 100755
index 0000000..d4052ee
--- /dev/null
+++ b/app/modules/admin/models/ContactForm.php
@@ -0,0 +1,64 @@
+ 'Verification Code',
+ ];
+ }
+
+ /**
+ * Sends an email to the specified email address using the information collected by this model.
+ * @param string $email the target email address
+ * @return boolean whether the model passes validation
+ */
+ public function contact($email)
+ {
+ if ($this->validate()) {
+ Yii::$app->mailer->compose()
+ ->setTo($email)
+ ->setFrom([$this->email => $this->name])
+ ->setSubject($this->subject)
+ ->setTextBody($this->body)
+ ->send();
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/app/modules/admin/models/Export.php b/app/modules/admin/models/Export.php
new file mode 100755
index 0000000..2648dbc
--- /dev/null
+++ b/app/modules/admin/models/Export.php
@@ -0,0 +1,72 @@
+select(['products.*','cp.name as catalog_parent','cp.image as catalog_parent_image','c.name as catalog','c.image as catalog_image']);
+ $products->leftJoin('catalog c', 'c.id = products.catalog_id');
+ $products->leftJoin('catalog cp', 'cp.id = c.parent_id');
+
+
+ //print_R($products);exit;
+ foreach ($products->all() as $product){
+
+ $mods = [];
+ foreach($product->mods as $m){
+ $mods[] = $m->art.'='.$m->name.'='.$m->cost;
+ }
+
+ $fotos = [];
+ foreach($product->fotos as $f){
+ $fotos[] = $f->image;
+ }
+
+ $types = [];
+ foreach($product->type as $t){
+ $types[] = $t->name;
+ }
+
+ $brends = [];
+ foreach($product->brends as $b){
+ $brends[] = $b->name;
+ }
+
+ $fasovkas = [];
+ foreach($product->fasovka as $f){
+ $fasovkas[] = $f->name;
+ }
+
+ $list = [$product->catalog_parent,
+ $product->catalog_parent_image,
+ $product->catalog,
+ $product->catalog_image,
+ $product->art . '=' . $product->name,
+ $product->image,
+ $product->char,
+ $product->body,
+ implode('|',$mods),
+ implode('|',$fotos),
+ implode('|',$types),
+ implode('|',$brends),
+ implode('|',$fasovkas),
+ $product->new,
+ $product->top,
+ $product->akciya,
+ $product->out_of_stock,
+ ];
+ //print_r($list);
+ fputcsv($handle,$list,';');
+ }
+ fclose($handle);
+ }
+
+}
\ No newline at end of file
diff --git a/app/modules/admin/models/Fasovka.php b/app/modules/admin/models/Fasovka.php
new file mode 100755
index 0000000..aeda850
--- /dev/null
+++ b/app/modules/admin/models/Fasovka.php
@@ -0,0 +1,50 @@
+'jpg, gif, png', 'skipOnEmpty'=>true],
+ ];
+ }
+
+ public function attributeLabels()
+ {
+ return [
+ 'name'=>'Название',
+ 'cost'=>'Цена',
+ 'sort'=>'Сорт.',
+ 'image'=>'Изображения',
+ ];
+ }
+
+ public function beforeSave($insert) {
+ return parent::beforeSave($insert);
+ }
+
+ public function beforeDelete() {
+ return parent::beforeDelete();
+ }
+
+
+
+
+
+
+
+}
diff --git a/app/modules/admin/models/Fotos.php b/app/modules/admin/models/Fotos.php
new file mode 100755
index 0000000..568c44f
--- /dev/null
+++ b/app/modules/admin/models/Fotos.php
@@ -0,0 +1,74 @@
+'jpg, gif, png', 'skipOnEmpty'=>true],
+ ];
+ }
+
+ public function attributeLabels()
+ {
+ return [
+ 'name'=>'Название',
+ 'cost'=>'Цена',
+ 'sort'=>'Сорт.',
+ 'image'=>'Изображения',
+ ];
+ }
+
+ public function beforeSave($insert) {
+ if($image = UploadedFile::getInstance($this,'image')){
+
+ $this->deleteImage($this->old_image);
+ //$this->image = $image;
+ $this->image = time() . '_' . rand(1, 1000) . '.' . $image->extension;
+ $image->saveAs('upload/fotos/'.$this->image);
+
+ $resizeObj = new resize('upload/fotos/'.$this->image);
+ $resizeObj -> resizeImage(100, 100, 'crop');
+ $resizeObj -> saveImage('upload/fotos/ico/'.$this->image, 100);
+ $resizeObj -> resizeImage(400, 400, 'crop');
+ $resizeObj -> saveImage('upload/fotos/big/'.$this->image, 100);
+ }else $this->image = $this->old_image;
+
+ return parent::beforeSave($insert);
+ }
+
+ public function beforeDelete() {
+ $this->deleteImage($this->image);
+ return parent::beforeDelete();
+ }
+
+ public function deleteImage($file){
+ if(!empty($file)){
+ @unlink('upload/fotos/'.$file);
+ @unlink('upload/fotos/ico/'.$file);
+ @unlink('upload/fotos/big/'.$file);
+ }
+ }
+
+
+
+
+
+
+
+}
diff --git a/app/modules/admin/models/Import.php b/app/modules/admin/models/Import.php
new file mode 100755
index 0000000..67bedd1
--- /dev/null
+++ b/app/modules/admin/models/Import.php
@@ -0,0 +1,313 @@
+'csv', 'skipOnEmpty'=>false],
+
+ ];
+ }
+
+ /**
+ * @return array customized attribute labels
+ */
+ public function attributeLabels()
+ {
+ return [
+ 'file' => 'Файл .csv',
+ ];
+ }
+
+
+ public function go()
+ {
+
+ $db = Yii::$app->db;
+ $this->file = UploadedFile::getInstance($this, 'file');
+
+ if (($handle = fopen($this->file->tempName, "r")) !== FALSE) {
+ while (($data = fgetcsv($handle, 100000, ";")) !== FALSE) {
+ // print_r($data);
+ $catalogParent = trim($data[0]);
+ if(!$catalogParent)continue;
+ $catalogParent_image = trim($data[1]);
+ $catalog = trim($data[2]);
+ $catalog_image = trim($data[3]);
+ $p = explode('=',trim($data[4]));
+ $art = trim($p[0]);
+ $product = trim($p[1]);
+ $product_image = trim($data[5]);
+ $product_char = trim($data[6]);
+ $product_body = trim($data[7]);
+ $mods = (!empty($data[8])) ? explode('|',trim($data[8])) : [];
+ $fotos = (!empty($data[9])) ? explode('|',trim($data[9])) : [];
+
+ $types = (!empty($data[10])) ? explode('|',trim($data[10])) : [];
+
+ $brends = (!empty($data[11])) ? explode('|',trim($data[11])) : [];
+ $fasovkas = (!empty($data[12])) ? explode('|',trim($data[12])) : [];
+ $product_new = (!empty($data[13])) ? trim($data[13]) : 0;
+ $product_top = (!empty($data[14])) ? trim($data[14]) : 0;
+ $product_akciya = (!empty($data[15])) ? trim($data[15]) : 0;
+ $product_out_of_stock = (!empty($data[16])) ? trim($data[16]) : 0;
+
+ //*********catalogParent*********//
+ $modelCatalog = Catalog::find()->where('name=:name and parent_id=0',[':name'=>$catalogParent])->one();
+
+ if(empty($modelCatalog->id)){
+ $db->createCommand()->insert('catalog', [
+ 'name' => $catalogParent,
+ 'image' => $catalogParent_image,
+ 'translit' => Translite::rusencode($catalogParent),
+ ])->execute();
+ $catalogParent_id = Yii::$app->db->lastInsertID;
+ }else{
+
+ $db ->createCommand()
+ ->update('catalog', [
+ 'name' => $catalogParent,
+ 'image' => $catalogParent_image,
+ 'translit' => Translite::rusencode($catalogParent),
+ ], 'id = '.$modelCatalog->id)
+ ->execute();
+ $catalogParent_id = $modelCatalog->id;
+
+ }
+ if(is_file('upload/catalog/'.$catalogParent_image)){
+ $resizeObj = new resize('upload/catalog/'.$catalogParent_image);
+ $resizeObj -> resizeImage(195, 186, 'crop');
+ $resizeObj -> saveImage('upload/catalog/ico/'.$catalogParent_image, 100);
+ }
+ //*********END catalogParent*********//
+
+ //*********catalog*********//
+ $modelCatalog = Catalog::find()->where('name=:name and parent_id='.$catalogParent_id,[':name'=>$catalog])->one();
+
+ if(empty($modelCatalog->id)){
+ $db->createCommand()->insert('catalog', [
+ 'parent_id'=>$catalogParent_id,
+ 'name' => $catalog,
+ 'image' => $catalog_image,
+ 'translit' => Translite::rusencode($catalog),
+ ])->execute();
+ $catalog_id = Yii::$app->db->lastInsertID;
+ }else{
+
+ $db ->createCommand()
+ ->update('catalog', [
+ 'parent_id'=>$catalogParent_id,
+ 'name' => $catalog,
+ 'image' => $catalog_image,
+ 'translit' => Translite::rusencode($catalog),
+ ], 'id = '.$modelCatalog->id)
+ ->execute();
+ $catalog_id = $modelCatalog->id;
+
+ }
+ if(is_file('upload/catalog/'.$catalog_image)){
+ $resizeObj = new resize('upload/catalog/'.$catalog_image);
+ $resizeObj -> resizeImage(195, 186, 'crop');
+ $resizeObj -> saveImage('upload/catalog/ico/'.$catalog_image, 100);
+ }
+ //*********END catalog*********//
+
+ //*********product*********//
+ $modelProducts = Products::find()->where('art=:art',[':art'=>$art])->one();
+
+ if(empty($modelProducts->id)){
+ $db->createCommand()->insert('products', [
+ 'catalog_id'=>$catalog_id,
+ 'name' => $product,
+ 'art' => $art,
+ 'image' => $product_image,
+ 'translit' => Translite::rusencode($product),
+ 'char'=>$product_char,
+ 'body'=>$product_body,
+ 'new'=>$product_new,
+ 'top'=>$product_top,
+ 'akciya'=>$product_akciya,
+ 'out_of_stock'=>$product_out_of_stock,
+ ])->execute();
+ $product_id = Yii::$app->db->lastInsertID;
+ }else{
+
+ $db ->createCommand()
+ ->update('products', [
+ 'catalog_id'=>$catalog_id,
+ 'name' => $product,
+ 'art' => $art,
+ 'image' => $product_image,
+ 'translit' => Translite::rusencode($product),
+ 'char'=>$product_char,
+ 'body'=>$product_body,
+ 'new'=>$product_new,
+ 'top'=>$product_top,
+ 'akciya'=>$product_akciya,
+ 'out_of_stock'=>$product_out_of_stock,
+ ], 'id = '.$modelProducts->id)
+ ->execute();
+ $product_id = $modelProducts->id;
+
+ }
+ if(is_file('upload/products/'.$product_image)){
+ $resizeObj = new resize('upload/products/'.$product_image);
+ $resizeObj -> resizeImage(180, 240, 'landscape');
+ $resizeObj -> saveImage('upload/products/ico/'.$product_image, 100);
+ $resizeObj -> resizeImage(400, 400, 'landscape');
+ $resizeObj -> saveImage('upload/products/big/'.$product_image, 100);
+
+ }
+ //*********END product*********//
+
+ //*********mods*********//
+ foreach($mods as $mod){
+ $mod_arr = explode('=',$mod);
+ if(count($mod_arr)<2)continue;
+ $mod_art = trim($mod_arr[0]);
+ $mod_name = trim($mod_arr[1]);
+ $mod_cost = trim($mod_arr[2]);
+ $fields = [
+ 'product_id'=>$product_id,
+ 'art'=>$mod_art,
+ 'name'=>$mod_name,
+ 'cost'=>$mod_cost,
+ ];
+ $modelMod = Mod::find()->where('art=:art',[':art'=>$mod_art])->one();
+ if(empty($modelMod->id)){
+ $db->createCommand()->insert('mod', $fields)->execute();
+ }else{
+ $db->createCommand()->update('mod', $fields, 'id = '.$modelMod->id)->execute();
+ }
+ }
+ //*********END mods*********//
+ //
+ //*********fotos*********//
+ foreach($fotos as $foto){
+ $fields = [
+ 'product_id'=>$product_id,
+ 'image'=>$foto,
+ ];
+ $modelFotos = Fotos::find()->where('image=:image',[':image'=>$foto])->one();
+ if(empty($modelFotos->id)){
+ $db->createCommand()->insert('products_fotos', $fields)->execute();
+ }else{
+ $db->createCommand()->update('products_fotos', $fields, 'id = '.$modelFotos->id)->execute();
+ }
+ if(is_file('upload/fotos/'.$foto)){
+ $resizeObj = new resize('upload/fotos/'.$foto);
+ $resizeObj -> resizeImage(100, 100, 'crop');
+ $resizeObj -> saveImage('upload/fotos/ico/'.$foto, 100);
+ $resizeObj -> resizeImage(400, 400, 'crop');
+ $resizeObj -> saveImage('upload/fotos/big/'.$foto, 100);
+ }
+ }
+ //*********END fotos*********//
+
+ //*********types*********//
+ ProductsType::deleteAll(['product_id' => $product_id]);
+ foreach($types as $type){
+ $fields = [
+ 'catalog_id'=>$catalog_id,
+ 'name'=>$type,
+ ];
+ $modelType = Type::find()->where('name=:name and catalog_id=:catalog_id',[':name'=>$type,':catalog_id'=>$catalog_id])->one();
+ if(empty($modelType->id)){
+ $db->createCommand()->insert('catalog_type', $fields)->execute();
+ $type_id = Yii::$app->db->lastInsertID;
+ }else{
+ $db->createCommand()->update('catalog_type', $fields, 'id = '.$modelType->id)->execute();
+ $type_id = $modelType->id;
+
+ }
+ $db->createCommand()->insert('productsType', ['type_id'=>$type_id,'product_id'=>$product_id])->execute();
+
+
+ }
+ //*********END types*********//
+ //*********brends*********//
+ ProductsBrends::deleteAll(['product_id' => $product_id]);
+ foreach($brends as $brend){
+ $fields = [
+ 'catalog_id'=>$catalog_id,
+ 'name'=>$brend,
+ ];
+ $modelBrends = Brends::find()->where('name=:name and catalog_id=:catalog_id',[':name'=>$brend,':catalog_id'=>$catalog_id])->one();
+ if(empty($modelBrends->id)){
+ $db->createCommand()->insert('catalog_brends', $fields)->execute();
+ $brend_id = Yii::$app->db->lastInsertID;
+ }else{
+ $db->createCommand()->update('catalog_brends', $fields, 'id = '.$modelBrends->id)->execute();
+ $brend_id = $modelBrends->id;
+
+ }
+ $db->createCommand()->insert('productsBrends', ['brend_id'=>$brend_id,'product_id'=>$product_id])->execute();
+
+
+ }
+ //*********END brends*********//
+ //*********fasovka*********//
+ ProductsFasovka::deleteAll(['product_id' => $product_id]);
+ foreach($fasovkas as $fasovka){
+ $fields = [
+ 'catalog_id'=>$catalog_id,
+ 'name'=>$fasovka,
+ ];
+ $modelFasovka = Fasovka::find()->where('name=:name and catalog_id=:catalog_id',[':name'=>$fasovka,':catalog_id'=>$catalog_id])->one();
+ if(empty($modelFasovka->id)){
+ $db->createCommand()->insert('catalog_fasovka', $fields)->execute();
+ $fasovka_id = Yii::$app->db->lastInsertID;
+ }else{
+ $db->createCommand()->update('catalog_fasovka', $fields, 'id = '.$modelFasovka->id)->execute();
+ $fasovka_id = $modelFasovka->id;
+
+ }
+ $db->createCommand()->insert('productsFasovka', ['fasovka_id'=>$fasovka_id,'product_id'=>$product_id])->execute();
+
+
+ }
+ //*********END fasovka*********//
+
+ // print"";print_r($data);
+
+ }
+ fclose($handle);
+ }
+
+
+
+
+
+
+
+ return true;
+
+ }
+}
\ No newline at end of file
diff --git a/app/modules/admin/models/LoginForm.php b/app/modules/admin/models/LoginForm.php
new file mode 100755
index 0000000..ac92068
--- /dev/null
+++ b/app/modules/admin/models/LoginForm.php
@@ -0,0 +1,88 @@
+'Логин',
+ 'password'=>'Пароль',
+ 'rememberMe'=>'Запомнить',
+ ];
+ }
+
+ /**
+ * Validates the password.
+ * This method serves as the inline validation for password.
+ *
+ * @param string $attribute the attribute currently being validated
+ * @param array $params the additional name-value pairs given in the rule
+ */
+ public function validatePassword($attribute, $params)
+ {
+ if (!$this->hasErrors()) {
+ $user = $this->getUser();
+
+ if (!$user || !$user->validatePassword($this->password)) {
+ $this->addError($attribute, 'Incorrect username or password.');
+ }
+ }
+ }
+
+ /**
+ * Logs in a user using the provided username and password.
+ * @return boolean whether the user is logged in successfully
+ */
+ public function login()
+ {
+ if ($this->validate()) {
+ return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600*24*30 : 0);
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Finds user by [[username]]
+ *
+ * @return User|null
+ */
+ public function getUser()
+ {
+ if ($this->_user === false) {
+ $this->_user = User::findByUsername($this->username);
+ }
+
+ return $this->_user;
+ }
+}
diff --git a/app/modules/admin/models/Menu.php b/app/modules/admin/models/Menu.php
new file mode 100755
index 0000000..2cade05
--- /dev/null
+++ b/app/modules/admin/models/Menu.php
@@ -0,0 +1,32 @@
+'Url',
+ 'name'=>'Название',
+ 'sort'=>'Сорт.',
+ ];
+ }
+
+
+}
diff --git a/app/modules/admin/models/Mod.php b/app/modules/admin/models/Mod.php
new file mode 100755
index 0000000..8a182bb
--- /dev/null
+++ b/app/modules/admin/models/Mod.php
@@ -0,0 +1,56 @@
+'jpg, gif, png', 'skipOnEmpty'=>true],
+ ];
+ }
+
+ public function attributeLabels()
+ {
+ return [
+ 'art'=>'Артикуль',
+ 'name'=>'Название',
+ 'cost'=>'Цена',
+ 'sort'=>'Сорт.',
+ 'image'=>'Изображения',
+ ];
+ }
+
+ public function beforeSave($insert) {
+ return parent::beforeSave($insert);
+ }
+
+ public function beforeDelete() {
+ return parent::beforeDelete();
+ }
+
+ public function getProduct(){
+ return $this->hasOne(Products::className(), ['id' => 'product_id']);
+ }
+
+
+
+
+
+
+
+
+}
diff --git a/app/modules/admin/models/News.php b/app/modules/admin/models/News.php
new file mode 100755
index 0000000..cd4b2ef
--- /dev/null
+++ b/app/modules/admin/models/News.php
@@ -0,0 +1,74 @@
+'jpg, gif, png', 'skipOnEmpty'=>true],
+
+ ];
+ }
+
+ public function attributeLabels()
+ {
+ return [
+ 'title'=>'Название',
+ 'body'=>'Описание',
+ 'date'=>'Дата',
+ 'image'=>'Изображения',
+ ];
+ }
+
+ public function beforeSave($insert) {
+ if (!$this->translit)
+ $this->translit = Translite::rusencode($this->title);
+
+
+ if($image = UploadedFile::getInstance($this,'image')){
+
+ $this->deleteImage($this->old_image);
+ //$this->image = $image;
+ $this->image = time() . '_' . rand(1, 1000) . '.' . $image->extension;
+ $image->saveAs('upload/news/'.$this->image);
+
+ $resizeObj = new resize('upload/news/'.$this->image);
+ $resizeObj -> resizeImage(180, 125, 'crop');
+ $resizeObj -> saveImage('upload/news/ico/'.$this->image, 100);
+ $resizeObj -> resizeImage(400, 400, 'crop');
+ $resizeObj -> saveImage('upload/news/big/'.$this->image, 100);
+ }else $this->image = $this->old_image;
+
+ return parent::beforeSave($insert);
+ }
+
+ public function beforeDelete() {
+ $this->deleteImage($this->image);
+ return parent::beforeDelete();
+ }
+
+ public function deleteImage($file){
+ if(!empty($file)){
+ @unlink('upload/news/'.$file);
+ @unlink('upload/news/ico/'.$file);
+ @unlink('upload/news/big/'.$file);
+ }
+ }
+
+
+}
+
diff --git a/app/modules/admin/models/Orders.php b/app/modules/admin/models/Orders.php
new file mode 100755
index 0000000..b109b14
--- /dev/null
+++ b/app/modules/admin/models/Orders.php
@@ -0,0 +1,49 @@
+'jpg, gif, png', 'skipOnEmpty'=>true],
+ ];
+ }
+
+ public function attributeLabels()
+ {
+ return [
+ 'id'=>'№ заказа',
+ 'name'=>'Имя',
+ 'phone'=>'Телефон',
+ 'adress'=>'Адрес',
+ 'body'=>'Сообщение',
+ 'reserve'=>'Резерв',
+ 'status'=>'Статус',
+ 'email'=>'E-mail',
+ 'patronymic'=>'Очество',
+ 'surname'=>'Фамилия',
+ 'total'=>'Сумма',
+ 'comment'=>'Комментарий менеджера',
+ ];
+ }
+
+ public function beforeSave($insert) {
+ return parent::beforeSave($insert);
+ }
+
+ public function beforeDelete() {
+ return parent::beforeDelete();
+ }
+
+}
\ No newline at end of file
diff --git a/app/modules/admin/models/OrdersProducts.php b/app/modules/admin/models/OrdersProducts.php
new file mode 100755
index 0000000..f66fd93
--- /dev/null
+++ b/app/modules/admin/models/OrdersProducts.php
@@ -0,0 +1,32 @@
+'Продукт',
+ 'name'=>'Вид',
+ 'art'=>'Артикул',
+ 'cost'=>'Цена за один',
+ 'count'=>'Кол.',
+ 'sum_cost'=>'Сумма',
+ ];
+ }
+}
\ No newline at end of file
diff --git a/app/modules/admin/models/Products.php b/app/modules/admin/models/Products.php
new file mode 100755
index 0000000..90399ea
--- /dev/null
+++ b/app/modules/admin/models/Products.php
@@ -0,0 +1,200 @@
+'jpg, gif, png',
+ 'skipOnEmpty'=>true
+ ],
+ ];
+ }
+
+ public function attributeLabels()
+ {
+ return [
+ 'name'=>'Название',
+ 'body'=>'Описание',
+ 'char'=>'Характеристики',
+ 'sort'=>'Сорт.',
+ 'image'=>'Изображения',
+ 'fasovka'=>'Фасовка',
+ 'type'=>'Типы',
+ 'brends'=>'Производители',
+ 'top'=>'Топ',
+ 'new'=>'Новинка',
+ 'akciya'=>'Акция',
+ 'out_of_stock'=>'Нет в наличии',
+ 'similar'=>'Похожие товары',
+ 'featured'=>'Рекоммендуемые товары',
+ ];
+ }
+
+ public function beforeSave($insert) {
+
+
+ if (!$this->translit)
+ $this->translit = Translite::rusencode($this->name);
+
+
+ if($image = UploadedFile::getInstance($this,'image')){
+
+ $this->deleteImage($this->old_image);
+ //$this->image = $image;
+ $this->image = time() . '_' . rand(1, 1000) . '.' . $image->extension;
+ $image->saveAs('upload/products/'.$this->image);
+
+ $resizeObj = new resize('upload/products/'.$this->image);
+ $resizeObj -> resizeImage(180, 240, 'landscape');
+ $resizeObj -> saveImage('upload/products/ico/'.$this->image, 100);
+ $resizeObj -> resizeImage(400, 400, 'landscape');
+ $resizeObj -> saveImage('upload/products/big/'.$this->image, 100);
+ }else $this->image = $this->old_image;
+
+
+
+ return parent::beforeSave($insert);
+ }
+
+ public function afterSave($insert, $changedAttributes) {
+ if(!$insert) {
+ ProductsFasovka::deleteAll(['product_id' => $this->id]);
+ }
+ if(is_array($this->fasovka)) {
+ foreach ($this->fasovka as $fasovka) {
+ $ProductsFasovka = new ProductsFasovka();
+ $ProductsFasovka->product_id = $this->id;
+ $ProductsFasovka->fasovka_id = $fasovka;
+ $ProductsFasovka->save();
+ }
+ }
+
+
+ if(!$insert) {
+ ProductsType::deleteAll(['product_id' => $this->id]);
+ }
+ if(is_array($this->type)) {
+ foreach ($this->type as $type) {
+ $ProductsType = new ProductsType();
+ $ProductsType->product_id = $this->id;
+ $ProductsType->type_id = $type;
+ $ProductsType->save();
+ }
+ }
+
+
+ if(!$insert) {
+ ProductsBrends::deleteAll(['product_id' => $this->id]);
+ }
+ if(is_array($this->brends)) {
+ foreach ($this->brends as $brend) {
+ $ProductsBrends = new ProductsBrends();
+ $ProductsBrends->product_id = $this->id;
+ $ProductsBrends->brend_id = $brend;
+ $ProductsBrends->save();
+ }
+ }
+
+ return parent::afterSave($insert, $changedAttributes);
+
+ }
+
+ public function beforeDelete() {
+ $this->deleteImage($this->image);
+ return parent::beforeDelete();
+ }
+
+ public function getFasovka()
+ {
+ return $this->hasMany(Fasovka::className(), ['id' => 'fasovka_id'])->viaTable(ProductsFasovka::tableName(), ['product_id' => 'id']);
+ }
+
+ public function setFasovka($fasovka)
+ {
+ $this->fasovka = $fasovka;
+ }
+
+ public function getType()
+ {
+ return $this->hasMany(Type::className(), ['id' => 'type_id'])->viaTable(ProductsType::tableName(), ['product_id' => 'id']);
+ }
+
+ public function setType($type)
+ {
+ $this->type = $type;
+ }
+
+ public function getBrends()
+ {
+ return $this->hasMany(Brends::className(), ['id' => 'brend_id'])->viaTable(ProductsBrends::tableName(), ['product_id' => 'id']);
+ }
+
+ public function setBrends($brends)
+ {
+ $this->brends = $brends;
+ }
+
+
+ public function getCatalog()
+ {
+ return $this->hasOne(Catalog::className(), ['id' => 'catalog_id']);
+ }
+
+ public function getMods()
+ {
+ return $this->hasMany(Mod::className(), ['product_id' => 'id']);
+ }
+
+ public function getFotos()
+ {
+ return $this->hasMany(Fotos::className(), ['product_id' => 'id']);
+ }
+
+ public function deleteImage($file){
+ if(!empty($file)){
+ @unlink('upload/products/'.$file);
+ @unlink('upload/products/ico/'.$file);
+ @unlink('upload/products/big/'.$file);
+ }
+ }
+
+
+
+
+
+
+}
diff --git a/app/modules/admin/models/ProductsBrends.php b/app/modules/admin/models/ProductsBrends.php
new file mode 100755
index 0000000..35978a3
--- /dev/null
+++ b/app/modules/admin/models/ProductsBrends.php
@@ -0,0 +1,13 @@
+'jpg, gif, png', 'skipOnEmpty'=>true],
+
+ ];
+ }
+
+ public function attributeLabels()
+ {
+ return [
+ 'title'=>'Название',
+ 'body'=>'Описание',
+ 'date'=>'Дата',
+ 'image'=>'Изображения',
+ ];
+ }
+
+ public function beforeSave($insert) {
+
+
+ if($image = UploadedFile::getInstance($this,'image')){
+
+ $this->deleteImage($this->old_image);
+ //$this->image = $image;
+ $this->image = time() . '_' . rand(1, 1000) . '.' . $image->extension;
+ $image->saveAs('upload/slider/'.$this->image);
+
+ }else $this->image = $this->old_image;
+
+ return parent::beforeSave($insert);
+ }
+
+ public function beforeDelete() {
+ $this->deleteImage($this->image);
+ return parent::beforeDelete();
+ }
+
+ public function deleteImage($file){
+ if(!empty($file)){
+ @unlink('upload/slider/'.$file);
+ }
+ }
+
+
+}
+
diff --git a/app/modules/admin/models/Text.php b/app/modules/admin/models/Text.php
new file mode 100755
index 0000000..c67c240
--- /dev/null
+++ b/app/modules/admin/models/Text.php
@@ -0,0 +1,40 @@
+'Название',
+ 'body'=>'Описание',
+ 'sort'=>'Сорт.',
+ ];
+ }
+
+ public function beforeSave($insert) {
+ if (!$this->translit)
+ $this->translit = Translite::rusencode($this->title);
+
+ return parent::beforeSave($insert);
+ }
+
+
+}
+
diff --git a/app/modules/admin/models/Type.php b/app/modules/admin/models/Type.php
new file mode 100755
index 0000000..65d476b
--- /dev/null
+++ b/app/modules/admin/models/Type.php
@@ -0,0 +1,50 @@
+'jpg, gif, png', 'skipOnEmpty'=>true],
+ ];
+ }
+
+ public function attributeLabels()
+ {
+ return [
+ 'name'=>'Название',
+ 'cost'=>'Цена',
+ 'sort'=>'Сорт.',
+ 'image'=>'Изображения',
+ ];
+ }
+
+ public function beforeSave($insert) {
+ return parent::beforeSave($insert);
+ }
+
+ public function beforeDelete() {
+ return parent::beforeDelete();
+ }
+
+
+
+
+
+
+
+}
diff --git a/app/modules/admin/models/User.php b/app/modules/admin/models/User.php
new file mode 100755
index 0000000..7ebd892
--- /dev/null
+++ b/app/modules/admin/models/User.php
@@ -0,0 +1,131 @@
+'save'],
+ [['password_repeat'], 'password_repeat', 'on'=>'save'],
+ [['username'], 'is_username', 'on'=>'save'],
+ ];
+ }
+
+ public function attributeLabels()
+ {
+ return [
+ 'username'=>'Логин',
+ 'password'=>'Пароль',
+ 'password_repeat'=>'Повторить пароль',
+ ];
+ }
+
+ public function password_repeat($attribute){
+ if($this->password != $this->password_repeat)
+ $this->addError('password_repeat','Не правильный повтор пароля.');
+ }
+
+ public function is_username($attribute)
+ {
+ if(User::find()
+ //->where( ['username' => $this->username],['id!='.$_GET['id']] )
+ ->where('username = :username and id != :id', [':username' => $this->username, ':id' => $this->id])
+ ->exists())
+ $this->addError('username','Такой пользователь уже есть.');
+ }
+
+
+ public function afterSave($insert, $changedAttributes)
+ {
+ parent::afterSave($insert, $changedAttributes);
+ // установка роли пользователя
+ $auth = Yii::$app->authManager;
+ $role = $auth->getRole('admin');
+ if (!$insert) {
+ $auth->revokeAll($this->id);
+ }
+ $auth->assign($role, $this->id);
+ }
+
+
+ public function afterDelete(){
+ parent::afterDelete();
+ $auth = Yii::$app->authManager;
+ $auth->revokeAll($this->id);
+ }
+
+
+ /**
+ * @inheritdoc
+ */
+ public static function findIdentity($id)
+ {
+ return static::findOne($id);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public static function findIdentityByAccessToken($token, $type = null)
+ {
+ return static::findOne(['access_token' => $token]);
+ }
+
+ /**
+ * Finds user by username
+ *
+ * @param string $username
+ * @return static|null
+ */
+ public static function findByUsername($username)
+ {
+ return static::findOne(['username' => $username]);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getAuthKey()
+ {
+ return $this->authKey;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function validateAuthKey($authKey)
+ {
+ return $this->authKey === $authKey;
+ }
+
+ /**
+ * Validates password
+ *
+ * @param string $password password to validate
+ * @return boolean if password provided is valid for current user
+ */
+ public function validatePassword($password)
+ {
+ return $this->password === $password;
+ }
+}
diff --git a/app/modules/admin/views/articles/_form.php b/app/modules/admin/views/articles/_form.php
new file mode 100755
index 0000000..d8d8981
--- /dev/null
+++ b/app/modules/admin/views/articles/_form.php
@@ -0,0 +1,47 @@
+
+
+ 'form',
+ 'options' => ['enctype' => 'multipart/form-data'],
+
+ ]); ?>
+ = $form->field($model,'date')->widget(\yii\jui\DatePicker::className(),['clientOptions' => [],'options' => ['class'=>'form-control','style'=>'width:150px;'],'dateFormat' => 'yyyy-MM-dd','language' => 'ru',]) ?>
+
+ = $form->field($model, 'title') ?>
+
+ /*$form->field($model, 'translit', [
+ 'addon' => ['prepend' => ['content'=>'@']]
+ ]);*/?>
+ = $form->field($model, 'translit',[
+ 'inputTemplate' => 'articles/ {input}
',
+ ]);?>
+
+ = $form->field($model, 'image')->fileInput() ?>
+
+ = $form->field($model, 'old_image')->hiddenInput(['value'=>$model->image])->label(false); ?>
+
+
+ =$form->field($model, 'body')->widget(CKEditor::className(),[
+ 'editorOptions' => ElFinder::ckeditorOptions('elfinder',[/* Some CKEditor Options */]),
+ ]);
+ ?>
+
+ = $form->field($model, 'meta_title') ?>
+
+ = $form->field($model, 'meta_keywords') ?>
+
+ = $form->field($model, 'meta_description') ?>
+
+
+ = Html::submitButton('Сохранить', ['class' => 'btn btn-primary', 'name' => 'login-button']) ?>
+
+
+
+
+
diff --git a/app/modules/admin/views/articles/index.php b/app/modules/admin/views/articles/index.php
new file mode 100755
index 0000000..845267c
--- /dev/null
+++ b/app/modules/admin/views/articles/index.php
@@ -0,0 +1,43 @@
+
+use yii\helpers\Html;
+use yii\grid\GridView;
+
+$this->title = 'Статьи';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+Статьи
+= Html::a('Создать', ['/admin/articles/save'], ['class'=>'btn btn-success']) ?>
+= GridView::widget([
+ 'dataProvider' => $dataProvider,
+ 'columns' => [
+ [
+ 'attribute' => 'id',
+ 'value'=>'id',
+ 'contentOptions'=>['style'=>'width: 70px;']
+ ],
+ [
+ 'attribute' => 'image',
+ 'format' => 'image',
+ 'value'=>function($data) { return Yii::$app->request->BaseUrl.'/upload/articles/ico/'.$data->image; },
+ 'contentOptions'=>['style'=>'width: 100px;']
+ ],
+ [
+ 'attribute' => 'title',
+ 'value'=>'title',
+ //'contentOptions'=>['style'=>'max-width: 300px;']
+ ],
+ [
+ 'class' => 'yii\grid\ActionColumn',
+ 'template' => '{update} {delete}',
+ 'buttons' => [
+ 'update' => function ($url, $model) {
+ return Html::a(' ', ['/admin/articles/save','id'=>$model->id],
+ [
+ 'title' => "Редактировать",
+ ]);
+ }
+ ],
+ 'contentOptions'=>['style'=>'width: 70px;']
+ ],
+ ],
+]) ?>
diff --git a/app/modules/admin/views/articles/save.php b/app/modules/admin/views/articles/save.php
new file mode 100755
index 0000000..9073432
--- /dev/null
+++ b/app/modules/admin/views/articles/save.php
@@ -0,0 +1,6 @@
+
+$this->title = 'Добавить статью';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+Добавить статью
+= $this->render('_form',['model'=>$model]) ?>
\ No newline at end of file
diff --git a/app/modules/admin/views/brends/_form.php b/app/modules/admin/views/brends/_form.php
new file mode 100755
index 0000000..2062615
--- /dev/null
+++ b/app/modules/admin/views/brends/_form.php
@@ -0,0 +1,29 @@
+
+
+ 'form',
+ 'options' => ['enctype' => 'multipart/form-data'],
+
+ ]); ?>
+
+ = $form->field($model, 'catalog_id')->hiddenInput(['value'=>$_GET['catID']])->label(false); ?>
+
+ = $form->field($model, 'name') ?>
+
+
+
+
+
+ = Html::submitButton('Сохранить', ['class' => 'btn btn-primary', 'name' => 'login-button']) ?>
+
+
+
+
+
diff --git a/app/modules/admin/views/brends/index.php b/app/modules/admin/views/brends/index.php
new file mode 100755
index 0000000..58edc31
--- /dev/null
+++ b/app/modules/admin/views/brends/index.php
@@ -0,0 +1,47 @@
+
+use yii\helpers\Html;
+use yii\grid\GridView;
+
+$this->title = 'Бренды';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+Бренды
+
+= Html::a('Создать', ['/admin/brends/save','catID'=>$_GET['catID']], ['class'=>'btn btn-success']) ?>
+= GridView::widget([
+ 'dataProvider' => $dataProvider,
+ 'columns' => [
+ [
+ 'attribute' => 'id',
+ 'value'=>'id',
+ 'contentOptions'=>['style'=>'width: 70px;']
+ ],
+ [
+ 'attribute' => 'name',
+ 'value'=>'name',
+ //'contentOptions'=>['style'=>'max-width: 300px;']
+ ],
+
+ [
+ 'class' => 'yii\grid\ActionColumn',
+ 'template' => '{update} {delete}',
+ 'buttons' => [
+ 'update' => function ($url, $model) {
+ return Html::a(' ', ['/admin/brends/save','id'=>$model->id,'catID'=>$_GET['catID']],
+ [
+ 'title' => "Редактировать",
+ ]);
+ },
+ 'delete' => function ($url, $model) {
+ return Html::a(' ', ['/admin/brends/delete','id'=>$model->id,'catID'=>$_GET['catID']],
+ [
+ 'title' => "Удалить",
+ 'data-confirm' => 'Желаете удалить запись?',
+ ]);
+ },
+
+ ],
+ 'contentOptions'=>['style'=>'width: 70px;']
+ ],
+ ],
+]) ?>
diff --git a/app/modules/admin/views/brends/save.php b/app/modules/admin/views/brends/save.php
new file mode 100755
index 0000000..7620906
--- /dev/null
+++ b/app/modules/admin/views/brends/save.php
@@ -0,0 +1,6 @@
+
+$this->title = 'Добавить бренд';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+Добавить бренд
+= $this->render('_form',['model'=>$model]) ?>
\ No newline at end of file
diff --git a/app/modules/admin/views/catalog/_form.php b/app/modules/admin/views/catalog/_form.php
new file mode 100755
index 0000000..5bcad47
--- /dev/null
+++ b/app/modules/admin/views/catalog/_form.php
@@ -0,0 +1,55 @@
+
+
+ 'form',
+ 'options' => ['enctype' => 'multipart/form-data'],
+
+ ]); ?>
+
+= $form->field($model, 'parent_id')->dropDownList(
+ ArrayHelper::map(Catalog::find()->where('parent_id=0')->orderBy('id')->all(), 'id', 'name'),['prompt'=>'Корневой раздел','value'=>0]) ?>
+
+ = $form->field($model, 'sort') ?>
+
+ = $form->field($model, 'name') ?>
+
+ /*$form->field($model, 'translit', [
+ 'addon' => ['prepend' => ['content'=>'@']]
+ ]);*/?>
+ = $form->field($model, 'translit',[
+ 'inputTemplate' => 'catalog/ {input}
',
+ ]);?>
+
+ = $form->field($model, 'image')->fileInput() ?>
+
+ = $form->field($model, 'old_image')->hiddenInput(['value'=>$model->image])->label(false); ?>
+
+ =$form->field($model, 'body')->widget(CKEditor::className(),[
+ 'editorOptions' => ElFinder::ckeditorOptions('elfinder',[/* Some CKEditor Options */]),
+ ]);
+ ?>
+
+ = $form->field($model, 'fasovka_name') ?>
+ = $form->field($model, 'type_name') ?>
+ = $form->field($model, 'brends_name') ?>
+
+ = $form->field($model, 'meta_title') ?>
+
+ = $form->field($model, 'meta_keywords') ?>
+
+ = $form->field($model, 'meta_description') ?>
+
+
+ = Html::submitButton('Сохранить', ['class' => 'btn btn-primary', 'name' => 'login-button']) ?>
+
+
+
+
+
diff --git a/app/modules/admin/views/catalog/index.php b/app/modules/admin/views/catalog/index.php
new file mode 100755
index 0000000..0f8f82e
--- /dev/null
+++ b/app/modules/admin/views/catalog/index.php
@@ -0,0 +1,67 @@
+
+use yii\helpers\Html;
+use yii\grid\GridView;
+
+
+$this->title = 'Каталог';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+Каталог
+= Html::a('Создать', ['/admin/catalog/save'], ['class'=>'btn btn-success']) ?>
+
+echo GridView::widget([
+ 'dataProvider' =>$dataCatalog,
+ 'columns' => [
+ [
+ 'attribute' => 'id',
+ 'value'=>'id',
+ 'contentOptions'=>['style'=>'width: 70px;']
+ ],
+ [
+ 'attribute' => 'name',
+ 'value'=>function($data){
+ return ($data->parent_id==0) ? $data->name : Html::a($data->name, ['/admin/products/index','catID'=>$data->id]);
+ },
+ 'format'=>'raw',
+ //'contentOptions'=>['style'=>'max-width: 300px;']
+ ],
+ [
+ 'class' => 'yii\grid\ActionColumn',
+ 'template' => '{update} {delete} {fasovka} {type} {brends}',
+ 'buttons' => [
+ 'update' => function ($url, $model) {
+ return Html::a(' ', ['/admin/catalog/save','id'=>$model->id],
+ [
+ 'title' => "Редактировать",
+ ]);
+ },
+ 'delete' => function ($url, $model) {
+ return Html::a(' ', ['/admin/catalog/delete','id'=>$model->id],
+ [
+ 'title' => "Удалить",
+ 'data-confirm' => 'Желаете удалить запись?',
+ ]);
+ },
+ 'fasovka' => function ($url, $model) {
+ return Html::a($model->catFasovka, ['/admin/fasovka/index','catID'=>$model->id],
+ [
+ 'title' => $model->catFasovka,
+ ]);
+ },
+ 'type' => function ($url, $model) {
+ return Html::a($model->catType, ['/admin/type/index','catID'=>$model->id],
+ [
+ 'title' => $model->catType,
+ ]);
+ },
+ 'brends' => function ($url, $model) {
+ return Html::a($model->catBrends, ['/admin/brends/index','catID'=>$model->id],
+ [
+ 'title' => $model->catBrends,
+ ]);
+ }
+ ],
+ 'contentOptions'=>['style'=>'width: 320px;']
+ ],
+ ],
+]) ?>
diff --git a/app/modules/admin/views/catalog/save.php b/app/modules/admin/views/catalog/save.php
new file mode 100755
index 0000000..ffcc5cb
--- /dev/null
+++ b/app/modules/admin/views/catalog/save.php
@@ -0,0 +1,6 @@
+
+$this->title = 'Добавить каталог';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+Добавить каталог
+= $this->render('_form',['model'=>$model]) ?>
\ No newline at end of file
diff --git a/app/modules/admin/views/default/index.php b/app/modules/admin/views/default/index.php
new file mode 100755
index 0000000..4b234ec
--- /dev/null
+++ b/app/modules/admin/views/default/index.php
@@ -0,0 +1,15 @@
+
+
= $this->context->action->uniqueId ?>
+
+ This is the view content for action "= $this->context->action->id ?>".
+ The action belongs to the controller "= get_class($this->context) ?>"
+ in the "= $this->context->module->id ?>" module.
+
+
+ You may customize this page by editing the following file:
+ = __FILE__ ?>
+
+
+
+
+
diff --git a/app/modules/admin/views/export/index.php b/app/modules/admin/views/export/index.php
new file mode 100755
index 0000000..81c693d
--- /dev/null
+++ b/app/modules/admin/views/export/index.php
@@ -0,0 +1,10 @@
+
+
+$this->title = 'Экспорт';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+Экспорт
diff --git a/app/modules/admin/views/fasovka/_form.php b/app/modules/admin/views/fasovka/_form.php
new file mode 100755
index 0000000..2062615
--- /dev/null
+++ b/app/modules/admin/views/fasovka/_form.php
@@ -0,0 +1,29 @@
+
+
+ 'form',
+ 'options' => ['enctype' => 'multipart/form-data'],
+
+ ]); ?>
+
+ = $form->field($model, 'catalog_id')->hiddenInput(['value'=>$_GET['catID']])->label(false); ?>
+
+ = $form->field($model, 'name') ?>
+
+
+
+
+
+ = Html::submitButton('Сохранить', ['class' => 'btn btn-primary', 'name' => 'login-button']) ?>
+
+
+
+
+
diff --git a/app/modules/admin/views/fasovka/index.php b/app/modules/admin/views/fasovka/index.php
new file mode 100755
index 0000000..deaad4d
--- /dev/null
+++ b/app/modules/admin/views/fasovka/index.php
@@ -0,0 +1,47 @@
+
+use yii\helpers\Html;
+use yii\grid\GridView;
+
+$this->title = 'Фасовка';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+Фасовка
+
+= Html::a('Создать', ['/admin/fasovka/save','catID'=>$_GET['catID']], ['class'=>'btn btn-success']) ?>
+= GridView::widget([
+ 'dataProvider' => $dataProvider,
+ 'columns' => [
+ [
+ 'attribute' => 'id',
+ 'value'=>'id',
+ 'contentOptions'=>['style'=>'width: 70px;']
+ ],
+ [
+ 'attribute' => 'name',
+ 'value'=>'name',
+ //'contentOptions'=>['style'=>'max-width: 300px;']
+ ],
+
+ [
+ 'class' => 'yii\grid\ActionColumn',
+ 'template' => '{update} {delete}',
+ 'buttons' => [
+ 'update' => function ($url, $model) {
+ return Html::a(' ', ['/admin/fasovka/save','id'=>$model->id,'catID'=>$_GET['catID']],
+ [
+ 'title' => "Редактировать",
+ ]);
+ },
+ 'delete' => function ($url, $model) {
+ return Html::a(' ', ['/admin/fasovka/delete','id'=>$model->id,'catID'=>$_GET['catID']],
+ [
+ 'title' => "Удалить",
+ 'data-confirm' => 'Желаете удалить запись?',
+ ]);
+ },
+
+ ],
+ 'contentOptions'=>['style'=>'width: 70px;']
+ ],
+ ],
+]) ?>
diff --git a/app/modules/admin/views/fasovka/save.php b/app/modules/admin/views/fasovka/save.php
new file mode 100755
index 0000000..fe343e2
--- /dev/null
+++ b/app/modules/admin/views/fasovka/save.php
@@ -0,0 +1,6 @@
+
+$this->title = 'Добавить фасовку';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+Добавить фасовку
+= $this->render('_form',['model'=>$model]) ?>
\ No newline at end of file
diff --git a/app/modules/admin/views/fotos/_form.php b/app/modules/admin/views/fotos/_form.php
new file mode 100755
index 0000000..8cf9582
--- /dev/null
+++ b/app/modules/admin/views/fotos/_form.php
@@ -0,0 +1,33 @@
+
+
+ 'form',
+ 'options' => ['enctype' => 'multipart/form-data'],
+
+ ]); ?>
+
+ = $form->field($model, 'product_id')->hiddenInput(['value'=>$_GET['productID']])->label(false); ?>
+
+ = $form->field($model, 'name') ?>
+
+
+ = $form->field($model, 'image')->fileInput() ?>
+
+ = $form->field($model, 'old_image')->hiddenInput(['value'=>$model->image])->label(false); ?>
+
+
+
+
+ = Html::submitButton('Сохранить', ['class' => 'btn btn-primary', 'name' => 'login-button']) ?>
+
+
+
+
+
diff --git a/app/modules/admin/views/fotos/index.php b/app/modules/admin/views/fotos/index.php
new file mode 100755
index 0000000..2b0ee41
--- /dev/null
+++ b/app/modules/admin/views/fotos/index.php
@@ -0,0 +1,54 @@
+
+use yii\helpers\Html;
+use yii\grid\GridView;
+
+$this->title = 'Фотос';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+Фотос
+= Html::a('Вернуться к продуктат', ['/admin/products/index','catID'=>$_GET['catID']], ['class'=>'btn btn-info']) ?>
+
+= Html::a('Создать', ['/admin/fotos/save','productID'=>$_GET['productID'],'catID'=>$_GET['catID']], ['class'=>'btn btn-success']) ?>
+= GridView::widget([
+ 'dataProvider' => $dataProvider,
+ 'columns' => [
+ [
+ 'attribute' => 'id',
+ 'value'=>'id',
+ 'contentOptions'=>['style'=>'width: 70px;']
+ ],
+ [
+ 'attribute' => 'name',
+ 'value'=>'name',
+ //'contentOptions'=>['style'=>'max-width: 300px;']
+ ],
+ [
+ 'attribute' => 'image',
+ 'format' => 'image',
+ 'value'=>function($data) { return Yii::$app->request->BaseUrl.'/upload/fotos/ico/'.$data->image; },
+ 'contentOptions'=>['style'=>'width: 100px;']
+ ],
+
+ [
+ 'class' => 'yii\grid\ActionColumn',
+ 'template' => '{update} {delete}',
+ 'buttons' => [
+ 'update' => function ($url, $model) {
+ return Html::a(' ', ['/admin/fotos/save','id'=>$model->id,'productID'=>$_GET['productID'],'catID'=>$_GET['catID']],
+ [
+ 'title' => "Редактировать",
+ ]);
+ },
+ 'delete' => function ($url, $model) {
+ return Html::a(' ', ['/admin/fotos/delete','id'=>$model->id,'productID'=>$_GET['productID'],'catID'=>$_GET['catID']],
+ [
+ 'title' => "Удалить",
+ 'data-confirm' => 'Желаете удалить запись?',
+ ]);
+ },
+
+ ],
+ 'contentOptions'=>['style'=>'width: 70px;']
+ ],
+ ],
+]) ?>
diff --git a/app/modules/admin/views/fotos/save.php b/app/modules/admin/views/fotos/save.php
new file mode 100755
index 0000000..fcfee73
--- /dev/null
+++ b/app/modules/admin/views/fotos/save.php
@@ -0,0 +1,6 @@
+
+$this->title = 'Добавить фото';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+Добавить фото
+= $this->render('_form',['model'=>$model]) ?>
\ No newline at end of file
diff --git a/app/modules/admin/views/import/index.php b/app/modules/admin/views/import/index.php
new file mode 100755
index 0000000..3943991
--- /dev/null
+++ b/app/modules/admin/views/import/index.php
@@ -0,0 +1,31 @@
+
+
+$this->title = 'Импорт';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+Импорт
+
+ 'form',
+ 'options' => ['enctype' => 'multipart/form-data'],
+
+ ]); ?>
+
+
+
+
+ = $form->field($model, 'file')->fileInput() ?>
+
+
+
+
+ = Html::submitButton('Загрузить', ['class' => 'btn btn-primary', 'name' => 'login-button']) ?>
+
+
+
+
+
diff --git a/app/modules/admin/views/import/success.php b/app/modules/admin/views/import/success.php
new file mode 100755
index 0000000..7f4c02b
--- /dev/null
+++ b/app/modules/admin/views/import/success.php
@@ -0,0 +1,11 @@
+
+
+$this->title = 'Импорт';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+Импорт
+Файл успешно загружен на сайт!
\ No newline at end of file
diff --git a/app/modules/admin/views/layouts/_main.php b/app/modules/admin/views/layouts/_main.php
new file mode 100755
index 0000000..c311562
--- /dev/null
+++ b/app/modules/admin/views/layouts/_main.php
@@ -0,0 +1,69 @@
+
+beginPage() ?>
+
+
+
+
+
+ = Html::csrfMetaTags() ?>
+ = Html::encode($this->title) ?>
+ head() ?>
+
+
+
+beginBody() ?>
+ 111111111111111
+ 'My Company',
+ 'brandUrl' => Yii::$app->homeUrl,
+ 'options' => [
+ 'class' => 'navbar-inverse navbar-fixed-top',
+ ],
+ ]);
+ echo Nav::widget([
+ 'options' => ['class' => 'navbar-nav navbar-right'],
+ 'items' => [
+ ['label' => 'Home', 'url' => ['/site/index']],
+ ['label' => 'About', 'url' => ['/site/about']],
+ ['label' => 'Contact', 'url' => ['/site/contact']],
+ Yii::$app->user->isGuest ?
+ ['label' => 'Login', 'url' => ['/site/login']] :
+ ['label' => 'Logout (' . Yii::$app->user->identity->username . ')',
+ 'url' => ['/site/logout'],
+ 'linkOptions' => ['data-method' => 'post']],
+ ],
+ ]);
+ NavBar::end();
+ ?>
+
+
+ = Breadcrumbs::widget([
+ 'links' => isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : [],
+ ]) ?>
+ = $content ?>
+
+
+
+
+
+endBody() ?>
+
+
+endPage() ?>
diff --git a/app/modules/admin/views/layouts/layout.php b/app/modules/admin/views/layouts/layout.php
new file mode 100755
index 0000000..93afc3a
--- /dev/null
+++ b/app/modules/admin/views/layouts/layout.php
@@ -0,0 +1,34 @@
+
+beginPage() ?>
+
+
+
+
+
+ = Html::csrfMetaTags() ?>
+ = Html::encode($this->title) ?>
+ head() ?>
+
+
+
+beginBody() ?>
+
+
+= $content ?>
+
+
+endBody() ?>
+
+
+endPage() ?>
\ No newline at end of file
diff --git a/app/modules/admin/views/layouts/main.php b/app/modules/admin/views/layouts/main.php
new file mode 100755
index 0000000..bdc95c9
--- /dev/null
+++ b/app/modules/admin/views/layouts/main.php
@@ -0,0 +1,75 @@
+
+beginContent('@app/modules/admin/views/layouts/layout.php'); ?>
+
+
+ Yii::t('admin', 'AdminPanel'),
+ 'brandUrl' => ['/admin/menu/index'],
+ 'options' => [
+ 'class' => 'navbar-inverse navbar-fixed-top',
+ ],
+ ]);
+ echo Nav::widget([
+ 'options' => ['class' => 'navbar-nav navbar-right'],
+ 'items' => [
+ ['label' => 'Экспорт', 'url' => ['/admin/export/index']],
+ ['label' => 'Импорт', 'url' => ['/admin/import/index']],
+ ['label' => 'Заказы', 'url' => ['/admin/orders/index']],
+ ['label' => 'Пользователи', 'url' => ['/admin/users/index']],
+ /*['label' => 'Язык',
+ 'items'=>[['label' => 'Contact', 'url' => ['/site/contact']]]
+ ],*/
+ Yii::$app->user->isGuest ?
+ ['label' => 'Login', 'url' => ['/site/login']] :
+ ['label' => 'Выход (' . Yii::$app->user->identity->username . ')',
+ 'url' => ['/admin/login/logout'],
+ 'linkOptions' => ['data-method' => 'post']],
+ ],
+ ]);
+ NavBar::end();
+ ?>
+
+
+
+
+ false,
+ 'items'=>[
+ ['label'=>' Меню', 'url'=>['/admin/menu/index']],
+ ['label'=>' Текстовые страницы', 'url'=>['/admin/text/index']],
+ ['label'=>' Каталог', 'url'=>['/admin/catalog/index']],
+ ['label'=>' Новости', 'url'=>['/admin/news/index']],
+ ['label'=>' Слайдер', 'url'=>['/admin/slider/index']],
+
+
+ ],
+]); ?>
+
+
+
+ = Breadcrumbs::widget([
+ 'links' => isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : [],
+ ]) ?>
+ = $content ?>
+
+
+
+
+
+
+
+endContent(); ?>
\ No newline at end of file
diff --git a/app/modules/admin/views/login/index.php b/app/modules/admin/views/login/index.php
new file mode 100755
index 0000000..ae4ec73
--- /dev/null
+++ b/app/modules/admin/views/login/index.php
@@ -0,0 +1,35 @@
+title = 'Вход в админку';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+
+
= Html::encode($this->title) ?>
+
+ 'login-form',
+ 'options' => ['class' => 'well form-vertical'],
+
+ ]); ?>
+
+ = $form->field($model, 'username') ?>
+
+ = $form->field($model, 'password')->passwordInput() ?>
+
+ = $form->field($model, 'rememberMe')->checkbox() ?>
+
+
+
+ = Html::submitButton('Войти', ['class' => 'btn btn-primary', 'name' => 'login-button']) ?>
+
+
+
+
+
+
diff --git a/app/modules/admin/views/menu/_form.php b/app/modules/admin/views/menu/_form.php
new file mode 100755
index 0000000..64ca423
--- /dev/null
+++ b/app/modules/admin/views/menu/_form.php
@@ -0,0 +1,24 @@
+
+
+ 'form',
+ 'options' => ['class' => 'form-vertical'],
+
+ ]); ?>
+
+ = $form->field($model, 'name') ?>
+
+ = $form->field($model, 'url') ?>
+
+ = $form->field($model, 'sort') ?>
+
+
+ = Html::submitButton('Сохранить', ['class' => 'btn btn-primary', 'name' => 'login-button']) ?>
+
+
+
+
+
diff --git a/app/modules/admin/views/menu/index.php b/app/modules/admin/views/menu/index.php
new file mode 100755
index 0000000..8664749
--- /dev/null
+++ b/app/modules/admin/views/menu/index.php
@@ -0,0 +1,37 @@
+
+use yii\helpers\Html;
+use yii\grid\GridView;
+
+$this->title = 'Меню';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+Меню
+= Html::a('Создать', ['/admin/menu/save'], ['class'=>'btn btn-success']) ?>
+= GridView::widget([
+ 'dataProvider' => $dataProvider,
+ 'columns' => [
+ [
+ 'attribute' => 'id',
+ 'value'=>'id',
+ 'contentOptions'=>['style'=>'width: 70px;']
+ ],
+ [
+ 'attribute' => 'name',
+ 'value'=>'name',
+ //'contentOptions'=>['style'=>'max-width: 300px;']
+ ],
+ [
+ 'class' => 'yii\grid\ActionColumn',
+ 'template' => '{update} {delete}',
+ 'buttons' => [
+ 'update' => function ($url, $model) {
+ return Html::a(' ', ['/admin/menu/save','id'=>$model->id],
+ [
+ 'title' => "Редактировать",
+ ]);
+ }
+ ],
+ 'contentOptions'=>['style'=>'width: 70px;']
+ ],
+ ],
+]) ?>
diff --git a/app/modules/admin/views/menu/save.php b/app/modules/admin/views/menu/save.php
new file mode 100755
index 0000000..5e28b6e
--- /dev/null
+++ b/app/modules/admin/views/menu/save.php
@@ -0,0 +1,6 @@
+
+$this->title = 'Добавить меню';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+Добавить меню
+= $this->render('_form',['model'=>$model]) ?>
\ No newline at end of file
diff --git a/app/modules/admin/views/mod/_form.php b/app/modules/admin/views/mod/_form.php
new file mode 100755
index 0000000..d07d80f
--- /dev/null
+++ b/app/modules/admin/views/mod/_form.php
@@ -0,0 +1,32 @@
+
+
+ 'form',
+ 'options' => ['enctype' => 'multipart/form-data'],
+
+ ]); ?>
+
+ = $form->field($model, 'product_id')->hiddenInput(['value'=>$_GET['productID']])->label(false); ?>
+
+ = $form->field($model, 'art') ?>
+
+ = $form->field($model, 'name') ?>
+
+
+ = $form->field($model, 'cost') ?>
+
+
+
+ = Html::submitButton('Сохранить', ['class' => 'btn btn-primary', 'name' => 'login-button']) ?>
+
+
+
+
+
diff --git a/app/modules/admin/views/mod/index.php b/app/modules/admin/views/mod/index.php
new file mode 100755
index 0000000..d2fdce9
--- /dev/null
+++ b/app/modules/admin/views/mod/index.php
@@ -0,0 +1,52 @@
+
+use yii\helpers\Html;
+use yii\grid\GridView;
+
+$this->title = 'Модификации';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+Модификации
+= Html::a('Вернуться к продуктат', ['/admin/products/index','catID'=>$_GET['catID']], ['class'=>'btn btn-info']) ?>
+
+= Html::a('Создать', ['/admin/mod/save','productID'=>$_GET['productID'],'catID'=>$_GET['catID']], ['class'=>'btn btn-success']) ?>
+= GridView::widget([
+ 'dataProvider' => $dataProvider,
+ 'columns' => [
+ [
+ 'attribute' => 'id',
+ 'value'=>'id',
+ 'contentOptions'=>['style'=>'width: 70px;']
+ ],
+ [
+ 'attribute' => 'name',
+ 'value'=>'name',
+ //'contentOptions'=>['style'=>'max-width: 300px;']
+ ],
+ [
+ 'attribute' => 'cost',
+ 'value'=>'cost',
+ 'contentOptions'=>['style'=>'width: 170px;']
+ ],
+ [
+ 'class' => 'yii\grid\ActionColumn',
+ 'template' => '{update} {delete}',
+ 'buttons' => [
+ 'update' => function ($url, $model) {
+ return Html::a(' ', ['/admin/mod/save','id'=>$model->id,'productID'=>$_GET['productID'],'catID'=>$_GET['catID']],
+ [
+ 'title' => "Редактировать",
+ ]);
+ },
+ 'delete' => function ($url, $model) {
+ return Html::a(' ', ['/admin/mod/delete','id'=>$model->id,'productID'=>$_GET['productID'],'catID'=>$_GET['catID']],
+ [
+ 'title' => "Удалить",
+ 'data-confirm' => 'Желаете удалить запись?',
+ ]);
+ },
+
+ ],
+ 'contentOptions'=>['style'=>'width: 70px;']
+ ],
+ ],
+]) ?>
diff --git a/app/modules/admin/views/mod/save.php b/app/modules/admin/views/mod/save.php
new file mode 100755
index 0000000..52b7814
--- /dev/null
+++ b/app/modules/admin/views/mod/save.php
@@ -0,0 +1,6 @@
+
+$this->title = 'Добавить модификацию';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+Добавить модификацию
+= $this->render('_form',['model'=>$model]) ?>
\ No newline at end of file
diff --git a/app/modules/admin/views/news/_form.php b/app/modules/admin/views/news/_form.php
new file mode 100755
index 0000000..8f37162
--- /dev/null
+++ b/app/modules/admin/views/news/_form.php
@@ -0,0 +1,47 @@
+
+
+ 'form',
+ 'options' => ['enctype' => 'multipart/form-data'],
+
+ ]); ?>
+ = $form->field($model,'date')->widget(\yii\jui\DatePicker::className(),['clientOptions' => [],'options' => ['class'=>'form-control','style'=>'width:150px;'],'dateFormat' => 'yyyy-MM-dd',]) ?>
+
+ = $form->field($model, 'title') ?>
+
+ /*$form->field($model, 'translit', [
+ 'addon' => ['prepend' => ['content'=>'@']]
+ ]);*/?>
+ = $form->field($model, 'translit',[
+ 'inputTemplate' => 'news/ {input}
',
+ ]);?>
+
+ = $form->field($model, 'image')->fileInput() ?>
+
+ = $form->field($model, 'old_image')->hiddenInput(['value'=>$model->image])->label(false); ?>
+
+
+ =$form->field($model, 'body')->widget(CKEditor::className(),[
+ 'editorOptions' => ElFinder::ckeditorOptions('elfinder',[/* Some CKEditor Options */]),
+ ]);
+ ?>
+
+ = $form->field($model, 'meta_title') ?>
+
+ = $form->field($model, 'meta_keywords') ?>
+
+ = $form->field($model, 'meta_description') ?>
+
+
+ = Html::submitButton('Сохранить', ['class' => 'btn btn-primary', 'name' => 'login-button']) ?>
+
+
+
+
+
diff --git a/app/modules/admin/views/news/index.php b/app/modules/admin/views/news/index.php
new file mode 100755
index 0000000..0946d27
--- /dev/null
+++ b/app/modules/admin/views/news/index.php
@@ -0,0 +1,43 @@
+
+use yii\helpers\Html;
+use yii\grid\GridView;
+
+$this->title = 'Новости';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+Новости
+= Html::a('Создать', ['/admin/news/save'], ['class'=>'btn btn-success']) ?>
+= GridView::widget([
+ 'dataProvider' => $dataProvider,
+ 'columns' => [
+ [
+ 'attribute' => 'id',
+ 'value'=>'id',
+ 'contentOptions'=>['style'=>'width: 70px;']
+ ],
+ [
+ 'attribute' => 'image',
+ 'format' => 'image',
+ 'value'=>function($data) { return Yii::$app->request->BaseUrl.'/upload/news/ico/'.$data->image; },
+ 'contentOptions'=>['style'=>'width: 100px;']
+ ],
+ [
+ 'attribute' => 'title',
+ 'value'=>'title',
+ //'contentOptions'=>['style'=>'max-width: 300px;']
+ ],
+ [
+ 'class' => 'yii\grid\ActionColumn',
+ 'template' => '{update} {delete}',
+ 'buttons' => [
+ 'update' => function ($url, $model) {
+ return Html::a(' ', ['/admin/news/save','id'=>$model->id],
+ [
+ 'title' => "Редактировать",
+ ]);
+ }
+ ],
+ 'contentOptions'=>['style'=>'width: 70px;']
+ ],
+ ],
+]) ?>
diff --git a/app/modules/admin/views/news/save.php b/app/modules/admin/views/news/save.php
new file mode 100755
index 0000000..e7bf010
--- /dev/null
+++ b/app/modules/admin/views/news/save.php
@@ -0,0 +1,6 @@
+
+$this->title = 'Добавить новость';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+Добавить новость
+= $this->render('_form',['model'=>$model]) ?>
\ No newline at end of file
diff --git a/app/modules/admin/views/orders/add.php b/app/modules/admin/views/orders/add.php
new file mode 100755
index 0000000..043cbde
--- /dev/null
+++ b/app/modules/admin/views/orders/add.php
@@ -0,0 +1,32 @@
+
+use yii\helpers\Html;
+use yii\grid\GridView;
+use yii\bootstrap\ActiveForm;
+
+
+$this->title = 'Добавить товар в заказ';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+Добавить товар в заказ
+
+ 'reg-form',
+ 'options' => ['class' => 'form-vertical','enctype' => 'multipart/form-data'],
+ 'fieldConfig' => [
+ //'template' => "{label}\n{input}
\n{error}
",
+ //'labelOptions' => ['class' => 'col-lg-2 control-label'],
+ ],
+ ]); ?>
+
+= $form->field($model, 'art') ?>
+
+= $form->field($model, 'count') ?>
+
+ = $form->field($model, 'order_id')->hiddenInput(['value'=>$_GET['order_id']])->label(false); ?>
+
+
+
+ = Html::submitButton(' Сохранить ', ['class' => 'btn btn-primary', 'name' => 'login-button']) ?>
+
+
+
\ No newline at end of file
diff --git a/app/modules/admin/views/orders/index.php b/app/modules/admin/views/orders/index.php
new file mode 100755
index 0000000..e071313
--- /dev/null
+++ b/app/modules/admin/views/orders/index.php
@@ -0,0 +1,60 @@
+
+use yii\helpers\Html;
+use yii\grid\GridView;
+
+
+$this->title = 'Заказы';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+Заказы
+
+= GridView::widget([
+ 'dataProvider' => $dataProvider,
+ 'filterModel' => $searchModel,
+ 'columns' => [
+ ['class' => 'yii\grid\SerialColumn'],
+ [
+ 'attribute' => 'id',
+ 'value'=>'id',
+ //'contentOptions'=>['style'=>'width: 160px;']
+ ],
+ [
+ 'attribute' => 'date_time',
+ 'value'=>'date_time',
+ //'contentOptions'=>['style'=>'width: 160px;']
+ ],
+ [
+ 'attribute' => 'surname',
+ 'value'=>'surname',
+ //'contentOptions'=>['style'=>'max-width: 300px;']
+ ],
+ [
+ 'attribute' => 'name',
+ 'value'=>function($data){
+ return Html::a($data->name, ['/admin/orders/show','id'=>$data->id]);
+ },
+ 'format'=>'raw',
+ ],
+ [
+ 'attribute' => 'phone',
+ 'value'=>'phone',
+ //'contentOptions'=>['style'=>'max-width: 300px;']
+ ],
+ [
+ 'attribute' => 'total',
+ 'value'=>'total',
+ //'contentOptions'=>['style'=>'max-width: 300px;']
+ ],
+
+ [
+ 'attribute' => 'status',
+ 'value'=>'status',
+ 'contentOptions'=>['style'=>'width: 5px;']
+ ],
+ [
+ 'class' => 'yii\grid\ActionColumn',
+ 'template' => '{delete}',
+ 'contentOptions'=>['style'=>'width: 70px;']
+ ],
+ ],
+]) ?>
diff --git a/app/modules/admin/views/orders/show.php b/app/modules/admin/views/orders/show.php
new file mode 100755
index 0000000..5f7b5e7
--- /dev/null
+++ b/app/modules/admin/views/orders/show.php
@@ -0,0 +1,109 @@
+
+use yii\helpers\Html;
+use yii\grid\GridView;
+use yii\bootstrap\ActiveForm;
+
+
+$this->title = 'Заказ №'.$model->id;
+$this->params['breadcrumbs'][] = $this->title;
+?>
+Заказ №=$model->id?>
+
+
+
+ Заказ успешно сохранен!
+
+
+
+ 'reg-form',
+ 'options' => ['class' => 'form-vertical','enctype' => 'multipart/form-data'],
+ 'fieldConfig' => [
+ //'template' => "{label}\n{input}
\n{error}
",
+ //'labelOptions' => ['class' => 'col-lg-2 control-label'],
+ ],
+ ]); ?>
+= $form->field($model, 'surname') ?>
+
+= $form->field($model, 'name') ?>
+
+= $form->field($model, 'patronymic') ?>
+
+= $form->field($model, 'phone') ?>
+
+= $form->field($model, 'email') ?>
+
+= $form->field($model, 'adress') ?>
+
+= $form->field($model, 'body')->textArea(['rows' => '6']) ?>
+
+= $form->field($model, 'total') ?>
+
+=$form->field($model, 'status')->dropDownList(['Нет'=>'Нет','Обработан'=>'Обработан','На комплектации'=>'На комплектации','Укомплектован'=>'Укомплектован','Доставка'=>'Доставка','Выполнен'=>'Выполнен','Резерв оплачен'=>'Резерв оплачен','Резерв неоплачен'=>'Резерв неоплачен'],['prompt'=>'...']); ?>
+
+= $form->field($model, 'comment')->textArea(['rows' => '6']) ?>
+
+
+ = Html::submitButton(' Сохранить ', ['class' => 'btn btn-primary btn-lg btn-block', 'name' => 'login-button']) ?>
+
+
+
+
+= Html::a('Добавить товар', ['/admin/orders/add','order_id'=>$model->id], ['class'=>'btn btn-success']) ?>
+= GridView::widget([
+ 'dataProvider' => $dataProvider,
+ 'columns' => [
+ [
+ 'attribute' => 'id',
+ 'value'=>'id',
+ 'contentOptions'=>['style'=>'width: 70px;']
+ ],
+ [
+ 'attribute' => 'art',
+ 'value'=>'art',
+ 'contentOptions'=>['style'=>'width: 50px;']
+ ],
+ [
+ 'attribute' => 'product_name',
+ 'value'=>'product_name',
+ //'contentOptions'=>['style'=>'max-width: 300px;']
+ ],
+ [
+ 'attribute' => 'name',
+ 'value'=>'name',
+ //'contentOptions'=>['style'=>'max-width: 300px;']
+ ],
+ [
+ 'attribute' => 'cost',
+ 'value'=>'cost',
+ 'contentOptions'=>['style'=>'width: 100px;']
+ ],
+ [
+ 'attribute' => 'count',
+ 'value'=>'count',
+ 'contentOptions'=>['style'=>'width: 30px;']
+ ],
+ [
+ 'attribute' => 'sum_cost',
+ 'value'=>'sum_cost',
+ 'contentOptions'=>['style'=>'width: 100px;']
+ ],
+ [
+ 'class' => 'yii\grid\ActionColumn',
+ 'template' => '{delete}',
+ 'contentOptions'=>['style'=>'width: 20px;'],
+ 'buttons' => [
+ 'delete' => function ($url, $model) {
+ return Html::a(' ', ['/admin/orders/delete_product','id'=>$model->id,'order_id'=>$_GET['id']],
+ [
+ 'title' => "Удалить",'data-confirm'=>'Удалить?',
+ ]);
+ }
+ ],
+ ],
+
+ ],
+]) ?>
+
+
+
diff --git a/app/modules/admin/views/products/_form.php b/app/modules/admin/views/products/_form.php
new file mode 100755
index 0000000..fd50f16
--- /dev/null
+++ b/app/modules/admin/views/products/_form.php
@@ -0,0 +1,79 @@
+
+
+ 'form',
+ 'options' => ['enctype' => 'multipart/form-data'],
+
+ ]); ?>
+
+ = $form->field($model, 'catalog_id')->hiddenInput(['value'=>$_GET['catID']])->label(false); ?>
+
+ = $form->field($model, 'art') ?>
+
+ = $form->field($model, 'name') ?>
+
+ = $form->field($model, 'translit',[
+ 'inputTemplate' => 'products/ {input}
',
+ ]);?>
+
+ = $form->field($model, 'image')->fileInput() ?>
+
+ = $form->field($model, 'old_image')->hiddenInput(['value'=>$model->image])->label(false); ?>
+
+ =$form->field($model, 'body')->widget(CKEditor::className(),[
+ 'editorOptions' => ElFinder::ckeditorOptions('elfinder',[/* Some CKEditor Options */]),
+ ]);
+ ?>
+
+ =$form->field($model, 'char')->widget(CKEditor::className(),[
+ 'editorOptions' => ElFinder::ckeditorOptions('elfinder',[/* Some CKEditor Options */]),
+ ]);
+ ?>
+
+ = $form->field($model, 'new')->checkbox() ?>
+
+ = $form->field($model, 'top')->checkbox() ?>
+
+ = $form->field($model, 'akciya')->checkbox() ?>
+
+ = $form->field($model, 'out_of_stock')->checkbox() ?>
+
+= $form->field($model, 'fasovka')
+ ->dropDownList(ArrayHelper::map(Fasovka::find()->where(['catalog_id'=>$_GET['catID']])->asArray()->orderBy('name')->all(), 'id', 'name'), ['multiple' => true])
+ ?>
+
+ = $form->field($model, 'type')
+ ->dropDownList(ArrayHelper::map(Type::find()->where(['catalog_id'=>$_GET['catID']])->asArray()->orderBy('name')->all(), 'id', 'name'), ['multiple' => true])
+ ?>
+
+ = $form->field($model, 'brends')
+ ->dropDownList(ArrayHelper::map(Brends::find()->where(['catalog_id'=>$_GET['catID']])->asArray()->orderBy('name')->all(), 'id', 'name'), ['multiple' => true])
+ ?>
+
+ = $form->field($model, 'similar')->hint('Через запятую введите АРТИКЛИ') ?>
+
+ = $form->field($model, 'featured')->hint('Через запятую введите АРТИКЛИ') ?>
+
+ = $form->field($model, 'meta_title') ?>
+
+ = $form->field($model, 'meta_keywords') ?>
+
+ = $form->field($model, 'meta_description') ?>
+
+
+ = Html::submitButton('Сохранить', ['class' => 'btn btn-primary', 'name' => 'login-button']) ?>
+
+
+
+
+
diff --git a/app/modules/admin/views/products/index.php b/app/modules/admin/views/products/index.php
new file mode 100755
index 0000000..65b0051
--- /dev/null
+++ b/app/modules/admin/views/products/index.php
@@ -0,0 +1,56 @@
+
+use yii\helpers\Html;
+use yii\grid\GridView;
+
+$this->title = 'Продукты';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+Продукты
+= Html::a('Создать', ['/admin/products/save','catID'=>$_GET['catID']], ['class'=>'btn btn-success']) ?>
+= GridView::widget([
+ 'dataProvider' => $dataProvider,
+ 'columns' => [
+ [
+ 'attribute' => 'id',
+ 'value'=>'id',
+ 'contentOptions'=>['style'=>'width: 70px;']
+ ],
+ [
+ 'attribute' => 'name',
+ 'value'=>'name',
+ //'contentOptions'=>['style'=>'max-width: 300px;']
+ ],
+ [
+ 'class' => 'yii\grid\ActionColumn',
+ 'template' => '{update} {delete} {mod} {fotos}',
+ 'buttons' => [
+ 'update' => function ($url, $model) {
+ return Html::a(' ', ['/admin/products/save','id'=>$model->id,'catID'=>$_GET['catID']],
+ [
+ 'title' => "Редактировать",
+ ]);
+ },
+ 'delete' => function ($url, $model) {
+ return Html::a(' ', ['/admin/products/delete','id'=>$model->id,'catID'=>$_GET['catID']],
+ [
+ 'title' => "Удалить",
+ 'data-confirm' => 'Желаете удалить запись?',
+ ]);
+ },
+ 'mod' => function ($url, $model) {
+ return Html::a('Модификации', ['/admin/mod/index','productID'=>$model->id,'catID'=>$_GET['catID']],
+ [
+ 'title' => "Модификации",
+ ]);
+ },
+ 'fotos' => function ($url, $model) {
+ return Html::a('Фотос', ['/admin/fotos/index','productID'=>$model->id,'catID'=>$_GET['catID']],
+ [
+ 'title' => "Фотос",
+ ]);
+ }
+ ],
+ 'contentOptions'=>['style'=>'width: 270px;']
+ ],
+ ],
+]) ?>
diff --git a/app/modules/admin/views/products/save.php b/app/modules/admin/views/products/save.php
new file mode 100755
index 0000000..4aa5f87
--- /dev/null
+++ b/app/modules/admin/views/products/save.php
@@ -0,0 +1,6 @@
+
+$this->title = 'Добавить продукт';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+Добавить продукт
+= $this->render('_form',['model'=>$model]) ?>
\ No newline at end of file
diff --git a/app/modules/admin/views/slider/_form.php b/app/modules/admin/views/slider/_form.php
new file mode 100755
index 0000000..4dc2844
--- /dev/null
+++ b/app/modules/admin/views/slider/_form.php
@@ -0,0 +1,27 @@
+
+
+ 'form',
+ 'options' => ['enctype' => 'multipart/form-data'],
+
+ ]); ?>
+
+ = $form->field($model, 'title') ?>
+
+ = $form->field($model, 'url') ?>
+
+ = $form->field($model, 'image')->fileInput() ?>
+
+ = $form->field($model, 'old_image')->hiddenInput(['value'=>$model->image])->label(false); ?>
+
+
+
+ = Html::submitButton('Сохранить', ['class' => 'btn btn-primary', 'name' => 'login-button']) ?>
+
+
+
+
+
diff --git a/app/modules/admin/views/slider/index.php b/app/modules/admin/views/slider/index.php
new file mode 100755
index 0000000..ecc9f5f
--- /dev/null
+++ b/app/modules/admin/views/slider/index.php
@@ -0,0 +1,37 @@
+
+use yii\helpers\Html;
+use yii\grid\GridView;
+
+$this->title = 'Слайдер';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+Слайдер
+= Html::a('Создать', ['/admin/slider/save'], ['class'=>'btn btn-success']) ?>
+= GridView::widget([
+ 'dataProvider' => $dataProvider,
+ 'columns' => [
+ [
+ 'attribute' => 'id',
+ 'value'=>'id',
+ 'contentOptions'=>['style'=>'width: 70px;']
+ ],
+ [
+ 'attribute' => 'title',
+ 'value'=>'title',
+ //'contentOptions'=>['style'=>'max-width: 300px;']
+ ],
+ [
+ 'class' => 'yii\grid\ActionColumn',
+ 'template' => '{update} {delete}',
+ 'buttons' => [
+ 'update' => function ($url, $model) {
+ return Html::a(' ', ['/admin/slider/save','id'=>$model->id],
+ [
+ 'title' => "Редактировать",
+ ]);
+ }
+ ],
+ 'contentOptions'=>['style'=>'width: 70px;']
+ ],
+ ],
+]) ?>
diff --git a/app/modules/admin/views/slider/save.php b/app/modules/admin/views/slider/save.php
new file mode 100755
index 0000000..dfdb7ff
--- /dev/null
+++ b/app/modules/admin/views/slider/save.php
@@ -0,0 +1,6 @@
+
+$this->title = 'Добавить слайдер';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+Добавить слайдер
+= $this->render('_form',['model'=>$model]) ?>
\ No newline at end of file
diff --git a/app/modules/admin/views/text/_form.php b/app/modules/admin/views/text/_form.php
new file mode 100755
index 0000000..2cc9efc
--- /dev/null
+++ b/app/modules/admin/views/text/_form.php
@@ -0,0 +1,41 @@
+
+
+ 'form',
+ 'options' => ['class' => 'form-vertical'],
+
+ ]); ?>
+
+ = $form->field($model, 'title') ?>
+
+ /*$form->field($model, 'translit', [
+ 'addon' => ['prepend' => ['content'=>'@']]
+ ]);*/?>
+ = $form->field($model, 'translit',[
+ 'inputTemplate' => 'text/ {input}
',
+ ]);?>
+
+ =$form->field($model, 'body')->widget(CKEditor::className(),[
+ 'editorOptions' => ElFinder::ckeditorOptions('elfinder',[/* Some CKEditor Options */]),
+ ]);
+ ?>
+
+ = $form->field($model, 'meta_title') ?>
+
+ = $form->field($model, 'meta_keywords') ?>
+
+ = $form->field($model, 'meta_description') ?>
+
+
+ = Html::submitButton('Сохранить', ['class' => 'btn btn-primary', 'name' => 'login-button']) ?>
+
+
+
+
+
diff --git a/app/modules/admin/views/text/index.php b/app/modules/admin/views/text/index.php
new file mode 100755
index 0000000..effd9f4
--- /dev/null
+++ b/app/modules/admin/views/text/index.php
@@ -0,0 +1,37 @@
+
+use yii\helpers\Html;
+use yii\grid\GridView;
+
+$this->title = 'Текстовые страницы';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+Текстовые страницы
+= Html::a('Создать', ['/admin/text/save'], ['class'=>'btn btn-success']) ?>
+= GridView::widget([
+ 'dataProvider' => $dataProvider,
+ 'columns' => [
+ [
+ 'attribute' => 'id',
+ 'value'=>'id',
+ 'contentOptions'=>['style'=>'width: 70px;']
+ ],
+ [
+ 'attribute' => 'title',
+ 'value'=>'title',
+ //'contentOptions'=>['style'=>'max-width: 300px;']
+ ],
+ [
+ 'class' => 'yii\grid\ActionColumn',
+ 'template' => '{update} {delete}',
+ 'buttons' => [
+ 'update' => function ($url, $model) {
+ return Html::a(' ', ['/admin/text/save','id'=>$model->id],
+ [
+ 'title' => "Редактировать",
+ ]);
+ }
+ ],
+ 'contentOptions'=>['style'=>'width: 70px;']
+ ],
+ ],
+]) ?>
diff --git a/app/modules/admin/views/text/save.php b/app/modules/admin/views/text/save.php
new file mode 100755
index 0000000..af95883
--- /dev/null
+++ b/app/modules/admin/views/text/save.php
@@ -0,0 +1,6 @@
+
+$this->title = 'Добавить текстовую страницу';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+Добавить текстовую страницу
+= $this->render('_form',['model'=>$model]) ?>
\ No newline at end of file
diff --git a/app/modules/admin/views/type/_form.php b/app/modules/admin/views/type/_form.php
new file mode 100755
index 0000000..2062615
--- /dev/null
+++ b/app/modules/admin/views/type/_form.php
@@ -0,0 +1,29 @@
+
+
+ 'form',
+ 'options' => ['enctype' => 'multipart/form-data'],
+
+ ]); ?>
+
+ = $form->field($model, 'catalog_id')->hiddenInput(['value'=>$_GET['catID']])->label(false); ?>
+
+ = $form->field($model, 'name') ?>
+
+
+
+
+
+ = Html::submitButton('Сохранить', ['class' => 'btn btn-primary', 'name' => 'login-button']) ?>
+
+
+
+
+
diff --git a/app/modules/admin/views/type/index.php b/app/modules/admin/views/type/index.php
new file mode 100755
index 0000000..93560fb
--- /dev/null
+++ b/app/modules/admin/views/type/index.php
@@ -0,0 +1,47 @@
+
+use yii\helpers\Html;
+use yii\grid\GridView;
+
+$this->title = 'Тип';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+Тип
+
+= Html::a('Создать', ['/admin/type/save','catID'=>$_GET['catID']], ['class'=>'btn btn-success']) ?>
+= GridView::widget([
+ 'dataProvider' => $dataProvider,
+ 'columns' => [
+ [
+ 'attribute' => 'id',
+ 'value'=>'id',
+ 'contentOptions'=>['style'=>'width: 70px;']
+ ],
+ [
+ 'attribute' => 'name',
+ 'value'=>'name',
+ //'contentOptions'=>['style'=>'max-width: 300px;']
+ ],
+
+ [
+ 'class' => 'yii\grid\ActionColumn',
+ 'template' => '{update} {delete}',
+ 'buttons' => [
+ 'update' => function ($url, $model) {
+ return Html::a(' ', ['/admin/type/save','id'=>$model->id,'catID'=>$_GET['catID']],
+ [
+ 'title' => "Редактировать",
+ ]);
+ },
+ 'delete' => function ($url, $model) {
+ return Html::a(' ', ['/admin/type/delete','id'=>$model->id,'catID'=>$_GET['catID']],
+ [
+ 'title' => "Удалить",
+ 'data-confirm' => 'Желаете удалить запись?',
+ ]);
+ },
+
+ ],
+ 'contentOptions'=>['style'=>'width: 70px;']
+ ],
+ ],
+]) ?>
diff --git a/app/modules/admin/views/type/save.php b/app/modules/admin/views/type/save.php
new file mode 100755
index 0000000..c9ab896
--- /dev/null
+++ b/app/modules/admin/views/type/save.php
@@ -0,0 +1,6 @@
+
+$this->title = 'Добавить тип';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+Добавить тип
+= $this->render('_form',['model'=>$model]) ?>
\ No newline at end of file
diff --git a/app/modules/admin/views/users/_form.php b/app/modules/admin/views/users/_form.php
new file mode 100755
index 0000000..4e65683
--- /dev/null
+++ b/app/modules/admin/views/users/_form.php
@@ -0,0 +1,24 @@
+
+
+ 'form',
+ 'options' => ['class' => 'form-vertical'],
+
+ ]); ?>
+
+ = $form->field($model, 'username') ?>
+
+ = $form->field($model, 'password')->passwordInput() ?>
+
+ = $form->field($model, 'password_repeat')->passwordInput() ?>
+
+
+ = Html::submitButton('Сохранить', ['class' => 'btn btn-primary', 'name' => 'login-button']) ?>
+
+
+
+
+
diff --git a/app/modules/admin/views/users/index.php b/app/modules/admin/views/users/index.php
new file mode 100755
index 0000000..b66c05b
--- /dev/null
+++ b/app/modules/admin/views/users/index.php
@@ -0,0 +1,37 @@
+
+use yii\helpers\Html;
+use yii\grid\GridView;
+
+$this->title = 'Пользователи';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+Пользователи
+= Html::a('Создать', ['/admin/users/save'], ['class'=>'btn btn-success']) ?>
+= GridView::widget([
+ 'dataProvider' => $dataProvider,
+ 'columns' => [
+ [
+ 'attribute' => 'id',
+ 'value'=>'id',
+ 'contentOptions'=>['style'=>'width: 70px;']
+ ],
+ [
+ 'attribute' => 'username',
+ 'value'=>'username',
+ //'contentOptions'=>['style'=>'max-width: 300px;']
+ ],
+ [
+ 'class' => 'yii\grid\ActionColumn',
+ 'template' => '{update} {delete}',
+ 'buttons' => [
+ 'update' => function ($url, $model) {
+ return Html::a(' ', ['/admin/users/save','id'=>$model->id],
+ [
+ 'title' => "Редактировать",
+ ]);
+ }
+ ],
+ 'contentOptions'=>['style'=>'width: 70px;']
+ ],
+ ],
+]) ?>
diff --git a/app/modules/admin/views/users/save.php b/app/modules/admin/views/users/save.php
new file mode 100755
index 0000000..5085534
--- /dev/null
+++ b/app/modules/admin/views/users/save.php
@@ -0,0 +1,6 @@
+
+$this->title = 'Добавить пользователя';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+Добавить пользователя
+= $this->render('_form',['model'=>$model]) ?>
\ No newline at end of file
diff --git a/app/requirements.php b/app/requirements.php
new file mode 100755
index 0000000..ee6b2cb
--- /dev/null
+++ b/app/requirements.php
@@ -0,0 +1,132 @@
+Error';
+ echo 'The path to yii framework seems to be incorrect.
';
+ echo 'You need to install Yii framework via composer or adjust the framework path in file ' . basename(__FILE__) . ' .
';
+ echo 'Please refer to the README on how to install Yii.
';
+}
+
+require_once($frameworkPath . '/requirements/YiiRequirementChecker.php');
+$requirementsChecker = new YiiRequirementChecker();
+
+$gdMemo = $imagickMemo = 'Either GD PHP extension with FreeType support or ImageMagick PHP extension with PNG support is required for image CAPTCHA.';
+$gdOK = $imagickOK = false;
+
+if (extension_loaded('imagick')) {
+ $imagick = new Imagick();
+ $imagickFormats = $imagick->queryFormats('PNG');
+ if (in_array('PNG', $imagickFormats)) {
+ $imagickOK = true;
+ } else {
+ $imagickMemo = 'Imagick extension should be installed with PNG support in order to be used for image CAPTCHA.';
+ }
+}
+
+if (extension_loaded('gd')) {
+ $gdInfo = gd_info();
+ if (!empty($gdInfo['FreeType Support'])) {
+ $gdOK = true;
+ } else {
+ $gdMemo = 'GD extension should be installed with FreeType support in order to be used for image CAPTCHA.';
+ }
+}
+
+/**
+ * Adjust requirements according to your application specifics.
+ */
+$requirements = array(
+ // Database :
+ array(
+ 'name' => 'PDO extension',
+ 'mandatory' => true,
+ 'condition' => extension_loaded('pdo'),
+ 'by' => 'All DB-related classes',
+ ),
+ array(
+ 'name' => 'PDO SQLite extension',
+ 'mandatory' => false,
+ 'condition' => extension_loaded('pdo_sqlite'),
+ 'by' => 'All DB-related classes',
+ 'memo' => 'Required for SQLite database.',
+ ),
+ array(
+ 'name' => 'PDO MySQL extension',
+ 'mandatory' => false,
+ 'condition' => extension_loaded('pdo_mysql'),
+ 'by' => 'All DB-related classes',
+ 'memo' => 'Required for MySQL database.',
+ ),
+ array(
+ 'name' => 'PDO PostgreSQL extension',
+ 'mandatory' => false,
+ 'condition' => extension_loaded('pdo_pgsql'),
+ 'by' => 'All DB-related classes',
+ 'memo' => 'Required for PostgreSQL database.',
+ ),
+ // Cache :
+ array(
+ 'name' => 'Memcache extension',
+ 'mandatory' => false,
+ 'condition' => extension_loaded('memcache') || extension_loaded('memcached'),
+ 'by' => 'MemCache ',
+ 'memo' => extension_loaded('memcached') ? 'To use memcached set MemCache::useMemcached to true.' : ''
+ ),
+ array(
+ 'name' => 'APC extension',
+ 'mandatory' => false,
+ 'condition' => extension_loaded('apc'),
+ 'by' => 'ApcCache ',
+ ),
+ // CAPTCHA:
+ array(
+ 'name' => 'GD PHP extension with FreeType support',
+ 'mandatory' => false,
+ 'condition' => $gdOK,
+ 'by' => 'Captcha ',
+ 'memo' => $gdMemo,
+ ),
+ array(
+ 'name' => 'ImageMagick PHP extension with PNG support',
+ 'mandatory' => false,
+ 'condition' => $imagickOK,
+ 'by' => 'Captcha ',
+ 'memo' => $imagickMemo,
+ ),
+ // PHP ini :
+ 'phpExposePhp' => array(
+ 'name' => 'Expose PHP',
+ 'mandatory' => false,
+ 'condition' => $requirementsChecker->checkPhpIniOff("expose_php"),
+ 'by' => 'Security reasons',
+ 'memo' => '"expose_php" should be disabled at php.ini',
+ ),
+ 'phpAllowUrlInclude' => array(
+ 'name' => 'PHP allow url include',
+ 'mandatory' => false,
+ 'condition' => $requirementsChecker->checkPhpIniOff("allow_url_include"),
+ 'by' => 'Security reasons',
+ 'memo' => '"allow_url_include" should be disabled at php.ini',
+ ),
+ 'phpSmtp' => array(
+ 'name' => 'PHP mail SMTP',
+ 'mandatory' => false,
+ 'condition' => strlen(ini_get('SMTP'))>0,
+ 'by' => 'Email sending',
+ 'memo' => 'PHP mail SMTP server required',
+ ),
+);
+$requirementsChecker->checkYii()->check($requirements)->render();
diff --git a/app/runtime/.gitignore b/app/runtime/.gitignore
new file mode 100755
index 0000000..c96a04f
--- /dev/null
+++ b/app/runtime/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
\ No newline at end of file
diff --git a/app/tests/README.md b/app/tests/README.md
new file mode 100755
index 0000000..8134fb3
--- /dev/null
+++ b/app/tests/README.md
@@ -0,0 +1,111 @@
+This directory contains various tests for the basic application.
+
+Tests in `codeception` directory are developed with [Codeception PHP Testing Framework](http://codeception.com/).
+
+After creating the basic application, follow these steps to prepare for the tests:
+
+1. Install Codeception if it's not yet installed:
+
+```
+composer global require "codeception/codeception=2.0.*"
+composer global require "codeception/specify=*"
+composer global require "codeception/verify=*"
+```
+
+If you've never used Composer for global packages run `composer global status`. It should output:
+
+```
+Changed current directory to
+```
+
+Then add `/vendor/bin` to you `PATH` environment variable. Now we're able to use `codecept` from command
+line globally.
+
+2. Install faker extension by running the following from template root directory where `composer.json` is:
+
+```
+composer require --dev yiisoft/yii2-faker:*
+```
+
+3. Create `yii2_basic_tests` database and update it by applying migrations:
+
+```
+codeception/bin/yii migrate
+```
+
+4. Build the test suites:
+
+```
+codecept build
+```
+
+5. In order to be able to run acceptance tests you need to start a webserver. The simplest way is to use PHP built in
+webserver. In the `web` directory execute the following:
+
+```
+php -S localhost:8080
+```
+
+6. Now you can run the tests with the following commands:
+
+```
+# run all available tests
+codecept run
+# run acceptance tests
+codecept run acceptance
+# run functional tests
+codecept run functional
+# run unit tests
+codecept run unit
+```
+
+Code coverage support
+---------------------
+
+By default, code coverage is disabled in `codeception.yml` configuration file, you should uncomment needed rows to be able
+to collect code coverage. You can run your tests and collect coverage with the following command:
+
+```
+#collect coverage for all tests
+codecept run --coverage-html --coverage-xml
+
+#collect coverage only for unit tests
+codecept run unit --coverage-html --coverage-xml
+
+#collect coverage for unit and functional tests
+codecept run functional,unit --coverage-html --coverage-xml
+```
+
+You can see code coverage output under the `tests/_output` directory.
+
+###Remote code coverage
+
+When you run your tests not in the same process where code coverage is collected, then you should uncomment `remote` option and its
+related options, to be able to collect code coverage correctly. To setup remote code coverage you should follow [instructions](http://codeception.com/docs/11-Codecoverage)
+from codeception site.
+
+1. install `Codeception c3` remote support `composer require "codeception/c3:*"`;
+
+2. copy `c3.php` file under your `web` directory;
+
+3. include `c3.php` file in your `index-test.php` file before application run, so it can catch needed requests.
+
+Configuration options that are used by remote code coverage:
+
+- c3_url: url pointing to entry script that includes `c3.php` file, so `Codeception` will be able to produce code coverage;
+- remote: whether to enable remote code coverage or not;
+- remote_config: path to the `codeception.yml` configuration file, from the directory where `c3.php` file is located. This is needed
+ so that `Codeception` can create itself instance and collect code coverage correctly.
+
+By default `c3_url` and `remote_config` setup correctly, you only need to copy and include `c3.php` file in your `index-test.php`
+
+After that you should be able to collect code coverage from tests that run through `PhpBrowser` or `WebDriver` with same command
+as for other tests:
+
+```
+#collect coverage from remote
+codecept run acceptance --coverage-html --coverage-xml
+```
+
+Please refer to [Codeception tutorial](http://codeception.com/docs/01-Introduction) for
+more details about writing and running acceptance, functional and unit tests.
diff --git a/app/tests/codeception.yml b/app/tests/codeception.yml
new file mode 100755
index 0000000..b71ba31
--- /dev/null
+++ b/app/tests/codeception.yml
@@ -0,0 +1,36 @@
+actor: Tester
+#coverage:
+# #c3_url: http://localhost:8080/index-test.php/
+# enabled: true
+# #remote: true
+# #remote_config: '../tests/codeception.yml'
+# white_list:
+# include:
+# - ../models/*
+# - ../controllers/*
+# - ../commands/*
+# - ../mail/*
+# blacklist:
+# include:
+# - ../assets/*
+# - ../config/*
+# - ../runtime/*
+# - ../vendor/*
+# - ../views/*
+# - ../web/*
+# - ../tests/*
+paths:
+ tests: codeception
+ log: codeception/_output
+ data: codeception/_data
+ helpers: codeception/_support
+settings:
+ bootstrap: _bootstrap.php
+ suite_class: \PHPUnit_Framework_TestSuite
+ memory_limit: 1024M
+ log: true
+ colors: true
+config:
+ # the entry script URL (with host info) for functional and acceptance tests
+ # PLEASE ADJUST IT TO THE ACTUAL ENTRY SCRIPT URL
+ test_entry_url: http://localhost:8080/index-test.php
\ No newline at end of file
diff --git a/app/tests/codeception/.gitignore b/app/tests/codeception/.gitignore
new file mode 100755
index 0000000..985dbb4
--- /dev/null
+++ b/app/tests/codeception/.gitignore
@@ -0,0 +1,4 @@
+# these files are auto generated by codeception build
+/unit/UnitTester.php
+/functional/FunctionalTester.php
+/acceptance/AcceptanceTester.php
diff --git a/app/tests/codeception/_bootstrap.php b/app/tests/codeception/_bootstrap.php
new file mode 100755
index 0000000..755029e
--- /dev/null
+++ b/app/tests/codeception/_bootstrap.php
@@ -0,0 +1,16 @@
+ $value) {
+ $inputType = $field === 'body' ? 'textarea' : 'input';
+ $this->actor->fillField($inputType . '[name="ContactForm[' . $field . ']"]', $value);
+ }
+ $this->actor->click('contact-button');
+ }
+}
diff --git a/app/tests/codeception/_pages/LoginPage.php b/app/tests/codeception/_pages/LoginPage.php
new file mode 100755
index 0000000..c3a2ef2
--- /dev/null
+++ b/app/tests/codeception/_pages/LoginPage.php
@@ -0,0 +1,25 @@
+actor->fillField('input[name="LoginForm[username]"]', $username);
+ $this->actor->fillField('input[name="LoginForm[password]"]', $password);
+ $this->actor->click('login-button');
+ }
+}
diff --git a/app/tests/codeception/acceptance.suite.yml b/app/tests/codeception/acceptance.suite.yml
new file mode 100755
index 0000000..1781b00
--- /dev/null
+++ b/app/tests/codeception/acceptance.suite.yml
@@ -0,0 +1,27 @@
+# Codeception Test Suite Configuration
+
+# suite for acceptance tests.
+# perform tests in browser using the Selenium-like tools.
+# powered by Mink (http://mink.behat.org).
+# (tip: that's what your customer will see).
+# (tip: test your ajax and javascript by one of Mink drivers).
+
+# RUN `build` COMMAND AFTER ADDING/REMOVING MODULES.
+
+class_name: AcceptanceTester
+modules:
+ enabled:
+ - PhpBrowser
+# you can use WebDriver instead of PhpBrowser to test javascript and ajax.
+# This will require you to install selenium. See http://codeception.com/docs/04-AcceptanceTests#Selenium
+# "restart" option is used by the WebDriver to start each time per test-file new session and cookies,
+# it is useful if you want to login in your app in each test.
+# - WebDriver
+ config:
+ PhpBrowser:
+# PLEASE ADJUST IT TO THE ACTUAL ENTRY POINT WITHOUT PATH INFO
+ url: http://localhost:8080
+# WebDriver:
+# url: http://localhost:8080
+# browser: firefox
+# restart: true
diff --git a/app/tests/codeception/acceptance/AboutCept.php b/app/tests/codeception/acceptance/AboutCept.php
new file mode 100755
index 0000000..1ef220e
--- /dev/null
+++ b/app/tests/codeception/acceptance/AboutCept.php
@@ -0,0 +1,8 @@
+wantTo('ensure that about works');
+AboutPage::openBy($I);
+$I->see('About', 'h1');
diff --git a/app/tests/codeception/acceptance/ContactCept.php b/app/tests/codeception/acceptance/ContactCept.php
new file mode 100755
index 0000000..4e8ee80
--- /dev/null
+++ b/app/tests/codeception/acceptance/ContactCept.php
@@ -0,0 +1,55 @@
+wantTo('ensure that contact works');
+
+$contactPage = ContactPage::openBy($I);
+
+$I->see('Contact', 'h1');
+
+$I->amGoingTo('submit contact form with no data');
+$contactPage->submit([]);
+if (method_exists($I, 'wait')) {
+ $I->wait(3); // only for selenium
+}
+$I->expectTo('see validations errors');
+$I->see('Contact', 'h1');
+$I->see('Name cannot be blank');
+$I->see('Email cannot be blank');
+$I->see('Subject cannot be blank');
+$I->see('Body cannot be blank');
+$I->see('The verification code is incorrect');
+
+$I->amGoingTo('submit contact form with not correct email');
+$contactPage->submit([
+ 'name' => 'tester',
+ 'email' => 'tester.email',
+ 'subject' => 'test subject',
+ 'body' => 'test content',
+ 'verifyCode' => 'testme',
+]);
+if (method_exists($I, 'wait')) {
+ $I->wait(3); // only for selenium
+}
+$I->expectTo('see that email adress is wrong');
+$I->dontSee('Name cannot be blank', '.help-inline');
+$I->see('Email is not a valid email address.');
+$I->dontSee('Subject cannot be blank', '.help-inline');
+$I->dontSee('Body cannot be blank', '.help-inline');
+$I->dontSee('The verification code is incorrect', '.help-inline');
+
+$I->amGoingTo('submit contact form with correct data');
+$contactPage->submit([
+ 'name' => 'tester',
+ 'email' => 'tester@example.com',
+ 'subject' => 'test subject',
+ 'body' => 'test content',
+ 'verifyCode' => 'testme',
+]);
+if (method_exists($I, 'wait')) {
+ $I->wait(3); // only for selenium
+}
+$I->dontSeeElement('#contact-form');
+$I->see('Thank you for contacting us. We will respond to you as soon as possible.');
diff --git a/app/tests/codeception/acceptance/HomeCept.php b/app/tests/codeception/acceptance/HomeCept.php
new file mode 100755
index 0000000..369ab7f
--- /dev/null
+++ b/app/tests/codeception/acceptance/HomeCept.php
@@ -0,0 +1,9 @@
+wantTo('ensure that home page works');
+$I->amOnPage(Yii::$app->homeUrl);
+$I->see('My Company');
+$I->seeLink('About');
+$I->click('About');
+$I->see('This is the About page.');
diff --git a/app/tests/codeception/acceptance/LoginCept.php b/app/tests/codeception/acceptance/LoginCept.php
new file mode 100755
index 0000000..7575caf
--- /dev/null
+++ b/app/tests/codeception/acceptance/LoginCept.php
@@ -0,0 +1,35 @@
+wantTo('ensure that login works');
+
+$loginPage = LoginPage::openBy($I);
+
+$I->see('Login', 'h1');
+
+$I->amGoingTo('try to login with empty credentials');
+$loginPage->login('', '');
+if (method_exists($I, 'wait')) {
+ $I->wait(3); // only for selenium
+}
+$I->expectTo('see validations errors');
+$I->see('Username cannot be blank.');
+$I->see('Password cannot be blank.');
+
+$I->amGoingTo('try to login with wrong credentials');
+$loginPage->login('admin', 'wrong');
+if (method_exists($I, 'wait')) {
+ $I->wait(3); // only for selenium
+}
+$I->expectTo('see validations errors');
+$I->see('Incorrect username or password.');
+
+$I->amGoingTo('try to login with correct credentials');
+$loginPage->login('admin', 'admin');
+if (method_exists($I, 'wait')) {
+ $I->wait(3); // only for selenium
+}
+$I->expectTo('see user info');
+$I->see('Logout (admin)');
diff --git a/app/tests/codeception/acceptance/_bootstrap.php b/app/tests/codeception/acceptance/_bootstrap.php
new file mode 100755
index 0000000..36f9f1d
--- /dev/null
+++ b/app/tests/codeception/acceptance/_bootstrap.php
@@ -0,0 +1,2 @@
+ [
+ 'fixture' => [
+ 'class' => 'yii\faker\FixtureController',
+ 'fixtureDataPath' => '@tests/codeception/fixtures',
+ 'templatePath' => '@tests/codeception/templates',
+ 'namespace' => 'tests\codeception\fixtures',
+ ],
+ ],
+ ]
+);
+
+$application = new yii\console\Application($config);
+$exitCode = $application->run();
+exit($exitCode);
diff --git a/app/tests/codeception/bin/yii.bat b/app/tests/codeception/bin/yii.bat
new file mode 100755
index 0000000..d516b3a
--- /dev/null
+++ b/app/tests/codeception/bin/yii.bat
@@ -0,0 +1,20 @@
+@echo off
+
+rem -------------------------------------------------------------
+rem Yii command line bootstrap script for Windows.
+rem
+rem @author Qiang Xue
+rem @link http://www.yiiframework.com/
+rem @copyright Copyright (c) 2008 Yii Software LLC
+rem @license http://www.yiiframework.com/license/
+rem -------------------------------------------------------------
+
+@setlocal
+
+set YII_PATH=%~dp0
+
+if "%PHP_COMMAND%" == "" set PHP_COMMAND=php.exe
+
+"%PHP_COMMAND%" "%YII_PATH%yii" %*
+
+@endlocal
diff --git a/app/tests/codeception/config/acceptance.php b/app/tests/codeception/config/acceptance.php
new file mode 100755
index 0000000..c688575
--- /dev/null
+++ b/app/tests/codeception/config/acceptance.php
@@ -0,0 +1,11 @@
+ [
+ 'db' => [
+ 'dsn' => 'mysql:host=localhost;dbname=yii2_basic_tests',
+ ],
+ 'mailer' => [
+ 'useFileTransport' => true,
+ ],
+ 'urlManager' => [
+ 'showScriptName' => true,
+ ],
+ ],
+];
diff --git a/app/tests/codeception/config/functional.php b/app/tests/codeception/config/functional.php
new file mode 100755
index 0000000..6d22bd9
--- /dev/null
+++ b/app/tests/codeception/config/functional.php
@@ -0,0 +1,25 @@
+ [
+ 'request' => [
+ // it's not recommended to run functional tests with CSRF validation enabled
+ 'enableCsrfValidation' => false,
+ // but if you absolutely need it set cookie domain to localhost
+ /*
+ 'csrfCookie' => [
+ 'domain' => 'localhost',
+ ],
+ */
+ ],
+ ],
+ ]
+);
diff --git a/app/tests/codeception/config/unit.php b/app/tests/codeception/config/unit.php
new file mode 100755
index 0000000..5bab5ea
--- /dev/null
+++ b/app/tests/codeception/config/unit.php
@@ -0,0 +1,11 @@
+wantTo('ensure that about works');
+AboutPage::openBy($I);
+$I->see('About', 'h1');
diff --git a/app/tests/codeception/functional/ContactCept.php b/app/tests/codeception/functional/ContactCept.php
new file mode 100755
index 0000000..4760405
--- /dev/null
+++ b/app/tests/codeception/functional/ContactCept.php
@@ -0,0 +1,46 @@
+wantTo('ensure that contact works');
+
+$contactPage = ContactPage::openBy($I);
+
+$I->see('Contact', 'h1');
+
+$I->amGoingTo('submit contact form with no data');
+$contactPage->submit([]);
+$I->expectTo('see validations errors');
+$I->see('Contact', 'h1');
+$I->see('Name cannot be blank');
+$I->see('Email cannot be blank');
+$I->see('Subject cannot be blank');
+$I->see('Body cannot be blank');
+$I->see('The verification code is incorrect');
+
+$I->amGoingTo('submit contact form with not correct email');
+$contactPage->submit([
+ 'name' => 'tester',
+ 'email' => 'tester.email',
+ 'subject' => 'test subject',
+ 'body' => 'test content',
+ 'verifyCode' => 'testme',
+]);
+$I->expectTo('see that email adress is wrong');
+$I->dontSee('Name cannot be blank', '.help-inline');
+$I->see('Email is not a valid email address.');
+$I->dontSee('Subject cannot be blank', '.help-inline');
+$I->dontSee('Body cannot be blank', '.help-inline');
+$I->dontSee('The verification code is incorrect', '.help-inline');
+
+$I->amGoingTo('submit contact form with correct data');
+$contactPage->submit([
+ 'name' => 'tester',
+ 'email' => 'tester@example.com',
+ 'subject' => 'test subject',
+ 'body' => 'test content',
+ 'verifyCode' => 'testme',
+]);
+$I->dontSeeElement('#contact-form');
+$I->see('Thank you for contacting us. We will respond to you as soon as possible.');
diff --git a/app/tests/codeception/functional/HomeCept.php b/app/tests/codeception/functional/HomeCept.php
new file mode 100755
index 0000000..80aa551
--- /dev/null
+++ b/app/tests/codeception/functional/HomeCept.php
@@ -0,0 +1,9 @@
+wantTo('ensure that home page works');
+$I->amOnPage(Yii::$app->homeUrl);
+$I->see('My Company');
+$I->seeLink('About');
+$I->click('About');
+$I->see('This is the About page.');
diff --git a/app/tests/codeception/functional/LoginCept.php b/app/tests/codeception/functional/LoginCept.php
new file mode 100755
index 0000000..991d27c
--- /dev/null
+++ b/app/tests/codeception/functional/LoginCept.php
@@ -0,0 +1,26 @@
+wantTo('ensure that login works');
+
+$loginPage = LoginPage::openBy($I);
+
+$I->see('Login', 'h1');
+
+$I->amGoingTo('try to login with empty credentials');
+$loginPage->login('', '');
+$I->expectTo('see validations errors');
+$I->see('Username cannot be blank.');
+$I->see('Password cannot be blank.');
+
+$I->amGoingTo('try to login with wrong credentials');
+$loginPage->login('admin', 'wrong');
+$I->expectTo('see validations errors');
+$I->see('Incorrect username or password.');
+
+$I->amGoingTo('try to login with correct credentials');
+$loginPage->login('admin', 'admin');
+$I->expectTo('see user info');
+$I->see('Logout (admin)');
diff --git a/app/tests/codeception/functional/_bootstrap.php b/app/tests/codeception/functional/_bootstrap.php
new file mode 100755
index 0000000..8aac091
--- /dev/null
+++ b/app/tests/codeception/functional/_bootstrap.php
@@ -0,0 +1,2 @@
+mailer->fileTransportCallback = function ($mailer, $message) {
+ return 'testing_message.eml';
+ };
+ }
+
+ protected function tearDown()
+ {
+ unlink($this->getMessageFile());
+ parent::tearDown();
+ }
+
+ public function testContact()
+ {
+ $model = $this->getMock('app\models\ContactForm', ['validate']);
+ $model->expects($this->once())->method('validate')->will($this->returnValue(true));
+
+ $model->attributes = [
+ 'name' => 'Tester',
+ 'email' => 'tester@example.com',
+ 'subject' => 'very important letter subject',
+ 'body' => 'body of current message',
+ ];
+
+ $model->contact('admin@example.com');
+
+ $this->specify('email should be send', function () {
+ expect('email file should exist', file_exists($this->getMessageFile()))->true();
+ });
+
+ $this->specify('message should contain correct data', function () use ($model) {
+ $emailMessage = file_get_contents($this->getMessageFile());
+
+ expect('email should contain user name', $emailMessage)->contains($model->name);
+ expect('email should contain sender email', $emailMessage)->contains($model->email);
+ expect('email should contain subject', $emailMessage)->contains($model->subject);
+ expect('email should contain body', $emailMessage)->contains($model->body);
+ });
+ }
+
+ private function getMessageFile()
+ {
+ return Yii::getAlias(Yii::$app->mailer->fileTransportPath) . '/testing_message.eml';
+ }
+
+}
diff --git a/app/tests/codeception/unit/models/LoginFormTest.php b/app/tests/codeception/unit/models/LoginFormTest.php
new file mode 100755
index 0000000..c7f971a
--- /dev/null
+++ b/app/tests/codeception/unit/models/LoginFormTest.php
@@ -0,0 +1,61 @@
+user->logout();
+ parent::tearDown();
+ }
+
+ public function testLoginNoUser()
+ {
+ $model = new LoginForm([
+ 'username' => 'not_existing_username',
+ 'password' => 'not_existing_password',
+ ]);
+
+ $this->specify('user should not be able to login, when there is no identity', function () use ($model) {
+ expect('model should not login user', $model->login())->false();
+ expect('user should not be logged in', Yii::$app->user->isGuest)->true();
+ });
+ }
+
+ public function testLoginWrongPassword()
+ {
+ $model = new LoginForm([
+ 'username' => 'demo',
+ 'password' => 'wrong_password',
+ ]);
+
+ $this->specify('user should not be able to login with wrong password', function () use ($model) {
+ expect('model should not login user', $model->login())->false();
+ expect('error message should be set', $model->errors)->hasKey('password');
+ expect('user should not be logged in', Yii::$app->user->isGuest)->true();
+ });
+ }
+
+ public function testLoginCorrect()
+ {
+ $model = new LoginForm([
+ 'username' => 'demo',
+ 'password' => 'demo',
+ ]);
+
+ $this->specify('user should be able to login with correct credentials', function () use ($model) {
+ expect('model should login user', $model->login())->true();
+ expect('error message should not be set', $model->errors)->hasntKey('password');
+ expect('user should be logged in', Yii::$app->user->isGuest)->false();
+ });
+ }
+
+}
diff --git a/app/tests/codeception/unit/models/UserTest.php b/app/tests/codeception/unit/models/UserTest.php
new file mode 100755
index 0000000..f4f4f4b
--- /dev/null
+++ b/app/tests/codeception/unit/models/UserTest.php
@@ -0,0 +1,17 @@
+loadFixtures(['user']);
+ }
+
+ // TODO add test methods here
+}
diff --git a/app/tests/codeception/unit/templates/fixtures/.gitkeep b/app/tests/codeception/unit/templates/fixtures/.gitkeep
new file mode 100755
index 0000000..e69de29
--- /dev/null
+++ b/app/tests/codeception/unit/templates/fixtures/.gitkeep
diff --git a/app/views/basket/ajax_info.php b/app/views/basket/ajax_info.php
new file mode 100755
index 0000000..695eed7
--- /dev/null
+++ b/app/views/basket/ajax_info.php
@@ -0,0 +1,9 @@
+
+use yii\helpers\Url;
+use yii\helpers\Html;
+?>
+
+ Ваша корзина
+ =$info->count?> товаров
+ =$info->cost?> грн
+
\ No newline at end of file
diff --git a/app/views/basket/index.php b/app/views/basket/index.php
new file mode 100755
index 0000000..b21ac41
--- /dev/null
+++ b/app/views/basket/index.php
@@ -0,0 +1,80 @@
+
+use yii\helpers\Url;
+use yii\helpers\Html;
+use yii\widgets\Breadcrumbs;
+use yii\widgets\ActiveForm;
+
+$this->title = 'Корзина';
+$this->registerMetaTag(['name' => 'description', 'content' => 'Корзина']);
+$this->registerMetaTag(['name' => 'keywords', 'content' => 'Корзина']);
+
+?>
+
+ = Breadcrumbs::widget([
+ 'links' => [
+ 'Корзина'
+ ],
+ ]) ?>
+
+
+
+
+
+
+
+
Корзина
+
+= Html::a('Вернуться в каталог', ['/site/index'], ['class'=>'btn-success']) ?>
+
+
+
+field($modelOrder,'surname'); ?>
+field($modelOrder,'name'); ?>
+field($modelOrder,'patronymic'); ?>
+field($modelOrder,'phone'); ?>
+field($modelOrder,'adress'); ?>
+field($modelOrder,'email'); ?>
+field($modelOrder,'body')->textarea(['rows'=>7]); ?>
+'submit4')); ?>
+
+
+
+
+
+$item):?>
+
+
+
+
=$item->product_name?>
+
=$item->name?>
+ field($item,'['.$i.']id')->hiddenInput()->label(false); ?>
+ field($item,'['.$i.']product_name')->hiddenInput()->label(false); ?>
+ field($item,'['.$i.']name')->hiddenInput()->label(false); ?>
+ field($item,'['.$i.']cost')->hiddenInput()->label(false); ?>
+ field($item,'['.$i.']sum_cost')->hiddenInput()->label(false); ?>
+
+
цена за один =$item->cost?> грн, цена =$item->sum_cost?> грн
+
Количество field($item,'['.$i.']count')->textInput(['type'=>'number'])->label(false); ?>
+
+
Удалить
+
+
+
+
+"update",'class'=>'submit4 fl')); ?>
+
+
+ = $form->field($modelOrder, 'total')->hiddenInput(['value'=>$modelMod->getSumCost()])->label(false); ?>
+ Общая сумма: =$modelMod->getSumCost();?> грн.
+
+
+
+ Сумма минимального заказа должна быть не меньше 100 грн.
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/views/basket/success.php b/app/views/basket/success.php
new file mode 100755
index 0000000..fe6f9dc
--- /dev/null
+++ b/app/views/basket/success.php
@@ -0,0 +1,28 @@
+
+use yii\helpers\Url;
+use yii\helpers\Html;
+use yii\widgets\Breadcrumbs;
+use yii\widgets\ActiveForm;
+
+$this->title = 'Корзина';
+$this->registerMetaTag(['name' => 'description', 'content' => 'Корзина']);
+$this->registerMetaTag(['name' => 'keywords', 'content' => 'Корзина']);
+
+?>
+
+ = Breadcrumbs::widget([
+ 'links' => [
+ 'Корзина'
+ ],
+ ]) ?>
+
+
+
+
+
+
+
+
Корзина
+Ваш заказ принят! Большое Спасибо! Менеджер с Вами свяжется в ближайшее время.
+
+
diff --git a/app/views/call/index.php b/app/views/call/index.php
new file mode 100755
index 0000000..504ceb5
--- /dev/null
+++ b/app/views/call/index.php
@@ -0,0 +1,34 @@
+
+use yii\helpers\Url;
+use yii\widgets\Breadcrumbs;
+use app\models\News;
+use yii\widgets\LinkPager;
+use yii\widgets\ActiveForm;
+
+?>
+
+$this->title = 'Обратный звонок';
+$this->registerMetaTag(['name' => 'description', 'content' => 'Обратный звонок']);
+$this->registerMetaTag(['name' => 'keywords', 'content' => 'Обратный звонок']);
+?>
+
+
+ = Breadcrumbs::widget([
+ 'links' => [
+ 'Обратный звонок'
+ ],
+ ]) ?>
+
+
+
+
+
+
+
Обратный звонок
+
+
+= $form->errorSummary($model); ?>
+
+
+
+
\ No newline at end of file
diff --git a/app/views/call/success.php b/app/views/call/success.php
new file mode 100755
index 0000000..84999f5
--- /dev/null
+++ b/app/views/call/success.php
@@ -0,0 +1,32 @@
+
+use yii\helpers\Url;
+use yii\widgets\Breadcrumbs;
+use app\models\News;
+use yii\widgets\LinkPager;
+use app\components\Text
+?>
+
+$this->title = 'Обратный звонок';
+$this->registerMetaTag(['name' => 'description', 'content' => 'Обратный звонок']);
+$this->registerMetaTag(['name' => 'keywords', 'content' => 'Обратный звонок']);
+?>
+
+
+ = Breadcrumbs::widget([
+ 'links' => [
+ 'Обратный звонок'
+ ],
+ ]) ?>
+
+
+
+
+
+
+
Обратный звонок
+
+ Мы получили от Вас сообщение! Мы свяжемся с Вами в ближайшее время.
+
+
+
+
\ No newline at end of file
diff --git a/app/views/catalog/_catalog_box.php b/app/views/catalog/_catalog_box.php
new file mode 100755
index 0000000..9905275
--- /dev/null
+++ b/app/views/catalog/_catalog_box.php
@@ -0,0 +1,22 @@
+
+use yii\helpers\Url;
+use app\models\Catalog;
+?>
+
\ No newline at end of file
diff --git a/app/views/catalog/all.php b/app/views/catalog/all.php
new file mode 100755
index 0000000..6424966
--- /dev/null
+++ b/app/views/catalog/all.php
@@ -0,0 +1,28 @@
+
+use yii\helpers\Html;
+use yii\web\View;
+use yii\helpers\Url;
+use yii\widgets\Breadcrumbs;
+
+$this->title = 'Каталог';
+$this->registerMetaTag(['name' => 'description', 'content' => 'Каталог']);
+$this->registerMetaTag(['name' => 'keywords', 'content' => 'Каталог']);
+
+?>
+
+ = Breadcrumbs::widget([
+ 'links' => ['Каталог'],
+ ]) ?>
+
+
+
+
+
Каталог
+
+
+ endforeach;?>
+
+
diff --git a/app/views/catalog/index.php b/app/views/catalog/index.php
new file mode 100755
index 0000000..0d33daf
--- /dev/null
+++ b/app/views/catalog/index.php
@@ -0,0 +1,45 @@
+
+use yii\helpers\Url;
+use yii\widgets\Breadcrumbs;
+use app\models\Catalog;
+?>
+
+$this->title = $catalog->meta_title;
+$this->registerMetaTag(['name' => 'description', 'content' => $catalog->meta_description]);
+$this->registerMetaTag(['name' => 'keywords', 'content' => $catalog->meta_keywords]);
+?>
+
+ = Breadcrumbs::widget([
+
+ 'links' => [ ['label'=>'Каталог','url'=>['catalog/all']],
+ $catalog->name],
+ ]) ?>
+
+
+
+
+
+
+
+ = $this->render('_catalog_box',['catalog'=>$catalog]) ?>
+
+
+
+
+
=$catalog->name?>
+
+
+ childs as $item):?>
+
+
+
+
+ =$catalog->body?>
+
+
+
+
+
\ No newline at end of file
diff --git a/app/views/layouts/_main.php b/app/views/layouts/_main.php
new file mode 100755
index 0000000..62e2edb
--- /dev/null
+++ b/app/views/layouts/_main.php
@@ -0,0 +1,79 @@
+
+beginPage() ?>
+
+
+
+
+
+ = Html::csrfMetaTags() ?>
+ = Html::encode($this->title) ?>
+ head() ?>
+
+
+
+beginBody() ?>
+
+ 'My Company',
+ 'brandUrl' => Yii::$app->homeUrl,
+ 'options' => [
+ 'class' => 'navbar-inverse navbar-fixed-top',
+ ],
+ ]);
+ echo Nav::widget([
+ 'options' => ['class' => 'navbar-nav navbar-right'],
+ 'items' => [
+ ['label' => 'Home', 'url' => ['/site/index']],
+ ['label' => 'About', 'url' => ['/site/about']],
+ ['label' => 'Contact', 'url' => ['/site/contact']],
+ Yii::$app->user->isGuest ?
+ ['label' => 'Login', 'url' => ['/site/login']] :
+ ['label' => 'Logout (' . Yii::$app->user->identity->username . ')',
+ 'url' => ['/site/logout'],
+ 'linkOptions' => ['data-method' => 'post']],
+ ],
+ ]);
+ NavBar::end();
+ ?>
+
+
+ = Breadcrumbs::widget([
+ 'links' => isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : [],
+ ]) ?>
+ = $content ?>
+
+
+
+
+
+endBody() ?>
+
+
+
+endPage() ?>
diff --git a/app/views/layouts/main.php b/app/views/layouts/main.php
new file mode 100755
index 0000000..98cd3cf
--- /dev/null
+++ b/app/views/layouts/main.php
@@ -0,0 +1,97 @@
+registerCssFile(Yii::$app->request->BaseUrl.'/css/style.css');
+$this->registerJsFile(Yii::$app->request->baseUrl.'/js/basic.js',['position'=>View::POS_HEAD,'depends'=>['yii\web\YiiAsset']]);
+$this->registerJsFile(Yii::$app->request->baseUrl.'/js/call.js',['position'=>View::POS_HEAD,'depends'=>['yii\web\YiiAsset']]);
+$this->registerJsFile(Yii::$app->request->baseUrl.'/js/basket.js',['position'=>View::POS_HEAD,'depends'=>['yii\web\YiiAsset']]);
+$this->registerJs("
+ $('#basket').basket();
+", View::POS_READY, 'basket');
+$this->registerJs("
+ $('.call').call({token:'".Yii::$app->request->getCsrfToken()."'});
+", View::POS_READY, 'call');
+?>
+beginPage() ?>
+
+
+
+
+
+
+
+
+
+ = Html::csrfMetaTags() ?>
+ = Html::encode($this->title) ?>
+ head() ?>
+
+
+beginBody() ?>
+
+
+
+
+
+
+ (098) 407 69 47
+ (095) 867 40 57
+
+
+
+ ...
+
+
+
+
+
+
+
+
+
+
+
+= $content ?>
+
+
+
© bubochka.in.ua Инернет - магазин семян и ландшафтного дизайна 2018
+
+
+
+
+
+
+endBody() ?>
+
+
+
+
+endPage() ?>
\ No newline at end of file
diff --git a/app/views/layouts/main2.php b/app/views/layouts/main2.php
new file mode 100755
index 0000000..e6b89d6
--- /dev/null
+++ b/app/views/layouts/main2.php
@@ -0,0 +1,16 @@
+beginContent('@app/views/layouts/layout.php'); ?>
+
+
+
+
+
+
+
+
+
+
+= $content ?>
+
+
+
+endContent(); ?>
diff --git a/app/views/news/index.php b/app/views/news/index.php
new file mode 100755
index 0000000..2809501
--- /dev/null
+++ b/app/views/news/index.php
@@ -0,0 +1,44 @@
+
+use yii\helpers\Url;
+use yii\widgets\Breadcrumbs;
+use app\models\News;
+use yii\widgets\LinkPager;
+use app\components\Text
+?>
+
+$this->title = 'Новости';
+$this->registerMetaTag(['name' => 'description', 'content' => 'Новости']);
+$this->registerMetaTag(['name' => 'keywords', 'content' => 'Новости']);
+?>
+
+
+ = Breadcrumbs::widget([
+ 'links' => [
+ 'Новости'
+ ],
+ ]) ?>
+
+
+
+
+
+
+
Новости
+
+
+
+
+
+
+ =LinkPager::widget([
+ 'pagination' => $pages,
+ 'registerLinkTags' => true
+ ]);?>
+
+
+
+
\ No newline at end of file
diff --git a/app/views/news/show.php b/app/views/news/show.php
new file mode 100755
index 0000000..4414595
--- /dev/null
+++ b/app/views/news/show.php
@@ -0,0 +1,32 @@
+
+use yii\helpers\Url;
+use yii\widgets\Breadcrumbs;
+use app\models\News;
+?>
+
+$this->title = $news->meta_title;
+$this->registerMetaTag(['name' => 'description', 'content' => $news->meta_description]);
+$this->registerMetaTag(['name' => 'keywords', 'content' => $news->meta_keywords]);
+?>
+
+
+ = Breadcrumbs::widget([
+ 'links' => [
+ ['label'=>'Новости','url'=>['news/index']],
+ $news->title
+ ],
+ ]) ?>
+
+
+
+
+
+
+
=$news->title?>
+
+
+ =$news->body?>
+
=$news->date?>
+
+
+
\ No newline at end of file
diff --git a/app/views/products/_product.php b/app/views/products/_product.php
new file mode 100755
index 0000000..7762301
--- /dev/null
+++ b/app/views/products/_product.php
@@ -0,0 +1,34 @@
+
+use yii\helpers\Url;
+?>
+
+
+
+
+ new==1):?>
+
+
+ akciya==1):?>
+
+
+ top==1):?>
+
+
+
+
+
+
+
+ out_of_stock == 0) {
+ echo "
в наличии
";
+ } else if ($item->out_of_stock == 1) {
+ echo "
нет в наличии
";
+ }
+ ?>
+
+
=$item->catalog->name?>
+
=$item->name?>
+
цена =$item->cost->cost?> грн
+
Купить
+
diff --git a/app/views/products/index.php b/app/views/products/index.php
new file mode 100755
index 0000000..af41822
--- /dev/null
+++ b/app/views/products/index.php
@@ -0,0 +1,80 @@
+
+use yii\helpers\Url;
+use yii\widgets\Breadcrumbs;
+use app\models\Catalog;
+use yii\bootstrap\ActiveForm;
+use yii\helpers\ArrayHelper;
+use yii\web\View;
+use yii\widgets\LinkPager;
+use app\models\Fasovka;
+use app\models\Type;
+use app\models\Brends;
+?>
+
+$this->title = $catalog->meta_title;
+$this->registerMetaTag(['name' => 'description', 'content' => $catalog->meta_description]);
+$this->registerMetaTag(['name' => 'keywords', 'content' => $catalog->meta_keywords]);
+$this->registerJs("
+ $('#filters-form .checkbox label').click(function() {
+ $( '#filters-form input[type=\"hidden\"]' ).remove();
+ $('#filters-form').submit();
+ });
+", View::POS_READY, 'filters-form');
+?>
+
+ = Breadcrumbs::widget([
+ 'links' => [
+ ['label'=>'Каталог','url'=>['catalog/all']],
+ ['label'=>$catalog->parent->name,'url'=>['catalog/index','translit'=>$catalog->parent->translit]],
+ $catalog->name
+ ],
+ ]) ?>
+
+
+
+
+
+
+
+
+ 'filters-form','method'=>'get','action'=>['products/index','translit'=>$catalog->translit]]); ?>
+
+ field($modelProducts, 'fasovka')->label($catalog->catFasovka)->checkboxList(ArrayHelper::map($modelProducts->fasovkaAll($catalog->id), 'id', 'name')); ?>
+
+ field($modelProducts, 'type')->label($catalog->catType)->checkboxList(ArrayHelper::map($modelProducts->typeAll($catalog->id), 'id', 'name')); ?>
+
+ field($modelProducts, 'brends')->label($catalog->catBrends)->checkboxList(ArrayHelper::map($modelProducts->brendsAll($catalog->id), 'id', 'name')); ?>
+
+
+
+
+
+
+
+ $vowels = ['&order=0','&order=1','&order=2','&order=3'];
+ $q = str_replace($vowels, "",$_SERVER['QUERY_STRING']);?>
+
+ Сортировка
+ selected value="1">От дешевых к дорогим
+ selected value="2">От дорогих к дешевым
+ selected value="3">По алфавиту
+
+
+
=$catalog->name?>
+
+
+ = $this->render('_product',['item'=>$item,'num'=>3]) ?>
+
+
+ =LinkPager::widget([
+ 'pagination' => $pages,
+ 'registerLinkTags' => true
+ ]);?>
+
+
+ =$catalog->body?>
+
+
+
+
+
\ No newline at end of file
diff --git a/app/views/products/search.php b/app/views/products/search.php
new file mode 100755
index 0000000..bf8ce7f
--- /dev/null
+++ b/app/views/products/search.php
@@ -0,0 +1,51 @@
+
+use yii\helpers\Url;
+use yii\widgets\Breadcrumbs;
+use app\models\Catalog;
+use yii\bootstrap\ActiveForm;
+use yii\helpers\ArrayHelper;
+use yii\web\View;
+use yii\widgets\LinkPager;
+use app\models\Fasovka;
+use app\models\Type;
+use app\models\Brends;
+?>
+
+$this->title = 'Поиск';
+$this->registerMetaTag(['name' => 'description', 'content' => 'Поиск']);
+$this->registerMetaTag(['name' => 'keywords', 'content' => 'Поиск']);
+
+?>
+
+ = Breadcrumbs::widget([
+ 'links' => [
+ ['label'=>'Каталог','url'=>['catalog/all']],
+ 'Поиск'
+ ],
+ ]) ?>
+
+
+
+
+
+
+
Поиск
+
+
+ =empty($products)?'Ничего не найдено!':''?>
+
+ = $this->render('_product',['item'=>$item,'num'=>4]) ?>
+
+
+ =LinkPager::widget([
+ 'pagination' => $pages,
+ 'registerLinkTags' => true
+ ]);?>
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/views/products/show.php b/app/views/products/show.php
new file mode 100755
index 0000000..b41aad7
--- /dev/null
+++ b/app/views/products/show.php
@@ -0,0 +1,255 @@
+
+use yii\widgets\Breadcrumbs;
+use yii\web\View;
+use yii\bootstrap\ActiveForm;
+use yii\helpers\ArrayHelper;
+use yii\helpers\Url;
+
+$this->title = (!empty($product->meta_title))?$product->meta_title:$product->name;
+$this->registerMetaTag(['name' => 'description', 'content' => ((!empty($product->meta_description))?$product->meta_description:$product->name)]);
+$this->registerMetaTag(['name' => 'keywords', 'content' => $product->meta_keywords]);
+
+$this->registerCssFile(Yii::$app->request->BaseUrl.'/js/fancyBox/source/jquery.fancybox.css?v=2.1.5');
+$this->registerJsFile(Yii::$app->request->baseUrl.'/js/fancyBox/source/jquery.fancybox.js?v=2.1.5',['position'=>View::POS_HEAD,'depends'=>['yii\web\JqueryAsset']]);
+$this->registerJs("
+$('.fancybox').fancybox();
+
+", View::POS_READY, 'fancybox');
+
+$this->registerJs("
+ var checkData = function(obj){
+ $('#cost').text($(obj).data('cost'));
+ $('#product_id').val($(obj).data('id'));
+ }
+ $('.fasovka input[type=\"radio\"]').click(function() {
+ checkData(this);
+ });
+ checkData($( '.fasovka input:checked' ));
+", View::POS_READY, 'fasovka');
+
+$this->registerJs("
+
+ $('#product_gallery1 a').click(function() {
+ var image = $(this).attr('href');
+ $('#productPic').attr('src', image);
+ return false;
+ });
+
+", View::POS_READY, 'gallery');
+
+$this->registerJsFile(Yii::$app->request->baseUrl.'/js/jquery.sliderkit.1.9.2.pack.js',['position'=>View::POS_HEAD,'depends'=>['yii\web\YiiAsset']]);
+$this->registerJs("
+
+ $('.skit').sliderkit({
+ cssprefix: 'skit',
+ shownavitems: 3,
+ auto: false,
+ scroll: 1,
+ circular: false,
+ // freeheight: true,
+ scrollspeed: 500
+ });
+
+", View::POS_READY, 'sliderkit');
+
+$this->registerJs("
+ $('#filters-form .checkbox label').click(function() {
+ $( '#filters-form input[type=\"hidden\"]' ).remove();
+ $('#filters-form').submit();
+ });
+", View::POS_READY, 'filters-form');
+
+$this->registerJs("
+
+ $('.skits').sliderkit({
+ cssprefix: 'skits',
+ shownavitems: 4,
+ auto: false,
+ scroll: 1,
+ circular: false,
+ // freeheight: true,
+ scrollspeed: 500
+ });
+
+", View::POS_READY, 'sliderkit');
+?>
+
+ = Breadcrumbs::widget([
+ 'links' => [
+ ['label'=>'Каталог','url'=>['catalog/all']],
+ ['label'=>$catalog->parent->name,'url'=>['catalog/index','translit'=>$catalog->parent->translit]],
+ ['label'=>$catalog->name,'url'=>['products/index','translit'=>$catalog->translit]],
+ $product->name,
+ ],
+ ]) ?>
+
+
+
+
+
+
+
+
+ 'filters-form','method'=>'get','action'=>['products/index','translit'=>$catalog->translit]]); ?>
+
+ field($product, 'fasovka')->label($catalog->catFasovka)->checkboxList(ArrayHelper::map($product->fasovkaAll($catalog->id), 'id', 'name')); ?>
+
+ field($product, 'type')->label($catalog->catType)->checkboxList(ArrayHelper::map($product->typeAll($catalog->id), 'id', 'name')); ?>
+
+ field($product, 'brends')->label($catalog->catBrends)->checkboxList(ArrayHelper::map($product->brendsAll($catalog->id), 'id', 'name')); ?>
+
+
+
+
+
+
+
=$product->art?>
+
=$product->name?>
+
+
+
+
+
+
+
+
+ fotos as $key=>$item):?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Наличие
+ out_of_stock == 0) {
+ echo "
в наличии
";
+ } else if ($product->out_of_stock == 1) {
+ echo "
нет в наличии
";
+ }
+ ?>
+
+
Фасовка
+
+ $i=1;foreach($product->mods as $key=>$item):?>
+ > =$item->name?> =$item->art?>
+
+ ";?>
+ $i++; endforeach;?>
+
+
+ Количество
+
+
+
+
Характеристики
+ =$product->char?>
+
+
Описание
+ =$product->body?>
+
+
+
+
+
+
+
+
+
+
+
+$arr = explode(',', $product->similar);
+if(!empty($product->similar) && count($arr)>0):
+?>
+Похожие товары
+
+
+
+endif;
+?>
+
+
+
+
+$arr = explode(',', $product->featured);
+if(!empty($product->featured) && count($arr)>0):
+ ?>
+ Рекоммендуемые товары
+
+
+
+endif;
+?>
diff --git a/app/views/site/_index.php b/app/views/site/_index.php
new file mode 100755
index 0000000..27b26b6
--- /dev/null
+++ b/app/views/site/_index.php
@@ -0,0 +1,98 @@
+title = 'My Yii Application';
+?>
+
+
+
+
Congratulations!
+
+= HelloWidget::widget(['message' => ' Yii2.0']) ?>
+
+
You have successfully created your Yii-powered application.
+
+
Get started with Yii
+
+
+
+
+
+= $form->field($model, 'term')->widget(\yii\jui\AutoComplete::classname(), [
+ 'clientOptions' => [
+ 'source' => Url::to(['site/term']),
+ ],
+ 'options'=>[
+ 'class'=>'form-control'
+ ]
+]) ?>
+= $form->field($model, 'term2')->widget(\yii\jui\AutoComplete::classname(), [
+ 'clientOptions' => [
+ 'source' => Url::to(['site/term']),
+ ],
+ 'options'=>[
+ 'class'=>'form-control'
+ ]
+]) ?>
+= $form->field($model,'date')->widget(\yii\jui\DatePicker::className(),['clientOptions' => [],'options' => ['class'=>'form-control']]) ?>
+= $form->field($model,'date_do')->widget(\yii\jui\DatePicker::className(),['clientOptions' => [],'options' => ['class'=>'form-control']]) ?>
+= $form->field($model, 'peoples')->widget(\yii\jui\Spinner::classname(), [
+ 'clientOptions' => ['step' => 1],
+
+]) ?>
+
+use app\components\ckeditor\CKEditor;
+use yii\helpers\Html;
+use app\mihaildev\elfinder\ElFinder;
+
+echo $form->field($model, 'username')->widget(CKEditor::className(),[
+'editorOptions' => ElFinder::ckeditorOptions('elfinder',[/* Some CKEditor Options */]),
+]);
+?>
+
+
+
+
+
+
+
Heading
+
+
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et
+ dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip
+ ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu
+ fugiat nulla pariatur.
+
+
Yii Documentation »
+
+
+
Heading
+
+
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et
+ dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip
+ ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu
+ fugiat nulla pariatur.
+
+
Yii Forum »
+
+
+
Heading
+
+
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et
+ dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip
+ ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu
+ fugiat nulla pariatur.
+
+
Yii Extensions »
+
+
+
+
+
diff --git a/app/views/site/about.php b/app/views/site/about.php
new file mode 100755
index 0000000..13d85a6
--- /dev/null
+++ b/app/views/site/about.php
@@ -0,0 +1,16 @@
+title = 'About';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+
+
= Html::encode($this->title) ?>
+
+
+ This is the About page. You may modify the following file to customize its content:
+
+
+
= __FILE__ ?>
+
diff --git a/app/views/site/contact.php b/app/views/site/contact.php
new file mode 100755
index 0000000..e964a34
--- /dev/null
+++ b/app/views/site/contact.php
@@ -0,0 +1,57 @@
+title = 'Contact';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+
diff --git a/app/views/site/error.php b/app/views/site/error.php
new file mode 100755
index 0000000..d780af6
--- /dev/null
+++ b/app/views/site/error.php
@@ -0,0 +1,20 @@
+title = 'Ошибка '.$code;
+?>
+
+
+
Ошибка =$code;?>
+
+
+ = nl2br(Html::encode($message)) ?>
+
+
+
diff --git a/app/views/site/index-old.php b/app/views/site/index-old.php
new file mode 100644
index 0000000..ae18c07
--- /dev/null
+++ b/app/views/site/index-old.php
@@ -0,0 +1,244 @@
+
+ use yii\helpers\Html;
+ use yii\web\View;
+ use app\models\Slider;
+ use yii\helpers\Url;
+ use app\components\Text;
+
+ /**
+ * @var \app\models\Products $products_new
+ * @var \app\models\Products $products_top
+ * @var \app\models\Products $products_akciya
+ */
+
+ $this->title = $menu->meta_title;
+ $this->registerMetaTag(['name' => 'description', 'content' => $menu->meta_description]);
+ $this->registerMetaTag(['name' => 'keywords', 'content' => $menu->meta_keywords]);
+ $this->registerJsFile(Yii::$app->request->baseUrl.'/js/jquery.slides.js',['position'=>View::POS_HEAD,'depends'=>['yii\web\YiiAsset']]);
+ $this->registerJs("
+ $('#slider').slidesjs({
+ width: 960,
+ height: 360,
+ navigation: false
+ });
+", View::POS_READY, 'slider');
+ $this->registerJsFile(Yii::$app->request->baseUrl.'/js/jquery.sliderkit.1.9.2.pack.js',['position'=>View::POS_HEAD,'depends'=>['yii\web\YiiAsset']]);
+ $this->registerJs("
+
+ $('.skits').sliderkit({
+ cssprefix: 'skits',
+ shownavitems: 4,
+ auto: false,
+ scroll: 1,
+ circular: false,
+ // freeheight: true,
+ scrollspeed: 500
+ });
+
+", View::POS_READY, 'sliderkit');
+?>
+
+
+
+ foreach(Slider::find()->orderBy('id')->all() as $item):?>
+
+ endforeach;?>
+
+
+
+
+
+
+
+
+
Каталог
+
+
+ endforeach;?>
+
+
+
+
+
+
Новинки
+
+
+
+
+
+
+
Топ продаж
+
+
+
+
+
Акции
+
+
+
+
+
+
Новости
+
+
+
+
+
+
+
+
+
+ =$menu->body ?>
+
+
+
+
diff --git a/app/views/site/index.php b/app/views/site/index.php
new file mode 100755
index 0000000..a48a6ab
--- /dev/null
+++ b/app/views/site/index.php
@@ -0,0 +1,140 @@
+
+use yii\helpers\Html;
+use yii\web\View;
+use app\models\Slider;
+use yii\helpers\Url;
+use app\components\Text;
+use app\widgets\ProductListWidget;
+
+/**
+ * @var \app\models\Products $products_new
+ * @var \app\models\Products $products_top
+ * @var \app\models\Products $products_akciya
+ */
+
+$this->title = $menu->meta_title;
+$this->registerMetaTag(['name' => 'description', 'content' => $menu->meta_description]);
+$this->registerMetaTag(['name' => 'keywords', 'content' => $menu->meta_keywords]);
+$this->registerJsFile(Yii::$app->request->baseUrl.'/js/jquery.slides.js',['position'=>View::POS_HEAD,'depends'=>['yii\web\YiiAsset']]);
+$this->registerJs("
+ $('#slider').slidesjs({
+ width: 960,
+ height: 360,
+ navigation: false
+ });
+", View::POS_READY, 'slider');
+$this->registerJsFile(Yii::$app->request->baseUrl.'/js/jquery.sliderkit.1.9.2.pack.js',['position'=>View::POS_HEAD,'depends'=>['yii\web\YiiAsset']]);
+$this->registerJs("
+
+ $('.skits').sliderkit({
+ cssprefix: 'skits',
+ shownavitems: 4,
+ auto: false,
+ scroll: 1,
+ circular: false,
+ // freeheight: true,
+ scrollspeed: 500
+ });
+
+", View::POS_READY, 'sliderkit');
+?>
+
+
+
+ foreach(Slider::find()->orderBy('id')->all() as $item):?>
+
+ endforeach;?>
+
+
+
+
+
+
+
+
+
Каталог
+
+
+ endforeach;?>
+
+
+
+
+
+
Новинки
+
+
+
+
+ = ProductListWidget::widget(
+ [
+ 'products' => $products_new
+ ]
+ )?>
+
+
+
+
+
+
+
+
+
+
Топ продаж
+
+
+
+ = ProductListWidget::widget(
+ [
+ 'products' => $products_top
+ ]
+ )?>
+
+
+
+
+
+
+
+
+
Акции
+
+
+
+
+ = ProductListWidget::widget(
+ [
+ 'products' => $products_akciya
+ ]
+ )?>
+
+
+
+
+
+
+
+
+
Новости
+
+
+
+
+
+
+
+
+
+ =$menu->body ?>
+
+
+
+
+
\ No newline at end of file
diff --git a/app/views/site/login.php b/app/views/site/login.php
new file mode 100755
index 0000000..916be98
--- /dev/null
+++ b/app/views/site/login.php
@@ -0,0 +1,46 @@
+title = 'Login';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+
+
= Html::encode($this->title) ?>
+
+
Please fill out the following fields to login:
+
+ 'login-form',
+ 'options' => ['class' => 'form-horizontal'],
+ 'fieldConfig' => [
+ 'template' => "{label}\n
{input}
\n
{error}
",
+ 'labelOptions' => ['class' => 'col-lg-1 control-label'],
+ ],
+ ]); ?>
+
+ = $form->field($model, 'username') ?>
+
+ = $form->field($model, 'password')->passwordInput() ?>
+
+ = $form->field($model, 'rememberMe', [
+ 'template' => "
{input}
\n
{error}
",
+ ])->checkbox() ?>
+
+
+
+
+
+
+ You may login with admin/admin or demo/demo .
+ To modify the username/password, please check out the code app\models\User::$users.
+
+
diff --git a/app/views/text/index.php b/app/views/text/index.php
new file mode 100755
index 0000000..79ea03e
--- /dev/null
+++ b/app/views/text/index.php
@@ -0,0 +1,19 @@
+
+use yii\widgets\Breadcrumbs;
+?>
+
+$this->title = $text->meta_title;
+$this->registerMetaTag(['name' => 'description', 'content' => $text->meta_description]);
+$this->registerMetaTag(['name' => 'keywords', 'content' => $text->meta_keywords]);
+?>
+
+ = Breadcrumbs::widget([
+ 'links' => [$text->title],
+ ]) ?>
+
+
+
+=$text->title;?>
+
+=$text->body;?>
+
\ No newline at end of file
diff --git a/app/widget/ProductListWidget.php b/app/widget/ProductListWidget.php
new file mode 100644
index 0000000..55659a8
--- /dev/null
+++ b/app/widget/ProductListWidget.php
@@ -0,0 +1,53 @@
+products)){
+ $this->products = [];
+ }
+ }
+
+ public function run()
+ {
+
+ $res = "";
+
+ foreach ($this->products as $item){
+ /**
+ * @var \app\models\Products $item
+ */
+
+ $res .= $this->render(
+ '_product_view',
+ [
+ 'item' => $item
+ ]
+ );
+
+ }
+
+ $res .= " ";
+
+ return $res;
+
+ }
+
+ }
\ No newline at end of file
diff --git a/app/widget/views/_product_view.php b/app/widget/views/_product_view.php
new file mode 100644
index 0000000..ba2d7b2
--- /dev/null
+++ b/app/widget/views/_product_view.php
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+ if ($item->new == 1): ?>
+
+ endif; ?>
+ if ($item->akciya == 1): ?>
+
+ endif; ?>
+ if ($item->top == 1): ?>
+
+ endif; ?>
+
+
+
+
+
+
+
+
+
+
+
+ out_of_stock == 0) {
+ echo "в наличии
";
+ } else if ($item->out_of_stock == 1) {
+ echo "нет в наличии
";
+ }
+ ?>
+
+ = $item->catalog->name ?>
+ = $item->name ?>
+ цена = $item->cost->cost ?> грн
+
+ Купить
+
+
diff --git a/app/widgets/ProductListWidget.php b/app/widgets/ProductListWidget.php
new file mode 100644
index 0000000..d4aa075
--- /dev/null
+++ b/app/widgets/ProductListWidget.php
@@ -0,0 +1,54 @@
+products)){
+ $this->products = [];
+ }
+ }
+
+ public function run()
+ {
+
+ $res = "";
+
+ foreach ($this->products as $item){
+ /**
+ * @var \app\models\Products $item
+ */
+
+ $res .= $this->render(
+ '_product_view',
+ [
+ 'item' => $item
+ ]
+ );
+
+ }
+
+ $res .= " ";
+
+ return $res;
+
+ }
+
+ }
\ No newline at end of file
diff --git a/app/widgets/views/_product_view.php b/app/widgets/views/_product_view.php
new file mode 100644
index 0000000..ba2d7b2
--- /dev/null
+++ b/app/widgets/views/_product_view.php
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+ if ($item->new == 1): ?>
+
+ endif; ?>
+ if ($item->akciya == 1): ?>
+
+ endif; ?>
+ if ($item->top == 1): ?>
+
+ endif; ?>
+
+
+
+
+
+
+
+
+
+
+
+ out_of_stock == 0) {
+ echo "в наличии
";
+ } else if ($item->out_of_stock == 1) {
+ echo "нет в наличии
";
+ }
+ ?>
+
+ = $item->catalog->name ?>
+ = $item->name ?>
+ цена = $item->cost->cost ?> грн
+
+ Купить
+
+
diff --git a/app/yii b/app/yii
new file mode 100755
index 0000000..b032ebd
--- /dev/null
+++ b/app/yii
@@ -0,0 +1,24 @@
+#!/usr/bin/env php
+run();
+exit($exitCode);
diff --git a/app/yii.bat b/app/yii.bat
new file mode 100755
index 0000000..d516b3a
--- /dev/null
+++ b/app/yii.bat
@@ -0,0 +1,20 @@
+@echo off
+
+rem -------------------------------------------------------------
+rem Yii command line bootstrap script for Windows.
+rem
+rem @author Qiang Xue
+rem @link http://www.yiiframework.com/
+rem @copyright Copyright (c) 2008 Yii Software LLC
+rem @license http://www.yiiframework.com/license/
+rem -------------------------------------------------------------
+
+@setlocal
+
+set YII_PATH=%~dp0
+
+if "%PHP_COMMAND%" == "" set PHP_COMMAND=php.exe
+
+"%PHP_COMMAND%" "%YII_PATH%yii" %*
+
+@endlocal
diff --git a/assets/.gitignore b/assets/.gitignore
new file mode 100755
index 0000000..d6b7ef3
--- /dev/null
+++ b/assets/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
diff --git a/css/site.css b/css/site.css
new file mode 100755
index 0000000..698be70
--- /dev/null
+++ b/css/site.css
@@ -0,0 +1,91 @@
+html,
+body {
+ height: 100%;
+}
+
+.wrap {
+ min-height: 100%;
+ height: auto;
+ margin: 0 auto -60px;
+ padding: 0 0 60px;
+}
+
+.wrap > .container {
+ padding: 70px 15px 20px;
+}
+
+.footer {
+ height: 60px;
+ background-color: #f5f5f5;
+ border-top: 1px solid #ddd;
+ padding-top: 20px;
+}
+
+.jumbotron {
+ text-align: center;
+ background-color: transparent;
+}
+
+.jumbotron .btn {
+ font-size: 21px;
+ padding: 14px 24px;
+}
+
+.not-set {
+ color: #c55;
+ font-style: italic;
+}
+
+/* add sorting icons to gridview sort links */
+a.asc:after, a.desc:after {
+ position: relative;
+ top: 1px;
+ display: inline-block;
+ font-family: 'Glyphicons Halflings';
+ font-style: normal;
+ font-weight: normal;
+ line-height: 1;
+ padding-left: 5px;
+}
+
+a.asc:after {
+ content: /*"\e113"*/ "\e151";
+}
+
+a.desc:after {
+ content: /*"\e114"*/ "\e152";
+}
+
+.sort-numerical a.asc:after {
+ content: "\e153";
+}
+
+.sort-numerical a.desc:after {
+ content: "\e154";
+}
+
+.sort-ordinal a.asc:after {
+ content: "\e155";
+}
+
+.sort-ordinal a.desc:after {
+ content: "\e156";
+}
+
+.grid-view th {
+ white-space: nowrap;
+}
+
+.hint-block {
+ display: block;
+ margin-top: 5px;
+ color: #999;
+}
+
+.error-summary {
+ color: #a94442;
+ background: #fdf7f7;
+ border-left: 3px solid #eed3d7;
+ padding: 10px 20px;
+ margin: 0 0 15px 0;
+}
diff --git a/css/style.css b/css/style.css
new file mode 100755
index 0000000..b0d7f83
--- /dev/null
+++ b/css/style.css
@@ -0,0 +1,686 @@
+BODY,FORM{margin:0;padding:0;font-family:Arial,Tahoma,Helvetica,sans-serif;font-size:14px;color:#1d1d1b}
+.fl{float:left}
+.fr{float:right}
+.both{clear:both}
+body{background:#fff}
+p{padding:0;margin:5px 0}
+h1,h2,h3{padding:0;margin:0}
+h2,.h2{font-size:20px;color:#87476a;margin-bottom:20px;text-transform:uppercase}
+h1{font-size:22px;color:#87476a;margin-bottom:10px;text-transform:uppercase}
+a:visited,a:link{font-size:12px;font-weight:400;color:#464646;text-decoration:underline}
+a:hover{color:#f1bc2e;text-decoration:underline}
+a.link2:visited,a.link2:link{font-size:14px;font-weight:700;color:#59a926;text-decoration:none}
+a.link2:hover{color:#87476a;text-decoration:underline}
+.site{max-width:960px;margin:0 auto}
+.top{padding:30px 0}
+.logo{margin:0;width:182px;height:47px;float:left}
+.logo a{display:block;width:182px;height:47px;background:url(../img/logo.png) no-repeat}
+.logo span{display:none}
+.phone{float:left;margin-left:90px;background:url(../img/ico_tel.png) no-repeat;padding-left:50px;font-size:18px;font-weight:700;color:#464646}
+.phone span{font-weight:400;color:#7d7d7d}
+.call_email{float:left;margin-left:70px}
+.call_email .call{display:block;margin-bottom:7px;background:url(../img/ico_call.png) left center no-repeat;padding:0 0 2px 25px;color:#464646;font-size:12px;text-decoration:underline}
+.call_email .email{display:block;background:url(../img/ico_email.png) left center no-repeat;padding:0 0 0 25px;color:#464646;font-size:12px;text-decoration:underline}
+.backet{float:left;margin-left:85px;background:url(../img/ico_basket.png) no-repeat;padding-left:50px;font-size:18px;font-weight:700;color:#464646;line-height:20px;max-width: 139px;height: 42px;}
+.backet a{color:#464646;font-size:16px;font-weight:700;text-decoration:none;text-transform:uppercase}
+.backet a span{font-size:14px;font-weight:400;text-decoration:underline;text-transform:lowercase;white-space: nowrap;}
+.backet .basket_nums {position: absolute;max-width: 132px;}
+.menu{background:#87476a;border-radius:5px}
+.ten{height:16px;background:url(../img/menu_ten.png) center no-repeat}
+.content .ten{border-top:1px solid #b7b7b7}
+.ten2{height:15px;background:url(../img/ten2.png) left no-repeat}
+.menu ul{margin:0;padding:0;list-style:none}
+.menu ul li{float:left;border-right:1px solid #6e3152}
+.menu ul li a:link,.menu ul li a:visited{float:left;padding:15px 18px;color:#fff;font-size:14px;text-decoration:none}
+.menu ul li a:hover{color:#ffdbef}
+.menu input[type="text"]{margin:8px 0 5px 18px;max-width:325px;outline:0;border:1px solid #d8d6d6;border-radius:5px;padding:5px 0;font-size:14px;text-indent:10px;margin-bottom:7px}
+.menu input[type="submit"]{width:35px;height:29px;border:none;background:url(../img/lupa_sub.png) center no-repeat;margin-left:-35px;cursor:pointer}
+.menu form{position:relative;text-align:right;float:right;}
+.menu input[type="text"]{margin-right:18px;width:240px;position:relative;z-index:1}
+.menu input[type="submit"]{position:absolute;margin-left:0;position:absolute;top:50%;right:17px;z-index:2;margin-top:-17px}
+.slider{margin-top:10px;height:360px}
+#slider{position:relative}
+#slider .slidesjs-previous{position:absolute;bottom:18px;right:30px;z-index:999;width:35px;height:35px;background:url(../img/slider_prev.png) no-repeat}
+#slider .slidesjs-next{position:absolute;bottom:18px;right:3px;z-index:999;width:35px;height:35px;background:url(../img/slider_next.png) no-repeat}
+.leftbar{float:left;width:221px;margin-right:35px}
+.rightbar{float:right;max-width:340px;margin-left:35px}
+.content{overflow:hidden}
+* html .content{height:1%}
+.rubric_item{width:195px;height:210px;float:left;margin:0 20px 20px}
+.rubric_item a.name{display:block;text-align:center;color:#59a926;font-weight:700;font-size:14px;text-transform:uppercase;text-decoration:none}
+.rubric_item a.name:hover{text-decoration:underline}
+.rubric_item2{width:165px;height:200px;float:left;margin:0 10px 20px 0}
+.rubric_item2 a.name{display:block;text-align:center;color:#59a926;font-weight:700;font-size:14px;text-transform:uppercase;text-decoration:none}
+.rubric_item2 a.name:hover{text-decoration:underline}
+.product_item{width:180px;float:left;margin:0 30px 20px;text-align:center;line-height:22px}
+.product_item a.name{display:block;text-align:center;color:#59a926;font-weight:700;font-size:14px;text-decoration:none}
+.product_item a.name:hover{text-decoration:underline}
+.product_item .cost{color:#915977}
+.product_item a.buy{display:inline-block;padding:5px 13px;background:#59a926;border-radius:5px;color:#fff;text-transform:uppercase;text-decoration:none;font-size:14px;font-weight:700;margin-top:5px}
+.product_item a.buy:hover{background:#87476a}
+.product_item2{width:180px;height:440px;float:left;margin:0 50px 20px 0;text-align:center;line-height:22px}
+.product_item2 a.name{display:block;text-align:center;color:#59a926;font-weight:700;font-size:14px;text-decoration:none}
+.product_item2 a.name:hover{text-decoration:underline}
+.product_item2 .cost{color:#915977}
+.product_item2 a.buy{display:inline-block;padding:5px 13px;background:#59a926;border-radius:5px;color:#fff;text-transform:uppercase;text-decoration:none;font-size:14px;font-weight:700;margin-top:5px}
+.product_item2 a.buy:hover{background:#87476a}
+.n{margin-right:0}
+.news_item{max-width:460px;float:left;margin:0 10px 20px;line-height:22px;border-bottom:1px solid #b7b7b7;padding-bottom:10px}
+.news_item img{margin-right:20px}
+.news_item a.name{display:block;color:#59a926;font-weight:700;font-size:14px;text-decoration:none}
+.news_item a.name:hover{text-decoration:underline}
+.fotter{background:#87476a;padding:20px;border-radius:5px;color:#fff;margin-top:50px}
+.fotter a{color:#fff}
+.bread-crumbs{padding:0 0 20px 20px}
+.bread-crumbs ul{list-style:none;margin:0;padding:0}
+.bread-crumbs ul li{float:left;padding-right:5px}
+.bread-crumbs ul li a:visited,.bread-crumbs ul li a:link{font-size:14px;color:#454545;text-decoration:underline}
+.bread-crumbs ul li a:hover{color:#464646;text-decoration:none}
+.breadcrumb > li + li:before{color:#ccc;content:"/ ";padding:0 5px}
+.filtes_box{width:219px;background:url(../img/filters_bg.jpg) repeat-y;border:1px solid #ebebeb;border-radius:5px;line-height:25px}
+.filtes_box .w{padding:20px}
+.filtes_box .control-label{font-size:14px;font-weight:700}
+.txtb1{font-size:14px;font-weight:700}
+.txtf{font-size:14px;font-weight:700;color:#87476a}
+.txtfb{font-size:20px;font-weight:700;color:#87476a}
+.filtes_box ul{list-style:none;margin:0;padding:0;padding-bottom:10px;margin-bottom:10px}
+.filtes_box ul li{border-bottom:1px solid #dcdcdc}
+.filtes_box ul li ul li{border:none}
+.filtes_box ul li a{display:block;font-weight:700;color:#464646;text-decoration:none;font-size:14px}
+.filtes_box ul li ul li a{display:block;font-weight:400;color:#464646;text-decoration:none;font-size:14px}
+.filtes_box ul li a:hover{color:#87476a;text-decoration:underline}
+.filtes_box ul li a.active{font-weight:700;color:#87476a}
+.product_pic_big{max-width:400px;min-height:400px;position1:relative}
+.leftbar_product{max-width:400px;float:left;margin-right:25px}
+.content_product{overflow:hidden}
+* html .content_product{height:1%}
+.fasovka{padding:10px;background:#f0f0f0;border-radius:5px}
+.count{margin:20px 0}
+.count input[type="number"]{outline:0;width:50px;border:1px solid #d8d6d6;border-radius:5px;padding:5px 0;font-size:14px;text-indent:10px;margin-bottom:7px}
+.content_product a.buy{display:inline-block;padding:8px 13px;background:#59a926;border-radius:5px;color:#fff;text-transform:uppercase;text-decoration:none;font-size:14px;font-weight:700;margin-top:5px}
+.content_product a.buy:hover{background:#87476a}
+.submit4{margin-top:5px;border:none;padding:8px 13px;background:#59a926;border-radius:5px;color:#fff;text-transform:uppercase;text-decoration:none;font-size:14px;font-weight:700;cursor:pointer}
+.submit4:hover{background:#87476a}
+.boy_box{border-bottom:1px solid #b7b7b7;padding:0 0 15px}
+.boy_box div{padding-top:10px}
+.content_product .info{padding:0 0 20px}
+.basket_item{padding:10px 0;border-bottom:1px solid #b7b7b7}
+.basket_item img{margin-right:20px}
+.basket_item .count{margin:20px 0}
+.basket_item .fr{margin-top:5px}
+.basket_item .info{overflow:hidden}
+a.del:visited,a.del:link{background:url(../img/del.png) left center no-repeat;padding:2px 25px;font-size:12px;font-weight:400;color:#787878;text-decoration:underline}
+a.del:hover{color:#a52828;text-decoration:underline}
+.total{text-align:right;color:#87476a;font-size:20px;margin:10px 0}
+ul.pagination{list-style:none;text-align:center}
+ul.pagination li{display:inline}
+ul.pagination li a{background:#87476a;padding:7px;border-radius:100%;color:#fff}
+ul.pagination li.active a{background:#ccc}
+.skit{display:block;position:relative;margin:0;padding:20px 0}
+.skit-nav{display:block;position:relative;margin:0;padding:0}
+.skit-nav-clip{max-width:880px;display:block;overflow:hidden;position:relative;margin:0 auto;padding:0}
+.skit ul{position:relative;margin:0;padding:0;list-style:none}
+.skit ul li{width:100px;height:100px;float:left;text-align:center;margin:0 20px 0 0;padding:0}
+.skit .skit-nav-prev{width:16px;height:30px;background:url(../img/slider_prev.png);position:absolute;left:0;top:30px}
+.skit .skit-nav-next{width:16px;height:30px;background:url(../img/slider_next.png);position:absolute;right:0;top:30px}
+.skits{display:block;position:relative;margin:0;padding:0}
+.skits-nav{display:block;position:relative;margin:0;padding:0}
+.skits-nav-clip{display:block;overflow:hidden;position:relative;margin:0;padding:0}
+.skits ul{position:relative;margin:0;padding:0;list-style:none}
+.skits ul li{width:180px;height:400px;float:left;text-align:center;padding:0 30px 20px;margin:0}
+.skits .skits-nav-prev{width:16px;height:30px;background:url(../img/slider_prev.png);position:absolute;left:0;top:130px}
+.skits .skits-nav-next{width:16px;height:30px;background:url(../img/slider_next.png);position:absolute;right:0;top:130px}
+.modal_box{position:fixed;left:0;top:0;width:100%;height:100%;z-index:999;background:#000;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=50);-moz-opacity:.5;-khtml-opacity:.5;opacity:.5}
+#data_box{position:absolute;top:100px;z-index:1000;max-width:400px;background:#fff;-webkit-box-shadow:0 0 15px #000;-moz-box-shadow:0 0 15px #000;box-shadow:0 0 15px #000;border:7px solid #87476a;border-radius:5px}
+#data_box .data_wrp{padding:25px 15px 15px}
+#data_box .data_wrp h1{text-transform:uppercase}
+#data_box .data_wrp hr{height:1px;border:none;color:#000;background:#000;margin:45px 0 20px}
+#data_box .data_wrp hr.hr{height:1px;border:none;color:#000;background:#000;margin:20px 0}
+#data_box .pic-tango{margin-right:7px;margin-bottom:7px}
+#modal_close{cursor:pointer;margin-top:-80px;margin-right:-50px}
+.rightbar .control-label{float:left;width:80px;padding-top:5px}
+.form-control{outline:0;border:1px solid #d8d6d6;border-radius:5px;padding:5px 0;font-size:14px;text-indent:10px;margin-bottom:10px;width:250px}
+.form-control:focus{border:#87476a 1px solid;box-shadow:0 0 10px #87476a;-webkit-box-shadow:0 0 10px #87476a;-moz-box-shadow:0 0 10px #87476a}
+.help-block{color:red;font-size:12px;margin-bottom:5px}
+.pic{border:1px solid #87476a;margin-right:20px}
+.date{color:#707070}
+#data_box label{display:block}
+#data_box input[type="text"],#data_box textarea{outline:0;border:1px solid #d8d6d6;border-radius:5px;padding:5px 0;font-size:14px;text-indent:10px;margin-bottom:10px}
+#data_box input[type="text"]:focus,#data_box textarea:focus{border:#87476a 1px solid;box-shadow:0 0 10px #87476a;-webkit-box-shadow:0 0 10px #87476a;-moz-box-shadow:0 0 10px #87476a}
+#pic_notvisible{position:absolute;top:200px;left:110px;display:none}
+a.btn-success{display:inline-block;border:2px solid #d8d6d6;border-radius:5px;padding:5px;margin-bottom:10px;text-decoration:none;font-size:14px}
+a.btn-success:hover{border:#87476a 2px solid;color:#87476a}
+.p_new{background:url(../img/lb_new_01.png) no-repeat;width:60px;height:20px;margin-botto1m:-20px;position:relative;float:left}
+.p_top{background:url(../img/lb_top_01.png) no-repeat;width:60px;height:20px;margin-bottom1:-20px;position:relative;float:left}
+.p_action{background:url(../img/lb_action_01.png) no-repeat;width:60px;height:20px;margin-bottom1:-20px;position:relative;float:left}
+
+.skits ul li, .product_item2 {
+ position: relative;
+}
+
+.status_items-wr {
+ position: absolute;
+ top: 0;
+ left: 30px;
+ width: 50%;
+ z-index: 1;
+}
+
+.status_items-wr div {
+ margin-top: 3px;
+ width: 100%;
+ float: left;
+}
+
+.status_items-wr div:first-child {
+ margin-top: 0;
+}
+
+.status_items-wr div p {
+ float: left;
+ color: #fff;
+ text-transform: uppercase;
+ font-size: 11px;
+ padding: 0 7px 0 10px;
+ height: 20px;
+ line-height: 20px;
+ position: relative;
+ margin: 0;
+ box-shadow: 3px 3px 10px 0 rgba(0, 0, 0, 0.85);
+
+}
+
+.status_items-wr div p span {
+ font-family: 'icomoon' !important;
+ speak: none;
+ font-style: normal;
+ font-weight: normal;
+ font-variant: normal;
+ text-transform: none;
+ line-height: 1;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ position: absolute;
+ top: 0;
+ right: -21px;
+ overflow: hidden;
+ display: block;
+ width: 22px;
+ height: 20px;
+}
+
+/*.status_items-wr div p span:before {*/
+ /*font-size: 23px;*/
+ /*content: "\e9001";*/
+ /*position: absolute;*/
+ /*left: 0;*/
+ /*top: -1px;*/
+/*}*/
+
+.status_items-wr div p.staus_sale {
+ background-color: #de3b1b;
+}
+
+.status_items-wr div p.staus_sale span:before {
+ color: #de3b1b;
+}
+
+.status_items-wr div p.staus_new {
+ background: #50a924;
+}
+
+.status_items-wr div p.staus_new span:before {
+ color: #50a924;
+}
+
+.status_items-wr div p.staus_hit {
+ background-color: #7862aa;
+}
+
+.status_items-wr div p.staus_hit span:before {
+ color: #7862aa;
+}
+
+
+.t_stock {
+ font-size: 13px;
+ text-align: center;
+ color: #8a8686;
+ line-height: 13px;
+ margin-top: 3px;
+ margin-bottom: -7px;
+}
+
+.t_stock.t_no_stock {color: #842f22;}
+
+.t_stock.t_show_product_stock {
+ text-align: left;
+ margin-bottom: 17px;
+}
+
+.landing-header-new {
+ height: 384px;
+ max-width: 960px;
+ background-image:url(../img/land/grey-green22.jpg);
+
+}
+
+.block-services {
+ height: 650px;
+ max-width: 960px;
+ background-image:url(../img/land/services-bg.jpg);
+ padding-top: 15px;
+ padding-bottom: 25px;
+}
+
+.services-header {
+ height: auto;
+ max-width: 960px;
+ background-color:#59a926;
+ border-radius:5px;
+ padding-top:10px;
+ margin-top:10px;
+ margin-bottom:15px;
+ box-shadow: 0px 9px 10px rgba(0, 0, 0, 0.5);
+ padding-bottom: 15px;
+}
+
+.block-services-bg {
+ height: 575px;
+ width: 90%;
+ margin-left:5%;
+ background-image:url(../img/land/opac-bg.png);
+ border-radius: 5px;
+ box-shadow: 0px 9px 10px rgba(0, 0, 0, 0.5);
+}
+
+.services-images {
+ margin-top: 20px;
+}
+
+.service-1 {
+ float:left;
+ height: 250px;
+ width: 35%;
+ background-image:url(../img/land/1.jpg);
+ margin-left: 10%;
+ margin-top: 25px;
+}
+
+.service-2 {
+ float:right;
+ height: 250px;
+ width: 35%;
+ background-image:url(../img/land/2.jpg);
+ margin-right: 10%;
+ margin-top: 25px;
+}
+.service-3 {
+ float:left;
+ height: 250px;
+ width: 35%;
+ background-image:url(../img/land/3.jpg);
+ margin-left: 10%;
+ margin-top: 25px;
+}
+.service-4 {
+ float:right;
+ height: 250px;
+ width: 35%;
+ background-image:url(../img/land/4.jpg);
+ margin-right: 10%;
+ margin-top: 25px;
+}
+
+.title-box{
+ width:90%;
+ background-color:#59a926;
+ border-radius:5px;
+ height: auto;
+ margin-top: 10px;
+ margin-left: 5%;
+ padding-top: 10px;
+ padding-bottom: 10px;
+ box-shadow: 0px 9px 10px rgba(0, 0, 0, 0.5);
+}
+
+.services-adv {
+ height: 440px;
+ max-width: 960px;
+ background-image:url(../img/land/adv-bg.jpg);
+
+}
+
+.adv-list {
+ height: 365px;
+ width: 90%;
+ margin-left:5%;
+ background-image:url(../img/land/adv-bg.png);
+ border-radius: 5px;
+ box-shadow: 0px 9px 10px rgba(0, 0, 0, 0.5);
+ padding-top: 15px;
+ padding-bottom: 25px;
+}
+
+
+.landing-text {
+ max-width:960px;
+ margin-top: 25px;
+
+}
+
+.land-gallery {
+ max-width:960px;
+ height:auto;
+ margin-top: 25px;
+}
+.land-projects {
+ width:100%;
+ height:40px;
+ border-radius: 5px;
+ background-color:#59a926;
+ margin-bottom: 10px;
+ padding-top: 15px;
+}
+
+.land-pic {
+ width:100%;
+ height:auto;
+}
+
+
+@media all and (max-width: 959px) {
+ h1, .h1 {
+ font-size: 18px;
+ padding: 0 20px;
+ margin-bottom: 20px;
+ }
+ h2, .h2 {font-size: 16px;}
+ .top {text-align: center;}
+ .top .logo, .top .phone, .top .call_email, .top .backet {
+ display: inline-block;
+ vertical-align: top;
+ float: none;
+ text-align: left;
+ margin: 15px;
+ }
+ .top .sandwich {position: fixed;}
+ .top .sandwich.open, .burger.open {
+ top: 12px;
+ right: 15px;
+ width: 28px;
+ height: 28px;
+ }
+ .sandwich, .burger {
+ position: absolute;
+ top: 15px;
+ right: 15px;
+ cursor: pointer;
+ transition: .15s;
+ -o-transition: .15s;
+ -moz-transition: .15s;
+ -webkit-transition: .15s;
+ z-index: 11;
+ }
+ .sandwich i:last-child, .burger i:last-child {margin-bottom: 0;}
+ .sandwich.open i:first-child, .burger.open i:first-child {
+ transform: rotate(45deg);
+ -o-transform: rotate(45deg);
+ -ms-transform: rotate(45deg);
+ -moz-transform: rotate(45deg);
+ -webkit-transform: rotate(45deg);
+ }
+ .sandwich.open i:nth-child(2), .burger.open i:nth-child(2) {display: none;}
+ .sandwich.open i:last-child, .burger.open i:last-child {
+ transform: rotate(-45deg);
+ -o-transform: rotate(-45deg);
+ -ms-transform: rotate(-45deg);
+ -moz-transform: rotate(-45deg);
+ -webkit-transform: rotate(-45deg);
+ }
+ .sandwich.open i, .burger.open i {
+ position: absolute;
+ top: 12px;
+ left: 0;
+ margin: 0;
+ }
+ .sandwich i, .burger i {
+ display: block;
+ background: black;
+ transition: .15s;
+ -o-transition: .15s;
+ -moz-transition: .15s;
+ -webkit-transition: .15s;
+ width: 28px;
+ height: 4px;
+ margin: 0 auto 5px;
+ }
+ .leftbar .close {
+ position: absolute;
+ top: 15px;
+ right: 15px;
+ cursor: pointer;
+ width: 28px;
+ height: 28px;
+ z-index: 1000;
+ }
+ .leftbar .close i:first-child {
+ transform: rotate(45deg);
+ -o-transform: rotate(45deg);
+ -ms-transform: rotate(45deg);
+ -moz-transform: rotate(45deg);
+ -webkit-transform: rotate(45deg);
+ }
+ .leftbar .close i:nth-child(2) {display: none;}
+ .leftbar .close i:last-child {
+ transform: rotate(-45deg);
+ -o-transform: rotate(-45deg);
+ -ms-transform: rotate(-45deg);
+ -moz-transform: rotate(-45deg);
+ -webkit-transform: rotate(-45deg);
+ }
+ .leftbar .close i {
+ position: absolute;
+ top: 12px;
+ left: 0;
+ background: black;
+ width: 28px;
+ height: 4px;
+ }
+ .menu.open {left: 0;}
+ .menu {
+ position: fixed;
+ top: 0;
+ left: -238px;
+ border-top-left-radius: 0;
+ border-bottom-left-radius: 0;
+ border-top-right-radius: 0;
+ transition: all .15s;
+ padding: 15px 0;
+ z-index: 100;
+ }
+ .menu ul li {
+ float: none;
+ border: 0;
+ }
+ .site .menu ul li a {
+ display: block;
+ float: none;
+ padding: 7px 20px;
+ }
+ .menu input[type="text"] {width: 200px;}
+ .slider {
+ height: auto;
+ margin-top: -16px;
+ }
+ #slider .slidesjs-previous {
+ left: 15px;
+ right: auto;
+ }
+ #slider .slidesjs-next {right: 15px;}
+ #slider .slidesjs-navigation {
+ top: 0;
+ bottom: 0;
+ background-position: center;
+ margin: auto;
+ }
+ .slider img {
+ width: 100%;
+ height: auto;
+ }
+ .content {padding: 20px;}
+ .layout form .content {text-align: left;}
+ .loyout, .layout {position: relative;}
+ .loyout .content, .layout .content {
+ position: relative;
+ text-align: center;
+ }
+ .ten, .ten2 {
+ position: relative;
+ z-index: 11;
+ }
+ .ten2 {background-size: 100%;}
+ .fr {float: none;}
+ .product_pic_big {min-height: auto;}
+ .content .ten, .content .ten2 {margin: 0 -20px 20px;}
+ .rubric_item {
+ display: inline-block;
+ vertical-align: top;
+ float: none;
+ }
+ .skits-nav-clip {width: 100%!important;}
+ .news_item {
+ display: inline-block;
+ vertical-align: top;
+ float: none;
+ max-width: 300px;
+ margin-bottom: 30px;
+ }
+ .news_item img {
+ float: none;
+ margin: 0 0 20px;
+ }
+ .bread-crumbs {padding-top: 10px;}
+ .content table {
+ width: 100%!important;
+ max-width: 700px;
+ }
+ .content table th, .content table td {padding: 5px;}
+ .content table span {font-size: 12px!important;}
+ .pic {
+ max-width: 400px;
+ width: 100%;
+ height: auto;
+ margin-bottom: 20px;
+ }
+ .landing-header-new {
+ background-size: 100%;
+ height: 32vw;
+ }
+ .services-header {padding: 10px;}
+ .services-header > span {font-size: 14px!important;}
+ .services-images {text-align: center;}
+ .block-services, .block-services-bg {height: auto;}
+ .services-images > div {
+ display: inline-block;
+ vertical-align: top;
+ float: none;
+ background-size: 100%;
+ width: 87%;
+ max-width: 245px;
+ height: 165px;
+ margin: 15px;
+ }
+ .services-adv {
+ background-position: center bottom;
+ height: 290px;
+ padding: 35px 0;
+ }
+ .adv-list {
+ position: relative;
+ height: auto;
+ padding: 20px 0;
+ z-index: 1;
+ }
+ .adv-list h2:last-child {margin-bottom: 0;}
+ .adv-list h2 {font-size: 12px;}
+ .landing-text img {
+ width: 100%!important;
+ max-width: 559px;
+ height: auto!important;
+ }
+ .land-pic img {
+ width: 100%!important;
+ max-width: 960px;
+ height: auto!important;
+ }
+ .leftbar.open {left: 0;}
+ .leftbar {
+ position: absolute;
+ top: 0;
+ left: -221px;
+ transition: all .15s;
+ z-index: 12;
+ }
+ .rubric_item2, .product_item2 {
+ display: inline-block;
+ vertical-align: top;
+ float: none;
+ margin: 15px;
+ }
+ .leftbar_product {
+ float: none;
+ margin: auto;
+ }
+ .content_product {padding-top: 50px;}
+ .content_product .info {text-align: left;}
+ .product_pic_big img {
+ width: 100%;
+ max-width: 400px;
+ }
+ .t_stock.t_show_product_stock {text-align: center;}
+ a.btn-success {margin: 10px 20px;}
+ #data_box {
+ left: 0!important;
+ right: 0;
+ box-sizing: border-box;
+ max-width: 400px;
+ width: 95%!important;
+ margin: auto;
+ }
+ #data_box input[type="text"], #data_box textarea {
+ max-width: 300px;
+ width: 100%!important;
+ }
+ ul.pagination {padding: 0 0 15px;}
+ .layout .burger {
+ top: 20px;
+ left: 20px;
+ right: auto;
+ }
+ .fotter {
+ text-align: center;
+ margin-top: 10px;
+ }
+ .fotter .fl, .fotter .fr {
+ display: inline-block;
+ vertical-align: middle;
+ float: none;
+ margin: 10px;
+ }
+}
+@media all and (min-width: 800px) and (max-width: 959px) {
+ .skits {width: 720px;}
+}
+@media all and (min-width: 550px) and (max-width: 799px) {
+ .skits {width: 480px;}
+}
+@media all and (max-width: 959px) {
+ .skits {margin: auto;}
+}
+@media all and (max-width: 549px) {
+ .skits {width: 240px;}
+}
+@media all and (max-width: 399px) {
+ .content table span {font-size: 10px!important;}
+}
\ No newline at end of file
diff --git a/favicon.ico b/favicon.ico
new file mode 100755
index 0000000..580ed73
Binary files /dev/null and b/favicon.ico differ
diff --git a/img/artweb.png b/img/artweb.png
new file mode 100755
index 0000000..92a6dfa
Binary files /dev/null and b/img/artweb.png differ
diff --git a/img/close_modal.jpg b/img/close_modal.jpg
new file mode 100755
index 0000000..912fe9c
Binary files /dev/null and b/img/close_modal.jpg differ
diff --git a/img/del.png b/img/del.png
new file mode 100755
index 0000000..4774115
Binary files /dev/null and b/img/del.png differ
diff --git a/img/filters_bg.jpg b/img/filters_bg.jpg
new file mode 100755
index 0000000..b42b228
Binary files /dev/null and b/img/filters_bg.jpg differ
diff --git a/img/ico_basket.png b/img/ico_basket.png
new file mode 100755
index 0000000..fc1d4b1
Binary files /dev/null and b/img/ico_basket.png differ
diff --git a/img/ico_call.png b/img/ico_call.png
new file mode 100755
index 0000000..94049fa
Binary files /dev/null and b/img/ico_call.png differ
diff --git a/img/ico_email.png b/img/ico_email.png
new file mode 100755
index 0000000..373b748
Binary files /dev/null and b/img/ico_email.png differ
diff --git a/img/ico_tel.png b/img/ico_tel.png
new file mode 100755
index 0000000..2e26b29
Binary files /dev/null and b/img/ico_tel.png differ
diff --git a/img/land/1.jpg b/img/land/1.jpg
new file mode 100644
index 0000000..0122932
Binary files /dev/null and b/img/land/1.jpg differ
diff --git a/img/land/2.jpg b/img/land/2.jpg
new file mode 100644
index 0000000..8d3beb7
Binary files /dev/null and b/img/land/2.jpg differ
diff --git a/img/land/3.jpg b/img/land/3.jpg
new file mode 100644
index 0000000..1951647
Binary files /dev/null and b/img/land/3.jpg differ
diff --git a/img/land/4.jpg b/img/land/4.jpg
new file mode 100644
index 0000000..aadd2ba
Binary files /dev/null and b/img/land/4.jpg differ
diff --git a/img/land/adv-bg.jpg b/img/land/adv-bg.jpg
new file mode 100644
index 0000000..548c73b
Binary files /dev/null and b/img/land/adv-bg.jpg differ
diff --git a/img/land/adv-bg.png b/img/land/adv-bg.png
new file mode 100644
index 0000000..5de5661
Binary files /dev/null and b/img/land/adv-bg.png differ
diff --git a/img/land/combo.jpg b/img/land/combo.jpg
new file mode 100644
index 0000000..9f5a2bd
Binary files /dev/null and b/img/land/combo.jpg differ
diff --git a/img/land/grey-green22.jpg b/img/land/grey-green22.jpg
new file mode 100644
index 0000000..56b91d2
Binary files /dev/null and b/img/land/grey-green22.jpg differ
diff --git a/img/land/opac-bg.png b/img/land/opac-bg.png
new file mode 100644
index 0000000..be86d69
Binary files /dev/null and b/img/land/opac-bg.png differ
diff --git a/img/land/services-bg.jpg b/img/land/services-bg.jpg
new file mode 100644
index 0000000..b2a18c5
Binary files /dev/null and b/img/land/services-bg.jpg differ
diff --git a/img/lb_action_01.png b/img/lb_action_01.png
new file mode 100644
index 0000000..6fd5d66
Binary files /dev/null and b/img/lb_action_01.png differ
diff --git a/img/lb_new_01.png b/img/lb_new_01.png
new file mode 100644
index 0000000..25a5fe6
Binary files /dev/null and b/img/lb_new_01.png differ
diff --git a/img/lb_top_01.png b/img/lb_top_01.png
new file mode 100644
index 0000000..adbc352
Binary files /dev/null and b/img/lb_top_01.png differ
diff --git a/img/logo.png b/img/logo.png
new file mode 100755
index 0000000..5976047
Binary files /dev/null and b/img/logo.png differ
diff --git a/img/lupa_sub.png b/img/lupa_sub.png
new file mode 100755
index 0000000..f5b2376
Binary files /dev/null and b/img/lupa_sub.png differ
diff --git a/img/menu_ten.png b/img/menu_ten.png
new file mode 100755
index 0000000..e74f17f
Binary files /dev/null and b/img/menu_ten.png differ
diff --git a/img/pic_news.jpg b/img/pic_news.jpg
new file mode 100755
index 0000000..fd43794
Binary files /dev/null and b/img/pic_news.jpg differ
diff --git a/img/pic_product.jpg b/img/pic_product.jpg
new file mode 100755
index 0000000..61cd8b5
Binary files /dev/null and b/img/pic_product.jpg differ
diff --git a/img/pic_product_big.jpg b/img/pic_product_big.jpg
new file mode 100755
index 0000000..f482607
Binary files /dev/null and b/img/pic_product_big.jpg differ
diff --git a/img/pic_product_ico.jpg b/img/pic_product_ico.jpg
new file mode 100755
index 0000000..69b81a0
Binary files /dev/null and b/img/pic_product_ico.jpg differ
diff --git a/img/pic_rubric.jpg b/img/pic_rubric.jpg
new file mode 100755
index 0000000..6dce54b
Binary files /dev/null and b/img/pic_rubric.jpg differ
diff --git a/img/slider.jpg b/img/slider.jpg
new file mode 100755
index 0000000..5aabf2c
Binary files /dev/null and b/img/slider.jpg differ
diff --git a/img/slider_next.png b/img/slider_next.png
new file mode 100755
index 0000000..9c9ea7b
Binary files /dev/null and b/img/slider_next.png differ
diff --git a/img/slider_prev.png b/img/slider_prev.png
new file mode 100755
index 0000000..6dfb114
Binary files /dev/null and b/img/slider_prev.png differ
diff --git a/img/ten2.png b/img/ten2.png
new file mode 100755
index 0000000..b7fca8d
Binary files /dev/null and b/img/ten2.png differ
diff --git a/index-test.php b/index-test.php
new file mode 100755
index 0000000..32b4ce3
--- /dev/null
+++ b/index-test.php
@@ -0,0 +1,16 @@
+run();
diff --git a/index.php b/index.php
new file mode 100755
index 0000000..94ccba3
--- /dev/null
+++ b/index.php
@@ -0,0 +1,12 @@
+run();
diff --git a/js/basic.js b/js/basic.js
new file mode 100644
index 0000000..93d5107
--- /dev/null
+++ b/js/basic.js
@@ -0,0 +1,14 @@
+if(window.matchMedia('(max-width: 959px)').matches) {$(function($) {
+ $('.top .sandwich').click(function() {
+ $('.top .sandwich, .menu').toggleClass('open');
+ });
+ $('.layout .burger').click(function() {
+ $('.leftbar').addClass('open');
+ });
+ $('.leftbar .close').click(function() {
+ $('.leftbar').removeClass('open');
+ });
+ $('.content').html(function (i, html) {
+ return html.replace(/ /g, ' ');
+ });
+});}
\ No newline at end of file
diff --git a/js/basket.js b/js/basket.js
new file mode 100755
index 0000000..af59b56
--- /dev/null
+++ b/js/basket.js
@@ -0,0 +1,183 @@
+(function($){
+
+ $.fn.basket = function(callerSettings) {
+
+ var basket_id = this;
+
+ var find_products = function(){
+ $("a[rel~='product']").each(function (i) {
+ $(this).bind('click',function(){
+ var rel = $(this).attr('rel');
+ var id = $('#product_id').val();
+ var count = $('#count').val();
+ $("#pic_notvisible").css('top','200px').css('left','110px');
+ $('#pic_notvisible').show();
+ var div2Pos = $(basket_id).position();
+ $("#pic_notvisible").animate({left:div2Pos.left, top:div2Pos.top, opacity: 0.25, height: 'toggle'}, 1000);
+ go_product({mod_id : id,count:count});
+ return false;
+ })
+ });
+ };
+
+ var go_product = function(data){
+ var product_id = data.product_id;
+ $.post("/basket/add/", data ,
+ function(data){
+ //alert_msg("Товар добавлен в корзину",product_id);
+ start_basket();
+ });
+ };
+
+ var start_basket = function(){
+ $.post("/basket/info/",
+ function(data){
+ $(basket_id).html(data);
+ });
+
+ };
+
+ var alert_msg = function(msg,product_id){
+ winW = document.body.offsetWidth;
+ winH = document.body.offsetHeight
+ $('.modal_box').remove();
+ $('#data_box').remove();
+ $('body').append('
');
+ $('body').append('
');
+ $('#data_box').append('
');
+ $('#data_box').css( "left", ((winW-400)/2)+'px' );
+
+ var scrollTop = document.documentElement.scrollTop
+ if (navigator.userAgent.toLowerCase().indexOf('chrome') > -1 || navigator.userAgent.toLowerCase().indexOf('safari') > -1) {
+ scrollTop = document.body.scrollTop;
+ }
+ $('#data_box').css( "top", (scrollTop+150)+'px' );
+
+ app = '';
+ app +=''+msg+' ';
+ app += ' ';
+ app += ' ';
+ app += ' ';
+ $('#data_box .data_wrp').append(app);
+
+
+ $(".modal_box, #modal_close, #p_close").click(function() {
+ $('.modal_box').remove();
+ $('#data_box').remove();
+ });
+ };
+
+ find_products();
+ start_basket();
+
+ // frontend calculator
+ var Model = {
+ init : function() {
+ this.data = [];
+ this.setModel();
+ },
+
+ setModel : function() {
+ Model.data = [];
+ $(".basket_item").each(function(index, el) {
+ var objItem = {};
+ objItem.cost = parseFloat(
+ $(el).find("[name $= '[cost]']").val()
+ );
+ objItem.count = parseInt(
+ $(el).find("[name $= '[count]']").val()
+ );
+ Model.data.push(objItem);
+ });
+ },
+
+ getData : function() {
+ return this.data;
+ }
+ };
+
+ var Controll = {
+ init : function() {
+ Model.init();
+ View.init();
+ },
+
+ getData : function() {
+ return Model.getData();
+ },
+
+ setData : function() {
+ Model.setModel();
+ },
+
+ countSumCost : function(elementIndex) {
+ var obj = this.getData()[elementIndex];
+ var sumCost = obj.cost * obj.count;
+ if ( isNaN(sumCost) ){
+ return 0;
+ }
+ return parseFloat(sumCost.toFixed(2));
+ },
+
+ countTotalCost : function() {
+ var totalCost = 0;
+ this.getData().forEach(function(obj, index) {
+ totalCost += Controll.countSumCost(index);
+ });
+ return parseFloat(totalCost.toFixed(2));
+ }
+ };
+
+ var View = {
+ init : function() {
+
+ this.xhr = null;
+
+ $(document).on( "keyup", "[name $= '[count]']", function(e) {
+ var form = $(this).parents("form");
+ Controll.setData();
+// console.log(Controll.getData());
+ $("[name $= '[sum_cost]']").each(function(index, el) {
+ var sumCost = Controll.countSumCost(index);
+ $(el).val(sumCost);
+ $($(".t_sum_cost")[index]).text(sumCost);
+ });
+
+ var total_cost = Controll.countTotalCost();
+ $("#order-total").val(total_cost);
+ $(".t_total_cost").text(total_cost);
+// console.log(total_cost);
+
+ if (View.xhr !== null){
+ View.xhr.abort();
+ }
+
+ View.xhr = $.ajax(
+ "/basket/update",
+ {
+ 'data' : form.serializeArray(),
+ 'method' : "POST"
+ }
+ )
+ .done(function(data) {
+// console.log("done");
+ $(basket_id).html(data);
+ })
+ .fail(function() {
+// console.error("ERROR");
+ })
+ .always(function() {
+// console.log("xhr to null");
+ View.xhr = null;
+ });
+
+ } );
+ }
+
+ };
+
+ Controll.init();
+ // frontend calculator
+ }
+
+})(jQuery);
\ No newline at end of file
diff --git a/js/call.js b/js/call.js
new file mode 100755
index 0000000..d5ddc03
--- /dev/null
+++ b/js/call.js
@@ -0,0 +1,48 @@
+(function($){
+
+ $.fn.call = function(callerSettings) {
+
+ var login_id = this;
+
+ $(login_id).bind('click',function(){
+ winW = document.body.offsetWidth;
+ winH = document.body.offsetHeight
+ $('.modal_box').remove();
+ $('#data_box').remove();
+ $('body').append('
');
+ $('body').append('
');
+ $('#data_box').append('
');
+ $('#data_box').css( "left", ((winW-350)/2)+'px' );
+
+ var scrollTop = document.documentElement.scrollTop
+ if (navigator.userAgent.toLowerCase().indexOf('chrome') > -1) {
+ scrollTop = document.body.scrollTop;
+ }
+ $('#data_box').css( {"top" : (scrollTop+200)+'px',"width":"350px"} );
+
+ $('#data_box .data_wrp').append(' ');
+ app = 'Обратный звонок ';
+ app += ' ';
+ app += '';
+
+ $('#data_box .data_wrp').append(app);
+
+ $(".modal_box, #modal_close").click(function() {
+ $('.modal_box').remove();
+ $('#data_box').remove();
+ });
+ return false;
+ })
+
+ }
+
+})(jQuery);
\ No newline at end of file
diff --git a/js/fancyBox/.gitattributes b/js/fancyBox/.gitattributes
new file mode 100644
index 0000000..f6bb280
--- /dev/null
+++ b/js/fancyBox/.gitattributes
@@ -0,0 +1,7 @@
+# Auto detect text files and perform LF normalization
+* text=auto
+
+# Denote all files that are truly binary and should not be modified.
+*.png binary
+*.jpg binary
+*.gif binary
\ No newline at end of file
diff --git a/js/fancyBox/CHANGELOG.md b/js/fancyBox/CHANGELOG.md
new file mode 100644
index 0000000..b0d847e
--- /dev/null
+++ b/js/fancyBox/CHANGELOG.md
@@ -0,0 +1,125 @@
+fancyBox - Changelog
+=========
+
+### Version 2.1.5 - June 14, 2013
+* Fixed #493 - Broken slideshow
+* Fixed #556 - Parent option
+* Retina graphics (#564) and retina display support (#420)
+* Improved "lock" feature
+
+### Version 2.1.4 - January 10, 2013
+* Update to be compatible with jQuery v1.9
+* Small changes that should fix usability issues for certain users
+
+### Version 2.1.3 - October 23, 2012
+
+* Fixed #426 - Broken IE7
+* Fixed #423 - Background flickering on iOS
+* Fixed #418 - Automatically Grow/Shrink and Center
+* Updated the script to work with jQuery 1.6
+* Media helper supports YouTube video series
+
+### Version 2.1.2 - October 15, 2012
+
+* Fixed #414 - Don't allow nextClick if there is only one item
+* Fixed #397 - Button helper 'Menu' not visible in IE7
+* Overlay can be opened/closed manually:
+* $.fancybox.helpers.overlay.open();
+* $.fancybox.helpers.overlay.open({closeClick : false});
+* $.fancybox.helpers.overlay.close();
+* Optimized for Internet Explorer 10 (Windows 8)
+
+### Version 2.1.1 - October 01, 2012
+
+* Fixed #357 - Converting values like 'auto' in getScalar()
+* Fixed #358 - Updated overlay background image
+* New "fancybox-href" and "fancybox-title" HTML5 data-attributes (#317)
+* Improved helpers:
+* - now they can have a property 'defaults' that contains default settings
+* - updated vimeo and youtube parsers for media helper
+* Content locking now can be turned off
+
+### Version 2.1.0 - August 20, 2012
+
+* Fixed #103 - DOM element re-injection after closing
+* Fixed #188 - navigation keys inside editable content
+* New animation directions (see https://github.com/fancyapps/fancyBox/issues/233#issuecomment-5512453)
+* New option "iframe" - it is now possible to separate scrolling for iframe and wrapping element; choose to preload
+* New option "swf" - brings back functionality from fancyBox v1
+* Improved media helper - better support for vimeo and youtube; links are now configurable
+* Rewritten overlay helper:
+* - new option "showEarly" - toggles if should be open before of after content is loaded
+* - Facebook-style (https://github.com/fancyapps/fancyBox/issues/24) and therefore uses image for background
+* Option "padding" accepts array (e.g., padding: [15, 50, 10, 5])
+* One of dimensions (width or height) can now be set to "auto" (option "autoSize" needs to be "false")
+* Updated callbacks:
+* - "beforeClose" is now called only once
+* - "afterLoad" receives current and previous object as arguments
+* Method "$.fancybox.update();" recalculates content width/height
+* Updated to work with jQuery v1.8
+
+### Version 2.0.6 - April 16, 2012
+
+* Fixed #188 - keystrokes in contenteditable
+* Fixed #171 - non-images should not be preloaded
+* Fixed #158 - 'closeClick: true' breaks gallery navigation
+* New "media" helper - detects and displays various media types
+* New option "groupAttr" - name of group selector attribute, default is "data-fancybox-group"
+* New feature - selector expressions in URLs, see #170
+* Improved 'overlay' helper to use "position: fixed"
+* Improved autoSize, fixed wrong height in some cases
+* Improved centering and iframe scrolling for iOS
+* Updated markup, new element '.fancybox-skin' is now used for styling
+
+### Version 2.0.5 - February 21, 2012
+
+* Fixed #155 - easing for prev/next animations
+* Fixed #153 - overriding "keys" options
+* Fixed #147 - IE7 problem with #hash links
+* Fixed #130 - changing dynamically data-fancybox-group
+* Fixed #126 - obey minWidth/minHeight
+* Fixed #118 - placement of loading icon and navigation arrows
+* Fixed #101 - "index" option not working
+* Fixed #94 - "orig" option not working
+* Fixed #80 - does not work on IE6
+* Fixed #72 - can't set overlay opacity to 0
+* Fixed #63 - properly set gallery index
+* New option "autoCenter" - toggles centering on window resize or scroll, disabled for mobile devices by default
+* New option "autoResize" - toggles responsivity, disabled for mobile devices by default
+* New option "preload" - number of images to preload
+* New feature to target mobile/desktop browsers using CSS, see #108
+* Changed ajax option defaults to "{ dataType: 'html', headers: { 'X-fancyBox': true } }", see #150 and #128
+* Updated loading icon for IE7, IE8
+* Calculates height of the iframe if 'autoSize' is set to 'true' and the iframe is on the same domain as the main page
+
+### Version 2.0.4 - December 12, 2011
+
+* Fixed #47 - fix overriding properties
+* New option "position" to thumbnail and button helpers
+
+
+### Version 2.0.3 - November 29, 2011
+
+* Fixed #29 - broken elastic transitions
+
+
+### Version 2.0.2 - November 28, 2011
+
+* Fixed slideshow
+* Fixed scrollbars issue when displayed a very tall image
+* New option "nextClick" - navigate to next gallery item when user clicks the content
+* New option "modal" - to disable navigation and closing
+* Add 'metadata' plugin support
+* Add ability to create groups using 'data-fancybox-group' attribute
+* Updated manual usage to match earlier releases
+
+
+### Version 2.0.1 - November 23, 2011
+
+* Fixed keyboard events inside form elements
+* Fixed manual usage
+
+
+### Version 2.0.0 - November 21, 2011
+
+First release - completely rewritten, many new features and updated graphics.
\ No newline at end of file
diff --git a/js/fancyBox/README.md b/js/fancyBox/README.md
new file mode 100644
index 0000000..9434893
--- /dev/null
+++ b/js/fancyBox/README.md
@@ -0,0 +1,217 @@
+fancyBox
+========
+
+fancyBox is a tool that offers a nice and elegant way to add zooming functionality for images, html content and multi-media on your webpages.
+
+More information and examples: http://www.fancyapps.com/fancybox/
+
+License: http://www.fancyapps.com/fancybox/#license
+
+Copyright (c) 2012 Janis Skarnelis - janis@fancyapps.com
+
+
+How to use
+----------
+
+To get started, download the plugin, unzip it and copy files to your website/application directory.
+Load files in the section of your HTML document. Make sure you also add the jQuery library.
+
+
+
+
+
+
+
+Create your links with a `title` if you want a title to be shown, and add a class:
+
+
+
+If you have a set of related items that you would like to group,
+additionally include a group name in the `rel` (or `data-fancybox-group`) attribute:
+
+
+
+
+Initialise the script like this:
+
+
+
+May also be passed an optional options object which will extend the default values. Example:
+
+
+
+Tip: Automatically group and apply fancyBox to all images:
+
+ $("a[href$='.jpg'],a[href$='.jpeg'],a[href$='.png'],a[href$='.gif']").attr('rel', 'gallery').fancybox();
+
+Script uses the `href` attribute of the matched elements to obtain the location of the content and to figure out content type you want to display.
+You can specify type directly by adding classname (fancybox.image, fancybox.iframe, etc) or `data-fancybox-type` attribute:
+
+ //Ajax:
+ Example
+ //or
+ Example
+
+ //Iframe:
+ Example
+
+ //Inline (will display an element with `id="example"`)
+ Example
+
+ //SWF:
+ Example
+
+ //Image:
+ Example
+
+Note, ajax requests are subject to the [same origin policy](http://en.wikipedia.org/wiki/Same_origin_policy).
+If fancyBox will not be able to get content type, it will try to guess based on 'href' and will quit silently if would not succeed.
+(this is different from previsous versions where 'ajax' was used as default type or an error message was displayed).
+
+Advanced
+--------
+
+### Helpers
+
+Helpers provide a simple mechanism to extend the capabilities of fancyBox. There are two built-in helpers - 'overlay' and 'title'.
+You can disable them, set custom options or enable other helpers. Examples:
+
+ //Disable title helper
+ $(".fancybox").fancybox({
+ helpers: {
+ title: null
+ }
+ });
+
+ //Disable overlay helper
+ $(".fancybox").fancybox({
+ helpers: {
+ overlay : null
+ }
+ });
+
+ //Change title position and overlay color
+ $(".fancybox").fancybox({
+ helpers: {
+ title : {
+ type : 'inside'
+ },
+ overlay : {
+ css : {
+ 'background' : 'rgba(255,255,255,0.5)'
+ }
+ }
+ }
+ });
+
+ //Enable thumbnail helper and set custom options
+ $(".fancybox").fancybox({
+ helpers: {
+ thumbs : {
+ width: 50,
+ height: 50
+ }
+ }
+ });
+
+
+### API
+
+Also available are event driven callback methods. The `this` keyword refers to the current or upcoming object (depends on callback method). Here is how you can change title:
+
+ $(".fancybox").fancybox({
+ beforeLoad : function() {
+ this.title = 'Image ' + (this.index + 1) + ' of ' + this.group.length + (this.title ? ' - ' + this.title : '');
+
+ /*
+ "this.element" refers to current element, so you can, for example, use the "alt" attribute of the image to store the title:
+ this.title = $(this.element).find('img').attr('alt');
+ */
+ }
+ });
+
+It`s possible to open fancyBox programmatically in various ways:
+
+ //HTML content:
+ $.fancybox( '', {
+ title : 'Custom Title'
+ });
+
+ //DOM element:
+ $.fancybox( $("#inline"), {
+ title : 'Custom Title'
+ });
+
+ //Custom object:
+ $.fancybox({
+ href: 'example.jpg',
+ title : 'Custom Title'
+ });
+
+ //Array of objects:
+ $.fancybox([
+ {
+ href: 'example1.jpg',
+ title : 'Custom Title 1'
+ },
+ {
+ href: 'example2.jpg',
+ title : 'Custom Title 2'
+ }
+ ], {
+ padding: 0
+ });
+
+There are several methods that allow you to interact with and manipulate fancyBox, example:
+
+ //Close fancybox:
+ $.fancybox.close();
+
+There is a simply way to access wrapping elements using JS:
+
+ $.fancybox.wrap
+ $.fancybox.skin
+ $.fancybox.outer
+ $.fancybox.inner
+
+You can override CSS to customize the look. For example, make navigation arrows always visible,
+change width and move them outside of area (use this snippet after including fancybox.css):
+
+ .fancybox-nav span {
+ visibility: visible;
+ }
+
+ .fancybox-nav {
+ width: 80px;
+ }
+
+ .fancybox-prev {
+ left: -80px;
+ }
+
+ .fancybox-next {
+ right: -80px;
+ }
+
+In that case, you might want to increase space around box:
+
+ $(".fancybox").fancybox({
+ margin : [20, 60, 20, 60]
+ });
+
+
+Bug tracker
+-----------
+
+Have a bug? Please create an issue on GitHub at https://github.com/fancyapps/fancyBox/issues
\ No newline at end of file
diff --git a/js/fancyBox/demo/1_b.jpg b/js/fancyBox/demo/1_b.jpg
new file mode 100644
index 0000000..0f662e3
Binary files /dev/null and b/js/fancyBox/demo/1_b.jpg differ
diff --git a/js/fancyBox/demo/1_s.jpg b/js/fancyBox/demo/1_s.jpg
new file mode 100644
index 0000000..ef0bd55
Binary files /dev/null and b/js/fancyBox/demo/1_s.jpg differ
diff --git a/js/fancyBox/demo/2_b.jpg b/js/fancyBox/demo/2_b.jpg
new file mode 100644
index 0000000..977cb6a
Binary files /dev/null and b/js/fancyBox/demo/2_b.jpg differ
diff --git a/js/fancyBox/demo/2_s.jpg b/js/fancyBox/demo/2_s.jpg
new file mode 100644
index 0000000..258cbcb
Binary files /dev/null and b/js/fancyBox/demo/2_s.jpg differ
diff --git a/js/fancyBox/demo/3_b.jpg b/js/fancyBox/demo/3_b.jpg
new file mode 100644
index 0000000..e007a51
Binary files /dev/null and b/js/fancyBox/demo/3_b.jpg differ
diff --git a/js/fancyBox/demo/3_s.jpg b/js/fancyBox/demo/3_s.jpg
new file mode 100644
index 0000000..7206f24
Binary files /dev/null and b/js/fancyBox/demo/3_s.jpg differ
diff --git a/js/fancyBox/demo/4_b.jpg b/js/fancyBox/demo/4_b.jpg
new file mode 100644
index 0000000..a3a12a6
Binary files /dev/null and b/js/fancyBox/demo/4_b.jpg differ
diff --git a/js/fancyBox/demo/4_s.jpg b/js/fancyBox/demo/4_s.jpg
new file mode 100644
index 0000000..b9ea423
Binary files /dev/null and b/js/fancyBox/demo/4_s.jpg differ
diff --git a/js/fancyBox/demo/5_b.jpg b/js/fancyBox/demo/5_b.jpg
new file mode 100644
index 0000000..ea1cfbc
Binary files /dev/null and b/js/fancyBox/demo/5_b.jpg differ
diff --git a/js/fancyBox/demo/5_s.jpg b/js/fancyBox/demo/5_s.jpg
new file mode 100644
index 0000000..989975d
Binary files /dev/null and b/js/fancyBox/demo/5_s.jpg differ
diff --git a/js/fancyBox/demo/ajax.txt b/js/fancyBox/demo/ajax.txt
new file mode 100644
index 0000000..0850e80
--- /dev/null
+++ b/js/fancyBox/demo/ajax.txt
@@ -0,0 +1,15 @@
+
+
Lorem ipsum dolor sit amet3
+
+ Close me
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas fermentum ante et sapien dignissim in viverra magna feugiat. Donec tempus ipsum nec neque dignissim quis eleifend eros gravida. Praesent nisi massa, sodales quis tincidunt ac, semper quis risus. In suscipit nisl sed leo aliquet consequat. Integer vitae augue in risus porttitor pellentesque eu eget odio. Fusce ut sagittis quam. Morbi aliquam interdum blandit. Integer pharetra tempor velit, aliquam dictum justo tempus sed. Morbi congue fringilla justo a feugiat. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent quis metus et nisl consectetur pharetra. Nam bibendum turpis eu metus luctus eu volutpat sem molestie. Nam sollicitudin porttitor lorem, ac ultricies est venenatis eu. Ut dignissim elit et orci feugiat ac placerat purus euismod. Ut mi lorem, cursus et sagittis elementum, luctus ac massa.
+
+
+ Phasellus et ligula vel diam ullamcorper volutpat. Integer rhoncus rhoncus aliquam. Aliquam erat volutpat. Aenean luctus vestibulum placerat. Quisque quam neque, lacinia aliquet eleifend ac, aliquet blandit felis. Curabitur porta ultricies dui, sit amet mattis quam euismod a. Ut eleifend scelerisque neque, sit amet accumsan odio consequat ut. Proin facilisis auctor elit sed accumsan. Cras dapibus nisl in nisi rhoncus laoreet. Nullam pellentesque tortor libero, eget facilisis ipsum. Donec ultricies tellus tellus, in tincidunt purus. Nullam in est aliquam velit scelerisque blandit. In tincidunt, magna a dapibus imperdiet, quam urna elementum leo, vitae rhoncus nisl velit cursus velit. In dignissim sem ac mauris rhoncus ornare.
+
+
+ Duis imperdiet velit vel quam malesuada suscipit imperdiet tellus hendrerit. Mauris vestibulum odio mauris, ut placerat leo. Mauris quis neque at tellus feugiat congue id non enim. Nam vehicula posuere nulla eget vehicula. Donec pretium purus nec ligula porta eu laoreet sapien venenatis. Nulla facilisi. Phasellus eget mi enim. Phasellus molestie tincidunt ultrices. Aenean id sem a tellus lobortis tincidunt. Nam laoreet nulla vel velit tincidunt ac rutrum libero malesuada. Nulla consequat dolor quis nisl tempor fermentum. Integer sodales pretium varius. Aenean a leo vitae odio dictum dignissim malesuada nec dolor. Phasellus adipiscing viverra est, ac sagittis libero sagittis quis. Sed interdum dapibus nunc et fringilla. Nunc vel velit et urna laoreet bibendum.
+
+
\ No newline at end of file
diff --git a/js/fancyBox/demo/iframe.html b/js/fancyBox/demo/iframe.html
new file mode 100644
index 0000000..b586e15
--- /dev/null
+++ b/js/fancyBox/demo/iframe.html
@@ -0,0 +1,26 @@
+
+
+
+ fancyBox - iframe demo
+
+
+
+ fancyBox - iframe demo
+
+
+ Close iframe parent
+
+ |
+
+ Change content
+
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam scelerisque justo ac eros consectetur bibendum. In hac habitasse platea dictumst. Nulla aliquam turpis et tellus elementum luctus. Duis sit amet rhoncus velit. Duis nisl ligula, mattis interdum blandit laoreet, mattis id ante. Cras pulvinar lacus vitae nisi egestas non euismod neque bibendum. Vestibulum faucibus libero id ante molestie ultricies. Vestibulum quis nibh felis. Vestibulum libero nisl, vehicula vel ullamcorper sit amet, tristique sit amet augue. Etiam urna neque, porttitor sed sodales lacinia, posuere a nisl. Vestibulum blandit neque in sapien volutpat ac condimentum sapien auctor. Ut imperdiet venenatis ultricies. Phasellus accumsan, sem eu placerat commodo, felis purus commodo ipsum, sit amet vulputate orci est viverra est.
+
+
+
+ Aenean velit est, condimentum ut iaculis ut, accumsan at mi. Maecenas velit mi, venenatis ut condimentum at, ultrices vel tortor. Curabitur pharetra ornare dapibus. Ut volutpat cursus semper. In hac habitasse platea dictumst. Donec eu iaculis ipsum. Morbi eu dolor velit, a semper nunc.
+
+
+
\ No newline at end of file
diff --git a/js/fancyBox/demo/index.html b/js/fancyBox/demo/index.html
new file mode 100644
index 0000000..bb079bb
--- /dev/null
+++ b/js/fancyBox/demo/index.html
@@ -0,0 +1,138 @@
+
+
+
+ fancyBox - Fancy jQuery Lightbox Alternative | Demonstration
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ fancyBox
+
+ This is a demonstration. More information and examples: www.fancyapps.com/fancybox/
+
+ Simple image gallery
+
+
+
+
+
+
+
+
+
+
+ Different effects
+
+
+
+
+
+
+
+
+
+
+ Various types
+
+ fancyBox will try to guess content type from href attribute but you can specify it directly by adding classname (fancybox.image, fancybox.iframe, etc).
+
+
+
+
+
Etiam quis mi eu elit
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam quis mi eu elit tempor facilisis id et neque. Nulla sit amet sem sapien. Vestibulum imperdiet porta ante ac ornare. Nulla et lorem eu nibh adipiscing ultricies nec at lacus. Cras laoreet ultricies sem, at blandit mi eleifend aliquam. Nunc enim ipsum, vehicula non pretium varius, cursus ac tortor. Vivamus fringilla congue laoreet. Quisque ultrices sodales orci, quis rhoncus justo auctor in. Phasellus dui eros, bibendum eu feugiat ornare, faucibus eu mi. Nunc aliquet tempus sem, id aliquam diam varius ac. Maecenas nisl nunc, molestie vitae eleifend vel, iaculis sed magna. Aenean tempus lacus vitae orci posuere porttitor eget non felis. Donec lectus elit, aliquam nec eleifend sit amet, vestibulum sed nunc.
+
+
+
+
+ Ajax example will not run from your local computer and requires a server to run.
+
+
+ Button helper
+
+
+
+
+
+
+
+
+
+
+ Thumbnail helper
+
+
+
+
+
+
+
+
+
+
+ Media helper
+
+ Will not run from your local computer, requires a server to run.
+
+
+
+
+ Open manually
+
+
+
+ Photo Credit: Instagrammer @whitjohns
+
+
+
\ No newline at end of file
diff --git a/js/fancyBox/lib/jquery-1.10.1.min.js b/js/fancyBox/lib/jquery-1.10.1.min.js
new file mode 100644
index 0000000..e407e76
--- /dev/null
+++ b/js/fancyBox/lib/jquery-1.10.1.min.js
@@ -0,0 +1,6 @@
+/*! jQuery v1.10.1 | (c) 2005, 2013 jQuery Foundation, Inc. | jquery.org/license
+//@ sourceMappingURL=jquery-1.10.1.min.map
+*/
+(function(e,t){var n,r,i=typeof t,o=e.location,a=e.document,s=a.documentElement,l=e.jQuery,u=e.$,c={},p=[],f="1.10.1",d=p.concat,h=p.push,g=p.slice,m=p.indexOf,y=c.toString,v=c.hasOwnProperty,b=f.trim,x=function(e,t){return new x.fn.init(e,t,r)},w=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,T=/\S+/g,C=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,N=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,k=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,E=/^[\],:{}\s]*$/,S=/(?:^|:|,)(?:\s*\[)+/g,A=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,j=/"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,D=/^-ms-/,L=/-([\da-z])/gi,H=function(e,t){return t.toUpperCase()},q=function(e){(a.addEventListener||"load"===e.type||"complete"===a.readyState)&&(_(),x.ready())},_=function(){a.addEventListener?(a.removeEventListener("DOMContentLoaded",q,!1),e.removeEventListener("load",q,!1)):(a.detachEvent("onreadystatechange",q),e.detachEvent("onload",q))};x.fn=x.prototype={jquery:f,constructor:x,init:function(e,n,r){var i,o;if(!e)return this;if("string"==typeof e){if(i="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:N.exec(e),!i||!i[1]&&n)return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e);if(i[1]){if(n=n instanceof x?n[0]:n,x.merge(this,x.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:a,!0)),k.test(i[1])&&x.isPlainObject(n))for(i in n)x.isFunction(this[i])?this[i](n[i]):this.attr(i,n[i]);return this}if(o=a.getElementById(i[2]),o&&o.parentNode){if(o.id!==i[2])return r.find(e);this.length=1,this[0]=o}return this.context=a,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):x.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),x.makeArray(e,this))},selector:"",length:0,toArray:function(){return g.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=x.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return x.each(this,e,t)},ready:function(e){return x.ready.promise().done(e),this},slice:function(){return this.pushStack(g.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(x.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:h,sort:[].sort,splice:[].splice},x.fn.init.prototype=x.fn,x.extend=x.fn.extend=function(){var e,n,r,i,o,a,s=arguments[0]||{},l=1,u=arguments.length,c=!1;for("boolean"==typeof s&&(c=s,s=arguments[1]||{},l=2),"object"==typeof s||x.isFunction(s)||(s={}),u===l&&(s=this,--l);u>l;l++)if(null!=(o=arguments[l]))for(i in o)e=s[i],r=o[i],s!==r&&(c&&r&&(x.isPlainObject(r)||(n=x.isArray(r)))?(n?(n=!1,a=e&&x.isArray(e)?e:[]):a=e&&x.isPlainObject(e)?e:{},s[i]=x.extend(c,a,r)):r!==t&&(s[i]=r));return s},x.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),noConflict:function(t){return e.$===x&&(e.$=u),t&&e.jQuery===x&&(e.jQuery=l),x},isReady:!1,readyWait:1,holdReady:function(e){e?x.readyWait++:x.ready(!0)},ready:function(e){if(e===!0?!--x.readyWait:!x.isReady){if(!a.body)return setTimeout(x.ready);x.isReady=!0,e!==!0&&--x.readyWait>0||(n.resolveWith(a,[x]),x.fn.trigger&&x(a).trigger("ready").off("ready"))}},isFunction:function(e){return"function"===x.type(e)},isArray:Array.isArray||function(e){return"array"===x.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?c[y.call(e)]||"object":typeof e},isPlainObject:function(e){var n;if(!e||"object"!==x.type(e)||e.nodeType||x.isWindow(e))return!1;try{if(e.constructor&&!v.call(e,"constructor")&&!v.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(r){return!1}if(x.support.ownLast)for(n in e)return v.call(e,n);for(n in e);return n===t||v.call(e,n)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||a;var r=k.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=x.buildFragment([e],t,i),i&&x(i).remove(),x.merge([],r.childNodes))},parseJSON:function(n){return e.JSON&&e.JSON.parse?e.JSON.parse(n):null===n?n:"string"==typeof n&&(n=x.trim(n),n&&E.test(n.replace(A,"@").replace(j,"]").replace(S,"")))?Function("return "+n)():(x.error("Invalid JSON: "+n),t)},parseXML:function(n){var r,i;if(!n||"string"!=typeof n)return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(o){r=t}return r&&r.documentElement&&!r.getElementsByTagName("parsererror").length||x.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&x.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(D,"ms-").replace(L,H)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,a=M(e);if(n){if(a){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(a){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:b&&!b.call("\ufeff\u00a0")?function(e){return null==e?"":b.call(e)}:function(e){return null==e?"":(e+"").replace(C,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(M(Object(e))?x.merge(n,"string"==typeof e?[e]:e):h.call(n,e)),n},inArray:function(e,t,n){var r;if(t){if(m)return m.call(t,e,n);for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,o=0;if("number"==typeof r)for(;r>o;o++)e[i++]=n[o];else while(n[o]!==t)e[i++]=n[o++];return e.length=i,e},grep:function(e,t,n){var r,i=[],o=0,a=e.length;for(n=!!n;a>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,a=M(e),s=[];if(a)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(s[s.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(s[s.length]=r);return d.apply([],s)},guid:1,proxy:function(e,n){var r,i,o;return"string"==typeof n&&(o=e[n],n=e,e=o),x.isFunction(e)?(r=g.call(arguments,2),i=function(){return e.apply(n||this,r.concat(g.call(arguments)))},i.guid=e.guid=e.guid||x.guid++,i):t},access:function(e,n,r,i,o,a,s){var l=0,u=e.length,c=null==r;if("object"===x.type(r)){o=!0;for(l in r)x.access(e,n,l,r[l],!0,a,s)}else if(i!==t&&(o=!0,x.isFunction(i)||(s=!0),c&&(s?(n.call(e,i),n=null):(c=n,n=function(e,t,n){return c.call(x(e),n)})),n))for(;u>l;l++)n(e[l],r,s?i:i.call(e[l],l,n(e[l],r)));return o?e:c?n.call(e):u?n(e[0],r):a},now:function(){return(new Date).getTime()},swap:function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i}}),x.ready.promise=function(t){if(!n)if(n=x.Deferred(),"complete"===a.readyState)setTimeout(x.ready);else if(a.addEventListener)a.addEventListener("DOMContentLoaded",q,!1),e.addEventListener("load",q,!1);else{a.attachEvent("onreadystatechange",q),e.attachEvent("onload",q);var r=!1;try{r=null==e.frameElement&&a.documentElement}catch(i){}r&&r.doScroll&&function o(){if(!x.isReady){try{r.doScroll("left")}catch(e){return setTimeout(o,50)}_(),x.ready()}}()}return n.promise(t)},x.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){c["[object "+t+"]"]=t.toLowerCase()});function M(e){var t=e.length,n=x.type(e);return x.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}r=x(a),function(e,t){var n,r,i,o,a,s,l,u,c,p,f,d,h,g,m,y,v,b="sizzle"+-new Date,w=e.document,T=0,C=0,N=lt(),k=lt(),E=lt(),S=!1,A=function(){return 0},j=typeof t,D=1<<31,L={}.hasOwnProperty,H=[],q=H.pop,_=H.push,M=H.push,O=H.slice,F=H.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},B="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",P="[\\x20\\t\\r\\n\\f]",R="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",W=R.replace("w","w#"),$="\\["+P+"*("+R+")"+P+"*(?:([*^$|!~]?=)"+P+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+W+")|)|)"+P+"*\\]",I=":("+R+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+$.replace(3,8)+")*)|.*)\\)|)",z=RegExp("^"+P+"+|((?:^|[^\\\\])(?:\\\\.)*)"+P+"+$","g"),X=RegExp("^"+P+"*,"+P+"*"),U=RegExp("^"+P+"*([>+~]|"+P+")"+P+"*"),V=RegExp(P+"*[+~]"),Y=RegExp("="+P+"*([^\\]'\"]*)"+P+"*\\]","g"),J=RegExp(I),G=RegExp("^"+W+"$"),Q={ID:RegExp("^#("+R+")"),CLASS:RegExp("^\\.("+R+")"),TAG:RegExp("^("+R.replace("w","w*")+")"),ATTR:RegExp("^"+$),PSEUDO:RegExp("^"+I),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+P+"*(even|odd|(([+-]|)(\\d*)n|)"+P+"*(?:([+-]|)"+P+"*(\\d+)|))"+P+"*\\)|)","i"),bool:RegExp("^(?:"+B+")$","i"),needsContext:RegExp("^"+P+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+P+"*((?:-\\d)?\\d*)"+P+"*\\)|)(?=[^-]|$)","i")},K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,et=/^(?:input|select|textarea|button)$/i,tt=/^h\d$/i,nt=/'|\\/g,rt=RegExp("\\\\([\\da-f]{1,6}"+P+"?|("+P+")|.)","ig"),it=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:0>r?String.fromCharCode(r+65536):String.fromCharCode(55296|r>>10,56320|1023&r)};try{M.apply(H=O.call(w.childNodes),w.childNodes),H[w.childNodes.length].nodeType}catch(ot){M={apply:H.length?function(e,t){_.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function at(e,t,n,i){var o,a,s,l,u,c,d,m,y,x;if((t?t.ownerDocument||t:w)!==f&&p(t),t=t||f,n=n||[],!e||"string"!=typeof e)return n;if(1!==(l=t.nodeType)&&9!==l)return[];if(h&&!i){if(o=Z.exec(e))if(s=o[1]){if(9===l){if(a=t.getElementById(s),!a||!a.parentNode)return n;if(a.id===s)return n.push(a),n}else if(t.ownerDocument&&(a=t.ownerDocument.getElementById(s))&&v(t,a)&&a.id===s)return n.push(a),n}else{if(o[2])return M.apply(n,t.getElementsByTagName(e)),n;if((s=o[3])&&r.getElementsByClassName&&t.getElementsByClassName)return M.apply(n,t.getElementsByClassName(s)),n}if(r.qsa&&(!g||!g.test(e))){if(m=d=b,y=t,x=9===l&&e,1===l&&"object"!==t.nodeName.toLowerCase()){c=bt(e),(d=t.getAttribute("id"))?m=d.replace(nt,"\\$&"):t.setAttribute("id",m),m="[id='"+m+"'] ",u=c.length;while(u--)c[u]=m+xt(c[u]);y=V.test(e)&&t.parentNode||t,x=c.join(",")}if(x)try{return M.apply(n,y.querySelectorAll(x)),n}catch(T){}finally{d||t.removeAttribute("id")}}}return At(e.replace(z,"$1"),t,n,i)}function st(e){return K.test(e+"")}function lt(){var e=[];function t(n,r){return e.push(n+=" ")>o.cacheLength&&delete t[e.shift()],t[n]=r}return t}function ut(e){return e[b]=!0,e}function ct(e){var t=f.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function pt(e,t,n){e=e.split("|");var r,i=e.length,a=n?null:t;while(i--)(r=o.attrHandle[e[i]])&&r!==t||(o.attrHandle[e[i]]=a)}function ft(e,t){var n=e.getAttributeNode(t);return n&&n.specified?n.value:e[t]===!0?t.toLowerCase():null}function dt(e,t){return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}function ht(e){return"input"===e.nodeName.toLowerCase()?e.defaultValue:t}function gt(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||D)-(~e.sourceIndex||D);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function mt(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function yt(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function vt(e){return ut(function(t){return t=+t,ut(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}s=at.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},r=at.support={},p=at.setDocument=function(e){var n=e?e.ownerDocument||e:w,i=n.parentWindow;return n!==f&&9===n.nodeType&&n.documentElement?(f=n,d=n.documentElement,h=!s(n),i&&i.frameElement&&i.attachEvent("onbeforeunload",function(){p()}),r.attributes=ct(function(e){return e.innerHTML=" ",pt("type|href|height|width",dt,"#"===e.firstChild.getAttribute("href")),pt(B,ft,null==e.getAttribute("disabled")),e.className="i",!e.getAttribute("className")}),r.input=ct(function(e){return e.innerHTML=" ",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")}),pt("value",ht,r.attributes&&r.input),r.getElementsByTagName=ct(function(e){return e.appendChild(n.createComment("")),!e.getElementsByTagName("*").length}),r.getElementsByClassName=ct(function(e){return e.innerHTML="
",e.firstChild.className="i",2===e.getElementsByClassName("i").length}),r.getById=ct(function(e){return d.appendChild(e).id=b,!n.getElementsByName||!n.getElementsByName(b).length}),r.getById?(o.find.ID=function(e,t){if(typeof t.getElementById!==j&&h){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){return e.getAttribute("id")===t}}):(delete o.find.ID,o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){var n=typeof e.getAttributeNode!==j&&e.getAttributeNode("id");return n&&n.value===t}}),o.find.TAG=r.getElementsByTagName?function(e,n){return typeof n.getElementsByTagName!==j?n.getElementsByTagName(e):t}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},o.find.CLASS=r.getElementsByClassName&&function(e,n){return typeof n.getElementsByClassName!==j&&h?n.getElementsByClassName(e):t},m=[],g=[],(r.qsa=st(n.querySelectorAll))&&(ct(function(e){e.innerHTML=" ",e.querySelectorAll("[selected]").length||g.push("\\["+P+"*(?:value|"+B+")"),e.querySelectorAll(":checked").length||g.push(":checked")}),ct(function(e){var t=n.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("t",""),e.querySelectorAll("[t^='']").length&&g.push("[*^$]="+P+"*(?:''|\"\")"),e.querySelectorAll(":enabled").length||g.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),g.push(",.*:")})),(r.matchesSelector=st(y=d.webkitMatchesSelector||d.mozMatchesSelector||d.oMatchesSelector||d.msMatchesSelector))&&ct(function(e){r.disconnectedMatch=y.call(e,"div"),y.call(e,"[s!='']:x"),m.push("!=",I)}),g=g.length&&RegExp(g.join("|")),m=m.length&&RegExp(m.join("|")),v=st(d.contains)||d.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},r.sortDetached=ct(function(e){return 1&e.compareDocumentPosition(n.createElement("div"))}),A=d.compareDocumentPosition?function(e,t){if(e===t)return S=!0,0;var i=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t);return i?1&i||!r.sortDetached&&t.compareDocumentPosition(e)===i?e===n||v(w,e)?-1:t===n||v(w,t)?1:c?F.call(c,e)-F.call(c,t):0:4&i?-1:1:e.compareDocumentPosition?-1:1}:function(e,t){var r,i=0,o=e.parentNode,a=t.parentNode,s=[e],l=[t];if(e===t)return S=!0,0;if(!o||!a)return e===n?-1:t===n?1:o?-1:a?1:c?F.call(c,e)-F.call(c,t):0;if(o===a)return gt(e,t);r=e;while(r=r.parentNode)s.unshift(r);r=t;while(r=r.parentNode)l.unshift(r);while(s[i]===l[i])i++;return i?gt(s[i],l[i]):s[i]===w?-1:l[i]===w?1:0},n):f},at.matches=function(e,t){return at(e,null,null,t)},at.matchesSelector=function(e,t){if((e.ownerDocument||e)!==f&&p(e),t=t.replace(Y,"='$1']"),!(!r.matchesSelector||!h||m&&m.test(t)||g&&g.test(t)))try{var n=y.call(e,t);if(n||r.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(i){}return at(t,f,null,[e]).length>0},at.contains=function(e,t){return(e.ownerDocument||e)!==f&&p(e),v(e,t)},at.attr=function(e,n){(e.ownerDocument||e)!==f&&p(e);var i=o.attrHandle[n.toLowerCase()],a=i&&L.call(o.attrHandle,n.toLowerCase())?i(e,n,!h):t;return a===t?r.attributes||!h?e.getAttribute(n):(a=e.getAttributeNode(n))&&a.specified?a.value:null:a},at.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},at.uniqueSort=function(e){var t,n=[],i=0,o=0;if(S=!r.detectDuplicates,c=!r.sortStable&&e.slice(0),e.sort(A),S){while(t=e[o++])t===e[o]&&(i=n.push(o));while(i--)e.splice(n[i],1)}return e},a=at.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=a(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=a(t);return n},o=at.selectors={cacheLength:50,createPseudo:ut,match:Q,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(rt,it),e[3]=(e[4]||e[5]||"").replace(rt,it),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||at.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&at.error(e[0]),e},PSEUDO:function(e){var n,r=!e[5]&&e[2];return Q.CHILD.test(e[0])?null:(e[3]&&e[4]!==t?e[2]=e[4]:r&&J.test(r)&&(n=bt(r,!0))&&(n=r.indexOf(")",r.length-n)-r.length)&&(e[0]=e[0].slice(0,n),e[2]=r.slice(0,n)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(rt,it).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=N[e+" "];return t||(t=RegExp("(^|"+P+")"+e+"("+P+"|$)"))&&N(e,function(e){return t.test("string"==typeof e.className&&e.className||typeof e.getAttribute!==j&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=at.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,l){var u,c,p,f,d,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!l&&!s;if(m){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){c=m[b]||(m[b]={}),u=c[e]||[],d=u[0]===T&&u[1],f=u[0]===T&&u[2],p=d&&m.childNodes[d];while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[T,d,f];break}}else if(v&&(u=(t[b]||(t[b]={}))[e])&&u[0]===T)f=u[1];else while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(v&&((p[b]||(p[b]={}))[e]=[T,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=o.pseudos[e]||o.setFilters[e.toLowerCase()]||at.error("unsupported pseudo: "+e);return r[b]?r(t):r.length>1?(n=[e,e,"",t],o.setFilters.hasOwnProperty(e.toLowerCase())?ut(function(e,n){var i,o=r(e,t),a=o.length;while(a--)i=F.call(e,o[a]),e[i]=!(n[i]=o[a])}):function(e){return r(e,0,n)}):r}},pseudos:{not:ut(function(e){var t=[],n=[],r=l(e.replace(z,"$1"));return r[b]?ut(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:ut(function(e){return function(t){return at(e,t).length>0}}),contains:ut(function(e){return function(t){return(t.textContent||t.innerText||a(t)).indexOf(e)>-1}}),lang:ut(function(e){return G.test(e||"")||at.error("unsupported lang: "+e),e=e.replace(rt,it).toLowerCase(),function(t){var n;do if(n=h?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===d},focus:function(e){return e===f.activeElement&&(!f.hasFocus||f.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!o.pseudos.empty(e)},header:function(e){return tt.test(e.nodeName)},input:function(e){return et.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:vt(function(){return[0]}),last:vt(function(e,t){return[t-1]}),eq:vt(function(e,t,n){return[0>n?n+t:n]}),even:vt(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:vt(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:vt(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:vt(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}};for(n in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})o.pseudos[n]=mt(n);for(n in{submit:!0,reset:!0})o.pseudos[n]=yt(n);function bt(e,t){var n,r,i,a,s,l,u,c=k[e+" "];if(c)return t?0:c.slice(0);s=e,l=[],u=o.preFilter;while(s){(!n||(r=X.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),l.push(i=[])),n=!1,(r=U.exec(s))&&(n=r.shift(),i.push({value:n,type:r[0].replace(z," ")}),s=s.slice(n.length));for(a in o.filter)!(r=Q[a].exec(s))||u[a]&&!(r=u[a](r))||(n=r.shift(),i.push({value:n,type:a,matches:r}),s=s.slice(n.length));if(!n)break}return t?s.length:s?at.error(e):k(e,l).slice(0)}function xt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function wt(e,t,n){var r=t.dir,o=n&&"parentNode"===r,a=C++;return t.first?function(t,n,i){while(t=t[r])if(1===t.nodeType||o)return e(t,n,i)}:function(t,n,s){var l,u,c,p=T+" "+a;if(s){while(t=t[r])if((1===t.nodeType||o)&&e(t,n,s))return!0}else while(t=t[r])if(1===t.nodeType||o)if(c=t[b]||(t[b]={}),(u=c[r])&&u[0]===p){if((l=u[1])===!0||l===i)return l===!0}else if(u=c[r]=[p],u[1]=e(t,n,s)||i,u[1]===!0)return!0}}function Tt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function Ct(e,t,n,r,i){var o,a=[],s=0,l=e.length,u=null!=t;for(;l>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),u&&t.push(s));return a}function Nt(e,t,n,r,i,o){return r&&!r[b]&&(r=Nt(r)),i&&!i[b]&&(i=Nt(i,o)),ut(function(o,a,s,l){var u,c,p,f=[],d=[],h=a.length,g=o||St(t||"*",s.nodeType?[s]:s,[]),m=!e||!o&&t?g:Ct(g,f,e,s,l),y=n?i||(o?e:h||r)?[]:a:m;if(n&&n(m,y,s,l),r){u=Ct(y,d),r(u,[],s,l),c=u.length;while(c--)(p=u[c])&&(y[d[c]]=!(m[d[c]]=p))}if(o){if(i||e){if(i){u=[],c=y.length;while(c--)(p=y[c])&&u.push(m[c]=p);i(null,y=[],u,l)}c=y.length;while(c--)(p=y[c])&&(u=i?F.call(o,p):f[c])>-1&&(o[u]=!(a[u]=p))}}else y=Ct(y===a?y.splice(h,y.length):y),i?i(null,a,y,l):M.apply(a,y)})}function kt(e){var t,n,r,i=e.length,a=o.relative[e[0].type],s=a||o.relative[" "],l=a?1:0,c=wt(function(e){return e===t},s,!0),p=wt(function(e){return F.call(t,e)>-1},s,!0),f=[function(e,n,r){return!a&&(r||n!==u)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;i>l;l++)if(n=o.relative[e[l].type])f=[wt(Tt(f),n)];else{if(n=o.filter[e[l].type].apply(null,e[l].matches),n[b]){for(r=++l;i>r;r++)if(o.relative[e[r].type])break;return Nt(l>1&&Tt(f),l>1&&xt(e.slice(0,l-1).concat({value:" "===e[l-2].type?"*":""})).replace(z,"$1"),n,r>l&&kt(e.slice(l,r)),i>r&&kt(e=e.slice(r)),i>r&&xt(e))}f.push(n)}return Tt(f)}function Et(e,t){var n=0,r=t.length>0,a=e.length>0,s=function(s,l,c,p,d){var h,g,m,y=[],v=0,b="0",x=s&&[],w=null!=d,C=u,N=s||a&&o.find.TAG("*",d&&l.parentNode||l),k=T+=null==C?1:Math.random()||.1;for(w&&(u=l!==f&&l,i=n);null!=(h=N[b]);b++){if(a&&h){g=0;while(m=e[g++])if(m(h,l,c)){p.push(h);break}w&&(T=k,i=++n)}r&&((h=!m&&h)&&v--,s&&x.push(h))}if(v+=b,r&&b!==v){g=0;while(m=t[g++])m(x,y,l,c);if(s){if(v>0)while(b--)x[b]||y[b]||(y[b]=q.call(p));y=Ct(y)}M.apply(p,y),w&&!s&&y.length>0&&v+t.length>1&&at.uniqueSort(p)}return w&&(T=k,u=C),x};return r?ut(s):s}l=at.compile=function(e,t){var n,r=[],i=[],o=E[e+" "];if(!o){t||(t=bt(e)),n=t.length;while(n--)o=kt(t[n]),o[b]?r.push(o):i.push(o);o=E(e,Et(i,r))}return o};function St(e,t,n){var r=0,i=t.length;for(;i>r;r++)at(e,t[r],n);return n}function At(e,t,n,i){var a,s,u,c,p,f=bt(e);if(!i&&1===f.length){if(s=f[0]=f[0].slice(0),s.length>2&&"ID"===(u=s[0]).type&&r.getById&&9===t.nodeType&&h&&o.relative[s[1].type]){if(t=(o.find.ID(u.matches[0].replace(rt,it),t)||[])[0],!t)return n;e=e.slice(s.shift().value.length)}a=Q.needsContext.test(e)?0:s.length;while(a--){if(u=s[a],o.relative[c=u.type])break;if((p=o.find[c])&&(i=p(u.matches[0].replace(rt,it),V.test(s[0].type)&&t.parentNode||t))){if(s.splice(a,1),e=i.length&&xt(s),!e)return M.apply(n,i),n;break}}}return l(e,f)(i,t,!h,n,V.test(e)),n}o.pseudos.nth=o.pseudos.eq;function jt(){}jt.prototype=o.filters=o.pseudos,o.setFilters=new jt,r.sortStable=b.split("").sort(A).join("")===b,p(),[0,0].sort(A),r.detectDuplicates=S,x.find=at,x.expr=at.selectors,x.expr[":"]=x.expr.pseudos,x.unique=at.uniqueSort,x.text=at.getText,x.isXMLDoc=at.isXML,x.contains=at.contains}(e);var O={};function F(e){var t=O[e]={};return x.each(e.match(T)||[],function(e,n){t[n]=!0}),t}x.Callbacks=function(e){e="string"==typeof e?O[e]||F(e):x.extend({},e);var n,r,i,o,a,s,l=[],u=!e.once&&[],c=function(t){for(r=e.memory&&t,i=!0,a=s||0,s=0,o=l.length,n=!0;l&&o>a;a++)if(l[a].apply(t[0],t[1])===!1&&e.stopOnFalse){r=!1;break}n=!1,l&&(u?u.length&&c(u.shift()):r?l=[]:p.disable())},p={add:function(){if(l){var t=l.length;(function i(t){x.each(t,function(t,n){var r=x.type(n);"function"===r?e.unique&&p.has(n)||l.push(n):n&&n.length&&"string"!==r&&i(n)})})(arguments),n?o=l.length:r&&(s=t,c(r))}return this},remove:function(){return l&&x.each(arguments,function(e,t){var r;while((r=x.inArray(t,l,r))>-1)l.splice(r,1),n&&(o>=r&&o--,a>=r&&a--)}),this},has:function(e){return e?x.inArray(e,l)>-1:!(!l||!l.length)},empty:function(){return l=[],o=0,this},disable:function(){return l=u=r=t,this},disabled:function(){return!l},lock:function(){return u=t,r||p.disable(),this},locked:function(){return!u},fireWith:function(e,t){return t=t||[],t=[e,t.slice?t.slice():t],!l||i&&!u||(n?u.push(t):c(t)),this},fire:function(){return p.fireWith(this,arguments),this},fired:function(){return!!i}};return p},x.extend({Deferred:function(e){var t=[["resolve","done",x.Callbacks("once memory"),"resolved"],["reject","fail",x.Callbacks("once memory"),"rejected"],["notify","progress",x.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return x.Deferred(function(n){x.each(t,function(t,o){var a=o[0],s=x.isFunction(e[t])&&e[t];i[o[1]](function(){var e=s&&s.apply(this,arguments);e&&x.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a+"With"](this===r?n.promise():this,s?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?x.extend(e,r):r}},i={};return r.pipe=r.then,x.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=g.call(arguments),r=n.length,i=1!==r||e&&x.isFunction(e.promise)?r:0,o=1===i?e:x.Deferred(),a=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?g.call(arguments):r,n===s?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},s,l,u;if(r>1)for(s=Array(r),l=Array(r),u=Array(r);r>t;t++)n[t]&&x.isFunction(n[t].promise)?n[t].promise().done(a(t,u,n)).fail(o.reject).progress(a(t,l,s)):--i;return i||o.resolveWith(u,n),o.promise()}}),x.support=function(t){var n,r,o,s,l,u,c,p,f,d=a.createElement("div");if(d.setAttribute("className","t"),d.innerHTML=" a ",n=d.getElementsByTagName("*")||[],r=d.getElementsByTagName("a")[0],!r||!r.style||!n.length)return t;s=a.createElement("select"),u=s.appendChild(a.createElement("option")),o=d.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t.getSetAttribute="t"!==d.className,t.leadingWhitespace=3===d.firstChild.nodeType,t.tbody=!d.getElementsByTagName("tbody").length,t.htmlSerialize=!!d.getElementsByTagName("link").length,t.style=/top/.test(r.getAttribute("style")),t.hrefNormalized="/a"===r.getAttribute("href"),t.opacity=/^0.5/.test(r.style.opacity),t.cssFloat=!!r.style.cssFloat,t.checkOn=!!o.value,t.optSelected=u.selected,t.enctype=!!a.createElement("form").enctype,t.html5Clone="<:nav>"!==a.createElement("nav").cloneNode(!0).outerHTML,t.inlineBlockNeedsLayout=!1,t.shrinkWrapBlocks=!1,t.pixelPosition=!1,t.deleteExpando=!0,t.noCloneEvent=!0,t.reliableMarginRight=!0,t.boxSizingReliable=!0,o.checked=!0,t.noCloneChecked=o.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!u.disabled;try{delete d.test}catch(h){t.deleteExpando=!1}o=a.createElement("input"),o.setAttribute("value",""),t.input=""===o.getAttribute("value"),o.value="t",o.setAttribute("type","radio"),t.radioValue="t"===o.value,o.setAttribute("checked","t"),o.setAttribute("name","t"),l=a.createDocumentFragment(),l.appendChild(o),t.appendChecked=o.checked,t.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,d.attachEvent&&(d.attachEvent("onclick",function(){t.noCloneEvent=!1}),d.cloneNode(!0).click());for(f in{submit:!0,change:!0,focusin:!0})d.setAttribute(c="on"+f,"t"),t[f+"Bubbles"]=c in e||d.attributes[c].expando===!1;d.style.backgroundClip="content-box",d.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===d.style.backgroundClip;for(f in x(t))break;return t.ownLast="0"!==f,x(function(){var n,r,o,s="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",l=a.getElementsByTagName("body")[0];l&&(n=a.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",l.appendChild(n).appendChild(d),d.innerHTML="",o=d.getElementsByTagName("td"),o[0].style.cssText="padding:0;margin:0;border:0;display:none",p=0===o[0].offsetHeight,o[0].style.display="",o[1].style.display="none",t.reliableHiddenOffsets=p&&0===o[0].offsetHeight,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",x.swap(l,null!=l.style.zoom?{zoom:1}:{},function(){t.boxSizing=4===d.offsetWidth}),e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(d,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(d,null)||{width:"4px"}).width,r=d.appendChild(a.createElement("div")),r.style.cssText=d.style.cssText=s,r.style.marginRight=r.style.width="0",d.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),typeof d.style.zoom!==i&&(d.innerHTML="",d.style.cssText=s+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=3===d.offsetWidth,d.style.display="block",d.innerHTML="
",d.firstChild.style.width="5px",t.shrinkWrapBlocks=3!==d.offsetWidth,t.inlineBlockNeedsLayout&&(l.style.zoom=1)),l.removeChild(n),n=d=o=r=null)
+}),n=s=l=u=r=o=null,t}({});var B=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,P=/([A-Z])/g;function R(e,n,r,i){if(x.acceptData(e)){var o,a,s=x.expando,l=e.nodeType,u=l?x.cache:e,c=l?e[s]:e[s]&&s;if(c&&u[c]&&(i||u[c].data)||r!==t||"string"!=typeof n)return c||(c=l?e[s]=p.pop()||x.guid++:s),u[c]||(u[c]=l?{}:{toJSON:x.noop}),("object"==typeof n||"function"==typeof n)&&(i?u[c]=x.extend(u[c],n):u[c].data=x.extend(u[c].data,n)),a=u[c],i||(a.data||(a.data={}),a=a.data),r!==t&&(a[x.camelCase(n)]=r),"string"==typeof n?(o=a[n],null==o&&(o=a[x.camelCase(n)])):o=a,o}}function W(e,t,n){if(x.acceptData(e)){var r,i,o=e.nodeType,a=o?x.cache:e,s=o?e[x.expando]:x.expando;if(a[s]){if(t&&(r=n?a[s]:a[s].data)){x.isArray(t)?t=t.concat(x.map(t,x.camelCase)):t in r?t=[t]:(t=x.camelCase(t),t=t in r?[t]:t.split(" ")),i=t.length;while(i--)delete r[t[i]];if(n?!I(r):!x.isEmptyObject(r))return}(n||(delete a[s].data,I(a[s])))&&(o?x.cleanData([e],!0):x.support.deleteExpando||a!=a.window?delete a[s]:a[s]=null)}}}x.extend({cache:{},noData:{applet:!0,embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(e){return e=e.nodeType?x.cache[e[x.expando]]:e[x.expando],!!e&&!I(e)},data:function(e,t,n){return R(e,t,n)},removeData:function(e,t){return W(e,t)},_data:function(e,t,n){return R(e,t,n,!0)},_removeData:function(e,t){return W(e,t,!0)},acceptData:function(e){if(e.nodeType&&1!==e.nodeType&&9!==e.nodeType)return!1;var t=e.nodeName&&x.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),x.fn.extend({data:function(e,n){var r,i,o=null,a=0,s=this[0];if(e===t){if(this.length&&(o=x.data(s),1===s.nodeType&&!x._data(s,"parsedAttrs"))){for(r=s.attributes;r.length>a;a++)i=r[a].name,0===i.indexOf("data-")&&(i=x.camelCase(i.slice(5)),$(s,i,o[i]));x._data(s,"parsedAttrs",!0)}return o}return"object"==typeof e?this.each(function(){x.data(this,e)}):arguments.length>1?this.each(function(){x.data(this,e,n)}):s?$(s,e,x.data(s,e)):null},removeData:function(e){return this.each(function(){x.removeData(this,e)})}});function $(e,n,r){if(r===t&&1===e.nodeType){var i="data-"+n.replace(P,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"==typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null:+r+""===r?+r:B.test(r)?x.parseJSON(r):r}catch(o){}x.data(e,n,r)}else r=t}return r}function I(e){var t;for(t in e)if(("data"!==t||!x.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}x.extend({queue:function(e,n,r){var i;return e?(n=(n||"fx")+"queue",i=x._data(e,n),r&&(!i||x.isArray(r)?i=x._data(e,n,x.makeArray(r)):i.push(r)),i||[]):t},dequeue:function(e,t){t=t||"fx";var n=x.queue(e,t),r=n.length,i=n.shift(),o=x._queueHooks(e,t),a=function(){x.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return x._data(e,n)||x._data(e,n,{empty:x.Callbacks("once memory").add(function(){x._removeData(e,t+"queue"),x._removeData(e,n)})})}}),x.fn.extend({queue:function(e,n){var r=2;return"string"!=typeof e&&(n=e,e="fx",r--),r>arguments.length?x.queue(this[0],e):n===t?this:this.each(function(){var t=x.queue(this,e,n);x._queueHooks(this,e),"fx"===e&&"inprogress"!==t[0]&&x.dequeue(this,e)})},dequeue:function(e){return this.each(function(){x.dequeue(this,e)})},delay:function(e,t){return e=x.fx?x.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,o=x.Deferred(),a=this,s=this.length,l=function(){--i||o.resolveWith(a,[a])};"string"!=typeof e&&(n=e,e=t),e=e||"fx";while(s--)r=x._data(a[s],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(l));return l(),o.promise(n)}});var z,X,U=/[\t\r\n\f]/g,V=/\r/g,Y=/^(?:input|select|textarea|button|object)$/i,J=/^(?:a|area)$/i,G=/^(?:checked|selected)$/i,Q=x.support.getSetAttribute,K=x.support.input;x.fn.extend({attr:function(e,t){return x.access(this,x.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){x.removeAttr(this,e)})},prop:function(e,t){return x.access(this,x.prop,e,t,arguments.length>1)},removeProp:function(e){return e=x.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,o,a=0,s=this.length,l="string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).addClass(e.call(this,t,this.className))});if(l)for(t=(e||"").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(U," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=x.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,a=0,s=this.length,l=0===arguments.length||"string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).removeClass(e.call(this,t,this.className))});if(l)for(t=(e||"").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(U," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?x.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e,r="boolean"==typeof t;return x.isFunction(e)?this.each(function(n){x(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var o,a=0,s=x(this),l=t,u=e.match(T)||[];while(o=u[a++])l=r?l:!s.hasClass(o),s[l?"addClass":"removeClass"](o)}else(n===i||"boolean"===n)&&(this.className&&x._data(this,"__className__",this.className),this.className=this.className||e===!1?"":x._data(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(U," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,o=this[0];{if(arguments.length)return i=x.isFunction(e),this.each(function(n){var o;1===this.nodeType&&(o=i?e.call(this,n,x(this).val()):e,null==o?o="":"number"==typeof o?o+="":x.isArray(o)&&(o=x.map(o,function(e){return null==e?"":e+""})),r=x.valHooks[this.type]||x.valHooks[this.nodeName.toLowerCase()],r&&"set"in r&&r.set(this,o,"value")!==t||(this.value=o))});if(o)return r=x.valHooks[o.type]||x.valHooks[o.nodeName.toLowerCase()],r&&"get"in r&&(n=r.get(o,"value"))!==t?n:(n=o.value,"string"==typeof n?n.replace(V,""):null==n?"":n)}}}),x.extend({valHooks:{option:{get:function(e){var t=x.find.attr(e,"value");return null!=t?t:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,l=0>i?s:o?i:0;for(;s>l;l++)if(n=r[l],!(!n.selected&&l!==i||(x.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&x.nodeName(n.parentNode,"optgroup"))){if(t=x(n).val(),o)return t;a.push(t)}return a},set:function(e,t){var n,r,i=e.options,o=x.makeArray(t),a=i.length;while(a--)r=i[a],(r.selected=x.inArray(x(r).val(),o)>=0)&&(n=!0);return n||(e.selectedIndex=-1),o}}},attr:function(e,n,r){var o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return typeof e.getAttribute===i?x.prop(e,n,r):(1===s&&x.isXMLDoc(e)||(n=n.toLowerCase(),o=x.attrHooks[n]||(x.expr.match.bool.test(n)?X:z)),r===t?o&&"get"in o&&null!==(a=o.get(e,n))?a:(a=x.find.attr(e,n),null==a?t:a):null!==r?o&&"set"in o&&(a=o.set(e,r,n))!==t?a:(e.setAttribute(n,r+""),r):(x.removeAttr(e,n),t))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(T);if(o&&1===e.nodeType)while(n=o[i++])r=x.propFix[n]||n,x.expr.match.bool.test(n)?K&&Q||!G.test(n)?e[r]=!1:e[x.camelCase("default-"+n)]=e[r]=!1:x.attr(e,n,""),e.removeAttribute(Q?n:r)},attrHooks:{type:{set:function(e,t){if(!x.support.radioValue&&"radio"===t&&x.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{"for":"htmlFor","class":"className"},prop:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return a=1!==s||!x.isXMLDoc(e),a&&(n=x.propFix[n]||n,o=x.propHooks[n]),r!==t?o&&"set"in o&&(i=o.set(e,r,n))!==t?i:e[n]=r:o&&"get"in o&&null!==(i=o.get(e,n))?i:e[n]},propHooks:{tabIndex:{get:function(e){var t=x.find.attr(e,"tabindex");return t?parseInt(t,10):Y.test(e.nodeName)||J.test(e.nodeName)&&e.href?0:-1}}}}),X={set:function(e,t,n){return t===!1?x.removeAttr(e,n):K&&Q||!G.test(n)?e.setAttribute(!Q&&x.propFix[n]||n,n):e[x.camelCase("default-"+n)]=e[n]=!0,n}},x.each(x.expr.match.bool.source.match(/\w+/g),function(e,n){var r=x.expr.attrHandle[n]||x.find.attr;x.expr.attrHandle[n]=K&&Q||!G.test(n)?function(e,n,i){var o=x.expr.attrHandle[n],a=i?t:(x.expr.attrHandle[n]=t)!=r(e,n,i)?n.toLowerCase():null;return x.expr.attrHandle[n]=o,a}:function(e,n,r){return r?t:e[x.camelCase("default-"+n)]?n.toLowerCase():null}}),K&&Q||(x.attrHooks.value={set:function(e,n,r){return x.nodeName(e,"input")?(e.defaultValue=n,t):z&&z.set(e,n,r)}}),Q||(z={set:function(e,n,r){var i=e.getAttributeNode(r);return i||e.setAttributeNode(i=e.ownerDocument.createAttribute(r)),i.value=n+="","value"===r||n===e.getAttribute(r)?n:t}},x.expr.attrHandle.id=x.expr.attrHandle.name=x.expr.attrHandle.coords=function(e,n,r){var i;return r?t:(i=e.getAttributeNode(n))&&""!==i.value?i.value:null},x.valHooks.button={get:function(e,n){var r=e.getAttributeNode(n);return r&&r.specified?r.value:t},set:z.set},x.attrHooks.contenteditable={set:function(e,t,n){z.set(e,""===t?!1:t,n)}},x.each(["width","height"],function(e,n){x.attrHooks[n]={set:function(e,r){return""===r?(e.setAttribute(n,"auto"),r):t}}})),x.support.hrefNormalized||x.each(["href","src"],function(e,t){x.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}}),x.support.style||(x.attrHooks.style={get:function(e){return e.style.cssText||t},set:function(e,t){return e.style.cssText=t+""}}),x.support.optSelected||(x.propHooks.selected={get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}}),x.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){x.propFix[this.toLowerCase()]=this}),x.support.enctype||(x.propFix.enctype="encoding"),x.each(["radio","checkbox"],function(){x.valHooks[this]={set:function(e,n){return x.isArray(n)?e.checked=x.inArray(x(e).val(),n)>=0:t}},x.support.checkOn||(x.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var Z=/^(?:input|select|textarea)$/i,et=/^key/,tt=/^(?:mouse|contextmenu)|click/,nt=/^(?:focusinfocus|focusoutblur)$/,rt=/^([^.]*)(?:\.(.+)|)$/;function it(){return!0}function ot(){return!1}function at(){try{return a.activeElement}catch(e){}}x.event={global:{},add:function(e,n,r,o,a){var s,l,u,c,p,f,d,h,g,m,y,v=x._data(e);if(v){r.handler&&(c=r,r=c.handler,a=c.selector),r.guid||(r.guid=x.guid++),(l=v.events)||(l=v.events={}),(f=v.handle)||(f=v.handle=function(e){return typeof x===i||e&&x.event.triggered===e.type?t:x.event.dispatch.apply(f.elem,arguments)},f.elem=e),n=(n||"").match(T)||[""],u=n.length;while(u--)s=rt.exec(n[u])||[],g=y=s[1],m=(s[2]||"").split(".").sort(),g&&(p=x.event.special[g]||{},g=(a?p.delegateType:p.bindType)||g,p=x.event.special[g]||{},d=x.extend({type:g,origType:y,data:o,handler:r,guid:r.guid,selector:a,needsContext:a&&x.expr.match.needsContext.test(a),namespace:m.join(".")},c),(h=l[g])||(h=l[g]=[],h.delegateCount=0,p.setup&&p.setup.call(e,o,m,f)!==!1||(e.addEventListener?e.addEventListener(g,f,!1):e.attachEvent&&e.attachEvent("on"+g,f))),p.add&&(p.add.call(e,d),d.handler.guid||(d.handler.guid=r.guid)),a?h.splice(h.delegateCount++,0,d):h.push(d),x.event.global[g]=!0);e=null}},remove:function(e,t,n,r,i){var o,a,s,l,u,c,p,f,d,h,g,m=x.hasData(e)&&x._data(e);if(m&&(c=m.events)){t=(t||"").match(T)||[""],u=t.length;while(u--)if(s=rt.exec(t[u])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){p=x.event.special[d]||{},d=(r?p.delegateType:p.bindType)||d,f=c[d]||[],s=s[2]&&RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),l=o=f.length;while(o--)a=f[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&("**"!==r||!a.selector)||(f.splice(o,1),a.selector&&f.delegateCount--,p.remove&&p.remove.call(e,a));l&&!f.length&&(p.teardown&&p.teardown.call(e,h,m.handle)!==!1||x.removeEvent(e,d,m.handle),delete c[d])}else for(d in c)x.event.remove(e,d+t[u],n,r,!0);x.isEmptyObject(c)&&(delete m.handle,x._removeData(e,"events"))}},trigger:function(n,r,i,o){var s,l,u,c,p,f,d,h=[i||a],g=v.call(n,"type")?n.type:n,m=v.call(n,"namespace")?n.namespace.split("."):[];if(u=f=i=i||a,3!==i.nodeType&&8!==i.nodeType&&!nt.test(g+x.event.triggered)&&(g.indexOf(".")>=0&&(m=g.split("."),g=m.shift(),m.sort()),l=0>g.indexOf(":")&&"on"+g,n=n[x.expando]?n:new x.Event(g,"object"==typeof n&&n),n.isTrigger=o?2:3,n.namespace=m.join("."),n.namespace_re=n.namespace?RegExp("(^|\\.)"+m.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,n.result=t,n.target||(n.target=i),r=null==r?[n]:x.makeArray(r,[n]),p=x.event.special[g]||{},o||!p.trigger||p.trigger.apply(i,r)!==!1)){if(!o&&!p.noBubble&&!x.isWindow(i)){for(c=p.delegateType||g,nt.test(c+g)||(u=u.parentNode);u;u=u.parentNode)h.push(u),f=u;f===(i.ownerDocument||a)&&h.push(f.defaultView||f.parentWindow||e)}d=0;while((u=h[d++])&&!n.isPropagationStopped())n.type=d>1?c:p.bindType||g,s=(x._data(u,"events")||{})[n.type]&&x._data(u,"handle"),s&&s.apply(u,r),s=l&&u[l],s&&x.acceptData(u)&&s.apply&&s.apply(u,r)===!1&&n.preventDefault();if(n.type=g,!o&&!n.isDefaultPrevented()&&(!p._default||p._default.apply(h.pop(),r)===!1)&&x.acceptData(i)&&l&&i[g]&&!x.isWindow(i)){f=i[l],f&&(i[l]=null),x.event.triggered=g;try{i[g]()}catch(y){}x.event.triggered=t,f&&(i[l]=f)}return n.result}},dispatch:function(e){e=x.event.fix(e);var n,r,i,o,a,s=[],l=g.call(arguments),u=(x._data(this,"events")||{})[e.type]||[],c=x.event.special[e.type]||{};if(l[0]=e,e.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,e)!==!1){s=x.event.handlers.call(this,e,u),n=0;while((o=s[n++])&&!e.isPropagationStopped()){e.currentTarget=o.elem,a=0;while((i=o.handlers[a++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(i.namespace))&&(e.handleObj=i,e.data=i.data,r=((x.event.special[i.origType]||{}).handle||i.handler).apply(o.elem,l),r!==t&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,e),e.result}},handlers:function(e,n){var r,i,o,a,s=[],l=n.delegateCount,u=e.target;if(l&&u.nodeType&&(!e.button||"click"!==e.type))for(;u!=this;u=u.parentNode||this)if(1===u.nodeType&&(u.disabled!==!0||"click"!==e.type)){for(o=[],a=0;l>a;a++)i=n[a],r=i.selector+" ",o[r]===t&&(o[r]=i.needsContext?x(r,this).index(u)>=0:x.find(r,this,null,[u]).length),o[r]&&o.push(i);o.length&&s.push({elem:u,handlers:o})}return n.length>l&&s.push({elem:this,handlers:n.slice(l)}),s},fix:function(e){if(e[x.expando])return e;var t,n,r,i=e.type,o=e,s=this.fixHooks[i];s||(this.fixHooks[i]=s=tt.test(i)?this.mouseHooks:et.test(i)?this.keyHooks:{}),r=s.props?this.props.concat(s.props):this.props,e=new x.Event(o),t=r.length;while(t--)n=r[t],e[n]=o[n];return e.target||(e.target=o.srcElement||a),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,o):e},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,i,o,s=n.button,l=n.fromElement;return null==e.pageX&&null!=n.clientX&&(i=e.target.ownerDocument||a,o=i.documentElement,r=i.body,e.pageX=n.clientX+(o&&o.scrollLeft||r&&r.scrollLeft||0)-(o&&o.clientLeft||r&&r.clientLeft||0),e.pageY=n.clientY+(o&&o.scrollTop||r&&r.scrollTop||0)-(o&&o.clientTop||r&&r.clientTop||0)),!e.relatedTarget&&l&&(e.relatedTarget=l===e.target?n.toElement:l),e.which||s===t||(e.which=1&s?1:2&s?3:4&s?2:0),e}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==at()&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:"focusin"},blur:{trigger:function(){return this===at()&&this.blur?(this.blur(),!1):t},delegateType:"focusout"},click:{trigger:function(){return x.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):t},_default:function(e){return x.nodeName(e.target,"a")}},beforeunload:{postDispatch:function(e){e.result!==t&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=x.extend(new x.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?x.event.trigger(i,null,t):x.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},x.removeEvent=a.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]===i&&(e[r]=null),e.detachEvent(r,n))},x.Event=function(e,n){return this instanceof x.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?it:ot):this.type=e,n&&x.extend(this,n),this.timeStamp=e&&e.timeStamp||x.now(),this[x.expando]=!0,t):new x.Event(e,n)},x.Event.prototype={isDefaultPrevented:ot,isPropagationStopped:ot,isImmediatePropagationStopped:ot,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=it,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=it,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=it,this.stopPropagation()}},x.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){x.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return(!i||i!==r&&!x.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),x.support.submitBubbles||(x.event.special.submit={setup:function(){return x.nodeName(this,"form")?!1:(x.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=x.nodeName(n,"input")||x.nodeName(n,"button")?n.form:t;r&&!x._data(r,"submitBubbles")&&(x.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),x._data(r,"submitBubbles",!0))}),t)},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&x.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){return x.nodeName(this,"form")?!1:(x.event.remove(this,"._submit"),t)}}),x.support.changeBubbles||(x.event.special.change={setup:function(){return Z.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(x.event.add(this,"propertychange._change",function(e){"checked"===e.originalEvent.propertyName&&(this._just_changed=!0)}),x.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),x.event.simulate("change",this,e,!0)})),!1):(x.event.add(this,"beforeactivate._change",function(e){var t=e.target;Z.test(t.nodeName)&&!x._data(t,"changeBubbles")&&(x.event.add(t,"change._change",function(e){!this.parentNode||e.isSimulated||e.isTrigger||x.event.simulate("change",this.parentNode,e,!0)}),x._data(t,"changeBubbles",!0))}),t)},handle:function(e){var n=e.target;return this!==n||e.isSimulated||e.isTrigger||"radio"!==n.type&&"checkbox"!==n.type?e.handleObj.handler.apply(this,arguments):t},teardown:function(){return x.event.remove(this,"._change"),!Z.test(this.nodeName)}}),x.support.focusinBubbles||x.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){x.event.simulate(t,e.target,x.event.fix(e),!0)};x.event.special[t]={setup:function(){0===n++&&a.addEventListener(e,r,!0)},teardown:function(){0===--n&&a.removeEventListener(e,r,!0)}}}),x.fn.extend({on:function(e,n,r,i,o){var a,s;if("object"==typeof e){"string"!=typeof n&&(r=r||n,n=t);for(a in e)this.on(a,n,r,e[a],o);return this}if(null==r&&null==i?(i=n,r=n=t):null==i&&("string"==typeof n?(i=r,r=t):(i=r,r=n,n=t)),i===!1)i=ot;else if(!i)return this;return 1===o&&(s=i,i=function(e){return x().off(e),s.apply(this,arguments)},i.guid=s.guid||(s.guid=x.guid++)),this.each(function(){x.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,o;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,x(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if("object"==typeof e){for(o in e)this.off(o,n,e[o]);return this}return(n===!1||"function"==typeof n)&&(r=n,n=t),r===!1&&(r=ot),this.each(function(){x.event.remove(this,e,r,n)})},trigger:function(e,t){return this.each(function(){x.event.trigger(e,t,this)})},triggerHandler:function(e,n){var r=this[0];return r?x.event.trigger(e,n,r,!0):t}});var st=/^.[^:#\[\.,]*$/,lt=/^(?:parents|prev(?:Until|All))/,ut=x.expr.match.needsContext,ct={children:!0,contents:!0,next:!0,prev:!0};x.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if("string"!=typeof e)return this.pushStack(x(e).filter(function(){for(t=0;i>t;t++)if(x.contains(r[t],this))return!0}));for(t=0;i>t;t++)x.find(e,r[t],n);return n=this.pushStack(i>1?x.unique(n):n),n.selector=this.selector?this.selector+" "+e:e,n},has:function(e){var t,n=x(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++)if(x.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e||[],!0))},filter:function(e){return this.pushStack(ft(this,e||[],!1))},is:function(e){return!!ft(this,"string"==typeof e&&ut.test(e)?x(e):e||[],!1).length},closest:function(e,t){var n,r=0,i=this.length,o=[],a=ut.test(e)||"string"!=typeof e?x(e,t||this.context):0;for(;i>r;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(11>n.nodeType&&(a?a.index(n)>-1:1===n.nodeType&&x.find.matchesSelector(n,e))){n=o.push(n);break}return this.pushStack(o.length>1?x.unique(o):o)},index:function(e){return e?"string"==typeof e?x.inArray(this[0],x(e)):x.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?x(e,t):x.makeArray(e&&e.nodeType?[e]:e),r=x.merge(this.get(),n);return this.pushStack(x.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function pt(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}x.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return x.dir(e,"parentNode")},parentsUntil:function(e,t,n){return x.dir(e,"parentNode",n)},next:function(e){return pt(e,"nextSibling")},prev:function(e){return pt(e,"previousSibling")},nextAll:function(e){return x.dir(e,"nextSibling")},prevAll:function(e){return x.dir(e,"previousSibling")},nextUntil:function(e,t,n){return x.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return x.dir(e,"previousSibling",n)},siblings:function(e){return x.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return x.sibling(e.firstChild)},contents:function(e){return x.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:x.merge([],e.childNodes)}},function(e,t){x.fn[e]=function(n,r){var i=x.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=x.filter(r,i)),this.length>1&&(ct[e]||(i=x.unique(i)),lt.test(e)&&(i=i.reverse())),this.pushStack(i)}}),x.extend({filter:function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?x.find.matchesSelector(r,e)?[r]:[]:x.find.matches(e,x.grep(t,function(e){return 1===e.nodeType}))},dir:function(e,n,r){var i=[],o=e[n];while(o&&9!==o.nodeType&&(r===t||1!==o.nodeType||!x(o).is(r)))1===o.nodeType&&i.push(o),o=o[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function ft(e,t,n){if(x.isFunction(t))return x.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return x.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(st.test(t))return x.filter(t,e,n);t=x.filter(t,e)}return x.grep(e,function(e){return x.inArray(e,t)>=0!==n})}function dt(e){var t=ht.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}var ht="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",gt=/ jQuery\d+="(?:null|\d+)"/g,mt=RegExp("<(?:"+ht+")[\\s/>]","i"),yt=/^\s+/,vt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bt=/<([\w:]+)/,xt=/\s*$/g,At={option:[1,""," "],legend:[1,""," "],area:[1,""," "],param:[1,""," "],thead:[1,""],tr:[2,""],col:[2,""],td:[3,""],_default:x.support.htmlSerialize?[0,"",""]:[1,"X","
"]},jt=dt(a),Dt=jt.appendChild(a.createElement("div"));At.optgroup=At.option,At.tbody=At.tfoot=At.colgroup=At.caption=At.thead,At.th=At.td,x.fn.extend({text:function(e){return x.access(this,function(e){return e===t?x.text(this):this.empty().append((this[0]&&this[0].ownerDocument||a).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.appendChild(e)}})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=e?x.filter(e,this):this,i=0;for(;null!=(n=r[i]);i++)t||1!==n.nodeType||x.cleanData(Ft(n)),n.parentNode&&(t&&x.contains(n.ownerDocument,n)&&_t(Ft(n,"script")),n.parentNode.removeChild(n));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++){1===e.nodeType&&x.cleanData(Ft(e,!1));while(e.firstChild)e.removeChild(e.firstChild);e.options&&x.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return x.clone(this,e,t)})},html:function(e){return x.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return 1===n.nodeType?n.innerHTML.replace(gt,""):t;if(!("string"!=typeof e||Tt.test(e)||!x.support.htmlSerialize&&mt.test(e)||!x.support.leadingWhitespace&&yt.test(e)||At[(bt.exec(e)||["",""])[1].toLowerCase()])){e=e.replace(vt,"<$1>$2>");try{for(;i>r;r++)n=this[r]||{},1===n.nodeType&&(x.cleanData(Ft(n,!1)),n.innerHTML=e);n=0}catch(o){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=x.map(this,function(e){return[e.nextSibling,e.parentNode]}),t=0;return this.domManip(arguments,function(n){var r=e[t++],i=e[t++];i&&(r&&r.parentNode!==i&&(r=this.nextSibling),x(this).remove(),i.insertBefore(n,r))},!0),t?this:this.remove()},detach:function(e){return this.remove(e,!0)},domManip:function(e,t,n){e=d.apply([],e);var r,i,o,a,s,l,u=0,c=this.length,p=this,f=c-1,h=e[0],g=x.isFunction(h);if(g||!(1>=c||"string"!=typeof h||x.support.checkClone)&&Nt.test(h))return this.each(function(r){var i=p.eq(r);g&&(e[0]=h.call(this,r,i.html())),i.domManip(e,t,n)});if(c&&(l=x.buildFragment(e,this[0].ownerDocument,!1,!n&&this),r=l.firstChild,1===l.childNodes.length&&(l=r),r)){for(a=x.map(Ft(l,"script"),Ht),o=a.length;c>u;u++)i=l,u!==f&&(i=x.clone(i,!0,!0),o&&x.merge(a,Ft(i,"script"))),t.call(this[u],i,u);if(o)for(s=a[a.length-1].ownerDocument,x.map(a,qt),u=0;o>u;u++)i=a[u],kt.test(i.type||"")&&!x._data(i,"globalEval")&&x.contains(s,i)&&(i.src?x._evalUrl(i.src):x.globalEval((i.text||i.textContent||i.innerHTML||"").replace(St,"")));l=r=null}return this}});function Lt(e,t){return x.nodeName(e,"table")&&x.nodeName(1===t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function Ht(e){return e.type=(null!==x.find.attr(e,"type"))+"/"+e.type,e}function qt(e){var t=Et.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function _t(e,t){var n,r=0;for(;null!=(n=e[r]);r++)x._data(n,"globalEval",!t||x._data(t[r],"globalEval"))}function Mt(e,t){if(1===t.nodeType&&x.hasData(e)){var n,r,i,o=x._data(e),a=x._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)x.event.add(t,n,s[n][r])}a.data&&(a.data=x.extend({},a.data))}}function Ot(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!x.support.noCloneEvent&&t[x.expando]){i=x._data(t);for(r in i.events)x.removeEvent(t,r,i.handle);t.removeAttribute(x.expando)}"script"===n&&t.text!==e.text?(Ht(t).text=e.text,qt(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),x.support.html5Clone&&e.innerHTML&&!x.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Ct.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}x.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){x.fn[e]=function(e){var n,r=0,i=[],o=x(e),a=o.length-1;for(;a>=r;r++)n=r===a?this:this.clone(!0),x(o[r])[t](n),h.apply(i,n.get());return this.pushStack(i)}});function Ft(e,n){var r,o,a=0,s=typeof e.getElementsByTagName!==i?e.getElementsByTagName(n||"*"):typeof e.querySelectorAll!==i?e.querySelectorAll(n||"*"):t;if(!s)for(s=[],r=e.childNodes||e;null!=(o=r[a]);a++)!n||x.nodeName(o,n)?s.push(o):x.merge(s,Ft(o,n));return n===t||n&&x.nodeName(e,n)?x.merge([e],s):s}function Bt(e){Ct.test(e.type)&&(e.defaultChecked=e.checked)}x.extend({clone:function(e,t,n){var r,i,o,a,s,l=x.contains(e.ownerDocument,e);if(x.support.html5Clone||x.isXMLDoc(e)||!mt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(Dt.innerHTML=e.outerHTML,Dt.removeChild(o=Dt.firstChild)),!(x.support.noCloneEvent&&x.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||x.isXMLDoc(e)))for(r=Ft(o),s=Ft(e),a=0;null!=(i=s[a]);++a)r[a]&&Ot(i,r[a]);if(t)if(n)for(s=s||Ft(e),r=r||Ft(o),a=0;null!=(i=s[a]);a++)Mt(i,r[a]);else Mt(e,o);return r=Ft(o,"script"),r.length>0&&_t(r,!l&&Ft(e,"script")),r=s=i=null,o},buildFragment:function(e,t,n,r){var i,o,a,s,l,u,c,p=e.length,f=dt(t),d=[],h=0;for(;p>h;h++)if(o=e[h],o||0===o)if("object"===x.type(o))x.merge(d,o.nodeType?[o]:o);else if(wt.test(o)){s=s||f.appendChild(t.createElement("div")),l=(bt.exec(o)||["",""])[1].toLowerCase(),c=At[l]||At._default,s.innerHTML=c[1]+o.replace(vt,"<$1>$2>")+c[2],i=c[0];while(i--)s=s.lastChild;if(!x.support.leadingWhitespace&&yt.test(o)&&d.push(t.createTextNode(yt.exec(o)[0])),!x.support.tbody){o="table"!==l||xt.test(o)?""!==c[1]||xt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;while(i--)x.nodeName(u=o.childNodes[i],"tbody")&&!u.childNodes.length&&o.removeChild(u)}x.merge(d,s.childNodes),s.textContent="";while(s.firstChild)s.removeChild(s.firstChild);s=f.lastChild}else d.push(t.createTextNode(o));s&&f.removeChild(s),x.support.appendChecked||x.grep(Ft(d,"input"),Bt),h=0;while(o=d[h++])if((!r||-1===x.inArray(o,r))&&(a=x.contains(o.ownerDocument,o),s=Ft(f.appendChild(o),"script"),a&&_t(s),n)){i=0;while(o=s[i++])kt.test(o.type||"")&&n.push(o)}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,l=x.expando,u=x.cache,c=x.support.deleteExpando,f=x.event.special;for(;null!=(n=e[s]);s++)if((t||x.acceptData(n))&&(o=n[l],a=o&&u[o])){if(a.events)for(r in a.events)f[r]?x.event.remove(n,r):x.removeEvent(n,r,a.handle);
+u[o]&&(delete u[o],c?delete n[l]:typeof n.removeAttribute!==i?n.removeAttribute(l):n[l]=null,p.push(o))}},_evalUrl:function(e){return x.ajax({url:e,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})}}),x.fn.extend({wrapAll:function(e){if(x.isFunction(e))return this.each(function(t){x(this).wrapAll(e.call(this,t))});if(this[0]){var t=x(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&1===e.firstChild.nodeType)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return x.isFunction(e)?this.each(function(t){x(this).wrapInner(e.call(this,t))}):this.each(function(){var t=x(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=x.isFunction(e);return this.each(function(n){x(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){x.nodeName(this,"body")||x(this).replaceWith(this.childNodes)}).end()}});var Pt,Rt,Wt,$t=/alpha\([^)]*\)/i,It=/opacity\s*=\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp("^("+w+")(.*)$","i"),Yt=RegExp("^("+w+")(?!px)[a-z%]+$","i"),Jt=RegExp("^([+-])=("+w+")","i"),Gt={BODY:"block"},Qt={position:"absolute",visibility:"hidden",display:"block"},Kt={letterSpacing:0,fontWeight:400},Zt=["Top","Right","Bottom","Left"],en=["Webkit","O","Moz","ms"];function tn(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--)if(t=en[i]+n,t in e)return t;return r}function nn(e,t){return e=t||e,"none"===x.css(e,"display")||!x.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++)r=e[a],r.style&&(o[a]=x._data(r,"olddisplay"),n=r.style.display,t?(o[a]||"none"!==n||(r.style.display=""),""===r.style.display&&nn(r)&&(o[a]=x._data(r,"olddisplay",ln(r.nodeName)))):o[a]||(i=nn(r),(n&&"none"!==n||!i)&&x._data(r,"olddisplay",i?n:x.css(r,"display"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[a]||"":"none"));return e}x.fn.extend({css:function(e,n){return x.access(this,function(e,n,r){var i,o,a={},s=0;if(x.isArray(n)){for(o=Rt(e),i=n.length;i>s;s++)a[n[s]]=x.css(e,n[s],!1,o);return a}return r!==t?x.style(e,n,r):x.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){var t="boolean"==typeof e;return this.each(function(){(t?e:nn(this))?x(this).show():x(this).hide()})}}),x.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":x.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,l=x.camelCase(n),u=e.style;if(n=x.cssProps[l]||(x.cssProps[l]=tn(u,l)),s=x.cssHooks[n]||x.cssHooks[l],r===t)return s&&"get"in s&&(o=s.get(e,!1,i))!==t?o:u[n];if(a=typeof r,"string"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(x.css(e,n)),a="number"),!(null==r||"number"===a&&isNaN(r)||("number"!==a||x.cssNumber[l]||(r+="px"),x.support.clearCloneStyle||""!==r||0!==n.indexOf("background")||(u[n]="inherit"),s&&"set"in s&&(r=s.set(e,r,i))===t)))try{u[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,l=x.camelCase(n);return n=x.cssProps[l]||(x.cssProps[l]=tn(e.style,l)),s=x.cssHooks[n]||x.cssHooks[l],s&&"get"in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),"normal"===a&&n in Kt&&(a=Kt[n]),""===r||r?(o=parseFloat(a),r===!0||x.isNumeric(o)?o||0:a):a}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s.getPropertyValue(n)||s[n]:t,u=e.style;return s&&(""!==l||x.contains(e.ownerDocument,e)||(l=x.style(e,n)),Yt.test(l)&&Ut.test(n)&&(i=u.width,o=u.minWidth,a=u.maxWidth,u.minWidth=u.maxWidth=u.width=l,l=s.width,u.width=i,u.minWidth=o,u.maxWidth=a)),l}):a.documentElement.currentStyle&&(Rt=function(e){return e.currentStyle},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s[n]:t,u=e.style;return null==l&&u&&u[n]&&(l=u[n]),Yt.test(l)&&!zt.test(n)&&(i=u.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),u.left="fontSize"===n?"1em":l,l=u.pixelLeft+"px",u.left=i,a&&(o.left=a)),""===l?"auto":l});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function an(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;for(;4>o;o+=2)"margin"===n&&(a+=x.css(e,n+Zt[o],!0,i)),r?("content"===n&&(a-=x.css(e,"padding"+Zt[o],!0,i)),"margin"!==n&&(a-=x.css(e,"border"+Zt[o]+"Width",!0,i))):(a+=x.css(e,"padding"+Zt[o],!0,i),"padding"!==n&&(a+=x.css(e,"border"+Zt[o]+"Width",!0,i)));return a}function sn(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i))return i;r=a&&(x.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+an(e,t,n||(a?"border":"content"),r,o)+"px"}function ln(e){var t=a,n=Gt[e];return n||(n=un(e,t),"none"!==n&&n||(Pt=(Pt||x("").css("cssText","display:block !important")).appendTo(t.documentElement),t=(Pt[0].contentWindow||Pt[0].contentDocument).document,t.write(""),t.close(),n=un(e,t),Pt.detach()),Gt[e]=n),n}function un(e,t){var n=x(t.createElement(e)).appendTo(t.body),r=x.css(n[0],"display");return n.remove(),r}x.each(["height","width"],function(e,n){x.cssHooks[n]={get:function(e,r,i){return r?0===e.offsetWidth&&Xt.test(x.css(e,"display"))?x.swap(e,Qt,function(){return sn(e,n,i)}):sn(e,n,i):t},set:function(e,t,r){var i=r&&Rt(e);return on(e,t,r?an(e,n,r,x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,i),i):0)}}}),x.support.opacity||(x.cssHooks.opacity={get:function(e,t){return It.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=x.isNumeric(t)?"alpha(opacity="+100*t+")":"",o=r&&r.filter||n.filter||"";n.zoom=1,(t>=1||""===t)&&""===x.trim(o.replace($t,""))&&n.removeAttribute&&(n.removeAttribute("filter"),""===t||r&&!r.filter)||(n.filter=$t.test(o)?o.replace($t,i):o+" "+i)}}),x(function(){x.support.reliableMarginRight||(x.cssHooks.marginRight={get:function(e,n){return n?x.swap(e,{display:"inline-block"},Wt,[e,"marginRight"]):t}}),!x.support.pixelPosition&&x.fn.position&&x.each(["top","left"],function(e,n){x.cssHooks[n]={get:function(e,r){return r?(r=Wt(e,n),Yt.test(r)?x(e).position()[n]+"px":r):t}}})}),x.expr&&x.expr.filters&&(x.expr.filters.hidden=function(e){return 0>=e.offsetWidth&&0>=e.offsetHeight||!x.support.reliableHiddenOffsets&&"none"===(e.style&&e.style.display||x.css(e,"display"))},x.expr.filters.visible=function(e){return!x.expr.filters.hidden(e)}),x.each({margin:"",padding:"",border:"Width"},function(e,t){x.cssHooks[e+t]={expand:function(n){var r=0,i={},o="string"==typeof n?n.split(" "):[n];for(;4>r;r++)i[e+Zt[r]+t]=o[r]||o[r-2]||o[0];return i}},Ut.test(e)||(x.cssHooks[e+t].set=on)});var cn=/%20/g,pn=/\[\]$/,fn=/\r?\n/g,dn=/^(?:submit|button|image|reset|file)$/i,hn=/^(?:input|select|textarea|keygen)/i;x.fn.extend({serialize:function(){return x.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=x.prop(this,"elements");return e?x.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!x(this).is(":disabled")&&hn.test(this.nodeName)&&!dn.test(e)&&(this.checked||!Ct.test(e))}).map(function(e,t){var n=x(this).val();return null==n?null:x.isArray(n)?x.map(n,function(e){return{name:t.name,value:e.replace(fn,"\r\n")}}):{name:t.name,value:n.replace(fn,"\r\n")}}).get()}}),x.param=function(e,n){var r,i=[],o=function(e,t){t=x.isFunction(t)?t():null==t?"":t,i[i.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};if(n===t&&(n=x.ajaxSettings&&x.ajaxSettings.traditional),x.isArray(e)||e.jquery&&!x.isPlainObject(e))x.each(e,function(){o(this.name,this.value)});else for(r in e)gn(r,e[r],n,o);return i.join("&").replace(cn,"+")};function gn(e,t,n,r){var i;if(x.isArray(t))x.each(t,function(t,i){n||pn.test(e)?r(e,i):gn(e+"["+("object"==typeof i?t:"")+"]",i,n,r)});else if(n||"object"!==x.type(t))r(e,t);else for(i in t)gn(e+"["+i+"]",t[i],n,r)}x.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(e,t){x.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),x.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)},bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)}});var mn,yn,vn=x.now(),bn=/\?/,xn=/#.*$/,wn=/([?&])_=[^&]*/,Tn=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Cn=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Nn=/^(?:GET|HEAD)$/,kn=/^\/\//,En=/^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,Sn=x.fn.load,An={},jn={},Dn="*/".concat("*");try{yn=o.href}catch(Ln){yn=a.createElement("a"),yn.href="",yn=yn.href}mn=En.exec(yn.toLowerCase())||[];function Hn(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(T)||[];if(x.isFunction(n))while(r=o[i++])"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function qn(e,n,r,i){var o={},a=e===jn;function s(l){var u;return o[l]=!0,x.each(e[l]||[],function(e,l){var c=l(n,r,i);return"string"!=typeof c||a||o[c]?a?!(u=c):t:(n.dataTypes.unshift(c),s(c),!1)}),u}return s(n.dataTypes[0])||!o["*"]&&s("*")}function _n(e,n){var r,i,o=x.ajaxSettings.flatOptions||{};for(i in n)n[i]!==t&&((o[i]?e:r||(r={}))[i]=n[i]);return r&&x.extend(!0,e,r),e}x.fn.load=function(e,n,r){if("string"!=typeof e&&Sn)return Sn.apply(this,arguments);var i,o,a,s=this,l=e.indexOf(" ");return l>=0&&(i=e.slice(l,e.length),e=e.slice(0,l)),x.isFunction(n)?(r=n,n=t):n&&"object"==typeof n&&(a="POST"),s.length>0&&x.ajax({url:e,type:a,dataType:"html",data:n}).done(function(e){o=arguments,s.html(i?x("").append(x.parseHTML(e)).find(i):e)}).complete(r&&function(e,t){s.each(r,o||[e.responseText,t,e])}),this},x.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){x.fn[t]=function(e){return this.on(t,e)}}),x.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:yn,type:"GET",isLocal:Cn.test(mn[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Dn,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":x.parseJSON,"text xml":x.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?_n(_n(e,x.ajaxSettings),t):_n(x.ajaxSettings,e)},ajaxPrefilter:Hn(An),ajaxTransport:Hn(jn),ajax:function(e,n){"object"==typeof e&&(n=e,e=t),n=n||{};var r,i,o,a,s,l,u,c,p=x.ajaxSetup({},n),f=p.context||p,d=p.context&&(f.nodeType||f.jquery)?x(f):x.event,h=x.Deferred(),g=x.Callbacks("once memory"),m=p.statusCode||{},y={},v={},b=0,w="canceled",C={readyState:0,getResponseHeader:function(e){var t;if(2===b){if(!c){c={};while(t=Tn.exec(a))c[t[1].toLowerCase()]=t[2]}t=c[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===b?a:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return b||(e=v[n]=v[n]||e,y[e]=t),this},overrideMimeType:function(e){return b||(p.mimeType=e),this},statusCode:function(e){var t;if(e)if(2>b)for(t in e)m[t]=[m[t],e[t]];else C.always(e[C.status]);return this},abort:function(e){var t=e||w;return u&&u.abort(t),k(0,t),this}};if(h.promise(C).complete=g.add,C.success=C.done,C.error=C.fail,p.url=((e||p.url||yn)+"").replace(xn,"").replace(kn,mn[1]+"//"),p.type=n.method||n.type||p.method||p.type,p.dataTypes=x.trim(p.dataType||"*").toLowerCase().match(T)||[""],null==p.crossDomain&&(r=En.exec(p.url.toLowerCase()),p.crossDomain=!(!r||r[1]===mn[1]&&r[2]===mn[2]&&(r[3]||("http:"===r[1]?"80":"443"))===(mn[3]||("http:"===mn[1]?"80":"443")))),p.data&&p.processData&&"string"!=typeof p.data&&(p.data=x.param(p.data,p.traditional)),qn(An,p,n,C),2===b)return C;l=p.global,l&&0===x.active++&&x.event.trigger("ajaxStart"),p.type=p.type.toUpperCase(),p.hasContent=!Nn.test(p.type),o=p.url,p.hasContent||(p.data&&(o=p.url+=(bn.test(o)?"&":"?")+p.data,delete p.data),p.cache===!1&&(p.url=wn.test(o)?o.replace(wn,"$1_="+vn++):o+(bn.test(o)?"&":"?")+"_="+vn++)),p.ifModified&&(x.lastModified[o]&&C.setRequestHeader("If-Modified-Since",x.lastModified[o]),x.etag[o]&&C.setRequestHeader("If-None-Match",x.etag[o])),(p.data&&p.hasContent&&p.contentType!==!1||n.contentType)&&C.setRequestHeader("Content-Type",p.contentType),C.setRequestHeader("Accept",p.dataTypes[0]&&p.accepts[p.dataTypes[0]]?p.accepts[p.dataTypes[0]]+("*"!==p.dataTypes[0]?", "+Dn+"; q=0.01":""):p.accepts["*"]);for(i in p.headers)C.setRequestHeader(i,p.headers[i]);if(p.beforeSend&&(p.beforeSend.call(f,C,p)===!1||2===b))return C.abort();w="abort";for(i in{success:1,error:1,complete:1})C[i](p[i]);if(u=qn(jn,p,n,C)){C.readyState=1,l&&d.trigger("ajaxSend",[C,p]),p.async&&p.timeout>0&&(s=setTimeout(function(){C.abort("timeout")},p.timeout));try{b=1,u.send(y,k)}catch(N){if(!(2>b))throw N;k(-1,N)}}else k(-1,"No Transport");function k(e,n,r,i){var c,y,v,w,T,N=n;2!==b&&(b=2,s&&clearTimeout(s),u=t,a=i||"",C.readyState=e>0?4:0,c=e>=200&&300>e||304===e,r&&(w=Mn(p,C,r)),w=On(p,w,C,c),c?(p.ifModified&&(T=C.getResponseHeader("Last-Modified"),T&&(x.lastModified[o]=T),T=C.getResponseHeader("etag"),T&&(x.etag[o]=T)),204===e||"HEAD"===p.type?N="nocontent":304===e?N="notmodified":(N=w.state,y=w.data,v=w.error,c=!v)):(v=N,(e||!N)&&(N="error",0>e&&(e=0))),C.status=e,C.statusText=(n||N)+"",c?h.resolveWith(f,[y,N,C]):h.rejectWith(f,[C,N,v]),C.statusCode(m),m=t,l&&d.trigger(c?"ajaxSuccess":"ajaxError",[C,p,c?y:v]),g.fireWith(f,[C,N]),l&&(d.trigger("ajaxComplete",[C,p]),--x.active||x.event.trigger("ajaxStop")))}return C},getJSON:function(e,t,n){return x.get(e,t,n,"json")},getScript:function(e,n){return x.get(e,t,n,"script")}}),x.each(["get","post"],function(e,n){x[n]=function(e,r,i,o){return x.isFunction(r)&&(o=o||i,i=r,r=t),x.ajax({url:e,type:n,dataType:o,data:r,success:i})}});function Mn(e,n,r){var i,o,a,s,l=e.contents,u=e.dataTypes;while("*"===u[0])u.shift(),o===t&&(o=e.mimeType||n.getResponseHeader("Content-Type"));if(o)for(s in l)if(l[s]&&l[s].test(o)){u.unshift(s);break}if(u[0]in r)a=u[0];else{for(s in r){if(!u[0]||e.converters[s+" "+u[0]]){a=s;break}i||(i=s)}a=a||i}return a?(a!==u[0]&&u.unshift(a),r[a]):t}function On(e,t,n,r){var i,o,a,s,l,u={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)u[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!l&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),l=o,o=c.shift())if("*"===o)o=l;else if("*"!==l&&l!==o){if(a=u[l+" "+o]||u["* "+o],!a)for(i in u)if(s=i.split(" "),s[1]===o&&(a=u[l+" "+s[0]]||u["* "+s[0]])){a===!0?a=u[i]:u[i]!==!0&&(o=s[0],c.unshift(s[1]));break}if(a!==!0)if(a&&e["throws"])t=a(t);else try{t=a(t)}catch(p){return{state:"parsererror",error:a?p:"No conversion from "+l+" to "+o}}}return{state:"success",data:t}}x.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(e){return x.globalEval(e),e}}}),x.ajaxPrefilter("script",function(e){e.cache===t&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),x.ajaxTransport("script",function(e){if(e.crossDomain){var n,r=a.head||x("head")[0]||a.documentElement;return{send:function(t,i){n=a.createElement("script"),n.async=!0,e.scriptCharset&&(n.charset=e.scriptCharset),n.src=e.url,n.onload=n.onreadystatechange=function(e,t){(t||!n.readyState||/loaded|complete/.test(n.readyState))&&(n.onload=n.onreadystatechange=null,n.parentNode&&n.parentNode.removeChild(n),n=null,t||i(200,"success"))},r.insertBefore(n,r.firstChild)},abort:function(){n&&n.onload(t,!0)}}}});var Fn=[],Bn=/(=)\?(?=&|$)|\?\?/;x.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Fn.pop()||x.expando+"_"+vn++;return this[e]=!0,e}}),x.ajaxPrefilter("json jsonp",function(n,r,i){var o,a,s,l=n.jsonp!==!1&&(Bn.test(n.url)?"url":"string"==typeof n.data&&!(n.contentType||"").indexOf("application/x-www-form-urlencoded")&&Bn.test(n.data)&&"data");return l||"jsonp"===n.dataTypes[0]?(o=n.jsonpCallback=x.isFunction(n.jsonpCallback)?n.jsonpCallback():n.jsonpCallback,l?n[l]=n[l].replace(Bn,"$1"+o):n.jsonp!==!1&&(n.url+=(bn.test(n.url)?"&":"?")+n.jsonp+"="+o),n.converters["script json"]=function(){return s||x.error(o+" was not called"),s[0]},n.dataTypes[0]="json",a=e[o],e[o]=function(){s=arguments},i.always(function(){e[o]=a,n[o]&&(n.jsonpCallback=r.jsonpCallback,Fn.push(o)),s&&x.isFunction(a)&&a(s[0]),s=a=t}),"script"):t});var Pn,Rn,Wn=0,$n=e.ActiveXObject&&function(){var e;for(e in Pn)Pn[e](t,!0)};function In(){try{return new e.XMLHttpRequest}catch(t){}}function zn(){try{return new e.ActiveXObject("Microsoft.XMLHTTP")}catch(t){}}x.ajaxSettings.xhr=e.ActiveXObject?function(){return!this.isLocal&&In()||zn()}:In,Rn=x.ajaxSettings.xhr(),x.support.cors=!!Rn&&"withCredentials"in Rn,Rn=x.support.ajax=!!Rn,Rn&&x.ajaxTransport(function(n){if(!n.crossDomain||x.support.cors){var r;return{send:function(i,o){var a,s,l=n.xhr();if(n.username?l.open(n.type,n.url,n.async,n.username,n.password):l.open(n.type,n.url,n.async),n.xhrFields)for(s in n.xhrFields)l[s]=n.xhrFields[s];n.mimeType&&l.overrideMimeType&&l.overrideMimeType(n.mimeType),n.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");try{for(s in i)l.setRequestHeader(s,i[s])}catch(u){}l.send(n.hasContent&&n.data||null),r=function(e,i){var s,u,c,p;try{if(r&&(i||4===l.readyState))if(r=t,a&&(l.onreadystatechange=x.noop,$n&&delete Pn[a]),i)4!==l.readyState&&l.abort();else{p={},s=l.status,u=l.getAllResponseHeaders(),"string"==typeof l.responseText&&(p.text=l.responseText);try{c=l.statusText}catch(f){c=""}s||!n.isLocal||n.crossDomain?1223===s&&(s=204):s=p.text?200:404}}catch(d){i||o(-1,d)}p&&o(s,c,p,u)},n.async?4===l.readyState?setTimeout(r):(a=++Wn,$n&&(Pn||(Pn={},x(e).unload($n)),Pn[a]=r),l.onreadystatechange=r):r()},abort:function(){r&&r(t,!0)}}}});var Xn,Un,Vn=/^(?:toggle|show|hide)$/,Yn=RegExp("^(?:([+-])=|)("+w+")([a-z%]*)$","i"),Jn=/queueHooks$/,Gn=[nr],Qn={"*":[function(e,t){var n=this.createTween(e,t),r=n.cur(),i=Yn.exec(t),o=i&&i[3]||(x.cssNumber[e]?"":"px"),a=(x.cssNumber[e]||"px"!==o&&+r)&&Yn.exec(x.css(n.elem,e)),s=1,l=20;if(a&&a[3]!==o){o=o||a[3],i=i||[],a=+r||1;do s=s||".5",a/=s,x.style(n.elem,e,a+o);while(s!==(s=n.cur()/r)&&1!==s&&--l)}return i&&(a=n.start=+a||+r||0,n.unit=o,n.end=i[1]?a+(i[1]+1)*i[2]:+i[2]),n}]};function Kn(){return setTimeout(function(){Xn=t}),Xn=x.now()}function Zn(e,t,n){var r,i=(Qn[t]||[]).concat(Qn["*"]),o=0,a=i.length;for(;a>o;o++)if(r=i[o].call(n,t,e))return r}function er(e,t,n){var r,i,o=0,a=Gn.length,s=x.Deferred().always(function(){delete l.elem}),l=function(){if(i)return!1;var t=Xn||Kn(),n=Math.max(0,u.startTime+u.duration-t),r=n/u.duration||0,o=1-r,a=0,l=u.tweens.length;for(;l>a;a++)u.tweens[a].run(o);return s.notifyWith(e,[u,o,n]),1>o&&l?n:(s.resolveWith(e,[u]),!1)},u=s.promise({elem:e,props:x.extend({},t),opts:x.extend(!0,{specialEasing:{}},n),originalProperties:t,originalOptions:n,startTime:Xn||Kn(),duration:n.duration,tweens:[],createTween:function(t,n){var r=x.Tween(e,u.opts,t,n,u.opts.specialEasing[t]||u.opts.easing);return u.tweens.push(r),r},stop:function(t){var n=0,r=t?u.tweens.length:0;if(i)return this;for(i=!0;r>n;n++)u.tweens[n].run(1);return t?s.resolveWith(e,[u,t]):s.rejectWith(e,[u,t]),this}}),c=u.props;for(tr(c,u.opts.specialEasing);a>o;o++)if(r=Gn[o].call(u,e,c,u.opts))return r;return x.map(c,Zn,u),x.isFunction(u.opts.start)&&u.opts.start.call(e,u),x.fx.timer(x.extend(l,{elem:e,anim:u,queue:u.opts.queue})),u.progress(u.opts.progress).done(u.opts.done,u.opts.complete).fail(u.opts.fail).always(u.opts.always)}function tr(e,t){var n,r,i,o,a;for(n in e)if(r=x.camelCase(n),i=t[r],o=e[n],x.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),a=x.cssHooks[r],a&&"expand"in a){o=a.expand(o),delete e[r];for(n in o)n in e||(e[n]=o[n],t[n]=i)}else t[r]=i}x.Animation=x.extend(er,{tweener:function(e,t){x.isFunction(e)?(t=e,e=["*"]):e=e.split(" ");var n,r=0,i=e.length;for(;i>r;r++)n=e[r],Qn[n]=Qn[n]||[],Qn[n].unshift(t)},prefilter:function(e,t){t?Gn.unshift(e):Gn.push(e)}});function nr(e,t,n){var r,i,o,a,s,l,u=this,c={},p=e.style,f=e.nodeType&&nn(e),d=x._data(e,"fxshow");n.queue||(s=x._queueHooks(e,"fx"),null==s.unqueued&&(s.unqueued=0,l=s.empty.fire,s.empty.fire=function(){s.unqueued||l()}),s.unqueued++,u.always(function(){u.always(function(){s.unqueued--,x.queue(e,"fx").length||s.empty.fire()})})),1===e.nodeType&&("height"in t||"width"in t)&&(n.overflow=[p.overflow,p.overflowX,p.overflowY],"inline"===x.css(e,"display")&&"none"===x.css(e,"float")&&(x.support.inlineBlockNeedsLayout&&"inline"!==ln(e.nodeName)?p.zoom=1:p.display="inline-block")),n.overflow&&(p.overflow="hidden",x.support.shrinkWrapBlocks||u.always(function(){p.overflow=n.overflow[0],p.overflowX=n.overflow[1],p.overflowY=n.overflow[2]}));for(r in t)if(i=t[r],Vn.exec(i)){if(delete t[r],o=o||"toggle"===i,i===(f?"hide":"show"))continue;c[r]=d&&d[r]||x.style(e,r)}if(!x.isEmptyObject(c)){d?"hidden"in d&&(f=d.hidden):d=x._data(e,"fxshow",{}),o&&(d.hidden=!f),f?x(e).show():u.done(function(){x(e).hide()}),u.done(function(){var t;x._removeData(e,"fxshow");for(t in c)x.style(e,t,c[t])});for(r in c)a=Zn(f?d[r]:0,r,u),r in d||(d[r]=a.start,f&&(a.end=a.start,a.start="width"===r||"height"===r?1:0))}}function rr(e,t,n,r,i){return new rr.prototype.init(e,t,n,r,i)}x.Tween=rr,rr.prototype={constructor:rr,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||"swing",this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(x.cssNumber[n]?"":"px")},cur:function(){var e=rr.propHooks[this.prop];return e&&e.get?e.get(this):rr.propHooks._default.get(this)},run:function(e){var t,n=rr.propHooks[this.prop];return this.pos=t=this.options.duration?x.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):rr.propHooks._default.set(this),this}},rr.prototype.init.prototype=rr.prototype,rr.propHooks={_default:{get:function(e){var t;return null==e.elem[e.prop]||e.elem.style&&null!=e.elem.style[e.prop]?(t=x.css(e.elem,e.prop,""),t&&"auto"!==t?t:0):e.elem[e.prop]},set:function(e){x.fx.step[e.prop]?x.fx.step[e.prop](e):e.elem.style&&(null!=e.elem.style[x.cssProps[e.prop]]||x.cssHooks[e.prop])?x.style(e.elem,e.prop,e.now+e.unit):e.elem[e.prop]=e.now}}},rr.propHooks.scrollTop=rr.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},x.each(["toggle","show","hide"],function(e,t){var n=x.fn[t];x.fn[t]=function(e,r,i){return null==e||"boolean"==typeof e?n.apply(this,arguments):this.animate(ir(t,!0),e,r,i)}}),x.fn.extend({fadeTo:function(e,t,n,r){return this.filter(nn).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=x.isEmptyObject(e),o=x.speed(t,n,r),a=function(){var t=er(this,x.extend({},e),o);(i||x._data(this,"finish"))&&t.stop(!0)};return a.finish=a,i||o.queue===!1?this.each(a):this.queue(o.queue,a)},stop:function(e,n,r){var i=function(e){var t=e.stop;delete e.stop,t(r)};return"string"!=typeof e&&(r=n,n=e,e=t),n&&e!==!1&&this.queue(e||"fx",[]),this.each(function(){var t=!0,n=null!=e&&e+"queueHooks",o=x.timers,a=x._data(this);if(n)a[n]&&a[n].stop&&i(a[n]);else for(n in a)a[n]&&a[n].stop&&Jn.test(n)&&i(a[n]);for(n=o.length;n--;)o[n].elem!==this||null!=e&&o[n].queue!==e||(o[n].anim.stop(r),t=!1,o.splice(n,1));(t||!r)&&x.dequeue(this,e)})},finish:function(e){return e!==!1&&(e=e||"fx"),this.each(function(){var t,n=x._data(this),r=n[e+"queue"],i=n[e+"queueHooks"],o=x.timers,a=r?r.length:0;for(n.finish=!0,x.queue(this,e,[]),i&&i.stop&&i.stop.call(this,!0),t=o.length;t--;)o[t].elem===this&&o[t].queue===e&&(o[t].anim.stop(!0),o.splice(t,1));for(t=0;a>t;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}});function ir(e,t){var n,r={height:e},i=0;for(t=t?1:0;4>i;i+=2-t)n=Zt[i],r["margin"+n]=r["padding"+n]=e;return t&&(r.opacity=r.width=e),r}x.each({slideDown:ir("show"),slideUp:ir("hide"),slideToggle:ir("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){x.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),x.speed=function(e,t,n){var r=e&&"object"==typeof e?x.extend({},e):{complete:n||!n&&t||x.isFunction(e)&&e,duration:e,easing:n&&t||t&&!x.isFunction(t)&&t};return r.duration=x.fx.off?0:"number"==typeof r.duration?r.duration:r.duration in x.fx.speeds?x.fx.speeds[r.duration]:x.fx.speeds._default,(null==r.queue||r.queue===!0)&&(r.queue="fx"),r.old=r.complete,r.complete=function(){x.isFunction(r.old)&&r.old.call(this),r.queue&&x.dequeue(this,r.queue)},r},x.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2}},x.timers=[],x.fx=rr.prototype.init,x.fx.tick=function(){var e,n=x.timers,r=0;for(Xn=x.now();n.length>r;r++)e=n[r],e()||n[r]!==e||n.splice(r--,1);n.length||x.fx.stop(),Xn=t},x.fx.timer=function(e){e()&&x.timers.push(e)&&x.fx.start()},x.fx.interval=13,x.fx.start=function(){Un||(Un=setInterval(x.fx.tick,x.fx.interval))},x.fx.stop=function(){clearInterval(Un),Un=null},x.fx.speeds={slow:600,fast:200,_default:400},x.fx.step={},x.expr&&x.expr.filters&&(x.expr.filters.animated=function(e){return x.grep(x.timers,function(t){return e===t.elem}).length}),x.fn.offset=function(e){if(arguments.length)return e===t?this:this.each(function(t){x.offset.setOffset(this,e,t)});var n,r,o={top:0,left:0},a=this[0],s=a&&a.ownerDocument;if(s)return n=s.documentElement,x.contains(n,a)?(typeof a.getBoundingClientRect!==i&&(o=a.getBoundingClientRect()),r=or(s),{top:o.top+(r.pageYOffset||n.scrollTop)-(n.clientTop||0),left:o.left+(r.pageXOffset||n.scrollLeft)-(n.clientLeft||0)}):o},x.offset={setOffset:function(e,t,n){var r=x.css(e,"position");"static"===r&&(e.style.position="relative");var i=x(e),o=i.offset(),a=x.css(e,"top"),s=x.css(e,"left"),l=("absolute"===r||"fixed"===r)&&x.inArray("auto",[a,s])>-1,u={},c={},p,f;l?(c=i.position(),p=c.top,f=c.left):(p=parseFloat(a)||0,f=parseFloat(s)||0),x.isFunction(t)&&(t=t.call(e,n,o)),null!=t.top&&(u.top=t.top-o.top+p),null!=t.left&&(u.left=t.left-o.left+f),"using"in t?t.using.call(e,u):i.css(u)}},x.fn.extend({position:function(){if(this[0]){var e,t,n={top:0,left:0},r=this[0];return"fixed"===x.css(r,"position")?t=r.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),x.nodeName(e[0],"html")||(n=e.offset()),n.top+=x.css(e[0],"borderTopWidth",!0),n.left+=x.css(e[0],"borderLeftWidth",!0)),{top:t.top-n.top-x.css(r,"marginTop",!0),left:t.left-n.left-x.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||s;while(e&&!x.nodeName(e,"html")&&"static"===x.css(e,"position"))e=e.offsetParent;return e||s})}}),x.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,n){var r=/Y/.test(n);x.fn[e]=function(i){return x.access(this,function(e,i,o){var a=or(e);return o===t?a?n in a?a[n]:a.document.documentElement[i]:e[i]:(a?a.scrollTo(r?x(a).scrollLeft():o,r?o:x(a).scrollTop()):e[i]=o,t)},e,i,arguments.length,null)}});function or(e){return x.isWindow(e)?e:9===e.nodeType?e.defaultView||e.parentWindow:!1}x.each({Height:"height",Width:"width"},function(e,n){x.each({padding:"inner"+e,content:n,"":"outer"+e},function(r,i){x.fn[i]=function(i,o){var a=arguments.length&&(r||"boolean"!=typeof i),s=r||(i===!0||o===!0?"margin":"border");return x.access(this,function(n,r,i){var o;return x.isWindow(n)?n.document.documentElement["client"+e]:9===n.nodeType?(o=n.documentElement,Math.max(n.body["scroll"+e],o["scroll"+e],n.body["offset"+e],o["offset"+e],o["client"+e])):i===t?x.css(n,r,s):x.style(n,r,i,s)},n,a?i:t,a,null)}})}),x.fn.size=function(){return this.length},x.fn.andSelf=x.fn.addBack,"object"==typeof module&&module&&"object"==typeof module.exports?module.exports=x:(e.jQuery=e.$=x,"function"==typeof define&&define.amd&&define("jquery",[],function(){return x}))})(window);
diff --git a/js/fancyBox/lib/jquery-1.9.0.min.js b/js/fancyBox/lib/jquery-1.9.0.min.js
new file mode 100644
index 0000000..50d1b22
--- /dev/null
+++ b/js/fancyBox/lib/jquery-1.9.0.min.js
@@ -0,0 +1,4 @@
+/*! jQuery v1.9.0 | (c) 2005, 2012 jQuery Foundation, Inc. | jquery.org/license */(function(e,t){"use strict";function n(e){var t=e.length,n=st.type(e);return st.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}function r(e){var t=Tt[e]={};return st.each(e.match(lt)||[],function(e,n){t[n]=!0}),t}function i(e,n,r,i){if(st.acceptData(e)){var o,a,s=st.expando,u="string"==typeof n,l=e.nodeType,c=l?st.cache:e,f=l?e[s]:e[s]&&s;if(f&&c[f]&&(i||c[f].data)||!u||r!==t)return f||(l?e[s]=f=K.pop()||st.guid++:f=s),c[f]||(c[f]={},l||(c[f].toJSON=st.noop)),("object"==typeof n||"function"==typeof n)&&(i?c[f]=st.extend(c[f],n):c[f].data=st.extend(c[f].data,n)),o=c[f],i||(o.data||(o.data={}),o=o.data),r!==t&&(o[st.camelCase(n)]=r),u?(a=o[n],null==a&&(a=o[st.camelCase(n)])):a=o,a}}function o(e,t,n){if(st.acceptData(e)){var r,i,o,a=e.nodeType,u=a?st.cache:e,l=a?e[st.expando]:st.expando;if(u[l]){if(t&&(r=n?u[l]:u[l].data)){st.isArray(t)?t=t.concat(st.map(t,st.camelCase)):t in r?t=[t]:(t=st.camelCase(t),t=t in r?[t]:t.split(" "));for(i=0,o=t.length;o>i;i++)delete r[t[i]];if(!(n?s:st.isEmptyObject)(r))return}(n||(delete u[l].data,s(u[l])))&&(a?st.cleanData([e],!0):st.support.deleteExpando||u!=u.window?delete u[l]:u[l]=null)}}}function a(e,n,r){if(r===t&&1===e.nodeType){var i="data-"+n.replace(Nt,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"==typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null:+r+""===r?+r:wt.test(r)?st.parseJSON(r):r}catch(o){}st.data(e,n,r)}else r=t}return r}function s(e){var t;for(t in e)if(("data"!==t||!st.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}function u(){return!0}function l(){return!1}function c(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}function f(e,t,n){if(t=t||0,st.isFunction(t))return st.grep(e,function(e,r){var i=!!t.call(e,r,e);return i===n});if(t.nodeType)return st.grep(e,function(e){return e===t===n});if("string"==typeof t){var r=st.grep(e,function(e){return 1===e.nodeType});if(Wt.test(t))return st.filter(t,r,!n);t=st.filter(t,r)}return st.grep(e,function(e){return st.inArray(e,t)>=0===n})}function p(e){var t=zt.split("|"),n=e.createDocumentFragment();if(n.createElement)for(;t.length;)n.createElement(t.pop());return n}function d(e,t){return e.getElementsByTagName(t)[0]||e.appendChild(e.ownerDocument.createElement(t))}function h(e){var t=e.getAttributeNode("type");return e.type=(t&&t.specified)+"/"+e.type,e}function g(e){var t=nn.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function m(e,t){for(var n,r=0;null!=(n=e[r]);r++)st._data(n,"globalEval",!t||st._data(t[r],"globalEval"))}function y(e,t){if(1===t.nodeType&&st.hasData(e)){var n,r,i,o=st._data(e),a=st._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)st.event.add(t,n,s[n][r])}a.data&&(a.data=st.extend({},a.data))}}function v(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!st.support.noCloneEvent&&t[st.expando]){r=st._data(t);for(i in r.events)st.removeEvent(t,i,r.handle);t.removeAttribute(st.expando)}"script"===n&&t.text!==e.text?(h(t).text=e.text,g(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),st.support.html5Clone&&e.innerHTML&&!st.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Zt.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}function b(e,n){var r,i,o=0,a=e.getElementsByTagName!==t?e.getElementsByTagName(n||"*"):e.querySelectorAll!==t?e.querySelectorAll(n||"*"):t;if(!a)for(a=[],r=e.childNodes||e;null!=(i=r[o]);o++)!n||st.nodeName(i,n)?a.push(i):st.merge(a,b(i,n));return n===t||n&&st.nodeName(e,n)?st.merge([e],a):a}function x(e){Zt.test(e.type)&&(e.defaultChecked=e.checked)}function T(e,t){if(t in e)return t;for(var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=Nn.length;i--;)if(t=Nn[i]+n,t in e)return t;return r}function w(e,t){return e=t||e,"none"===st.css(e,"display")||!st.contains(e.ownerDocument,e)}function N(e,t){for(var n,r=[],i=0,o=e.length;o>i;i++)n=e[i],n.style&&(r[i]=st._data(n,"olddisplay"),t?(r[i]||"none"!==n.style.display||(n.style.display=""),""===n.style.display&&w(n)&&(r[i]=st._data(n,"olddisplay",S(n.nodeName)))):r[i]||w(n)||st._data(n,"olddisplay",st.css(n,"display")));for(i=0;o>i;i++)n=e[i],n.style&&(t&&"none"!==n.style.display&&""!==n.style.display||(n.style.display=t?r[i]||"":"none"));return e}function C(e,t,n){var r=mn.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function k(e,t,n,r,i){for(var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;4>o;o+=2)"margin"===n&&(a+=st.css(e,n+wn[o],!0,i)),r?("content"===n&&(a-=st.css(e,"padding"+wn[o],!0,i)),"margin"!==n&&(a-=st.css(e,"border"+wn[o]+"Width",!0,i))):(a+=st.css(e,"padding"+wn[o],!0,i),"padding"!==n&&(a+=st.css(e,"border"+wn[o]+"Width",!0,i)));return a}function E(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=ln(e),a=st.support.boxSizing&&"border-box"===st.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=un(e,t,o),(0>i||null==i)&&(i=e.style[t]),yn.test(i))return i;r=a&&(st.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+k(e,t,n||(a?"border":"content"),r,o)+"px"}function S(e){var t=V,n=bn[e];return n||(n=A(e,t),"none"!==n&&n||(cn=(cn||st("
").css("cssText","display:block !important")).appendTo(t.documentElement),t=(cn[0].contentWindow||cn[0].contentDocument).document,t.write(""),t.close(),n=A(e,t),cn.detach()),bn[e]=n),n}function A(e,t){var n=st(t.createElement(e)).appendTo(t.body),r=st.css(n[0],"display");return n.remove(),r}function j(e,t,n,r){var i;if(st.isArray(t))st.each(t,function(t,i){n||kn.test(e)?r(e,i):j(e+"["+("object"==typeof i?t:"")+"]",i,n,r)});else if(n||"object"!==st.type(t))r(e,t);else for(i in t)j(e+"["+i+"]",t[i],n,r)}function D(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(lt)||[];if(st.isFunction(n))for(;r=o[i++];)"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function L(e,n,r,i){function o(u){var l;return a[u]=!0,st.each(e[u]||[],function(e,u){var c=u(n,r,i);return"string"!=typeof c||s||a[c]?s?!(l=c):t:(n.dataTypes.unshift(c),o(c),!1)}),l}var a={},s=e===$n;return o(n.dataTypes[0])||!a["*"]&&o("*")}function H(e,n){var r,i,o=st.ajaxSettings.flatOptions||{};for(r in n)n[r]!==t&&((o[r]?e:i||(i={}))[r]=n[r]);return i&&st.extend(!0,e,i),e}function M(e,n,r){var i,o,a,s,u=e.contents,l=e.dataTypes,c=e.responseFields;for(o in c)o in r&&(n[c[o]]=r[o]);for(;"*"===l[0];)l.shift(),i===t&&(i=e.mimeType||n.getResponseHeader("Content-Type"));if(i)for(o in u)if(u[o]&&u[o].test(i)){l.unshift(o);break}if(l[0]in r)a=l[0];else{for(o in r){if(!l[0]||e.converters[o+" "+l[0]]){a=o;break}s||(s=o)}a=a||s}return a?(a!==l[0]&&l.unshift(a),r[a]):t}function q(e,t){var n,r,i,o,a={},s=0,u=e.dataTypes.slice(),l=u[0];if(e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u[1])for(n in e.converters)a[n.toLowerCase()]=e.converters[n];for(;i=u[++s];)if("*"!==i){if("*"!==l&&l!==i){if(n=a[l+" "+i]||a["* "+i],!n)for(r in a)if(o=r.split(" "),o[1]===i&&(n=a[l+" "+o[0]]||a["* "+o[0]])){n===!0?n=a[r]:a[r]!==!0&&(i=o[0],u.splice(s--,0,i));break}if(n!==!0)if(n&&e["throws"])t=n(t);else try{t=n(t)}catch(c){return{state:"parsererror",error:n?c:"No conversion from "+l+" to "+i}}}l=i}return{state:"success",data:t}}function _(){try{return new e.XMLHttpRequest}catch(t){}}function F(){try{return new e.ActiveXObject("Microsoft.XMLHTTP")}catch(t){}}function O(){return setTimeout(function(){Qn=t}),Qn=st.now()}function B(e,t){st.each(t,function(t,n){for(var r=(rr[t]||[]).concat(rr["*"]),i=0,o=r.length;o>i;i++)if(r[i].call(e,t,n))return})}function P(e,t,n){var r,i,o=0,a=nr.length,s=st.Deferred().always(function(){delete u.elem}),u=function(){if(i)return!1;for(var t=Qn||O(),n=Math.max(0,l.startTime+l.duration-t),r=n/l.duration||0,o=1-r,a=0,u=l.tweens.length;u>a;a++)l.tweens[a].run(o);return s.notifyWith(e,[l,o,n]),1>o&&u?n:(s.resolveWith(e,[l]),!1)},l=s.promise({elem:e,props:st.extend({},t),opts:st.extend(!0,{specialEasing:{}},n),originalProperties:t,originalOptions:n,startTime:Qn||O(),duration:n.duration,tweens:[],createTween:function(t,n){var r=st.Tween(e,l.opts,t,n,l.opts.specialEasing[t]||l.opts.easing);return l.tweens.push(r),r},stop:function(t){var n=0,r=t?l.tweens.length:0;if(i)return this;for(i=!0;r>n;n++)l.tweens[n].run(1);return t?s.resolveWith(e,[l,t]):s.rejectWith(e,[l,t]),this}}),c=l.props;for(R(c,l.opts.specialEasing);a>o;o++)if(r=nr[o].call(l,e,c,l.opts))return r;return B(l,c),st.isFunction(l.opts.start)&&l.opts.start.call(e,l),st.fx.timer(st.extend(u,{elem:e,anim:l,queue:l.opts.queue})),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always)}function R(e,t){var n,r,i,o,a;for(n in e)if(r=st.camelCase(n),i=t[r],o=e[n],st.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),a=st.cssHooks[r],a&&"expand"in a){o=a.expand(o),delete e[r];for(n in o)n in e||(e[n]=o[n],t[n]=i)}else t[r]=i}function W(e,t,n){var r,i,o,a,s,u,l,c,f,p=this,d=e.style,h={},g=[],m=e.nodeType&&w(e);n.queue||(c=st._queueHooks(e,"fx"),null==c.unqueued&&(c.unqueued=0,f=c.empty.fire,c.empty.fire=function(){c.unqueued||f()}),c.unqueued++,p.always(function(){p.always(function(){c.unqueued--,st.queue(e,"fx").length||c.empty.fire()})})),1===e.nodeType&&("height"in t||"width"in t)&&(n.overflow=[d.overflow,d.overflowX,d.overflowY],"inline"===st.css(e,"display")&&"none"===st.css(e,"float")&&(st.support.inlineBlockNeedsLayout&&"inline"!==S(e.nodeName)?d.zoom=1:d.display="inline-block")),n.overflow&&(d.overflow="hidden",st.support.shrinkWrapBlocks||p.done(function(){d.overflow=n.overflow[0],d.overflowX=n.overflow[1],d.overflowY=n.overflow[2]}));for(r in t)if(o=t[r],Zn.exec(o)){if(delete t[r],u=u||"toggle"===o,o===(m?"hide":"show"))continue;g.push(r)}if(a=g.length){s=st._data(e,"fxshow")||st._data(e,"fxshow",{}),"hidden"in s&&(m=s.hidden),u&&(s.hidden=!m),m?st(e).show():p.done(function(){st(e).hide()}),p.done(function(){var t;st._removeData(e,"fxshow");for(t in h)st.style(e,t,h[t])});for(r=0;a>r;r++)i=g[r],l=p.createTween(i,m?s[i]:0),h[i]=s[i]||st.style(e,i),i in s||(s[i]=l.start,m&&(l.end=l.start,l.start="width"===i||"height"===i?1:0))}}function $(e,t,n,r,i){return new $.prototype.init(e,t,n,r,i)}function I(e,t){var n,r={height:e},i=0;for(t=t?1:0;4>i;i+=2-t)n=wn[i],r["margin"+n]=r["padding"+n]=e;return t&&(r.opacity=r.width=e),r}function z(e){return st.isWindow(e)?e:9===e.nodeType?e.defaultView||e.parentWindow:!1}var X,U,V=e.document,Y=e.location,J=e.jQuery,G=e.$,Q={},K=[],Z="1.9.0",et=K.concat,tt=K.push,nt=K.slice,rt=K.indexOf,it=Q.toString,ot=Q.hasOwnProperty,at=Z.trim,st=function(e,t){return new st.fn.init(e,t,X)},ut=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,lt=/\S+/g,ct=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,ft=/^(?:(<[\w\W]+>)[^>]*|#([\w-]*))$/,pt=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,dt=/^[\],:{}\s]*$/,ht=/(?:^|:|,)(?:\s*\[)+/g,gt=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,mt=/"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,yt=/^-ms-/,vt=/-([\da-z])/gi,bt=function(e,t){return t.toUpperCase()},xt=function(){V.addEventListener?(V.removeEventListener("DOMContentLoaded",xt,!1),st.ready()):"complete"===V.readyState&&(V.detachEvent("onreadystatechange",xt),st.ready())};st.fn=st.prototype={jquery:Z,constructor:st,init:function(e,n,r){var i,o;if(!e)return this;if("string"==typeof e){if(i="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:ft.exec(e),!i||!i[1]&&n)return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e);if(i[1]){if(n=n instanceof st?n[0]:n,st.merge(this,st.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:V,!0)),pt.test(i[1])&&st.isPlainObject(n))for(i in n)st.isFunction(this[i])?this[i](n[i]):this.attr(i,n[i]);return this}if(o=V.getElementById(i[2]),o&&o.parentNode){if(o.id!==i[2])return r.find(e);this.length=1,this[0]=o}return this.context=V,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):st.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),st.makeArray(e,this))},selector:"",length:0,size:function(){return this.length},toArray:function(){return nt.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=st.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return st.each(this,e,t)},ready:function(e){return st.ready.promise().done(e),this},slice:function(){return this.pushStack(nt.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(st.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:tt,sort:[].sort,splice:[].splice},st.fn.init.prototype=st.fn,st.extend=st.fn.extend=function(){var e,n,r,i,o,a,s=arguments[0]||{},u=1,l=arguments.length,c=!1;for("boolean"==typeof s&&(c=s,s=arguments[1]||{},u=2),"object"==typeof s||st.isFunction(s)||(s={}),l===u&&(s=this,--u);l>u;u++)if(null!=(e=arguments[u]))for(n in e)r=s[n],i=e[n],s!==i&&(c&&i&&(st.isPlainObject(i)||(o=st.isArray(i)))?(o?(o=!1,a=r&&st.isArray(r)?r:[]):a=r&&st.isPlainObject(r)?r:{},s[n]=st.extend(c,a,i)):i!==t&&(s[n]=i));return s},st.extend({noConflict:function(t){return e.$===st&&(e.$=G),t&&e.jQuery===st&&(e.jQuery=J),st},isReady:!1,readyWait:1,holdReady:function(e){e?st.readyWait++:st.ready(!0)},ready:function(e){if(e===!0?!--st.readyWait:!st.isReady){if(!V.body)return setTimeout(st.ready);st.isReady=!0,e!==!0&&--st.readyWait>0||(U.resolveWith(V,[st]),st.fn.trigger&&st(V).trigger("ready").off("ready"))}},isFunction:function(e){return"function"===st.type(e)},isArray:Array.isArray||function(e){return"array"===st.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?Q[it.call(e)]||"object":typeof e},isPlainObject:function(e){if(!e||"object"!==st.type(e)||e.nodeType||st.isWindow(e))return!1;try{if(e.constructor&&!ot.call(e,"constructor")&&!ot.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(n){return!1}var r;for(r in e);return r===t||ot.call(e,r)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||V;var r=pt.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=st.buildFragment([e],t,i),i&&st(i).remove(),st.merge([],r.childNodes))},parseJSON:function(n){return e.JSON&&e.JSON.parse?e.JSON.parse(n):null===n?n:"string"==typeof n&&(n=st.trim(n),n&&dt.test(n.replace(gt,"@").replace(mt,"]").replace(ht,"")))?Function("return "+n)():(st.error("Invalid JSON: "+n),t)},parseXML:function(n){var r,i;if(!n||"string"!=typeof n)return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(o){r=t}return r&&r.documentElement&&!r.getElementsByTagName("parsererror").length||st.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&st.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(yt,"ms-").replace(vt,bt)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,r){var i,o=0,a=e.length,s=n(e);if(r){if(s)for(;a>o&&(i=t.apply(e[o],r),i!==!1);o++);else for(o in e)if(i=t.apply(e[o],r),i===!1)break}else if(s)for(;a>o&&(i=t.call(e[o],o,e[o]),i!==!1);o++);else for(o in e)if(i=t.call(e[o],o,e[o]),i===!1)break;return e},trim:at&&!at.call("\ufeff\u00a0")?function(e){return null==e?"":at.call(e)}:function(e){return null==e?"":(e+"").replace(ct,"")},makeArray:function(e,t){var r=t||[];return null!=e&&(n(Object(e))?st.merge(r,"string"==typeof e?[e]:e):tt.call(r,e)),r},inArray:function(e,t,n){var r;if(t){if(rt)return rt.call(t,e,n);for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,o=0;if("number"==typeof r)for(;r>o;o++)e[i++]=n[o];else for(;n[o]!==t;)e[i++]=n[o++];return e.length=i,e},grep:function(e,t,n){var r,i=[],o=0,a=e.length;for(n=!!n;a>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,r){var i,o=0,a=e.length,s=n(e),u=[];if(s)for(;a>o;o++)i=t(e[o],o,r),null!=i&&(u[u.length]=i);else for(o in e)i=t(e[o],o,r),null!=i&&(u[u.length]=i);return et.apply([],u)},guid:1,proxy:function(e,n){var r,i,o;return"string"==typeof n&&(r=e[n],n=e,e=r),st.isFunction(e)?(i=nt.call(arguments,2),o=function(){return e.apply(n||this,i.concat(nt.call(arguments)))},o.guid=e.guid=e.guid||st.guid++,o):t},access:function(e,n,r,i,o,a,s){var u=0,l=e.length,c=null==r;if("object"===st.type(r)){o=!0;for(u in r)st.access(e,n,u,r[u],!0,a,s)}else if(i!==t&&(o=!0,st.isFunction(i)||(s=!0),c&&(s?(n.call(e,i),n=null):(c=n,n=function(e,t,n){return c.call(st(e),n)})),n))for(;l>u;u++)n(e[u],r,s?i:i.call(e[u],u,n(e[u],r)));return o?e:c?n.call(e):l?n(e[0],r):a},now:function(){return(new Date).getTime()}}),st.ready.promise=function(t){if(!U)if(U=st.Deferred(),"complete"===V.readyState)setTimeout(st.ready);else if(V.addEventListener)V.addEventListener("DOMContentLoaded",xt,!1),e.addEventListener("load",st.ready,!1);else{V.attachEvent("onreadystatechange",xt),e.attachEvent("onload",st.ready);var n=!1;try{n=null==e.frameElement&&V.documentElement}catch(r){}n&&n.doScroll&&function i(){if(!st.isReady){try{n.doScroll("left")}catch(e){return setTimeout(i,50)}st.ready()}}()}return U.promise(t)},st.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){Q["[object "+t+"]"]=t.toLowerCase()}),X=st(V);var Tt={};st.Callbacks=function(e){e="string"==typeof e?Tt[e]||r(e):st.extend({},e);var n,i,o,a,s,u,l=[],c=!e.once&&[],f=function(t){for(n=e.memory&&t,i=!0,u=a||0,a=0,s=l.length,o=!0;l&&s>u;u++)if(l[u].apply(t[0],t[1])===!1&&e.stopOnFalse){n=!1;break}o=!1,l&&(c?c.length&&f(c.shift()):n?l=[]:p.disable())},p={add:function(){if(l){var t=l.length;(function r(t){st.each(t,function(t,n){var i=st.type(n);"function"===i?e.unique&&p.has(n)||l.push(n):n&&n.length&&"string"!==i&&r(n)})})(arguments),o?s=l.length:n&&(a=t,f(n))}return this},remove:function(){return l&&st.each(arguments,function(e,t){for(var n;(n=st.inArray(t,l,n))>-1;)l.splice(n,1),o&&(s>=n&&s--,u>=n&&u--)}),this},has:function(e){return st.inArray(e,l)>-1},empty:function(){return l=[],this},disable:function(){return l=c=n=t,this},disabled:function(){return!l},lock:function(){return c=t,n||p.disable(),this},locked:function(){return!c},fireWith:function(e,t){return t=t||[],t=[e,t.slice?t.slice():t],!l||i&&!c||(o?c.push(t):f(t)),this},fire:function(){return p.fireWith(this,arguments),this},fired:function(){return!!i}};return p},st.extend({Deferred:function(e){var t=[["resolve","done",st.Callbacks("once memory"),"resolved"],["reject","fail",st.Callbacks("once memory"),"rejected"],["notify","progress",st.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return st.Deferred(function(n){st.each(t,function(t,o){var a=o[0],s=st.isFunction(e[t])&&e[t];i[o[1]](function(){var e=s&&s.apply(this,arguments);e&&st.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a+"With"](this===r?n.promise():this,s?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?st.extend(e,r):r}},i={};return r.pipe=r.then,st.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t,n,r,i=0,o=nt.call(arguments),a=o.length,s=1!==a||e&&st.isFunction(e.promise)?a:0,u=1===s?e:st.Deferred(),l=function(e,n,r){return function(i){n[e]=this,r[e]=arguments.length>1?nt.call(arguments):i,r===t?u.notifyWith(n,r):--s||u.resolveWith(n,r)}};if(a>1)for(t=Array(a),n=Array(a),r=Array(a);a>i;i++)o[i]&&st.isFunction(o[i].promise)?o[i].promise().done(l(i,r,o)).fail(u.reject).progress(l(i,n,t)):--s;return s||u.resolveWith(r,o),u.promise()}}),st.support=function(){var n,r,i,o,a,s,u,l,c,f,p=V.createElement("div");if(p.setAttribute("className","t"),p.innerHTML="
a ",r=p.getElementsByTagName("*"),i=p.getElementsByTagName("a")[0],!r||!i||!r.length)return{};o=V.createElement("select"),a=o.appendChild(V.createElement("option")),s=p.getElementsByTagName("input")[0],i.style.cssText="top:1px;float:left;opacity:.5",n={getSetAttribute:"t"!==p.className,leadingWhitespace:3===p.firstChild.nodeType,tbody:!p.getElementsByTagName("tbody").length,htmlSerialize:!!p.getElementsByTagName("link").length,style:/top/.test(i.getAttribute("style")),hrefNormalized:"/a"===i.getAttribute("href"),opacity:/^0.5/.test(i.style.opacity),cssFloat:!!i.style.cssFloat,checkOn:!!s.value,optSelected:a.selected,enctype:!!V.createElement("form").enctype,html5Clone:"<:nav>"!==V.createElement("nav").cloneNode(!0).outerHTML,boxModel:"CSS1Compat"===V.compatMode,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},s.checked=!0,n.noCloneChecked=s.cloneNode(!0).checked,o.disabled=!0,n.optDisabled=!a.disabled;try{delete p.test}catch(d){n.deleteExpando=!1}s=V.createElement("input"),s.setAttribute("value",""),n.input=""===s.getAttribute("value"),s.value="t",s.setAttribute("type","radio"),n.radioValue="t"===s.value,s.setAttribute("checked","t"),s.setAttribute("name","t"),u=V.createDocumentFragment(),u.appendChild(s),n.appendChecked=s.checked,n.checkClone=u.cloneNode(!0).cloneNode(!0).lastChild.checked,p.attachEvent&&(p.attachEvent("onclick",function(){n.noCloneEvent=!1}),p.cloneNode(!0).click());for(f in{submit:!0,change:!0,focusin:!0})p.setAttribute(l="on"+f,"t"),n[f+"Bubbles"]=l in e||p.attributes[l].expando===!1;return p.style.backgroundClip="content-box",p.cloneNode(!0).style.backgroundClip="",n.clearCloneStyle="content-box"===p.style.backgroundClip,st(function(){var r,i,o,a="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",s=V.getElementsByTagName("body")[0];s&&(r=V.createElement("div"),r.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",s.appendChild(r).appendChild(p),p.innerHTML="
",o=p.getElementsByTagName("td"),o[0].style.cssText="padding:0;margin:0;border:0;display:none",c=0===o[0].offsetHeight,o[0].style.display="",o[1].style.display="none",n.reliableHiddenOffsets=c&&0===o[0].offsetHeight,p.innerHTML="",p.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",n.boxSizing=4===p.offsetWidth,n.doesNotIncludeMarginInBodyOffset=1!==s.offsetTop,e.getComputedStyle&&(n.pixelPosition="1%"!==(e.getComputedStyle(p,null)||{}).top,n.boxSizingReliable="4px"===(e.getComputedStyle(p,null)||{width:"4px"}).width,i=p.appendChild(V.createElement("div")),i.style.cssText=p.style.cssText=a,i.style.marginRight=i.style.width="0",p.style.width="1px",n.reliableMarginRight=!parseFloat((e.getComputedStyle(i,null)||{}).marginRight)),p.style.zoom!==t&&(p.innerHTML="",p.style.cssText=a+"width:1px;padding:1px;display:inline;zoom:1",n.inlineBlockNeedsLayout=3===p.offsetWidth,p.style.display="block",p.innerHTML="
",p.firstChild.style.width="5px",n.shrinkWrapBlocks=3!==p.offsetWidth,s.style.zoom=1),s.removeChild(r),r=p=o=i=null)}),r=o=u=a=i=s=null,n}();var wt=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,Nt=/([A-Z])/g;st.extend({cache:{},expando:"jQuery"+(Z+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(e){return e=e.nodeType?st.cache[e[st.expando]]:e[st.expando],!!e&&!s(e)},data:function(e,t,n){return i(e,t,n,!1)},removeData:function(e,t){return o(e,t,!1)},_data:function(e,t,n){return i(e,t,n,!0)},_removeData:function(e,t){return o(e,t,!0)},acceptData:function(e){var t=e.nodeName&&st.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),st.fn.extend({data:function(e,n){var r,i,o=this[0],s=0,u=null;if(e===t){if(this.length&&(u=st.data(o),1===o.nodeType&&!st._data(o,"parsedAttrs"))){for(r=o.attributes;r.length>s;s++)i=r[s].name,i.indexOf("data-")||(i=st.camelCase(i.substring(5)),a(o,i,u[i]));st._data(o,"parsedAttrs",!0)}return u}return"object"==typeof e?this.each(function(){st.data(this,e)}):st.access(this,function(n){return n===t?o?a(o,e,st.data(o,e)):null:(this.each(function(){st.data(this,e,n)}),t)},null,n,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){st.removeData(this,e)})}}),st.extend({queue:function(e,n,r){var i;return e?(n=(n||"fx")+"queue",i=st._data(e,n),r&&(!i||st.isArray(r)?i=st._data(e,n,st.makeArray(r)):i.push(r)),i||[]):t},dequeue:function(e,t){t=t||"fx";var n=st.queue(e,t),r=n.length,i=n.shift(),o=st._queueHooks(e,t),a=function(){st.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),o.cur=i,i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return st._data(e,n)||st._data(e,n,{empty:st.Callbacks("once memory").add(function(){st._removeData(e,t+"queue"),st._removeData(e,n)})})}}),st.fn.extend({queue:function(e,n){var r=2;return"string"!=typeof e&&(n=e,e="fx",r--),r>arguments.length?st.queue(this[0],e):n===t?this:this.each(function(){var t=st.queue(this,e,n);st._queueHooks(this,e),"fx"===e&&"inprogress"!==t[0]&&st.dequeue(this,e)})},dequeue:function(e){return this.each(function(){st.dequeue(this,e)})},delay:function(e,t){return e=st.fx?st.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,o=st.Deferred(),a=this,s=this.length,u=function(){--i||o.resolveWith(a,[a])};for("string"!=typeof e&&(n=e,e=t),e=e||"fx";s--;)r=st._data(a[s],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(u));return u(),o.promise(n)}});var Ct,kt,Et=/[\t\r\n]/g,St=/\r/g,At=/^(?:input|select|textarea|button|object)$/i,jt=/^(?:a|area)$/i,Dt=/^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i,Lt=/^(?:checked|selected)$/i,Ht=st.support.getSetAttribute,Mt=st.support.input;st.fn.extend({attr:function(e,t){return st.access(this,st.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){st.removeAttr(this,e)})},prop:function(e,t){return st.access(this,st.prop,e,t,arguments.length>1)},removeProp:function(e){return e=st.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,o,a=0,s=this.length,u="string"==typeof e&&e;if(st.isFunction(e))return this.each(function(t){st(this).addClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(lt)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(Et," "):" ")){for(o=0;i=t[o++];)0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=st.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,a=0,s=this.length,u=0===arguments.length||"string"==typeof e&&e;if(st.isFunction(e))return this.each(function(t){st(this).removeClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(lt)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(Et," "):"")){for(o=0;i=t[o++];)for(;r.indexOf(" "+i+" ")>=0;)r=r.replace(" "+i+" "," ");n.className=e?st.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e,r="boolean"==typeof t;return st.isFunction(e)?this.each(function(n){st(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n)for(var i,o=0,a=st(this),s=t,u=e.match(lt)||[];i=u[o++];)s=r?s:!a.hasClass(i),a[s?"addClass":"removeClass"](i);else("undefined"===n||"boolean"===n)&&(this.className&&st._data(this,"__className__",this.className),this.className=this.className||e===!1?"":st._data(this,"__className__")||"")})},hasClass:function(e){for(var t=" "+e+" ",n=0,r=this.length;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(Et," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,o=this[0];{if(arguments.length)return i=st.isFunction(e),this.each(function(r){var o,a=st(this);1===this.nodeType&&(o=i?e.call(this,r,a.val()):e,null==o?o="":"number"==typeof o?o+="":st.isArray(o)&&(o=st.map(o,function(e){return null==e?"":e+""})),n=st.valHooks[this.type]||st.valHooks[this.nodeName.toLowerCase()],n&&"set"in n&&n.set(this,o,"value")!==t||(this.value=o))});if(o)return n=st.valHooks[o.type]||st.valHooks[o.nodeName.toLowerCase()],n&&"get"in n&&(r=n.get(o,"value"))!==t?r:(r=o.value,"string"==typeof r?r.replace(St,""):null==r?"":r)}}}),st.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){for(var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,u=0>i?s:o?i:0;s>u;u++)if(n=r[u],!(!n.selected&&u!==i||(st.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&st.nodeName(n.parentNode,"optgroup"))){if(t=st(n).val(),o)return t;a.push(t)}return a},set:function(e,t){var n=st.makeArray(t);return st(e).find("option").each(function(){this.selected=st.inArray(st(this).val(),n)>=0}),n.length||(e.selectedIndex=-1),n}}},attr:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return e.getAttribute===t?st.prop(e,n,r):(a=1!==s||!st.isXMLDoc(e),a&&(n=n.toLowerCase(),o=st.attrHooks[n]||(Dt.test(n)?kt:Ct)),r===t?o&&a&&"get"in o&&null!==(i=o.get(e,n))?i:(e.getAttribute!==t&&(i=e.getAttribute(n)),null==i?t:i):null!==r?o&&a&&"set"in o&&(i=o.set(e,r,n))!==t?i:(e.setAttribute(n,r+""),r):(st.removeAttr(e,n),t))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(lt);if(o&&1===e.nodeType)for(;n=o[i++];)r=st.propFix[n]||n,Dt.test(n)?!Ht&&Lt.test(n)?e[st.camelCase("default-"+n)]=e[r]=!1:e[r]=!1:st.attr(e,n,""),e.removeAttribute(Ht?n:r)},attrHooks:{type:{set:function(e,t){if(!st.support.radioValue&&"radio"===t&&st.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return a=1!==s||!st.isXMLDoc(e),a&&(n=st.propFix[n]||n,o=st.propHooks[n]),r!==t?o&&"set"in o&&(i=o.set(e,r,n))!==t?i:e[n]=r:o&&"get"in o&&null!==(i=o.get(e,n))?i:e[n]},propHooks:{tabIndex:{get:function(e){var n=e.getAttributeNode("tabindex");return n&&n.specified?parseInt(n.value,10):At.test(e.nodeName)||jt.test(e.nodeName)&&e.href?0:t}}}}),kt={get:function(e,n){var r=st.prop(e,n),i="boolean"==typeof r&&e.getAttribute(n),o="boolean"==typeof r?Mt&&Ht?null!=i:Lt.test(n)?e[st.camelCase("default-"+n)]:!!i:e.getAttributeNode(n);return o&&o.value!==!1?n.toLowerCase():t},set:function(e,t,n){return t===!1?st.removeAttr(e,n):Mt&&Ht||!Lt.test(n)?e.setAttribute(!Ht&&st.propFix[n]||n,n):e[st.camelCase("default-"+n)]=e[n]=!0,n}},Mt&&Ht||(st.attrHooks.value={get:function(e,n){var r=e.getAttributeNode(n);return st.nodeName(e,"input")?e.defaultValue:r&&r.specified?r.value:t
+},set:function(e,n,r){return st.nodeName(e,"input")?(e.defaultValue=n,t):Ct&&Ct.set(e,n,r)}}),Ht||(Ct=st.valHooks.button={get:function(e,n){var r=e.getAttributeNode(n);return r&&("id"===n||"name"===n||"coords"===n?""!==r.value:r.specified)?r.value:t},set:function(e,n,r){var i=e.getAttributeNode(r);return i||e.setAttributeNode(i=e.ownerDocument.createAttribute(r)),i.value=n+="","value"===r||n===e.getAttribute(r)?n:t}},st.attrHooks.contenteditable={get:Ct.get,set:function(e,t,n){Ct.set(e,""===t?!1:t,n)}},st.each(["width","height"],function(e,n){st.attrHooks[n]=st.extend(st.attrHooks[n],{set:function(e,r){return""===r?(e.setAttribute(n,"auto"),r):t}})})),st.support.hrefNormalized||(st.each(["href","src","width","height"],function(e,n){st.attrHooks[n]=st.extend(st.attrHooks[n],{get:function(e){var r=e.getAttribute(n,2);return null==r?t:r}})}),st.each(["href","src"],function(e,t){st.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}})),st.support.style||(st.attrHooks.style={get:function(e){return e.style.cssText||t},set:function(e,t){return e.style.cssText=t+""}}),st.support.optSelected||(st.propHooks.selected=st.extend(st.propHooks.selected,{get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}})),st.support.enctype||(st.propFix.enctype="encoding"),st.support.checkOn||st.each(["radio","checkbox"],function(){st.valHooks[this]={get:function(e){return null===e.getAttribute("value")?"on":e.value}}}),st.each(["radio","checkbox"],function(){st.valHooks[this]=st.extend(st.valHooks[this],{set:function(e,n){return st.isArray(n)?e.checked=st.inArray(st(e).val(),n)>=0:t}})});var qt=/^(?:input|select|textarea)$/i,_t=/^key/,Ft=/^(?:mouse|contextmenu)|click/,Ot=/^(?:focusinfocus|focusoutblur)$/,Bt=/^([^.]*)(?:\.(.+)|)$/;st.event={global:{},add:function(e,n,r,i,o){var a,s,u,l,c,f,p,d,h,g,m,y=3!==e.nodeType&&8!==e.nodeType&&st._data(e);if(y){for(r.handler&&(a=r,r=a.handler,o=a.selector),r.guid||(r.guid=st.guid++),(l=y.events)||(l=y.events={}),(s=y.handle)||(s=y.handle=function(e){return st===t||e&&st.event.triggered===e.type?t:st.event.dispatch.apply(s.elem,arguments)},s.elem=e),n=(n||"").match(lt)||[""],c=n.length;c--;)u=Bt.exec(n[c])||[],h=m=u[1],g=(u[2]||"").split(".").sort(),p=st.event.special[h]||{},h=(o?p.delegateType:p.bindType)||h,p=st.event.special[h]||{},f=st.extend({type:h,origType:m,data:i,handler:r,guid:r.guid,selector:o,needsContext:o&&st.expr.match.needsContext.test(o),namespace:g.join(".")},a),(d=l[h])||(d=l[h]=[],d.delegateCount=0,p.setup&&p.setup.call(e,i,g,s)!==!1||(e.addEventListener?e.addEventListener(h,s,!1):e.attachEvent&&e.attachEvent("on"+h,s))),p.add&&(p.add.call(e,f),f.handler.guid||(f.handler.guid=r.guid)),o?d.splice(d.delegateCount++,0,f):d.push(f),st.event.global[h]=!0;e=null}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,m=st.hasData(e)&&st._data(e);if(m&&(u=m.events)){for(t=(t||"").match(lt)||[""],l=t.length;l--;)if(s=Bt.exec(t[l])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){for(f=st.event.special[d]||{},d=(r?f.delegateType:f.bindType)||d,p=u[d]||[],s=s[2]&&RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;o--;)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&f.teardown.call(e,h,m.handle)!==!1||st.removeEvent(e,d,m.handle),delete u[d])}else for(d in u)st.event.remove(e,d+t[l],n,r,!0);st.isEmptyObject(u)&&(delete m.handle,st._removeData(e,"events"))}},trigger:function(n,r,i,o){var a,s,u,l,c,f,p,d=[i||V],h=n.type||n,g=n.namespace?n.namespace.split("."):[];if(s=u=i=i||V,3!==i.nodeType&&8!==i.nodeType&&!Ot.test(h+st.event.triggered)&&(h.indexOf(".")>=0&&(g=h.split("."),h=g.shift(),g.sort()),c=0>h.indexOf(":")&&"on"+h,n=n[st.expando]?n:new st.Event(h,"object"==typeof n&&n),n.isTrigger=!0,n.namespace=g.join("."),n.namespace_re=n.namespace?RegExp("(^|\\.)"+g.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,n.result=t,n.target||(n.target=i),r=null==r?[n]:st.makeArray(r,[n]),p=st.event.special[h]||{},o||!p.trigger||p.trigger.apply(i,r)!==!1)){if(!o&&!p.noBubble&&!st.isWindow(i)){for(l=p.delegateType||h,Ot.test(l+h)||(s=s.parentNode);s;s=s.parentNode)d.push(s),u=s;u===(i.ownerDocument||V)&&d.push(u.defaultView||u.parentWindow||e)}for(a=0;(s=d[a++])&&!n.isPropagationStopped();)n.type=a>1?l:p.bindType||h,f=(st._data(s,"events")||{})[n.type]&&st._data(s,"handle"),f&&f.apply(s,r),f=c&&s[c],f&&st.acceptData(s)&&f.apply&&f.apply(s,r)===!1&&n.preventDefault();if(n.type=h,!(o||n.isDefaultPrevented()||p._default&&p._default.apply(i.ownerDocument,r)!==!1||"click"===h&&st.nodeName(i,"a")||!st.acceptData(i)||!c||!i[h]||st.isWindow(i))){u=i[c],u&&(i[c]=null),st.event.triggered=h;try{i[h]()}catch(m){}st.event.triggered=t,u&&(i[c]=u)}return n.result}},dispatch:function(e){e=st.event.fix(e);var n,r,i,o,a,s=[],u=nt.call(arguments),l=(st._data(this,"events")||{})[e.type]||[],c=st.event.special[e.type]||{};if(u[0]=e,e.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,e)!==!1){for(s=st.event.handlers.call(this,e,l),n=0;(o=s[n++])&&!e.isPropagationStopped();)for(e.currentTarget=o.elem,r=0;(a=o.handlers[r++])&&!e.isImmediatePropagationStopped();)(!e.namespace_re||e.namespace_re.test(a.namespace))&&(e.handleObj=a,e.data=a.data,i=((st.event.special[a.origType]||{}).handle||a.handler).apply(o.elem,u),i!==t&&(e.result=i)===!1&&(e.preventDefault(),e.stopPropagation()));return c.postDispatch&&c.postDispatch.call(this,e),e.result}},handlers:function(e,n){var r,i,o,a,s=[],u=n.delegateCount,l=e.target;if(u&&l.nodeType&&(!e.button||"click"!==e.type))for(;l!=this;l=l.parentNode||this)if(l.disabled!==!0||"click"!==e.type){for(i=[],r=0;u>r;r++)a=n[r],o=a.selector+" ",i[o]===t&&(i[o]=a.needsContext?st(o,this).index(l)>=0:st.find(o,this,null,[l]).length),i[o]&&i.push(a);i.length&&s.push({elem:l,handlers:i})}return n.length>u&&s.push({elem:this,handlers:n.slice(u)}),s},fix:function(e){if(e[st.expando])return e;var t,n,r=e,i=st.event.fixHooks[e.type]||{},o=i.props?this.props.concat(i.props):this.props;for(e=new st.Event(r),t=o.length;t--;)n=o[t],e[n]=r[n];return e.target||(e.target=r.srcElement||V),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,i.filter?i.filter(e,r):e},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,i,o,a=n.button,s=n.fromElement;return null==e.pageX&&null!=n.clientX&&(r=e.target.ownerDocument||V,i=r.documentElement,o=r.body,e.pageX=n.clientX+(i&&i.scrollLeft||o&&o.scrollLeft||0)-(i&&i.clientLeft||o&&o.clientLeft||0),e.pageY=n.clientY+(i&&i.scrollTop||o&&o.scrollTop||0)-(i&&i.clientTop||o&&o.clientTop||0)),!e.relatedTarget&&s&&(e.relatedTarget=s===e.target?n.toElement:s),e.which||a===t||(e.which=1&a?1:2&a?3:4&a?2:0),e}},special:{load:{noBubble:!0},click:{trigger:function(){return st.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):t}},focus:{trigger:function(){if(this!==V.activeElement&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:"focusin"},blur:{trigger:function(){return this===V.activeElement&&this.blur?(this.blur(),!1):t},delegateType:"focusout"},beforeunload:{postDispatch:function(e){e.result!==t&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=st.extend(new st.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?st.event.trigger(i,null,t):st.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},st.removeEvent=V.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,n,r){var i="on"+n;e.detachEvent&&(e[i]===t&&(e[i]=null),e.detachEvent(i,r))},st.Event=function(e,n){return this instanceof st.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?u:l):this.type=e,n&&st.extend(this,n),this.timeStamp=e&&e.timeStamp||st.now(),this[st.expando]=!0,t):new st.Event(e,n)},st.Event.prototype={isDefaultPrevented:l,isPropagationStopped:l,isImmediatePropagationStopped:l,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=u,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=u,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u,this.stopPropagation()}},st.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){st.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return(!i||i!==r&&!st.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),st.support.submitBubbles||(st.event.special.submit={setup:function(){return st.nodeName(this,"form")?!1:(st.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=st.nodeName(n,"input")||st.nodeName(n,"button")?n.form:t;r&&!st._data(r,"submitBubbles")&&(st.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),st._data(r,"submitBubbles",!0))}),t)},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&st.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){return st.nodeName(this,"form")?!1:(st.event.remove(this,"._submit"),t)}}),st.support.changeBubbles||(st.event.special.change={setup:function(){return qt.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(st.event.add(this,"propertychange._change",function(e){"checked"===e.originalEvent.propertyName&&(this._just_changed=!0)}),st.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),st.event.simulate("change",this,e,!0)})),!1):(st.event.add(this,"beforeactivate._change",function(e){var t=e.target;qt.test(t.nodeName)&&!st._data(t,"changeBubbles")&&(st.event.add(t,"change._change",function(e){!this.parentNode||e.isSimulated||e.isTrigger||st.event.simulate("change",this.parentNode,e,!0)}),st._data(t,"changeBubbles",!0))}),t)},handle:function(e){var n=e.target;return this!==n||e.isSimulated||e.isTrigger||"radio"!==n.type&&"checkbox"!==n.type?e.handleObj.handler.apply(this,arguments):t},teardown:function(){return st.event.remove(this,"._change"),!qt.test(this.nodeName)}}),st.support.focusinBubbles||st.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){st.event.simulate(t,e.target,st.event.fix(e),!0)};st.event.special[t]={setup:function(){0===n++&&V.addEventListener(e,r,!0)},teardown:function(){0===--n&&V.removeEventListener(e,r,!0)}}}),st.fn.extend({on:function(e,n,r,i,o){var a,s;if("object"==typeof e){"string"!=typeof n&&(r=r||n,n=t);for(s in e)this.on(s,n,r,e[s],o);return this}if(null==r&&null==i?(i=n,r=n=t):null==i&&("string"==typeof n?(i=r,r=t):(i=r,r=n,n=t)),i===!1)i=l;else if(!i)return this;return 1===o&&(a=i,i=function(e){return st().off(e),a.apply(this,arguments)},i.guid=a.guid||(a.guid=st.guid++)),this.each(function(){st.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,o;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,st(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if("object"==typeof e){for(o in e)this.off(o,n,e[o]);return this}return(n===!1||"function"==typeof n)&&(r=n,n=t),r===!1&&(r=l),this.each(function(){st.event.remove(this,e,r,n)})},bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},trigger:function(e,t){return this.each(function(){st.event.trigger(e,t,this)})},triggerHandler:function(e,n){var r=this[0];return r?st.event.trigger(e,n,r,!0):t},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),st.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(e,t){st.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)},_t.test(t)&&(st.event.fixHooks[t]=st.event.keyHooks),Ft.test(t)&&(st.event.fixHooks[t]=st.event.mouseHooks)}),function(e,t){function n(e){return ht.test(e+"")}function r(){var e,t=[];return e=function(n,r){return t.push(n+=" ")>C.cacheLength&&delete e[t.shift()],e[n]=r}}function i(e){return e[P]=!0,e}function o(e){var t=L.createElement("div");try{return e(t)}catch(n){return!1}finally{t=null}}function a(e,t,n,r){var i,o,a,s,u,l,c,d,h,g;if((t?t.ownerDocument||t:R)!==L&&D(t),t=t||L,n=n||[],!e||"string"!=typeof e)return n;if(1!==(s=t.nodeType)&&9!==s)return[];if(!M&&!r){if(i=gt.exec(e))if(a=i[1]){if(9===s){if(o=t.getElementById(a),!o||!o.parentNode)return n;if(o.id===a)return n.push(o),n}else if(t.ownerDocument&&(o=t.ownerDocument.getElementById(a))&&O(t,o)&&o.id===a)return n.push(o),n}else{if(i[2])return Q.apply(n,K.call(t.getElementsByTagName(e),0)),n;if((a=i[3])&&W.getByClassName&&t.getElementsByClassName)return Q.apply(n,K.call(t.getElementsByClassName(a),0)),n}if(W.qsa&&!q.test(e)){if(c=!0,d=P,h=t,g=9===s&&e,1===s&&"object"!==t.nodeName.toLowerCase()){for(l=f(e),(c=t.getAttribute("id"))?d=c.replace(vt,"\\$&"):t.setAttribute("id",d),d="[id='"+d+"'] ",u=l.length;u--;)l[u]=d+p(l[u]);h=dt.test(e)&&t.parentNode||t,g=l.join(",")}if(g)try{return Q.apply(n,K.call(h.querySelectorAll(g),0)),n}catch(m){}finally{c||t.removeAttribute("id")}}}return x(e.replace(at,"$1"),t,n,r)}function s(e,t){for(var n=e&&t&&e.nextSibling;n;n=n.nextSibling)if(n===t)return-1;return e?1:-1}function u(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function l(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function c(e){return i(function(t){return t=+t,i(function(n,r){for(var i,o=e([],n.length,t),a=o.length;a--;)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}function f(e,t){var n,r,i,o,s,u,l,c=X[e+" "];if(c)return t?0:c.slice(0);for(s=e,u=[],l=C.preFilter;s;){(!n||(r=ut.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),u.push(i=[])),n=!1,(r=lt.exec(s))&&(n=r.shift(),i.push({value:n,type:r[0].replace(at," ")}),s=s.slice(n.length));for(o in C.filter)!(r=pt[o].exec(s))||l[o]&&!(r=l[o](r))||(n=r.shift(),i.push({value:n,type:o,matches:r}),s=s.slice(n.length));if(!n)break}return t?s.length:s?a.error(e):X(e,u).slice(0)}function p(e){for(var t=0,n=e.length,r="";n>t;t++)r+=e[t].value;return r}function d(e,t,n){var r=t.dir,i=n&&"parentNode"===t.dir,o=I++;return t.first?function(t,n,o){for(;t=t[r];)if(1===t.nodeType||i)return e(t,n,o)}:function(t,n,a){var s,u,l,c=$+" "+o;if(a){for(;t=t[r];)if((1===t.nodeType||i)&&e(t,n,a))return!0}else for(;t=t[r];)if(1===t.nodeType||i)if(l=t[P]||(t[P]={}),(u=l[r])&&u[0]===c){if((s=u[1])===!0||s===N)return s===!0}else if(u=l[r]=[c],u[1]=e(t,n,a)||N,u[1]===!0)return!0}}function h(e){return e.length>1?function(t,n,r){for(var i=e.length;i--;)if(!e[i](t,n,r))return!1;return!0}:e[0]}function g(e,t,n,r,i){for(var o,a=[],s=0,u=e.length,l=null!=t;u>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),l&&t.push(s));return a}function m(e,t,n,r,o,a){return r&&!r[P]&&(r=m(r)),o&&!o[P]&&(o=m(o,a)),i(function(i,a,s,u){var l,c,f,p=[],d=[],h=a.length,m=i||b(t||"*",s.nodeType?[s]:s,[]),y=!e||!i&&t?m:g(m,p,e,s,u),v=n?o||(i?e:h||r)?[]:a:y;if(n&&n(y,v,s,u),r)for(l=g(v,d),r(l,[],s,u),c=l.length;c--;)(f=l[c])&&(v[d[c]]=!(y[d[c]]=f));if(i){if(o||e){if(o){for(l=[],c=v.length;c--;)(f=v[c])&&l.push(y[c]=f);o(null,v=[],l,u)}for(c=v.length;c--;)(f=v[c])&&(l=o?Z.call(i,f):p[c])>-1&&(i[l]=!(a[l]=f))}}else v=g(v===a?v.splice(h,v.length):v),o?o(null,a,v,u):Q.apply(a,v)})}function y(e){for(var t,n,r,i=e.length,o=C.relative[e[0].type],a=o||C.relative[" "],s=o?1:0,u=d(function(e){return e===t},a,!0),l=d(function(e){return Z.call(t,e)>-1},a,!0),c=[function(e,n,r){return!o&&(r||n!==j)||((t=n).nodeType?u(e,n,r):l(e,n,r))}];i>s;s++)if(n=C.relative[e[s].type])c=[d(h(c),n)];else{if(n=C.filter[e[s].type].apply(null,e[s].matches),n[P]){for(r=++s;i>r&&!C.relative[e[r].type];r++);return m(s>1&&h(c),s>1&&p(e.slice(0,s-1)).replace(at,"$1"),n,r>s&&y(e.slice(s,r)),i>r&&y(e=e.slice(r)),i>r&&p(e))}c.push(n)}return h(c)}function v(e,t){var n=0,r=t.length>0,o=e.length>0,s=function(i,s,u,l,c){var f,p,d,h=[],m=0,y="0",v=i&&[],b=null!=c,x=j,T=i||o&&C.find.TAG("*",c&&s.parentNode||s),w=$+=null==x?1:Math.E;for(b&&(j=s!==L&&s,N=n);null!=(f=T[y]);y++){if(o&&f){for(p=0;d=e[p];p++)if(d(f,s,u)){l.push(f);break}b&&($=w,N=++n)}r&&((f=!d&&f)&&m--,i&&v.push(f))}if(m+=y,r&&y!==m){for(p=0;d=t[p];p++)d(v,h,s,u);if(i){if(m>0)for(;y--;)v[y]||h[y]||(h[y]=G.call(l));h=g(h)}Q.apply(l,h),b&&!i&&h.length>0&&m+t.length>1&&a.uniqueSort(l)}return b&&($=w,j=x),v};return r?i(s):s}function b(e,t,n){for(var r=0,i=t.length;i>r;r++)a(e,t[r],n);return n}function x(e,t,n,r){var i,o,a,s,u,l=f(e);if(!r&&1===l.length){if(o=l[0]=l[0].slice(0),o.length>2&&"ID"===(a=o[0]).type&&9===t.nodeType&&!M&&C.relative[o[1].type]){if(t=C.find.ID(a.matches[0].replace(xt,Tt),t)[0],!t)return n;e=e.slice(o.shift().value.length)}for(i=pt.needsContext.test(e)?-1:o.length-1;i>=0&&(a=o[i],!C.relative[s=a.type]);i--)if((u=C.find[s])&&(r=u(a.matches[0].replace(xt,Tt),dt.test(o[0].type)&&t.parentNode||t))){if(o.splice(i,1),e=r.length&&p(o),!e)return Q.apply(n,K.call(r,0)),n;break}}return S(e,l)(r,t,M,n,dt.test(e)),n}function T(){}var w,N,C,k,E,S,A,j,D,L,H,M,q,_,F,O,B,P="sizzle"+-new Date,R=e.document,W={},$=0,I=0,z=r(),X=r(),U=r(),V=typeof t,Y=1<<31,J=[],G=J.pop,Q=J.push,K=J.slice,Z=J.indexOf||function(e){for(var t=0,n=this.length;n>t;t++)if(this[t]===e)return t;return-1},et="[\\x20\\t\\r\\n\\f]",tt="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",nt=tt.replace("w","w#"),rt="([*^$|!~]?=)",it="\\["+et+"*("+tt+")"+et+"*(?:"+rt+et+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+nt+")|)|)"+et+"*\\]",ot=":("+tt+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+it.replace(3,8)+")*)|.*)\\)|)",at=RegExp("^"+et+"+|((?:^|[^\\\\])(?:\\\\.)*)"+et+"+$","g"),ut=RegExp("^"+et+"*,"+et+"*"),lt=RegExp("^"+et+"*([\\x20\\t\\r\\n\\f>+~])"+et+"*"),ct=RegExp(ot),ft=RegExp("^"+nt+"$"),pt={ID:RegExp("^#("+tt+")"),CLASS:RegExp("^\\.("+tt+")"),NAME:RegExp("^\\[name=['\"]?("+tt+")['\"]?\\]"),TAG:RegExp("^("+tt.replace("w","w*")+")"),ATTR:RegExp("^"+it),PSEUDO:RegExp("^"+ot),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+et+"*(even|odd|(([+-]|)(\\d*)n|)"+et+"*(?:([+-]|)"+et+"*(\\d+)|))"+et+"*\\)|)","i"),needsContext:RegExp("^"+et+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+et+"*((?:-\\d)?\\d*)"+et+"*\\)|)(?=[^-]|$)","i")},dt=/[\x20\t\r\n\f]*[+~]/,ht=/\{\s*\[native code\]\s*\}/,gt=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,mt=/^(?:input|select|textarea|button)$/i,yt=/^h\d$/i,vt=/'|\\/g,bt=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,xt=/\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g,Tt=function(e,t){var n="0x"+t-65536;return n!==n?t:0>n?String.fromCharCode(n+65536):String.fromCharCode(55296|n>>10,56320|1023&n)};try{K.call(H.childNodes,0)[0].nodeType}catch(wt){K=function(e){for(var t,n=[];t=this[e];e++)n.push(t);return n}}E=a.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},D=a.setDocument=function(e){var r=e?e.ownerDocument||e:R;return r!==L&&9===r.nodeType&&r.documentElement?(L=r,H=r.documentElement,M=E(r),W.tagNameNoComments=o(function(e){return e.appendChild(r.createComment("")),!e.getElementsByTagName("*").length}),W.attributes=o(function(e){e.innerHTML="
";var t=typeof e.lastChild.getAttribute("multiple");return"boolean"!==t&&"string"!==t}),W.getByClassName=o(function(e){return e.innerHTML="
",e.getElementsByClassName&&e.getElementsByClassName("e").length?(e.lastChild.className="e",2===e.getElementsByClassName("e").length):!1}),W.getByName=o(function(e){e.id=P+0,e.innerHTML="
",H.insertBefore(e,H.firstChild);var t=r.getElementsByName&&r.getElementsByName(P).length===2+r.getElementsByName(P+0).length;return W.getIdNotName=!r.getElementById(P),H.removeChild(e),t}),C.attrHandle=o(function(e){return e.innerHTML="
",e.firstChild&&typeof e.firstChild.getAttribute!==V&&"#"===e.firstChild.getAttribute("href")})?{}:{href:function(e){return e.getAttribute("href",2)},type:function(e){return e.getAttribute("type")}},W.getIdNotName?(C.find.ID=function(e,t){if(typeof t.getElementById!==V&&!M){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},C.filter.ID=function(e){var t=e.replace(xt,Tt);return function(e){return e.getAttribute("id")===t}}):(C.find.ID=function(e,n){if(typeof n.getElementById!==V&&!M){var r=n.getElementById(e);return r?r.id===e||typeof r.getAttributeNode!==V&&r.getAttributeNode("id").value===e?[r]:t:[]}},C.filter.ID=function(e){var t=e.replace(xt,Tt);return function(e){var n=typeof e.getAttributeNode!==V&&e.getAttributeNode("id");return n&&n.value===t}}),C.find.TAG=W.tagNameNoComments?function(e,n){return typeof n.getElementsByTagName!==V?n.getElementsByTagName(e):t}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){for(;n=o[i];i++)1===n.nodeType&&r.push(n);return r}return o},C.find.NAME=W.getByName&&function(e,n){return typeof n.getElementsByName!==V?n.getElementsByName(name):t},C.find.CLASS=W.getByClassName&&function(e,n){return typeof n.getElementsByClassName===V||M?t:n.getElementsByClassName(e)},_=[],q=[":focus"],(W.qsa=n(r.querySelectorAll))&&(o(function(e){e.innerHTML="
",e.querySelectorAll("[selected]").length||q.push("\\["+et+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),e.querySelectorAll(":checked").length||q.push(":checked")}),o(function(e){e.innerHTML="
",e.querySelectorAll("[i^='']").length&&q.push("[*^$]="+et+"*(?:\"\"|'')"),e.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),q.push(",.*:")})),(W.matchesSelector=n(F=H.matchesSelector||H.mozMatchesSelector||H.webkitMatchesSelector||H.oMatchesSelector||H.msMatchesSelector))&&o(function(e){W.disconnectedMatch=F.call(e,"div"),F.call(e,"[s!='']:x"),_.push("!=",ot)}),q=RegExp(q.join("|")),_=RegExp(_.join("|")),O=n(H.contains)||H.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},B=H.compareDocumentPosition?function(e,t){var n;return e===t?(A=!0,0):(n=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t))?1&n||e.parentNode&&11===e.parentNode.nodeType?e===r||O(R,e)?-1:t===r||O(R,t)?1:0:4&n?-1:1:e.compareDocumentPosition?-1:1}:function(e,t){var n,i=0,o=e.parentNode,a=t.parentNode,u=[e],l=[t];if(e===t)return A=!0,0;if(e.sourceIndex&&t.sourceIndex)return(~t.sourceIndex||Y)-(O(R,e)&&~e.sourceIndex||Y);if(!o||!a)return e===r?-1:t===r?1:o?-1:a?1:0;if(o===a)return s(e,t);for(n=e;n=n.parentNode;)u.unshift(n);for(n=t;n=n.parentNode;)l.unshift(n);for(;u[i]===l[i];)i++;return i?s(u[i],l[i]):u[i]===R?-1:l[i]===R?1:0},A=!1,[0,0].sort(B),W.detectDuplicates=A,L):L},a.matches=function(e,t){return a(e,null,null,t)},a.matchesSelector=function(e,t){if((e.ownerDocument||e)!==L&&D(e),t=t.replace(bt,"='$1']"),!(!W.matchesSelector||M||_&&_.test(t)||q.test(t)))try{var n=F.call(e,t);if(n||W.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(r){}return a(t,L,null,[e]).length>0},a.contains=function(e,t){return(e.ownerDocument||e)!==L&&D(e),O(e,t)},a.attr=function(e,t){var n;return(e.ownerDocument||e)!==L&&D(e),M||(t=t.toLowerCase()),(n=C.attrHandle[t])?n(e):M||W.attributes?e.getAttribute(t):((n=e.getAttributeNode(t))||e.getAttribute(t))&&e[t]===!0?t:n&&n.specified?n.value:null},a.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},a.uniqueSort=function(e){var t,n=[],r=1,i=0;if(A=!W.detectDuplicates,e.sort(B),A){for(;t=e[r];r++)t===e[r-1]&&(i=n.push(r));for(;i--;)e.splice(n[i],1)}return e},k=a.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=k(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=k(t);return n},C=a.selectors={cacheLength:50,createPseudo:i,match:pt,find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(xt,Tt),e[3]=(e[4]||e[5]||"").replace(xt,Tt),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||a.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&a.error(e[0]),e},PSEUDO:function(e){var t,n=!e[5]&&e[2];return pt.CHILD.test(e[0])?null:(e[4]?e[2]=e[4]:n&&ct.test(n)&&(t=f(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){return"*"===e?function(){return!0}:(e=e.replace(xt,Tt).toLowerCase(),function(t){return t.nodeName&&t.nodeName.toLowerCase()===e})},CLASS:function(e){var t=z[e+" "];return t||(t=RegExp("(^|"+et+")"+e+"("+et+"|$)"))&&z(e,function(e){return t.test(e.className||typeof e.getAttribute!==V&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=a.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.substr(i.length-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.substr(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,f,p,d,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!u&&!s;if(m){if(o){for(;g;){for(f=t;f=f[g];)if(s?f.nodeName.toLowerCase()===y:1===f.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){for(c=m[P]||(m[P]={}),l=c[e]||[],d=l[0]===$&&l[1],p=l[0]===$&&l[2],f=d&&m.childNodes[d];f=++d&&f&&f[g]||(p=d=0)||h.pop();)if(1===f.nodeType&&++p&&f===t){c[e]=[$,d,p];break}}else if(v&&(l=(t[P]||(t[P]={}))[e])&&l[0]===$)p=l[1];else for(;(f=++d&&f&&f[g]||(p=d=0)||h.pop())&&((s?f.nodeName.toLowerCase()!==y:1!==f.nodeType)||!++p||(v&&((f[P]||(f[P]={}))[e]=[$,p]),f!==t)););return p-=i,p===r||0===p%r&&p/r>=0}}},PSEUDO:function(e,t){var n,r=C.pseudos[e]||C.setFilters[e.toLowerCase()]||a.error("unsupported pseudo: "+e);return r[P]?r(t):r.length>1?(n=[e,e,"",t],C.setFilters.hasOwnProperty(e.toLowerCase())?i(function(e,n){for(var i,o=r(e,t),a=o.length;a--;)i=Z.call(e,o[a]),e[i]=!(n[i]=o[a])}):function(e){return r(e,0,n)}):r}},pseudos:{not:i(function(e){var t=[],n=[],r=S(e.replace(at,"$1"));return r[P]?i(function(e,t,n,i){for(var o,a=r(e,null,i,[]),s=e.length;s--;)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:i(function(e){return function(t){return a(e,t).length>0}}),contains:i(function(e){return function(t){return(t.textContent||t.innerText||k(t)).indexOf(e)>-1}}),lang:i(function(e){return ft.test(e||"")||a.error("unsupported lang: "+e),e=e.replace(xt,Tt).toLowerCase(),function(t){var n;do if(n=M?t.getAttribute("xml:lang")||t.getAttribute("lang"):t.lang)return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===H},focus:function(e){return e===L.activeElement&&(!L.hasFocus||L.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!C.pseudos.empty(e)},header:function(e){return yt.test(e.nodeName)},input:function(e){return mt.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:c(function(){return[0]}),last:c(function(e,t){return[t-1]}),eq:c(function(e,t,n){return[0>n?n+t:n]}),even:c(function(e,t){for(var n=0;t>n;n+=2)e.push(n);return e}),odd:c(function(e,t){for(var n=1;t>n;n+=2)e.push(n);return e}),lt:c(function(e,t,n){for(var r=0>n?n+t:n;--r>=0;)e.push(r);return e}),gt:c(function(e,t,n){for(var r=0>n?n+t:n;t>++r;)e.push(r);return e})}};for(w in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})C.pseudos[w]=u(w);for(w in{submit:!0,reset:!0})C.pseudos[w]=l(w);S=a.compile=function(e,t){var n,r=[],i=[],o=U[e+" "];if(!o){for(t||(t=f(e)),n=t.length;n--;)o=y(t[n]),o[P]?r.push(o):i.push(o);o=U(e,v(i,r))}return o},C.pseudos.nth=C.pseudos.eq,C.filters=T.prototype=C.pseudos,C.setFilters=new T,D(),a.attr=st.attr,st.find=a,st.expr=a.selectors,st.expr[":"]=st.expr.pseudos,st.unique=a.uniqueSort,st.text=a.getText,st.isXMLDoc=a.isXML,st.contains=a.contains}(e);var Pt=/Until$/,Rt=/^(?:parents|prev(?:Until|All))/,Wt=/^.[^:#\[\.,]*$/,$t=st.expr.match.needsContext,It={children:!0,contents:!0,next:!0,prev:!0};st.fn.extend({find:function(e){var t,n,r;if("string"!=typeof e)return r=this,this.pushStack(st(e).filter(function(){for(t=0;r.length>t;t++)if(st.contains(r[t],this))return!0}));for(n=[],t=0;this.length>t;t++)st.find(e,this[t],n);return n=this.pushStack(st.unique(n)),n.selector=(this.selector?this.selector+" ":"")+e,n},has:function(e){var t,n=st(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++)if(st.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(f(this,e,!1))},filter:function(e){return this.pushStack(f(this,e,!0))},is:function(e){return!!e&&("string"==typeof e?$t.test(e)?st(e,this.context).index(this[0])>=0:st.filter(e,this).length>0:this.filter(e).length>0)},closest:function(e,t){for(var n,r=0,i=this.length,o=[],a=$t.test(e)||"string"!=typeof e?st(e,t||this.context):0;i>r;r++)for(n=this[r];n&&n.ownerDocument&&n!==t&&11!==n.nodeType;){if(a?a.index(n)>-1:st.find.matchesSelector(n,e)){o.push(n);break}n=n.parentNode}return this.pushStack(o.length>1?st.unique(o):o)},index:function(e){return e?"string"==typeof e?st.inArray(this[0],st(e)):st.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?st(e,t):st.makeArray(e&&e.nodeType?[e]:e),r=st.merge(this.get(),n);return this.pushStack(st.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),st.fn.andSelf=st.fn.addBack,st.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return st.dir(e,"parentNode")},parentsUntil:function(e,t,n){return st.dir(e,"parentNode",n)},next:function(e){return c(e,"nextSibling")},prev:function(e){return c(e,"previousSibling")
+},nextAll:function(e){return st.dir(e,"nextSibling")},prevAll:function(e){return st.dir(e,"previousSibling")},nextUntil:function(e,t,n){return st.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return st.dir(e,"previousSibling",n)},siblings:function(e){return st.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return st.sibling(e.firstChild)},contents:function(e){return st.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:st.merge([],e.childNodes)}},function(e,t){st.fn[e]=function(n,r){var i=st.map(this,t,n);return Pt.test(e)||(r=n),r&&"string"==typeof r&&(i=st.filter(r,i)),i=this.length>1&&!It[e]?st.unique(i):i,this.length>1&&Rt.test(e)&&(i=i.reverse()),this.pushStack(i)}}),st.extend({filter:function(e,t,n){return n&&(e=":not("+e+")"),1===t.length?st.find.matchesSelector(t[0],e)?[t[0]]:[]:st.find.matches(e,t)},dir:function(e,n,r){for(var i=[],o=e[n];o&&9!==o.nodeType&&(r===t||1!==o.nodeType||!st(o).is(r));)1===o.nodeType&&i.push(o),o=o[n];return i},sibling:function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});var zt="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",Xt=/ jQuery\d+="(?:null|\d+)"/g,Ut=RegExp("<(?:"+zt+")[\\s/>]","i"),Vt=/^\s+/,Yt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,Jt=/<([\w:]+)/,Gt=/
\s*$/g,on={option:[1,""," "],legend:[1,""," "],area:[1,""," "],param:[1,""," "],thead:[1,""],tr:[2,""],col:[2,""],td:[3,""],_default:st.support.htmlSerialize?[0,"",""]:[1,"X","
"]},an=p(V),sn=an.appendChild(V.createElement("div"));on.optgroup=on.option,on.tbody=on.tfoot=on.colgroup=on.caption=on.thead,on.th=on.td,st.fn.extend({text:function(e){return st.access(this,function(e){return e===t?st.text(this):this.empty().append((this[0]&&this[0].ownerDocument||V).createTextNode(e))},null,e,arguments.length)},wrapAll:function(e){if(st.isFunction(e))return this.each(function(t){st(this).wrapAll(e.call(this,t))});if(this[0]){var t=st(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){for(var e=this;e.firstChild&&1===e.firstChild.nodeType;)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return st.isFunction(e)?this.each(function(t){st(this).wrapInner(e.call(this,t))}):this.each(function(){var t=st(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=st.isFunction(e);return this.each(function(n){st(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){st.nodeName(this,"body")||st(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(e){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&this.appendChild(e)})},prepend:function(){return this.domManip(arguments,!0,function(e){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&this.insertBefore(e,this.firstChild)})},before:function(){return this.domManip(arguments,!1,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,!1,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){for(var n,r=0;null!=(n=this[r]);r++)(!e||st.filter(e,[n]).length>0)&&(t||1!==n.nodeType||st.cleanData(b(n)),n.parentNode&&(t&&st.contains(n.ownerDocument,n)&&m(b(n,"script")),n.parentNode.removeChild(n)));return this},empty:function(){for(var e,t=0;null!=(e=this[t]);t++){for(1===e.nodeType&&st.cleanData(b(e,!1));e.firstChild;)e.removeChild(e.firstChild);e.options&&st.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return st.clone(this,e,t)})},html:function(e){return st.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return 1===n.nodeType?n.innerHTML.replace(Xt,""):t;if(!("string"!=typeof e||Kt.test(e)||!st.support.htmlSerialize&&Ut.test(e)||!st.support.leadingWhitespace&&Vt.test(e)||on[(Jt.exec(e)||["",""])[1].toLowerCase()])){e=e.replace(Yt,"<$1>$2>");try{for(;i>r;r++)n=this[r]||{},1===n.nodeType&&(st.cleanData(b(n,!1)),n.innerHTML=e);n=0}catch(o){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(e){var t=st.isFunction(e);return t||"string"==typeof e||(e=st(e).not(this).detach()),this.domManip([e],!0,function(e){var t=this.nextSibling,n=this.parentNode;(n&&1===this.nodeType||11===this.nodeType)&&(st(this).remove(),t?t.parentNode.insertBefore(e,t):n.appendChild(e))})},detach:function(e){return this.remove(e,!0)},domManip:function(e,n,r){e=et.apply([],e);var i,o,a,s,u,l,c=0,f=this.length,p=this,m=f-1,y=e[0],v=st.isFunction(y);if(v||!(1>=f||"string"!=typeof y||st.support.checkClone)&&en.test(y))return this.each(function(i){var o=p.eq(i);v&&(e[0]=y.call(this,i,n?o.html():t)),o.domManip(e,n,r)});if(f&&(i=st.buildFragment(e,this[0].ownerDocument,!1,this),o=i.firstChild,1===i.childNodes.length&&(i=o),o)){for(n=n&&st.nodeName(o,"tr"),a=st.map(b(i,"script"),h),s=a.length;f>c;c++)u=i,c!==m&&(u=st.clone(u,!0,!0),s&&st.merge(a,b(u,"script"))),r.call(n&&st.nodeName(this[c],"table")?d(this[c],"tbody"):this[c],u,c);if(s)for(l=a[a.length-1].ownerDocument,st.map(a,g),c=0;s>c;c++)u=a[c],tn.test(u.type||"")&&!st._data(u,"globalEval")&&st.contains(l,u)&&(u.src?st.ajax({url:u.src,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):st.globalEval((u.text||u.textContent||u.innerHTML||"").replace(rn,"")));i=o=null}return this}}),st.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){st.fn[e]=function(e){for(var n,r=0,i=[],o=st(e),a=o.length-1;a>=r;r++)n=r===a?this:this.clone(!0),st(o[r])[t](n),tt.apply(i,n.get());return this.pushStack(i)}}),st.extend({clone:function(e,t,n){var r,i,o,a,s,u=st.contains(e.ownerDocument,e);if(st.support.html5Clone||st.isXMLDoc(e)||!Ut.test("<"+e.nodeName+">")?s=e.cloneNode(!0):(sn.innerHTML=e.outerHTML,sn.removeChild(s=sn.firstChild)),!(st.support.noCloneEvent&&st.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||st.isXMLDoc(e)))for(r=b(s),i=b(e),a=0;null!=(o=i[a]);++a)r[a]&&v(o,r[a]);if(t)if(n)for(i=i||b(e),r=r||b(s),a=0;null!=(o=i[a]);a++)y(o,r[a]);else y(e,s);return r=b(s,"script"),r.length>0&&m(r,!u&&b(e,"script")),r=i=o=null,s},buildFragment:function(e,t,n,r){for(var i,o,a,s,u,l,c,f=e.length,d=p(t),h=[],g=0;f>g;g++)if(o=e[g],o||0===o)if("object"===st.type(o))st.merge(h,o.nodeType?[o]:o);else if(Qt.test(o)){for(s=s||d.appendChild(t.createElement("div")),a=(Jt.exec(o)||["",""])[1].toLowerCase(),u=on[a]||on._default,s.innerHTML=u[1]+o.replace(Yt,"<$1>$2>")+u[2],c=u[0];c--;)s=s.lastChild;if(!st.support.leadingWhitespace&&Vt.test(o)&&h.push(t.createTextNode(Vt.exec(o)[0])),!st.support.tbody)for(o="table"!==a||Gt.test(o)?""!==u[1]||Gt.test(o)?0:s:s.firstChild,c=o&&o.childNodes.length;c--;)st.nodeName(l=o.childNodes[c],"tbody")&&!l.childNodes.length&&o.removeChild(l);for(st.merge(h,s.childNodes),s.textContent="";s.firstChild;)s.removeChild(s.firstChild);s=d.lastChild}else h.push(t.createTextNode(o));for(s&&d.removeChild(s),st.support.appendChecked||st.grep(b(h,"input"),x),g=0;o=h[g++];)if((!r||-1===st.inArray(o,r))&&(i=st.contains(o.ownerDocument,o),s=b(d.appendChild(o),"script"),i&&m(s),n))for(c=0;o=s[c++];)tn.test(o.type||"")&&n.push(o);return s=null,d},cleanData:function(e,n){for(var r,i,o,a,s=0,u=st.expando,l=st.cache,c=st.support.deleteExpando,f=st.event.special;null!=(o=e[s]);s++)if((n||st.acceptData(o))&&(i=o[u],r=i&&l[i])){if(r.events)for(a in r.events)f[a]?st.event.remove(o,a):st.removeEvent(o,a,r.handle);l[i]&&(delete l[i],c?delete o[u]:o.removeAttribute!==t?o.removeAttribute(u):o[u]=null,K.push(i))}}});var un,ln,cn,fn=/alpha\([^)]*\)/i,pn=/opacity\s*=\s*([^)]*)/,dn=/^(top|right|bottom|left)$/,hn=/^(none|table(?!-c[ea]).+)/,gn=/^margin/,mn=RegExp("^("+ut+")(.*)$","i"),yn=RegExp("^("+ut+")(?!px)[a-z%]+$","i"),vn=RegExp("^([+-])=("+ut+")","i"),bn={BODY:"block"},xn={position:"absolute",visibility:"hidden",display:"block"},Tn={letterSpacing:0,fontWeight:400},wn=["Top","Right","Bottom","Left"],Nn=["Webkit","O","Moz","ms"];st.fn.extend({css:function(e,n){return st.access(this,function(e,n,r){var i,o,a={},s=0;if(st.isArray(n)){for(i=ln(e),o=n.length;o>s;s++)a[n[s]]=st.css(e,n[s],!1,i);return a}return r!==t?st.style(e,n,r):st.css(e,n)},e,n,arguments.length>1)},show:function(){return N(this,!0)},hide:function(){return N(this)},toggle:function(e){var t="boolean"==typeof e;return this.each(function(){(t?e:w(this))?st(this).show():st(this).hide()})}}),st.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=un(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":st.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,u=st.camelCase(n),l=e.style;if(n=st.cssProps[u]||(st.cssProps[u]=T(l,u)),s=st.cssHooks[n]||st.cssHooks[u],r===t)return s&&"get"in s&&(o=s.get(e,!1,i))!==t?o:l[n];if(a=typeof r,"string"===a&&(o=vn.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(st.css(e,n)),a="number"),!(null==r||"number"===a&&isNaN(r)||("number"!==a||st.cssNumber[u]||(r+="px"),st.support.clearCloneStyle||""!==r||0!==n.indexOf("background")||(l[n]="inherit"),s&&"set"in s&&(r=s.set(e,r,i))===t)))try{l[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,u=st.camelCase(n);return n=st.cssProps[u]||(st.cssProps[u]=T(e.style,u)),s=st.cssHooks[n]||st.cssHooks[u],s&&"get"in s&&(o=s.get(e,!0,r)),o===t&&(o=un(e,n,i)),"normal"===o&&n in Tn&&(o=Tn[n]),r?(a=parseFloat(o),r===!0||st.isNumeric(a)?a||0:o):o},swap:function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i}}),e.getComputedStyle?(ln=function(t){return e.getComputedStyle(t,null)},un=function(e,n,r){var i,o,a,s=r||ln(e),u=s?s.getPropertyValue(n)||s[n]:t,l=e.style;return s&&(""!==u||st.contains(e.ownerDocument,e)||(u=st.style(e,n)),yn.test(u)&&gn.test(n)&&(i=l.width,o=l.minWidth,a=l.maxWidth,l.minWidth=l.maxWidth=l.width=u,u=s.width,l.width=i,l.minWidth=o,l.maxWidth=a)),u}):V.documentElement.currentStyle&&(ln=function(e){return e.currentStyle},un=function(e,n,r){var i,o,a,s=r||ln(e),u=s?s[n]:t,l=e.style;return null==u&&l&&l[n]&&(u=l[n]),yn.test(u)&&!dn.test(n)&&(i=l.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),l.left="fontSize"===n?"1em":u,u=l.pixelLeft+"px",l.left=i,a&&(o.left=a)),""===u?"auto":u}),st.each(["height","width"],function(e,n){st.cssHooks[n]={get:function(e,r,i){return r?0===e.offsetWidth&&hn.test(st.css(e,"display"))?st.swap(e,xn,function(){return E(e,n,i)}):E(e,n,i):t},set:function(e,t,r){var i=r&&ln(e);return C(e,t,r?k(e,n,r,st.support.boxSizing&&"border-box"===st.css(e,"boxSizing",!1,i),i):0)}}}),st.support.opacity||(st.cssHooks.opacity={get:function(e,t){return pn.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=st.isNumeric(t)?"alpha(opacity="+100*t+")":"",o=r&&r.filter||n.filter||"";n.zoom=1,(t>=1||""===t)&&""===st.trim(o.replace(fn,""))&&n.removeAttribute&&(n.removeAttribute("filter"),""===t||r&&!r.filter)||(n.filter=fn.test(o)?o.replace(fn,i):o+" "+i)}}),st(function(){st.support.reliableMarginRight||(st.cssHooks.marginRight={get:function(e,n){return n?st.swap(e,{display:"inline-block"},un,[e,"marginRight"]):t}}),!st.support.pixelPosition&&st.fn.position&&st.each(["top","left"],function(e,n){st.cssHooks[n]={get:function(e,r){return r?(r=un(e,n),yn.test(r)?st(e).position()[n]+"px":r):t}}})}),st.expr&&st.expr.filters&&(st.expr.filters.hidden=function(e){return 0===e.offsetWidth&&0===e.offsetHeight||!st.support.reliableHiddenOffsets&&"none"===(e.style&&e.style.display||st.css(e,"display"))},st.expr.filters.visible=function(e){return!st.expr.filters.hidden(e)}),st.each({margin:"",padding:"",border:"Width"},function(e,t){st.cssHooks[e+t]={expand:function(n){for(var r=0,i={},o="string"==typeof n?n.split(" "):[n];4>r;r++)i[e+wn[r]+t]=o[r]||o[r-2]||o[0];return i}},gn.test(e)||(st.cssHooks[e+t].set=C)});var Cn=/%20/g,kn=/\[\]$/,En=/\r?\n/g,Sn=/^(?:submit|button|image|reset)$/i,An=/^(?:input|select|textarea|keygen)/i;st.fn.extend({serialize:function(){return st.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=st.prop(this,"elements");return e?st.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!st(this).is(":disabled")&&An.test(this.nodeName)&&!Sn.test(e)&&(this.checked||!Zt.test(e))}).map(function(e,t){var n=st(this).val();return null==n?null:st.isArray(n)?st.map(n,function(e){return{name:t.name,value:e.replace(En,"\r\n")}}):{name:t.name,value:n.replace(En,"\r\n")}}).get()}}),st.param=function(e,n){var r,i=[],o=function(e,t){t=st.isFunction(t)?t():null==t?"":t,i[i.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};if(n===t&&(n=st.ajaxSettings&&st.ajaxSettings.traditional),st.isArray(e)||e.jquery&&!st.isPlainObject(e))st.each(e,function(){o(this.name,this.value)});else for(r in e)j(r,e[r],n,o);return i.join("&").replace(Cn,"+")};var jn,Dn,Ln=st.now(),Hn=/\?/,Mn=/#.*$/,qn=/([?&])_=[^&]*/,_n=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Fn=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,On=/^(?:GET|HEAD)$/,Bn=/^\/\//,Pn=/^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,Rn=st.fn.load,Wn={},$n={},In="*/".concat("*");try{Dn=Y.href}catch(zn){Dn=V.createElement("a"),Dn.href="",Dn=Dn.href}jn=Pn.exec(Dn.toLowerCase())||[],st.fn.load=function(e,n,r){if("string"!=typeof e&&Rn)return Rn.apply(this,arguments);var i,o,a,s=this,u=e.indexOf(" ");return u>=0&&(i=e.slice(u,e.length),e=e.slice(0,u)),st.isFunction(n)?(r=n,n=t):n&&"object"==typeof n&&(o="POST"),s.length>0&&st.ajax({url:e,type:o,dataType:"html",data:n}).done(function(e){a=arguments,s.html(i?st("").append(st.parseHTML(e)).find(i):e)}).complete(r&&function(e,t){s.each(r,a||[e.responseText,t,e])}),this},st.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){st.fn[t]=function(e){return this.on(t,e)}}),st.each(["get","post"],function(e,n){st[n]=function(e,r,i,o){return st.isFunction(r)&&(o=o||i,i=r,r=t),st.ajax({url:e,type:n,dataType:o,data:r,success:i})}}),st.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Dn,type:"GET",isLocal:Fn.test(jn[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":In,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":e.String,"text html":!0,"text json":st.parseJSON,"text xml":st.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?H(H(e,st.ajaxSettings),t):H(st.ajaxSettings,e)},ajaxPrefilter:D(Wn),ajaxTransport:D($n),ajax:function(e,n){function r(e,n,r,s){var l,f,v,b,T,N=n;2!==x&&(x=2,u&&clearTimeout(u),i=t,a=s||"",w.readyState=e>0?4:0,r&&(b=M(p,w,r)),e>=200&&300>e||304===e?(p.ifModified&&(T=w.getResponseHeader("Last-Modified"),T&&(st.lastModified[o]=T),T=w.getResponseHeader("etag"),T&&(st.etag[o]=T)),304===e?(l=!0,N="notmodified"):(l=q(p,b),N=l.state,f=l.data,v=l.error,l=!v)):(v=N,(e||!N)&&(N="error",0>e&&(e=0))),w.status=e,w.statusText=(n||N)+"",l?g.resolveWith(d,[f,N,w]):g.rejectWith(d,[w,N,v]),w.statusCode(y),y=t,c&&h.trigger(l?"ajaxSuccess":"ajaxError",[w,p,l?f:v]),m.fireWith(d,[w,N]),c&&(h.trigger("ajaxComplete",[w,p]),--st.active||st.event.trigger("ajaxStop")))}"object"==typeof e&&(n=e,e=t),n=n||{};var i,o,a,s,u,l,c,f,p=st.ajaxSetup({},n),d=p.context||p,h=p.context&&(d.nodeType||d.jquery)?st(d):st.event,g=st.Deferred(),m=st.Callbacks("once memory"),y=p.statusCode||{},v={},b={},x=0,T="canceled",w={readyState:0,getResponseHeader:function(e){var t;if(2===x){if(!s)for(s={};t=_n.exec(a);)s[t[1].toLowerCase()]=t[2];t=s[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===x?a:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return x||(e=b[n]=b[n]||e,v[e]=t),this},overrideMimeType:function(e){return x||(p.mimeType=e),this},statusCode:function(e){var t;if(e)if(2>x)for(t in e)y[t]=[y[t],e[t]];else w.always(e[w.status]);return this},abort:function(e){var t=e||T;return i&&i.abort(t),r(0,t),this}};if(g.promise(w).complete=m.add,w.success=w.done,w.error=w.fail,p.url=((e||p.url||Dn)+"").replace(Mn,"").replace(Bn,jn[1]+"//"),p.type=n.method||n.type||p.method||p.type,p.dataTypes=st.trim(p.dataType||"*").toLowerCase().match(lt)||[""],null==p.crossDomain&&(l=Pn.exec(p.url.toLowerCase()),p.crossDomain=!(!l||l[1]===jn[1]&&l[2]===jn[2]&&(l[3]||("http:"===l[1]?80:443))==(jn[3]||("http:"===jn[1]?80:443)))),p.data&&p.processData&&"string"!=typeof p.data&&(p.data=st.param(p.data,p.traditional)),L(Wn,p,n,w),2===x)return w;c=p.global,c&&0===st.active++&&st.event.trigger("ajaxStart"),p.type=p.type.toUpperCase(),p.hasContent=!On.test(p.type),o=p.url,p.hasContent||(p.data&&(o=p.url+=(Hn.test(o)?"&":"?")+p.data,delete p.data),p.cache===!1&&(p.url=qn.test(o)?o.replace(qn,"$1_="+Ln++):o+(Hn.test(o)?"&":"?")+"_="+Ln++)),p.ifModified&&(st.lastModified[o]&&w.setRequestHeader("If-Modified-Since",st.lastModified[o]),st.etag[o]&&w.setRequestHeader("If-None-Match",st.etag[o])),(p.data&&p.hasContent&&p.contentType!==!1||n.contentType)&&w.setRequestHeader("Content-Type",p.contentType),w.setRequestHeader("Accept",p.dataTypes[0]&&p.accepts[p.dataTypes[0]]?p.accepts[p.dataTypes[0]]+("*"!==p.dataTypes[0]?", "+In+"; q=0.01":""):p.accepts["*"]);for(f in p.headers)w.setRequestHeader(f,p.headers[f]);if(p.beforeSend&&(p.beforeSend.call(d,w,p)===!1||2===x))return w.abort();T="abort";for(f in{success:1,error:1,complete:1})w[f](p[f]);if(i=L($n,p,n,w)){w.readyState=1,c&&h.trigger("ajaxSend",[w,p]),p.async&&p.timeout>0&&(u=setTimeout(function(){w.abort("timeout")},p.timeout));try{x=1,i.send(v,r)}catch(N){if(!(2>x))throw N;r(-1,N)}}else r(-1,"No Transport");return w},getScript:function(e,n){return st.get(e,t,n,"script")},getJSON:function(e,t,n){return st.get(e,t,n,"json")}}),st.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(e){return st.globalEval(e),e}}}),st.ajaxPrefilter("script",function(e){e.cache===t&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),st.ajaxTransport("script",function(e){if(e.crossDomain){var n,r=V.head||st("head")[0]||V.documentElement;return{send:function(t,i){n=V.createElement("script"),n.async=!0,e.scriptCharset&&(n.charset=e.scriptCharset),n.src=e.url,n.onload=n.onreadystatechange=function(e,t){(t||!n.readyState||/loaded|complete/.test(n.readyState))&&(n.onload=n.onreadystatechange=null,n.parentNode&&n.parentNode.removeChild(n),n=null,t||i(200,"success"))},r.insertBefore(n,r.firstChild)},abort:function(){n&&n.onload(t,!0)}}}});var Xn=[],Un=/(=)\?(?=&|$)|\?\?/;st.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Xn.pop()||st.expando+"_"+Ln++;return this[e]=!0,e}}),st.ajaxPrefilter("json jsonp",function(n,r,i){var o,a,s,u=n.jsonp!==!1&&(Un.test(n.url)?"url":"string"==typeof n.data&&!(n.contentType||"").indexOf("application/x-www-form-urlencoded")&&Un.test(n.data)&&"data");return u||"jsonp"===n.dataTypes[0]?(o=n.jsonpCallback=st.isFunction(n.jsonpCallback)?n.jsonpCallback():n.jsonpCallback,u?n[u]=n[u].replace(Un,"$1"+o):n.jsonp!==!1&&(n.url+=(Hn.test(n.url)?"&":"?")+n.jsonp+"="+o),n.converters["script json"]=function(){return s||st.error(o+" was not called"),s[0]},n.dataTypes[0]="json",a=e[o],e[o]=function(){s=arguments},i.always(function(){e[o]=a,n[o]&&(n.jsonpCallback=r.jsonpCallback,Xn.push(o)),s&&st.isFunction(a)&&a(s[0]),s=a=t}),"script"):t});var Vn,Yn,Jn=0,Gn=e.ActiveXObject&&function(){var e;for(e in Vn)Vn[e](t,!0)};st.ajaxSettings.xhr=e.ActiveXObject?function(){return!this.isLocal&&_()||F()}:_,Yn=st.ajaxSettings.xhr(),st.support.cors=!!Yn&&"withCredentials"in Yn,Yn=st.support.ajax=!!Yn,Yn&&st.ajaxTransport(function(n){if(!n.crossDomain||st.support.cors){var r;return{send:function(i,o){var a,s,u=n.xhr();if(n.username?u.open(n.type,n.url,n.async,n.username,n.password):u.open(n.type,n.url,n.async),n.xhrFields)for(s in n.xhrFields)u[s]=n.xhrFields[s];n.mimeType&&u.overrideMimeType&&u.overrideMimeType(n.mimeType),n.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");try{for(s in i)u.setRequestHeader(s,i[s])}catch(l){}u.send(n.hasContent&&n.data||null),r=function(e,i){var s,l,c,f,p;try{if(r&&(i||4===u.readyState))if(r=t,a&&(u.onreadystatechange=st.noop,Gn&&delete Vn[a]),i)4!==u.readyState&&u.abort();else{f={},s=u.status,p=u.responseXML,c=u.getAllResponseHeaders(),p&&p.documentElement&&(f.xml=p),"string"==typeof u.responseText&&(f.text=u.responseText);try{l=u.statusText}catch(d){l=""}s||!n.isLocal||n.crossDomain?1223===s&&(s=204):s=f.text?200:404}}catch(h){i||o(-1,h)}f&&o(s,l,f,c)},n.async?4===u.readyState?setTimeout(r):(a=++Jn,Gn&&(Vn||(Vn={},st(e).unload(Gn)),Vn[a]=r),u.onreadystatechange=r):r()},abort:function(){r&&r(t,!0)}}}});var Qn,Kn,Zn=/^(?:toggle|show|hide)$/,er=RegExp("^(?:([+-])=|)("+ut+")([a-z%]*)$","i"),tr=/queueHooks$/,nr=[W],rr={"*":[function(e,t){var n,r,i=this.createTween(e,t),o=er.exec(t),a=i.cur(),s=+a||0,u=1,l=20;if(o){if(n=+o[2],r=o[3]||(st.cssNumber[e]?"":"px"),"px"!==r&&s){s=st.css(i.elem,e,!0)||n||1;do u=u||".5",s/=u,st.style(i.elem,e,s+r);while(u!==(u=i.cur()/a)&&1!==u&&--l)}i.unit=r,i.start=s,i.end=o[1]?s+(o[1]+1)*n:n}return i}]};st.Animation=st.extend(P,{tweener:function(e,t){st.isFunction(e)?(t=e,e=["*"]):e=e.split(" ");for(var n,r=0,i=e.length;i>r;r++)n=e[r],rr[n]=rr[n]||[],rr[n].unshift(t)},prefilter:function(e,t){t?nr.unshift(e):nr.push(e)}}),st.Tween=$,$.prototype={constructor:$,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||"swing",this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(st.cssNumber[n]?"":"px")},cur:function(){var e=$.propHooks[this.prop];return e&&e.get?e.get(this):$.propHooks._default.get(this)},run:function(e){var t,n=$.propHooks[this.prop];return this.pos=t=this.options.duration?st.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):$.propHooks._default.set(this),this}},$.prototype.init.prototype=$.prototype,$.propHooks={_default:{get:function(e){var t;return null==e.elem[e.prop]||e.elem.style&&null!=e.elem.style[e.prop]?(t=st.css(e.elem,e.prop,"auto"),t&&"auto"!==t?t:0):e.elem[e.prop]},set:function(e){st.fx.step[e.prop]?st.fx.step[e.prop](e):e.elem.style&&(null!=e.elem.style[st.cssProps[e.prop]]||st.cssHooks[e.prop])?st.style(e.elem,e.prop,e.now+e.unit):e.elem[e.prop]=e.now}}},$.propHooks.scrollTop=$.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},st.each(["toggle","show","hide"],function(e,t){var n=st.fn[t];st.fn[t]=function(e,r,i){return null==e||"boolean"==typeof e?n.apply(this,arguments):this.animate(I(t,!0),e,r,i)}}),st.fn.extend({fadeTo:function(e,t,n,r){return this.filter(w).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=st.isEmptyObject(e),o=st.speed(t,n,r),a=function(){var t=P(this,st.extend({},e),o);a.finish=function(){t.stop(!0)},(i||st._data(this,"finish"))&&t.stop(!0)};return a.finish=a,i||o.queue===!1?this.each(a):this.queue(o.queue,a)},stop:function(e,n,r){var i=function(e){var t=e.stop;delete e.stop,t(r)};return"string"!=typeof e&&(r=n,n=e,e=t),n&&e!==!1&&this.queue(e||"fx",[]),this.each(function(){var t=!0,n=null!=e&&e+"queueHooks",o=st.timers,a=st._data(this);if(n)a[n]&&a[n].stop&&i(a[n]);else for(n in a)a[n]&&a[n].stop&&tr.test(n)&&i(a[n]);for(n=o.length;n--;)o[n].elem!==this||null!=e&&o[n].queue!==e||(o[n].anim.stop(r),t=!1,o.splice(n,1));(t||!r)&&st.dequeue(this,e)})},finish:function(e){return e!==!1&&(e=e||"fx"),this.each(function(){var t,n=st._data(this),r=n[e+"queue"],i=n[e+"queueHooks"],o=st.timers,a=r?r.length:0;for(n.finish=!0,st.queue(this,e,[]),i&&i.cur&&i.cur.finish&&i.cur.finish.call(this),t=o.length;t--;)o[t].elem===this&&o[t].queue===e&&(o[t].anim.stop(!0),o.splice(t,1));for(t=0;a>t;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}}),st.each({slideDown:I("show"),slideUp:I("hide"),slideToggle:I("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){st.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),st.speed=function(e,t,n){var r=e&&"object"==typeof e?st.extend({},e):{complete:n||!n&&t||st.isFunction(e)&&e,duration:e,easing:n&&t||t&&!st.isFunction(t)&&t};return r.duration=st.fx.off?0:"number"==typeof r.duration?r.duration:r.duration in st.fx.speeds?st.fx.speeds[r.duration]:st.fx.speeds._default,(null==r.queue||r.queue===!0)&&(r.queue="fx"),r.old=r.complete,r.complete=function(){st.isFunction(r.old)&&r.old.call(this),r.queue&&st.dequeue(this,r.queue)},r},st.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2}},st.timers=[],st.fx=$.prototype.init,st.fx.tick=function(){var e,n=st.timers,r=0;for(Qn=st.now();n.length>r;r++)e=n[r],e()||n[r]!==e||n.splice(r--,1);n.length||st.fx.stop(),Qn=t},st.fx.timer=function(e){e()&&st.timers.push(e)&&st.fx.start()},st.fx.interval=13,st.fx.start=function(){Kn||(Kn=setInterval(st.fx.tick,st.fx.interval))},st.fx.stop=function(){clearInterval(Kn),Kn=null},st.fx.speeds={slow:600,fast:200,_default:400},st.fx.step={},st.expr&&st.expr.filters&&(st.expr.filters.animated=function(e){return st.grep(st.timers,function(t){return e===t.elem}).length}),st.fn.offset=function(e){if(arguments.length)return e===t?this:this.each(function(t){st.offset.setOffset(this,e,t)});var n,r,i={top:0,left:0},o=this[0],a=o&&o.ownerDocument;if(a)return n=a.documentElement,st.contains(n,o)?(o.getBoundingClientRect!==t&&(i=o.getBoundingClientRect()),r=z(a),{top:i.top+(r.pageYOffset||n.scrollTop)-(n.clientTop||0),left:i.left+(r.pageXOffset||n.scrollLeft)-(n.clientLeft||0)}):i},st.offset={setOffset:function(e,t,n){var r=st.css(e,"position");"static"===r&&(e.style.position="relative");var i,o,a=st(e),s=a.offset(),u=st.css(e,"top"),l=st.css(e,"left"),c=("absolute"===r||"fixed"===r)&&st.inArray("auto",[u,l])>-1,f={},p={};c?(p=a.position(),i=p.top,o=p.left):(i=parseFloat(u)||0,o=parseFloat(l)||0),st.isFunction(t)&&(t=t.call(e,n,s)),null!=t.top&&(f.top=t.top-s.top+i),null!=t.left&&(f.left=t.left-s.left+o),"using"in t?t.using.call(e,f):a.css(f)}},st.fn.extend({position:function(){if(this[0]){var e,t,n={top:0,left:0},r=this[0];return"fixed"===st.css(r,"position")?t=r.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),st.nodeName(e[0],"html")||(n=e.offset()),n.top+=st.css(e[0],"borderTopWidth",!0),n.left+=st.css(e[0],"borderLeftWidth",!0)),{top:t.top-n.top-st.css(r,"marginTop",!0),left:t.left-n.left-st.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){for(var e=this.offsetParent||V.documentElement;e&&!st.nodeName(e,"html")&&"static"===st.css(e,"position");)e=e.offsetParent;return e||V.documentElement})}}),st.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,n){var r=/Y/.test(n);st.fn[e]=function(i){return st.access(this,function(e,i,o){var a=z(e);return o===t?a?n in a?a[n]:a.document.documentElement[i]:e[i]:(a?a.scrollTo(r?st(a).scrollLeft():o,r?o:st(a).scrollTop()):e[i]=o,t)},e,i,arguments.length,null)}}),st.each({Height:"height",Width:"width"},function(e,n){st.each({padding:"inner"+e,content:n,"":"outer"+e},function(r,i){st.fn[i]=function(i,o){var a=arguments.length&&(r||"boolean"!=typeof i),s=r||(i===!0||o===!0?"margin":"border");return st.access(this,function(n,r,i){var o;return st.isWindow(n)?n.document.documentElement["client"+e]:9===n.nodeType?(o=n.documentElement,Math.max(n.body["scroll"+e],o["scroll"+e],n.body["offset"+e],o["offset"+e],o["client"+e])):i===t?st.css(n,r,s):st.style(n,r,i,s)},n,a?i:t,a,null)}})}),e.jQuery=e.$=st,"function"==typeof define&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return st})})(window);
+//@ sourceMappingURL=jquery.min.map
\ No newline at end of file
diff --git a/js/fancyBox/lib/jquery.mousewheel-3.0.6.pack.js b/js/fancyBox/lib/jquery.mousewheel-3.0.6.pack.js
new file mode 100644
index 0000000..e39a83a
--- /dev/null
+++ b/js/fancyBox/lib/jquery.mousewheel-3.0.6.pack.js
@@ -0,0 +1,13 @@
+/*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net)
+ * Licensed under the MIT License (LICENSE.txt).
+ *
+ * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
+ * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
+ * Thanks to: Seamus Leahy for adding deltaX and deltaY
+ *
+ * Version: 3.0.6
+ *
+ * Requires: 1.2.2+
+ */
+(function(d){function e(a){var b=a||window.event,c=[].slice.call(arguments,1),f=0,e=0,g=0,a=d.event.fix(b);a.type="mousewheel";b.wheelDelta&&(f=b.wheelDelta/120);b.detail&&(f=-b.detail/3);g=f;b.axis!==void 0&&b.axis===b.HORIZONTAL_AXIS&&(g=0,e=-1*f);b.wheelDeltaY!==void 0&&(g=b.wheelDeltaY/120);b.wheelDeltaX!==void 0&&(e=-1*b.wheelDeltaX/120);c.unshift(a,f,e,g);return(d.event.dispatch||d.event.handle).apply(this,c)}var c=["DOMMouseScroll","mousewheel"];if(d.event.fixHooks)for(var h=c.length;h;)d.event.fixHooks[c[--h]]=
+d.event.mouseHooks;d.event.special.mousewheel={setup:function(){if(this.addEventListener)for(var a=c.length;a;)this.addEventListener(c[--a],e,false);else this.onmousewheel=e},teardown:function(){if(this.removeEventListener)for(var a=c.length;a;)this.removeEventListener(c[--a],e,false);else this.onmousewheel=null}};d.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})})(jQuery);
\ No newline at end of file
diff --git a/js/fancyBox/source/blank.gif b/js/fancyBox/source/blank.gif
new file mode 100644
index 0000000..35d42e8
Binary files /dev/null and b/js/fancyBox/source/blank.gif differ
diff --git a/js/fancyBox/source/fancybox_loading.gif b/js/fancyBox/source/fancybox_loading.gif
new file mode 100644
index 0000000..a03a40c
Binary files /dev/null and b/js/fancyBox/source/fancybox_loading.gif differ
diff --git a/js/fancyBox/source/fancybox_loading@2x.gif b/js/fancyBox/source/fancybox_loading@2x.gif
new file mode 100644
index 0000000..9205aeb
Binary files /dev/null and b/js/fancyBox/source/fancybox_loading@2x.gif differ
diff --git a/js/fancyBox/source/fancybox_overlay.png b/js/fancyBox/source/fancybox_overlay.png
new file mode 100644
index 0000000..a439139
Binary files /dev/null and b/js/fancyBox/source/fancybox_overlay.png differ
diff --git a/js/fancyBox/source/fancybox_sprite.png b/js/fancyBox/source/fancybox_sprite.png
new file mode 100644
index 0000000..fd8d5ca
Binary files /dev/null and b/js/fancyBox/source/fancybox_sprite.png differ
diff --git a/js/fancyBox/source/fancybox_sprite@2x.png b/js/fancyBox/source/fancybox_sprite@2x.png
new file mode 100644
index 0000000..d0e4779
Binary files /dev/null and b/js/fancyBox/source/fancybox_sprite@2x.png differ
diff --git a/js/fancyBox/source/helpers/fancybox_buttons.png b/js/fancyBox/source/helpers/fancybox_buttons.png
new file mode 100644
index 0000000..0787207
Binary files /dev/null and b/js/fancyBox/source/helpers/fancybox_buttons.png differ
diff --git a/js/fancyBox/source/helpers/jquery.fancybox-buttons.css b/js/fancyBox/source/helpers/jquery.fancybox-buttons.css
new file mode 100644
index 0000000..a26273a
--- /dev/null
+++ b/js/fancyBox/source/helpers/jquery.fancybox-buttons.css
@@ -0,0 +1,97 @@
+#fancybox-buttons {
+ position: fixed;
+ left: 0;
+ width: 100%;
+ z-index: 8050;
+}
+
+#fancybox-buttons.top {
+ top: 10px;
+}
+
+#fancybox-buttons.bottom {
+ bottom: 10px;
+}
+
+#fancybox-buttons ul {
+ display: block;
+ width: 166px;
+ height: 30px;
+ margin: 0 auto;
+ padding: 0;
+ list-style: none;
+ border: 1px solid #111;
+ border-radius: 3px;
+ -webkit-box-shadow: inset 0 0 0 1px rgba(255,255,255,.05);
+ -moz-box-shadow: inset 0 0 0 1px rgba(255,255,255,.05);
+ box-shadow: inset 0 0 0 1px rgba(255,255,255,.05);
+ background: rgb(50,50,50);
+ background: -moz-linear-gradient(top, rgb(68,68,68) 0%, rgb(52,52,52) 50%, rgb(41,41,41) 50%, rgb(51,51,51) 100%);
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgb(68,68,68)), color-stop(50%,rgb(52,52,52)), color-stop(50%,rgb(41,41,41)), color-stop(100%,rgb(51,51,51)));
+ background: -webkit-linear-gradient(top, rgb(68,68,68) 0%,rgb(52,52,52) 50%,rgb(41,41,41) 50%,rgb(51,51,51) 100%);
+ background: -o-linear-gradient(top, rgb(68,68,68) 0%,rgb(52,52,52) 50%,rgb(41,41,41) 50%,rgb(51,51,51) 100%);
+ background: -ms-linear-gradient(top, rgb(68,68,68) 0%,rgb(52,52,52) 50%,rgb(41,41,41) 50%,rgb(51,51,51) 100%);
+ background: linear-gradient(top, rgb(68,68,68) 0%,rgb(52,52,52) 50%,rgb(41,41,41) 50%,rgb(51,51,51) 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#444444', endColorstr='#222222',GradientType=0 );
+}
+
+#fancybox-buttons ul li {
+ float: left;
+ margin: 0;
+ padding: 0;
+}
+
+#fancybox-buttons a {
+ display: block;
+ width: 30px;
+ height: 30px;
+ text-indent: -9999px;
+ background-color: transparent;
+ background-image: url('fancybox_buttons.png');
+ background-repeat: no-repeat;
+ outline: none;
+ opacity: 0.8;
+}
+
+#fancybox-buttons a:hover {
+ opacity: 1;
+}
+
+#fancybox-buttons a.btnPrev {
+ background-position: 5px 0;
+}
+
+#fancybox-buttons a.btnNext {
+ background-position: -33px 0;
+ border-right: 1px solid #3e3e3e;
+}
+
+#fancybox-buttons a.btnPlay {
+ background-position: 0 -30px;
+}
+
+#fancybox-buttons a.btnPlayOn {
+ background-position: -30px -30px;
+}
+
+#fancybox-buttons a.btnToggle {
+ background-position: 3px -60px;
+ border-left: 1px solid #111;
+ border-right: 1px solid #3e3e3e;
+ width: 35px
+}
+
+#fancybox-buttons a.btnToggleOn {
+ background-position: -27px -60px;
+}
+
+#fancybox-buttons a.btnClose {
+ border-left: 1px solid #111;
+ width: 35px;
+ background-position: -56px 0px;
+}
+
+#fancybox-buttons a.btnDisabled {
+ opacity : 0.4;
+ cursor: default;
+}
\ No newline at end of file
diff --git a/js/fancyBox/source/helpers/jquery.fancybox-buttons.js b/js/fancyBox/source/helpers/jquery.fancybox-buttons.js
new file mode 100644
index 0000000..fd8b955
--- /dev/null
+++ b/js/fancyBox/source/helpers/jquery.fancybox-buttons.js
@@ -0,0 +1,122 @@
+ /*!
+ * Buttons helper for fancyBox
+ * version: 1.0.5 (Mon, 15 Oct 2012)
+ * @requires fancyBox v2.0 or later
+ *
+ * Usage:
+ * $(".fancybox").fancybox({
+ * helpers : {
+ * buttons: {
+ * position : 'top'
+ * }
+ * }
+ * });
+ *
+ */
+(function ($) {
+ //Shortcut for fancyBox object
+ var F = $.fancybox;
+
+ //Add helper object
+ F.helpers.buttons = {
+ defaults : {
+ skipSingle : false, // disables if gallery contains single image
+ position : 'top', // 'top' or 'bottom'
+ tpl : '
'
+ },
+
+ list : null,
+ buttons: null,
+
+ beforeLoad: function (opts, obj) {
+ //Remove self if gallery do not have at least two items
+
+ if (opts.skipSingle && obj.group.length < 2) {
+ obj.helpers.buttons = false;
+ obj.closeBtn = true;
+
+ return;
+ }
+
+ //Increase top margin to give space for buttons
+ obj.margin[ opts.position === 'bottom' ? 2 : 0 ] += 30;
+ },
+
+ onPlayStart: function () {
+ if (this.buttons) {
+ this.buttons.play.attr('title', 'Pause slideshow').addClass('btnPlayOn');
+ }
+ },
+
+ onPlayEnd: function () {
+ if (this.buttons) {
+ this.buttons.play.attr('title', 'Start slideshow').removeClass('btnPlayOn');
+ }
+ },
+
+ afterShow: function (opts, obj) {
+ var buttons = this.buttons;
+
+ if (!buttons) {
+ this.list = $(opts.tpl).addClass(opts.position).appendTo('body');
+
+ buttons = {
+ prev : this.list.find('.btnPrev').click( F.prev ),
+ next : this.list.find('.btnNext').click( F.next ),
+ play : this.list.find('.btnPlay').click( F.play ),
+ toggle : this.list.find('.btnToggle').click( F.toggle ),
+ close : this.list.find('.btnClose').click( F.close )
+ }
+ }
+
+ //Prev
+ if (obj.index > 0 || obj.loop) {
+ buttons.prev.removeClass('btnDisabled');
+ } else {
+ buttons.prev.addClass('btnDisabled');
+ }
+
+ //Next / Play
+ if (obj.loop || obj.index < obj.group.length - 1) {
+ buttons.next.removeClass('btnDisabled');
+ buttons.play.removeClass('btnDisabled');
+
+ } else {
+ buttons.next.addClass('btnDisabled');
+ buttons.play.addClass('btnDisabled');
+ }
+
+ this.buttons = buttons;
+
+ this.onUpdate(opts, obj);
+ },
+
+ onUpdate: function (opts, obj) {
+ var toggle;
+
+ if (!this.buttons) {
+ return;
+ }
+
+ toggle = this.buttons.toggle.removeClass('btnDisabled btnToggleOn');
+
+ //Size toggle button
+ if (obj.canShrink) {
+ toggle.addClass('btnToggleOn');
+
+ } else if (!obj.canExpand) {
+ toggle.addClass('btnDisabled');
+ }
+ },
+
+ beforeClose: function () {
+ if (this.list) {
+ this.list.remove();
+ }
+
+ this.list = null;
+ this.buttons = null;
+ }
+ };
+
+}(jQuery));
diff --git a/js/fancyBox/source/helpers/jquery.fancybox-media.js b/js/fancyBox/source/helpers/jquery.fancybox-media.js
new file mode 100644
index 0000000..3584c8a
--- /dev/null
+++ b/js/fancyBox/source/helpers/jquery.fancybox-media.js
@@ -0,0 +1,199 @@
+/*!
+ * Media helper for fancyBox
+ * version: 1.0.6 (Fri, 14 Jun 2013)
+ * @requires fancyBox v2.0 or later
+ *
+ * Usage:
+ * $(".fancybox").fancybox({
+ * helpers : {
+ * media: true
+ * }
+ * });
+ *
+ * Set custom URL parameters:
+ * $(".fancybox").fancybox({
+ * helpers : {
+ * media: {
+ * youtube : {
+ * params : {
+ * autoplay : 0
+ * }
+ * }
+ * }
+ * }
+ * });
+ *
+ * Or:
+ * $(".fancybox").fancybox({,
+ * helpers : {
+ * media: true
+ * },
+ * youtube : {
+ * autoplay: 0
+ * }
+ * });
+ *
+ * Supports:
+ *
+ * Youtube
+ * http://www.youtube.com/watch?v=opj24KnzrWo
+ * http://www.youtube.com/embed/opj24KnzrWo
+ * http://youtu.be/opj24KnzrWo
+ * http://www.youtube-nocookie.com/embed/opj24KnzrWo
+ * Vimeo
+ * http://vimeo.com/40648169
+ * http://vimeo.com/channels/staffpicks/38843628
+ * http://vimeo.com/groups/surrealism/videos/36516384
+ * http://player.vimeo.com/video/45074303
+ * Metacafe
+ * http://www.metacafe.com/watch/7635964/dr_seuss_the_lorax_movie_trailer/
+ * http://www.metacafe.com/watch/7635964/
+ * Dailymotion
+ * http://www.dailymotion.com/video/xoytqh_dr-seuss-the-lorax-premiere_people
+ * Twitvid
+ * http://twitvid.com/QY7MD
+ * Twitpic
+ * http://twitpic.com/7p93st
+ * Instagram
+ * http://instagr.am/p/IejkuUGxQn/
+ * http://instagram.com/p/IejkuUGxQn/
+ * Google maps
+ * http://maps.google.com/maps?q=Eiffel+Tower,+Avenue+Gustave+Eiffel,+Paris,+France&t=h&z=17
+ * http://maps.google.com/?ll=48.857995,2.294297&spn=0.007666,0.021136&t=m&z=16
+ * http://maps.google.com/?ll=48.859463,2.292626&spn=0.000965,0.002642&t=m&z=19&layer=c&cbll=48.859524,2.292532&panoid=YJ0lq28OOy3VT2IqIuVY0g&cbp=12,151.58,,0,-15.56
+ */
+(function ($) {
+ "use strict";
+
+ //Shortcut for fancyBox object
+ var F = $.fancybox,
+ format = function( url, rez, params ) {
+ params = params || '';
+
+ if ( $.type( params ) === "object" ) {
+ params = $.param(params, true);
+ }
+
+ $.each(rez, function(key, value) {
+ url = url.replace( '$' + key, value || '' );
+ });
+
+ if (params.length) {
+ url += ( url.indexOf('?') > 0 ? '&' : '?' ) + params;
+ }
+
+ return url;
+ };
+
+ //Add helper object
+ F.helpers.media = {
+ defaults : {
+ youtube : {
+ matcher : /(youtube\.com|youtu\.be|youtube-nocookie\.com)\/(watch\?v=|v\/|u\/|embed\/?)?(videoseries\?list=(.*)|[\w-]{11}|\?listType=(.*)&list=(.*)).*/i,
+ params : {
+ autoplay : 1,
+ autohide : 1,
+ fs : 1,
+ rel : 0,
+ hd : 1,
+ wmode : 'opaque',
+ enablejsapi : 1
+ },
+ type : 'iframe',
+ url : '//www.youtube.com/embed/$3'
+ },
+ vimeo : {
+ matcher : /(?:vimeo(?:pro)?.com)\/(?:[^\d]+)?(\d+)(?:.*)/,
+ params : {
+ autoplay : 1,
+ hd : 1,
+ show_title : 1,
+ show_byline : 1,
+ show_portrait : 0,
+ fullscreen : 1
+ },
+ type : 'iframe',
+ url : '//player.vimeo.com/video/$1'
+ },
+ metacafe : {
+ matcher : /metacafe.com\/(?:watch|fplayer)\/([\w\-]{1,10})/,
+ params : {
+ autoPlay : 'yes'
+ },
+ type : 'swf',
+ url : function( rez, params, obj ) {
+ obj.swf.flashVars = 'playerVars=' + $.param( params, true );
+
+ return '//www.metacafe.com/fplayer/' + rez[1] + '/.swf';
+ }
+ },
+ dailymotion : {
+ matcher : /dailymotion.com\/video\/(.*)\/?(.*)/,
+ params : {
+ additionalInfos : 0,
+ autoStart : 1
+ },
+ type : 'swf',
+ url : '//www.dailymotion.com/swf/video/$1'
+ },
+ twitvid : {
+ matcher : /twitvid\.com\/([a-zA-Z0-9_\-\?\=]+)/i,
+ params : {
+ autoplay : 0
+ },
+ type : 'iframe',
+ url : '//www.twitvid.com/embed.php?guid=$1'
+ },
+ twitpic : {
+ matcher : /twitpic\.com\/(?!(?:place|photos|events)\/)([a-zA-Z0-9\?\=\-]+)/i,
+ type : 'image',
+ url : '//twitpic.com/show/full/$1/'
+ },
+ instagram : {
+ matcher : /(instagr\.am|instagram\.com)\/p\/([a-zA-Z0-9_\-]+)\/?/i,
+ type : 'image',
+ url : '//$1/p/$2/media/?size=l'
+ },
+ google_maps : {
+ matcher : /maps\.google\.([a-z]{2,3}(\.[a-z]{2})?)\/(\?ll=|maps\?)(.*)/i,
+ type : 'iframe',
+ url : function( rez ) {
+ return '//maps.google.' + rez[1] + '/' + rez[3] + '' + rez[4] + '&output=' + (rez[4].indexOf('layer=c') > 0 ? 'svembed' : 'embed');
+ }
+ }
+ },
+
+ beforeLoad : function(opts, obj) {
+ var url = obj.href || '',
+ type = false,
+ what,
+ item,
+ rez,
+ params;
+
+ for (what in opts) {
+ if (opts.hasOwnProperty(what)) {
+ item = opts[ what ];
+ rez = url.match( item.matcher );
+
+ if (rez) {
+ type = item.type;
+ params = $.extend(true, {}, item.params, obj[ what ] || ($.isPlainObject(opts[ what ]) ? opts[ what ].params : null));
+
+ url = $.type( item.url ) === "function" ? item.url.call( this, rez, params, obj ) : format( item.url, rez, params );
+
+ break;
+ }
+ }
+ }
+
+ if (type) {
+ obj.href = url;
+ obj.type = type;
+
+ obj.autoHeight = false;
+ }
+ }
+ };
+
+}(jQuery));
\ No newline at end of file
diff --git a/js/fancyBox/source/helpers/jquery.fancybox-thumbs.css b/js/fancyBox/source/helpers/jquery.fancybox-thumbs.css
new file mode 100644
index 0000000..63d2943
--- /dev/null
+++ b/js/fancyBox/source/helpers/jquery.fancybox-thumbs.css
@@ -0,0 +1,55 @@
+#fancybox-thumbs {
+ position: fixed;
+ left: 0;
+ width: 100%;
+ overflow: hidden;
+ z-index: 8050;
+}
+
+#fancybox-thumbs.bottom {
+ bottom: 2px;
+}
+
+#fancybox-thumbs.top {
+ top: 2px;
+}
+
+#fancybox-thumbs ul {
+ position: relative;
+ list-style: none;
+ margin: 0;
+ padding: 0;
+}
+
+#fancybox-thumbs ul li {
+ float: left;
+ padding: 1px;
+ opacity: 0.5;
+}
+
+#fancybox-thumbs ul li.active {
+ opacity: 0.75;
+ padding: 0;
+ border: 1px solid #fff;
+}
+
+#fancybox-thumbs ul li:hover {
+ opacity: 1;
+}
+
+#fancybox-thumbs ul li a {
+ display: block;
+ position: relative;
+ overflow: hidden;
+ border: 1px solid #222;
+ background: #111;
+ outline: none;
+}
+
+#fancybox-thumbs ul li img {
+ display: block;
+ position: relative;
+ border: 0;
+ padding: 0;
+ max-width: none;
+}
\ No newline at end of file
diff --git a/js/fancyBox/source/helpers/jquery.fancybox-thumbs.js b/js/fancyBox/source/helpers/jquery.fancybox-thumbs.js
new file mode 100644
index 0000000..5db3d4a
--- /dev/null
+++ b/js/fancyBox/source/helpers/jquery.fancybox-thumbs.js
@@ -0,0 +1,162 @@
+ /*!
+ * Thumbnail helper for fancyBox
+ * version: 1.0.7 (Mon, 01 Oct 2012)
+ * @requires fancyBox v2.0 or later
+ *
+ * Usage:
+ * $(".fancybox").fancybox({
+ * helpers : {
+ * thumbs: {
+ * width : 50,
+ * height : 50
+ * }
+ * }
+ * });
+ *
+ */
+(function ($) {
+ //Shortcut for fancyBox object
+ var F = $.fancybox;
+
+ //Add helper object
+ F.helpers.thumbs = {
+ defaults : {
+ width : 50, // thumbnail width
+ height : 50, // thumbnail height
+ position : 'bottom', // 'top' or 'bottom'
+ source : function ( item ) { // function to obtain the URL of the thumbnail image
+ var href;
+
+ if (item.element) {
+ href = $(item.element).find('img').attr('src');
+ }
+
+ if (!href && item.type === 'image' && item.href) {
+ href = item.href;
+ }
+
+ return href;
+ }
+ },
+
+ wrap : null,
+ list : null,
+ width : 0,
+
+ init: function (opts, obj) {
+ var that = this,
+ list,
+ thumbWidth = opts.width,
+ thumbHeight = opts.height,
+ thumbSource = opts.source;
+
+ //Build list structure
+ list = '';
+
+ for (var n = 0; n < obj.group.length; n++) {
+ list += '
';
+ }
+
+ this.wrap = $('
').addClass(opts.position).appendTo('body');
+ this.list = $('
').appendTo(this.wrap);
+
+ //Load each thumbnail
+ $.each(obj.group, function (i) {
+ var href = thumbSource( obj.group[ i ] );
+
+ if (!href) {
+ return;
+ }
+
+ $("
").load(function () {
+ var width = this.width,
+ height = this.height,
+ widthRatio, heightRatio, parent;
+
+ if (!that.list || !width || !height) {
+ return;
+ }
+
+ //Calculate thumbnail width/height and center it
+ widthRatio = width / thumbWidth;
+ heightRatio = height / thumbHeight;
+
+ parent = that.list.children().eq(i).find('a');
+
+ if (widthRatio >= 1 && heightRatio >= 1) {
+ if (widthRatio > heightRatio) {
+ width = Math.floor(width / heightRatio);
+ height = thumbHeight;
+
+ } else {
+ width = thumbWidth;
+ height = Math.floor(height / widthRatio);
+ }
+ }
+
+ $(this).css({
+ width : width,
+ height : height,
+ top : Math.floor(thumbHeight / 2 - height / 2),
+ left : Math.floor(thumbWidth / 2 - width / 2)
+ });
+
+ parent.width(thumbWidth).height(thumbHeight);
+
+ $(this).hide().appendTo(parent).fadeIn(300);
+
+ }).attr('src', href);
+ });
+
+ //Set initial width
+ this.width = this.list.children().eq(0).outerWidth(true);
+
+ this.list.width(this.width * (obj.group.length + 1)).css('left', Math.floor($(window).width() * 0.5 - (obj.index * this.width + this.width * 0.5)));
+ },
+
+ beforeLoad: function (opts, obj) {
+ //Remove self if gallery do not have at least two items
+ if (obj.group.length < 2) {
+ obj.helpers.thumbs = false;
+
+ return;
+ }
+
+ //Increase bottom margin to give space for thumbs
+ obj.margin[ opts.position === 'top' ? 0 : 2 ] += ((opts.height) + 15);
+ },
+
+ afterShow: function (opts, obj) {
+ //Check if exists and create or update list
+ if (this.list) {
+ this.onUpdate(opts, obj);
+
+ } else {
+ this.init(opts, obj);
+ }
+
+ //Set active element
+ this.list.children().removeClass('active').eq(obj.index).addClass('active');
+ },
+
+ //Center list
+ onUpdate: function (opts, obj) {
+ if (this.list) {
+ this.list.stop(true).animate({
+ 'left': Math.floor($(window).width() * 0.5 - (obj.index * this.width + this.width * 0.5))
+ }, 150);
+ }
+ },
+
+ beforeClose: function () {
+ if (this.wrap) {
+ this.wrap.remove();
+ }
+
+ this.wrap = null;
+ this.list = null;
+ this.width = 0;
+ }
+ }
+
+}(jQuery));
\ No newline at end of file
diff --git a/js/fancyBox/source/jquery.fancybox.css b/js/fancyBox/source/jquery.fancybox.css
new file mode 100644
index 0000000..367890a
--- /dev/null
+++ b/js/fancyBox/source/jquery.fancybox.css
@@ -0,0 +1,274 @@
+/*! fancyBox v2.1.5 fancyapps.com | fancyapps.com/fancybox/#license */
+.fancybox-wrap,
+.fancybox-skin,
+.fancybox-outer,
+.fancybox-inner,
+.fancybox-image,
+.fancybox-wrap iframe,
+.fancybox-wrap object,
+.fancybox-nav,
+.fancybox-nav span,
+.fancybox-tmp
+{
+ padding: 0;
+ margin: 0;
+ border: 0;
+ outline: none;
+ vertical-align: top;
+}
+
+.fancybox-wrap {
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: 8020;
+}
+
+.fancybox-skin {
+ position: relative;
+ background: #f9f9f9;
+ color: #444;
+ text-shadow: none;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+}
+
+.fancybox-opened {
+ z-index: 8030;
+}
+
+.fancybox-opened .fancybox-skin {
+ -webkit-box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5);
+ -moz-box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5);
+ box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5);
+}
+
+.fancybox-outer, .fancybox-inner {
+ position: relative;
+}
+
+.fancybox-inner {
+ overflow: hidden;
+}
+
+.fancybox-type-iframe .fancybox-inner {
+ -webkit-overflow-scrolling: touch;
+}
+
+.fancybox-error {
+ color: #444;
+ font: 14px/20px "Helvetica Neue",Helvetica,Arial,sans-serif;
+ margin: 0;
+ padding: 15px;
+ white-space: nowrap;
+}
+
+.fancybox-image, .fancybox-iframe {
+ display: block;
+ width: 100%;
+ height: 100%;
+}
+
+.fancybox-image {
+ max-width: 100%;
+ max-height: 100%;
+}
+
+#fancybox-loading, .fancybox-close, .fancybox-prev span, .fancybox-next span {
+ background-image: url('fancybox_sprite.png');
+}
+
+#fancybox-loading {
+ position: fixed;
+ top: 50%;
+ left: 50%;
+ margin-top: -22px;
+ margin-left: -22px;
+ background-position: 0 -108px;
+ opacity: 0.8;
+ cursor: pointer;
+ z-index: 8060;
+}
+
+#fancybox-loading div {
+ width: 44px;
+ height: 44px;
+ background: url('fancybox_loading.gif') center center no-repeat;
+}
+
+.fancybox-close {
+ position: absolute;
+ top: -18px;
+ right: -18px;
+ width: 36px;
+ height: 36px;
+ cursor: pointer;
+ z-index: 8040;
+}
+
+.fancybox-nav {
+ position: absolute;
+ top: 0;
+ width: 40%;
+ height: 100%;
+ cursor: pointer;
+ text-decoration: none;
+ background: transparent url('blank.gif'); /* helps IE */
+ -webkit-tap-highlight-color: rgba(0,0,0,0);
+ z-index: 8040;
+}
+
+.fancybox-prev {
+ left: 0;
+}
+
+.fancybox-next {
+ right: 0;
+}
+
+.fancybox-nav span {
+ position: absolute;
+ top: 50%;
+ width: 36px;
+ height: 34px;
+ margin-top: -18px;
+ cursor: pointer;
+ z-index: 8040;
+ visibility: hidden;
+}
+
+.fancybox-prev span {
+ left: 10px;
+ background-position: 0 -36px;
+}
+
+.fancybox-next span {
+ right: 10px;
+ background-position: 0 -72px;
+}
+
+.fancybox-nav:hover span {
+ visibility: visible;
+}
+
+.fancybox-tmp {
+ position: absolute;
+ top: -99999px;
+ left: -99999px;
+ visibility: hidden;
+ max-width: 99999px;
+ max-height: 99999px;
+ overflow: visible !important;
+}
+
+/* Overlay helper */
+
+.fancybox-lock {
+ overflow: hidden !important;
+ width: auto;
+}
+
+.fancybox-lock body {
+ overflow: hidden !important;
+}
+
+.fancybox-lock-test {
+ overflow-y: hidden !important;
+}
+
+.fancybox-overlay {
+ position: absolute;
+ top: 0;
+ left: 0;
+ overflow: hidden;
+ display: none;
+ z-index: 8010;
+ background: url('fancybox_overlay.png');
+}
+
+.fancybox-overlay-fixed {
+ position: fixed;
+ bottom: 0;
+ right: 0;
+}
+
+.fancybox-lock .fancybox-overlay {
+ overflow: auto;
+ overflow-y: scroll;
+}
+
+/* Title helper */
+
+.fancybox-title {
+ visibility: hidden;
+ font: normal 13px/20px "Helvetica Neue",Helvetica,Arial,sans-serif;
+ position: relative;
+ text-shadow: none;
+ z-index: 8050;
+}
+
+.fancybox-opened .fancybox-title {
+ visibility: visible;
+}
+
+.fancybox-title-float-wrap {
+ position: absolute;
+ bottom: 0;
+ right: 50%;
+ margin-bottom: -35px;
+ z-index: 8050;
+ text-align: center;
+}
+
+.fancybox-title-float-wrap .child {
+ display: inline-block;
+ margin-right: -100%;
+ padding: 2px 20px;
+ background: transparent; /* Fallback for web browsers that doesn't support RGBa */
+ background: rgba(0, 0, 0, 0.8);
+ -webkit-border-radius: 15px;
+ -moz-border-radius: 15px;
+ border-radius: 15px;
+ text-shadow: 0 1px 2px #222;
+ color: #FFF;
+ font-weight: bold;
+ line-height: 24px;
+ white-space: nowrap;
+}
+
+.fancybox-title-outside-wrap {
+ position: relative;
+ margin-top: 10px;
+ color: #fff;
+}
+
+.fancybox-title-inside-wrap {
+ padding-top: 10px;
+}
+
+.fancybox-title-over-wrap {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ color: #fff;
+ padding: 10px;
+ background: #000;
+ background: rgba(0, 0, 0, .8);
+}
+
+/*Retina graphics!*/
+@media only screen and (-webkit-min-device-pixel-ratio: 1.5),
+ only screen and (min--moz-device-pixel-ratio: 1.5),
+ only screen and (min-device-pixel-ratio: 1.5){
+
+ #fancybox-loading, .fancybox-close, .fancybox-prev span, .fancybox-next span {
+ background-image: url('fancybox_sprite@2x.png');
+ background-size: 44px 152px; /*The size of the normal image, half the size of the hi-res image*/
+ }
+
+ #fancybox-loading div {
+ background-image: url('fancybox_loading@2x.gif');
+ background-size: 24px 24px; /*The size of the normal image, half the size of the hi-res image*/
+ }
+}
\ No newline at end of file
diff --git a/js/fancyBox/source/jquery.fancybox.js b/js/fancyBox/source/jquery.fancybox.js
new file mode 100644
index 0000000..e8e1987
--- /dev/null
+++ b/js/fancyBox/source/jquery.fancybox.js
@@ -0,0 +1,2020 @@
+/*!
+ * fancyBox - jQuery Plugin
+ * version: 2.1.5 (Fri, 14 Jun 2013)
+ * @requires jQuery v1.6 or later
+ *
+ * Examples at http://fancyapps.com/fancybox/
+ * License: www.fancyapps.com/fancybox/#license
+ *
+ * Copyright 2012 Janis Skarnelis - janis@fancyapps.com
+ *
+ */
+
+(function (window, document, $, undefined) {
+ "use strict";
+
+ var H = $("html"),
+ W = $(window),
+ D = $(document),
+ F = $.fancybox = function () {
+ F.open.apply( this, arguments );
+ },
+ IE = navigator.userAgent.match(/msie/i),
+ didUpdate = null,
+ isTouch = document.createTouch !== undefined,
+
+ isQuery = function(obj) {
+ return obj && obj.hasOwnProperty && obj instanceof $;
+ },
+ isString = function(str) {
+ return str && $.type(str) === "string";
+ },
+ isPercentage = function(str) {
+ return isString(str) && str.indexOf('%') > 0;
+ },
+ isScrollable = function(el) {
+ return (el && !(el.style.overflow && el.style.overflow === 'hidden') && ((el.clientWidth && el.scrollWidth > el.clientWidth) || (el.clientHeight && el.scrollHeight > el.clientHeight)));
+ },
+ getScalar = function(orig, dim) {
+ var value = parseInt(orig, 10) || 0;
+
+ if (dim && isPercentage(orig)) {
+ value = F.getViewport()[ dim ] / 100 * value;
+ }
+
+ return Math.ceil(value);
+ },
+ getValue = function(value, dim) {
+ return getScalar(value, dim) + 'px';
+ };
+
+ $.extend(F, {
+ // The current version of fancyBox
+ version: '2.1.5',
+
+ defaults: {
+ padding : 15,
+ margin : 20,
+
+ width : 800,
+ height : 600,
+ minWidth : 100,
+ minHeight : 100,
+ maxWidth : 9999,
+ maxHeight : 9999,
+ pixelRatio: 1, // Set to 2 for retina display support
+
+ autoSize : true,
+ autoHeight : false,
+ autoWidth : false,
+
+ autoResize : true,
+ autoCenter : !isTouch,
+ fitToView : true,
+ aspectRatio : false,
+ topRatio : 0.5,
+ leftRatio : 0.5,
+
+ scrolling : 'auto', // 'auto', 'yes' or 'no'
+ wrapCSS : '',
+
+ arrows : true,
+ closeBtn : true,
+ closeClick : false,
+ nextClick : false,
+ mouseWheel : true,
+ autoPlay : false,
+ playSpeed : 3000,
+ preload : 3,
+ modal : false,
+ loop : true,
+
+ ajax : {
+ dataType : 'html',
+ headers : { 'X-fancyBox': true }
+ },
+ iframe : {
+ scrolling : 'auto',
+ preload : true
+ },
+ swf : {
+ wmode: 'transparent',
+ allowfullscreen : 'true',
+ allowscriptaccess : 'always'
+ },
+
+ keys : {
+ next : {
+ 13 : 'left', // enter
+ 34 : 'up', // page down
+ 39 : 'left', // right arrow
+ 40 : 'up' // down arrow
+ },
+ prev : {
+ 8 : 'right', // backspace
+ 33 : 'down', // page up
+ 37 : 'right', // left arrow
+ 38 : 'down' // up arrow
+ },
+ close : [27], // escape key
+ play : [32], // space - start/stop slideshow
+ toggle : [70] // letter "f" - toggle fullscreen
+ },
+
+ direction : {
+ next : 'left',
+ prev : 'right'
+ },
+
+ scrollOutside : true,
+
+ // Override some properties
+ index : 0,
+ type : null,
+ href : null,
+ content : null,
+ title : null,
+
+ // HTML templates
+ tpl: {
+ wrap : '
',
+ image : '
',
+ iframe : '
',
+ error : '
The requested content cannot be loaded. Please try again later.
',
+ closeBtn : '
',
+ next : '
',
+ prev : '
'
+ },
+
+ // Properties for each animation type
+ // Opening fancyBox
+ openEffect : 'fade', // 'elastic', 'fade' or 'none'
+ openSpeed : 250,
+ openEasing : 'swing',
+ openOpacity : true,
+ openMethod : 'zoomIn',
+
+ // Closing fancyBox
+ closeEffect : 'fade', // 'elastic', 'fade' or 'none'
+ closeSpeed : 250,
+ closeEasing : 'swing',
+ closeOpacity : true,
+ closeMethod : 'zoomOut',
+
+ // Changing next gallery item
+ nextEffect : 'elastic', // 'elastic', 'fade' or 'none'
+ nextSpeed : 250,
+ nextEasing : 'swing',
+ nextMethod : 'changeIn',
+
+ // Changing previous gallery item
+ prevEffect : 'elastic', // 'elastic', 'fade' or 'none'
+ prevSpeed : 250,
+ prevEasing : 'swing',
+ prevMethod : 'changeOut',
+
+ // Enable default helpers
+ helpers : {
+ overlay : true,
+ title : true
+ },
+
+ // Callbacks
+ onCancel : $.noop, // If canceling
+ beforeLoad : $.noop, // Before loading
+ afterLoad : $.noop, // After loading
+ beforeShow : $.noop, // Before changing in current item
+ afterShow : $.noop, // After opening
+ beforeChange : $.noop, // Before changing gallery item
+ beforeClose : $.noop, // Before closing
+ afterClose : $.noop // After closing
+ },
+
+ //Current state
+ group : {}, // Selected group
+ opts : {}, // Group options
+ previous : null, // Previous element
+ coming : null, // Element being loaded
+ current : null, // Currently loaded element
+ isActive : false, // Is activated
+ isOpen : false, // Is currently open
+ isOpened : false, // Have been fully opened at least once
+
+ wrap : null,
+ skin : null,
+ outer : null,
+ inner : null,
+
+ player : {
+ timer : null,
+ isActive : false
+ },
+
+ // Loaders
+ ajaxLoad : null,
+ imgPreload : null,
+
+ // Some collections
+ transitions : {},
+ helpers : {},
+
+ /*
+ * Static methods
+ */
+
+ open: function (group, opts) {
+ if (!group) {
+ return;
+ }
+
+ if (!$.isPlainObject(opts)) {
+ opts = {};
+ }
+
+ // Close if already active
+ if (false === F.close(true)) {
+ return;
+ }
+
+ // Normalize group
+ if (!$.isArray(group)) {
+ group = isQuery(group) ? $(group).get() : [group];
+ }
+
+ // Recheck if the type of each element is `object` and set content type (image, ajax, etc)
+ $.each(group, function(i, element) {
+ var obj = {},
+ href,
+ title,
+ content,
+ type,
+ rez,
+ hrefParts,
+ selector;
+
+ if ($.type(element) === "object") {
+ // Check if is DOM element
+ if (element.nodeType) {
+ element = $(element);
+ }
+
+ if (isQuery(element)) {
+ obj = {
+ href : element.data('fancybox-href') || element.attr('href'),
+ title : element.data('fancybox-title') || element.attr('title'),
+ isDom : true,
+ element : element
+ };
+
+ if ($.metadata) {
+ $.extend(true, obj, element.metadata());
+ }
+
+ } else {
+ obj = element;
+ }
+ }
+
+ href = opts.href || obj.href || (isString(element) ? element : null);
+ title = opts.title !== undefined ? opts.title : obj.title || '';
+
+ content = opts.content || obj.content;
+ type = content ? 'html' : (opts.type || obj.type);
+
+ if (!type && obj.isDom) {
+ type = element.data('fancybox-type');
+
+ if (!type) {
+ rez = element.prop('class').match(/fancybox\.(\w+)/);
+ type = rez ? rez[1] : null;
+ }
+ }
+
+ if (isString(href)) {
+ // Try to guess the content type
+ if (!type) {
+ if (F.isImage(href)) {
+ type = 'image';
+
+ } else if (F.isSWF(href)) {
+ type = 'swf';
+
+ } else if (href.charAt(0) === '#') {
+ type = 'inline';
+
+ } else if (isString(element)) {
+ type = 'html';
+ content = element;
+ }
+ }
+
+ // Split url into two pieces with source url and content selector, e.g,
+ // "/mypage.html #my_id" will load "/mypage.html" and display element having id "my_id"
+ if (type === 'ajax') {
+ hrefParts = href.split(/\s+/, 2);
+ href = hrefParts.shift();
+ selector = hrefParts.shift();
+ }
+ }
+
+ if (!content) {
+ if (type === 'inline') {
+ if (href) {
+ content = $( isString(href) ? href.replace(/.*(?=#[^\s]+$)/, '') : href ); //strip for ie7
+
+ } else if (obj.isDom) {
+ content = element;
+ }
+
+ } else if (type === 'html') {
+ content = href;
+
+ } else if (!type && !href && obj.isDom) {
+ type = 'inline';
+ content = element;
+ }
+ }
+
+ $.extend(obj, {
+ href : href,
+ type : type,
+ content : content,
+ title : title,
+ selector : selector
+ });
+
+ group[ i ] = obj;
+ });
+
+ // Extend the defaults
+ F.opts = $.extend(true, {}, F.defaults, opts);
+
+ // All options are merged recursive except keys
+ if (opts.keys !== undefined) {
+ F.opts.keys = opts.keys ? $.extend({}, F.defaults.keys, opts.keys) : false;
+ }
+
+ F.group = group;
+
+ return F._start(F.opts.index);
+ },
+
+ // Cancel image loading or abort ajax request
+ cancel: function () {
+ var coming = F.coming;
+
+ if (!coming || false === F.trigger('onCancel')) {
+ return;
+ }
+
+ F.hideLoading();
+
+ if (F.ajaxLoad) {
+ F.ajaxLoad.abort();
+ }
+
+ F.ajaxLoad = null;
+
+ if (F.imgPreload) {
+ F.imgPreload.onload = F.imgPreload.onerror = null;
+ }
+
+ if (coming.wrap) {
+ coming.wrap.stop(true, true).trigger('onReset').remove();
+ }
+
+ F.coming = null;
+
+ // If the first item has been canceled, then clear everything
+ if (!F.current) {
+ F._afterZoomOut( coming );
+ }
+ },
+
+ // Start closing animation if is open; remove immediately if opening/closing
+ close: function (event) {
+ F.cancel();
+
+ if (false === F.trigger('beforeClose')) {
+ return;
+ }
+
+ F.unbindEvents();
+
+ if (!F.isActive) {
+ return;
+ }
+
+ if (!F.isOpen || event === true) {
+ $('.fancybox-wrap').stop(true).trigger('onReset').remove();
+
+ F._afterZoomOut();
+
+ } else {
+ F.isOpen = F.isOpened = false;
+ F.isClosing = true;
+
+ $('.fancybox-item, .fancybox-nav').remove();
+
+ F.wrap.stop(true, true).removeClass('fancybox-opened');
+
+ F.transitions[ F.current.closeMethod ]();
+ }
+ },
+
+ // Manage slideshow:
+ // $.fancybox.play(); - toggle slideshow
+ // $.fancybox.play( true ); - start
+ // $.fancybox.play( false ); - stop
+ play: function ( action ) {
+ var clear = function () {
+ clearTimeout(F.player.timer);
+ },
+ set = function () {
+ clear();
+
+ if (F.current && F.player.isActive) {
+ F.player.timer = setTimeout(F.next, F.current.playSpeed);
+ }
+ },
+ stop = function () {
+ clear();
+
+ D.unbind('.player');
+
+ F.player.isActive = false;
+
+ F.trigger('onPlayEnd');
+ },
+ start = function () {
+ if (F.current && (F.current.loop || F.current.index < F.group.length - 1)) {
+ F.player.isActive = true;
+
+ D.bind({
+ 'onCancel.player beforeClose.player' : stop,
+ 'onUpdate.player' : set,
+ 'beforeLoad.player' : clear
+ });
+
+ set();
+
+ F.trigger('onPlayStart');
+ }
+ };
+
+ if (action === true || (!F.player.isActive && action !== false)) {
+ start();
+ } else {
+ stop();
+ }
+ },
+
+ // Navigate to next gallery item
+ next: function ( direction ) {
+ var current = F.current;
+
+ if (current) {
+ if (!isString(direction)) {
+ direction = current.direction.next;
+ }
+
+ F.jumpto(current.index + 1, direction, 'next');
+ }
+ },
+
+ // Navigate to previous gallery item
+ prev: function ( direction ) {
+ var current = F.current;
+
+ if (current) {
+ if (!isString(direction)) {
+ direction = current.direction.prev;
+ }
+
+ F.jumpto(current.index - 1, direction, 'prev');
+ }
+ },
+
+ // Navigate to gallery item by index
+ jumpto: function ( index, direction, router ) {
+ var current = F.current;
+
+ if (!current) {
+ return;
+ }
+
+ index = getScalar(index);
+
+ F.direction = direction || current.direction[ (index >= current.index ? 'next' : 'prev') ];
+ F.router = router || 'jumpto';
+
+ if (current.loop) {
+ if (index < 0) {
+ index = current.group.length + (index % current.group.length);
+ }
+
+ index = index % current.group.length;
+ }
+
+ if (current.group[ index ] !== undefined) {
+ F.cancel();
+
+ F._start(index);
+ }
+ },
+
+ // Center inside viewport and toggle position type to fixed or absolute if needed
+ reposition: function (e, onlyAbsolute) {
+ var current = F.current,
+ wrap = current ? current.wrap : null,
+ pos;
+
+ if (wrap) {
+ pos = F._getPosition(onlyAbsolute);
+
+ if (e && e.type === 'scroll') {
+ delete pos.position;
+
+ wrap.stop(true, true).animate(pos, 200);
+
+ } else {
+ wrap.css(pos);
+
+ current.pos = $.extend({}, current.dim, pos);
+ }
+ }
+ },
+
+ update: function (e) {
+ var type = (e && e.type),
+ anyway = !type || type === 'orientationchange';
+
+ if (anyway) {
+ clearTimeout(didUpdate);
+
+ didUpdate = null;
+ }
+
+ if (!F.isOpen || didUpdate) {
+ return;
+ }
+
+ didUpdate = setTimeout(function() {
+ var current = F.current;
+
+ if (!current || F.isClosing) {
+ return;
+ }
+
+ F.wrap.removeClass('fancybox-tmp');
+
+ if (anyway || type === 'load' || (type === 'resize' && current.autoResize)) {
+ F._setDimension();
+ }
+
+ if (!(type === 'scroll' && current.canShrink)) {
+ F.reposition(e);
+ }
+
+ F.trigger('onUpdate');
+
+ didUpdate = null;
+
+ }, (anyway && !isTouch ? 0 : 300));
+ },
+
+ // Shrink content to fit inside viewport or restore if resized
+ toggle: function ( action ) {
+ if (F.isOpen) {
+ F.current.fitToView = $.type(action) === "boolean" ? action : !F.current.fitToView;
+
+ // Help browser to restore document dimensions
+ if (isTouch) {
+ F.wrap.removeAttr('style').addClass('fancybox-tmp');
+
+ F.trigger('onUpdate');
+ }
+
+ F.update();
+ }
+ },
+
+ hideLoading: function () {
+ D.unbind('.loading');
+
+ $('#fancybox-loading').remove();
+ },
+
+ showLoading: function () {
+ var el, viewport;
+
+ F.hideLoading();
+
+ el = $('
').click(F.cancel).appendTo('body');
+
+ // If user will press the escape-button, the request will be canceled
+ D.bind('keydown.loading', function(e) {
+ if ((e.which || e.keyCode) === 27) {
+ e.preventDefault();
+
+ F.cancel();
+ }
+ });
+
+ if (!F.defaults.fixed) {
+ viewport = F.getViewport();
+
+ el.css({
+ position : 'absolute',
+ top : (viewport.h * 0.5) + viewport.y,
+ left : (viewport.w * 0.5) + viewport.x
+ });
+ }
+ },
+
+ getViewport: function () {
+ var locked = (F.current && F.current.locked) || false,
+ rez = {
+ x: W.scrollLeft(),
+ y: W.scrollTop()
+ };
+
+ if (locked) {
+ rez.w = locked[0].clientWidth;
+ rez.h = locked[0].clientHeight;
+
+ } else {
+ // See http://bugs.jquery.com/ticket/6724
+ rez.w = isTouch && window.innerWidth ? window.innerWidth : W.width();
+ rez.h = isTouch && window.innerHeight ? window.innerHeight : W.height();
+ }
+
+ return rez;
+ },
+
+ // Unbind the keyboard / clicking actions
+ unbindEvents: function () {
+ if (F.wrap && isQuery(F.wrap)) {
+ F.wrap.unbind('.fb');
+ }
+
+ D.unbind('.fb');
+ W.unbind('.fb');
+ },
+
+ bindEvents: function () {
+ var current = F.current,
+ keys;
+
+ if (!current) {
+ return;
+ }
+
+ // Changing document height on iOS devices triggers a 'resize' event,
+ // that can change document height... repeating infinitely
+ W.bind('orientationchange.fb' + (isTouch ? '' : ' resize.fb') + (current.autoCenter && !current.locked ? ' scroll.fb' : ''), F.update);
+
+ keys = current.keys;
+
+ if (keys) {
+ D.bind('keydown.fb', function (e) {
+ var code = e.which || e.keyCode,
+ target = e.target || e.srcElement;
+
+ // Skip esc key if loading, because showLoading will cancel preloading
+ if (code === 27 && F.coming) {
+ return false;
+ }
+
+ // Ignore key combinations and key events within form elements
+ if (!e.ctrlKey && !e.altKey && !e.shiftKey && !e.metaKey && !(target && (target.type || $(target).is('[contenteditable]')))) {
+ $.each(keys, function(i, val) {
+ if (current.group.length > 1 && val[ code ] !== undefined) {
+ F[ i ]( val[ code ] );
+
+ e.preventDefault();
+ return false;
+ }
+
+ if ($.inArray(code, val) > -1) {
+ F[ i ] ();
+
+ e.preventDefault();
+ return false;
+ }
+ });
+ }
+ });
+ }
+
+ if ($.fn.mousewheel && current.mouseWheel) {
+ F.wrap.bind('mousewheel.fb', function (e, delta, deltaX, deltaY) {
+ var target = e.target || null,
+ parent = $(target),
+ canScroll = false;
+
+ while (parent.length) {
+ if (canScroll || parent.is('.fancybox-skin') || parent.is('.fancybox-wrap')) {
+ break;
+ }
+
+ canScroll = isScrollable( parent[0] );
+ parent = $(parent).parent();
+ }
+
+ if (delta !== 0 && !canScroll) {
+ if (F.group.length > 1 && !current.canShrink) {
+ if (deltaY > 0 || deltaX > 0) {
+ F.prev( deltaY > 0 ? 'down' : 'left' );
+
+ } else if (deltaY < 0 || deltaX < 0) {
+ F.next( deltaY < 0 ? 'up' : 'right' );
+ }
+
+ e.preventDefault();
+ }
+ }
+ });
+ }
+ },
+
+ trigger: function (event, o) {
+ var ret, obj = o || F.coming || F.current;
+
+ if (!obj) {
+ return;
+ }
+
+ if ($.isFunction( obj[event] )) {
+ ret = obj[event].apply(obj, Array.prototype.slice.call(arguments, 1));
+ }
+
+ if (ret === false) {
+ return false;
+ }
+
+ if (obj.helpers) {
+ $.each(obj.helpers, function (helper, opts) {
+ if (opts && F.helpers[helper] && $.isFunction(F.helpers[helper][event])) {
+ F.helpers[helper][event]($.extend(true, {}, F.helpers[helper].defaults, opts), obj);
+ }
+ });
+ }
+
+ D.trigger(event);
+ },
+
+ isImage: function (str) {
+ return isString(str) && str.match(/(^data:image\/.*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg)((\?|#).*)?$)/i);
+ },
+
+ isSWF: function (str) {
+ return isString(str) && str.match(/\.(swf)((\?|#).*)?$/i);
+ },
+
+ _start: function (index) {
+ var coming = {},
+ obj,
+ href,
+ type,
+ margin,
+ padding;
+
+ index = getScalar( index );
+ obj = F.group[ index ] || null;
+
+ if (!obj) {
+ return false;
+ }
+
+ coming = $.extend(true, {}, F.opts, obj);
+
+ // Convert margin and padding properties to array - top, right, bottom, left
+ margin = coming.margin;
+ padding = coming.padding;
+
+ if ($.type(margin) === 'number') {
+ coming.margin = [margin, margin, margin, margin];
+ }
+
+ if ($.type(padding) === 'number') {
+ coming.padding = [padding, padding, padding, padding];
+ }
+
+ // 'modal' propery is just a shortcut
+ if (coming.modal) {
+ $.extend(true, coming, {
+ closeBtn : false,
+ closeClick : false,
+ nextClick : false,
+ arrows : false,
+ mouseWheel : false,
+ keys : null,
+ helpers: {
+ overlay : {
+ closeClick : false
+ }
+ }
+ });
+ }
+
+ // 'autoSize' property is a shortcut, too
+ if (coming.autoSize) {
+ coming.autoWidth = coming.autoHeight = true;
+ }
+
+ if (coming.width === 'auto') {
+ coming.autoWidth = true;
+ }
+
+ if (coming.height === 'auto') {
+ coming.autoHeight = true;
+ }
+
+ /*
+ * Add reference to the group, so it`s possible to access from callbacks, example:
+ * afterLoad : function() {
+ * this.title = 'Image ' + (this.index + 1) + ' of ' + this.group.length + (this.title ? ' - ' + this.title : '');
+ * }
+ */
+
+ coming.group = F.group;
+ coming.index = index;
+
+ // Give a chance for callback or helpers to update coming item (type, title, etc)
+ F.coming = coming;
+
+ if (false === F.trigger('beforeLoad')) {
+ F.coming = null;
+
+ return;
+ }
+
+ type = coming.type;
+ href = coming.href;
+
+ if (!type) {
+ F.coming = null;
+
+ //If we can not determine content type then drop silently or display next/prev item if looping through gallery
+ if (F.current && F.router && F.router !== 'jumpto') {
+ F.current.index = index;
+
+ return F[ F.router ]( F.direction );
+ }
+
+ return false;
+ }
+
+ F.isActive = true;
+
+ if (type === 'image' || type === 'swf') {
+ coming.autoHeight = coming.autoWidth = false;
+ coming.scrolling = 'visible';
+ }
+
+ if (type === 'image') {
+ coming.aspectRatio = true;
+ }
+
+ if (type === 'iframe' && isTouch) {
+ coming.scrolling = 'scroll';
+ }
+
+ // Build the neccessary markup
+ coming.wrap = $(coming.tpl.wrap).addClass('fancybox-' + (isTouch ? 'mobile' : 'desktop') + ' fancybox-type-' + type + ' fancybox-tmp ' + coming.wrapCSS).appendTo( coming.parent || 'body' );
+
+ $.extend(coming, {
+ skin : $('.fancybox-skin', coming.wrap),
+ outer : $('.fancybox-outer', coming.wrap),
+ inner : $('.fancybox-inner', coming.wrap)
+ });
+
+ $.each(["Top", "Right", "Bottom", "Left"], function(i, v) {
+ coming.skin.css('padding' + v, getValue(coming.padding[ i ]));
+ });
+
+ F.trigger('onReady');
+
+ // Check before try to load; 'inline' and 'html' types need content, others - href
+ if (type === 'inline' || type === 'html') {
+ if (!coming.content || !coming.content.length) {
+ return F._error( 'content' );
+ }
+
+ } else if (!href) {
+ return F._error( 'href' );
+ }
+
+ if (type === 'image') {
+ F._loadImage();
+
+ } else if (type === 'ajax') {
+ F._loadAjax();
+
+ } else if (type === 'iframe') {
+ F._loadIframe();
+
+ } else {
+ F._afterLoad();
+ }
+ },
+
+ _error: function ( type ) {
+ $.extend(F.coming, {
+ type : 'html',
+ autoWidth : true,
+ autoHeight : true,
+ minWidth : 0,
+ minHeight : 0,
+ scrolling : 'no',
+ hasError : type,
+ content : F.coming.tpl.error
+ });
+
+ F._afterLoad();
+ },
+
+ _loadImage: function () {
+ // Reset preload image so it is later possible to check "complete" property
+ var img = F.imgPreload = new Image();
+
+ img.onload = function () {
+ this.onload = this.onerror = null;
+
+ F.coming.width = this.width / F.opts.pixelRatio;
+ F.coming.height = this.height / F.opts.pixelRatio;
+
+ F._afterLoad();
+ };
+
+ img.onerror = function () {
+ this.onload = this.onerror = null;
+
+ F._error( 'image' );
+ };
+
+ img.src = F.coming.href;
+
+ if (img.complete !== true) {
+ F.showLoading();
+ }
+ },
+
+ _loadAjax: function () {
+ var coming = F.coming;
+
+ F.showLoading();
+
+ F.ajaxLoad = $.ajax($.extend({}, coming.ajax, {
+ url: coming.href,
+ error: function (jqXHR, textStatus) {
+ if (F.coming && textStatus !== 'abort') {
+ F._error( 'ajax', jqXHR );
+
+ } else {
+ F.hideLoading();
+ }
+ },
+ success: function (data, textStatus) {
+ if (textStatus === 'success') {
+ coming.content = data;
+
+ F._afterLoad();
+ }
+ }
+ }));
+ },
+
+ _loadIframe: function() {
+ var coming = F.coming,
+ iframe = $(coming.tpl.iframe.replace(/\{rnd\}/g, new Date().getTime()))
+ .attr('scrolling', isTouch ? 'auto' : coming.iframe.scrolling)
+ .attr('src', coming.href);
+
+ // This helps IE
+ $(coming.wrap).bind('onReset', function () {
+ try {
+ $(this).find('iframe').hide().attr('src', '//about:blank').end().empty();
+ } catch (e) {}
+ });
+
+ if (coming.iframe.preload) {
+ F.showLoading();
+
+ iframe.one('load', function() {
+ $(this).data('ready', 1);
+
+ // iOS will lose scrolling if we resize
+ if (!isTouch) {
+ $(this).bind('load.fb', F.update);
+ }
+
+ // Without this trick:
+ // - iframe won't scroll on iOS devices
+ // - IE7 sometimes displays empty iframe
+ $(this).parents('.fancybox-wrap').width('100%').removeClass('fancybox-tmp').show();
+
+ F._afterLoad();
+ });
+ }
+
+ coming.content = iframe.appendTo( coming.inner );
+
+ if (!coming.iframe.preload) {
+ F._afterLoad();
+ }
+ },
+
+ _preloadImages: function() {
+ var group = F.group,
+ current = F.current,
+ len = group.length,
+ cnt = current.preload ? Math.min(current.preload, len - 1) : 0,
+ item,
+ i;
+
+ for (i = 1; i <= cnt; i += 1) {
+ item = group[ (current.index + i ) % len ];
+
+ if (item.type === 'image' && item.href) {
+ new Image().src = item.href;
+ }
+ }
+ },
+
+ _afterLoad: function () {
+ var coming = F.coming,
+ previous = F.current,
+ placeholder = 'fancybox-placeholder',
+ current,
+ content,
+ type,
+ scrolling,
+ href,
+ embed;
+
+ F.hideLoading();
+
+ if (!coming || F.isActive === false) {
+ return;
+ }
+
+ if (false === F.trigger('afterLoad', coming, previous)) {
+ coming.wrap.stop(true).trigger('onReset').remove();
+
+ F.coming = null;
+
+ return;
+ }
+
+ if (previous) {
+ F.trigger('beforeChange', previous);
+
+ previous.wrap.stop(true).removeClass('fancybox-opened')
+ .find('.fancybox-item, .fancybox-nav')
+ .remove();
+ }
+
+ F.unbindEvents();
+
+ current = coming;
+ content = coming.content;
+ type = coming.type;
+ scrolling = coming.scrolling;
+
+ $.extend(F, {
+ wrap : current.wrap,
+ skin : current.skin,
+ outer : current.outer,
+ inner : current.inner,
+ current : current,
+ previous : previous
+ });
+
+ href = current.href;
+
+ switch (type) {
+ case 'inline':
+ case 'ajax':
+ case 'html':
+ if (current.selector) {
+ content = $('
').html(content).find(current.selector);
+
+ } else if (isQuery(content)) {
+ if (!content.data(placeholder)) {
+ content.data(placeholder, $('
').insertAfter( content ).hide() );
+ }
+
+ content = content.show().detach();
+
+ current.wrap.bind('onReset', function () {
+ if ($(this).find(content).length) {
+ content.hide().replaceAll( content.data(placeholder) ).data(placeholder, false);
+ }
+ });
+ }
+ break;
+
+ case 'image':
+ content = current.tpl.image.replace('{href}', href);
+ break;
+
+ case 'swf':
+ content = '
';
+ embed = '';
+
+ $.each(current.swf, function(name, val) {
+ content += ' ';
+ embed += ' ' + name + '="' + val + '"';
+ });
+
+ content += '';
+ break;
+ }
+
+ if (!(isQuery(content) && content.parent().is(current.inner))) {
+ current.inner.append( content );
+ }
+
+ // Give a chance for helpers or callbacks to update elements
+ F.trigger('beforeShow');
+
+ // Set scrolling before calculating dimensions
+ current.inner.css('overflow', scrolling === 'yes' ? 'scroll' : (scrolling === 'no' ? 'hidden' : scrolling));
+
+ // Set initial dimensions and start position
+ F._setDimension();
+
+ F.reposition();
+
+ F.isOpen = false;
+ F.coming = null;
+
+ F.bindEvents();
+
+ if (!F.isOpened) {
+ $('.fancybox-wrap').not( current.wrap ).stop(true).trigger('onReset').remove();
+
+ } else if (previous.prevMethod) {
+ F.transitions[ previous.prevMethod ]();
+ }
+
+ F.transitions[ F.isOpened ? current.nextMethod : current.openMethod ]();
+
+ F._preloadImages();
+ },
+
+ _setDimension: function () {
+ var viewport = F.getViewport(),
+ steps = 0,
+ canShrink = false,
+ canExpand = false,
+ wrap = F.wrap,
+ skin = F.skin,
+ inner = F.inner,
+ current = F.current,
+ width = current.width,
+ height = current.height,
+ minWidth = current.minWidth,
+ minHeight = current.minHeight,
+ maxWidth = current.maxWidth,
+ maxHeight = current.maxHeight,
+ scrolling = current.scrolling,
+ scrollOut = current.scrollOutside ? current.scrollbarWidth : 0,
+ margin = current.margin,
+ wMargin = getScalar(margin[1] + margin[3]),
+ hMargin = getScalar(margin[0] + margin[2]),
+ wPadding,
+ hPadding,
+ wSpace,
+ hSpace,
+ origWidth,
+ origHeight,
+ origMaxWidth,
+ origMaxHeight,
+ ratio,
+ width_,
+ height_,
+ maxWidth_,
+ maxHeight_,
+ iframe,
+ body;
+
+ // Reset dimensions so we could re-check actual size
+ wrap.add(skin).add(inner).width('auto').height('auto').removeClass('fancybox-tmp');
+
+ wPadding = getScalar(skin.outerWidth(true) - skin.width());
+ hPadding = getScalar(skin.outerHeight(true) - skin.height());
+
+ // Any space between content and viewport (margin, padding, border, title)
+ wSpace = wMargin + wPadding;
+ hSpace = hMargin + hPadding;
+
+ origWidth = isPercentage(width) ? (viewport.w - wSpace) * getScalar(width) / 100 : width;
+ origHeight = isPercentage(height) ? (viewport.h - hSpace) * getScalar(height) / 100 : height;
+
+ if (current.type === 'iframe') {
+ iframe = current.content;
+
+ if (current.autoHeight && iframe.data('ready') === 1) {
+ try {
+ if (iframe[0].contentWindow.document.location) {
+ inner.width( origWidth ).height(9999);
+
+ body = iframe.contents().find('body');
+
+ if (scrollOut) {
+ body.css('overflow-x', 'hidden');
+ }
+
+ origHeight = body.outerHeight(true);
+ }
+
+ } catch (e) {}
+ }
+
+ } else if (current.autoWidth || current.autoHeight) {
+ inner.addClass( 'fancybox-tmp' );
+
+ // Set width or height in case we need to calculate only one dimension
+ if (!current.autoWidth) {
+ inner.width( origWidth );
+ }
+
+ if (!current.autoHeight) {
+ inner.height( origHeight );
+ }
+
+ if (current.autoWidth) {
+ origWidth = inner.width();
+ }
+
+ if (current.autoHeight) {
+ origHeight = inner.height();
+ }
+
+ inner.removeClass( 'fancybox-tmp' );
+ }
+
+ width = getScalar( origWidth );
+ height = getScalar( origHeight );
+
+ ratio = origWidth / origHeight;
+
+ // Calculations for the content
+ minWidth = getScalar(isPercentage(minWidth) ? getScalar(minWidth, 'w') - wSpace : minWidth);
+ maxWidth = getScalar(isPercentage(maxWidth) ? getScalar(maxWidth, 'w') - wSpace : maxWidth);
+
+ minHeight = getScalar(isPercentage(minHeight) ? getScalar(minHeight, 'h') - hSpace : minHeight);
+ maxHeight = getScalar(isPercentage(maxHeight) ? getScalar(maxHeight, 'h') - hSpace : maxHeight);
+
+ // These will be used to determine if wrap can fit in the viewport
+ origMaxWidth = maxWidth;
+ origMaxHeight = maxHeight;
+
+ if (current.fitToView) {
+ maxWidth = Math.min(viewport.w - wSpace, maxWidth);
+ maxHeight = Math.min(viewport.h - hSpace, maxHeight);
+ }
+
+ maxWidth_ = viewport.w - wMargin;
+ maxHeight_ = viewport.h - hMargin;
+
+ if (current.aspectRatio) {
+ if (width > maxWidth) {
+ width = maxWidth;
+ height = getScalar(width / ratio);
+ }
+
+ if (height > maxHeight) {
+ height = maxHeight;
+ width = getScalar(height * ratio);
+ }
+
+ if (width < minWidth) {
+ width = minWidth;
+ height = getScalar(width / ratio);
+ }
+
+ if (height < minHeight) {
+ height = minHeight;
+ width = getScalar(height * ratio);
+ }
+
+ } else {
+ width = Math.max(minWidth, Math.min(width, maxWidth));
+
+ if (current.autoHeight && current.type !== 'iframe') {
+ inner.width( width );
+
+ height = inner.height();
+ }
+
+ height = Math.max(minHeight, Math.min(height, maxHeight));
+ }
+
+ // Try to fit inside viewport (including the title)
+ if (current.fitToView) {
+ inner.width( width ).height( height );
+
+ wrap.width( width + wPadding );
+
+ // Real wrap dimensions
+ width_ = wrap.width();
+ height_ = wrap.height();
+
+ if (current.aspectRatio) {
+ while ((width_ > maxWidth_ || height_ > maxHeight_) && width > minWidth && height > minHeight) {
+ if (steps++ > 19) {
+ break;
+ }
+
+ height = Math.max(minHeight, Math.min(maxHeight, height - 10));
+ width = getScalar(height * ratio);
+
+ if (width < minWidth) {
+ width = minWidth;
+ height = getScalar(width / ratio);
+ }
+
+ if (width > maxWidth) {
+ width = maxWidth;
+ height = getScalar(width / ratio);
+ }
+
+ inner.width( width ).height( height );
+
+ wrap.width( width + wPadding );
+
+ width_ = wrap.width();
+ height_ = wrap.height();
+ }
+
+ } else {
+ width = Math.max(minWidth, Math.min(width, width - (width_ - maxWidth_)));
+ height = Math.max(minHeight, Math.min(height, height - (height_ - maxHeight_)));
+ }
+ }
+
+ if (scrollOut && scrolling === 'auto' && height < origHeight && (width + wPadding + scrollOut) < maxWidth_) {
+ width += scrollOut;
+ }
+
+ inner.width( width ).height( height );
+
+ wrap.width( width + wPadding );
+
+ width_ = wrap.width();
+ height_ = wrap.height();
+
+ canShrink = (width_ > maxWidth_ || height_ > maxHeight_) && width > minWidth && height > minHeight;
+ canExpand = current.aspectRatio ? (width < origMaxWidth && height < origMaxHeight && width < origWidth && height < origHeight) : ((width < origMaxWidth || height < origMaxHeight) && (width < origWidth || height < origHeight));
+
+ $.extend(current, {
+ dim : {
+ width : getValue( width_ ),
+ height : getValue( height_ )
+ },
+ origWidth : origWidth,
+ origHeight : origHeight,
+ canShrink : canShrink,
+ canExpand : canExpand,
+ wPadding : wPadding,
+ hPadding : hPadding,
+ wrapSpace : height_ - skin.outerHeight(true),
+ skinSpace : skin.height() - height
+ });
+
+ if (!iframe && current.autoHeight && height > minHeight && height < maxHeight && !canExpand) {
+ inner.height('auto');
+ }
+ },
+
+ _getPosition: function (onlyAbsolute) {
+ var current = F.current,
+ viewport = F.getViewport(),
+ margin = current.margin,
+ width = F.wrap.width() + margin[1] + margin[3],
+ height = F.wrap.height() + margin[0] + margin[2],
+ rez = {
+ position: 'absolute',
+ top : margin[0],
+ left : margin[3]
+ };
+
+ if (current.autoCenter && current.fixed && !onlyAbsolute && height <= viewport.h && width <= viewport.w) {
+ rez.position = 'fixed';
+
+ } else if (!current.locked) {
+ rez.top += viewport.y;
+ rez.left += viewport.x;
+ }
+
+ rez.top = getValue(Math.max(rez.top, rez.top + ((viewport.h - height) * current.topRatio)));
+ rez.left = getValue(Math.max(rez.left, rez.left + ((viewport.w - width) * current.leftRatio)));
+
+ return rez;
+ },
+
+ _afterZoomIn: function () {
+ var current = F.current;
+
+ if (!current) {
+ return;
+ }
+
+ F.isOpen = F.isOpened = true;
+
+ F.wrap.css('overflow', 'visible').addClass('fancybox-opened');
+
+ F.update();
+
+ // Assign a click event
+ if ( current.closeClick || (current.nextClick && F.group.length > 1) ) {
+ F.inner.css('cursor', 'pointer').bind('click.fb', function(e) {
+ if (!$(e.target).is('a') && !$(e.target).parent().is('a')) {
+ e.preventDefault();
+
+ F[ current.closeClick ? 'close' : 'next' ]();
+ }
+ });
+ }
+
+ // Create a close button
+ if (current.closeBtn) {
+ $(current.tpl.closeBtn).appendTo(F.skin).bind('click.fb', function(e) {
+ e.preventDefault();
+
+ F.close();
+ });
+ }
+
+ // Create navigation arrows
+ if (current.arrows && F.group.length > 1) {
+ if (current.loop || current.index > 0) {
+ $(current.tpl.prev).appendTo(F.outer).bind('click.fb', F.prev);
+ }
+
+ if (current.loop || current.index < F.group.length - 1) {
+ $(current.tpl.next).appendTo(F.outer).bind('click.fb', F.next);
+ }
+ }
+
+ F.trigger('afterShow');
+
+ // Stop the slideshow if this is the last item
+ if (!current.loop && current.index === current.group.length - 1) {
+ F.play( false );
+
+ } else if (F.opts.autoPlay && !F.player.isActive) {
+ F.opts.autoPlay = false;
+
+ F.play();
+ }
+ },
+
+ _afterZoomOut: function ( obj ) {
+ obj = obj || F.current;
+
+ $('.fancybox-wrap').trigger('onReset').remove();
+
+ $.extend(F, {
+ group : {},
+ opts : {},
+ router : false,
+ current : null,
+ isActive : false,
+ isOpened : false,
+ isOpen : false,
+ isClosing : false,
+ wrap : null,
+ skin : null,
+ outer : null,
+ inner : null
+ });
+
+ F.trigger('afterClose', obj);
+ }
+ });
+
+ /*
+ * Default transitions
+ */
+
+ F.transitions = {
+ getOrigPosition: function () {
+ var current = F.current,
+ element = current.element,
+ orig = current.orig,
+ pos = {},
+ width = 50,
+ height = 50,
+ hPadding = current.hPadding,
+ wPadding = current.wPadding,
+ viewport = F.getViewport();
+
+ if (!orig && current.isDom && element.is(':visible')) {
+ orig = element.find('img:first');
+
+ if (!orig.length) {
+ orig = element;
+ }
+ }
+
+ if (isQuery(orig)) {
+ pos = orig.offset();
+
+ if (orig.is('img')) {
+ width = orig.outerWidth();
+ height = orig.outerHeight();
+ }
+
+ } else {
+ pos.top = viewport.y + (viewport.h - height) * current.topRatio;
+ pos.left = viewport.x + (viewport.w - width) * current.leftRatio;
+ }
+
+ if (F.wrap.css('position') === 'fixed' || current.locked) {
+ pos.top -= viewport.y;
+ pos.left -= viewport.x;
+ }
+
+ pos = {
+ top : getValue(pos.top - hPadding * current.topRatio),
+ left : getValue(pos.left - wPadding * current.leftRatio),
+ width : getValue(width + wPadding),
+ height : getValue(height + hPadding)
+ };
+
+ return pos;
+ },
+
+ step: function (now, fx) {
+ var ratio,
+ padding,
+ value,
+ prop = fx.prop,
+ current = F.current,
+ wrapSpace = current.wrapSpace,
+ skinSpace = current.skinSpace;
+
+ if (prop === 'width' || prop === 'height') {
+ ratio = fx.end === fx.start ? 1 : (now - fx.start) / (fx.end - fx.start);
+
+ if (F.isClosing) {
+ ratio = 1 - ratio;
+ }
+
+ padding = prop === 'width' ? current.wPadding : current.hPadding;
+ value = now - padding;
+
+ F.skin[ prop ]( getScalar( prop === 'width' ? value : value - (wrapSpace * ratio) ) );
+ F.inner[ prop ]( getScalar( prop === 'width' ? value : value - (wrapSpace * ratio) - (skinSpace * ratio) ) );
+ }
+ },
+
+ zoomIn: function () {
+ var current = F.current,
+ startPos = current.pos,
+ effect = current.openEffect,
+ elastic = effect === 'elastic',
+ endPos = $.extend({opacity : 1}, startPos);
+
+ // Remove "position" property that breaks older IE
+ delete endPos.position;
+
+ if (elastic) {
+ startPos = this.getOrigPosition();
+
+ if (current.openOpacity) {
+ startPos.opacity = 0.1;
+ }
+
+ } else if (effect === 'fade') {
+ startPos.opacity = 0.1;
+ }
+
+ F.wrap.css(startPos).animate(endPos, {
+ duration : effect === 'none' ? 0 : current.openSpeed,
+ easing : current.openEasing,
+ step : elastic ? this.step : null,
+ complete : F._afterZoomIn
+ });
+ },
+
+ zoomOut: function () {
+ var current = F.current,
+ effect = current.closeEffect,
+ elastic = effect === 'elastic',
+ endPos = {opacity : 0.1};
+
+ if (elastic) {
+ endPos = this.getOrigPosition();
+
+ if (current.closeOpacity) {
+ endPos.opacity = 0.1;
+ }
+ }
+
+ F.wrap.animate(endPos, {
+ duration : effect === 'none' ? 0 : current.closeSpeed,
+ easing : current.closeEasing,
+ step : elastic ? this.step : null,
+ complete : F._afterZoomOut
+ });
+ },
+
+ changeIn: function () {
+ var current = F.current,
+ effect = current.nextEffect,
+ startPos = current.pos,
+ endPos = { opacity : 1 },
+ direction = F.direction,
+ distance = 200,
+ field;
+
+ startPos.opacity = 0.1;
+
+ if (effect === 'elastic') {
+ field = direction === 'down' || direction === 'up' ? 'top' : 'left';
+
+ if (direction === 'down' || direction === 'right') {
+ startPos[ field ] = getValue(getScalar(startPos[ field ]) - distance);
+ endPos[ field ] = '+=' + distance + 'px';
+
+ } else {
+ startPos[ field ] = getValue(getScalar(startPos[ field ]) + distance);
+ endPos[ field ] = '-=' + distance + 'px';
+ }
+ }
+
+ // Workaround for http://bugs.jquery.com/ticket/12273
+ if (effect === 'none') {
+ F._afterZoomIn();
+
+ } else {
+ F.wrap.css(startPos).animate(endPos, {
+ duration : current.nextSpeed,
+ easing : current.nextEasing,
+ complete : F._afterZoomIn
+ });
+ }
+ },
+
+ changeOut: function () {
+ var previous = F.previous,
+ effect = previous.prevEffect,
+ endPos = { opacity : 0.1 },
+ direction = F.direction,
+ distance = 200;
+
+ if (effect === 'elastic') {
+ endPos[ direction === 'down' || direction === 'up' ? 'top' : 'left' ] = ( direction === 'up' || direction === 'left' ? '-' : '+' ) + '=' + distance + 'px';
+ }
+
+ previous.wrap.animate(endPos, {
+ duration : effect === 'none' ? 0 : previous.prevSpeed,
+ easing : previous.prevEasing,
+ complete : function () {
+ $(this).trigger('onReset').remove();
+ }
+ });
+ }
+ };
+
+ /*
+ * Overlay helper
+ */
+
+ F.helpers.overlay = {
+ defaults : {
+ closeClick : true, // if true, fancyBox will be closed when user clicks on the overlay
+ speedOut : 200, // duration of fadeOut animation
+ showEarly : true, // indicates if should be opened immediately or wait until the content is ready
+ css : {}, // custom CSS properties
+ locked : !isTouch, // if true, the content will be locked into overlay
+ fixed : true // if false, the overlay CSS position property will not be set to "fixed"
+ },
+
+ overlay : null, // current handle
+ fixed : false, // indicates if the overlay has position "fixed"
+ el : $('html'), // element that contains "the lock"
+
+ // Public methods
+ create : function(opts) {
+ opts = $.extend({}, this.defaults, opts);
+
+ if (this.overlay) {
+ this.close();
+ }
+
+ this.overlay = $('
').appendTo( F.coming ? F.coming.parent : opts.parent );
+ this.fixed = false;
+
+ if (opts.fixed && F.defaults.fixed) {
+ this.overlay.addClass('fancybox-overlay-fixed');
+
+ this.fixed = true;
+ }
+ },
+
+ open : function(opts) {
+ var that = this;
+
+ opts = $.extend({}, this.defaults, opts);
+
+ if (this.overlay) {
+ this.overlay.unbind('.overlay').width('auto').height('auto');
+
+ } else {
+ this.create(opts);
+ }
+
+ if (!this.fixed) {
+ W.bind('resize.overlay', $.proxy( this.update, this) );
+
+ this.update();
+ }
+
+ if (opts.closeClick) {
+ this.overlay.bind('click.overlay', function(e) {
+ if ($(e.target).hasClass('fancybox-overlay')) {
+ if (F.isActive) {
+ F.close();
+ } else {
+ that.close();
+ }
+
+ return false;
+ }
+ });
+ }
+
+ this.overlay.css( opts.css ).show();
+ },
+
+ close : function() {
+ var scrollV, scrollH;
+
+ W.unbind('resize.overlay');
+
+ if (this.el.hasClass('fancybox-lock')) {
+ $('.fancybox-margin').removeClass('fancybox-margin');
+
+ scrollV = W.scrollTop();
+ scrollH = W.scrollLeft();
+
+ this.el.removeClass('fancybox-lock');
+
+ W.scrollTop( scrollV ).scrollLeft( scrollH );
+ }
+
+ $('.fancybox-overlay').remove().hide();
+
+ $.extend(this, {
+ overlay : null,
+ fixed : false
+ });
+ },
+
+ // Private, callbacks
+
+ update : function () {
+ var width = '100%', offsetWidth;
+
+ // Reset width/height so it will not mess
+ this.overlay.width(width).height('100%');
+
+ // jQuery does not return reliable result for IE
+ if (IE) {
+ offsetWidth = Math.max(document.documentElement.offsetWidth, document.body.offsetWidth);
+
+ if (D.width() > offsetWidth) {
+ width = D.width();
+ }
+
+ } else if (D.width() > W.width()) {
+ width = D.width();
+ }
+
+ this.overlay.width(width).height(D.height());
+ },
+
+ // This is where we can manipulate DOM, because later it would cause iframes to reload
+ onReady : function (opts, obj) {
+ var overlay = this.overlay;
+
+ $('.fancybox-overlay').stop(true, true);
+
+ if (!overlay) {
+ this.create(opts);
+ }
+
+ if (opts.locked && this.fixed && obj.fixed) {
+ if (!overlay) {
+ this.margin = D.height() > W.height() ? $('html').css('margin-right').replace("px", "") : false;
+ }
+
+ obj.locked = this.overlay.append( obj.wrap );
+ obj.fixed = false;
+ }
+
+ if (opts.showEarly === true) {
+ this.beforeShow.apply(this, arguments);
+ }
+ },
+
+ beforeShow : function(opts, obj) {
+ var scrollV, scrollH;
+
+ if (obj.locked) {
+ if (this.margin !== false) {
+ $('*').filter(function(){
+ return ($(this).css('position') === 'fixed' && !$(this).hasClass("fancybox-overlay") && !$(this).hasClass("fancybox-wrap") );
+ }).addClass('fancybox-margin');
+
+ this.el.addClass('fancybox-margin');
+ }
+
+ scrollV = W.scrollTop();
+ scrollH = W.scrollLeft();
+
+ this.el.addClass('fancybox-lock');
+
+ W.scrollTop( scrollV ).scrollLeft( scrollH );
+ }
+
+ this.open(opts);
+ },
+
+ onUpdate : function() {
+ if (!this.fixed) {
+ this.update();
+ }
+ },
+
+ afterClose: function (opts) {
+ // Remove overlay if exists and fancyBox is not opening
+ // (e.g., it is not being open using afterClose callback)
+ //if (this.overlay && !F.isActive) {
+ if (this.overlay && !F.coming) {
+ this.overlay.fadeOut(opts.speedOut, $.proxy( this.close, this ));
+ }
+ }
+ };
+
+ /*
+ * Title helper
+ */
+
+ F.helpers.title = {
+ defaults : {
+ type : 'float', // 'float', 'inside', 'outside' or 'over',
+ position : 'bottom' // 'top' or 'bottom'
+ },
+
+ beforeShow: function (opts) {
+ var current = F.current,
+ text = current.title,
+ type = opts.type,
+ title,
+ target;
+
+ if ($.isFunction(text)) {
+ text = text.call(current.element, current);
+ }
+
+ if (!isString(text) || $.trim(text) === '') {
+ return;
+ }
+
+ title = $('
' + text + '
');
+
+ switch (type) {
+ case 'inside':
+ target = F.skin;
+ break;
+
+ case 'outside':
+ target = F.wrap;
+ break;
+
+ case 'over':
+ target = F.inner;
+ break;
+
+ default: // 'float'
+ target = F.skin;
+
+ title.appendTo('body');
+
+ if (IE) {
+ title.width( title.width() );
+ }
+
+ title.wrapInner('
');
+
+ //Increase bottom margin so this title will also fit into viewport
+ F.current.margin[2] += Math.abs( getScalar(title.css('margin-bottom')) );
+ break;
+ }
+
+ title[ (opts.position === 'top' ? 'prependTo' : 'appendTo') ](target);
+ }
+ };
+
+ // jQuery plugin initialization
+ $.fn.fancybox = function (options) {
+ var index,
+ that = $(this),
+ selector = this.selector || '',
+ run = function(e) {
+ var what = $(this).blur(), idx = index, relType, relVal;
+
+ if (!(e.ctrlKey || e.altKey || e.shiftKey || e.metaKey) && !what.is('.fancybox-wrap')) {
+ relType = options.groupAttr || 'data-fancybox-group';
+ relVal = what.attr(relType);
+
+ if (!relVal) {
+ relType = 'rel';
+ relVal = what.get(0)[ relType ];
+ }
+
+ if (relVal && relVal !== '' && relVal !== 'nofollow') {
+ what = selector.length ? $(selector) : that;
+ what = what.filter('[' + relType + '="' + relVal + '"]');
+ idx = what.index(this);
+ }
+
+ options.index = idx;
+
+ // Stop an event from bubbling if everything is fine
+ if (F.open(what, options) !== false) {
+ e.preventDefault();
+ }
+ }
+ };
+
+ options = options || {};
+ index = options.index || 0;
+
+ if (!selector || options.live === false) {
+ that.unbind('click.fb-start').bind('click.fb-start', run);
+
+ } else {
+ D.undelegate(selector, 'click.fb-start').delegate(selector + ":not('.fancybox-item, .fancybox-nav')", 'click.fb-start', run);
+ }
+
+ this.filter('[data-fancybox-start=1]').trigger('click');
+
+ return this;
+ };
+
+ // Tests that need a body at doc ready
+ D.ready(function() {
+ var w1, w2;
+
+ if ( $.scrollbarWidth === undefined ) {
+ // http://benalman.com/projects/jquery-misc-plugins/#scrollbarwidth
+ $.scrollbarWidth = function() {
+ var parent = $('
').appendTo('body'),
+ child = parent.children(),
+ width = child.innerWidth() - child.height( 99 ).innerWidth();
+
+ parent.remove();
+
+ return width;
+ };
+ }
+
+ if ( $.support.fixedPosition === undefined ) {
+ $.support.fixedPosition = (function() {
+ var elem = $('
').appendTo('body'),
+ fixed = ( elem[0].offsetTop === 20 || elem[0].offsetTop === 15 );
+
+ elem.remove();
+
+ return fixed;
+ }());
+ }
+
+ $.extend(F.defaults, {
+ scrollbarWidth : $.scrollbarWidth(),
+ fixed : $.support.fixedPosition,
+ parent : $('body')
+ });
+
+ //Get real width of page scroll-bar
+ w1 = $(window).width();
+
+ H.addClass('fancybox-lock-test');
+
+ w2 = $(window).width();
+
+ H.removeClass('fancybox-lock-test');
+
+ $("").appendTo("head");
+ });
+
+}(window, document, jQuery));
\ No newline at end of file
diff --git a/js/fancyBox/source/jquery.fancybox.pack.js b/js/fancyBox/source/jquery.fancybox.pack.js
new file mode 100644
index 0000000..73f7578
--- /dev/null
+++ b/js/fancyBox/source/jquery.fancybox.pack.js
@@ -0,0 +1,46 @@
+/*! fancyBox v2.1.5 fancyapps.com | fancyapps.com/fancybox/#license */
+(function(r,G,f,v){var J=f("html"),n=f(r),p=f(G),b=f.fancybox=function(){b.open.apply(this,arguments)},I=navigator.userAgent.match(/msie/i),B=null,s=G.createTouch!==v,t=function(a){return a&&a.hasOwnProperty&&a instanceof f},q=function(a){return a&&"string"===f.type(a)},E=function(a){return q(a)&&0
',image:'
',iframe:'
",error:'
The requested content cannot be loaded. Please try again later.
',closeBtn:'
',next:'
',prev:'
'},openEffect:"fade",openSpeed:250,openEasing:"swing",openOpacity:!0,
+openMethod:"zoomIn",closeEffect:"fade",closeSpeed:250,closeEasing:"swing",closeOpacity:!0,closeMethod:"zoomOut",nextEffect:"elastic",nextSpeed:250,nextEasing:"swing",nextMethod:"changeIn",prevEffect:"elastic",prevSpeed:250,prevEasing:"swing",prevMethod:"changeOut",helpers:{overlay:!0,title:!0},onCancel:f.noop,beforeLoad:f.noop,afterLoad:f.noop,beforeShow:f.noop,afterShow:f.noop,beforeChange:f.noop,beforeClose:f.noop,afterClose:f.noop},group:{},opts:{},previous:null,coming:null,current:null,isActive:!1,
+isOpen:!1,isOpened:!1,wrap:null,skin:null,outer:null,inner:null,player:{timer:null,isActive:!1},ajaxLoad:null,imgPreload:null,transitions:{},helpers:{},open:function(a,d){if(a&&(f.isPlainObject(d)||(d={}),!1!==b.close(!0)))return f.isArray(a)||(a=t(a)?f(a).get():[a]),f.each(a,function(e,c){var k={},g,h,j,m,l;"object"===f.type(c)&&(c.nodeType&&(c=f(c)),t(c)?(k={href:c.data("fancybox-href")||c.attr("href"),title:c.data("fancybox-title")||c.attr("title"),isDom:!0,element:c},f.metadata&&f.extend(!0,k,
+c.metadata())):k=c);g=d.href||k.href||(q(c)?c:null);h=d.title!==v?d.title:k.title||"";m=(j=d.content||k.content)?"html":d.type||k.type;!m&&k.isDom&&(m=c.data("fancybox-type"),m||(m=(m=c.prop("class").match(/fancybox\.(\w+)/))?m[1]:null));q(g)&&(m||(b.isImage(g)?m="image":b.isSWF(g)?m="swf":"#"===g.charAt(0)?m="inline":q(c)&&(m="html",j=c)),"ajax"===m&&(l=g.split(/\s+/,2),g=l.shift(),l=l.shift()));j||("inline"===m?g?j=f(q(g)?g.replace(/.*(?=#[^\s]+$)/,""):g):k.isDom&&(j=c):"html"===m?j=g:!m&&(!g&&
+k.isDom)&&(m="inline",j=c));f.extend(k,{href:g,type:m,content:j,title:h,selector:l});a[e]=k}),b.opts=f.extend(!0,{},b.defaults,d),d.keys!==v&&(b.opts.keys=d.keys?f.extend({},b.defaults.keys,d.keys):!1),b.group=a,b._start(b.opts.index)},cancel:function(){var a=b.coming;a&&!1!==b.trigger("onCancel")&&(b.hideLoading(),b.ajaxLoad&&b.ajaxLoad.abort(),b.ajaxLoad=null,b.imgPreload&&(b.imgPreload.onload=b.imgPreload.onerror=null),a.wrap&&a.wrap.stop(!0,!0).trigger("onReset").remove(),b.coming=null,b.current||
+b._afterZoomOut(a))},close:function(a){b.cancel();!1!==b.trigger("beforeClose")&&(b.unbindEvents(),b.isActive&&(!b.isOpen||!0===a?(f(".fancybox-wrap").stop(!0).trigger("onReset").remove(),b._afterZoomOut()):(b.isOpen=b.isOpened=!1,b.isClosing=!0,f(".fancybox-item, .fancybox-nav").remove(),b.wrap.stop(!0,!0).removeClass("fancybox-opened"),b.transitions[b.current.closeMethod]())))},play:function(a){var d=function(){clearTimeout(b.player.timer)},e=function(){d();b.current&&b.player.isActive&&(b.player.timer=
+setTimeout(b.next,b.current.playSpeed))},c=function(){d();p.unbind(".player");b.player.isActive=!1;b.trigger("onPlayEnd")};if(!0===a||!b.player.isActive&&!1!==a){if(b.current&&(b.current.loop||b.current.index
=c.index?"next":"prev"],b.router=e||"jumpto",c.loop&&(0>a&&(a=c.group.length+a%c.group.length),a%=c.group.length),c.group[a]!==v&&(b.cancel(),b._start(a)))},reposition:function(a,d){var e=b.current,c=e?e.wrap:null,k;c&&(k=b._getPosition(d),a&&"scroll"===a.type?(delete k.position,c.stop(!0,!0).animate(k,200)):(c.css(k),e.pos=f.extend({},e.dim,k)))},update:function(a){var d=
+a&&a.type,e=!d||"orientationchange"===d;e&&(clearTimeout(B),B=null);b.isOpen&&!B&&(B=setTimeout(function(){var c=b.current;c&&!b.isClosing&&(b.wrap.removeClass("fancybox-tmp"),(e||"load"===d||"resize"===d&&c.autoResize)&&b._setDimension(),"scroll"===d&&c.canShrink||b.reposition(a),b.trigger("onUpdate"),B=null)},e&&!s?0:300))},toggle:function(a){b.isOpen&&(b.current.fitToView="boolean"===f.type(a)?a:!b.current.fitToView,s&&(b.wrap.removeAttr("style").addClass("fancybox-tmp"),b.trigger("onUpdate")),
+b.update())},hideLoading:function(){p.unbind(".loading");f("#fancybox-loading").remove()},showLoading:function(){var a,d;b.hideLoading();a=f('').click(b.cancel).appendTo("body");p.bind("keydown.loading",function(a){if(27===(a.which||a.keyCode))a.preventDefault(),b.cancel()});b.defaults.fixed||(d=b.getViewport(),a.css({position:"absolute",top:0.5*d.h+d.y,left:0.5*d.w+d.x}))},getViewport:function(){var a=b.current&&b.current.locked||!1,d={x:n.scrollLeft(),
+y:n.scrollTop()};a?(d.w=a[0].clientWidth,d.h=a[0].clientHeight):(d.w=s&&r.innerWidth?r.innerWidth:n.width(),d.h=s&&r.innerHeight?r.innerHeight:n.height());return d},unbindEvents:function(){b.wrap&&t(b.wrap)&&b.wrap.unbind(".fb");p.unbind(".fb");n.unbind(".fb")},bindEvents:function(){var a=b.current,d;a&&(n.bind("orientationchange.fb"+(s?"":" resize.fb")+(a.autoCenter&&!a.locked?" scroll.fb":""),b.update),(d=a.keys)&&p.bind("keydown.fb",function(e){var c=e.which||e.keyCode,k=e.target||e.srcElement;
+if(27===c&&b.coming)return!1;!e.ctrlKey&&(!e.altKey&&!e.shiftKey&&!e.metaKey&&(!k||!k.type&&!f(k).is("[contenteditable]")))&&f.each(d,function(d,k){if(1h[0].clientWidth||h[0].clientHeight&&h[0].scrollHeight>h[0].clientHeight),h=f(h).parent();if(0!==c&&!j&&1g||0>k)b.next(0>g?"up":"right");d.preventDefault()}}))},trigger:function(a,d){var e,c=d||b.coming||b.current;if(c){f.isFunction(c[a])&&(e=c[a].apply(c,Array.prototype.slice.call(arguments,1)));if(!1===e)return!1;c.helpers&&f.each(c.helpers,function(d,e){if(e&&b.helpers[d]&&f.isFunction(b.helpers[d][a]))b.helpers[d][a](f.extend(!0,
+{},b.helpers[d].defaults,e),c)});p.trigger(a)}},isImage:function(a){return q(a)&&a.match(/(^data:image\/.*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg)((\?|#).*)?$)/i)},isSWF:function(a){return q(a)&&a.match(/\.(swf)((\?|#).*)?$/i)},_start:function(a){var d={},e,c;a=l(a);e=b.group[a]||null;if(!e)return!1;d=f.extend(!0,{},b.opts,e);e=d.margin;c=d.padding;"number"===f.type(e)&&(d.margin=[e,e,e,e]);"number"===f.type(c)&&(d.padding=[c,c,c,c]);d.modal&&f.extend(!0,d,{closeBtn:!1,closeClick:!1,nextClick:!1,arrows:!1,
+mouseWheel:!1,keys:null,helpers:{overlay:{closeClick:!1}}});d.autoSize&&(d.autoWidth=d.autoHeight=!0);"auto"===d.width&&(d.autoWidth=!0);"auto"===d.height&&(d.autoHeight=!0);d.group=b.group;d.index=a;b.coming=d;if(!1===b.trigger("beforeLoad"))b.coming=null;else{c=d.type;e=d.href;if(!c)return b.coming=null,b.current&&b.router&&"jumpto"!==b.router?(b.current.index=a,b[b.router](b.direction)):!1;b.isActive=!0;if("image"===c||"swf"===c)d.autoHeight=d.autoWidth=!1,d.scrolling="visible";"image"===c&&(d.aspectRatio=
+!0);"iframe"===c&&s&&(d.scrolling="scroll");d.wrap=f(d.tpl.wrap).addClass("fancybox-"+(s?"mobile":"desktop")+" fancybox-type-"+c+" fancybox-tmp "+d.wrapCSS).appendTo(d.parent||"body");f.extend(d,{skin:f(".fancybox-skin",d.wrap),outer:f(".fancybox-outer",d.wrap),inner:f(".fancybox-inner",d.wrap)});f.each(["Top","Right","Bottom","Left"],function(a,b){d.skin.css("padding"+b,w(d.padding[a]))});b.trigger("onReady");if("inline"===c||"html"===c){if(!d.content||!d.content.length)return b._error("content")}else if(!e)return b._error("href");
+"image"===c?b._loadImage():"ajax"===c?b._loadAjax():"iframe"===c?b._loadIframe():b._afterLoad()}},_error:function(a){f.extend(b.coming,{type:"html",autoWidth:!0,autoHeight:!0,minWidth:0,minHeight:0,scrolling:"no",hasError:a,content:b.coming.tpl.error});b._afterLoad()},_loadImage:function(){var a=b.imgPreload=new Image;a.onload=function(){this.onload=this.onerror=null;b.coming.width=this.width/b.opts.pixelRatio;b.coming.height=this.height/b.opts.pixelRatio;b._afterLoad()};a.onerror=function(){this.onload=
+this.onerror=null;b._error("image")};a.src=b.coming.href;!0!==a.complete&&b.showLoading()},_loadAjax:function(){var a=b.coming;b.showLoading();b.ajaxLoad=f.ajax(f.extend({},a.ajax,{url:a.href,error:function(a,e){b.coming&&"abort"!==e?b._error("ajax",a):b.hideLoading()},success:function(d,e){"success"===e&&(a.content=d,b._afterLoad())}}))},_loadIframe:function(){var a=b.coming,d=f(a.tpl.iframe.replace(/\{rnd\}/g,(new Date).getTime())).attr("scrolling",s?"auto":a.iframe.scrolling).attr("src",a.href);
+f(a.wrap).bind("onReset",function(){try{f(this).find("iframe").hide().attr("src","//about:blank").end().empty()}catch(a){}});a.iframe.preload&&(b.showLoading(),d.one("load",function(){f(this).data("ready",1);s||f(this).bind("load.fb",b.update);f(this).parents(".fancybox-wrap").width("100%").removeClass("fancybox-tmp").show();b._afterLoad()}));a.content=d.appendTo(a.inner);a.iframe.preload||b._afterLoad()},_preloadImages:function(){var a=b.group,d=b.current,e=a.length,c=d.preload?Math.min(d.preload,
+e-1):0,f,g;for(g=1;g<=c;g+=1)f=a[(d.index+g)%e],"image"===f.type&&f.href&&((new Image).src=f.href)},_afterLoad:function(){var a=b.coming,d=b.current,e,c,k,g,h;b.hideLoading();if(a&&!1!==b.isActive)if(!1===b.trigger("afterLoad",a,d))a.wrap.stop(!0).trigger("onReset").remove(),b.coming=null;else{d&&(b.trigger("beforeChange",d),d.wrap.stop(!0).removeClass("fancybox-opened").find(".fancybox-item, .fancybox-nav").remove());b.unbindEvents();e=a.content;c=a.type;k=a.scrolling;f.extend(b,{wrap:a.wrap,skin:a.skin,
+outer:a.outer,inner:a.inner,current:a,previous:d});g=a.href;switch(c){case "inline":case "ajax":case "html":a.selector?e=f("").html(e).find(a.selector):t(e)&&(e.data("fancybox-placeholder")||e.data("fancybox-placeholder",f('
').insertAfter(e).hide()),e=e.show().detach(),a.wrap.bind("onReset",function(){f(this).find(e).length&&e.hide().replaceAll(e.data("fancybox-placeholder")).data("fancybox-placeholder",!1)}));break;case "image":e=a.tpl.image.replace("{href}",
+g);break;case "swf":e='
',h="",f.each(a.swf,function(a,b){e+=' ';h+=" "+a+'="'+b+'"'}),e+='"}(!t(e)||!e.parent().is(a.inner))&&a.inner.append(e);b.trigger("beforeShow");a.inner.css("overflow","yes"===k?"scroll":
+"no"===k?"hidden":k);b._setDimension();b.reposition();b.isOpen=!1;b.coming=null;b.bindEvents();if(b.isOpened){if(d.prevMethod)b.transitions[d.prevMethod]()}else f(".fancybox-wrap").not(a.wrap).stop(!0).trigger("onReset").remove();b.transitions[b.isOpened?a.nextMethod:a.openMethod]();b._preloadImages()}},_setDimension:function(){var a=b.getViewport(),d=0,e=!1,c=!1,e=b.wrap,k=b.skin,g=b.inner,h=b.current,c=h.width,j=h.height,m=h.minWidth,u=h.minHeight,n=h.maxWidth,p=h.maxHeight,s=h.scrolling,q=h.scrollOutside?
+h.scrollbarWidth:0,x=h.margin,y=l(x[1]+x[3]),r=l(x[0]+x[2]),v,z,t,C,A,F,B,D,H;e.add(k).add(g).width("auto").height("auto").removeClass("fancybox-tmp");x=l(k.outerWidth(!0)-k.width());v=l(k.outerHeight(!0)-k.height());z=y+x;t=r+v;C=E(c)?(a.w-z)*l(c)/100:c;A=E(j)?(a.h-t)*l(j)/100:j;if("iframe"===h.type){if(H=h.content,h.autoHeight&&1===H.data("ready"))try{H[0].contentWindow.document.location&&(g.width(C).height(9999),F=H.contents().find("body"),q&&F.css("overflow-x","hidden"),A=F.outerHeight(!0))}catch(G){}}else if(h.autoWidth||
+h.autoHeight)g.addClass("fancybox-tmp"),h.autoWidth||g.width(C),h.autoHeight||g.height(A),h.autoWidth&&(C=g.width()),h.autoHeight&&(A=g.height()),g.removeClass("fancybox-tmp");c=l(C);j=l(A);D=C/A;m=l(E(m)?l(m,"w")-z:m);n=l(E(n)?l(n,"w")-z:n);u=l(E(u)?l(u,"h")-t:u);p=l(E(p)?l(p,"h")-t:p);F=n;B=p;h.fitToView&&(n=Math.min(a.w-z,n),p=Math.min(a.h-t,p));z=a.w-y;r=a.h-r;h.aspectRatio?(c>n&&(c=n,j=l(c/D)),j>p&&(j=p,c=l(j*D)),c
z||y>r)&&(c>m&&j>u)&&!(19n&&(c=n,j=l(c/D)),g.width(c).height(j),e.width(c+x),a=e.width(),y=e.height();else c=Math.max(m,Math.min(c,c-(a-z))),j=Math.max(u,Math.min(j,j-(y-r)));q&&("auto"===s&&jz||y>r)&&c>m&&j>u;c=h.aspectRatio?cu&&j
').appendTo(b.coming?b.coming.parent:a.parent);this.fixed=!1;a.fixed&&b.defaults.fixed&&(this.overlay.addClass("fancybox-overlay-fixed"),this.fixed=!0)},open:function(a){var d=this;a=f.extend({},this.defaults,a);this.overlay?this.overlay.unbind(".overlay").width("auto").height("auto"):this.create(a);this.fixed||(n.bind("resize.overlay",f.proxy(this.update,this)),this.update());a.closeClick&&this.overlay.bind("click.overlay",function(a){if(f(a.target).hasClass("fancybox-overlay"))return b.isActive?
+b.close():d.close(),!1});this.overlay.css(a.css).show()},close:function(){var a,b;n.unbind("resize.overlay");this.el.hasClass("fancybox-lock")&&(f(".fancybox-margin").removeClass("fancybox-margin"),a=n.scrollTop(),b=n.scrollLeft(),this.el.removeClass("fancybox-lock"),n.scrollTop(a).scrollLeft(b));f(".fancybox-overlay").remove().hide();f.extend(this,{overlay:null,fixed:!1})},update:function(){var a="100%",b;this.overlay.width(a).height("100%");I?(b=Math.max(G.documentElement.offsetWidth,G.body.offsetWidth),
+p.width()>b&&(a=p.width())):p.width()>n.width()&&(a=p.width());this.overlay.width(a).height(p.height())},onReady:function(a,b){var e=this.overlay;f(".fancybox-overlay").stop(!0,!0);e||this.create(a);a.locked&&(this.fixed&&b.fixed)&&(e||(this.margin=p.height()>n.height()?f("html").css("margin-right").replace("px",""):!1),b.locked=this.overlay.append(b.wrap),b.fixed=!1);!0===a.showEarly&&this.beforeShow.apply(this,arguments)},beforeShow:function(a,b){var e,c;b.locked&&(!1!==this.margin&&(f("*").filter(function(){return"fixed"===
+f(this).css("position")&&!f(this).hasClass("fancybox-overlay")&&!f(this).hasClass("fancybox-wrap")}).addClass("fancybox-margin"),this.el.addClass("fancybox-margin")),e=n.scrollTop(),c=n.scrollLeft(),this.el.addClass("fancybox-lock"),n.scrollTop(e).scrollLeft(c));this.open(a)},onUpdate:function(){this.fixed||this.update()},afterClose:function(a){this.overlay&&!b.coming&&this.overlay.fadeOut(a.speedOut,f.proxy(this.close,this))}};b.helpers.title={defaults:{type:"float",position:"bottom"},beforeShow:function(a){var d=
+b.current,e=d.title,c=a.type;f.isFunction(e)&&(e=e.call(d.element,d));if(q(e)&&""!==f.trim(e)){d=f(''+e+"
");switch(c){case "inside":c=b.skin;break;case "outside":c=b.wrap;break;case "over":c=b.inner;break;default:c=b.skin,d.appendTo("body"),I&&d.width(d.width()),d.wrapInner(' '),b.current.margin[2]+=Math.abs(l(d.css("margin-bottom")))}d["top"===a.position?"prependTo":"appendTo"](c)}}};f.fn.fancybox=function(a){var d,
+e=f(this),c=this.selector||"",k=function(g){var h=f(this).blur(),j=d,k,l;!g.ctrlKey&&(!g.altKey&&!g.shiftKey&&!g.metaKey)&&!h.is(".fancybox-wrap")&&(k=a.groupAttr||"data-fancybox-group",l=h.attr(k),l||(k="rel",l=h.get(0)[k]),l&&(""!==l&&"nofollow"!==l)&&(h=c.length?f(c):e,h=h.filter("["+k+'="'+l+'"]'),j=h.index(this)),a.index=j,!1!==b.open(h,a)&&g.preventDefault())};a=a||{};d=a.index||0;!c||!1===a.live?e.unbind("click.fb-start").bind("click.fb-start",k):p.undelegate(c,"click.fb-start").delegate(c+
+":not('.fancybox-item, .fancybox-nav')","click.fb-start",k);this.filter("[data-fancybox-start=1]").trigger("click");return this};p.ready(function(){var a,d;f.scrollbarWidth===v&&(f.scrollbarWidth=function(){var a=f('').appendTo("body"),b=a.children(),b=b.innerWidth()-b.height(99).innerWidth();a.remove();return b});if(f.support.fixedPosition===v){a=f.support;d=f('
').appendTo("body");var e=20===
+d[0].offsetTop||15===d[0].offsetTop;d.remove();a.fixedPosition=e}f.extend(b.defaults,{scrollbarWidth:f.scrollbarWidth(),fixed:f.support.fixedPosition,parent:f("body")});a=f(r).width();J.addClass("fancybox-lock-test");d=f(r).width();J.removeClass("fancybox-lock-test");f("").appendTo("head")})})(window,document,jQuery);
\ No newline at end of file
diff --git a/js/fancyBox/sprite.psd b/js/fancyBox/sprite.psd
new file mode 100644
index 0000000..6f2032d
Binary files /dev/null and b/js/fancyBox/sprite.psd differ
diff --git a/js/jquery-1.9.1.min.js b/js/jquery-1.9.1.min.js
new file mode 100755
index 0000000..006e953
--- /dev/null
+++ b/js/jquery-1.9.1.min.js
@@ -0,0 +1,5 @@
+/*! jQuery v1.9.1 | (c) 2005, 2012 jQuery Foundation, Inc. | jquery.org/license
+//@ sourceMappingURL=jquery.min.map
+*/(function(e,t){var n,r,i=typeof t,o=e.document,a=e.location,s=e.jQuery,u=e.$,l={},c=[],p="1.9.1",f=c.concat,d=c.push,h=c.slice,g=c.indexOf,m=l.toString,y=l.hasOwnProperty,v=p.trim,b=function(e,t){return new b.fn.init(e,t,r)},x=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,w=/\S+/g,T=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,N=/^(?:(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,k=/^[\],:{}\s]*$/,E=/(?:^|:|,)(?:\s*\[)+/g,S=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,A=/"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,j=/^-ms-/,D=/-([\da-z])/gi,L=function(e,t){return t.toUpperCase()},H=function(e){(o.addEventListener||"load"===e.type||"complete"===o.readyState)&&(q(),b.ready())},q=function(){o.addEventListener?(o.removeEventListener("DOMContentLoaded",H,!1),e.removeEventListener("load",H,!1)):(o.detachEvent("onreadystatechange",H),e.detachEvent("onload",H))};b.fn=b.prototype={jquery:p,constructor:b,init:function(e,n,r){var i,a;if(!e)return this;if("string"==typeof e){if(i="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:N.exec(e),!i||!i[1]&&n)return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e);if(i[1]){if(n=n instanceof b?n[0]:n,b.merge(this,b.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:o,!0)),C.test(i[1])&&b.isPlainObject(n))for(i in n)b.isFunction(this[i])?this[i](n[i]):this.attr(i,n[i]);return this}if(a=o.getElementById(i[2]),a&&a.parentNode){if(a.id!==i[2])return r.find(e);this.length=1,this[0]=a}return this.context=o,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):b.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),b.makeArray(e,this))},selector:"",length:0,size:function(){return this.length},toArray:function(){return h.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=b.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return b.each(this,e,t)},ready:function(e){return b.ready.promise().done(e),this},slice:function(){return this.pushStack(h.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(b.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:d,sort:[].sort,splice:[].splice},b.fn.init.prototype=b.fn,b.extend=b.fn.extend=function(){var e,n,r,i,o,a,s=arguments[0]||{},u=1,l=arguments.length,c=!1;for("boolean"==typeof s&&(c=s,s=arguments[1]||{},u=2),"object"==typeof s||b.isFunction(s)||(s={}),l===u&&(s=this,--u);l>u;u++)if(null!=(o=arguments[u]))for(i in o)e=s[i],r=o[i],s!==r&&(c&&r&&(b.isPlainObject(r)||(n=b.isArray(r)))?(n?(n=!1,a=e&&b.isArray(e)?e:[]):a=e&&b.isPlainObject(e)?e:{},s[i]=b.extend(c,a,r)):r!==t&&(s[i]=r));return s},b.extend({noConflict:function(t){return e.$===b&&(e.$=u),t&&e.jQuery===b&&(e.jQuery=s),b},isReady:!1,readyWait:1,holdReady:function(e){e?b.readyWait++:b.ready(!0)},ready:function(e){if(e===!0?!--b.readyWait:!b.isReady){if(!o.body)return setTimeout(b.ready);b.isReady=!0,e!==!0&&--b.readyWait>0||(n.resolveWith(o,[b]),b.fn.trigger&&b(o).trigger("ready").off("ready"))}},isFunction:function(e){return"function"===b.type(e)},isArray:Array.isArray||function(e){return"array"===b.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[m.call(e)]||"object":typeof e},isPlainObject:function(e){if(!e||"object"!==b.type(e)||e.nodeType||b.isWindow(e))return!1;try{if(e.constructor&&!y.call(e,"constructor")&&!y.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(n){return!1}var r;for(r in e);return r===t||y.call(e,r)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||o;var r=C.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=b.buildFragment([e],t,i),i&&b(i).remove(),b.merge([],r.childNodes))},parseJSON:function(n){return e.JSON&&e.JSON.parse?e.JSON.parse(n):null===n?n:"string"==typeof n&&(n=b.trim(n),n&&k.test(n.replace(S,"@").replace(A,"]").replace(E,"")))?Function("return "+n)():(b.error("Invalid JSON: "+n),t)},parseXML:function(n){var r,i;if(!n||"string"!=typeof n)return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(o){r=t}return r&&r.documentElement&&!r.getElementsByTagName("parsererror").length||b.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&b.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(j,"ms-").replace(D,L)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,a=M(e);if(n){if(a){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(a){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:v&&!v.call("\ufeff\u00a0")?function(e){return null==e?"":v.call(e)}:function(e){return null==e?"":(e+"").replace(T,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(M(Object(e))?b.merge(n,"string"==typeof e?[e]:e):d.call(n,e)),n},inArray:function(e,t,n){var r;if(t){if(g)return g.call(t,e,n);for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,o=0;if("number"==typeof r)for(;r>o;o++)e[i++]=n[o];else while(n[o]!==t)e[i++]=n[o++];return e.length=i,e},grep:function(e,t,n){var r,i=[],o=0,a=e.length;for(n=!!n;a>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,a=M(e),s=[];if(a)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(s[s.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(s[s.length]=r);return f.apply([],s)},guid:1,proxy:function(e,n){var r,i,o;return"string"==typeof n&&(o=e[n],n=e,e=o),b.isFunction(e)?(r=h.call(arguments,2),i=function(){return e.apply(n||this,r.concat(h.call(arguments)))},i.guid=e.guid=e.guid||b.guid++,i):t},access:function(e,n,r,i,o,a,s){var u=0,l=e.length,c=null==r;if("object"===b.type(r)){o=!0;for(u in r)b.access(e,n,u,r[u],!0,a,s)}else if(i!==t&&(o=!0,b.isFunction(i)||(s=!0),c&&(s?(n.call(e,i),n=null):(c=n,n=function(e,t,n){return c.call(b(e),n)})),n))for(;l>u;u++)n(e[u],r,s?i:i.call(e[u],u,n(e[u],r)));return o?e:c?n.call(e):l?n(e[0],r):a},now:function(){return(new Date).getTime()}}),b.ready.promise=function(t){if(!n)if(n=b.Deferred(),"complete"===o.readyState)setTimeout(b.ready);else if(o.addEventListener)o.addEventListener("DOMContentLoaded",H,!1),e.addEventListener("load",H,!1);else{o.attachEvent("onreadystatechange",H),e.attachEvent("onload",H);var r=!1;try{r=null==e.frameElement&&o.documentElement}catch(i){}r&&r.doScroll&&function a(){if(!b.isReady){try{r.doScroll("left")}catch(e){return setTimeout(a,50)}q(),b.ready()}}()}return n.promise(t)},b.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){l["[object "+t+"]"]=t.toLowerCase()});function M(e){var t=e.length,n=b.type(e);return b.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}r=b(o);var _={};function F(e){var t=_[e]={};return b.each(e.match(w)||[],function(e,n){t[n]=!0}),t}b.Callbacks=function(e){e="string"==typeof e?_[e]||F(e):b.extend({},e);var n,r,i,o,a,s,u=[],l=!e.once&&[],c=function(t){for(r=e.memory&&t,i=!0,a=s||0,s=0,o=u.length,n=!0;u&&o>a;a++)if(u[a].apply(t[0],t[1])===!1&&e.stopOnFalse){r=!1;break}n=!1,u&&(l?l.length&&c(l.shift()):r?u=[]:p.disable())},p={add:function(){if(u){var t=u.length;(function i(t){b.each(t,function(t,n){var r=b.type(n);"function"===r?e.unique&&p.has(n)||u.push(n):n&&n.length&&"string"!==r&&i(n)})})(arguments),n?o=u.length:r&&(s=t,c(r))}return this},remove:function(){return u&&b.each(arguments,function(e,t){var r;while((r=b.inArray(t,u,r))>-1)u.splice(r,1),n&&(o>=r&&o--,a>=r&&a--)}),this},has:function(e){return e?b.inArray(e,u)>-1:!(!u||!u.length)},empty:function(){return u=[],this},disable:function(){return u=l=r=t,this},disabled:function(){return!u},lock:function(){return l=t,r||p.disable(),this},locked:function(){return!l},fireWith:function(e,t){return t=t||[],t=[e,t.slice?t.slice():t],!u||i&&!l||(n?l.push(t):c(t)),this},fire:function(){return p.fireWith(this,arguments),this},fired:function(){return!!i}};return p},b.extend({Deferred:function(e){var t=[["resolve","done",b.Callbacks("once memory"),"resolved"],["reject","fail",b.Callbacks("once memory"),"rejected"],["notify","progress",b.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return b.Deferred(function(n){b.each(t,function(t,o){var a=o[0],s=b.isFunction(e[t])&&e[t];i[o[1]](function(){var e=s&&s.apply(this,arguments);e&&b.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a+"With"](this===r?n.promise():this,s?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?b.extend(e,r):r}},i={};return r.pipe=r.then,b.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=h.call(arguments),r=n.length,i=1!==r||e&&b.isFunction(e.promise)?r:0,o=1===i?e:b.Deferred(),a=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?h.call(arguments):r,n===s?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},s,u,l;if(r>1)for(s=Array(r),u=Array(r),l=Array(r);r>t;t++)n[t]&&b.isFunction(n[t].promise)?n[t].promise().done(a(t,l,n)).fail(o.reject).progress(a(t,u,s)):--i;return i||o.resolveWith(l,n),o.promise()}}),b.support=function(){var t,n,r,a,s,u,l,c,p,f,d=o.createElement("div");if(d.setAttribute("className","t"),d.innerHTML=" a ",n=d.getElementsByTagName("*"),r=d.getElementsByTagName("a")[0],!n||!r||!n.length)return{};s=o.createElement("select"),l=s.appendChild(o.createElement("option")),a=d.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t={getSetAttribute:"t"!==d.className,leadingWhitespace:3===d.firstChild.nodeType,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/top/.test(r.getAttribute("style")),hrefNormalized:"/a"===r.getAttribute("href"),opacity:/^0.5/.test(r.style.opacity),cssFloat:!!r.style.cssFloat,checkOn:!!a.value,optSelected:l.selected,enctype:!!o.createElement("form").enctype,html5Clone:"<:nav>"!==o.createElement("nav").cloneNode(!0).outerHTML,boxModel:"CSS1Compat"===o.compatMode,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},a.checked=!0,t.noCloneChecked=a.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!l.disabled;try{delete d.test}catch(h){t.deleteExpando=!1}a=o.createElement("input"),a.setAttribute("value",""),t.input=""===a.getAttribute("value"),a.value="t",a.setAttribute("type","radio"),t.radioValue="t"===a.value,a.setAttribute("checked","t"),a.setAttribute("name","t"),u=o.createDocumentFragment(),u.appendChild(a),t.appendChecked=a.checked,t.checkClone=u.cloneNode(!0).cloneNode(!0).lastChild.checked,d.attachEvent&&(d.attachEvent("onclick",function(){t.noCloneEvent=!1}),d.cloneNode(!0).click());for(f in{submit:!0,change:!0,focusin:!0})d.setAttribute(c="on"+f,"t"),t[f+"Bubbles"]=c in e||d.attributes[c].expando===!1;return d.style.backgroundClip="content-box",d.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===d.style.backgroundClip,b(function(){var n,r,a,s="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",u=o.getElementsByTagName("body")[0];u&&(n=o.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",u.appendChild(n).appendChild(d),d.innerHTML="",a=d.getElementsByTagName("td"),a[0].style.cssText="padding:0;margin:0;border:0;display:none",p=0===a[0].offsetHeight,a[0].style.display="",a[1].style.display="none",t.reliableHiddenOffsets=p&&0===a[0].offsetHeight,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",t.boxSizing=4===d.offsetWidth,t.doesNotIncludeMarginInBodyOffset=1!==u.offsetTop,e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(d,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(d,null)||{width:"4px"}).width,r=d.appendChild(o.createElement("div")),r.style.cssText=d.style.cssText=s,r.style.marginRight=r.style.width="0",d.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),typeof d.style.zoom!==i&&(d.innerHTML="",d.style.cssText=s+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=3===d.offsetWidth,d.style.display="block",d.innerHTML="
",d.firstChild.style.width="5px",t.shrinkWrapBlocks=3!==d.offsetWidth,t.inlineBlockNeedsLayout&&(u.style.zoom=1)),u.removeChild(n),n=d=a=r=null)}),n=s=u=l=r=a=null,t}();var O=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,B=/([A-Z])/g;function P(e,n,r,i){if(b.acceptData(e)){var o,a,s=b.expando,u="string"==typeof n,l=e.nodeType,p=l?b.cache:e,f=l?e[s]:e[s]&&s;if(f&&p[f]&&(i||p[f].data)||!u||r!==t)return f||(l?e[s]=f=c.pop()||b.guid++:f=s),p[f]||(p[f]={},l||(p[f].toJSON=b.noop)),("object"==typeof n||"function"==typeof n)&&(i?p[f]=b.extend(p[f],n):p[f].data=b.extend(p[f].data,n)),o=p[f],i||(o.data||(o.data={}),o=o.data),r!==t&&(o[b.camelCase(n)]=r),u?(a=o[n],null==a&&(a=o[b.camelCase(n)])):a=o,a}}function R(e,t,n){if(b.acceptData(e)){var r,i,o,a=e.nodeType,s=a?b.cache:e,u=a?e[b.expando]:b.expando;if(s[u]){if(t&&(o=n?s[u]:s[u].data)){b.isArray(t)?t=t.concat(b.map(t,b.camelCase)):t in o?t=[t]:(t=b.camelCase(t),t=t in o?[t]:t.split(" "));for(r=0,i=t.length;i>r;r++)delete o[t[r]];if(!(n?$:b.isEmptyObject)(o))return}(n||(delete s[u].data,$(s[u])))&&(a?b.cleanData([e],!0):b.support.deleteExpando||s!=s.window?delete s[u]:s[u]=null)}}}b.extend({cache:{},expando:"jQuery"+(p+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(e){return e=e.nodeType?b.cache[e[b.expando]]:e[b.expando],!!e&&!$(e)},data:function(e,t,n){return P(e,t,n)},removeData:function(e,t){return R(e,t)},_data:function(e,t,n){return P(e,t,n,!0)},_removeData:function(e,t){return R(e,t,!0)},acceptData:function(e){if(e.nodeType&&1!==e.nodeType&&9!==e.nodeType)return!1;var t=e.nodeName&&b.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),b.fn.extend({data:function(e,n){var r,i,o=this[0],a=0,s=null;if(e===t){if(this.length&&(s=b.data(o),1===o.nodeType&&!b._data(o,"parsedAttrs"))){for(r=o.attributes;r.length>a;a++)i=r[a].name,i.indexOf("data-")||(i=b.camelCase(i.slice(5)),W(o,i,s[i]));b._data(o,"parsedAttrs",!0)}return s}return"object"==typeof e?this.each(function(){b.data(this,e)}):b.access(this,function(n){return n===t?o?W(o,e,b.data(o,e)):null:(this.each(function(){b.data(this,e,n)}),t)},null,n,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){b.removeData(this,e)})}});function W(e,n,r){if(r===t&&1===e.nodeType){var i="data-"+n.replace(B,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"==typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null:+r+""===r?+r:O.test(r)?b.parseJSON(r):r}catch(o){}b.data(e,n,r)}else r=t}return r}function $(e){var t;for(t in e)if(("data"!==t||!b.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}b.extend({queue:function(e,n,r){var i;return e?(n=(n||"fx")+"queue",i=b._data(e,n),r&&(!i||b.isArray(r)?i=b._data(e,n,b.makeArray(r)):i.push(r)),i||[]):t},dequeue:function(e,t){t=t||"fx";var n=b.queue(e,t),r=n.length,i=n.shift(),o=b._queueHooks(e,t),a=function(){b.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),o.cur=i,i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return b._data(e,n)||b._data(e,n,{empty:b.Callbacks("once memory").add(function(){b._removeData(e,t+"queue"),b._removeData(e,n)})})}}),b.fn.extend({queue:function(e,n){var r=2;return"string"!=typeof e&&(n=e,e="fx",r--),r>arguments.length?b.queue(this[0],e):n===t?this:this.each(function(){var t=b.queue(this,e,n);b._queueHooks(this,e),"fx"===e&&"inprogress"!==t[0]&&b.dequeue(this,e)})},dequeue:function(e){return this.each(function(){b.dequeue(this,e)})},delay:function(e,t){return e=b.fx?b.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,o=b.Deferred(),a=this,s=this.length,u=function(){--i||o.resolveWith(a,[a])};"string"!=typeof e&&(n=e,e=t),e=e||"fx";while(s--)r=b._data(a[s],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(u));return u(),o.promise(n)}});var I,z,X=/[\t\r\n]/g,U=/\r/g,V=/^(?:input|select|textarea|button|object)$/i,Y=/^(?:a|area)$/i,J=/^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i,G=/^(?:checked|selected)$/i,Q=b.support.getSetAttribute,K=b.support.input;b.fn.extend({attr:function(e,t){return b.access(this,b.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){b.removeAttr(this,e)})},prop:function(e,t){return b.access(this,b.prop,e,t,arguments.length>1)},removeProp:function(e){return e=b.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,o,a=0,s=this.length,u="string"==typeof e&&e;if(b.isFunction(e))return this.each(function(t){b(this).addClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(X," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=b.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,a=0,s=this.length,u=0===arguments.length||"string"==typeof e&&e;if(b.isFunction(e))return this.each(function(t){b(this).removeClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(X," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?b.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e,r="boolean"==typeof t;return b.isFunction(e)?this.each(function(n){b(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var o,a=0,s=b(this),u=t,l=e.match(w)||[];while(o=l[a++])u=r?u:!s.hasClass(o),s[u?"addClass":"removeClass"](o)}else(n===i||"boolean"===n)&&(this.className&&b._data(this,"__className__",this.className),this.className=this.className||e===!1?"":b._data(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(X," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,o=this[0];{if(arguments.length)return i=b.isFunction(e),this.each(function(n){var o,a=b(this);1===this.nodeType&&(o=i?e.call(this,n,a.val()):e,null==o?o="":"number"==typeof o?o+="":b.isArray(o)&&(o=b.map(o,function(e){return null==e?"":e+""})),r=b.valHooks[this.type]||b.valHooks[this.nodeName.toLowerCase()],r&&"set"in r&&r.set(this,o,"value")!==t||(this.value=o))});if(o)return r=b.valHooks[o.type]||b.valHooks[o.nodeName.toLowerCase()],r&&"get"in r&&(n=r.get(o,"value"))!==t?n:(n=o.value,"string"==typeof n?n.replace(U,""):null==n?"":n)}}}),b.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,u=0>i?s:o?i:0;for(;s>u;u++)if(n=r[u],!(!n.selected&&u!==i||(b.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&b.nodeName(n.parentNode,"optgroup"))){if(t=b(n).val(),o)return t;a.push(t)}return a},set:function(e,t){var n=b.makeArray(t);return b(e).find("option").each(function(){this.selected=b.inArray(b(this).val(),n)>=0}),n.length||(e.selectedIndex=-1),n}}},attr:function(e,n,r){var o,a,s,u=e.nodeType;if(e&&3!==u&&8!==u&&2!==u)return typeof e.getAttribute===i?b.prop(e,n,r):(a=1!==u||!b.isXMLDoc(e),a&&(n=n.toLowerCase(),o=b.attrHooks[n]||(J.test(n)?z:I)),r===t?o&&a&&"get"in o&&null!==(s=o.get(e,n))?s:(typeof e.getAttribute!==i&&(s=e.getAttribute(n)),null==s?t:s):null!==r?o&&a&&"set"in o&&(s=o.set(e,r,n))!==t?s:(e.setAttribute(n,r+""),r):(b.removeAttr(e,n),t))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(w);if(o&&1===e.nodeType)while(n=o[i++])r=b.propFix[n]||n,J.test(n)?!Q&&G.test(n)?e[b.camelCase("default-"+n)]=e[r]=!1:e[r]=!1:b.attr(e,n,""),e.removeAttribute(Q?n:r)},attrHooks:{type:{set:function(e,t){if(!b.support.radioValue&&"radio"===t&&b.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return a=1!==s||!b.isXMLDoc(e),a&&(n=b.propFix[n]||n,o=b.propHooks[n]),r!==t?o&&"set"in o&&(i=o.set(e,r,n))!==t?i:e[n]=r:o&&"get"in o&&null!==(i=o.get(e,n))?i:e[n]},propHooks:{tabIndex:{get:function(e){var n=e.getAttributeNode("tabindex");return n&&n.specified?parseInt(n.value,10):V.test(e.nodeName)||Y.test(e.nodeName)&&e.href?0:t}}}}),z={get:function(e,n){var r=b.prop(e,n),i="boolean"==typeof r&&e.getAttribute(n),o="boolean"==typeof r?K&&Q?null!=i:G.test(n)?e[b.camelCase("default-"+n)]:!!i:e.getAttributeNode(n);return o&&o.value!==!1?n.toLowerCase():t},set:function(e,t,n){return t===!1?b.removeAttr(e,n):K&&Q||!G.test(n)?e.setAttribute(!Q&&b.propFix[n]||n,n):e[b.camelCase("default-"+n)]=e[n]=!0,n}},K&&Q||(b.attrHooks.value={get:function(e,n){var r=e.getAttributeNode(n);return b.nodeName(e,"input")?e.defaultValue:r&&r.specified?r.value:t},set:function(e,n,r){return b.nodeName(e,"input")?(e.defaultValue=n,t):I&&I.set(e,n,r)}}),Q||(I=b.valHooks.button={get:function(e,n){var r=e.getAttributeNode(n);return r&&("id"===n||"name"===n||"coords"===n?""!==r.value:r.specified)?r.value:t},set:function(e,n,r){var i=e.getAttributeNode(r);return i||e.setAttributeNode(i=e.ownerDocument.createAttribute(r)),i.value=n+="","value"===r||n===e.getAttribute(r)?n:t}},b.attrHooks.contenteditable={get:I.get,set:function(e,t,n){I.set(e,""===t?!1:t,n)}},b.each(["width","height"],function(e,n){b.attrHooks[n]=b.extend(b.attrHooks[n],{set:function(e,r){return""===r?(e.setAttribute(n,"auto"),r):t}})})),b.support.hrefNormalized||(b.each(["href","src","width","height"],function(e,n){b.attrHooks[n]=b.extend(b.attrHooks[n],{get:function(e){var r=e.getAttribute(n,2);return null==r?t:r}})}),b.each(["href","src"],function(e,t){b.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}})),b.support.style||(b.attrHooks.style={get:function(e){return e.style.cssText||t},set:function(e,t){return e.style.cssText=t+""}}),b.support.optSelected||(b.propHooks.selected=b.extend(b.propHooks.selected,{get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}})),b.support.enctype||(b.propFix.enctype="encoding"),b.support.checkOn||b.each(["radio","checkbox"],function(){b.valHooks[this]={get:function(e){return null===e.getAttribute("value")?"on":e.value}}}),b.each(["radio","checkbox"],function(){b.valHooks[this]=b.extend(b.valHooks[this],{set:function(e,n){return b.isArray(n)?e.checked=b.inArray(b(e).val(),n)>=0:t}})});var Z=/^(?:input|select|textarea)$/i,et=/^key/,tt=/^(?:mouse|contextmenu)|click/,nt=/^(?:focusinfocus|focusoutblur)$/,rt=/^([^.]*)(?:\.(.+)|)$/;function it(){return!0}function ot(){return!1}b.event={global:{},add:function(e,n,r,o,a){var s,u,l,c,p,f,d,h,g,m,y,v=b._data(e);if(v){r.handler&&(c=r,r=c.handler,a=c.selector),r.guid||(r.guid=b.guid++),(u=v.events)||(u=v.events={}),(f=v.handle)||(f=v.handle=function(e){return typeof b===i||e&&b.event.triggered===e.type?t:b.event.dispatch.apply(f.elem,arguments)},f.elem=e),n=(n||"").match(w)||[""],l=n.length;while(l--)s=rt.exec(n[l])||[],g=y=s[1],m=(s[2]||"").split(".").sort(),p=b.event.special[g]||{},g=(a?p.delegateType:p.bindType)||g,p=b.event.special[g]||{},d=b.extend({type:g,origType:y,data:o,handler:r,guid:r.guid,selector:a,needsContext:a&&b.expr.match.needsContext.test(a),namespace:m.join(".")},c),(h=u[g])||(h=u[g]=[],h.delegateCount=0,p.setup&&p.setup.call(e,o,m,f)!==!1||(e.addEventListener?e.addEventListener(g,f,!1):e.attachEvent&&e.attachEvent("on"+g,f))),p.add&&(p.add.call(e,d),d.handler.guid||(d.handler.guid=r.guid)),a?h.splice(h.delegateCount++,0,d):h.push(d),b.event.global[g]=!0;e=null}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,p,f,d,h,g,m=b.hasData(e)&&b._data(e);if(m&&(c=m.events)){t=(t||"").match(w)||[""],l=t.length;while(l--)if(s=rt.exec(t[l])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){p=b.event.special[d]||{},d=(r?p.delegateType:p.bindType)||d,f=c[d]||[],s=s[2]&&RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),u=o=f.length;while(o--)a=f[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&("**"!==r||!a.selector)||(f.splice(o,1),a.selector&&f.delegateCount--,p.remove&&p.remove.call(e,a));u&&!f.length&&(p.teardown&&p.teardown.call(e,h,m.handle)!==!1||b.removeEvent(e,d,m.handle),delete c[d])}else for(d in c)b.event.remove(e,d+t[l],n,r,!0);b.isEmptyObject(c)&&(delete m.handle,b._removeData(e,"events"))}},trigger:function(n,r,i,a){var s,u,l,c,p,f,d,h=[i||o],g=y.call(n,"type")?n.type:n,m=y.call(n,"namespace")?n.namespace.split("."):[];if(l=f=i=i||o,3!==i.nodeType&&8!==i.nodeType&&!nt.test(g+b.event.triggered)&&(g.indexOf(".")>=0&&(m=g.split("."),g=m.shift(),m.sort()),u=0>g.indexOf(":")&&"on"+g,n=n[b.expando]?n:new b.Event(g,"object"==typeof n&&n),n.isTrigger=!0,n.namespace=m.join("."),n.namespace_re=n.namespace?RegExp("(^|\\.)"+m.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,n.result=t,n.target||(n.target=i),r=null==r?[n]:b.makeArray(r,[n]),p=b.event.special[g]||{},a||!p.trigger||p.trigger.apply(i,r)!==!1)){if(!a&&!p.noBubble&&!b.isWindow(i)){for(c=p.delegateType||g,nt.test(c+g)||(l=l.parentNode);l;l=l.parentNode)h.push(l),f=l;f===(i.ownerDocument||o)&&h.push(f.defaultView||f.parentWindow||e)}d=0;while((l=h[d++])&&!n.isPropagationStopped())n.type=d>1?c:p.bindType||g,s=(b._data(l,"events")||{})[n.type]&&b._data(l,"handle"),s&&s.apply(l,r),s=u&&l[u],s&&b.acceptData(l)&&s.apply&&s.apply(l,r)===!1&&n.preventDefault();if(n.type=g,!(a||n.isDefaultPrevented()||p._default&&p._default.apply(i.ownerDocument,r)!==!1||"click"===g&&b.nodeName(i,"a")||!b.acceptData(i)||!u||!i[g]||b.isWindow(i))){f=i[u],f&&(i[u]=null),b.event.triggered=g;try{i[g]()}catch(v){}b.event.triggered=t,f&&(i[u]=f)}return n.result}},dispatch:function(e){e=b.event.fix(e);var n,r,i,o,a,s=[],u=h.call(arguments),l=(b._data(this,"events")||{})[e.type]||[],c=b.event.special[e.type]||{};if(u[0]=e,e.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,e)!==!1){s=b.event.handlers.call(this,e,l),n=0;while((o=s[n++])&&!e.isPropagationStopped()){e.currentTarget=o.elem,a=0;while((i=o.handlers[a++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(i.namespace))&&(e.handleObj=i,e.data=i.data,r=((b.event.special[i.origType]||{}).handle||i.handler).apply(o.elem,u),r!==t&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,e),e.result}},handlers:function(e,n){var r,i,o,a,s=[],u=n.delegateCount,l=e.target;if(u&&l.nodeType&&(!e.button||"click"!==e.type))for(;l!=this;l=l.parentNode||this)if(1===l.nodeType&&(l.disabled!==!0||"click"!==e.type)){for(o=[],a=0;u>a;a++)i=n[a],r=i.selector+" ",o[r]===t&&(o[r]=i.needsContext?b(r,this).index(l)>=0:b.find(r,this,null,[l]).length),o[r]&&o.push(i);o.length&&s.push({elem:l,handlers:o})}return n.length>u&&s.push({elem:this,handlers:n.slice(u)}),s},fix:function(e){if(e[b.expando])return e;var t,n,r,i=e.type,a=e,s=this.fixHooks[i];s||(this.fixHooks[i]=s=tt.test(i)?this.mouseHooks:et.test(i)?this.keyHooks:{}),r=s.props?this.props.concat(s.props):this.props,e=new b.Event(a),t=r.length;while(t--)n=r[t],e[n]=a[n];return e.target||(e.target=a.srcElement||o),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,a):e},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,i,a,s=n.button,u=n.fromElement;return null==e.pageX&&null!=n.clientX&&(i=e.target.ownerDocument||o,a=i.documentElement,r=i.body,e.pageX=n.clientX+(a&&a.scrollLeft||r&&r.scrollLeft||0)-(a&&a.clientLeft||r&&r.clientLeft||0),e.pageY=n.clientY+(a&&a.scrollTop||r&&r.scrollTop||0)-(a&&a.clientTop||r&&r.clientTop||0)),!e.relatedTarget&&u&&(e.relatedTarget=u===e.target?n.toElement:u),e.which||s===t||(e.which=1&s?1:2&s?3:4&s?2:0),e}},special:{load:{noBubble:!0},click:{trigger:function(){return b.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):t}},focus:{trigger:function(){if(this!==o.activeElement&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:"focusin"},blur:{trigger:function(){return this===o.activeElement&&this.blur?(this.blur(),!1):t},delegateType:"focusout"},beforeunload:{postDispatch:function(e){e.result!==t&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=b.extend(new b.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?b.event.trigger(i,null,t):b.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},b.removeEvent=o.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]===i&&(e[r]=null),e.detachEvent(r,n))},b.Event=function(e,n){return this instanceof b.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?it:ot):this.type=e,n&&b.extend(this,n),this.timeStamp=e&&e.timeStamp||b.now(),this[b.expando]=!0,t):new b.Event(e,n)},b.Event.prototype={isDefaultPrevented:ot,isPropagationStopped:ot,isImmediatePropagationStopped:ot,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=it,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=it,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=it,this.stopPropagation()}},b.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){b.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;
+return(!i||i!==r&&!b.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),b.support.submitBubbles||(b.event.special.submit={setup:function(){return b.nodeName(this,"form")?!1:(b.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=b.nodeName(n,"input")||b.nodeName(n,"button")?n.form:t;r&&!b._data(r,"submitBubbles")&&(b.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),b._data(r,"submitBubbles",!0))}),t)},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&b.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){return b.nodeName(this,"form")?!1:(b.event.remove(this,"._submit"),t)}}),b.support.changeBubbles||(b.event.special.change={setup:function(){return Z.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(b.event.add(this,"propertychange._change",function(e){"checked"===e.originalEvent.propertyName&&(this._just_changed=!0)}),b.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),b.event.simulate("change",this,e,!0)})),!1):(b.event.add(this,"beforeactivate._change",function(e){var t=e.target;Z.test(t.nodeName)&&!b._data(t,"changeBubbles")&&(b.event.add(t,"change._change",function(e){!this.parentNode||e.isSimulated||e.isTrigger||b.event.simulate("change",this.parentNode,e,!0)}),b._data(t,"changeBubbles",!0))}),t)},handle:function(e){var n=e.target;return this!==n||e.isSimulated||e.isTrigger||"radio"!==n.type&&"checkbox"!==n.type?e.handleObj.handler.apply(this,arguments):t},teardown:function(){return b.event.remove(this,"._change"),!Z.test(this.nodeName)}}),b.support.focusinBubbles||b.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){b.event.simulate(t,e.target,b.event.fix(e),!0)};b.event.special[t]={setup:function(){0===n++&&o.addEventListener(e,r,!0)},teardown:function(){0===--n&&o.removeEventListener(e,r,!0)}}}),b.fn.extend({on:function(e,n,r,i,o){var a,s;if("object"==typeof e){"string"!=typeof n&&(r=r||n,n=t);for(a in e)this.on(a,n,r,e[a],o);return this}if(null==r&&null==i?(i=n,r=n=t):null==i&&("string"==typeof n?(i=r,r=t):(i=r,r=n,n=t)),i===!1)i=ot;else if(!i)return this;return 1===o&&(s=i,i=function(e){return b().off(e),s.apply(this,arguments)},i.guid=s.guid||(s.guid=b.guid++)),this.each(function(){b.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,o;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,b(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if("object"==typeof e){for(o in e)this.off(o,n,e[o]);return this}return(n===!1||"function"==typeof n)&&(r=n,n=t),r===!1&&(r=ot),this.each(function(){b.event.remove(this,e,r,n)})},bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},trigger:function(e,t){return this.each(function(){b.event.trigger(e,t,this)})},triggerHandler:function(e,n){var r=this[0];return r?b.event.trigger(e,n,r,!0):t}}),function(e,t){var n,r,i,o,a,s,u,l,c,p,f,d,h,g,m,y,v,x="sizzle"+-new Date,w=e.document,T={},N=0,C=0,k=it(),E=it(),S=it(),A=typeof t,j=1<<31,D=[],L=D.pop,H=D.push,q=D.slice,M=D.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},_="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",O=F.replace("w","w#"),B="([*^$|!~]?=)",P="\\["+_+"*("+F+")"+_+"*(?:"+B+_+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+O+")|)|)"+_+"*\\]",R=":("+F+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+P.replace(3,8)+")*)|.*)\\)|)",W=RegExp("^"+_+"+|((?:^|[^\\\\])(?:\\\\.)*)"+_+"+$","g"),$=RegExp("^"+_+"*,"+_+"*"),I=RegExp("^"+_+"*([\\x20\\t\\r\\n\\f>+~])"+_+"*"),z=RegExp(R),X=RegExp("^"+O+"$"),U={ID:RegExp("^#("+F+")"),CLASS:RegExp("^\\.("+F+")"),NAME:RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:RegExp("^("+F.replace("w","w*")+")"),ATTR:RegExp("^"+P),PSEUDO:RegExp("^"+R),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+_+"*(even|odd|(([+-]|)(\\d*)n|)"+_+"*(?:([+-]|)"+_+"*(\\d+)|))"+_+"*\\)|)","i"),needsContext:RegExp("^"+_+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+_+"*((?:-\\d)?\\d*)"+_+"*\\)|)(?=[^-]|$)","i")},V=/[\x20\t\r\n\f]*[+~]/,Y=/^[^{]+\{\s*\[native code/,J=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,G=/^(?:input|select|textarea|button)$/i,Q=/^h\d$/i,K=/'|\\/g,Z=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,et=/\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g,tt=function(e,t){var n="0x"+t-65536;return n!==n?t:0>n?String.fromCharCode(n+65536):String.fromCharCode(55296|n>>10,56320|1023&n)};try{q.call(w.documentElement.childNodes,0)[0].nodeType}catch(nt){q=function(e){var t,n=[];while(t=this[e++])n.push(t);return n}}function rt(e){return Y.test(e+"")}function it(){var e,t=[];return e=function(n,r){return t.push(n+=" ")>i.cacheLength&&delete e[t.shift()],e[n]=r}}function ot(e){return e[x]=!0,e}function at(e){var t=p.createElement("div");try{return e(t)}catch(n){return!1}finally{t=null}}function st(e,t,n,r){var i,o,a,s,u,l,f,g,m,v;if((t?t.ownerDocument||t:w)!==p&&c(t),t=t||p,n=n||[],!e||"string"!=typeof e)return n;if(1!==(s=t.nodeType)&&9!==s)return[];if(!d&&!r){if(i=J.exec(e))if(a=i[1]){if(9===s){if(o=t.getElementById(a),!o||!o.parentNode)return n;if(o.id===a)return n.push(o),n}else if(t.ownerDocument&&(o=t.ownerDocument.getElementById(a))&&y(t,o)&&o.id===a)return n.push(o),n}else{if(i[2])return H.apply(n,q.call(t.getElementsByTagName(e),0)),n;if((a=i[3])&&T.getByClassName&&t.getElementsByClassName)return H.apply(n,q.call(t.getElementsByClassName(a),0)),n}if(T.qsa&&!h.test(e)){if(f=!0,g=x,m=t,v=9===s&&e,1===s&&"object"!==t.nodeName.toLowerCase()){l=ft(e),(f=t.getAttribute("id"))?g=f.replace(K,"\\$&"):t.setAttribute("id",g),g="[id='"+g+"'] ",u=l.length;while(u--)l[u]=g+dt(l[u]);m=V.test(e)&&t.parentNode||t,v=l.join(",")}if(v)try{return H.apply(n,q.call(m.querySelectorAll(v),0)),n}catch(b){}finally{f||t.removeAttribute("id")}}}return wt(e.replace(W,"$1"),t,n,r)}a=st.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},c=st.setDocument=function(e){var n=e?e.ownerDocument||e:w;return n!==p&&9===n.nodeType&&n.documentElement?(p=n,f=n.documentElement,d=a(n),T.tagNameNoComments=at(function(e){return e.appendChild(n.createComment("")),!e.getElementsByTagName("*").length}),T.attributes=at(function(e){e.innerHTML=" ";var t=typeof e.lastChild.getAttribute("multiple");return"boolean"!==t&&"string"!==t}),T.getByClassName=at(function(e){return e.innerHTML="
",e.getElementsByClassName&&e.getElementsByClassName("e").length?(e.lastChild.className="e",2===e.getElementsByClassName("e").length):!1}),T.getByName=at(function(e){e.id=x+0,e.innerHTML="
",f.insertBefore(e,f.firstChild);var t=n.getElementsByName&&n.getElementsByName(x).length===2+n.getElementsByName(x+0).length;return T.getIdNotName=!n.getElementById(x),f.removeChild(e),t}),i.attrHandle=at(function(e){return e.innerHTML=" ",e.firstChild&&typeof e.firstChild.getAttribute!==A&&"#"===e.firstChild.getAttribute("href")})?{}:{href:function(e){return e.getAttribute("href",2)},type:function(e){return e.getAttribute("type")}},T.getIdNotName?(i.find.ID=function(e,t){if(typeof t.getElementById!==A&&!d){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},i.filter.ID=function(e){var t=e.replace(et,tt);return function(e){return e.getAttribute("id")===t}}):(i.find.ID=function(e,n){if(typeof n.getElementById!==A&&!d){var r=n.getElementById(e);return r?r.id===e||typeof r.getAttributeNode!==A&&r.getAttributeNode("id").value===e?[r]:t:[]}},i.filter.ID=function(e){var t=e.replace(et,tt);return function(e){var n=typeof e.getAttributeNode!==A&&e.getAttributeNode("id");return n&&n.value===t}}),i.find.TAG=T.tagNameNoComments?function(e,n){return typeof n.getElementsByTagName!==A?n.getElementsByTagName(e):t}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},i.find.NAME=T.getByName&&function(e,n){return typeof n.getElementsByName!==A?n.getElementsByName(name):t},i.find.CLASS=T.getByClassName&&function(e,n){return typeof n.getElementsByClassName===A||d?t:n.getElementsByClassName(e)},g=[],h=[":focus"],(T.qsa=rt(n.querySelectorAll))&&(at(function(e){e.innerHTML=" ",e.querySelectorAll("[selected]").length||h.push("\\["+_+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),e.querySelectorAll(":checked").length||h.push(":checked")}),at(function(e){e.innerHTML=" ",e.querySelectorAll("[i^='']").length&&h.push("[*^$]="+_+"*(?:\"\"|'')"),e.querySelectorAll(":enabled").length||h.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),h.push(",.*:")})),(T.matchesSelector=rt(m=f.matchesSelector||f.mozMatchesSelector||f.webkitMatchesSelector||f.oMatchesSelector||f.msMatchesSelector))&&at(function(e){T.disconnectedMatch=m.call(e,"div"),m.call(e,"[s!='']:x"),g.push("!=",R)}),h=RegExp(h.join("|")),g=RegExp(g.join("|")),y=rt(f.contains)||f.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},v=f.compareDocumentPosition?function(e,t){var r;return e===t?(u=!0,0):(r=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t))?1&r||e.parentNode&&11===e.parentNode.nodeType?e===n||y(w,e)?-1:t===n||y(w,t)?1:0:4&r?-1:1:e.compareDocumentPosition?-1:1}:function(e,t){var r,i=0,o=e.parentNode,a=t.parentNode,s=[e],l=[t];if(e===t)return u=!0,0;if(!o||!a)return e===n?-1:t===n?1:o?-1:a?1:0;if(o===a)return ut(e,t);r=e;while(r=r.parentNode)s.unshift(r);r=t;while(r=r.parentNode)l.unshift(r);while(s[i]===l[i])i++;return i?ut(s[i],l[i]):s[i]===w?-1:l[i]===w?1:0},u=!1,[0,0].sort(v),T.detectDuplicates=u,p):p},st.matches=function(e,t){return st(e,null,null,t)},st.matchesSelector=function(e,t){if((e.ownerDocument||e)!==p&&c(e),t=t.replace(Z,"='$1']"),!(!T.matchesSelector||d||g&&g.test(t)||h.test(t)))try{var n=m.call(e,t);if(n||T.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(r){}return st(t,p,null,[e]).length>0},st.contains=function(e,t){return(e.ownerDocument||e)!==p&&c(e),y(e,t)},st.attr=function(e,t){var n;return(e.ownerDocument||e)!==p&&c(e),d||(t=t.toLowerCase()),(n=i.attrHandle[t])?n(e):d||T.attributes?e.getAttribute(t):((n=e.getAttributeNode(t))||e.getAttribute(t))&&e[t]===!0?t:n&&n.specified?n.value:null},st.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},st.uniqueSort=function(e){var t,n=[],r=1,i=0;if(u=!T.detectDuplicates,e.sort(v),u){for(;t=e[r];r++)t===e[r-1]&&(i=n.push(r));while(i--)e.splice(n[i],1)}return e};function ut(e,t){var n=t&&e,r=n&&(~t.sourceIndex||j)-(~e.sourceIndex||j);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function lt(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function ct(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function pt(e){return ot(function(t){return t=+t,ot(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}o=st.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=o(t);return n},i=st.selectors={cacheLength:50,createPseudo:ot,match:U,find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(et,tt),e[3]=(e[4]||e[5]||"").replace(et,tt),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||st.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&st.error(e[0]),e},PSEUDO:function(e){var t,n=!e[5]&&e[2];return U.CHILD.test(e[0])?null:(e[4]?e[2]=e[4]:n&&z.test(n)&&(t=ft(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){return"*"===e?function(){return!0}:(e=e.replace(et,tt).toLowerCase(),function(t){return t.nodeName&&t.nodeName.toLowerCase()===e})},CLASS:function(e){var t=k[e+" "];return t||(t=RegExp("(^|"+_+")"+e+"("+_+"|$)"))&&k(e,function(e){return t.test(e.className||typeof e.getAttribute!==A&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=st.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,p,f,d,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!u&&!s;if(m){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){c=m[x]||(m[x]={}),l=c[e]||[],d=l[0]===N&&l[1],f=l[0]===N&&l[2],p=d&&m.childNodes[d];while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[N,d,f];break}}else if(v&&(l=(t[x]||(t[x]={}))[e])&&l[0]===N)f=l[1];else while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(v&&((p[x]||(p[x]={}))[e]=[N,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||st.error("unsupported pseudo: "+e);return r[x]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?ot(function(e,n){var i,o=r(e,t),a=o.length;while(a--)i=M.call(e,o[a]),e[i]=!(n[i]=o[a])}):function(e){return r(e,0,n)}):r}},pseudos:{not:ot(function(e){var t=[],n=[],r=s(e.replace(W,"$1"));return r[x]?ot(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:ot(function(e){return function(t){return st(e,t).length>0}}),contains:ot(function(e){return function(t){return(t.textContent||t.innerText||o(t)).indexOf(e)>-1}}),lang:ot(function(e){return X.test(e||"")||st.error("unsupported lang: "+e),e=e.replace(et,tt).toLowerCase(),function(t){var n;do if(n=d?t.getAttribute("xml:lang")||t.getAttribute("lang"):t.lang)return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===f},focus:function(e){return e===p.activeElement&&(!p.hasFocus||p.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!i.pseudos.empty(e)},header:function(e){return Q.test(e.nodeName)},input:function(e){return G.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:pt(function(){return[0]}),last:pt(function(e,t){return[t-1]}),eq:pt(function(e,t,n){return[0>n?n+t:n]}),even:pt(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:pt(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:pt(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:pt(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}};for(n in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})i.pseudos[n]=lt(n);for(n in{submit:!0,reset:!0})i.pseudos[n]=ct(n);function ft(e,t){var n,r,o,a,s,u,l,c=E[e+" "];if(c)return t?0:c.slice(0);s=e,u=[],l=i.preFilter;while(s){(!n||(r=$.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),u.push(o=[])),n=!1,(r=I.exec(s))&&(n=r.shift(),o.push({value:n,type:r[0].replace(W," ")}),s=s.slice(n.length));for(a in i.filter)!(r=U[a].exec(s))||l[a]&&!(r=l[a](r))||(n=r.shift(),o.push({value:n,type:a,matches:r}),s=s.slice(n.length));if(!n)break}return t?s.length:s?st.error(e):E(e,u).slice(0)}function dt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function ht(e,t,n){var i=t.dir,o=n&&"parentNode"===i,a=C++;return t.first?function(t,n,r){while(t=t[i])if(1===t.nodeType||o)return e(t,n,r)}:function(t,n,s){var u,l,c,p=N+" "+a;if(s){while(t=t[i])if((1===t.nodeType||o)&&e(t,n,s))return!0}else while(t=t[i])if(1===t.nodeType||o)if(c=t[x]||(t[x]={}),(l=c[i])&&l[0]===p){if((u=l[1])===!0||u===r)return u===!0}else if(l=c[i]=[p],l[1]=e(t,n,s)||r,l[1]===!0)return!0}}function gt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function mt(e,t,n,r,i){var o,a=[],s=0,u=e.length,l=null!=t;for(;u>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),l&&t.push(s));return a}function yt(e,t,n,r,i,o){return r&&!r[x]&&(r=yt(r)),i&&!i[x]&&(i=yt(i,o)),ot(function(o,a,s,u){var l,c,p,f=[],d=[],h=a.length,g=o||xt(t||"*",s.nodeType?[s]:s,[]),m=!e||!o&&t?g:mt(g,f,e,s,u),y=n?i||(o?e:h||r)?[]:a:m;if(n&&n(m,y,s,u),r){l=mt(y,d),r(l,[],s,u),c=l.length;while(c--)(p=l[c])&&(y[d[c]]=!(m[d[c]]=p))}if(o){if(i||e){if(i){l=[],c=y.length;while(c--)(p=y[c])&&l.push(m[c]=p);i(null,y=[],l,u)}c=y.length;while(c--)(p=y[c])&&(l=i?M.call(o,p):f[c])>-1&&(o[l]=!(a[l]=p))}}else y=mt(y===a?y.splice(h,y.length):y),i?i(null,a,y,u):H.apply(a,y)})}function vt(e){var t,n,r,o=e.length,a=i.relative[e[0].type],s=a||i.relative[" "],u=a?1:0,c=ht(function(e){return e===t},s,!0),p=ht(function(e){return M.call(t,e)>-1},s,!0),f=[function(e,n,r){return!a&&(r||n!==l)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;o>u;u++)if(n=i.relative[e[u].type])f=[ht(gt(f),n)];else{if(n=i.filter[e[u].type].apply(null,e[u].matches),n[x]){for(r=++u;o>r;r++)if(i.relative[e[r].type])break;return yt(u>1&>(f),u>1&&dt(e.slice(0,u-1)).replace(W,"$1"),n,r>u&&vt(e.slice(u,r)),o>r&&vt(e=e.slice(r)),o>r&&dt(e))}f.push(n)}return gt(f)}function bt(e,t){var n=0,o=t.length>0,a=e.length>0,s=function(s,u,c,f,d){var h,g,m,y=[],v=0,b="0",x=s&&[],w=null!=d,T=l,C=s||a&&i.find.TAG("*",d&&u.parentNode||u),k=N+=null==T?1:Math.random()||.1;for(w&&(l=u!==p&&u,r=n);null!=(h=C[b]);b++){if(a&&h){g=0;while(m=e[g++])if(m(h,u,c)){f.push(h);break}w&&(N=k,r=++n)}o&&((h=!m&&h)&&v--,s&&x.push(h))}if(v+=b,o&&b!==v){g=0;while(m=t[g++])m(x,y,u,c);if(s){if(v>0)while(b--)x[b]||y[b]||(y[b]=L.call(f));y=mt(y)}H.apply(f,y),w&&!s&&y.length>0&&v+t.length>1&&st.uniqueSort(f)}return w&&(N=k,l=T),x};return o?ot(s):s}s=st.compile=function(e,t){var n,r=[],i=[],o=S[e+" "];if(!o){t||(t=ft(e)),n=t.length;while(n--)o=vt(t[n]),o[x]?r.push(o):i.push(o);o=S(e,bt(i,r))}return o};function xt(e,t,n){var r=0,i=t.length;for(;i>r;r++)st(e,t[r],n);return n}function wt(e,t,n,r){var o,a,u,l,c,p=ft(e);if(!r&&1===p.length){if(a=p[0]=p[0].slice(0),a.length>2&&"ID"===(u=a[0]).type&&9===t.nodeType&&!d&&i.relative[a[1].type]){if(t=i.find.ID(u.matches[0].replace(et,tt),t)[0],!t)return n;e=e.slice(a.shift().value.length)}o=U.needsContext.test(e)?0:a.length;while(o--){if(u=a[o],i.relative[l=u.type])break;if((c=i.find[l])&&(r=c(u.matches[0].replace(et,tt),V.test(a[0].type)&&t.parentNode||t))){if(a.splice(o,1),e=r.length&&dt(a),!e)return H.apply(n,q.call(r,0)),n;break}}}return s(e,p)(r,t,d,n,V.test(e)),n}i.pseudos.nth=i.pseudos.eq;function Tt(){}i.filters=Tt.prototype=i.pseudos,i.setFilters=new Tt,c(),st.attr=b.attr,b.find=st,b.expr=st.selectors,b.expr[":"]=b.expr.pseudos,b.unique=st.uniqueSort,b.text=st.getText,b.isXMLDoc=st.isXML,b.contains=st.contains}(e);var at=/Until$/,st=/^(?:parents|prev(?:Until|All))/,ut=/^.[^:#\[\.,]*$/,lt=b.expr.match.needsContext,ct={children:!0,contents:!0,next:!0,prev:!0};b.fn.extend({find:function(e){var t,n,r,i=this.length;if("string"!=typeof e)return r=this,this.pushStack(b(e).filter(function(){for(t=0;i>t;t++)if(b.contains(r[t],this))return!0}));for(n=[],t=0;i>t;t++)b.find(e,this[t],n);return n=this.pushStack(i>1?b.unique(n):n),n.selector=(this.selector?this.selector+" ":"")+e,n},has:function(e){var t,n=b(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++)if(b.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e,!1))},filter:function(e){return this.pushStack(ft(this,e,!0))},is:function(e){return!!e&&("string"==typeof e?lt.test(e)?b(e,this.context).index(this[0])>=0:b.filter(e,this).length>0:this.filter(e).length>0)},closest:function(e,t){var n,r=0,i=this.length,o=[],a=lt.test(e)||"string"!=typeof e?b(e,t||this.context):0;for(;i>r;r++){n=this[r];while(n&&n.ownerDocument&&n!==t&&11!==n.nodeType){if(a?a.index(n)>-1:b.find.matchesSelector(n,e)){o.push(n);break}n=n.parentNode}}return this.pushStack(o.length>1?b.unique(o):o)},index:function(e){return e?"string"==typeof e?b.inArray(this[0],b(e)):b.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?b(e,t):b.makeArray(e&&e.nodeType?[e]:e),r=b.merge(this.get(),n);return this.pushStack(b.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),b.fn.andSelf=b.fn.addBack;function pt(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}b.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return b.dir(e,"parentNode")},parentsUntil:function(e,t,n){return b.dir(e,"parentNode",n)},next:function(e){return pt(e,"nextSibling")},prev:function(e){return pt(e,"previousSibling")},nextAll:function(e){return b.dir(e,"nextSibling")},prevAll:function(e){return b.dir(e,"previousSibling")},nextUntil:function(e,t,n){return b.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return b.dir(e,"previousSibling",n)},siblings:function(e){return b.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return b.sibling(e.firstChild)},contents:function(e){return b.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:b.merge([],e.childNodes)}},function(e,t){b.fn[e]=function(n,r){var i=b.map(this,t,n);return at.test(e)||(r=n),r&&"string"==typeof r&&(i=b.filter(r,i)),i=this.length>1&&!ct[e]?b.unique(i):i,this.length>1&&st.test(e)&&(i=i.reverse()),this.pushStack(i)}}),b.extend({filter:function(e,t,n){return n&&(e=":not("+e+")"),1===t.length?b.find.matchesSelector(t[0],e)?[t[0]]:[]:b.find.matches(e,t)},dir:function(e,n,r){var i=[],o=e[n];while(o&&9!==o.nodeType&&(r===t||1!==o.nodeType||!b(o).is(r)))1===o.nodeType&&i.push(o),o=o[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function ft(e,t,n){if(t=t||0,b.isFunction(t))return b.grep(e,function(e,r){var i=!!t.call(e,r,e);return i===n});if(t.nodeType)return b.grep(e,function(e){return e===t===n});if("string"==typeof t){var r=b.grep(e,function(e){return 1===e.nodeType});if(ut.test(t))return b.filter(t,r,!n);t=b.filter(t,r)}return b.grep(e,function(e){return b.inArray(e,t)>=0===n})}function dt(e){var t=ht.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}var ht="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",gt=/ jQuery\d+="(?:null|\d+)"/g,mt=RegExp("<(?:"+ht+")[\\s/>]","i"),yt=/^\s+/,vt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bt=/<([\w:]+)/,xt=/\s*$/g,At={option:[1,""," "],legend:[1,""," "],area:[1,""," "],param:[1,""," "],thead:[1,""],tr:[2,""],col:[2,""],td:[3,""],_default:b.support.htmlSerialize?[0,"",""]:[1,"X","
"]},jt=dt(o),Dt=jt.appendChild(o.createElement("div"));At.optgroup=At.option,At.tbody=At.tfoot=At.colgroup=At.caption=At.thead,At.th=At.td,b.fn.extend({text:function(e){return b.access(this,function(e){return e===t?b.text(this):this.empty().append((this[0]&&this[0].ownerDocument||o).createTextNode(e))},null,e,arguments.length)},wrapAll:function(e){if(b.isFunction(e))return this.each(function(t){b(this).wrapAll(e.call(this,t))});if(this[0]){var t=b(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&1===e.firstChild.nodeType)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return b.isFunction(e)?this.each(function(t){b(this).wrapInner(e.call(this,t))}):this.each(function(){var t=b(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=b.isFunction(e);return this.each(function(n){b(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){b.nodeName(this,"body")||b(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(e){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&this.appendChild(e)})},prepend:function(){return this.domManip(arguments,!0,function(e){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&this.insertBefore(e,this.firstChild)})},before:function(){return this.domManip(arguments,!1,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,!1,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=0;for(;null!=(n=this[r]);r++)(!e||b.filter(e,[n]).length>0)&&(t||1!==n.nodeType||b.cleanData(Ot(n)),n.parentNode&&(t&&b.contains(n.ownerDocument,n)&&Mt(Ot(n,"script")),n.parentNode.removeChild(n)));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++){1===e.nodeType&&b.cleanData(Ot(e,!1));while(e.firstChild)e.removeChild(e.firstChild);e.options&&b.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return b.clone(this,e,t)})},html:function(e){return b.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return 1===n.nodeType?n.innerHTML.replace(gt,""):t;if(!("string"!=typeof e||Tt.test(e)||!b.support.htmlSerialize&&mt.test(e)||!b.support.leadingWhitespace&&yt.test(e)||At[(bt.exec(e)||["",""])[1].toLowerCase()])){e=e.replace(vt,"<$1>$2>");try{for(;i>r;r++)n=this[r]||{},1===n.nodeType&&(b.cleanData(Ot(n,!1)),n.innerHTML=e);n=0}catch(o){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(e){var t=b.isFunction(e);return t||"string"==typeof e||(e=b(e).not(this).detach()),this.domManip([e],!0,function(e){var t=this.nextSibling,n=this.parentNode;n&&(b(this).remove(),n.insertBefore(e,t))})},detach:function(e){return this.remove(e,!0)},domManip:function(e,n,r){e=f.apply([],e);var i,o,a,s,u,l,c=0,p=this.length,d=this,h=p-1,g=e[0],m=b.isFunction(g);if(m||!(1>=p||"string"!=typeof g||b.support.checkClone)&&Ct.test(g))return this.each(function(i){var o=d.eq(i);m&&(e[0]=g.call(this,i,n?o.html():t)),o.domManip(e,n,r)});if(p&&(l=b.buildFragment(e,this[0].ownerDocument,!1,this),i=l.firstChild,1===l.childNodes.length&&(l=i),i)){for(n=n&&b.nodeName(i,"tr"),s=b.map(Ot(l,"script"),Ht),a=s.length;p>c;c++)o=l,c!==h&&(o=b.clone(o,!0,!0),a&&b.merge(s,Ot(o,"script"))),r.call(n&&b.nodeName(this[c],"table")?Lt(this[c],"tbody"):this[c],o,c);if(a)for(u=s[s.length-1].ownerDocument,b.map(s,qt),c=0;a>c;c++)o=s[c],kt.test(o.type||"")&&!b._data(o,"globalEval")&&b.contains(u,o)&&(o.src?b.ajax({url:o.src,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):b.globalEval((o.text||o.textContent||o.innerHTML||"").replace(St,"")));l=i=null}return this}});function Lt(e,t){return e.getElementsByTagName(t)[0]||e.appendChild(e.ownerDocument.createElement(t))}function Ht(e){var t=e.getAttributeNode("type");return e.type=(t&&t.specified)+"/"+e.type,e}function qt(e){var t=Et.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function Mt(e,t){var n,r=0;for(;null!=(n=e[r]);r++)b._data(n,"globalEval",!t||b._data(t[r],"globalEval"))}function _t(e,t){if(1===t.nodeType&&b.hasData(e)){var n,r,i,o=b._data(e),a=b._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)b.event.add(t,n,s[n][r])}a.data&&(a.data=b.extend({},a.data))}}function Ft(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!b.support.noCloneEvent&&t[b.expando]){i=b._data(t);for(r in i.events)b.removeEvent(t,r,i.handle);t.removeAttribute(b.expando)}"script"===n&&t.text!==e.text?(Ht(t).text=e.text,qt(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),b.support.html5Clone&&e.innerHTML&&!b.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Nt.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}b.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){b.fn[e]=function(e){var n,r=0,i=[],o=b(e),a=o.length-1;for(;a>=r;r++)n=r===a?this:this.clone(!0),b(o[r])[t](n),d.apply(i,n.get());return this.pushStack(i)}});function Ot(e,n){var r,o,a=0,s=typeof e.getElementsByTagName!==i?e.getElementsByTagName(n||"*"):typeof e.querySelectorAll!==i?e.querySelectorAll(n||"*"):t;if(!s)for(s=[],r=e.childNodes||e;null!=(o=r[a]);a++)!n||b.nodeName(o,n)?s.push(o):b.merge(s,Ot(o,n));return n===t||n&&b.nodeName(e,n)?b.merge([e],s):s}function Bt(e){Nt.test(e.type)&&(e.defaultChecked=e.checked)}b.extend({clone:function(e,t,n){var r,i,o,a,s,u=b.contains(e.ownerDocument,e);if(b.support.html5Clone||b.isXMLDoc(e)||!mt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(Dt.innerHTML=e.outerHTML,Dt.removeChild(o=Dt.firstChild)),!(b.support.noCloneEvent&&b.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||b.isXMLDoc(e)))for(r=Ot(o),s=Ot(e),a=0;null!=(i=s[a]);++a)r[a]&&Ft(i,r[a]);if(t)if(n)for(s=s||Ot(e),r=r||Ot(o),a=0;null!=(i=s[a]);a++)_t(i,r[a]);else _t(e,o);return r=Ot(o,"script"),r.length>0&&Mt(r,!u&&Ot(e,"script")),r=s=i=null,o},buildFragment:function(e,t,n,r){var i,o,a,s,u,l,c,p=e.length,f=dt(t),d=[],h=0;for(;p>h;h++)if(o=e[h],o||0===o)if("object"===b.type(o))b.merge(d,o.nodeType?[o]:o);else if(wt.test(o)){s=s||f.appendChild(t.createElement("div")),u=(bt.exec(o)||["",""])[1].toLowerCase(),c=At[u]||At._default,s.innerHTML=c[1]+o.replace(vt,"<$1>$2>")+c[2],i=c[0];while(i--)s=s.lastChild;if(!b.support.leadingWhitespace&&yt.test(o)&&d.push(t.createTextNode(yt.exec(o)[0])),!b.support.tbody){o="table"!==u||xt.test(o)?""!==c[1]||xt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;while(i--)b.nodeName(l=o.childNodes[i],"tbody")&&!l.childNodes.length&&o.removeChild(l)
+}b.merge(d,s.childNodes),s.textContent="";while(s.firstChild)s.removeChild(s.firstChild);s=f.lastChild}else d.push(t.createTextNode(o));s&&f.removeChild(s),b.support.appendChecked||b.grep(Ot(d,"input"),Bt),h=0;while(o=d[h++])if((!r||-1===b.inArray(o,r))&&(a=b.contains(o.ownerDocument,o),s=Ot(f.appendChild(o),"script"),a&&Mt(s),n)){i=0;while(o=s[i++])kt.test(o.type||"")&&n.push(o)}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,u=b.expando,l=b.cache,p=b.support.deleteExpando,f=b.event.special;for(;null!=(n=e[s]);s++)if((t||b.acceptData(n))&&(o=n[u],a=o&&l[o])){if(a.events)for(r in a.events)f[r]?b.event.remove(n,r):b.removeEvent(n,r,a.handle);l[o]&&(delete l[o],p?delete n[u]:typeof n.removeAttribute!==i?n.removeAttribute(u):n[u]=null,c.push(o))}}});var Pt,Rt,Wt,$t=/alpha\([^)]*\)/i,It=/opacity\s*=\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp("^("+x+")(.*)$","i"),Yt=RegExp("^("+x+")(?!px)[a-z%]+$","i"),Jt=RegExp("^([+-])=("+x+")","i"),Gt={BODY:"block"},Qt={position:"absolute",visibility:"hidden",display:"block"},Kt={letterSpacing:0,fontWeight:400},Zt=["Top","Right","Bottom","Left"],en=["Webkit","O","Moz","ms"];function tn(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--)if(t=en[i]+n,t in e)return t;return r}function nn(e,t){return e=t||e,"none"===b.css(e,"display")||!b.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++)r=e[a],r.style&&(o[a]=b._data(r,"olddisplay"),n=r.style.display,t?(o[a]||"none"!==n||(r.style.display=""),""===r.style.display&&nn(r)&&(o[a]=b._data(r,"olddisplay",un(r.nodeName)))):o[a]||(i=nn(r),(n&&"none"!==n||!i)&&b._data(r,"olddisplay",i?n:b.css(r,"display"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[a]||"":"none"));return e}b.fn.extend({css:function(e,n){return b.access(this,function(e,n,r){var i,o,a={},s=0;if(b.isArray(n)){for(o=Rt(e),i=n.length;i>s;s++)a[n[s]]=b.css(e,n[s],!1,o);return a}return r!==t?b.style(e,n,r):b.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){var t="boolean"==typeof e;return this.each(function(){(t?e:nn(this))?b(this).show():b(this).hide()})}}),b.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":b.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,u=b.camelCase(n),l=e.style;if(n=b.cssProps[u]||(b.cssProps[u]=tn(l,u)),s=b.cssHooks[n]||b.cssHooks[u],r===t)return s&&"get"in s&&(o=s.get(e,!1,i))!==t?o:l[n];if(a=typeof r,"string"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(b.css(e,n)),a="number"),!(null==r||"number"===a&&isNaN(r)||("number"!==a||b.cssNumber[u]||(r+="px"),b.support.clearCloneStyle||""!==r||0!==n.indexOf("background")||(l[n]="inherit"),s&&"set"in s&&(r=s.set(e,r,i))===t)))try{l[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,u=b.camelCase(n);return n=b.cssProps[u]||(b.cssProps[u]=tn(e.style,u)),s=b.cssHooks[n]||b.cssHooks[u],s&&"get"in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),"normal"===a&&n in Kt&&(a=Kt[n]),""===r||r?(o=parseFloat(a),r===!0||b.isNumeric(o)?o||0:a):a},swap:function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),u=s?s.getPropertyValue(n)||s[n]:t,l=e.style;return s&&(""!==u||b.contains(e.ownerDocument,e)||(u=b.style(e,n)),Yt.test(u)&&Ut.test(n)&&(i=l.width,o=l.minWidth,a=l.maxWidth,l.minWidth=l.maxWidth=l.width=u,u=s.width,l.width=i,l.minWidth=o,l.maxWidth=a)),u}):o.documentElement.currentStyle&&(Rt=function(e){return e.currentStyle},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),u=s?s[n]:t,l=e.style;return null==u&&l&&l[n]&&(u=l[n]),Yt.test(u)&&!zt.test(n)&&(i=l.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),l.left="fontSize"===n?"1em":u,u=l.pixelLeft+"px",l.left=i,a&&(o.left=a)),""===u?"auto":u});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function an(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;for(;4>o;o+=2)"margin"===n&&(a+=b.css(e,n+Zt[o],!0,i)),r?("content"===n&&(a-=b.css(e,"padding"+Zt[o],!0,i)),"margin"!==n&&(a-=b.css(e,"border"+Zt[o]+"Width",!0,i))):(a+=b.css(e,"padding"+Zt[o],!0,i),"padding"!==n&&(a+=b.css(e,"border"+Zt[o]+"Width",!0,i)));return a}function sn(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=b.support.boxSizing&&"border-box"===b.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i))return i;r=a&&(b.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+an(e,t,n||(a?"border":"content"),r,o)+"px"}function un(e){var t=o,n=Gt[e];return n||(n=ln(e,t),"none"!==n&&n||(Pt=(Pt||b("").css("cssText","display:block !important")).appendTo(t.documentElement),t=(Pt[0].contentWindow||Pt[0].contentDocument).document,t.write(""),t.close(),n=ln(e,t),Pt.detach()),Gt[e]=n),n}function ln(e,t){var n=b(t.createElement(e)).appendTo(t.body),r=b.css(n[0],"display");return n.remove(),r}b.each(["height","width"],function(e,n){b.cssHooks[n]={get:function(e,r,i){return r?0===e.offsetWidth&&Xt.test(b.css(e,"display"))?b.swap(e,Qt,function(){return sn(e,n,i)}):sn(e,n,i):t},set:function(e,t,r){var i=r&&Rt(e);return on(e,t,r?an(e,n,r,b.support.boxSizing&&"border-box"===b.css(e,"boxSizing",!1,i),i):0)}}}),b.support.opacity||(b.cssHooks.opacity={get:function(e,t){return It.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=b.isNumeric(t)?"alpha(opacity="+100*t+")":"",o=r&&r.filter||n.filter||"";n.zoom=1,(t>=1||""===t)&&""===b.trim(o.replace($t,""))&&n.removeAttribute&&(n.removeAttribute("filter"),""===t||r&&!r.filter)||(n.filter=$t.test(o)?o.replace($t,i):o+" "+i)}}),b(function(){b.support.reliableMarginRight||(b.cssHooks.marginRight={get:function(e,n){return n?b.swap(e,{display:"inline-block"},Wt,[e,"marginRight"]):t}}),!b.support.pixelPosition&&b.fn.position&&b.each(["top","left"],function(e,n){b.cssHooks[n]={get:function(e,r){return r?(r=Wt(e,n),Yt.test(r)?b(e).position()[n]+"px":r):t}}})}),b.expr&&b.expr.filters&&(b.expr.filters.hidden=function(e){return 0>=e.offsetWidth&&0>=e.offsetHeight||!b.support.reliableHiddenOffsets&&"none"===(e.style&&e.style.display||b.css(e,"display"))},b.expr.filters.visible=function(e){return!b.expr.filters.hidden(e)}),b.each({margin:"",padding:"",border:"Width"},function(e,t){b.cssHooks[e+t]={expand:function(n){var r=0,i={},o="string"==typeof n?n.split(" "):[n];for(;4>r;r++)i[e+Zt[r]+t]=o[r]||o[r-2]||o[0];return i}},Ut.test(e)||(b.cssHooks[e+t].set=on)});var cn=/%20/g,pn=/\[\]$/,fn=/\r?\n/g,dn=/^(?:submit|button|image|reset|file)$/i,hn=/^(?:input|select|textarea|keygen)/i;b.fn.extend({serialize:function(){return b.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=b.prop(this,"elements");return e?b.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!b(this).is(":disabled")&&hn.test(this.nodeName)&&!dn.test(e)&&(this.checked||!Nt.test(e))}).map(function(e,t){var n=b(this).val();return null==n?null:b.isArray(n)?b.map(n,function(e){return{name:t.name,value:e.replace(fn,"\r\n")}}):{name:t.name,value:n.replace(fn,"\r\n")}}).get()}}),b.param=function(e,n){var r,i=[],o=function(e,t){t=b.isFunction(t)?t():null==t?"":t,i[i.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};if(n===t&&(n=b.ajaxSettings&&b.ajaxSettings.traditional),b.isArray(e)||e.jquery&&!b.isPlainObject(e))b.each(e,function(){o(this.name,this.value)});else for(r in e)gn(r,e[r],n,o);return i.join("&").replace(cn,"+")};function gn(e,t,n,r){var i;if(b.isArray(t))b.each(t,function(t,i){n||pn.test(e)?r(e,i):gn(e+"["+("object"==typeof i?t:"")+"]",i,n,r)});else if(n||"object"!==b.type(t))r(e,t);else for(i in t)gn(e+"["+i+"]",t[i],n,r)}b.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(e,t){b.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),b.fn.hover=function(e,t){return this.mouseenter(e).mouseleave(t||e)};var mn,yn,vn=b.now(),bn=/\?/,xn=/#.*$/,wn=/([?&])_=[^&]*/,Tn=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Nn=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Cn=/^(?:GET|HEAD)$/,kn=/^\/\//,En=/^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,Sn=b.fn.load,An={},jn={},Dn="*/".concat("*");try{yn=a.href}catch(Ln){yn=o.createElement("a"),yn.href="",yn=yn.href}mn=En.exec(yn.toLowerCase())||[];function Hn(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(w)||[];if(b.isFunction(n))while(r=o[i++])"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function qn(e,n,r,i){var o={},a=e===jn;function s(u){var l;return o[u]=!0,b.each(e[u]||[],function(e,u){var c=u(n,r,i);return"string"!=typeof c||a||o[c]?a?!(l=c):t:(n.dataTypes.unshift(c),s(c),!1)}),l}return s(n.dataTypes[0])||!o["*"]&&s("*")}function Mn(e,n){var r,i,o=b.ajaxSettings.flatOptions||{};for(i in n)n[i]!==t&&((o[i]?e:r||(r={}))[i]=n[i]);return r&&b.extend(!0,e,r),e}b.fn.load=function(e,n,r){if("string"!=typeof e&&Sn)return Sn.apply(this,arguments);var i,o,a,s=this,u=e.indexOf(" ");return u>=0&&(i=e.slice(u,e.length),e=e.slice(0,u)),b.isFunction(n)?(r=n,n=t):n&&"object"==typeof n&&(a="POST"),s.length>0&&b.ajax({url:e,type:a,dataType:"html",data:n}).done(function(e){o=arguments,s.html(i?b("